From e70b137002050f41f18c876fb753c793a47fabc4 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Mon, 11 Jul 2016 16:45:24 +0100 Subject: [PATCH] Fix sporadic failure in lexical_cast. --- include/helpers/lexical_cast.hpp | 14 +++++++------ test/unit/test_lexical_cast.cpp | 36 ++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/include/helpers/lexical_cast.hpp b/include/helpers/lexical_cast.hpp index 18332c9..7417892 100644 --- a/include/helpers/lexical_cast.hpp +++ b/include/helpers/lexical_cast.hpp @@ -161,17 +161,19 @@ namespace dinhelp { template template std::size_t dec::count_digits_implem (T parValue, dinhelp::bt::index_seq, dinhelp::bt::index_seq) { - static T powers[] = { 0, static_cast(dinhelp::implem::power<10, Powers + 1>::value)... }; - static std::size_t maxdigits[] = { count_digits_bt(static_cast(::pow(2.0, Digits)))... }; - const auto bits = sizeof(parValue) * CHAR_BIT - dinhelp::implem::count_leading_zeroes(parValue); - return (parValue < powers[maxdigits[bits] - 1] ? maxdigits[bits] - 1 : maxdigits[bits]) + dinhelp::implem::is_negative::check(parValue); + typedef typename std::make_unsigned::type UT; + static constexpr UT powers[] = { 0, static_cast(dinhelp::implem::power<10, Powers + 1>::value)... }; + static constexpr std::size_t maxdigits[] = { count_digits_bt(static_cast(::pow(2.0, Digits))) - (std::numeric_limits::is_signed ? 1 : 0)... }; + const auto bits = sizeof(parValue) * CHAR_BIT - dinhelp::implem::count_leading_zeroes(dinhelp::implem::abs(parValue)); + static_assert(std::is_same::value, "Unexpected type"); + return (dinhelp::implem::abs(parValue) < powers[maxdigits[bits] - 1] ? maxdigits[bits] - 1 : maxdigits[bits]) + dinhelp::implem::is_negative::check(parValue); } template std::size_t dec::count_digits (T parValue) { return count_digits_implem( parValue, - dinhelp::bt::index_range<0, count_digits_bt(std::numeric_limits::max()) + 1>(), + dinhelp::bt::index_range<0, count_digits_bt(std::numeric_limits::max()) - (std::numeric_limits::is_signed ? 1 : 0) - 1>(), dinhelp::bt::index_range<0, CHAR_BIT * sizeof(T) + 1>() ); } @@ -209,7 +211,7 @@ namespace dinhelp { template inline int count_leading_zeroes (typename std::enable_if::is_signed, T>::type parValue) { - return count_leading_zeroes(abs(parValue)); + return count_leading_zeroes(dinhelp::implem::abs(parValue)); } template diff --git a/test/unit/test_lexical_cast.cpp b/test/unit/test_lexical_cast.cpp index 379b1f8..976f438 100644 --- a/test/unit/test_lexical_cast.cpp +++ b/test/unit/test_lexical_cast.cpp @@ -126,4 +126,40 @@ TEST(helpers, lexical_cast) { const auto bin_str = lexical_cast(value); EXPECT_EQ("11111111111111111111101010001000", bin_str); } + { + const int32_t value = 515; + const auto hex_str = lexical_cast(value); + EXPECT_EQ("203", hex_str); + const auto dec_str = lexical_cast(value); + EXPECT_EQ("515", dec_str); + const auto bin_str = lexical_cast(value); + EXPECT_EQ("1000000011", bin_str); + } + { + const int64_t value = 515; + const auto hex_str = lexical_cast(value); + EXPECT_EQ("203", hex_str); + const auto dec_str = lexical_cast(value); + EXPECT_EQ("515", dec_str); + const auto bin_str = lexical_cast(value); + EXPECT_EQ("1000000011", bin_str); + } + { + const uint32_t value = 515; + const auto hex_str = lexical_cast(value); + EXPECT_EQ("203", hex_str); + const auto dec_str = lexical_cast(value); + EXPECT_EQ("515", dec_str); + const auto bin_str = lexical_cast(value); + EXPECT_EQ("1000000011", bin_str); + } + { + const uint64_t value = 515; + const auto hex_str = lexical_cast(value); + EXPECT_EQ("203", hex_str); + const auto dec_str = lexical_cast(value); + EXPECT_EQ("515", dec_str); + const auto bin_str = lexical_cast(value); + EXPECT_EQ("1000000011", bin_str); + } }