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 
00021 const float fast_atof_table[17] = {
00022     0.f,
00023     0.1f,
00024     0.01f,
00025     0.001f,
00026     0.0001f,
00027     0.00001f,
00028     0.000001f,
00029     0.0000001f,
00030     0.00000001f,
00031     0.000000001f,
00032     0.0000000001f,
00033     0.00000000001f,
00034     0.000000000001f,
00035     0.0000000000001f,
00036     0.00000000000001f,
00037     0.000000000000001f,
00038     0.0000000000000001f
00039 };
00040 
00042 
00049 inline u32 strtoul10(const char* in, const char** out=0)
00050 {
00051     if (!in)
00052     {
00053         if (out)
00054             *out = in;
00055         return 0;
00056     }
00057 
00058     bool overflow=false;
00059     u32 unsignedValue = 0;
00060     while ( ( *in >= '0') && ( *in <= '9' ))
00061     {
00062         const u32 tmp = ( unsignedValue * 10 ) + ( *in - '0' );
00063         if (tmp<unsignedValue)
00064         {
00065             unsignedValue=(u32)0xffffffff;
00066             overflow=true;
00067         }
00068         if (!overflow)
00069             unsignedValue = tmp;
00070         ++in;
00071     }
00072 
00073     if (out)
00074         *out = in;
00075 
00076     return unsignedValue;
00077 }
00078 
00080 
00089 inline s32 strtol10(const char* in, const char** out=0)
00090 {
00091     if (!in)
00092     {
00093         if (out)
00094             *out = in;
00095         return 0;
00096     }
00097 
00098     const bool negative = ('-' == *in);
00099     if (negative || ('+' == *in))
00100         ++in;
00101 
00102     const u32 unsignedValue = strtoul10(in,out);
00103     if (unsignedValue > (u32)INT_MAX)
00104     {
00105         if (negative)
00106             return (s32)INT_MIN;
00107         else
00108             return (s32)INT_MAX;
00109     }
00110     else
00111     {
00112         if (negative)
00113             return -((s32)unsignedValue);
00114         else
00115             return (s32)unsignedValue;
00116     }
00117 }
00118 
00120 
00125 inline u32 ctoul16(char in)
00126 {
00127     if (in >= '0' && in <= '9')
00128         return in - '0';
00129     else if (in >= 'a' && in <= 'f')
00130         return 10u + in - 'a';
00131     else if (in >= 'A' && in <= 'F')
00132         return 10u + in - 'A';
00133     else
00134         return 0xffffffff;
00135 }
00136 
00138 
00146 inline u32 strtoul16(const char* in, const char** out=0)
00147 {
00148     if (!in)
00149     {
00150         if (out)
00151             *out = in;
00152         return 0;
00153     }
00154 
00155     bool overflow=false;
00156     u32 unsignedValue = 0;
00157     while (true)
00158     {
00159         u32 tmp = 0;
00160         if ((*in >= '0') && (*in <= '9'))
00161             tmp = (unsignedValue << 4u) + (*in - '0');
00162         else if ((*in >= 'A') && (*in <= 'F'))
00163             tmp = (unsignedValue << 4u) + (*in - 'A') + 10;
00164         else if ((*in >= 'a') && (*in <= 'f'))
00165             tmp = (unsignedValue << 4u) + (*in - 'a') + 10;
00166         else
00167             break;
00168         if (tmp<unsignedValue)
00169         {
00170             unsignedValue=(u32)INT_MAX;
00171             overflow=true;
00172         }
00173         if (!overflow)
00174             unsignedValue = tmp;
00175         ++in;
00176     }
00177 
00178     if (out)
00179         *out = in;
00180 
00181     return unsignedValue;
00182 }
00183 
00185 
00193 inline u32 strtoul8(const char* in, const char** out=0)
00194 {
00195     if (!in)
00196     {
00197         if (out)
00198             *out = in;
00199         return 0;
00200     }
00201 
00202     bool overflow=false;
00203     u32 unsignedValue = 0;
00204     while (true)
00205     {
00206         u32 tmp = 0;
00207         if ((*in >= '0') && (*in <= '7'))
00208             tmp = (unsignedValue << 3u) + (*in - '0');
00209         else
00210             break;
00211         if (tmp<unsignedValue)
00212         {
00213             unsignedValue=(u32)INT_MAX;
00214             overflow=true;
00215         }
00216         if (!overflow)
00217             unsignedValue = tmp;
00218         ++in;
00219     }
00220 
00221     if (out)
00222         *out = in;
00223 
00224     return unsignedValue;
00225 }
00226 
00228 
00236 inline u32 strtoul_prefix(const char* in, const char** out=0)
00237 {
00238     if (!in)
00239     {
00240         if (out)
00241             *out = in;
00242         return 0;
00243     }
00244     if ('0'==in[0])
00245         return ('x'==in[1] ? strtoul16(in+2,out) : strtoul8(in+1,out));
00246     return strtoul10(in,out);
00247 }
00248 
00250 
00258 inline f32 strtof10(const char* in, const char** out = 0)
00259 {
00260     if (!in)
00261     {
00262         if (out)
00263             *out = in;
00264         return 0.f;
00265     }
00266 
00267     const u32 MAX_SAFE_U32_VALUE = UINT_MAX / 10 - 10;
00268     u32 intValue = 0;
00269 
00270     
00271     
00272     while ( ( *in >= '0') && ( *in <= '9' ) )
00273     {
00274         
00275         
00276         if (intValue >= MAX_SAFE_U32_VALUE)
00277             break;
00278 
00279         intValue = (intValue * 10) + (*in - '0');
00280         ++in;
00281     }
00282 
00283     f32 floatValue = (f32)intValue;
00284 
00285     
00286     
00287     while ( ( *in >= '0') && ( *in <= '9' ) )
00288     {
00289         floatValue = (floatValue * 10.f) + (f32)(*in - '0');
00290         ++in;
00291         if (floatValue > FLT_MAX) 
00292             break;
00293     }
00294 
00295     if (out)
00296         *out = in;
00297 
00298     return floatValue;
00299 }
00300 
00302 
00309 inline const char* fast_atof_move(const char* in, f32& result)
00310 {
00311     
00312 
00313     result = 0.f;
00314     if (!in)
00315         return 0;
00316 
00317     const bool negative = ('-' == *in);
00318     if (negative || ('+'==*in))
00319         ++in;
00320 
00321     f32 value = strtof10(in, &in);
00322 
00323     if ( LOCALE_DECIMAL_POINTS.findFirst(*in) >= 0 )
00324     {
00325         const char* afterDecimal = ++in;
00326         const f32 decimal = strtof10(in, &afterDecimal);
00327         value += decimal * fast_atof_table[afterDecimal - in];
00328         in = afterDecimal;
00329     }
00330 
00331     if ('e' == *in || 'E' == *in)
00332     {
00333         ++in;
00334         
00335         
00336         
00337         value *= powf(10.f, (f32)strtol10(in, &in));
00338     }
00339 
00340     result = negative?-value:value;
00341     return in;
00342 }
00343 
00345 
00350 inline float fast_atof(const char* floatAsString, const char** out=0)
00351 {
00352     float ret;
00353     if (out)
00354         *out=fast_atof_move(floatAsString, ret);
00355     else
00356         fast_atof_move(floatAsString, ret);
00357     return ret;
00358 }
00359 
00360 } 
00361 } 
00362 
00363 #endif
00364