diff options
| author | Arseny Kapoulkine <arseny.kapoulkine@gmail.com> | 2015-09-20 00:03:02 -0700 | 
|---|---|---|
| committer | Arseny Kapoulkine <arseny.kapoulkine@gmail.com> | 2015-09-20 00:03:02 -0700 | 
| commit | 131c1a159c672ee651fa14efe41ee6ea6fd7ebf8 (patch) | |
| tree | 001a18c632c791b2babfaff32fb463534a9ebd35 | |
| parent | 234c2f3657ec50671299a359877b058d55aa1d1d (diff) | |
Implement integer to string conversion manually
This reduces the amount of non-standard C++ functionality pugixml may be using
by avoiding sprintf with %lld; additionally this implementation is significantly
faster (4-5x) than sprintf, mostly due to avoiding format string parsing and
stream setup that commonly happens in CRT implementations.
This comes at the expense of requiring long long division/remainder operations
if PUGIXML_USE_LONG_LONG is defined which will surely bite me one day.
| -rw-r--r-- | src/pugixml.cpp | 52 | 
1 files changed, 37 insertions, 15 deletions
| diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 2ad2f15..e817690 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -4540,6 +4540,28 @@ PUGI__NS_BEGIN  	}  #endif +	template <typename U> +	PUGI__FN char_t* integer_to_string(char_t (&buf)[64], U value, bool negative) +	{ +		char_t* end = buf + sizeof(buf) / sizeof(buf[0]) - 1; +		U rest = negative ? 0 - value : value; + +		*end-- = 0; + +		do +		{ +			*end-- = static_cast<char_t>('0' + (rest % 10)); +			rest /= 10; +		} +		while (rest); + +		assert(end >= buf); + +		*end = '-'; + +		return end + !negative; +	} +  	// set value with conversion functions  	template <typename String, typename Header>  	PUGI__FN bool set_value_buffer(String& dest, Header& header, uintptr_t header_mask, char (&buf)[128]) @@ -4557,19 +4579,19 @@ PUGI__NS_BEGIN  	template <typename String, typename Header>  	PUGI__FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, int value)  	{ -		char buf[128]; -		sprintf(buf, "%d", value); -	 -		return set_value_buffer(dest, header, header_mask, buf); +		char_t buf[64]; +		char_t* begin = integer_to_string<unsigned int>(buf, value, value < 0); + +		return strcpy_insitu(dest, header, header_mask, begin);  	}  	template <typename String, typename Header>  	PUGI__FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, unsigned int value)  	{ -		char buf[128]; -		sprintf(buf, "%u", value); +		char_t buf[64]; +		char_t* begin = integer_to_string<unsigned int>(buf, value, false); -		return set_value_buffer(dest, header, header_mask, buf); +		return strcpy_insitu(dest, header, header_mask, begin);  	}  	template <typename String, typename Header> @@ -4600,19 +4622,19 @@ PUGI__NS_BEGIN  	template <typename String, typename Header>  	PUGI__FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, long long value)  	{ -		char buf[128]; -		sprintf(buf, "%lld", value); -	 -		return set_value_buffer(dest, header, header_mask, buf); +		char_t buf[64]; +		char_t* begin = integer_to_string<unsigned long long>(buf, value, value < 0); + +		return strcpy_insitu(dest, header, header_mask, begin);  	}  	template <typename String, typename Header>  	PUGI__FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, unsigned long long value)  	{ -		char buf[128]; -		sprintf(buf, "%llu", value); -	 -		return set_value_buffer(dest, header, header_mask, buf); +		char_t buf[64]; +		char_t* begin = integer_to_string<unsigned long long>(buf, value, false); + +		return strcpy_insitu(dest, header, header_mask, begin);  	}  #endif | 
