From d1a51b897dd68c81e8ad8ad4bd3fcd93ee94935e Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 5 Mar 2014 14:48:21 +0400 Subject: [PATCH] Fix conversions to bool with leading zeros (refs #9659) --- include/boost/lexical_cast.hpp | 48 ++++++++++++++++++---------------- test/lexical_cast_test.cpp | 27 ++++++++++++++++--- 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 421b823..814b69e 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1878,35 +1878,37 @@ namespace boost { } #endif - /* - * case "-0" || "0" || "+0" : output = false; return true; - * case "1" || "+1": output = true; return true; - * default: return false; - */ bool operator>>(bool& output) BOOST_NOEXCEPT { + output = false; // Suppress warning about uninitalized variable + + if (start == finish) return false; CharT const zero = lcast_char_constants::zero; CharT const plus = lcast_char_constants::plus; CharT const minus = lcast_char_constants::minus; - output = false; // Suppress warning about uninitalized variable - switch (finish - start) { - case 1: - output = Traits::eq(start[0], zero+1); - return output || Traits::eq(start[0], zero ); - - case 2: - if (Traits::eq(plus, *start)) { - ++start; - output = Traits::eq(start[0], zero + 1); - return output || Traits::eq(start[0], zero ); - } else { - return Traits::eq( minus, *start) - && Traits::eq( zero, start[1]); - } - - default: - return false; + const CharT* const dec_finish = finish - 1; + output = Traits::eq(*dec_finish, zero + 1); + if (!output && !Traits::eq(*dec_finish, zero)) { + return false; // Does not ends on '0' or '1' } + + if (start == dec_finish) return true; + + // We may have sign at the beginning + if (Traits::eq(plus, *start) || (Traits::eq(minus, *start) && !output)) { + ++ start; + } + + // Skipping zeros + while (start != dec_finish) { + if (!Traits::eq(zero, *start)) { + return false; // Not a zero => error + } + + ++ start; + } + + return true; } bool operator>>(float& output) { return lcast_ret_float(output,start,finish); } diff --git a/test/lexical_cast_test.cpp b/test/lexical_cast_test.cpp index 875d820..f27e6df 100644 --- a/test/lexical_cast_test.cpp +++ b/test/lexical_cast_test.cpp @@ -272,11 +272,32 @@ void test_conversion_to_bool() BOOST_CHECK_THROW( lexical_cast(std::string("Test")), bad_lexical_cast); - BOOST_CHECK(lexical_cast("+1") == true ); - BOOST_CHECK(lexical_cast("+0") == false ); - BOOST_CHECK(lexical_cast("-0") == false ); + BOOST_CHECK(lexical_cast("+1") == true); + BOOST_CHECK(lexical_cast("+0") == false); + BOOST_CHECK(lexical_cast("-0") == false); BOOST_CHECK_THROW(lexical_cast("--0"), bad_lexical_cast); BOOST_CHECK_THROW(lexical_cast("-+-0"), bad_lexical_cast); + + BOOST_CHECK(lexical_cast("0") == false); + BOOST_CHECK(lexical_cast("1") == true); + BOOST_CHECK(lexical_cast("00") == false); + BOOST_CHECK(lexical_cast("00000000000") == false); + BOOST_CHECK(lexical_cast("000000000001") == true); + BOOST_CHECK(lexical_cast("+00") == false ); + BOOST_CHECK(lexical_cast("-00") == false ); + BOOST_CHECK(lexical_cast("+00000000001") == true ); + + BOOST_CHECK_THROW(lexical_cast("020"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("00200"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("-00200"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("+00200"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("000000000002"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("-1"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("-0000000001"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("00000000011"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("001001"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("-00000000010"), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast("-000000000100"), bad_lexical_cast); } void test_conversion_to_string()