ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

num_put_float.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1999
00003  * Silicon Graphics Computer Systems, Inc.
00004  *
00005  * Copyright (c) 1999
00006  * Boris Fomitchev
00007  *
00008  * This material is provided "as is", with absolutely no warranty expressed
00009  * or implied. Any use is at your own risk.
00010  *
00011  * Permission to use or copy this software for any purpose is hereby granted
00012  * without fee, provided the above notices are retained on all copies.
00013  * Permission to modify the code and to distribute modified code is granted,
00014  * provided the above notices are retained, and a notice that the code was
00015  * modified is included with the above copyright notice.
00016  *
00017  */
00018 
00019 #include "stlport_prefix.h"
00020 
00021 #include <cmath>
00022 #include <ios>
00023 #include <locale>
00024 
00025 #if defined (__DECCXX)
00026 #  define NDIG 400
00027 #else
00028 #  define NDIG 82
00029 #endif
00030 
00031 #define todigit(x) ((x)+'0')
00032 
00033 #if defined (_STLP_UNIX)
00034 
00035 #  if defined (__sun)
00036 #    include <floatingpoint.h>
00037 #  endif
00038 
00039 #  if defined (__sun) || defined (__digital__) || defined (__sgi) || defined (_STLP_SCO_OPENSERVER) || defined (__NCR_SVR)
00040 // DEC, SGI & Solaris need this
00041 #    include <values.h>
00042 #    include <nan.h>
00043 #  endif
00044 
00045 #  if defined (__QNXNTO__) || ( defined(__GNUC__) && defined(__APPLE__) ) || defined(_STLP_USE_UCLIBC) /* 0.9.26 */ || \
00046       defined(__FreeBSD__)
00047 #    define USE_SPRINTF_INSTEAD
00048 #  endif
00049 
00050 #  if defined (_AIX) // JFA 3-Aug-2000
00051 #    include <math.h>
00052 #    include <float.h>
00053 #  endif
00054 
00055 #  include <math.h>
00056 #endif
00057 
00058 #include <cstdio>
00059 #include <cstdlib>
00060 
00061 #if defined (_STLP_MSVC_LIB) || defined (__MINGW32__) || defined (__BORLANDC__) || defined (__DJGPP) || \
00062     defined (_STLP_SCO_OPENSERVER) || defined (__NCR_SVR)
00063 #  include <float.h>
00064 #endif
00065 
00066 #if defined (__MRC__) || defined (__SC__)  || defined (_CRAY)  //*TY 02/24/2000 - added support for MPW
00067 #  include <fp.h>
00068 #endif
00069 
00070 #if defined (__CYGWIN__)
00071 #  include <ieeefp.h>
00072 #endif
00073 
00074 #if defined (__MSL__)
00075 #  include <cstdlib>  // for atoi
00076 #  include <cstdio>  // for snprintf
00077 #  include <algorithm>
00078 #  include <cassert>
00079 #endif
00080 
00081 #if defined (__ISCPP__)
00082 #  include <cfloat>
00083 #endif
00084 
00085 #include <algorithm>
00086 
00087 #if defined (__DMC__)
00088 #  define snprintf _snprintf
00089 #endif
00090 
00091 _STLP_BEGIN_NAMESPACE
00092 
00093 _STLP_MOVE_TO_PRIV_NAMESPACE
00094 
00095 #if defined (__MWERKS__) || defined(__BEOS__)
00096 #  define USE_SPRINTF_INSTEAD
00097 #endif
00098 
00099 template <int N>
00100 struct _Dig
00101 {
00102     enum { dig = _Dig<N/10>::dig + 1 };
00103 };
00104 
00105 _STLP_TEMPLATE_NULL
00106 struct _Dig<0>
00107 {
00108     enum { dig = 0 };
00109 };
00110 
00111 #ifdef _STLP_NO_LONG_DOUBLE
00112 # define MAXEDIGITS int(_Dig<DBL_MAX_10_EXP>::dig)
00113 # define MAXFSIG DBL_DIG
00114 # define MAXFCVT (DBL_DIG + 1)
00115 #else
00116 # define MAXEDIGITS int(_Dig<LDBL_MAX_10_EXP>::dig)
00117 # define MAXFSIG LDBL_DIG
00118 # define MAXFCVT (LDBL_DIG + 1)
00119 #endif
00120 
00121 // Tests for infinity and NaN differ on different OSs.  We encapsulate
00122 // these differences here.
00123 #if !defined (USE_SPRINTF_INSTEAD)
00124 #  if defined (__hpux) && defined (__GNUC__)
00125 #    define _STLP_USE_SIGN_HELPER
00126 #  elif defined (__DJGPP) || (defined (_STLP_USE_GLIBC) && ! defined (__MSL__)) || \
00127       defined (__CYGWIN__) || \
00128       defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || \
00129       defined (__HP_aCC)
00130 static inline bool _Stl_is_nan_or_inf(double x)
00131 #    if defined (isfinite)
00132 { return !isfinite(x); }
00133 #    else
00134 { return !finite(x); }
00135 #    endif
00136 static inline bool _Stl_is_neg_nan(double x)    { return isnan(x) && ( copysign(1., x) < 0 ); }
00137 static inline bool _Stl_is_inf(double x)        { return isinf(x); }
00138 // inline bool _Stl_is_neg_inf(double x)    { return isinf(x) < 0; }
00139 static inline bool _Stl_is_neg_inf(double x)    { return isinf(x) && x < 0; }
00140 #  elif (defined (__unix) || defined (__unix__)) && \
00141          !defined (__APPLE__) && !defined (__DJGPP) && !defined(__osf__) && \
00142          !defined (_CRAY)
00143 static inline bool _Stl_is_nan_or_inf(double x) { return IsNANorINF(x); }
00144 static inline bool _Stl_is_inf(double x)        { return IsNANorINF(x) && IsINF(x); }
00145 static inline bool _Stl_is_neg_inf(double x)    { return (IsINF(x)) && (x < 0.0); }
00146 static inline bool _Stl_is_neg_nan(double x)    { return IsNegNAN(x); }
00147 #  elif defined (_STLP_MSVC_LIB) || defined (__MINGW32__) || defined (__BORLANDC__)
00148 static inline bool _Stl_is_nan_or_inf(double x) { return !_finite(x); }
00149 #    if !defined (__BORLANDC__)
00150 static inline bool _Stl_is_inf(double x)        {
00151   int fclass = _fpclass(x);
00152   return fclass == _FPCLASS_NINF || fclass == _FPCLASS_PINF;
00153 }
00154 static inline bool _Stl_is_neg_inf(double x)    { return _fpclass(x) == _FPCLASS_NINF; }
00155 #    else
00156 static inline bool _Stl_is_inf(double x)        {  return _Stl_is_nan_or_inf(x) && !_isnan(x);}
00157 static inline bool _Stl_is_neg_inf(double x)    {  return _Stl_is_inf(x) && x < 0 ; }
00158 #    endif
00159 static inline bool _Stl_is_neg_nan(double x)    { return _isnan(x) && _copysign(1., x) < 0 ; }
00160 #    if defined (__BORLANDC__)
00161 static inline bool _Stl_is_nan_or_inf(long double x) { return !_finitel(x); }
00162 static inline bool _Stl_is_inf(long double x)        {  return _Stl_is_nan_or_inf(x) && !_isnanl(x);}
00163 static inline bool _Stl_is_neg_inf(long double x)    {  return _Stl_is_inf(x) && x < 0 ; }
00164 static inline bool _Stl_is_neg_nan(long double x)    { return _isnanl(x) && _copysignl(1.l, x) < 0 ; }
00165 #    elif !defined (_STLP_NO_LONG_DOUBLE)
00166 // Simply there to avoid warning long double -> double implicit conversion:
00167 static inline bool _Stl_is_nan_or_inf(long double x) { return _Stl_is_nan_or_inf(__STATIC_CAST(double, x)); }
00168 static inline bool _Stl_is_inf(long double x)        {  return _Stl_is_inf(__STATIC_CAST(double, x));}
00169 static inline bool _Stl_is_neg_inf(long double x)    {  return _Stl_is_neg_inf(__STATIC_CAST(double, x)); }
00170 static inline bool _Stl_is_neg_nan(long double x)    { return _Stl_is_neg_nan(__STATIC_CAST(double, x)); }
00171 #    endif
00172 #  elif defined (__MRC__) || defined (__SC__) || defined (__DMC__)
00173 static bool _Stl_is_nan_or_inf(double x) { return isnan(x) || !isfinite(x); }
00174 static bool _Stl_is_inf(double x)        { return !isfinite(x); }
00175 static bool _Stl_is_neg_inf(double x)    { return !isfinite(x) && signbit(x); }
00176 static bool _Stl_is_neg_nan(double x)    { return isnan(x) && signbit(x); }
00177 #  elif /* defined(__FreeBSD__) || defined(__OpenBSD__) || */ (defined(__GNUC__) && defined(__APPLE__))
00178 static inline bool _Stl_is_nan_or_inf(double x) { return !finite(x); }
00179 static inline bool _Stl_is_inf(double x)        {   return _Stl_is_nan_or_inf(x) && ! isnan(x); }
00180 static inline bool _Stl_is_neg_inf(double x)    {   return _Stl_is_inf(x) && x < 0 ; }
00181 static inline bool _Stl_is_neg_nan(double x)    { return isnan(x) && copysign(1., x) < 0 ; }
00182 #  elif defined( _AIX ) // JFA 11-Aug-2000
00183 static bool _Stl_is_nan_or_inf(double x) { return isnan(x) || !finite(x); }
00184 static bool _Stl_is_inf(double x)        { return !finite(x); }
00185 // bool _Stl_is_neg_inf(double x)    { return _class(x) == FP_MINUS_INF; }
00186 static bool _Stl_is_neg_inf(double x)    { return _Stl_is_inf(x) && ( copysign(1., x) < 0 );  }
00187 static bool _Stl_is_neg_nan(double x)    { return isnan(x) && ( copysign(1., x) < 0 );  }
00188 #  elif defined (__ISCPP__)
00189 static inline bool _Stl_is_nan_or_inf  (double x) { return _fp_isINF(x) || _fp_isNAN(x); }
00190 static inline bool _Stl_is_inf         (double x) { return _fp_isINF(x); }
00191 static inline bool _Stl_is_neg_inf     (double x) { return _fp_isINF(x) && x < 0; }
00192 static inline bool _Stl_is_neg_nan     (double x) { return _fp_isNAN(x) && x < 0; }
00193 #  elif defined (_CRAY)
00194 #    if defined (_CRAYIEEE)
00195 static inline bool _Stl_is_nan_or_inf(double x) { return isnan(x) || isinf(x); }
00196 static inline bool _Stl_is_inf(double x)        { return isinf(x); }
00197 static inline bool _Stl_is_neg_inf(double x)    { return isinf(x) && signbit(x); }
00198 static inline bool _Stl_is_neg_nan(double x)    { return isnan(x) && signbit(x); }
00199 #    else
00200 static inline bool _Stl_is_nan_or_inf(double x) { return false; }
00201 static inline bool _Stl_is_inf(double x)        { return false; }
00202 static inline bool _Stl_is_neg_inf(double x)    { return false; }
00203 static inline bool _Stl_is_neg_nan(double x)    { return false; }
00204 #    endif
00205 #  else // nothing from above
00206 #    define USE_SPRINTF_INSTEAD
00207 #  endif
00208 #endif // !USE_SPRINTF_INSTEAD
00209 
00210 #if !defined (USE_SPRINTF_INSTEAD)
00211 // Reentrant versions of floating-point conversion functions.  The argument
00212 // lists look slightly different on different operating systems, so we're
00213 // encapsulating the differences here.
00214 
00215 #  if defined (__CYGWIN__) || defined(__DJGPP)
00216 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf)
00217 { return ecvtbuf(x, n, pt, sign, buf); }
00218 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf)
00219 { return fcvtbuf(x, n, pt, sign, buf); }
00220 #    if !defined (_STLP_NO_LONG_DOUBLE)
00221 #      if defined (__CYGWIN__)
00222 #        define _STLP_EMULATE_LONG_DOUBLE_CVT
00223 #      else
00224 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf)
00225 { return ecvtbuf(x, n, pt, sign, buf); }
00226 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf)
00227 { return fcvtbuf(x, n, pt, sign, buf); }
00228 #      endif
00229 #    endif
00230 #  elif defined (_STLP_USE_GLIBC)
00231 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf, size_t bsize)
00232 { return ecvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0; }
00233 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf, size_t bsize)
00234 { return fcvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0; }
00235 #    ifndef _STLP_NO_LONG_DOUBLE
00236 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf, size_t bsize)
00237 { return qecvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0; }
00238 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf, size_t bsize)
00239 { return qfcvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0; }
00240 #    endif
00241 #    define _STLP_NEED_CVT_BUFFER_SIZE
00242 #  elif defined (__sun)
00243 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf)
00244 { return econvert(x, n, pt, sign, buf); }
00245 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf)
00246 { return fconvert(x, n, pt, sign, buf); }
00247 #    ifndef _STLP_NO_LONG_DOUBLE
00248 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf)
00249 { return qeconvert(&x, n, pt, sign, buf); }
00250 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf)
00251 { return qfconvert(&x, n, pt, sign, buf); }
00252 #    endif
00253 #  elif defined (__DECCXX)
00254 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf, size_t bsize)
00255 { return (ecvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0); }
00256 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf, size_t bsize)
00257 { return (fcvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0); }
00258 #    ifndef _STLP_NO_LONG_DOUBLE
00259 // fbp : no "long double" conversions !
00260 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf, size_t bsize)
00261 { return (ecvt_r((double)x, n, pt, sign, buf, bsize) == 0 ? buf : 0) ; }
00262 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf, size_t bsize)
00263 { return (fcvt_r((double)x, n, pt, sign, buf, bsize) == 0 ? buf : 0); }
00264 #    endif
00265 #    define _STLP_NEED_CVT_BUFFER_SIZE
00266 #  elif defined (__hpux)
00267 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign)
00268 { return ecvt(x, n, pt, sign); }
00269 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign)
00270 { return fcvt(x, n, pt, sign); }
00271 #    if !defined (_STLP_NO_LONG_DOUBLE)
00272 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign)
00273 { return _ldecvt(*(long_double*)&x, n, pt, sign); }
00274 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign)
00275 { return _ldfcvt(*(long_double*)&x, n, pt, sign); }
00276 #    endif
00277 #    define _STLP_CVT_NEED_SYNCHRONIZATION
00278 #  elif defined (__unix) && !defined (__APPLE__) && !defined (_CRAY)
00279 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf)
00280 { return ecvt_r(x, n, pt, sign, buf); }
00281 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf)
00282 { return fcvt_r(x, n, pt, sign, buf); }
00283 #    if !defined (_STLP_NO_LONG_DOUBLE)
00284 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf)
00285 { return qecvt_r(x, n, pt, sign, buf); }
00286 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf)
00287 { return qfcvt_r(x, n, pt, sign, buf); }
00288 #    endif
00289 #  elif defined (_STLP_MSVC_LIB) || defined (__MINGW32__) || defined (__BORLANDC__)
00290 #    if defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
00291 #      define _STLP_APPEND(a, b) a##b
00292 #      define _STLP_BUF_PARAMS , char* buf, size_t bsize
00293 #      define _STLP_SECURE_FUN(F, X, N, PT, SIGN) _STLP_APPEND(F, _s)(buf, bsize, X, N, PT, SIGN); return buf
00294 #    else
00295 #      define _STLP_BUF_PARAMS
00296 #      define _STLP_SECURE_FUN(F, X, N, PT, SIGN) return F(X, N, PT, SIGN)
00297 #      define _STLP_CVT_NEED_SYNCHRONIZATION
00298 #    endif
00299 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign _STLP_BUF_PARAMS)
00300 { _STLP_SECURE_FUN(_ecvt, x, n, pt, sign); }
00301 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign _STLP_BUF_PARAMS)
00302 { _STLP_SECURE_FUN(_fcvt, x, n, pt, sign); }
00303 #    if !defined (_STLP_NO_LONG_DOUBLE)
00304 #      if defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
00305 #        define _STLP_PARAMS , buf, bsize
00306 #      else
00307 #        define _STLP_PARAMS
00308 #      endif
00309 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign _STLP_BUF_PARAMS)
00310 { return _Stl_ecvtR(__STATIC_CAST(double, x), n, pt, sign _STLP_PARAMS); }
00311 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign _STLP_BUF_PARAMS)
00312 { return _Stl_fcvtR(__STATIC_CAST(double, x), n, pt, sign _STLP_PARAMS); }
00313 #      undef _STLP_PARAMS
00314 #    endif
00315 #    undef _STLP_SECURE_FUN
00316 #    undef _STLP_BUF_PARAMS
00317 #    undef _STLP_APPEND
00318 #    if defined (__BORLANDC__) /* || defined (__GNUC__) MinGW do not support 'L' modifier so emulation do not work */
00319 #      define _STLP_EMULATE_LONG_DOUBLE_CVT
00320 #    endif
00321 #  elif defined (__ISCPP__)
00322 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf)
00323 { return _fp_ecvt( x, n, pt, sign, buf); }
00324 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf)
00325 { return _fp_fcvt(x, n, pt, sign, buf); }
00326 #    if !defined (_STLP_NO_LONG_DOUBLE)
00327 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf)
00328 { return _fp_ecvt( x, n, pt, sign, buf); }
00329 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf)
00330 { return _fp_fcvt(x, n, pt, sign, buf); }
00331 #    endif
00332 #  elif defined (_AIX) || defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || \
00333         defined (__MRC__) || defined (__SC__) || defined (_CRAY) || \
00334         defined (_STLP_SCO_OPENSERVER) || defined (__NCR_SVR) || \
00335         defined (__DMC__)
00336 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign)
00337 { return ecvt(x, n, pt, sign ); }
00338 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign)
00339 { return fcvt(x, n, pt, sign); }
00340 #    if !defined (_STLP_NO_LONG_DOUBLE)
00341 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign)
00342 { return ecvt(x, n, pt, sign ); }
00343 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign)
00344 { return fcvt(x, n, pt, sign); }
00345 #    endif
00346 #    define _STLP_CVT_NEED_SYNCHRONIZATION
00347 #  else
00348 #    error Missing _Stl_ecvtR and _Stl_fcvtR implementations.
00349 #  endif
00350 
00351 #if defined (_STLP_CVT_NEED_SYNCHRONIZATION)
00352 /* STLport synchronize access to *cvt functions but those methods might
00353  * be called from outside, in this case we will still have a race condition. */
00354 #  if defined (_STLP_THREADS)
00355 static _STLP_STATIC_MUTEX& put_float_mutex() {
00356   static _STLP_STATIC_MUTEX __put_float_mutex _STLP_MUTEX_INITIALIZER;
00357   return __put_float_mutex;
00358 }
00359 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf) {
00360   _STLP_auto_lock lock(put_float_mutex());
00361   strcpy(buf, _Stl_ecvtR(x, n, pt, sign)); return buf;
00362 }
00363 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf) {
00364   _STLP_auto_lock lock(put_float_mutex());
00365   strcpy(buf, _Stl_fcvtR(x, n, pt, sign)); return buf;
00366 }
00367 #    if !defined (_STLP_NO_LONG_DOUBLE) && !defined (_STLP_EMULATE_LONG_DOUBLE_CVT)
00368 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf) {
00369   _STLP_auto_lock lock(put_float_mutex());
00370   strcpy(buf, _Stl_ecvtR(x, n, pt, sign)); return buf;
00371 }
00372 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf) {
00373   _STLP_auto_lock lock(put_float_mutex());
00374   strcpy(buf, _Stl_fcvtR(x, n, pt, sign)); return buf;
00375 }
00376 #    endif
00377 #  else
00378 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char*)
00379 { return _Stl_ecvtR(x, n, pt, sign); }
00380 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char*)
00381 { return _Stl_fcvtR(x, n, pt, sign); }
00382 #    if !defined (_STLP_NO_LONG_DOUBLE) && !defined (_STLP_EMULATE_LONG_DOUBLE_CVT)
00383 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char*)
00384 { return _Stl_ecvtR(x, n, pt, sign); }
00385 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char*)
00386 { return _Stl_fcvtR(x, n, pt, sign); }
00387 #    endif
00388 #  endif
00389 #endif
00390 
00391 #  if !defined (_STLP_USE_SAFE_STRING_FUNCTIONS) && !defined (_STLP_NEED_CVT_BUFFER_SIZE)
00392 #    define _STLP_CVT_BUFFER(B) B
00393 #  else
00394 #    define _STLP_CVT_BUFFER(B) _STLP_ARRAY_AND_SIZE(B)
00395 #  endif
00396 
00397 #  if defined (_STLP_EMULATE_LONG_DOUBLE_CVT)
00398 static void __fill_fmtbuf(char* fmtbuf, ios_base::fmtflags flags, char long_modifier);
00399 
00400 // Emulation of ecvt/fcvt functions using sprintf:
00401 static char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf) {
00402   // If long double value can be safely converted to double without losing precision
00403   // we use the ecvt function for double:
00404   double y = __STATIC_CAST(double, x); 
00405   if (x == y)
00406     return _Stl_ecvtR(y, n, pt, sign, buf);
00407 
00408   char fmtbuf[32];
00409   __fill_fmtbuf(fmtbuf, 0, 'L');
00410   sprintf(buf, fmtbuf, n, x < 0.0l ? -x : x);
00411   /* We are waiting for something having the form x.xxxe+yyyy */
00412   *pt = 0;
00413   *sign = 0;
00414   int i = -1;
00415   int offset = 0;
00416   while (buf[++i] != 0 && n != 0) {
00417     if (buf[i] >= '0' && buf[i] <= '9') {
00418       --n;
00419       if (offset != 0)
00420         buf[i - offset] = buf[i];
00421     }
00422     else {
00423       if (offset != 0) break;
00424       ++offset;
00425       *pt = i;
00426     }
00427   }
00428   if (offset != 0)
00429     buf[i - offset] = 0;
00430   // Extract exponent part in point position:
00431   int e = 0;
00432   while (buf[++i] != 0) {
00433     if (buf[i] >= '0' && buf[i] <= '9') {
00434       e = e * 10 + (buf[i] - '0');
00435     }
00436   }
00437   *pt += e;
00438   return buf;
00439 }
00440 
00441 static char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf) {
00442   // If long double value can be safely converted to double without losing precision
00443   // we use the fcvt function for double:
00444   double y = __STATIC_CAST(double, x);
00445   if (x == y)
00446     return _Stl_fcvtR(y, n, pt, sign, buf);
00447 
00448   char fmtbuf[32];
00449   __fill_fmtbuf(fmtbuf, ios_base::fixed, 'L');
00450   sprintf(buf, fmtbuf, n, x < 0.0l ? -x : x);
00451   *pt = 0;
00452   *sign = 0;
00453   int i = -1;
00454   int offset = 0;
00455   while (buf[++i] != 0 && (offset == 0 || n != 0)) {
00456     if (buf[i] >= '0' && buf[i] <= '9') {
00457       if (offset != 0) {
00458         --n;
00459         buf[i - offset] = buf[i];
00460       }
00461     }
00462     else {
00463       ++offset;
00464       *pt = i;
00465     }
00466   }
00467   if (offset != 0)
00468     buf[i - offset] = 0;
00469   else
00470     *pt = i;
00471   return buf;
00472 }
00473 #endif
00474 
00475 //----------------------------------------------------------------------
00476 // num_put
00477 
00478 // __format_float formats a mantissa and exponent as returned by
00479 // one of the conversion functions (ecvt_r, fcvt_r, qecvt_r, qfcvt_r)
00480 // according to the specified precision and format flags.  This is
00481 // based on doprnt but is much simpler since it is concerned only
00482 // with floating point input and does not consider all formats.  It
00483 // also does not deal with blank padding, which is handled by
00484 // __copy_float_and_fill.
00485 
00486 static size_t __format_float_scientific( __iostring& buf, const char *bp,
00487                                          int decpt, int sign, bool is_zero,
00488                                          ios_base::fmtflags flags,
00489                                          int precision) {
00490   // sign if required
00491   if (sign)
00492     buf += '-';
00493   else if (flags & ios_base::showpos)
00494     buf += '+';
00495 
00496   // first digit of mantissa
00497   buf += *bp++;
00498 
00499   // start of grouping position, grouping won't occur in scientific notation
00500   // as it is impossible to have something like 1234.0e04 but we return a correct
00501   // group position for coherency with __format_float_fixed.
00502   size_t __group_pos = buf.size();
00503 
00504   // decimal point if required
00505   if (precision != 0 || flags & ios_base::showpoint) {
00506     buf += '.';
00507   }
00508 
00509   // rest of mantissa
00510   while (*bp != 0 && precision--)
00511     buf += *bp++;
00512 
00513   // trailing 0 if needed
00514   if (precision > 0)
00515     buf.append(precision, '0');
00516 
00517   // exponent size = number of digits + exponent sign + exponent symbol + trailing zero
00518   char expbuf[MAXEDIGITS + 3];
00519   //We start filling at the buffer end
00520   char *suffix = expbuf + MAXEDIGITS + 2;
00521   *suffix = 0;
00522   if (!is_zero) {
00523     int nn = decpt - 1;
00524     if (nn < 0)
00525       nn = -nn;
00526     for (; nn > 9; nn /= 10)
00527       *--suffix = (char) todigit(nn % 10);
00528     *--suffix = (char) todigit(nn);
00529   }
00530 
00531   // prepend leading zeros to exponent
00532   // C89 Standard says that it should be at least 2 digits, C99 Standard says that
00533   // we stop prepend zeros if more than 3 digits. To repect both STLport prepend zeros
00534   // until it is 2 digits.
00535   while (suffix > &expbuf[MAXEDIGITS])
00536     *--suffix = '0';
00537 
00538   // put in the exponent sign
00539   *--suffix = (char) ((decpt > 0 || is_zero ) ? '+' : '-');
00540 
00541   // put in the e
00542   *--suffix = flags & ios_base::uppercase ? 'E' : 'e';
00543 
00544   // copy the suffix
00545   buf += suffix;
00546   return __group_pos;
00547 }
00548 
00549 static size_t __format_float_fixed( __iostring &buf, const char *bp,
00550                                     int decpt, int sign,
00551                                     ios_base::fmtflags flags,
00552                                     int precision) {
00553   if ( sign && (decpt > -precision) && (*bp != 0) )
00554     buf += '-';
00555   else if ( flags & ios_base::showpos )
00556     buf += '+';
00557 
00558   // digits before decimal point
00559   int nnn = decpt;
00560   do {
00561     buf += (nnn <= 0 || *bp == 0) ? '0' : *bp++;
00562   } while ( --nnn > 0 );
00563 
00564   // start of grouping position
00565   size_t __group_pos = buf.size();
00566 
00567   // decimal point if needed
00568   if ( flags & ios_base::showpoint || precision > 0 ) {
00569     buf += '.';
00570   }
00571 
00572   // digits after decimal point if any
00573   while ( *bp != 0 && --precision >= 0 ) {
00574     buf += (++decpt <= 0) ? '0' : *bp++;
00575   }
00576 
00577   // trailing zeros if needed
00578   if (precision > 0)
00579     buf.append(precision, '0');
00580 
00581   return __group_pos;
00582 }
00583 
00584 #if defined (_STLP_USE_SIGN_HELPER)
00585 template<class _FloatT>
00586 struct float_sign_helper {
00587   float_sign_helper(_FloatT __x)
00588   { _M_number._num = __x; }
00589 
00590   bool is_negative() const {
00591     const unsigned short sign_mask(1 << (sizeof(unsigned short) * CHAR_BIT - 1));
00592     return (get_sign_word() & sign_mask) != 0;
00593   }
00594 private:
00595   union {
00596     unsigned short _Words[8];
00597     _FloatT _num;
00598   } _M_number;
00599 
00600   unsigned short get_word_higher() const _STLP_NOTHROW
00601   { return _M_number._Words[0]; }
00602   unsigned short get_word_lower() const _STLP_NOTHROW
00603   { return _M_number._Words[(sizeof(_FloatT) >= 12 ? 10 : sizeof(_FloatT)) / sizeof(unsigned short) - 1]; }
00604   unsigned short get_sign_word() const _STLP_NOTHROW
00605 #  if defined (_STLP_BIG_ENDIAN)
00606   { return get_word_higher(); }
00607 #  else /* _STLP_LITTLE_ENDIAN */
00608   { return get_word_lower(); }
00609 #  endif
00610 };
00611 #endif
00612 
00613 template <class _FloatT>
00614 static size_t __format_nan_or_inf(__iostring& buf, _FloatT x, ios_base::fmtflags flags) {
00615   static const char* inf[2] = { "inf", "Inf" };
00616   static const char* nan[2] = { "nan", "NaN" };
00617   const char** inf_or_nan;
00618 #if !defined (_STLP_USE_SIGN_HELPER)
00619   if (_Stl_is_inf(x)) {            // Infinity
00620     inf_or_nan = inf;
00621     if (_Stl_is_neg_inf(x))
00622       buf += '-';
00623     else if (flags & ios_base::showpos)
00624       buf += '+';
00625   } else {                      // NaN
00626     inf_or_nan = nan;
00627     if (_Stl_is_neg_nan(x))
00628       buf += '-';
00629     else if (flags & ios_base::showpos)
00630       buf += '+';
00631   }
00632 #else
00633   typedef numeric_limits<_FloatT> limits;
00634   if (x == limits::infinity() || x == -limits::infinity()) {
00635     inf_or_nan = inf;
00636   } else {                    // NaN
00637     inf_or_nan = nan;
00638   }
00639   float_sign_helper<_FloatT> helper(x);
00640   if (helper.is_negative())
00641     buf += '-';
00642   else if (flags & ios_base::showpos)
00643     buf += '+';
00644 #endif
00645   size_t ret = buf.size();
00646   buf += inf_or_nan[flags & ios_base::uppercase ? 1 : 0];
00647   return ret;
00648 }
00649 
00650 static inline size_t __format_float(__iostring &buf, const char * bp,
00651                                     int decpt, int sign, bool is_zero,
00652                                     ios_base::fmtflags flags,
00653                                     int precision) {
00654   size_t __group_pos = 0;
00655   switch (flags & ios_base::floatfield) {
00656     case ios_base::scientific:
00657       __group_pos = __format_float_scientific( buf, bp, decpt, sign, is_zero,
00658                                                flags, precision);
00659       break;
00660     case ios_base::fixed:
00661       __group_pos = __format_float_fixed( buf, bp, decpt, sign,
00662                                           flags, precision);
00663       break;
00664     default: // g format
00665       // establish default precision
00666       if (flags & ios_base::showpoint || precision > 0) {
00667         if (precision == 0) precision = 1;
00668       } else
00669         precision = 6;
00670 
00671       // reset exponent if value is zero
00672       if (is_zero)
00673         decpt = 1;
00674 
00675       int kk = precision;
00676       if (!(flags & ios_base::showpoint)) {
00677         size_t n = strlen(bp);
00678         if (n < (size_t)kk)
00679           kk = (int)n;
00680         while (kk >= 1 && bp[kk-1] == '0')
00681           --kk;
00682       }
00683 
00684       if (decpt < -3 || decpt > precision) {
00685         precision = kk - 1;
00686         __group_pos = __format_float_scientific( buf, bp, decpt, sign, is_zero,
00687                                                  flags, precision);
00688       } else {
00689         precision = kk - decpt;
00690         __group_pos = __format_float_fixed( buf, bp, decpt, sign,
00691                                             flags, precision);
00692       }
00693       break;
00694   } /* switch */
00695   return __group_pos;
00696 }
00697 
00698 #endif
00699 
00700 #if defined (USE_SPRINTF_INSTEAD) || defined (_STLP_EMULATE_LONG_DOUBLE_CVT)
00701 struct GroupPos {
00702   bool operator () (char __c) const {
00703     return __c == '.' ||
00704            __c == 'e' || __c == 'E';
00705   }
00706 };
00707 
00708 // Creates a format string for sprintf()
00709 static void __fill_fmtbuf(char* fmtbuf, ios_base::fmtflags flags, char long_modifier) {
00710   fmtbuf[0] = '%';
00711   int i = 1;
00712 
00713   if (flags & ios_base::showpos)
00714     fmtbuf[i++] = '+';
00715 
00716   if (flags & ios_base::showpoint)
00717     fmtbuf[i++] = '#';
00718 
00719   fmtbuf[i++] = '.';
00720   fmtbuf[i++] = '*';
00721 
00722   if (long_modifier)
00723     fmtbuf[i++] = long_modifier;
00724 
00725   switch (flags & ios_base::floatfield)
00726     {
00727     case ios_base::scientific:
00728       fmtbuf[i++] = (flags & ios_base::uppercase) ?  'E' : 'e';
00729       break;
00730     case ios_base::fixed:
00731 #  if defined (__FreeBSD__)
00732       fmtbuf[i++] = 'f';
00733 #  else
00734       fmtbuf[i++] = (flags & ios_base::uppercase) ? 'F' : 'f';
00735 #  endif
00736       break;
00737     default:
00738       fmtbuf[i++] = (flags & ios_base::uppercase) ?  'G' : 'g';
00739       break;
00740     }
00741 
00742   fmtbuf[i] = 0;
00743 }
00744 
00745 #endif  /* USE_SPRINTF_INSTEAD */
00746 
00747 template <class _FloatT>
00748 static size_t  __write_floatT(__iostring &buf, ios_base::fmtflags flags, int precision,
00749                               _FloatT x
00750 #if defined (USE_SPRINTF_INSTEAD)
00751                               , char modifier) {
00752   /* In theory, if we want 'arbitrary' precision, we should use 'arbitrary'
00753    * buffer size below, but really we limited by exponent part in double.
00754    *    - ptr
00755    */
00756   typedef numeric_limits<_FloatT> limits;
00757   char static_buf[limits::max_exponent10 + 6]; // 6: -xxx.yyyE-zzz (sign, dot, E, exp sign, \0)
00758   char fmtbuf[32];
00759   __fill_fmtbuf(fmtbuf, flags, modifier);
00760   snprintf(_STLP_ARRAY_AND_SIZE(static_buf), fmtbuf, precision, x);
00761   buf = static_buf;
00762   return find_if(buf.begin(), buf.end(), GroupPos()) - buf.begin();
00763 #else
00764                               ) {
00765   typedef numeric_limits<_FloatT> limits;
00766   //If numeric_limits support is correct we use the exposed values to detect NaN and infinity:
00767   if (limits::has_infinity && limits::has_quiet_NaN) {
00768     if (!(x == x) || // NaN check
00769         (x == limits::infinity() || x == -limits::infinity())) {
00770       return __format_nan_or_inf(buf, x, flags);
00771     }
00772   }
00773   // numeric_limits support is not good enough, we rely on platform dependent function
00774   // _Stl_is_nan_or_inf that do not support long double.
00775   else if (_Stl_is_nan_or_inf(x)) {
00776     return __format_nan_or_inf(buf, x, flags);
00777   }
00778 #  if defined (__MINGW32__)
00779   //For the moment MinGW is limited to display at most numeric_limits<double>::max()
00780   if (x > numeric_limits<double>::max() ||
00781       x < -numeric_limits<double>::max()) {
00782     return __format_nan_or_inf(buf, x, flags);
00783   }
00784 #  endif
00785 
00786   /* Buffer size is max number of digits which is the addition of:
00787    * - max_exponent10: max number of digits in fixed mode
00788    * - digits10 + 2: max number of significant digits
00789    * - trailing '\0'
00790    */
00791   char cvtbuf[limits::max_exponent10 + limits::digits10 + 2 + 1];
00792   char *bp;
00793   int decpt, sign;
00794 
00795   switch (flags & ios_base::floatfield) {
00796   case ios_base::fixed:
00797     {
00798       /* Here, number of digits represents digits _after_ decimal point.
00799        * In order to limit static buffer size we have to give 2 different values depending on x value. 
00800        * For small values (abs(x) < 1) we need as many digits as requested by precision limited by the maximum number of digits
00801        * which is min_exponent10 + digits10 + 2
00802        * For bigger values we won't have more than limits::digits10 + 2 digits after decimal point. */
00803       int digits10 = (x > -1.0 && x < 1.0 ? -limits::min_exponent10 + limits::digits10 + 2
00804                                           : limits::digits10 + 2);
00805       bp = _Stl_fcvtR(x, (min) (precision, digits10), &decpt, &sign, _STLP_CVT_BUFFER(cvtbuf) );
00806     }
00807     break;
00808   case ios_base::scientific:
00809   default:
00810     /* Here, number of digits is total number of digits which is limited to digits10 + 2. */
00811     {
00812       int digits10 = limits::digits10 + 2;
00813       bp = _Stl_ecvtR(x, (min) (precision, digits10), &decpt, &sign, _STLP_CVT_BUFFER(cvtbuf) );
00814     }
00815     break;
00816   }
00817   return __format_float(buf, bp, decpt, sign, x == 0.0, flags, precision);
00818 #endif
00819 }
00820 
00821 size_t  _STLP_CALL
00822 __write_float(__iostring &buf, ios_base::fmtflags flags, int precision,
00823               double x) {
00824   return __write_floatT(buf, flags, precision, x
00825 #if defined (USE_SPRINTF_INSTEAD)
00826                                                , 0
00827 #endif
00828                                                   );
00829 }
00830 
00831 #if !defined (_STLP_NO_LONG_DOUBLE)
00832 size_t _STLP_CALL
00833 __write_float(__iostring &buf, ios_base::fmtflags flags, int precision,
00834               long double x) {
00835   return __write_floatT(buf, flags, precision, x
00836 #if defined (USE_SPRINTF_INSTEAD)
00837                                                , 'L'
00838 #endif
00839                                                     );
00840 }
00841 #endif
00842 
00843 void _STLP_CALL __get_floor_digits(__iostring &out, _STLP_LONGEST_FLOAT_TYPE __x) {
00844   typedef numeric_limits<_STLP_LONGEST_FLOAT_TYPE> limits;
00845 #if defined (USE_SPRINTF_INSTEAD)
00846   char cvtbuf[limits::max_exponent10 + 6];
00847 #  if !defined (_STLP_NO_LONG_DOUBLE)
00848   snprintf(_STLP_ARRAY_AND_SIZE(cvtbuf), "%Lf", __x); // check for 1234.56!
00849 #  else
00850   snprintf(_STLP_ARRAY_AND_SIZE(cvtbuf), "%f", __x);  // check for 1234.56!
00851 #  endif
00852   char *p = strchr( cvtbuf, '.' );
00853   if ( p == 0 ) {
00854     out.append( cvtbuf );
00855   } else {
00856     out.append( cvtbuf, p );
00857   }
00858 #else
00859   char cvtbuf[limits::max_exponent10 + 1];
00860   char * bp;
00861   int decpt, sign;
00862   bp = _Stl_fcvtR(__x, 0, &decpt, &sign, _STLP_CVT_BUFFER(cvtbuf));
00863 
00864   if (sign) {
00865     out += '-';
00866   }
00867   out.append(bp, bp + decpt);
00868 #endif
00869 }
00870 
00871 
00872 #if !defined (_STLP_NO_WCHAR_T)
00873 void _STLP_CALL __convert_float_buffer( __iostring const& str, __iowstring &out,
00874                                         const ctype<wchar_t>& ct, wchar_t dot, bool __check_dot) {
00875   string::const_iterator str_ite(str.begin()), str_end(str.end());
00876 
00877   //First loop, check the dot char
00878   if (__check_dot) {
00879     while (str_ite != str_end) {
00880       if (*str_ite != '.') {
00881         out += ct.widen(*str_ite++);
00882       } else {
00883         out += dot;
00884         break;
00885       }
00886     }
00887   } else {
00888     if (str_ite != str_end) {
00889       out += ct.widen(*str_ite);
00890     }
00891   }
00892 
00893   if (str_ite != str_end) {
00894     //Second loop, dot has been found, no check anymore
00895     while (++str_ite != str_end) {
00896       out += ct.widen(*str_ite);
00897     }
00898   }
00899 }
00900 
00901 #endif
00902 
00903 void _STLP_CALL
00904 __adjust_float_buffer(__iostring &str, char dot) {
00905   if ('.' != dot) {
00906     size_t __dot_pos = str.find('.');
00907     if (__dot_pos != string::npos) {
00908       str[__dot_pos] = dot;
00909     }
00910   }
00911 }
00912 
00913 _STLP_MOVE_TO_STD_NAMESPACE
00914 _STLP_END_NAMESPACE
00915 
00916 // Local Variables:
00917 // mode:C++
00918 // End:

Generated on Sun May 27 2012 04:35:13 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.