diff -up irrlicht18-svn3629/examples/22.MaterialViewer/main.cpp.fastatof irrlicht18-svn3629/examples/22.MaterialViewer/main.cpp --- irrlicht18-svn3629/examples/22.MaterialViewer/main.cpp.fastatof 2010-02-02 14:53:57.341250000 -0600 +++ irrlicht18-svn3629/examples/22.MaterialViewer/main.cpp 2012-08-23 14:00:46.917580700 -0500 @@ -230,7 +230,7 @@ protected: u32 alpha=col.getAlpha(); if ( EditAlpha ) { - alpha = (u32)core::strtol10( core::stringc( EditAlpha->getText() ).c_str(), 0); + alpha = (u32)core::strtoul10( core::stringc( EditAlpha->getText() ).c_str(), 0); if ( alpha > 255 ) alpha = 255; } @@ -239,7 +239,7 @@ protected: u32 red=col.getRed(); if ( EditRed ) { - red = (u32)core::strtol10( core::stringc( EditRed->getText() ).c_str(), 0); + red = (u32)core::strtoul10( core::stringc( EditRed->getText() ).c_str(), 0); if ( red > 255 ) red = 255; } @@ -248,7 +248,7 @@ protected: u32 green=col.getGreen(); if ( EditGreen ) { - green = (u32)core::strtol10( core::stringc( EditGreen->getText() ).c_str(), 0); + green = (u32)core::strtoul10( core::stringc( EditGreen->getText() ).c_str(), 0); if ( green > 255 ) green = 255; } @@ -257,7 +257,7 @@ protected: u32 blue=col.getBlue(); if ( EditBlue ) { - blue = (u32)core::strtol10( core::stringc( EditBlue->getText() ).c_str(), 0); + blue = (u32)core::strtoul10( core::stringc( EditBlue->getText() ).c_str(), 0); if ( blue > 255 ) blue = 255; } diff -up irrlicht18-svn3629/include/fast_atof.h.fastatof irrlicht18-svn3629/include/fast_atof.h --- irrlicht18-svn3629/include/fast_atof.h.fastatof 2011-01-14 07:24:40.897355000 -0600 +++ irrlicht18-svn3629/include/fast_atof.h 2012-08-23 14:00:46.918580700 -0500 @@ -12,8 +12,8 @@ namespace irr namespace core { -// we write [17] here instead of [] to work around a swig bug -const float fast_atof_table[17] = { +// we write [16] here instead of [] to work around a swig bug +const float fast_atof_table[16] = { 0.f, 0.1f, 0.01f, @@ -30,9 +30,32 @@ const float fast_atof_table[17] = { 0.0000000000001f, 0.00000000000001f, 0.000000000000001f, - 0.0000000000000001f }; +//! Convert a simple string of base 10 digits into an unsigned 32 bit integer. +//! \param[in] in: The string of digits to convert. Only a leading - or + followed +//! by digits 0 to 9 will be considered. Parsing stops at the +//! first non-digit. +//! \param[out] out: (optional) If provided, it will be set to point at the first +//! character not used in the calculation. +//! \return The unsigned integer value of the digits. +inline u32 strtoul10(const char* in, const char** out=0) +{ + unsigned int value = 0; + + bool running = true; + while ( running ) + { + if ( *in < '0' || *in > '9' ) + break; + + value = ( value * 10 ) + ( *in - '0' ); + ++in; + } + if (out)*out = in; + return value; +} + //! Convert a simple string of base 10 digits into a signed 32 bit integer. //! \param[in] in: The string of digits to convert. Only a leading - or + followed //! by digits 0 to 9 will be considered. Parsing stops at the @@ -43,38 +66,104 @@ const float fast_atof_table[17] = { //! digits to encode in an s32 then +INT_MAX or -INT_MAX will be returned. inline s32 strtol10(const char* in, const char** out=0) { - if(!in) - return 0; - - bool negative = false; - if('-' == *in) - { - negative = true; + bool inv = (*in=='-'); + if (inv || *in=='+') ++in; + + int value = strtoul10(in,out); + if (inv) { + value = -value; } - else if('+' == *in) - ++in; + return value; +} - u32 unsignedValue = 0; +//! Convert a simple string of base 8 (octal) digits into an unsigned 32 bit integer. +//! \param[in] in: The string of digits to convert. Only digits 0 to 7 will be considered. +//! Parsing stops at the first non-digit. +//! \param[out] out: (optional) If provided, it will be set to point at the first +//! character not used in the calculation. +//! \return The unsigned integer value of the digits. +inline u32 strtoul8(const char* in, const char** out=0) +{ + unsigned int value = 0; - while ( ( *in >= '0') && ( *in <= '9' )) + bool running = true; + while ( running ) { - unsignedValue = ( unsignedValue * 10 ) + ( *in - '0' ); + if ( *in < '0' || *in > '7' ) + break; + + value = ( value << 3 ) + ( *in - '0' ); ++in; + } + if (out)*out = in; + return value; +} - if(unsignedValue > (u32)INT_MAX) +//! Convert a simple string of base 16 (hex) digits into an unsigned 32 bit integer. +//! \param[in] in: The string of digits to convert. Only digits 0 to 9, A to F will be considered. +//! Parsing stops at the first non-digit. Letters can be in either case. +//! \param[out] out: (optional) If provided, it will be set to point at the first +//! character not used in the calculation. +//! \return The unsigned integer value of the digits. +inline u32 strtoul16( const char* in, const char** out=0) +{ + unsigned int value = 0; + + bool running = true; + while ( running ) + { + if ( *in >= '0' && *in <= '9' ) { - unsignedValue = (u32)INT_MAX; - break; + value = ( value << 4u ) + ( *in - '0' ); } + else if (*in >= 'A' && *in <= 'F') + { + value = ( value << 4u ) + ( *in - 'A' ) + 10; + } + else if (*in >= 'a' && *in <= 'f') + { + value = ( value << 4u ) + ( *in - 'a' ) + 10; + } + else break; + ++in; } if (out) *out = in; + return value; +} - if(negative) - return -((s32)unsignedValue); - else - return (s32)unsignedValue; +//! Convert a hex-encoded digi (1 character) to an 8 bit unsigned integer. +//! \param[in] in: The string of digits to convert. Only digits 0 to 9, A to F will be considered. +//! Parsing stops at the first non-digit. Letters can be in either case. +//! \param[out] out: (optional) If provided, it will be set to point at the first +//! character not used in the calculation. +//! \return The unsigned integer value of the digits. 0xffffffff if the input is not hex +inline u32 HexDigitToDecimal(char in) +{ + unsigned int out = 0xffffffff; + if (in >= '0' && in <= '9') + out = in - '0'; + + else if (in >= 'a' && in <= 'f') + out = 10u + in - 'a'; + + else if (in >= 'A' && in <= 'F') + out = 10u + in - 'A'; + + // return value is 0xffffffff if the input is not a hex digit + return out; +} + +//! Convert a hex-encoded octet (2 characters) to an 8 bit unsigned integer. +//! \param[in] in: The string of digits to convert. Only digits 0 to 9, A to F will be considered. +//! Parsing stops at the first non-digit. Letters can be in either case. +//! \param[out] out: (optional) If provided, it will be set to point at the first +//! character not used in the calculation. +//! \return The unsigned integer value of the digits. 0xffffffff if the input is not hex +inline u8 HexOctetToDecimal(const char* in) +{ + return ((u8)HexDigitToDecimal(in[0])<<4)+(u8)HexDigitToDecimal(in[1]); } //! Converts a sequence of digits into a whole positive floating point value. @@ -126,6 +215,56 @@ inline f32 strtof10(const char* in, cons return floatValue; } +//! Convert a simple string of base 10 digits into an unsigned 64 bit integer. +//! \param[in] in: The string of digits to convert. Only a leading - or + followed +//! by digits 0 to 9 will be considered. Parsing stops at the +//! first non-digit. +//! \param[out] out: (optional) If provided, it will be set to point at the first +//! character not used in the calculation. +//! \return The unsigned 64 bit integer value of the digits. +inline u64 strtoul10_64( const char* in, const char** out=0, unsigned int* max_inout=0) +{ + unsigned int cur = 0; + u64 value = 0; + + bool running = true; + while ( running ) + { + if ( *in < '0' || *in > '9' ) + break; + + const u64 new_value = ( value * 10 ) + ( *in - '0' ); + + if (new_value < value) /* numeric overflow, we rely on you */ + return value; + + value = new_value; + + ++in; + ++cur; + + if (max_inout && *max_inout == cur) { + + if (out) { /* skip to end */ + while (*in >= '0' && *in <= '9') + ++in; + *out = in; + } + + return value; + } + } + if (out) + *out = in; + + if (max_inout) + *max_inout = cur; + + return value; +} +// Number of relevant decimals for floating-point parsing. +#define AI_FAST_ATOF_RELAVANT_DECIMALS 10 + //! Provides a fast function for converting a string into a float. //! This is not guaranteed to be as accurate as atof(), but is //! approximately 6 to 8 times as fast. @@ -138,46 +277,51 @@ inline const char* fast_atof_move( const // Please run this regression test when making any modifications to this function: // https://sourceforge.net/tracker/download.php?group_id=74339&atid=540676&file_id=298968&aid=1865300 - out = 0.f; - if(!in) - return 0; + float f; - bool negative = false; - if(*in == '-') - { - negative = true; + bool inv = (*in=='-'); + if (inv || *in=='+') ++in; - } - - f32 value = strtof10 ( in, &in ); - if (*in == '.') + f = (float) strtoul10_64 ( in, &in); + if (*in == '.' || (in[0] == ',' && (in[1] >= '0' || in[1] <= '9'))) // allow for commas, too { ++in; - const char * afterDecimal = in; - f32 decimal = strtof10 ( in, &afterDecimal ); - decimal *= fast_atof_table[afterDecimal - in]; - - value += decimal; + // NOTE: The original implementation is highly unaccurate here. The precision of a single + // IEEE 754 float is not high enough, everything behind the 6th digit tends to be more + // inaccurate than it would need to be. Casting to double seems to solve the problem. + // strtol_64 is used to prevent integer overflow. + + // Another fix: this tends to become 0 for long numbers if we don't limit the maximum + // number of digits to be read. AI_FAST_ATOF_RELAVANT_DECIMALS can be a value between + // 1 and 15. + unsigned int diff = AI_FAST_ATOF_RELAVANT_DECIMALS; + double pl = (double) strtoul10_64 ( in, &in, &diff ); - in = afterDecimal; + pl *= fast_atof_table[diff]; + f += (float)pl; } - if ('e' == *in || 'E' == *in) + // A major 'E' must be allowed. Necessary for proper reading of some DXF files. + // Thanks to Zhao Lei to point out that this if() must be outside the if (*c == '.' ..) + if (*in == 'e' || *in == 'E') { ++in; - // Assume that the exponent is a whole number. - // strtol10() will deal with both + and - signs, - // but cast to (f32) to prevent overflow at FLT_MAX - value *= (f32)pow(10.0f, (f32)strtol10(in, &in)); - } - - if(negative) - out = -value; - else - out = value; + bool einv = (*in=='-'); + if (einv || *in=='+') + ++in; + + float exp = (float)strtoul10_64(in, &in); + if (einv) + exp *= -1.0f; + f *= pow(10.0f, exp); + } + if (inv) + f *= -1.0f; + + out = f; return in; } @@ -190,6 +334,47 @@ inline float fast_atof(const char* float return ret; } +//! Convert a string to a floating point number +//! \param c: The string to convert. +//! \param cout: A pointer to the first character in the string that wasn't +//! use to create the float value. +inline float fast_atof( const char* c, const char** cout) +{ + float ret; + *cout = fast_atof_move(c, ret); + + return ret; +} + +//! Convert a string to a floating point number +//! \param inout: The string to convert, returned +//! as the pointer to the first character +//! in the string that wasn't +//! use to create the float value. +inline float fast_atof( const char** inout) +{ + float ret; + *inout = fast_atof_move(*inout, ret); + + return ret; +} + +//! Parse a C++-like integer literal - hex and oct prefixes - to an unsigned int +//! 0xNNNN - hex +//! 0NNN - oct +//! NNN - dec +//! \param[in] in: The string to convert. +//! \param cout: A pointer to the first character in the string that wasn't +//! use to create the float value. +inline u32 strtoul_cppstyle( const char* in, const char** out=0) +{ + if ('0' == in[0]) + { + return 'x' == in[1] ? strtoul16(in+2,out) : strtoul8(in+1,out); + } + return strtoul10(in, out); +} + } // end namespace core } // end namespace irr diff -up irrlicht18-svn3629/include/irrTypes.h.fastatof irrlicht18-svn3629/include/irrTypes.h --- irrlicht18-svn3629/include/irrTypes.h.fastatof 2011-01-14 07:24:40.897355000 -0600 +++ irrlicht18-svn3629/include/irrTypes.h 2012-08-23 14:00:46.919580700 -0500 @@ -6,10 +6,25 @@ #define __IRR_TYPES_H_INCLUDED__ #include "IrrCompileConfig.h" +#include namespace irr { +#ifdef _LONGLONG +#define NATIVE64 +#elif !((4294967290UL+7UL) == ((4294967290UL+7UL)&ULONG_MAX)) +#undef NATIVE64 +#elif !(((1UL << 31) * 2UL) != 0UL) +#undef NATIVE64 +#elif !((((1UL << 31) * 2UL)&ULONG_MAX) != 0UL) +#undef NATIVE64 +#elif !(ULONG_MAX > 4294967295UL) +#undef NATIVE64 +#else +#define NATIVE64 +#endif + //! 8 bit unsigned variable. /** This is a typedef for unsigned char, it ensures portability of the engine. */ #ifdef _MSC_VER @@ -36,16 +51,20 @@ typedef char c8; /** This is a typedef for unsigned short, it ensures portability of the engine. */ #ifdef _MSC_VER typedef unsigned __int16 u16; -#else +#elif UINT_MAX >= 4294967295UL typedef unsigned short u16; +#else +typedef unsigned int u16; #endif //! 16 bit signed variable. /** This is a typedef for signed short, it ensures portability of the engine. */ #ifdef _MSC_VER typedef __int16 s16; -#else +#elif UINT_MAX >= 4294967295UL typedef signed short s16; +#else +typedef signed int s16; #endif @@ -54,27 +73,42 @@ typedef signed short s16; /** This is a typedef for unsigned int, it ensures portability of the engine. */ #ifdef _MSC_VER typedef unsigned __int32 u32; -#else +#elif UINT_MAX >= 4294967295UL typedef unsigned int u32; +#else +typedef unsigned long u32; #endif //! 32 bit signed variable. /** This is a typedef for signed int, it ensures portability of the engine. */ #ifdef _MSC_VER typedef __int32 s32; -#else +#elif UINT_MAX >= 4294967295UL typedef signed int s32; +#else +typedef signed long s32; #endif +//! 64 bit unsigned variable. +/** This is a typedef for unsigned long, it ensures portability of the engine */ +#ifdef _MSC_VER +typedef unsigned __int64 u64; +#elif defined( NATIVE64 ) +typedef unsigned long u64; +#else /** Not NATIVE64 or Windows */ +typedef unsigned long long u64; +#endif -// 64 bit signed variable. -// This is a typedef for __int64, it ensures portability of the engine. -// This type is currently not used by the engine and not supported by compilers -// other than Microsoft Compilers, so it is outcommented. -//typedef __int64 s64; - - +//! 64 bit signed variable. +/** This is a typedef for signed long, it ensures portability of the engine. */ +#ifdef _MSC_VER +typedef __int64 s64; +#elif defined ( NATIVE64 ) +typedef signed long s64; +#else /** Not NATIVE64 or Windows */ +typedef signed long long s64; +#endif //! 32 bit floating point variable. /** This is a typedef for float, it ensures portability of the engine. */ diff -up irrlicht18-svn3629/source/Irrlicht/CImageLoaderPPM.cpp.fastatof irrlicht18-svn3629/source/Irrlicht/CImageLoaderPPM.cpp --- irrlicht18-svn3629/source/Irrlicht/CImageLoaderPPM.cpp.fastatof 2011-01-14 07:24:40.897355000 -0600 +++ irrlicht18-svn3629/source/Irrlicht/CImageLoaderPPM.cpp 2012-08-23 14:00:46.919580700 -0500 @@ -64,10 +64,10 @@ IImage* CImageLoaderPPM::loadImage(io::I core::stringc token; getNextToken(file, token); - const u32 width = core::strtol10(token.c_str()); + const u32 width = core::strtoul10(token.c_str()); getNextToken(file, token); - const u32 height = core::strtol10(token.c_str()); + const u32 height = core::strtoul10(token.c_str()); u8* data = 0; const u32 size = width*height; @@ -106,7 +106,7 @@ IImage* CImageLoaderPPM::loadImage(io::I else { getNextToken(file, token); - const u32 maxDepth = core::strtol10(token.c_str()); + const u32 maxDepth = core::strtoul10(token.c_str()); if (maxDepth > 255) // no double bytes yet return 0; @@ -144,7 +144,7 @@ IImage* CImageLoaderPPM::loadImage(io::I for (u32 i=0; iValue.c_str()); - return core::strtol10(c.c_str()); + return core::strtoul10(c.c_str()); } @@ -156,7 +156,7 @@ public: return 0; core::stringc c(attrvalue); - return core::strtol10(c.c_str()); + return core::strtoul10(c.c_str()); } diff -up irrlicht18-svn3629/source/Irrlicht/dmfsupport.h.fastatof irrlicht18-svn3629/source/Irrlicht/dmfsupport.h --- irrlicht18-svn3629/source/Irrlicht/dmfsupport.h.fastatof 2011-01-14 07:24:40.897355000 -0600 +++ irrlicht18-svn3629/source/Irrlicht/dmfsupport.h 2012-08-23 14:00:46.923580700 -0500 @@ -330,7 +330,7 @@ bool GetDMFMaterials(const StringList& R materials[i].pathName.replace('\\','/'); materials[i].pathName += "/"; // temp[3] is reserved, temp[4] is the number of texture layers - materials[i].textureLayers = core::strtol10(temp[4].c_str()); + materials[i].textureLayers = core::strtoul10(temp[4].c_str()); // Three values are separated by commas temp1=SubdivideString(temp[5],","); @@ -449,7 +449,7 @@ bool GetDMFVerticesFaces(const StringLis offs++; // load vertices core::array pos; - const u32 posCount = core::strtol10(RawFile[offs].c_str()); + const u32 posCount = core::strtoul10(RawFile[offs].c_str()); ++offs; pos.reallocate(posCount); for (u32 i=0; i