Loading...
Searching...
No Matches
fast_atof.h
Go to the documentation of this file.
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine" and the "irrXML" project.
// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h
#ifndef __FAST_ATOF_H_INCLUDED__
#define __FAST_ATOF_H_INCLUDED__
#include "irrMath.h"
#include "irrString.h"
namespace irr
{
namespace core
{
// TODO: This should probably also be used in irr::core::string, but the float-to-string code
// used there has to be rewritten first.
IRRLICHT_API extern irr::core::stringc LOCALE_DECIMAL_POINTS;
#define IRR_ATOF_TABLE_SIZE 17
// we write [IRR_ATOF_TABLE_SIZE] here instead of [] to work around a swig bug
const float fast_atof_table[17] = {
0.f,
0.1f,
0.01f,
0.001f,
0.0001f,
0.00001f,
0.000001f,
0.0000001f,
0.00000001f,
0.000000001f,
0.0000000001f,
0.00000000001f,
0.000000000001f,
0.0000000000001f,
0.00000000000001f,
0.000000000000001f,
0.0000000000000001f
};
inline u32 strtoul10(const char* in, const char** out=0)
{
if (!in)
{
if (out)
*out = in;
return 0;
}
bool overflow=false;
u32 unsignedValue = 0;
while ( ( *in >= '0') && ( *in <= '9' ))
{
const u32 tmp = ( unsignedValue * 10 ) + ( *in - '0' );
if (tmp<unsignedValue)
{
unsignedValue=(u32)0xffffffff;
overflow=true;
}
if (!overflow)
unsignedValue = tmp;
++in;
}
if (out)
*out = in;
return unsignedValue;
}
inline s32 strtol10(const char* in, const char** out=0)
{
if (!in)
{
if (out)
*out = in;
return 0;
}
const bool negative = ('-' == *in);
if (negative || ('+' == *in))
++in;
const u32 unsignedValue = strtoul10(in,out);
if (unsignedValue > (u32)INT_MAX)
{
if (negative)
return (s32)INT_MIN;
else
return (s32)INT_MAX;
}
else
{
if (negative)
return -((s32)unsignedValue);
else
return (s32)unsignedValue;
}
}
inline u32 ctoul16(char in)
{
if (in >= '0' && in <= '9')
return in - '0';
else if (in >= 'a' && in <= 'f')
return 10u + in - 'a';
else if (in >= 'A' && in <= 'F')
return 10u + in - 'A';
else
return 0xffffffff;
}
inline u32 strtoul16(const char* in, const char** out=0)
{
if (!in)
{
if (out)
*out = in;
return 0;
}
bool overflow=false;
u32 unsignedValue = 0;
while (true)
{
u32 tmp = 0;
if ((*in >= '0') && (*in <= '9'))
tmp = (unsignedValue << 4u) + (*in - '0');
else if ((*in >= 'A') && (*in <= 'F'))
tmp = (unsignedValue << 4u) + (*in - 'A') + 10;
else if ((*in >= 'a') && (*in <= 'f'))
tmp = (unsignedValue << 4u) + (*in - 'a') + 10;
else
break;
if (tmp<unsignedValue)
{
unsignedValue=(u32)INT_MAX;
overflow=true;
}
if (!overflow)
unsignedValue = tmp;
++in;
}
if (out)
*out = in;
return unsignedValue;
}
inline u32 strtoul8(const char* in, const char** out=0)
{
if (!in)
{
if (out)
*out = in;
return 0;
}
bool overflow=false;
u32 unsignedValue = 0;
while (true)
{
u32 tmp = 0;
if ((*in >= '0') && (*in <= '7'))
tmp = (unsignedValue << 3u) + (*in - '0');
else
break;
if (tmp<unsignedValue)
{
unsignedValue=(u32)INT_MAX;
overflow=true;
}
if (!overflow)
unsignedValue = tmp;
++in;
}
if (out)
*out = in;
return unsignedValue;
}
inline u32 strtoul_prefix(const char* in, const char** out=0)
{
if (!in)
{
if (out)
*out = in;
return 0;
}
if ('0'==in[0])
return ('x'==in[1] ? strtoul16(in+2,out) : strtoul8(in+1,out));
return strtoul10(in,out);
}
inline f32 strtof10(const char* in, const char** out = 0)
{
if (!in)
{
if (out)
*out = in;
return 0.f;
}
const u32 MAX_SAFE_U32_VALUE = UINT_MAX / 10 - 10;
u32 intValue = 0;
// Use integer arithmetic for as long as possible, for speed
// and precision.
while ( ( *in >= '0') && ( *in <= '9' ) )
{
// If it looks like we're going to overflow, bail out
// now and start using floating point.
if (intValue >= MAX_SAFE_U32_VALUE)
break;
intValue = (intValue * 10) + (*in - '0');
++in;
}
f32 floatValue = (f32)intValue;
// If there are any digits left to parse, then we need to use
// floating point arithmetic from here.
while ( ( *in >= '0') && ( *in <= '9' ) )
{
floatValue = (floatValue * 10.f) + (f32)(*in - '0');
++in;
if (floatValue > FLT_MAX) // Just give up.
break;
}
if (out)
*out = in;
return floatValue;
}
inline const char* fast_atof_move(const char* in, f32& result)
{
// Please run the regression test when making any modifications to this function.
result = 0.f;
if (!in)
return 0;
const bool negative = ('-' == *in);
if (negative || ('+'==*in))
++in;
f32 value = strtof10(in, &in);
if ( LOCALE_DECIMAL_POINTS.findFirst(*in) >= 0 )
{
const char* afterDecimal = ++in;
f32 decimal = strtof10(in, &afterDecimal);
size_t numDecimals = afterDecimal - in;
if (numDecimals < IRR_ATOF_TABLE_SIZE)
{
value += decimal * fast_atof_table[numDecimals];
}
else
{
value += decimal * (f32)pow(10.f, -(float)numDecimals);
}
in = afterDecimal;
}
if ('e' == *in || 'E' == *in)
{
++in;
// Assume that the exponent is a whole number.
// strtol10() will deal with both + and - signs,
// but calculate as f32 to prevent overflow at FLT_MAX
// Using pow with float cast instead of powf as otherwise accuracy decreases.
value *= (f32)pow(10.f, (f32)strtol10(in, &in));
}
result = negative?-value:value;
return in;
}
inline float fast_atof(const char* floatAsString, const char** out=0)
{
float ret;
if (out)
*out=fast_atof_move(floatAsString, ret);
else
fast_atof_move(floatAsString, ret);
return ret;
}
} // end namespace core
} // end namespace irr
#endif
IRRLICHT_API
#define IRRLICHT_API
Set FPU settings.
Definition IrrCompileConfig.h:694
IRR_ATOF_TABLE_SIZE
#define IRR_ATOF_TABLE_SIZE
Definition fast_atof.h:20
irrMath.h
FLT_MAX
#define FLT_MAX
Definition irrMath.h:31
irrString.h
irr::core
Basic classes such as vectors, planes, arrays, lists, and so on can be found in this namespace.
Definition aabbox3d.h:15
irr::core::strtoul8
u32 strtoul8(const char *in, const char **out=0)
Convert a simple string of base 8 digits into an unsigned 32 bit integer.
Definition fast_atof.h:194
irr::core::strtof10
f32 strtof10(const char *in, const char **out=0)
Converts a sequence of digits into a whole positive floating point value.
Definition fast_atof.h:259
irr::core::fast_atof_move
const char * fast_atof_move(const char *in, f32 &result)
Provides a fast function for converting a string into a float.
Definition fast_atof.h:310
irr::core::strtol10
s32 strtol10(const char *in, const char **out=0)
Convert a simple string of base 10 digits into a signed 32 bit integer.
Definition fast_atof.h:90
irr::core::ctoul16
u32 ctoul16(char in)
Convert a hex-encoded character to an unsigned integer.
Definition fast_atof.h:126
irr::core::strtoul16
u32 strtoul16(const char *in, const char **out=0)
Convert a simple string of base 16 digits into an unsigned 32 bit integer.
Definition fast_atof.h:147
irr::core::LOCALE_DECIMAL_POINTS
IRRLICHT_API irr::core::stringc LOCALE_DECIMAL_POINTS
Selection of characters which count as decimal point in fast_atof.
irr::core::strtoul_prefix
u32 strtoul_prefix(const char *in, const char **out=0)
Convert a C-style prefixed string (hex, oct, integer) into an unsigned 32 bit integer.
Definition fast_atof.h:237
irr::core::stringc
string< c8 > stringc
Typedef for character strings.
Definition irrString.h:1358
irr::core::fast_atof_table
const float fast_atof_table[17]
Definition fast_atof.h:22
irr::core::strtoul10
u32 strtoul10(const char *in, const char **out=0)
Convert a simple string of base 10 digits into an unsigned 32 bit integer.
Definition fast_atof.h:50
irr::core::fast_atof
float fast_atof(const char *floatAsString, const char **out=0)
Convert a string to a floating point number.
Definition fast_atof.h:360
irr
Everything in the Irrlicht Engine can be found in this namespace.
Definition aabbox3d.h:13
irr::f32
float f32
32 bit floating point variable.
Definition irrTypes.h:104
irr::u32
unsigned int u32
32 bit unsigned variable.
Definition irrTypes.h:58
irr::s32
signed int s32
32 bit signed variable.
Definition irrTypes.h:66
- Irrlicht Engine Documentation © 2003-2012 by Nikolaus Gebhardt. Generated on for Irrlicht 3D Engine by Doxygen 1.15.0