diff --git a/include/boost/charconv/detail/parser.hpp b/include/boost/charconv/detail/parser.hpp index 10ed18c..765a5ac 100644 --- a/include/boost/charconv/detail/parser.hpp +++ b/include/boost/charconv/detail/parser.hpp @@ -51,12 +51,7 @@ inline from_chars_result parser(const char* first, const char* last, bool& sign, ++next; } - // Next we get the significand - constexpr std::size_t significand_buffer_size = limits::max_chars10 - 1; // Base 10 or 16 - char significand_buffer[significand_buffer_size] {}; - std::size_t i = 0; - std::size_t dot_position = 0; - std::size_t extra_zeros = 0; + // If the number is 0 we can abort now char exp_char; char capital_exp_char; if (fmt != chars_format::hex) @@ -70,6 +65,20 @@ inline from_chars_result parser(const char* first, const char* last, bool& sign, capital_exp_char = 'P'; } + if (next == last || *next == exp_char || *next == -capital_exp_char) + { + significand = 0; + exponent = 0; + return {next, 0}; + } + + // Next we get the significand + constexpr std::size_t significand_buffer_size = limits::max_chars10 - 1; // Base 10 or 16 + char significand_buffer[significand_buffer_size] {}; + std::size_t i = 0; + std::size_t dot_position = 0; + std::size_t extra_zeros = 0; + while (*next != '.' && *next != exp_char && *next != capital_exp_char && next != last && i < significand_buffer_size) { significand_buffer[i] = *next; diff --git a/test/from_chars_float.cpp b/test/from_chars_float.cpp index 2f937c0..cb41e06 100644 --- a/test/from_chars_float.cpp +++ b/test/from_chars_float.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include template @@ -144,6 +145,52 @@ void odd_strings_test() } +template +void zero_test() +{ + const char* buffer1 = "0e0"; + T v1 = 0; + auto r1 = boost::charconv::from_chars(buffer1, buffer1 + std::strlen(buffer1), v1); + BOOST_TEST_EQ(r1.ec, 0); + BOOST_TEST_EQ(v1, static_cast(0)); + BOOST_TEST(!std::signbit(v1)); + + const char* buffer2 = "-0e0"; + T v2 = 0; + auto r2 = boost::charconv::from_chars(buffer2, buffer2 + std::strlen(buffer2), v2); + BOOST_TEST_EQ(r2.ec, 0); + BOOST_TEST_EQ(v2, static_cast(-0)); + BOOST_TEST(std::signbit(v2)); + + const char* buffer3 = "0.0"; + T v3 = 0; + auto r3 = boost::charconv::from_chars(buffer3, buffer3 + std::strlen(buffer3), v3); + BOOST_TEST_EQ(r3.ec, 0); + BOOST_TEST_EQ(v3, static_cast(0.0)); + BOOST_TEST(!std::signbit(v3)); + + const char* buffer4 = "-0.0"; + T v4 = 0; + auto r4 = boost::charconv::from_chars(buffer4, buffer4 + std::strlen(buffer4), v4); + BOOST_TEST_EQ(r4.ec, 0); + BOOST_TEST_EQ(v4, static_cast(-0)); + BOOST_TEST(std::signbit(v4)); + + const char* buffer5 = "0"; + T v5 = 0; + auto r5 = boost::charconv::from_chars(buffer5, buffer5 + std::strlen(buffer5), v5); + BOOST_TEST_EQ(r5.ec, 0); + BOOST_TEST_EQ(v5, static_cast(0)); + BOOST_TEST(!std::signbit(v5)); + + const char* buffer6 = "-0"; + T v6 = 0; + auto r6 = boost::charconv::from_chars(buffer6, buffer6 + std::strlen(buffer6), v6); + BOOST_TEST_EQ(r6.ec, 0); + BOOST_TEST_EQ(v6, static_cast(-0)); + BOOST_TEST(std::signbit(v6)); +} + int main() { simple_integer_test(); @@ -171,5 +218,8 @@ int main() simple_hex_scientific_test(); #endif + zero_test(); + zero_test(); + return boost::report_errors(); }