Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* |
michael@0 | 2 | * Copyright (c) 1999 |
michael@0 | 3 | * Silicon Graphics Computer Systems, Inc. |
michael@0 | 4 | * |
michael@0 | 5 | * Copyright (c) 1999 |
michael@0 | 6 | * Boris Fomitchev |
michael@0 | 7 | * |
michael@0 | 8 | * This material is provided "as is", with absolutely no warranty expressed |
michael@0 | 9 | * or implied. Any use is at your own risk. |
michael@0 | 10 | * |
michael@0 | 11 | * Permission to use or copy this software for any purpose is hereby granted |
michael@0 | 12 | * without fee, provided the above notices are retained on all copies. |
michael@0 | 13 | * Permission to modify the code and to distribute modified code is granted, |
michael@0 | 14 | * provided the above notices are retained, and a notice that the code was |
michael@0 | 15 | * modified is included with the above copyright notice. |
michael@0 | 16 | * |
michael@0 | 17 | */ |
michael@0 | 18 | |
michael@0 | 19 | #include "stlport_prefix.h" |
michael@0 | 20 | |
michael@0 | 21 | #include <cmath> |
michael@0 | 22 | #include <ios> |
michael@0 | 23 | #include <locale> |
michael@0 | 24 | |
michael@0 | 25 | #if defined (__DECCXX) |
michael@0 | 26 | # define NDIG 400 |
michael@0 | 27 | #else |
michael@0 | 28 | # define NDIG 82 |
michael@0 | 29 | #endif |
michael@0 | 30 | |
michael@0 | 31 | #define todigit(x) ((x)+'0') |
michael@0 | 32 | |
michael@0 | 33 | #if defined (_STLP_UNIX) |
michael@0 | 34 | |
michael@0 | 35 | # if defined (__sun) |
michael@0 | 36 | # include <floatingpoint.h> |
michael@0 | 37 | # endif |
michael@0 | 38 | |
michael@0 | 39 | # if defined (__sun) || defined (__digital__) || defined (__sgi) || defined (_STLP_SCO_OPENSERVER) || defined (__NCR_SVR) |
michael@0 | 40 | // DEC, SGI & Solaris need this |
michael@0 | 41 | # include <values.h> |
michael@0 | 42 | # include <nan.h> |
michael@0 | 43 | # endif |
michael@0 | 44 | |
michael@0 | 45 | # if defined (__QNXNTO__) || ( defined(__GNUC__) && defined(__APPLE__) ) || defined(_STLP_USE_UCLIBC) /* 0.9.26 */ || \ |
michael@0 | 46 | defined(__FreeBSD__) |
michael@0 | 47 | # define USE_SPRINTF_INSTEAD |
michael@0 | 48 | # endif |
michael@0 | 49 | |
michael@0 | 50 | # if defined (_AIX) // JFA 3-Aug-2000 |
michael@0 | 51 | # include <math.h> |
michael@0 | 52 | # include <float.h> |
michael@0 | 53 | # endif |
michael@0 | 54 | |
michael@0 | 55 | # include <math.h> |
michael@0 | 56 | #endif |
michael@0 | 57 | |
michael@0 | 58 | #include <cstdio> |
michael@0 | 59 | #include <cstdlib> |
michael@0 | 60 | |
michael@0 | 61 | #if defined (_STLP_MSVC_LIB) || defined (__MINGW32__) || defined (__BORLANDC__) || defined (__DJGPP) || \ |
michael@0 | 62 | defined (_STLP_SCO_OPENSERVER) || defined (__NCR_SVR) |
michael@0 | 63 | # include <float.h> |
michael@0 | 64 | #endif |
michael@0 | 65 | |
michael@0 | 66 | #if defined (__MRC__) || defined (__SC__) || defined (_CRAY) //*TY 02/24/2000 - added support for MPW |
michael@0 | 67 | # include <fp.h> |
michael@0 | 68 | #endif |
michael@0 | 69 | |
michael@0 | 70 | #if defined (__CYGWIN__) |
michael@0 | 71 | # include <ieeefp.h> |
michael@0 | 72 | #endif |
michael@0 | 73 | |
michael@0 | 74 | #if defined (__MSL__) |
michael@0 | 75 | # include <cstdlib> // for atoi |
michael@0 | 76 | # include <cstdio> // for snprintf |
michael@0 | 77 | # include <algorithm> |
michael@0 | 78 | # include <cassert> |
michael@0 | 79 | #endif |
michael@0 | 80 | |
michael@0 | 81 | #if defined (__ISCPP__) |
michael@0 | 82 | # include <cfloat> |
michael@0 | 83 | #endif |
michael@0 | 84 | |
michael@0 | 85 | #include <algorithm> |
michael@0 | 86 | |
michael@0 | 87 | #if defined (__DMC__) |
michael@0 | 88 | # define snprintf _snprintf |
michael@0 | 89 | #endif |
michael@0 | 90 | |
michael@0 | 91 | _STLP_BEGIN_NAMESPACE |
michael@0 | 92 | |
michael@0 | 93 | _STLP_MOVE_TO_PRIV_NAMESPACE |
michael@0 | 94 | |
michael@0 | 95 | #if defined (__MWERKS__) || defined(__BEOS__) |
michael@0 | 96 | # define USE_SPRINTF_INSTEAD |
michael@0 | 97 | #endif |
michael@0 | 98 | |
michael@0 | 99 | template <int N> |
michael@0 | 100 | struct _Dig |
michael@0 | 101 | { |
michael@0 | 102 | enum { dig = _Dig<N/10>::dig + 1 }; |
michael@0 | 103 | }; |
michael@0 | 104 | |
michael@0 | 105 | _STLP_TEMPLATE_NULL |
michael@0 | 106 | struct _Dig<0> |
michael@0 | 107 | { |
michael@0 | 108 | enum { dig = 0 }; |
michael@0 | 109 | }; |
michael@0 | 110 | |
michael@0 | 111 | #ifdef _STLP_NO_LONG_DOUBLE |
michael@0 | 112 | # define MAXEDIGITS int(_Dig<DBL_MAX_10_EXP>::dig) |
michael@0 | 113 | # define MAXFSIG DBL_DIG |
michael@0 | 114 | # define MAXFCVT (DBL_DIG + 1) |
michael@0 | 115 | #else |
michael@0 | 116 | # define MAXEDIGITS int(_Dig<LDBL_MAX_10_EXP>::dig) |
michael@0 | 117 | # define MAXFSIG LDBL_DIG |
michael@0 | 118 | # define MAXFCVT (LDBL_DIG + 1) |
michael@0 | 119 | #endif |
michael@0 | 120 | |
michael@0 | 121 | // Tests for infinity and NaN differ on different OSs. We encapsulate |
michael@0 | 122 | // these differences here. |
michael@0 | 123 | #if !defined (USE_SPRINTF_INSTEAD) |
michael@0 | 124 | # if defined (__hpux) && defined (__GNUC__) |
michael@0 | 125 | # define _STLP_USE_SIGN_HELPER |
michael@0 | 126 | # elif defined (__DJGPP) || (defined (_STLP_USE_GLIBC) && ! defined (__MSL__)) || \ |
michael@0 | 127 | defined (__CYGWIN__) || \ |
michael@0 | 128 | defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || \ |
michael@0 | 129 | defined (__HP_aCC) |
michael@0 | 130 | static inline bool _Stl_is_nan_or_inf(double x) |
michael@0 | 131 | # if defined (isfinite) |
michael@0 | 132 | { return !isfinite(x); } |
michael@0 | 133 | # else |
michael@0 | 134 | { return !finite(x); } |
michael@0 | 135 | # endif |
michael@0 | 136 | static inline bool _Stl_is_neg_nan(double x) { return isnan(x) && ( copysign(1., x) < 0 ); } |
michael@0 | 137 | static inline bool _Stl_is_inf(double x) { return isinf(x); } |
michael@0 | 138 | // inline bool _Stl_is_neg_inf(double x) { return isinf(x) < 0; } |
michael@0 | 139 | static inline bool _Stl_is_neg_inf(double x) { return isinf(x) && x < 0; } |
michael@0 | 140 | # elif (defined (__unix) || defined (__unix__)) && \ |
michael@0 | 141 | !defined (__APPLE__) && !defined (__DJGPP) && !defined(__osf__) && \ |
michael@0 | 142 | !defined (_CRAY) && !defined (__ANDROID__) |
michael@0 | 143 | static inline bool _Stl_is_nan_or_inf(double x) { return IsNANorINF(x); } |
michael@0 | 144 | static inline bool _Stl_is_inf(double x) { return IsNANorINF(x) && IsINF(x); } |
michael@0 | 145 | static inline bool _Stl_is_neg_inf(double x) { return (IsINF(x)) && (x < 0.0); } |
michael@0 | 146 | static inline bool _Stl_is_neg_nan(double x) { return IsNegNAN(x); } |
michael@0 | 147 | # elif defined (_STLP_MSVC_LIB) || defined (__MINGW32__) || defined (__BORLANDC__) |
michael@0 | 148 | static inline bool _Stl_is_nan_or_inf(double x) { return !_finite(x); } |
michael@0 | 149 | # if !defined (__BORLANDC__) |
michael@0 | 150 | static inline bool _Stl_is_inf(double x) { |
michael@0 | 151 | int fclass = _fpclass(x); |
michael@0 | 152 | return fclass == _FPCLASS_NINF || fclass == _FPCLASS_PINF; |
michael@0 | 153 | } |
michael@0 | 154 | static inline bool _Stl_is_neg_inf(double x) { return _fpclass(x) == _FPCLASS_NINF; } |
michael@0 | 155 | # else |
michael@0 | 156 | static inline bool _Stl_is_inf(double x) { return _Stl_is_nan_or_inf(x) && !_isnan(x);} |
michael@0 | 157 | static inline bool _Stl_is_neg_inf(double x) { return _Stl_is_inf(x) && x < 0 ; } |
michael@0 | 158 | # endif |
michael@0 | 159 | static inline bool _Stl_is_neg_nan(double x) { return _isnan(x) && _copysign(1., x) < 0 ; } |
michael@0 | 160 | # if defined (__BORLANDC__) |
michael@0 | 161 | static inline bool _Stl_is_nan_or_inf(long double x) { return !_finitel(x); } |
michael@0 | 162 | static inline bool _Stl_is_inf(long double x) { return _Stl_is_nan_or_inf(x) && !_isnanl(x);} |
michael@0 | 163 | static inline bool _Stl_is_neg_inf(long double x) { return _Stl_is_inf(x) && x < 0 ; } |
michael@0 | 164 | static inline bool _Stl_is_neg_nan(long double x) { return _isnanl(x) && _copysignl(1.l, x) < 0 ; } |
michael@0 | 165 | # elif !defined (_STLP_NO_LONG_DOUBLE) |
michael@0 | 166 | // Simply there to avoid warning long double -> double implicit conversion: |
michael@0 | 167 | static inline bool _Stl_is_nan_or_inf(long double x) { return _Stl_is_nan_or_inf(__STATIC_CAST(double, x)); } |
michael@0 | 168 | static inline bool _Stl_is_inf(long double x) { return _Stl_is_inf(__STATIC_CAST(double, x));} |
michael@0 | 169 | static inline bool _Stl_is_neg_inf(long double x) { return _Stl_is_neg_inf(__STATIC_CAST(double, x)); } |
michael@0 | 170 | static inline bool _Stl_is_neg_nan(long double x) { return _Stl_is_neg_nan(__STATIC_CAST(double, x)); } |
michael@0 | 171 | # endif |
michael@0 | 172 | # elif defined (__MRC__) || defined (__SC__) || defined (__DMC__) |
michael@0 | 173 | static bool _Stl_is_nan_or_inf(double x) { return isnan(x) || !isfinite(x); } |
michael@0 | 174 | static bool _Stl_is_inf(double x) { return !isfinite(x); } |
michael@0 | 175 | static bool _Stl_is_neg_inf(double x) { return !isfinite(x) && signbit(x); } |
michael@0 | 176 | static bool _Stl_is_neg_nan(double x) { return isnan(x) && signbit(x); } |
michael@0 | 177 | # elif /* defined(__FreeBSD__) || defined(__OpenBSD__) || */ (defined(__GNUC__) && defined(__APPLE__)) |
michael@0 | 178 | static inline bool _Stl_is_nan_or_inf(double x) { return !finite(x); } |
michael@0 | 179 | static inline bool _Stl_is_inf(double x) { return _Stl_is_nan_or_inf(x) && ! isnan(x); } |
michael@0 | 180 | static inline bool _Stl_is_neg_inf(double x) { return _Stl_is_inf(x) && x < 0 ; } |
michael@0 | 181 | static inline bool _Stl_is_neg_nan(double x) { return isnan(x) && copysign(1., x) < 0 ; } |
michael@0 | 182 | # elif defined( _AIX ) // JFA 11-Aug-2000 |
michael@0 | 183 | static bool _Stl_is_nan_or_inf(double x) { return isnan(x) || !finite(x); } |
michael@0 | 184 | static bool _Stl_is_inf(double x) { return !finite(x); } |
michael@0 | 185 | // bool _Stl_is_neg_inf(double x) { return _class(x) == FP_MINUS_INF; } |
michael@0 | 186 | static bool _Stl_is_neg_inf(double x) { return _Stl_is_inf(x) && ( copysign(1., x) < 0 ); } |
michael@0 | 187 | static bool _Stl_is_neg_nan(double x) { return isnan(x) && ( copysign(1., x) < 0 ); } |
michael@0 | 188 | # elif defined (__ISCPP__) |
michael@0 | 189 | static inline bool _Stl_is_nan_or_inf (double x) { return _fp_isINF(x) || _fp_isNAN(x); } |
michael@0 | 190 | static inline bool _Stl_is_inf (double x) { return _fp_isINF(x); } |
michael@0 | 191 | static inline bool _Stl_is_neg_inf (double x) { return _fp_isINF(x) && x < 0; } |
michael@0 | 192 | static inline bool _Stl_is_neg_nan (double x) { return _fp_isNAN(x) && x < 0; } |
michael@0 | 193 | # elif defined (_CRAY) |
michael@0 | 194 | # if defined (_CRAYIEEE) |
michael@0 | 195 | static inline bool _Stl_is_nan_or_inf(double x) { return isnan(x) || isinf(x); } |
michael@0 | 196 | static inline bool _Stl_is_inf(double x) { return isinf(x); } |
michael@0 | 197 | static inline bool _Stl_is_neg_inf(double x) { return isinf(x) && signbit(x); } |
michael@0 | 198 | static inline bool _Stl_is_neg_nan(double x) { return isnan(x) && signbit(x); } |
michael@0 | 199 | # else |
michael@0 | 200 | static inline bool _Stl_is_nan_or_inf(double x) { return false; } |
michael@0 | 201 | static inline bool _Stl_is_inf(double x) { return false; } |
michael@0 | 202 | static inline bool _Stl_is_neg_inf(double x) { return false; } |
michael@0 | 203 | static inline bool _Stl_is_neg_nan(double x) { return false; } |
michael@0 | 204 | # endif |
michael@0 | 205 | # else // nothing from above |
michael@0 | 206 | # define USE_SPRINTF_INSTEAD |
michael@0 | 207 | # endif |
michael@0 | 208 | #endif // !USE_SPRINTF_INSTEAD |
michael@0 | 209 | |
michael@0 | 210 | #if !defined (USE_SPRINTF_INSTEAD) |
michael@0 | 211 | // Reentrant versions of floating-point conversion functions. The argument |
michael@0 | 212 | // lists look slightly different on different operating systems, so we're |
michael@0 | 213 | // encapsulating the differences here. |
michael@0 | 214 | |
michael@0 | 215 | # if defined (__CYGWIN__) || defined(__DJGPP) |
michael@0 | 216 | static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf) |
michael@0 | 217 | { return ecvtbuf(x, n, pt, sign, buf); } |
michael@0 | 218 | static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf) |
michael@0 | 219 | { return fcvtbuf(x, n, pt, sign, buf); } |
michael@0 | 220 | # if !defined (_STLP_NO_LONG_DOUBLE) |
michael@0 | 221 | # if defined (__CYGWIN__) |
michael@0 | 222 | # define _STLP_EMULATE_LONG_DOUBLE_CVT |
michael@0 | 223 | # else |
michael@0 | 224 | static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf) |
michael@0 | 225 | { return ecvtbuf(x, n, pt, sign, buf); } |
michael@0 | 226 | static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf) |
michael@0 | 227 | { return fcvtbuf(x, n, pt, sign, buf); } |
michael@0 | 228 | # endif |
michael@0 | 229 | # endif |
michael@0 | 230 | # elif defined (_STLP_USE_GLIBC) |
michael@0 | 231 | static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf, size_t bsize) |
michael@0 | 232 | { return ecvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0; } |
michael@0 | 233 | static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf, size_t bsize) |
michael@0 | 234 | { return fcvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0; } |
michael@0 | 235 | # ifndef _STLP_NO_LONG_DOUBLE |
michael@0 | 236 | static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf, size_t bsize) |
michael@0 | 237 | { return qecvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0; } |
michael@0 | 238 | static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf, size_t bsize) |
michael@0 | 239 | { return qfcvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0; } |
michael@0 | 240 | # endif |
michael@0 | 241 | # define _STLP_NEED_CVT_BUFFER_SIZE |
michael@0 | 242 | # elif defined (__sun) |
michael@0 | 243 | static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf) |
michael@0 | 244 | { return econvert(x, n, pt, sign, buf); } |
michael@0 | 245 | static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf) |
michael@0 | 246 | { return fconvert(x, n, pt, sign, buf); } |
michael@0 | 247 | # ifndef _STLP_NO_LONG_DOUBLE |
michael@0 | 248 | static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf) |
michael@0 | 249 | { return qeconvert(&x, n, pt, sign, buf); } |
michael@0 | 250 | static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf) |
michael@0 | 251 | { return qfconvert(&x, n, pt, sign, buf); } |
michael@0 | 252 | # endif |
michael@0 | 253 | # elif defined (__DECCXX) |
michael@0 | 254 | static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf, size_t bsize) |
michael@0 | 255 | { return (ecvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0); } |
michael@0 | 256 | static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf, size_t bsize) |
michael@0 | 257 | { return (fcvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0); } |
michael@0 | 258 | # ifndef _STLP_NO_LONG_DOUBLE |
michael@0 | 259 | // fbp : no "long double" conversions ! |
michael@0 | 260 | static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf, size_t bsize) |
michael@0 | 261 | { return (ecvt_r((double)x, n, pt, sign, buf, bsize) == 0 ? buf : 0) ; } |
michael@0 | 262 | static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf, size_t bsize) |
michael@0 | 263 | { return (fcvt_r((double)x, n, pt, sign, buf, bsize) == 0 ? buf : 0); } |
michael@0 | 264 | # endif |
michael@0 | 265 | # define _STLP_NEED_CVT_BUFFER_SIZE |
michael@0 | 266 | # elif defined (__hpux) |
michael@0 | 267 | static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign) |
michael@0 | 268 | { return ecvt(x, n, pt, sign); } |
michael@0 | 269 | static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign) |
michael@0 | 270 | { return fcvt(x, n, pt, sign); } |
michael@0 | 271 | # if !defined (_STLP_NO_LONG_DOUBLE) |
michael@0 | 272 | static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign) |
michael@0 | 273 | { return _ldecvt(*(long_double*)&x, n, pt, sign); } |
michael@0 | 274 | static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign) |
michael@0 | 275 | { return _ldfcvt(*(long_double*)&x, n, pt, sign); } |
michael@0 | 276 | # endif |
michael@0 | 277 | # define _STLP_CVT_NEED_SYNCHRONIZATION |
michael@0 | 278 | # elif defined (__unix) && !defined (__APPLE__) && !defined (_CRAY) && \ |
michael@0 | 279 | !defined (__ANDROID__) |
michael@0 | 280 | static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf) |
michael@0 | 281 | { return ecvt_r(x, n, pt, sign, buf); } |
michael@0 | 282 | static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf) |
michael@0 | 283 | { return fcvt_r(x, n, pt, sign, buf); } |
michael@0 | 284 | # if !defined (_STLP_NO_LONG_DOUBLE) |
michael@0 | 285 | static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf) |
michael@0 | 286 | { return qecvt_r(x, n, pt, sign, buf); } |
michael@0 | 287 | static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf) |
michael@0 | 288 | { return qfcvt_r(x, n, pt, sign, buf); } |
michael@0 | 289 | # endif |
michael@0 | 290 | # elif defined (_STLP_MSVC_LIB) || defined (__MINGW32__) || defined (__BORLANDC__) |
michael@0 | 291 | # if defined (_STLP_USE_SAFE_STRING_FUNCTIONS) |
michael@0 | 292 | # define _STLP_APPEND(a, b) a##b |
michael@0 | 293 | # define _STLP_BUF_PARAMS , char* buf, size_t bsize |
michael@0 | 294 | # define _STLP_SECURE_FUN(F, X, N, PT, SIGN) _STLP_APPEND(F, _s)(buf, bsize, X, N, PT, SIGN); return buf |
michael@0 | 295 | # else |
michael@0 | 296 | # define _STLP_BUF_PARAMS |
michael@0 | 297 | # define _STLP_SECURE_FUN(F, X, N, PT, SIGN) return F(X, N, PT, SIGN) |
michael@0 | 298 | # define _STLP_CVT_NEED_SYNCHRONIZATION |
michael@0 | 299 | # endif |
michael@0 | 300 | static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign _STLP_BUF_PARAMS) |
michael@0 | 301 | { _STLP_SECURE_FUN(_ecvt, x, n, pt, sign); } |
michael@0 | 302 | static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign _STLP_BUF_PARAMS) |
michael@0 | 303 | { _STLP_SECURE_FUN(_fcvt, x, n, pt, sign); } |
michael@0 | 304 | # if !defined (_STLP_NO_LONG_DOUBLE) |
michael@0 | 305 | # if defined (_STLP_USE_SAFE_STRING_FUNCTIONS) |
michael@0 | 306 | # define _STLP_PARAMS , buf, bsize |
michael@0 | 307 | # else |
michael@0 | 308 | # define _STLP_PARAMS |
michael@0 | 309 | # endif |
michael@0 | 310 | static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign _STLP_BUF_PARAMS) |
michael@0 | 311 | { return _Stl_ecvtR(__STATIC_CAST(double, x), n, pt, sign _STLP_PARAMS); } |
michael@0 | 312 | static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign _STLP_BUF_PARAMS) |
michael@0 | 313 | { return _Stl_fcvtR(__STATIC_CAST(double, x), n, pt, sign _STLP_PARAMS); } |
michael@0 | 314 | # undef _STLP_PARAMS |
michael@0 | 315 | # endif |
michael@0 | 316 | # undef _STLP_SECURE_FUN |
michael@0 | 317 | # undef _STLP_BUF_PARAMS |
michael@0 | 318 | # undef _STLP_APPEND |
michael@0 | 319 | # if defined (__BORLANDC__) /* || defined (__GNUC__) MinGW do not support 'L' modifier so emulation do not work */ |
michael@0 | 320 | # define _STLP_EMULATE_LONG_DOUBLE_CVT |
michael@0 | 321 | # endif |
michael@0 | 322 | # elif defined (__ISCPP__) |
michael@0 | 323 | static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf) |
michael@0 | 324 | { return _fp_ecvt( x, n, pt, sign, buf); } |
michael@0 | 325 | static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf) |
michael@0 | 326 | { return _fp_fcvt(x, n, pt, sign, buf); } |
michael@0 | 327 | # if !defined (_STLP_NO_LONG_DOUBLE) |
michael@0 | 328 | static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf) |
michael@0 | 329 | { return _fp_ecvt( x, n, pt, sign, buf); } |
michael@0 | 330 | static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf) |
michael@0 | 331 | { return _fp_fcvt(x, n, pt, sign, buf); } |
michael@0 | 332 | # endif |
michael@0 | 333 | # elif defined (_AIX) || defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || \ |
michael@0 | 334 | defined (__MRC__) || defined (__SC__) || defined (_CRAY) || \ |
michael@0 | 335 | defined (_STLP_SCO_OPENSERVER) || defined (__NCR_SVR) || \ |
michael@0 | 336 | defined (__DMC__) |
michael@0 | 337 | static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign) |
michael@0 | 338 | { return ecvt(x, n, pt, sign ); } |
michael@0 | 339 | static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign) |
michael@0 | 340 | { return fcvt(x, n, pt, sign); } |
michael@0 | 341 | # if !defined (_STLP_NO_LONG_DOUBLE) |
michael@0 | 342 | static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign) |
michael@0 | 343 | { return ecvt(x, n, pt, sign ); } |
michael@0 | 344 | static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign) |
michael@0 | 345 | { return fcvt(x, n, pt, sign); } |
michael@0 | 346 | # endif |
michael@0 | 347 | # define _STLP_CVT_NEED_SYNCHRONIZATION |
michael@0 | 348 | # else |
michael@0 | 349 | # error Missing _Stl_ecvtR and _Stl_fcvtR implementations. |
michael@0 | 350 | # endif |
michael@0 | 351 | |
michael@0 | 352 | #if defined (_STLP_CVT_NEED_SYNCHRONIZATION) |
michael@0 | 353 | /* STLport synchronize access to *cvt functions but those methods might |
michael@0 | 354 | * be called from outside, in this case we will still have a race condition. */ |
michael@0 | 355 | # if defined (_STLP_THREADS) |
michael@0 | 356 | static _STLP_STATIC_MUTEX& put_float_mutex() { |
michael@0 | 357 | static _STLP_STATIC_MUTEX __put_float_mutex _STLP_MUTEX_INITIALIZER; |
michael@0 | 358 | return __put_float_mutex; |
michael@0 | 359 | } |
michael@0 | 360 | static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf) { |
michael@0 | 361 | _STLP_auto_lock lock(put_float_mutex()); |
michael@0 | 362 | strcpy(buf, _Stl_ecvtR(x, n, pt, sign)); return buf; |
michael@0 | 363 | } |
michael@0 | 364 | static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf) { |
michael@0 | 365 | _STLP_auto_lock lock(put_float_mutex()); |
michael@0 | 366 | strcpy(buf, _Stl_fcvtR(x, n, pt, sign)); return buf; |
michael@0 | 367 | } |
michael@0 | 368 | # if !defined (_STLP_NO_LONG_DOUBLE) && !defined (_STLP_EMULATE_LONG_DOUBLE_CVT) |
michael@0 | 369 | static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf) { |
michael@0 | 370 | _STLP_auto_lock lock(put_float_mutex()); |
michael@0 | 371 | strcpy(buf, _Stl_ecvtR(x, n, pt, sign)); return buf; |
michael@0 | 372 | } |
michael@0 | 373 | static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf) { |
michael@0 | 374 | _STLP_auto_lock lock(put_float_mutex()); |
michael@0 | 375 | strcpy(buf, _Stl_fcvtR(x, n, pt, sign)); return buf; |
michael@0 | 376 | } |
michael@0 | 377 | # endif |
michael@0 | 378 | # else |
michael@0 | 379 | static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char*) |
michael@0 | 380 | { return _Stl_ecvtR(x, n, pt, sign); } |
michael@0 | 381 | static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char*) |
michael@0 | 382 | { return _Stl_fcvtR(x, n, pt, sign); } |
michael@0 | 383 | # if !defined (_STLP_NO_LONG_DOUBLE) && !defined (_STLP_EMULATE_LONG_DOUBLE_CVT) |
michael@0 | 384 | static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char*) |
michael@0 | 385 | { return _Stl_ecvtR(x, n, pt, sign); } |
michael@0 | 386 | static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char*) |
michael@0 | 387 | { return _Stl_fcvtR(x, n, pt, sign); } |
michael@0 | 388 | # endif |
michael@0 | 389 | # endif |
michael@0 | 390 | #endif |
michael@0 | 391 | |
michael@0 | 392 | # if !defined (_STLP_USE_SAFE_STRING_FUNCTIONS) && !defined (_STLP_NEED_CVT_BUFFER_SIZE) |
michael@0 | 393 | # define _STLP_CVT_BUFFER(B) B |
michael@0 | 394 | # else |
michael@0 | 395 | # define _STLP_CVT_BUFFER(B) _STLP_ARRAY_AND_SIZE(B) |
michael@0 | 396 | # endif |
michael@0 | 397 | |
michael@0 | 398 | # if defined (_STLP_EMULATE_LONG_DOUBLE_CVT) |
michael@0 | 399 | static void __fill_fmtbuf(char* fmtbuf, ios_base::fmtflags flags, char long_modifier); |
michael@0 | 400 | |
michael@0 | 401 | // Emulation of ecvt/fcvt functions using sprintf: |
michael@0 | 402 | static char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf) { |
michael@0 | 403 | // If long double value can be safely converted to double without losing precision |
michael@0 | 404 | // we use the ecvt function for double: |
michael@0 | 405 | double y = __STATIC_CAST(double, x); |
michael@0 | 406 | if (x == y) |
michael@0 | 407 | return _Stl_ecvtR(y, n, pt, sign, buf); |
michael@0 | 408 | |
michael@0 | 409 | char fmtbuf[32]; |
michael@0 | 410 | __fill_fmtbuf(fmtbuf, 0, 'L'); |
michael@0 | 411 | sprintf(buf, fmtbuf, n, x < 0.0l ? -x : x); |
michael@0 | 412 | /* We are waiting for something having the form x.xxxe+yyyy */ |
michael@0 | 413 | *pt = 0; |
michael@0 | 414 | *sign = 0; |
michael@0 | 415 | int i = -1; |
michael@0 | 416 | int offset = 0; |
michael@0 | 417 | while (buf[++i] != 0 && n != 0) { |
michael@0 | 418 | if (buf[i] >= '0' && buf[i] <= '9') { |
michael@0 | 419 | --n; |
michael@0 | 420 | if (offset != 0) |
michael@0 | 421 | buf[i - offset] = buf[i]; |
michael@0 | 422 | } |
michael@0 | 423 | else { |
michael@0 | 424 | if (offset != 0) break; |
michael@0 | 425 | ++offset; |
michael@0 | 426 | *pt = i; |
michael@0 | 427 | } |
michael@0 | 428 | } |
michael@0 | 429 | if (offset != 0) |
michael@0 | 430 | buf[i - offset] = 0; |
michael@0 | 431 | // Extract exponent part in point position: |
michael@0 | 432 | int e = 0; |
michael@0 | 433 | while (buf[++i] != 0) { |
michael@0 | 434 | if (buf[i] >= '0' && buf[i] <= '9') { |
michael@0 | 435 | e = e * 10 + (buf[i] - '0'); |
michael@0 | 436 | } |
michael@0 | 437 | } |
michael@0 | 438 | *pt += e; |
michael@0 | 439 | return buf; |
michael@0 | 440 | } |
michael@0 | 441 | |
michael@0 | 442 | static char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf) { |
michael@0 | 443 | // If long double value can be safely converted to double without losing precision |
michael@0 | 444 | // we use the fcvt function for double: |
michael@0 | 445 | double y = __STATIC_CAST(double, x); |
michael@0 | 446 | if (x == y) |
michael@0 | 447 | return _Stl_fcvtR(y, n, pt, sign, buf); |
michael@0 | 448 | |
michael@0 | 449 | char fmtbuf[32]; |
michael@0 | 450 | __fill_fmtbuf(fmtbuf, ios_base::fixed, 'L'); |
michael@0 | 451 | sprintf(buf, fmtbuf, n, x < 0.0l ? -x : x); |
michael@0 | 452 | *pt = 0; |
michael@0 | 453 | *sign = 0; |
michael@0 | 454 | int i = -1; |
michael@0 | 455 | int offset = 0; |
michael@0 | 456 | while (buf[++i] != 0 && (offset == 0 || n != 0)) { |
michael@0 | 457 | if (buf[i] >= '0' && buf[i] <= '9') { |
michael@0 | 458 | if (offset != 0) { |
michael@0 | 459 | --n; |
michael@0 | 460 | buf[i - offset] = buf[i]; |
michael@0 | 461 | } |
michael@0 | 462 | } |
michael@0 | 463 | else { |
michael@0 | 464 | ++offset; |
michael@0 | 465 | *pt = i; |
michael@0 | 466 | } |
michael@0 | 467 | } |
michael@0 | 468 | if (offset != 0) |
michael@0 | 469 | buf[i - offset] = 0; |
michael@0 | 470 | else |
michael@0 | 471 | *pt = i; |
michael@0 | 472 | return buf; |
michael@0 | 473 | } |
michael@0 | 474 | #endif |
michael@0 | 475 | |
michael@0 | 476 | //---------------------------------------------------------------------- |
michael@0 | 477 | // num_put |
michael@0 | 478 | |
michael@0 | 479 | // __format_float formats a mantissa and exponent as returned by |
michael@0 | 480 | // one of the conversion functions (ecvt_r, fcvt_r, qecvt_r, qfcvt_r) |
michael@0 | 481 | // according to the specified precision and format flags. This is |
michael@0 | 482 | // based on doprnt but is much simpler since it is concerned only |
michael@0 | 483 | // with floating point input and does not consider all formats. It |
michael@0 | 484 | // also does not deal with blank padding, which is handled by |
michael@0 | 485 | // __copy_float_and_fill. |
michael@0 | 486 | |
michael@0 | 487 | static size_t __format_float_scientific( __iostring& buf, const char *bp, |
michael@0 | 488 | int decpt, int sign, bool is_zero, |
michael@0 | 489 | ios_base::fmtflags flags, |
michael@0 | 490 | int precision) { |
michael@0 | 491 | // sign if required |
michael@0 | 492 | if (sign) |
michael@0 | 493 | buf += '-'; |
michael@0 | 494 | else if (flags & ios_base::showpos) |
michael@0 | 495 | buf += '+'; |
michael@0 | 496 | |
michael@0 | 497 | // first digit of mantissa |
michael@0 | 498 | buf += *bp++; |
michael@0 | 499 | |
michael@0 | 500 | // start of grouping position, grouping won't occur in scientific notation |
michael@0 | 501 | // as it is impossible to have something like 1234.0e04 but we return a correct |
michael@0 | 502 | // group position for coherency with __format_float_fixed. |
michael@0 | 503 | size_t __group_pos = buf.size(); |
michael@0 | 504 | |
michael@0 | 505 | // decimal point if required |
michael@0 | 506 | if (precision != 0 || flags & ios_base::showpoint) { |
michael@0 | 507 | buf += '.'; |
michael@0 | 508 | } |
michael@0 | 509 | |
michael@0 | 510 | // rest of mantissa |
michael@0 | 511 | while (*bp != 0 && precision--) |
michael@0 | 512 | buf += *bp++; |
michael@0 | 513 | |
michael@0 | 514 | // trailing 0 if needed |
michael@0 | 515 | if (precision > 0) |
michael@0 | 516 | buf.append(precision, '0'); |
michael@0 | 517 | |
michael@0 | 518 | // exponent size = number of digits + exponent sign + exponent symbol + trailing zero |
michael@0 | 519 | char expbuf[MAXEDIGITS + 3]; |
michael@0 | 520 | //We start filling at the buffer end |
michael@0 | 521 | char *suffix = expbuf + MAXEDIGITS + 2; |
michael@0 | 522 | *suffix = 0; |
michael@0 | 523 | if (!is_zero) { |
michael@0 | 524 | int nn = decpt - 1; |
michael@0 | 525 | if (nn < 0) |
michael@0 | 526 | nn = -nn; |
michael@0 | 527 | for (; nn > 9; nn /= 10) |
michael@0 | 528 | *--suffix = (char) todigit(nn % 10); |
michael@0 | 529 | *--suffix = (char) todigit(nn); |
michael@0 | 530 | } |
michael@0 | 531 | |
michael@0 | 532 | // prepend leading zeros to exponent |
michael@0 | 533 | // C89 Standard says that it should be at least 2 digits, C99 Standard says that |
michael@0 | 534 | // we stop prepend zeros if more than 3 digits. To repect both STLport prepend zeros |
michael@0 | 535 | // until it is 2 digits. |
michael@0 | 536 | while (suffix > &expbuf[MAXEDIGITS]) |
michael@0 | 537 | *--suffix = '0'; |
michael@0 | 538 | |
michael@0 | 539 | // put in the exponent sign |
michael@0 | 540 | *--suffix = (char) ((decpt > 0 || is_zero ) ? '+' : '-'); |
michael@0 | 541 | |
michael@0 | 542 | // put in the e |
michael@0 | 543 | *--suffix = flags & ios_base::uppercase ? 'E' : 'e'; |
michael@0 | 544 | |
michael@0 | 545 | // copy the suffix |
michael@0 | 546 | buf += suffix; |
michael@0 | 547 | return __group_pos; |
michael@0 | 548 | } |
michael@0 | 549 | |
michael@0 | 550 | static size_t __format_float_fixed( __iostring &buf, const char *bp, |
michael@0 | 551 | int decpt, int sign, |
michael@0 | 552 | ios_base::fmtflags flags, |
michael@0 | 553 | int precision) { |
michael@0 | 554 | if ( sign && (decpt > -precision) && (*bp != 0) ) |
michael@0 | 555 | buf += '-'; |
michael@0 | 556 | else if ( flags & ios_base::showpos ) |
michael@0 | 557 | buf += '+'; |
michael@0 | 558 | |
michael@0 | 559 | // digits before decimal point |
michael@0 | 560 | int nnn = decpt; |
michael@0 | 561 | do { |
michael@0 | 562 | buf += (nnn <= 0 || *bp == 0) ? '0' : *bp++; |
michael@0 | 563 | } while ( --nnn > 0 ); |
michael@0 | 564 | |
michael@0 | 565 | // start of grouping position |
michael@0 | 566 | size_t __group_pos = buf.size(); |
michael@0 | 567 | |
michael@0 | 568 | // decimal point if needed |
michael@0 | 569 | if ( flags & ios_base::showpoint || precision > 0 ) { |
michael@0 | 570 | buf += '.'; |
michael@0 | 571 | } |
michael@0 | 572 | |
michael@0 | 573 | // digits after decimal point if any |
michael@0 | 574 | while ( *bp != 0 && --precision >= 0 ) { |
michael@0 | 575 | buf += (++decpt <= 0) ? '0' : *bp++; |
michael@0 | 576 | } |
michael@0 | 577 | |
michael@0 | 578 | // trailing zeros if needed |
michael@0 | 579 | if (precision > 0) |
michael@0 | 580 | buf.append(precision, '0'); |
michael@0 | 581 | |
michael@0 | 582 | return __group_pos; |
michael@0 | 583 | } |
michael@0 | 584 | |
michael@0 | 585 | #if defined (_STLP_USE_SIGN_HELPER) |
michael@0 | 586 | template<class _FloatT> |
michael@0 | 587 | struct float_sign_helper { |
michael@0 | 588 | float_sign_helper(_FloatT __x) |
michael@0 | 589 | { _M_number._num = __x; } |
michael@0 | 590 | |
michael@0 | 591 | bool is_negative() const { |
michael@0 | 592 | const unsigned short sign_mask(1 << (sizeof(unsigned short) * CHAR_BIT - 1)); |
michael@0 | 593 | return (get_sign_word() & sign_mask) != 0; |
michael@0 | 594 | } |
michael@0 | 595 | private: |
michael@0 | 596 | union { |
michael@0 | 597 | unsigned short _Words[8]; |
michael@0 | 598 | _FloatT _num; |
michael@0 | 599 | } _M_number; |
michael@0 | 600 | |
michael@0 | 601 | unsigned short get_word_higher() const _STLP_NOTHROW |
michael@0 | 602 | { return _M_number._Words[0]; } |
michael@0 | 603 | unsigned short get_word_lower() const _STLP_NOTHROW |
michael@0 | 604 | { return _M_number._Words[(sizeof(_FloatT) >= 12 ? 10 : sizeof(_FloatT)) / sizeof(unsigned short) - 1]; } |
michael@0 | 605 | unsigned short get_sign_word() const _STLP_NOTHROW |
michael@0 | 606 | # if defined (_STLP_BIG_ENDIAN) |
michael@0 | 607 | { return get_word_higher(); } |
michael@0 | 608 | # else /* _STLP_LITTLE_ENDIAN */ |
michael@0 | 609 | { return get_word_lower(); } |
michael@0 | 610 | # endif |
michael@0 | 611 | }; |
michael@0 | 612 | #endif |
michael@0 | 613 | |
michael@0 | 614 | template <class _FloatT> |
michael@0 | 615 | static size_t __format_nan_or_inf(__iostring& buf, _FloatT x, ios_base::fmtflags flags) { |
michael@0 | 616 | static const char* inf[2] = { "inf", "Inf" }; |
michael@0 | 617 | static const char* nan[2] = { "nan", "NaN" }; |
michael@0 | 618 | const char** inf_or_nan; |
michael@0 | 619 | #if !defined (_STLP_USE_SIGN_HELPER) |
michael@0 | 620 | if (_Stl_is_inf(x)) { // Infinity |
michael@0 | 621 | inf_or_nan = inf; |
michael@0 | 622 | if (_Stl_is_neg_inf(x)) |
michael@0 | 623 | buf += '-'; |
michael@0 | 624 | else if (flags & ios_base::showpos) |
michael@0 | 625 | buf += '+'; |
michael@0 | 626 | } else { // NaN |
michael@0 | 627 | inf_or_nan = nan; |
michael@0 | 628 | if (_Stl_is_neg_nan(x)) |
michael@0 | 629 | buf += '-'; |
michael@0 | 630 | else if (flags & ios_base::showpos) |
michael@0 | 631 | buf += '+'; |
michael@0 | 632 | } |
michael@0 | 633 | #else |
michael@0 | 634 | typedef numeric_limits<_FloatT> limits; |
michael@0 | 635 | if (x == limits::infinity() || x == -limits::infinity()) { |
michael@0 | 636 | inf_or_nan = inf; |
michael@0 | 637 | } else { // NaN |
michael@0 | 638 | inf_or_nan = nan; |
michael@0 | 639 | } |
michael@0 | 640 | float_sign_helper<_FloatT> helper(x); |
michael@0 | 641 | if (helper.is_negative()) |
michael@0 | 642 | buf += '-'; |
michael@0 | 643 | else if (flags & ios_base::showpos) |
michael@0 | 644 | buf += '+'; |
michael@0 | 645 | #endif |
michael@0 | 646 | size_t ret = buf.size(); |
michael@0 | 647 | buf += inf_or_nan[flags & ios_base::uppercase ? 1 : 0]; |
michael@0 | 648 | return ret; |
michael@0 | 649 | } |
michael@0 | 650 | |
michael@0 | 651 | static inline size_t __format_float(__iostring &buf, const char * bp, |
michael@0 | 652 | int decpt, int sign, bool is_zero, |
michael@0 | 653 | ios_base::fmtflags flags, |
michael@0 | 654 | int precision) { |
michael@0 | 655 | size_t __group_pos = 0; |
michael@0 | 656 | switch (flags & ios_base::floatfield) { |
michael@0 | 657 | case ios_base::scientific: |
michael@0 | 658 | __group_pos = __format_float_scientific( buf, bp, decpt, sign, is_zero, |
michael@0 | 659 | flags, precision); |
michael@0 | 660 | break; |
michael@0 | 661 | case ios_base::fixed: |
michael@0 | 662 | __group_pos = __format_float_fixed( buf, bp, decpt, sign, |
michael@0 | 663 | flags, precision); |
michael@0 | 664 | break; |
michael@0 | 665 | default: // g format |
michael@0 | 666 | // establish default precision |
michael@0 | 667 | if (flags & ios_base::showpoint || precision > 0) { |
michael@0 | 668 | if (precision == 0) precision = 1; |
michael@0 | 669 | } else |
michael@0 | 670 | precision = 6; |
michael@0 | 671 | |
michael@0 | 672 | // reset exponent if value is zero |
michael@0 | 673 | if (is_zero) |
michael@0 | 674 | decpt = 1; |
michael@0 | 675 | |
michael@0 | 676 | int kk = precision; |
michael@0 | 677 | if (!(flags & ios_base::showpoint)) { |
michael@0 | 678 | size_t n = strlen(bp); |
michael@0 | 679 | if (n < (size_t)kk) |
michael@0 | 680 | kk = (int)n; |
michael@0 | 681 | while (kk >= 1 && bp[kk-1] == '0') |
michael@0 | 682 | --kk; |
michael@0 | 683 | } |
michael@0 | 684 | |
michael@0 | 685 | if (decpt < -3 || decpt > precision) { |
michael@0 | 686 | precision = kk - 1; |
michael@0 | 687 | __group_pos = __format_float_scientific( buf, bp, decpt, sign, is_zero, |
michael@0 | 688 | flags, precision); |
michael@0 | 689 | } else { |
michael@0 | 690 | precision = kk - decpt; |
michael@0 | 691 | __group_pos = __format_float_fixed( buf, bp, decpt, sign, |
michael@0 | 692 | flags, precision); |
michael@0 | 693 | } |
michael@0 | 694 | break; |
michael@0 | 695 | } /* switch */ |
michael@0 | 696 | return __group_pos; |
michael@0 | 697 | } |
michael@0 | 698 | |
michael@0 | 699 | #endif |
michael@0 | 700 | |
michael@0 | 701 | #if defined (USE_SPRINTF_INSTEAD) || defined (_STLP_EMULATE_LONG_DOUBLE_CVT) |
michael@0 | 702 | struct GroupPos { |
michael@0 | 703 | bool operator () (char __c) const { |
michael@0 | 704 | return __c == '.' || |
michael@0 | 705 | __c == 'e' || __c == 'E'; |
michael@0 | 706 | } |
michael@0 | 707 | }; |
michael@0 | 708 | |
michael@0 | 709 | // Creates a format string for sprintf() |
michael@0 | 710 | static void __fill_fmtbuf(char* fmtbuf, ios_base::fmtflags flags, char long_modifier) { |
michael@0 | 711 | fmtbuf[0] = '%'; |
michael@0 | 712 | int i = 1; |
michael@0 | 713 | |
michael@0 | 714 | if (flags & ios_base::showpos) |
michael@0 | 715 | fmtbuf[i++] = '+'; |
michael@0 | 716 | |
michael@0 | 717 | if (flags & ios_base::showpoint) |
michael@0 | 718 | fmtbuf[i++] = '#'; |
michael@0 | 719 | |
michael@0 | 720 | fmtbuf[i++] = '.'; |
michael@0 | 721 | fmtbuf[i++] = '*'; |
michael@0 | 722 | |
michael@0 | 723 | if (long_modifier) |
michael@0 | 724 | fmtbuf[i++] = long_modifier; |
michael@0 | 725 | |
michael@0 | 726 | switch (flags & ios_base::floatfield) |
michael@0 | 727 | { |
michael@0 | 728 | case ios_base::scientific: |
michael@0 | 729 | fmtbuf[i++] = (flags & ios_base::uppercase) ? 'E' : 'e'; |
michael@0 | 730 | break; |
michael@0 | 731 | case ios_base::fixed: |
michael@0 | 732 | # if defined (__FreeBSD__) |
michael@0 | 733 | fmtbuf[i++] = 'f'; |
michael@0 | 734 | # else |
michael@0 | 735 | fmtbuf[i++] = (flags & ios_base::uppercase) ? 'F' : 'f'; |
michael@0 | 736 | # endif |
michael@0 | 737 | break; |
michael@0 | 738 | default: |
michael@0 | 739 | fmtbuf[i++] = (flags & ios_base::uppercase) ? 'G' : 'g'; |
michael@0 | 740 | break; |
michael@0 | 741 | } |
michael@0 | 742 | |
michael@0 | 743 | fmtbuf[i] = 0; |
michael@0 | 744 | } |
michael@0 | 745 | |
michael@0 | 746 | #endif /* USE_SPRINTF_INSTEAD */ |
michael@0 | 747 | |
michael@0 | 748 | template <class _FloatT> |
michael@0 | 749 | static size_t __write_floatT(__iostring &buf, ios_base::fmtflags flags, int precision, |
michael@0 | 750 | _FloatT x |
michael@0 | 751 | #if defined (USE_SPRINTF_INSTEAD) |
michael@0 | 752 | , char modifier) { |
michael@0 | 753 | /* In theory, if we want 'arbitrary' precision, we should use 'arbitrary' |
michael@0 | 754 | * buffer size below, but really we limited by exponent part in double. |
michael@0 | 755 | * - ptr |
michael@0 | 756 | */ |
michael@0 | 757 | typedef numeric_limits<_FloatT> limits; |
michael@0 | 758 | char static_buf[limits::max_exponent10 + 6]; // 6: -xxx.yyyE-zzz (sign, dot, E, exp sign, \0) |
michael@0 | 759 | char fmtbuf[32]; |
michael@0 | 760 | __fill_fmtbuf(fmtbuf, flags, modifier); |
michael@0 | 761 | snprintf(_STLP_ARRAY_AND_SIZE(static_buf), fmtbuf, precision, x); |
michael@0 | 762 | buf = static_buf; |
michael@0 | 763 | return find_if(buf.begin(), buf.end(), GroupPos()) - buf.begin(); |
michael@0 | 764 | #else |
michael@0 | 765 | ) { |
michael@0 | 766 | typedef numeric_limits<_FloatT> limits; |
michael@0 | 767 | //If numeric_limits support is correct we use the exposed values to detect NaN and infinity: |
michael@0 | 768 | if (limits::has_infinity && limits::has_quiet_NaN) { |
michael@0 | 769 | if (!(x == x) || // NaN check |
michael@0 | 770 | (x == limits::infinity() || x == -limits::infinity())) { |
michael@0 | 771 | return __format_nan_or_inf(buf, x, flags); |
michael@0 | 772 | } |
michael@0 | 773 | } |
michael@0 | 774 | // numeric_limits support is not good enough, we rely on platform dependent function |
michael@0 | 775 | // _Stl_is_nan_or_inf that do not support long double. |
michael@0 | 776 | else if (_Stl_is_nan_or_inf(x)) { |
michael@0 | 777 | return __format_nan_or_inf(buf, x, flags); |
michael@0 | 778 | } |
michael@0 | 779 | # if defined (__MINGW32__) |
michael@0 | 780 | //For the moment MinGW is limited to display at most numeric_limits<double>::max() |
michael@0 | 781 | if (x > numeric_limits<double>::max() || |
michael@0 | 782 | x < -numeric_limits<double>::max()) { |
michael@0 | 783 | return __format_nan_or_inf(buf, x, flags); |
michael@0 | 784 | } |
michael@0 | 785 | # endif |
michael@0 | 786 | |
michael@0 | 787 | /* Buffer size is max number of digits which is the addition of: |
michael@0 | 788 | * - max_exponent10: max number of digits in fixed mode |
michael@0 | 789 | * - digits10 + 2: max number of significant digits |
michael@0 | 790 | * - trailing '\0' |
michael@0 | 791 | */ |
michael@0 | 792 | char cvtbuf[limits::max_exponent10 + limits::digits10 + 2 + 1]; |
michael@0 | 793 | char *bp; |
michael@0 | 794 | int decpt, sign; |
michael@0 | 795 | |
michael@0 | 796 | switch (flags & ios_base::floatfield) { |
michael@0 | 797 | case ios_base::fixed: |
michael@0 | 798 | { |
michael@0 | 799 | /* Here, number of digits represents digits _after_ decimal point. |
michael@0 | 800 | * In order to limit static buffer size we have to give 2 different values depending on x value. |
michael@0 | 801 | * For small values (abs(x) < 1) we need as many digits as requested by precision limited by the maximum number of digits |
michael@0 | 802 | * which is min_exponent10 + digits10 + 2 |
michael@0 | 803 | * For bigger values we won't have more than limits::digits10 + 2 digits after decimal point. */ |
michael@0 | 804 | int digits10 = (x > -1.0 && x < 1.0 ? -limits::min_exponent10 + limits::digits10 + 2 |
michael@0 | 805 | : limits::digits10 + 2); |
michael@0 | 806 | bp = _Stl_fcvtR(x, (min) (precision, digits10), &decpt, &sign, _STLP_CVT_BUFFER(cvtbuf) ); |
michael@0 | 807 | } |
michael@0 | 808 | break; |
michael@0 | 809 | case ios_base::scientific: |
michael@0 | 810 | default: |
michael@0 | 811 | /* Here, number of digits is total number of digits which is limited to digits10 + 2. */ |
michael@0 | 812 | { |
michael@0 | 813 | int digits10 = limits::digits10 + 2; |
michael@0 | 814 | bp = _Stl_ecvtR(x, (min) (precision, digits10), &decpt, &sign, _STLP_CVT_BUFFER(cvtbuf) ); |
michael@0 | 815 | } |
michael@0 | 816 | break; |
michael@0 | 817 | } |
michael@0 | 818 | return __format_float(buf, bp, decpt, sign, x == 0.0, flags, precision); |
michael@0 | 819 | #endif |
michael@0 | 820 | } |
michael@0 | 821 | |
michael@0 | 822 | size_t _STLP_CALL |
michael@0 | 823 | __write_float(__iostring &buf, ios_base::fmtflags flags, int precision, |
michael@0 | 824 | double x) { |
michael@0 | 825 | return __write_floatT(buf, flags, precision, x |
michael@0 | 826 | #if defined (USE_SPRINTF_INSTEAD) |
michael@0 | 827 | , 0 |
michael@0 | 828 | #endif |
michael@0 | 829 | ); |
michael@0 | 830 | } |
michael@0 | 831 | |
michael@0 | 832 | #if !defined (_STLP_NO_LONG_DOUBLE) |
michael@0 | 833 | size_t _STLP_CALL |
michael@0 | 834 | __write_float(__iostring &buf, ios_base::fmtflags flags, int precision, |
michael@0 | 835 | long double x) { |
michael@0 | 836 | return __write_floatT(buf, flags, precision, x |
michael@0 | 837 | #if defined (USE_SPRINTF_INSTEAD) |
michael@0 | 838 | , 'L' |
michael@0 | 839 | #endif |
michael@0 | 840 | ); |
michael@0 | 841 | } |
michael@0 | 842 | #endif |
michael@0 | 843 | |
michael@0 | 844 | void _STLP_CALL __get_floor_digits(__iostring &out, _STLP_LONGEST_FLOAT_TYPE __x) { |
michael@0 | 845 | typedef numeric_limits<_STLP_LONGEST_FLOAT_TYPE> limits; |
michael@0 | 846 | #if defined (USE_SPRINTF_INSTEAD) |
michael@0 | 847 | char cvtbuf[limits::max_exponent10 + 6]; |
michael@0 | 848 | # if !defined (_STLP_NO_LONG_DOUBLE) |
michael@0 | 849 | snprintf(_STLP_ARRAY_AND_SIZE(cvtbuf), "%Lf", __x); // check for 1234.56! |
michael@0 | 850 | # else |
michael@0 | 851 | snprintf(_STLP_ARRAY_AND_SIZE(cvtbuf), "%f", __x); // check for 1234.56! |
michael@0 | 852 | # endif |
michael@0 | 853 | char *p = strchr( cvtbuf, '.' ); |
michael@0 | 854 | if ( p == 0 ) { |
michael@0 | 855 | out.append( cvtbuf ); |
michael@0 | 856 | } else { |
michael@0 | 857 | out.append( cvtbuf, p ); |
michael@0 | 858 | } |
michael@0 | 859 | #else |
michael@0 | 860 | char cvtbuf[limits::max_exponent10 + 1]; |
michael@0 | 861 | char * bp; |
michael@0 | 862 | int decpt, sign; |
michael@0 | 863 | bp = _Stl_fcvtR(__x, 0, &decpt, &sign, _STLP_CVT_BUFFER(cvtbuf)); |
michael@0 | 864 | |
michael@0 | 865 | if (sign) { |
michael@0 | 866 | out += '-'; |
michael@0 | 867 | } |
michael@0 | 868 | out.append(bp, bp + decpt); |
michael@0 | 869 | #endif |
michael@0 | 870 | } |
michael@0 | 871 | |
michael@0 | 872 | |
michael@0 | 873 | #if !defined (_STLP_NO_WCHAR_T) |
michael@0 | 874 | void _STLP_CALL __convert_float_buffer( __iostring const& str, __iowstring &out, |
michael@0 | 875 | const ctype<wchar_t>& ct, wchar_t dot, bool __check_dot) { |
michael@0 | 876 | string::const_iterator str_ite(str.begin()), str_end(str.end()); |
michael@0 | 877 | |
michael@0 | 878 | //First loop, check the dot char |
michael@0 | 879 | if (__check_dot) { |
michael@0 | 880 | while (str_ite != str_end) { |
michael@0 | 881 | if (*str_ite != '.') { |
michael@0 | 882 | out += ct.widen(*str_ite++); |
michael@0 | 883 | } else { |
michael@0 | 884 | out += dot; |
michael@0 | 885 | break; |
michael@0 | 886 | } |
michael@0 | 887 | } |
michael@0 | 888 | } else { |
michael@0 | 889 | if (str_ite != str_end) { |
michael@0 | 890 | out += ct.widen(*str_ite); |
michael@0 | 891 | } |
michael@0 | 892 | } |
michael@0 | 893 | |
michael@0 | 894 | if (str_ite != str_end) { |
michael@0 | 895 | //Second loop, dot has been found, no check anymore |
michael@0 | 896 | while (++str_ite != str_end) { |
michael@0 | 897 | out += ct.widen(*str_ite); |
michael@0 | 898 | } |
michael@0 | 899 | } |
michael@0 | 900 | } |
michael@0 | 901 | |
michael@0 | 902 | #endif |
michael@0 | 903 | |
michael@0 | 904 | void _STLP_CALL |
michael@0 | 905 | __adjust_float_buffer(__iostring &str, char dot) { |
michael@0 | 906 | if ('.' != dot) { |
michael@0 | 907 | size_t __dot_pos = str.find('.'); |
michael@0 | 908 | if (__dot_pos != string::npos) { |
michael@0 | 909 | str[__dot_pos] = dot; |
michael@0 | 910 | } |
michael@0 | 911 | } |
michael@0 | 912 | } |
michael@0 | 913 | |
michael@0 | 914 | _STLP_MOVE_TO_STD_NAMESPACE |
michael@0 | 915 | _STLP_END_NAMESPACE |
michael@0 | 916 | |
michael@0 | 917 | // Local Variables: |
michael@0 | 918 | // mode:C++ |
michael@0 | 919 | // End: |