Go to the documentation of this file.00001
00002
00003
00004
00005 #ifndef __FAST_ATOF_H_INCLUDED__
00006 #define __FAST_ATOF_H_INCLUDED__
00007
00008 #include "irrMath.h"
00009 #include "irrString.h"
00010
00011 namespace irr
00012 {
00013 namespace core
00014 {
00016
00017
00018 IRRLICHT_API extern irr::core::stringc LOCALE_DECIMAL_POINTS;
00019
00020 #define IRR_ATOF_TABLE_SIZE 17
00021
00022 const float fast_atof_table[17] = {
00023 0.f,
00024 0.1f,
00025 0.01f,
00026 0.001f,
00027 0.0001f,
00028 0.00001f,
00029 0.000001f,
00030 0.0000001f,
00031 0.00000001f,
00032 0.000000001f,
00033 0.0000000001f,
00034 0.00000000001f,
00035 0.000000000001f,
00036 0.0000000000001f,
00037 0.00000000000001f,
00038 0.000000000000001f,
00039 0.0000000000000001f
00040 };
00041
00043
00050 inline u32 strtoul10(const char* in, const char** out=0)
00051 {
00052 if (!in)
00053 {
00054 if (out)
00055 *out = in;
00056 return 0;
00057 }
00058
00059 bool overflow=false;
00060 u32 unsignedValue = 0;
00061 while ( ( *in >= '0') && ( *in <= '9' ))
00062 {
00063 const u32 tmp = ( unsignedValue * 10 ) + ( *in - '0' );
00064 if (tmp<unsignedValue)
00065 {
00066 unsignedValue=(u32)0xffffffff;
00067 overflow=true;
00068 }
00069 if (!overflow)
00070 unsignedValue = tmp;
00071 ++in;
00072 }
00073
00074 if (out)
00075 *out = in;
00076
00077 return unsignedValue;
00078 }
00079
00081
00090 inline s32 strtol10(const char* in, const char** out=0)
00091 {
00092 if (!in)
00093 {
00094 if (out)
00095 *out = in;
00096 return 0;
00097 }
00098
00099 const bool negative = ('-' == *in);
00100 if (negative || ('+' == *in))
00101 ++in;
00102
00103 const u32 unsignedValue = strtoul10(in,out);
00104 if (unsignedValue > (u32)INT_MAX)
00105 {
00106 if (negative)
00107 return (s32)INT_MIN;
00108 else
00109 return (s32)INT_MAX;
00110 }
00111 else
00112 {
00113 if (negative)
00114 return -((s32)unsignedValue);
00115 else
00116 return (s32)unsignedValue;
00117 }
00118 }
00119
00121
00126 inline u32 ctoul16(char in)
00127 {
00128 if (in >= '0' && in <= '9')
00129 return in - '0';
00130 else if (in >= 'a' && in <= 'f')
00131 return 10u + in - 'a';
00132 else if (in >= 'A' && in <= 'F')
00133 return 10u + in - 'A';
00134 else
00135 return 0xffffffff;
00136 }
00137
00139
00147 inline u32 strtoul16(const char* in, const char** out=0)
00148 {
00149 if (!in)
00150 {
00151 if (out)
00152 *out = in;
00153 return 0;
00154 }
00155
00156 bool overflow=false;
00157 u32 unsignedValue = 0;
00158 while (true)
00159 {
00160 u32 tmp = 0;
00161 if ((*in >= '0') && (*in <= '9'))
00162 tmp = (unsignedValue << 4u) + (*in - '0');
00163 else if ((*in >= 'A') && (*in <= 'F'))
00164 tmp = (unsignedValue << 4u) + (*in - 'A') + 10;
00165 else if ((*in >= 'a') && (*in <= 'f'))
00166 tmp = (unsignedValue << 4u) + (*in - 'a') + 10;
00167 else
00168 break;
00169 if (tmp<unsignedValue)
00170 {
00171 unsignedValue=(u32)INT_MAX;
00172 overflow=true;
00173 }
00174 if (!overflow)
00175 unsignedValue = tmp;
00176 ++in;
00177 }
00178
00179 if (out)
00180 *out = in;
00181
00182 return unsignedValue;
00183 }
00184
00186
00194 inline u32 strtoul8(const char* in, const char** out=0)
00195 {
00196 if (!in)
00197 {
00198 if (out)
00199 *out = in;
00200 return 0;
00201 }
00202
00203 bool overflow=false;
00204 u32 unsignedValue = 0;
00205 while (true)
00206 {
00207 u32 tmp = 0;
00208 if ((*in >= '0') && (*in <= '7'))
00209 tmp = (unsignedValue << 3u) + (*in - '0');
00210 else
00211 break;
00212 if (tmp<unsignedValue)
00213 {
00214 unsignedValue=(u32)INT_MAX;
00215 overflow=true;
00216 }
00217 if (!overflow)
00218 unsignedValue = tmp;
00219 ++in;
00220 }
00221
00222 if (out)
00223 *out = in;
00224
00225 return unsignedValue;
00226 }
00227
00229
00237 inline u32 strtoul_prefix(const char* in, const char** out=0)
00238 {
00239 if (!in)
00240 {
00241 if (out)
00242 *out = in;
00243 return 0;
00244 }
00245 if ('0'==in[0])
00246 return ('x'==in[1] ? strtoul16(in+2,out) : strtoul8(in+1,out));
00247 return strtoul10(in,out);
00248 }
00249
00251
00259 inline f32 strtof10(const char* in, const char** out = 0)
00260 {
00261 if (!in)
00262 {
00263 if (out)
00264 *out = in;
00265 return 0.f;
00266 }
00267
00268 const u32 MAX_SAFE_U32_VALUE = UINT_MAX / 10 - 10;
00269 u32 intValue = 0;
00270
00271
00272
00273 while ( ( *in >= '0') && ( *in <= '9' ) )
00274 {
00275
00276
00277 if (intValue >= MAX_SAFE_U32_VALUE)
00278 break;
00279
00280 intValue = (intValue * 10) + (*in - '0');
00281 ++in;
00282 }
00283
00284 f32 floatValue = (f32)intValue;
00285
00286
00287
00288 while ( ( *in >= '0') && ( *in <= '9' ) )
00289 {
00290 floatValue = (floatValue * 10.f) + (f32)(*in - '0');
00291 ++in;
00292 if (floatValue > FLT_MAX)
00293 break;
00294 }
00295
00296 if (out)
00297 *out = in;
00298
00299 return floatValue;
00300 }
00301
00303
00310 inline const char* fast_atof_move(const char* in, f32& result)
00311 {
00312
00313
00314 result = 0.f;
00315 if (!in)
00316 return 0;
00317
00318 const bool negative = ('-' == *in);
00319 if (negative || ('+'==*in))
00320 ++in;
00321
00322 f32 value = strtof10(in, &in);
00323
00324 if ( LOCALE_DECIMAL_POINTS.findFirst(*in) >= 0 )
00325 {
00326 const char* afterDecimal = ++in;
00327 f32 decimal = strtof10(in, &afterDecimal);
00328 size_t numDecimals = afterDecimal - in;
00329 if (numDecimals < IRR_ATOF_TABLE_SIZE)
00330 {
00331 value += decimal * fast_atof_table[numDecimals];
00332 }
00333 else
00334 {
00335 value += decimal * (f32)pow(10.f, -(float)numDecimals);
00336 }
00337 in = afterDecimal;
00338 }
00339
00340 if ('e' == *in || 'E' == *in)
00341 {
00342 ++in;
00343
00344
00345
00346
00347 value *= (f32)pow(10.f, (f32)strtol10(in, &in));
00348 }
00349
00350 result = negative?-value:value;
00351 return in;
00352 }
00353
00355
00360 inline float fast_atof(const char* floatAsString, const char** out=0)
00361 {
00362 float ret;
00363 if (out)
00364 *out=fast_atof_move(floatAsString, ret);
00365 else
00366 fast_atof_move(floatAsString, ret);
00367 return ret;
00368 }
00369
00370 }
00371 }
00372
00373 #endif
00374