2aba1d4
diff -up irrlicht-1.7.2/include/fast_atof.h.fastatof irrlicht-1.7.2/include/fast_atof.h
2aba1d4
--- irrlicht-1.7.2/include/fast_atof.h.fastatof	2010-10-24 09:42:58.000000000 -0400
2aba1d4
+++ irrlicht-1.7.2/include/fast_atof.h	2010-11-17 15:35:45.278571002 -0500
2aba1d4
@@ -12,8 +12,8 @@ namespace irr
2aba1d4
 namespace core
2aba1d4
 {
2aba1d4
 
2aba1d4
-// we write [17] here instead of [] to work around a swig bug
2aba1d4
-const float fast_atof_table[17] = {
2aba1d4
+// we write [16] here instead of [] to work around a swig bug
2aba1d4
+const float fast_atof_table[16] = {
2aba1d4
 	0.f,
2aba1d4
 	0.1f,
2aba1d4
 	0.01f,
2aba1d4
@@ -30,7 +30,6 @@ const float fast_atof_table[17] = {
2aba1d4
 	0.0000000000001f,
2aba1d4
 	0.00000000000001f,
2aba1d4
 	0.000000000000001f,
2aba1d4
-	0.0000000000000001f
2aba1d4
 };
2aba1d4
 
2aba1d4
 //! Convert a simple string of base 10 digits into a signed 32 bit integer.
2aba1d4
@@ -39,42 +38,132 @@ const float fast_atof_table[17] = {
2aba1d4
 //!					first non-digit.
2aba1d4
 //! \param[out] out: (optional) If provided, it will be set to point at the first
2aba1d4
 //!					 character not used in the calculation.
2aba1d4
-//! \return The signed integer value of the digits. If the string specifies too many
2aba1d4
-//!			digits to encode in an s32 then +INT_MAX or -INT_MAX will be returned.
2aba1d4
-inline s32 strtol10(const char* in, const char** out=0)
2aba1d4
+//! \return The unsigned integer value of the digits.
2aba1d4
+inline u32 strtol10(const char* in, const char** out=0)
2aba1d4
 {
2aba1d4
-	if(!in)
2aba1d4
-		return 0;
2aba1d4
+	unsigned int value = 0;
2aba1d4
 
2aba1d4
-	bool negative = false;
2aba1d4
-	if('-' == *in)
2aba1d4
+	bool running = true;
2aba1d4
+	while ( running )
2aba1d4
 	{
2aba1d4
-		negative = true;
2aba1d4
+		if ( *in < '0' || *in > '9' )
2aba1d4
+			break;
2aba1d4
+
2aba1d4
+		value = ( value * 10 ) + ( *in - '0' );
2aba1d4
 		++in;
2aba1d4
 	}
2aba1d4
-	else if('+' == *in)
2aba1d4
+	if (out)*out = in;
2aba1d4
+	return value;
2aba1d4
+}
2aba1d4
+
2aba1d4
+//! Convert a simple string of base 10 digits into a signed 32 bit integer.
2aba1d4
+//! \param[in] in: The string of digits to convert. Only a leading - or + followed 
2aba1d4
+//!					by digits 0 to 9 will be considered.  Parsing stops at the
2aba1d4
+//!					first non-digit.
2aba1d4
+//! \param[out] out: (optional) If provided, it will be set to point at the first
2aba1d4
+//!					 character not used in the calculation.
2aba1d4
+//! \return The signed integer value of the digits. If the string specifies too many
2aba1d4
+//!			digits to encode in an s32 then +INT_MAX or -INT_MAX will be returned.
2aba1d4
+inline s32 strtol10s(const char* in, const char** out=0)
2aba1d4
+{
2aba1d4
+	bool inv = (*in=='-');
2aba1d4
+	if (inv || *in=='+')
2aba1d4
 		++in;
2aba1d4
 
2aba1d4
-	u32 unsignedValue = 0;
2aba1d4
+	int value = strtol10(in,out);
2aba1d4
+	if (inv) {
2aba1d4
+		value = -value;
2aba1d4
+	}
2aba1d4
+	return value;
2aba1d4
+}
2aba1d4
 
2aba1d4
-	while ( ( *in >= '0') && ( *in <= '9' ))
2aba1d4
+//! Convert a simple string of base 8 (octal) digits into an unsigned 32 bit integer.
2aba1d4
+//! \param[in] in: The string of digits to convert. Only digits 0 to 7 will be considered.  
2aba1d4
+//!                               Parsing stops at the first non-digit.
2aba1d4
+//! \param[out] out: (optional) If provided, it will be set to point at the first
2aba1d4
+//!					 character not used in the calculation.
2aba1d4
+//! \return The unsigned integer value of the digits.
2aba1d4
+inline u32 strtol8(const char* in, const char** out=0)
2aba1d4
+{
2aba1d4
+	unsigned int value = 0;
2aba1d4
+
2aba1d4
+	bool running = true;
2aba1d4
+	while ( running )
2aba1d4
 	{
2aba1d4
-		unsignedValue = ( unsignedValue * 10 ) + ( *in - '0' );
2aba1d4
+		if ( *in < '0' || *in > '7' )
2aba1d4
+			break;
2aba1d4
+
2aba1d4
+		value = ( value << 3 ) + ( *in - '0' );
2aba1d4
 		++in;
2aba1d4
+	}
2aba1d4
+	if (out)*out = in;
2aba1d4
+	return value;
2aba1d4
+}
2aba1d4
 
2aba1d4
-		if(unsignedValue > (u32)INT_MAX)
2aba1d4
+//! Convert a simple string of base 16 (hex) digits into an unsigned 32 bit integer.
2aba1d4
+//! \param[in] in: The string of digits to convert. Only digits 0 to 9, A to F will be considered.  
2aba1d4
+//!                               Parsing stops at the first non-digit. Letters can be in either case.
2aba1d4
+//! \param[out] out: (optional) If provided, it will be set to point at the first
2aba1d4
+//!					 character not used in the calculation.
2aba1d4
+//! \return The unsigned integer value of the digits.
2aba1d4
+inline u32 strtol16( const char* in, const char** out=0)
2aba1d4
+{
2aba1d4
+	unsigned int value = 0;
2aba1d4
+
2aba1d4
+	bool running = true;
2aba1d4
+	while ( running )
2aba1d4
+	{
2aba1d4
+		if ( *in >= '0' && *in <= '9' )
2aba1d4
 		{
2aba1d4
-			unsignedValue = (u32)INT_MAX;
2aba1d4
-			break;
2aba1d4
+			value = ( value << 4u ) + ( *in - '0' );
2aba1d4
 		}
2aba1d4
+		else if (*in >= 'A' && *in <= 'F')
2aba1d4
+		{
2aba1d4
+			value = ( value << 4u ) + ( *in - 'A' ) + 10;
2aba1d4
+		}
2aba1d4
+		else if (*in >= 'a' && *in <= 'f')
2aba1d4
+		{
2aba1d4
+			value = ( value << 4u ) + ( *in - 'a' ) + 10;
2aba1d4
+		}
2aba1d4
+		else break;
2aba1d4
+		++in;
2aba1d4
 	}
2aba1d4
 	if (out)
2aba1d4
 		*out = in;
2aba1d4
+	return value;
2aba1d4
+}
2aba1d4
+
2aba1d4
+//! Convert a hex-encoded digi (1 character) to an 8 bit unsigned integer.
2aba1d4
+//! \param[in] in: The string of digits to convert. Only digits 0 to 9, A to F will be considered.  
2aba1d4
+//!                               Parsing stops at the first non-digit. Letters can be in either case.
2aba1d4
+//! \param[out] out: (optional) If provided, it will be set to point at the first
2aba1d4
+//!					 character not used in the calculation.
2aba1d4
+//! \return The unsigned integer value of the digits. 0xffffffff if the input is not hex
2aba1d4
+inline u32 HexDigitToDecimal(char in)
2aba1d4
+{
2aba1d4
+	unsigned int out = 0xffffffff;
2aba1d4
+	if (in >= '0' && in <= '9')
2aba1d4
+		out = in - '0';
2aba1d4
+
2aba1d4
+	else if (in >= 'a' && in <= 'f')
2aba1d4
+		out = 10u + in - 'a';
2aba1d4
 
2aba1d4
-	if(negative)
2aba1d4
-		return -((s32)unsignedValue);
2aba1d4
-	else
2aba1d4
-		return (s32)unsignedValue;
2aba1d4
+	else if (in >= 'A' && in <= 'F')
2aba1d4
+		out = 10u + in - 'A';
2aba1d4
+
2aba1d4
+	// return value is 0xffffffff if the input is not a hex digit
2aba1d4
+	return out;
2aba1d4
+}
2aba1d4
+
2aba1d4
+//! Convert a hex-encoded octet (2 characters) to an 8 bit unsigned integer.
2aba1d4
+//! \param[in] in: The string of digits to convert. Only digits 0 to 9, A to F will be considered.  
2aba1d4
+//!                               Parsing stops at the first non-digit. Letters can be in either case.
2aba1d4
+//! \param[out] out: (optional) If provided, it will be set to point at the first
2aba1d4
+//!					 character not used in the calculation.
2aba1d4
+//! \return The unsigned integer value of the digits. 0xffffffff if the input is not hex
2aba1d4
+inline u8 HexOctetToDecimal(const char* in)
2aba1d4
+{
2aba1d4
+	return ((u8)HexDigitToDecimal(in[0])<<4)+(u8)HexDigitToDecimal(in[1]);
2aba1d4
 }
2aba1d4
 
2aba1d4
 //! Converts a sequence of digits into a whole positive floating point value.
2aba1d4
@@ -126,6 +215,56 @@ inline f32 strtof10(const char* in, cons
2aba1d4
 	return floatValue;
2aba1d4
 }
2aba1d4
 
2aba1d4
+//! Convert a simple string of base 10 digits into an unsigned 64 bit integer.
2aba1d4
+//! \param[in] in: The string of digits to convert. Only a leading - or + followed 
2aba1d4
+//!					by digits 0 to 9 will be considered.  Parsing stops at the
2aba1d4
+//!					first non-digit.
2aba1d4
+//! \param[out] out: (optional) If provided, it will be set to point at the first
2aba1d4
+//!					 character not used in the calculation.
2aba1d4
+//! \return The unsigned 64 bit integer value of the digits.
2aba1d4
+inline u64 strtol10_64( const char* in, const char** out=0, unsigned int* max_inout=0)
2aba1d4
+{
2aba1d4
+	unsigned int cur = 0;
2aba1d4
+	u64 value = 0;
2aba1d4
+
2aba1d4
+	bool running = true;
2aba1d4
+	while ( running )
2aba1d4
+	{
2aba1d4
+		if ( *in < '0' || *in > '9' )
2aba1d4
+			break;
2aba1d4
+
2aba1d4
+		const u64 new_value = ( value * 10 ) + ( *in - '0' );
2aba1d4
+		
2aba1d4
+		if (new_value < value) /* numeric overflow, we rely on you */
2aba1d4
+			return value;
2aba1d4
+
2aba1d4
+		value = new_value;
2aba1d4
+
2aba1d4
+		++in;
2aba1d4
+		++cur;
2aba1d4
+
2aba1d4
+		if (max_inout && *max_inout == cur) {
2aba1d4
+					
2aba1d4
+			if (out) { /* skip to end */
2aba1d4
+				while (*in >= '0' && *in <= '9')
2aba1d4
+					++in;
2aba1d4
+				*out = in;
2aba1d4
+			}
2aba1d4
+
2aba1d4
+			return value;
2aba1d4
+		}
2aba1d4
+	}
2aba1d4
+	if (out)
2aba1d4
+		*out = in;
2aba1d4
+
2aba1d4
+	if (max_inout)
2aba1d4
+		*max_inout = cur;
2aba1d4
+
2aba1d4
+	return value;
2aba1d4
+}
2aba1d4
+// Number of relevant decimals for floating-point parsing.
2aba1d4
+#define AI_FAST_ATOF_RELAVANT_DECIMALS 10
2aba1d4
+
2aba1d4
 //! Provides a fast function for converting a string into a float.
2aba1d4
 //! This is not guaranteed to be as accurate as atof(), but is 
2aba1d4
 //! approximately 6 to 8 times as fast.
2aba1d4
@@ -138,46 +277,51 @@ inline const char* fast_atof_move( const
2aba1d4
 	// Please run this regression test when making any modifications to this function:
2aba1d4
 	// https://sourceforge.net/tracker/download.php?group_id=74339&atid=540676&file_id=298968&aid=1865300
2aba1d4
 
2aba1d4
-	out = 0.f;
2aba1d4
-	if(!in)
2aba1d4
-		return 0;
2aba1d4
+	float f;
2aba1d4
 
2aba1d4
-	bool negative = false;
2aba1d4
-	if(*in == '-')
2aba1d4
-	{
2aba1d4
-		negative = true;
2aba1d4
+	bool inv = (*in=='-');
2aba1d4
+	if (inv || *in=='+')
2aba1d4
 		++in;
2aba1d4
-	}
2aba1d4
 
2aba1d4
-	f32 value = strtof10 ( in, &in );
2aba1d4
-
2aba1d4
-	if (*in == '.')
2aba1d4
+	f = (float) strtol10_64 ( in, &in);
2aba1d4
+	if (*in == '.' || (in[0] == ',' && (in[1] >= '0' || in[1] <= '9'))) // allow for commas, too
2aba1d4
 	{
2aba1d4
 		++in;
2aba1d4
 
2aba1d4
-		const char * afterDecimal = in;
2aba1d4
-		f32 decimal = strtof10 ( in, &afterDecimal );
2aba1d4
-		decimal *= fast_atof_table[afterDecimal - in];
2aba1d4
-
2aba1d4
-		value += decimal;
2aba1d4
+		// NOTE: The original implementation is highly unaccurate here. The precision of a single
2aba1d4
+		// IEEE 754 float is not high enough, everything behind the 6th digit tends to be more 
2aba1d4
+		// inaccurate than it would need to be. Casting to double seems to solve the problem.
2aba1d4
+		// strtol_64 is used to prevent integer overflow.
2aba1d4
+
2aba1d4
+		// Another fix: this tends to become 0 for long numbers if we don't limit the maximum 
2aba1d4
+		// number of digits to be read. AI_FAST_ATOF_RELAVANT_DECIMALS can be a value between
2aba1d4
+		// 1 and 15.
2aba1d4
+		unsigned int diff = AI_FAST_ATOF_RELAVANT_DECIMALS;
2aba1d4
+		double pl = (double) strtol10_64 ( in, &in, &diff );
2aba1d4
 
2aba1d4
-		in = afterDecimal;
2aba1d4
+		pl *= fast_atof_table[diff];
2aba1d4
+		f += (float)pl;
2aba1d4
 	}
2aba1d4
 
2aba1d4
-	if ('e' == *in || 'E' == *in)
2aba1d4
+	// A major 'E' must be allowed. Necessary for proper reading of some DXF files.
2aba1d4
+	// Thanks to Zhao Lei to point out that this if() must be outside the if (*c == '.' ..)
2aba1d4
+	if (*in == 'e' || *in == 'E')
2aba1d4
 	{
2aba1d4
 		++in;
2aba1d4
-		// Assume that the exponent is a whole number.
2aba1d4
-		// strtol10() will deal with both + and - signs,
2aba1d4
-		// but cast to (f32) to prevent overflow at FLT_MAX
2aba1d4
-		value *= (f32)pow(10.0f, (f32)strtol10(in, &in);;
2aba1d4
-	}
2aba1d4
-
2aba1d4
-	if(negative)
2aba1d4
-		out = -value;
2aba1d4
-	else
2aba1d4
-		out = value;
2aba1d4
+		bool einv = (*in=='-');
2aba1d4
+		if (einv || *in=='+')
2aba1d4
+			++in;
2aba1d4
+
2aba1d4
+		float exp = (float)strtol10_64(in, &in);
2aba1d4
+		if (einv)
2aba1d4
+			exp *= -1.0f;
2aba1d4
 
2aba1d4
+		f *= pow(10.0f, exp);
2aba1d4
+	}
2aba1d4
+	if (inv)
2aba1d4
+		f *= -1.0f;
2aba1d4
+	
2aba1d4
+	out = f;
2aba1d4
 	return in;
2aba1d4
 }
2aba1d4
 
2aba1d4
@@ -190,6 +334,47 @@ inline float fast_atof(const char* float
2aba1d4
 	return ret;
2aba1d4
 }
2aba1d4
 
2aba1d4
+//! Convert a string to a floating point number
2aba1d4
+//! \param c: The string to convert.
2aba1d4
+//! \param cout: A pointer to the first character in the string that wasn't
2aba1d4
+//!         use to create the float value.
2aba1d4
+inline float fast_atof( const char* c, const char** cout)
2aba1d4
+{
2aba1d4
+	float ret;
2aba1d4
+	*cout = fast_atof_move(c, ret);
2aba1d4
+
2aba1d4
+	return ret;
2aba1d4
+}
2aba1d4
+
2aba1d4
+//! Convert a string to a floating point number
2aba1d4
+//! \param inout: The string to convert, returned 
2aba1d4
+//!         as the pointer to the first character 
2aba1d4
+//!         in the string that wasn't
2aba1d4
+//!         use to create the float value.
2aba1d4
+inline float fast_atof( const char** inout)
2aba1d4
+{
2aba1d4
+	float ret;
2aba1d4
+	*inout = fast_atof_move(*inout, ret);
2aba1d4
+
2aba1d4
+	return ret;
2aba1d4
+}
2aba1d4
+
2aba1d4
+//! Parse a C++-like integer literal - hex and oct prefixes - to an unsigned int
2aba1d4
+//! 0xNNNN - hex
2aba1d4
+//! 0NNN   - oct
2aba1d4
+//! NNN    - dec
2aba1d4
+//! \param[in] in: The string to convert. 
2aba1d4
+//! \param cout: A pointer to the first character in the string that wasn't
2aba1d4
+//!         use to create the float value.
2aba1d4
+inline u32 strtol_cppstyle( const char* in, const char** out=0)
2aba1d4
+{
2aba1d4
+	if ('0' == in[0])
2aba1d4
+	{
2aba1d4
+		return 'x' == in[1] ? strtol16(in+2,out) : strtol8(in+1,out);
2aba1d4
+	}
2aba1d4
+	return strtol10(in, out);
2aba1d4
+}
2aba1d4
+
2aba1d4
 } // end namespace core
2aba1d4
 } // end namespace irr
2aba1d4
 
2aba1d4
diff -up irrlicht-1.7.2/include/irrTypes.h.fastatof irrlicht-1.7.2/include/irrTypes.h
2aba1d4
--- irrlicht-1.7.2/include/irrTypes.h.fastatof	2010-10-24 09:43:00.000000000 -0400
2aba1d4
+++ irrlicht-1.7.2/include/irrTypes.h	2010-11-17 15:35:17.651571001 -0500
2aba1d4
@@ -67,14 +67,21 @@ typedef signed int		s32;
2aba1d4
 #endif
2aba1d4
 
2aba1d4
 
2aba1d4
+//! 64 bit unsigned variable.
2aba1d4
+/** This is a typedef for unsigned long, it ensures portability of the engine */
2aba1d4
+#ifdef _MSC_VER
2aba1d4
+typedef unsigned __int64		u64;
2aba1d4
+#else
2aba1d4
+typedef unsigned long			u64;
2aba1d4
+#endif
2aba1d4
 
2aba1d4
-// 64 bit signed variable.
2aba1d4
-// This is a typedef for __int64, it ensures portability of the engine.
2aba1d4
-// This type is currently not used by the engine and not supported by compilers
2aba1d4
-// other than Microsoft Compilers, so it is outcommented.
2aba1d4
-//typedef __int64				s64;
2aba1d4
-
2aba1d4
-
2aba1d4
+//! 64 bit signed variable.
2aba1d4
+/** This is a typedef for signed long, it ensures portability of the engine. */
2aba1d4
+#ifdef _MSC_VER
2aba1d4
+typedef __int64				s64;
2aba1d4
+#else
2aba1d4
+typedef signed long			s64;
2aba1d4
+#endif
2aba1d4
 
2aba1d4
 //! 32 bit floating point variable.
2aba1d4
 /** This is a typedef for float, it ensures portability of the engine. */