Home | Namespaces | Hierarchy | Alphabetical List | Class list | Files | Namespace Members | Class members | File members | Tutorials

fast_atof.h

Go to the documentation of this file.
00001 // Copyright (C) 2002-2010 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_A_TO_F_H_INCLUDED__
00006 #define __FAST_A_TO_F_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 
00044 inline s32 strtol10(const char* in, const char** out=0)
00045 {
00046         if(!in)
00047                 return 0;
00048 
00049         bool negative = false;
00050         if('-' == *in)
00051         {
00052                 negative = true;
00053                 ++in;
00054         }
00055         else if('+' == *in)
00056                 ++in;
00057 
00058         u32 unsignedValue = 0;
00059 
00060         while ( ( *in >= '0') && ( *in <= '9' ))
00061         {
00062                 unsignedValue = ( unsignedValue * 10 ) + ( *in - '0' );
00063                 ++in;
00064 
00065                 if(unsignedValue > (u32)INT_MAX)
00066                 {
00067                         unsignedValue = (u32)INT_MAX;
00068                         break;
00069                 }
00070         }
00071         if (out)
00072                 *out = in;
00073 
00074         if(negative)
00075                 return -((s32)unsignedValue);
00076         else
00077                 return (s32)unsignedValue;
00078 }
00079 
00086 inline f32 strtof10(const char* in, const char * * out = 0)
00087 {
00088         if(out)
00089                 *out = in;
00090 
00091         if(!in)
00092                 return 0.f;
00093 
00094         static const u32 MAX_SAFE_U32_VALUE = UINT_MAX / 10 - 10;
00095         f32 floatValue = 0.f;
00096         u32 intValue = 0;
00097 
00098         // Use integer arithmetic for as long as possible, for speed
00099         // and precision.
00100         while ( ( *in >= '0') && ( *in <= '9' ) )
00101         {
00102                 // If it looks like we're going to overflow, bail out
00103                 // now and start using floating point.
00104                 if(intValue >= MAX_SAFE_U32_VALUE)
00105                         break;
00106 
00107                 intValue = ( intValue * 10) + ( *in - '0' );
00108                 ++in;
00109         }
00110 
00111         floatValue = (f32)intValue;
00112 
00113         // If there are any digits left to parse, then we need to use 
00114         // floating point arithmetic from here.
00115         while ( ( *in >= '0') && ( *in <= '9' ) )
00116         {
00117                 floatValue = ( floatValue * 10.f ) + (f32)( *in - '0' );
00118                 ++in;
00119                 if(floatValue > FLT_MAX) // Just give up.
00120                         break;
00121         }
00122 
00123         if(out)
00124                 *out = in;
00125 
00126         return floatValue;
00127 }
00128 
00136 inline const char* fast_atof_move( const char * in, f32 & out)
00137 {
00138         // Please run this regression test when making any modifications to this function:
00139         // https://sourceforge.net/tracker/download.php?group_id=74339&atid=540676&file_id=298968&aid=1865300
00140 
00141         out = 0.f;
00142         if(!in)
00143                 return 0;
00144 
00145         bool negative = false;
00146         if(*in == '-')
00147         {
00148                 negative = true;
00149                 ++in;
00150         }
00151 
00152         f32 value = strtof10 ( in, &in );
00153 
00154         if (*in == '.')
00155         {
00156                 ++in;
00157 
00158                 const char * afterDecimal = in;
00159                 f32 decimal = strtof10 ( in, &afterDecimal );
00160                 decimal *= fast_atof_table[afterDecimal - in];
00161 
00162                 value += decimal;
00163 
00164                 in = afterDecimal;
00165         }
00166 
00167         if ('e' == *in || 'E' == *in)
00168         {
00169                 ++in;
00170                 // Assume that the exponent is a whole number.
00171                 // strtol10() will deal with both + and - signs,
00172                 // but cast to (f32) to prevent overflow at FLT_MAX
00173                 value *= (f32)pow(10.0f, (f32)strtol10(in, &in));
00174         }
00175 
00176         if(negative)
00177                 out = -value;
00178         else
00179                 out = value;
00180 
00181         return in;
00182 }
00183 
00186 inline float fast_atof(const char* floatAsString)
00187 {
00188         float ret;
00189         fast_atof_move(floatAsString, ret);
00190         return ret;
00191 }
00192 
00193 } // end namespace core
00194 } // end namespace irr
00195 
00196 #endif
00197 

The Irrlicht Engine
The Irrlicht Engine Documentation © 2003-2010 by Nikolaus Gebhardt. Generated on Sun Oct 24 12:41:56 2010 by Doxygen (1.6.2)