mirror of
https://github.com/boostorg/charconv.git
synced 2026-02-09 23:12:24 +00:00
Merge pull request #36 from mborland/29
Fix parsing of 0 or empty significand
This commit is contained in:
@@ -217,6 +217,12 @@ inline from_chars_result parser(const char* first, const char* last, bool& sign,
|
||||
}
|
||||
else if (*next == exp_char || *next == capital_exp_char)
|
||||
{
|
||||
// Would be a number without a significand e.g. e+03
|
||||
if (next == first)
|
||||
{
|
||||
return {next, EINVAL};
|
||||
}
|
||||
|
||||
++next;
|
||||
if (fmt == chars_format::fixed)
|
||||
{
|
||||
@@ -243,25 +249,33 @@ inline from_chars_result parser(const char* first, const char* last, bool& sign,
|
||||
}
|
||||
|
||||
from_chars_result r {};
|
||||
if (fmt == chars_format::hex)
|
||||
{
|
||||
r = from_chars(significand_buffer, significand_buffer + offset, significand, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
r = from_chars(significand_buffer, significand_buffer + offset, significand);
|
||||
}
|
||||
switch (r.ec)
|
||||
{
|
||||
case EINVAL:
|
||||
return {first, EINVAL};
|
||||
case ERANGE:
|
||||
return {next, ERANGE};
|
||||
}
|
||||
|
||||
if (round)
|
||||
// If the significand is 0 from chars will return EINVAL because there is nothing in the buffer,
|
||||
// but it is a valid value. We need to continue parsing to get the correct value of ptr even
|
||||
// though we know we could bail now.
|
||||
//
|
||||
// See GitHub issue #29: https://github.com/cppalliance/charconv/issues/29
|
||||
if (offset != 0)
|
||||
{
|
||||
significand += 1;
|
||||
if (fmt == chars_format::hex)
|
||||
{
|
||||
r = from_chars(significand_buffer, significand_buffer + offset, significand, 16);
|
||||
} else
|
||||
{
|
||||
r = from_chars(significand_buffer, significand_buffer + offset, significand);
|
||||
}
|
||||
switch (r.ec)
|
||||
{
|
||||
case EINVAL:
|
||||
return {first, EINVAL};
|
||||
case ERANGE:
|
||||
return {next, ERANGE};
|
||||
}
|
||||
|
||||
if (round)
|
||||
{
|
||||
significand += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -139,7 +139,11 @@ from_chars_result from_chars_float_impl(const char* first, const char* last, T&
|
||||
auto r = boost::charconv::detail::parser(first, last, sign, significand, exponent, fmt);
|
||||
if (r.ec != 0)
|
||||
{
|
||||
value = 0;
|
||||
return r;
|
||||
}
|
||||
else if (significand == 0)
|
||||
{
|
||||
value = sign ? static_cast<T>(-0.0L) : static_cast<T>(0.0L);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cerrno>
|
||||
#include <cmath>
|
||||
|
||||
template <typename T>
|
||||
@@ -167,6 +168,10 @@ void odd_strings_test()
|
||||
BOOST_TEST_EQ(r5.ec, 0);
|
||||
BOOST_TEST_EQ(v5, static_cast<T>(1.23456789123456789123456789123456789123456789e-5L));
|
||||
|
||||
const char* buffer6 = "E01";
|
||||
T v6 = 0;
|
||||
auto r6 = boost::charconv::from_chars(buffer6, buffer6 + std::strlen(buffer6), v6);
|
||||
BOOST_TEST_EQ(r6.ec, EINVAL);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
||||
@@ -363,5 +363,15 @@ int main()
|
||||
"00000000000000000000000000000000000000000000000000" // 500 zeroes
|
||||
);
|
||||
|
||||
// Reported in issue #29
|
||||
// https://github.com/cppalliance/charconv/issues/29
|
||||
|
||||
fc("0E0");
|
||||
fc("0E01");
|
||||
fc("0.0e0");
|
||||
fc("-0E0");
|
||||
fc("-0E01");
|
||||
fc("-0.0e0");
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user