diff options
| -rw-r--r-- | src/pugixml.cpp | 111 | 
1 files changed, 63 insertions, 48 deletions
| diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 413e342..2df5394 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -20,6 +20,7 @@  #include <stdio.h>  #include <string.h>  #include <assert.h> +#include <limits.h>  #ifdef PUGIXML_WCHAR_MODE  #	include <wchar.h> @@ -4429,39 +4430,81 @@ PUGI__NS_BEGIN  	}  	// get value with conversion functions -	PUGI__FN int get_integer_base(const char_t* value) +	template <typename U> U string_to_integer(const char_t* value, U minneg, U maxpos)  	{ +		U result = 0;  		const char_t* s = value;  		while (PUGI__IS_CHARTYPE(*s, ct_space))  			s++; -		if (*s == '-') -			s++; +		bool negative = (*s == '-'); + +		s += negative; + +		bool overflow = false; + +		if (s[0] == '0' && (s[1] | ' ') == 'x') +		{ +			s += 2; + +			const char_t* start = s; + +			for (;;) +			{ +				if (static_cast<unsigned>(*s - '0') < 10) +					result = result * 16 + (*s - '0'); +				else if (static_cast<unsigned>((*s | ' ') - 'a') < 6) +					result = result * 16 + ((*s | ' ') - 'a' + 10); +				else +					break; + +				s++; +			} + +			size_t digits = static_cast<size_t>(s - start); + +			overflow = digits > sizeof(U) * 2; +		} +		else +		{ +			const char_t* start = s; + +			for (;;) +			{ +				if (static_cast<unsigned>(*s - '0') < 10) +					result = result * 10 + (*s - '0'); +				else +					break; + +				s++; +			} + +			size_t digits = static_cast<size_t>(s - start); + +			PUGI__STATIC_ASSERT(sizeof(U) == 8 || sizeof(U) == 4 || sizeof(U) == 2); -		return (s[0] == '0' && (s[1] | ' ') == 'x') ? 16 : 10; +			const size_t max_digits10 = sizeof(U) == 8 ? 20 : sizeof(U) == 4 ? 10 : 5; +			const char max_lead = sizeof(U) == 8 ? '1' : sizeof(U) == 4 ? '4' : '6'; +			const size_t high_bit = sizeof(U) * 8 - 1; + +			overflow = digits >= max_digits10 && !(digits == max_digits10 && (*start < max_lead || (*start == max_lead && result >> high_bit))); +		} + +		if (negative) +			return (overflow || result > minneg) ? 0 - minneg : 0 - result; +		else +			return (overflow || result > maxpos) ? maxpos : result;  	}  	PUGI__FN int get_value_int(const char_t* value)  	{ -		int base = get_integer_base(value); - -	#ifdef PUGIXML_WCHAR_MODE -		return static_cast<int>(wcstol(value, 0, base)); -	#else -		return static_cast<int>(strtol(value, 0, base)); -	#endif +		return string_to_integer<unsigned int>(value, INT_MIN, INT_MAX);  	}  	PUGI__FN unsigned int get_value_uint(const char_t* value)  	{ -		int base = get_integer_base(value); - -	#ifdef PUGIXML_WCHAR_MODE -		return static_cast<unsigned int>(wcstoul(value, 0, base)); -	#else -		return static_cast<unsigned int>(strtoul(value, 0, base)); -	#endif +		return string_to_integer<unsigned int>(value, 0, UINT_MAX);  	}  	PUGI__FN double get_value_double(const char_t* value) @@ -4494,40 +4537,12 @@ PUGI__NS_BEGIN  #ifdef PUGIXML_HAS_LONG_LONG  	PUGI__FN long long get_value_llong(const char_t* value)  	{ -		int base = get_integer_base(value); - -	#ifdef PUGIXML_WCHAR_MODE -		#ifdef PUGI__MSVC_CRT_VERSION -			return _wcstoi64(value, 0, base); -		#else -			return wcstoll(value, 0, base); -		#endif -	#else -		#ifdef PUGI__MSVC_CRT_VERSION -			return _strtoi64(value, 0, base); -		#else -			return strtoll(value, 0, base); -		#endif -	#endif +		return string_to_integer<unsigned long long>(value, LLONG_MIN, LLONG_MAX);  	}  	PUGI__FN unsigned long long get_value_ullong(const char_t* value)  	{ -		int base = get_integer_base(value); - -	#ifdef PUGIXML_WCHAR_MODE -		#ifdef PUGI__MSVC_CRT_VERSION -			return _wcstoui64(value, 0, base); -		#else -			return wcstoull(value, 0, base); -		#endif -	#else -		#ifdef PUGI__MSVC_CRT_VERSION -			return _strtoui64(value, 0, base); -		#else -			return strtoull(value, 0, base); -		#endif -	#endif +		return string_to_integer<unsigned long long>(value, 0, ULLONG_MAX);  	}  #endif | 
