|
IrrlichtEngine
|
00001 // Copyright (C) 2002-2011 Nikolaus Gebhardt 00002 // This file is part of the "Irrlicht Engine" and the "irrXML" project. 00003 // For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h 00004 00005 #ifndef __FAST_ATOF_H_INCLUDED__ 00006 #define __FAST_ATOF_H_INCLUDED__ 00007 00008 #include "irrMath.h" 00009 00010 namespace irr 00011 { 00012 namespace core 00013 { 00014 00015 // we write [17] here instead of [] to work around a swig bug 00016 const float fast_atof_table[17] = { 00017 0.f, 00018 0.1f, 00019 0.01f, 00020 0.001f, 00021 0.0001f, 00022 0.00001f, 00023 0.000001f, 00024 0.0000001f, 00025 0.00000001f, 00026 0.000000001f, 00027 0.0000000001f, 00028 0.00000000001f, 00029 0.000000000001f, 00030 0.0000000000001f, 00031 0.00000000000001f, 00032 0.000000000000001f, 00033 0.0000000000000001f 00034 }; 00035 00037 00044 inline u32 strtoul10(const char* in, const char** out=0) 00045 { 00046 if (!in) 00047 { 00048 if (out) 00049 *out = in; 00050 return 0; 00051 } 00052 00053 bool overflow=false; 00054 u32 unsignedValue = 0; 00055 while ( ( *in >= '0') && ( *in <= '9' )) 00056 { 00057 const u32 tmp = ( unsignedValue * 10 ) + ( *in - '0' ); 00058 if (tmp<unsignedValue) 00059 { 00060 unsignedValue=(u32)0xffffffff; 00061 overflow=true; 00062 } 00063 if (!overflow) 00064 unsignedValue = tmp; 00065 ++in; 00066 } 00067 00068 if (out) 00069 *out = in; 00070 00071 return unsignedValue; 00072 } 00073 00075 00084 inline s32 strtol10(const char* in, const char** out=0) 00085 { 00086 if (!in) 00087 { 00088 if (out) 00089 *out = in; 00090 return 0; 00091 } 00092 00093 const bool negative = ('-' == *in); 00094 if (negative || ('+' == *in)) 00095 ++in; 00096 00097 const u32 unsignedValue = strtoul10(in,out); 00098 if (unsignedValue > (u32)INT_MAX) 00099 { 00100 if (negative) 00101 return (s32)INT_MIN; 00102 else 00103 return (s32)INT_MAX; 00104 } 00105 else 00106 { 00107 if (negative) 00108 return -((s32)unsignedValue); 00109 else 00110 return (s32)unsignedValue; 00111 } 00112 } 00113 00115 00120 inline u32 ctoul16(char in) 00121 { 00122 if (in >= '0' && in <= '9') 00123 return in - '0'; 00124 else if (in >= 'a' && in <= 'f') 00125 return 10u + in - 'a'; 00126 else if (in >= 'A' && in <= 'F') 00127 return 10u + in - 'A'; 00128 else 00129 return 0xffffffff; 00130 } 00131 00133 00141 inline u32 strtoul16(const char* in, const char** out=0) 00142 { 00143 if (!in) 00144 { 00145 if (out) 00146 *out = in; 00147 return 0; 00148 } 00149 00150 bool overflow=false; 00151 u32 unsignedValue = 0; 00152 while (true) 00153 { 00154 u32 tmp = 0; 00155 if ((*in >= '0') && (*in <= '9')) 00156 tmp = (unsignedValue << 4u) + (*in - '0'); 00157 else if ((*in >= 'A') && (*in <= 'F')) 00158 tmp = (unsignedValue << 4u) + (*in - 'A') + 10; 00159 else if ((*in >= 'a') && (*in <= 'f')) 00160 tmp = (unsignedValue << 4u) + (*in - 'a') + 10; 00161 else 00162 break; 00163 if (tmp<unsignedValue) 00164 { 00165 unsignedValue=(u32)INT_MAX; 00166 overflow=true; 00167 } 00168 if (!overflow) 00169 unsignedValue = tmp; 00170 ++in; 00171 } 00172 00173 if (out) 00174 *out = in; 00175 00176 return unsignedValue; 00177 } 00178 00180 00188 inline u32 strtoul8(const char* in, const char** out=0) 00189 { 00190 if (!in) 00191 { 00192 if (out) 00193 *out = in; 00194 return 0; 00195 } 00196 00197 bool overflow=false; 00198 u32 unsignedValue = 0; 00199 while (true) 00200 { 00201 u32 tmp = 0; 00202 if ((*in >= '0') && (*in <= '7')) 00203 tmp = (unsignedValue << 3u) + (*in - '0'); 00204 else 00205 break; 00206 if (tmp<unsignedValue) 00207 { 00208 unsignedValue=(u32)INT_MAX; 00209 overflow=true; 00210 } 00211 if (!overflow) 00212 unsignedValue = tmp; 00213 ++in; 00214 } 00215 00216 if (out) 00217 *out = in; 00218 00219 return unsignedValue; 00220 } 00221 00223 00231 inline u32 strtoul_prefix(const char* in, const char** out=0) 00232 { 00233 if (!in) 00234 { 00235 if (out) 00236 *out = in; 00237 return 0; 00238 } 00239 if ('0'==in[0]) 00240 return ('x'==in[1] ? strtoul16(in+2,out) : strtoul8(in+1,out)); 00241 return strtoul10(in,out); 00242 } 00243 00245 00253 inline f32 strtof10(const char* in, const char** out = 0) 00254 { 00255 if (!in) 00256 { 00257 if (out) 00258 *out = in; 00259 return 0.f; 00260 } 00261 00262 const u32 MAX_SAFE_U32_VALUE = UINT_MAX / 10 - 10; 00263 u32 intValue = 0; 00264 00265 // Use integer arithmetic for as long as possible, for speed 00266 // and precision. 00267 while ( ( *in >= '0') && ( *in <= '9' ) ) 00268 { 00269 // If it looks like we're going to overflow, bail out 00270 // now and start using floating point. 00271 if (intValue >= MAX_SAFE_U32_VALUE) 00272 break; 00273 00274 intValue = (intValue * 10) + (*in - '0'); 00275 ++in; 00276 } 00277 00278 f32 floatValue = (f32)intValue; 00279 00280 // If there are any digits left to parse, then we need to use 00281 // floating point arithmetic from here. 00282 while ( ( *in >= '0') && ( *in <= '9' ) ) 00283 { 00284 floatValue = (floatValue * 10.f) + (f32)(*in - '0'); 00285 ++in; 00286 if (floatValue > FLT_MAX) // Just give up. 00287 break; 00288 } 00289 00290 if (out) 00291 *out = in; 00292 00293 return floatValue; 00294 } 00295 00297 00304 inline const char* fast_atof_move(const char* in, f32& result) 00305 { 00306 // Please run this regression test when making any modifications to this function: 00307 // https://sourceforge.net/tracker/download.php?group_id=74339&atid=540676&file_id=298968&aid=1865300 00308 00309 result = 0.f; 00310 if (!in) 00311 return 0; 00312 00313 const bool negative = ('-' == *in); 00314 if (negative || ('+'==*in)) 00315 ++in; 00316 00317 f32 value = strtof10(in, &in); 00318 00319 if ('.' == *in) 00320 { 00321 const char* afterDecimal = ++in; 00322 const f32 decimal = strtof10(in, &afterDecimal); 00323 value += decimal * fast_atof_table[afterDecimal - in]; 00324 in = afterDecimal; 00325 } 00326 00327 if ('e' == *in || 'E' == *in) 00328 { 00329 ++in; 00330 // Assume that the exponent is a whole number. 00331 // strtol10() will deal with both + and - signs, 00332 // but calculate as f32 to prevent overflow at FLT_MAX 00333 value *= powf(10.f, (f32)strtol10(in, &in)); 00334 } 00335 00336 result = negative?-value:value; 00337 return in; 00338 } 00339 00341 00346 inline float fast_atof(const char* floatAsString, const char** out=0) 00347 { 00348 float ret; 00349 if (out) 00350 *out=fast_atof_move(floatAsString, ret); 00351 else 00352 fast_atof_move(floatAsString, ret); 00353 return ret; 00354 } 00355 00356 } // end namespace core 00357 } // end namespace irr 00358 00359 #endif 00360