From 8c4df9033ce9fcc62044900e11a6e9e934869bd4 Mon Sep 17 00:00:00 2001 From: Yuri Gorshenin Date: Fri, 18 Mar 2016 01:43:14 +0300 Subject: [PATCH] [base] Fixed integral to string conversion. --- base/base_tests/string_utils_test.cpp | 3 +++ base/string_utils.hpp | 20 ++++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/base/base_tests/string_utils_test.cpp b/base/base_tests/string_utils_test.cpp index 3f6dc94418..55b256bacf 100644 --- a/base/base_tests/string_utils_test.cpp +++ b/base/base_tests/string_utils_test.cpp @@ -253,6 +253,9 @@ UNIT_TEST(to_string) TEST_EQUAL(strings::to_string(123456789123456789ULL), "123456789123456789", ()); TEST_EQUAL(strings::to_string(-987654321987654321LL), "-987654321987654321", ()); + + uint64_t const n = numeric_limits::max(); + TEST_EQUAL(strings::to_string(n), "18446744073709551615", ()); } UNIT_TEST(to_string_dac) diff --git a/base/string_utils.hpp b/base/string_utils.hpp index 09f459d90c..4d006a0d08 100644 --- a/base/string_utils.hpp +++ b/base/string_utils.hpp @@ -223,6 +223,22 @@ template string to_string(T t) namespace impl { +template +int UpperBoundOnChars() +{ + // It's wrong to return just numeric_limits::digits10 + [is + // signed] because digits10 for a type T is computed as: + // + // floor(log10(2 ^ (CHAR_BITS * sizeof(T)))) = + // floor(CHAR_BITS * sizeof(T) * log10(2)) + // + // Therefore, due to rounding, we need to compensate possible + // error. + // + // NOTE: following code works only on two-complement systems! + + return numeric_limits::digits10 + is_signed::value + 1; +} template char * to_string_digits(char * buf, T i) { @@ -238,7 +254,7 @@ template char * to_string_digits(char * buf, T i) template string to_string_signed(T i) { bool const negative = i < 0; - int const sz = numeric_limits::digits10 + 1; + int const sz = UpperBoundOnChars(); char buf[sz]; char * end = buf + sz; char * beg = to_string_digits(end, negative ? -i : i); @@ -252,7 +268,7 @@ template string to_string_signed(T i) template string to_string_unsigned(T i) { - int const sz = numeric_limits::digits10; + int const sz = UpperBoundOnChars(); char buf[sz]; char * end = buf + sz; char * beg = to_string_digits(end, i);