Fix read_long_double with respect to decimal_point:

*  Respect locale settings when ONLY_C_LOCALE=0
*  Do not respect locale settings when ONLY_C_LOCALE=1
Fixes #637
This commit is contained in:
Howard Hinnant 2021-01-05 21:14:41 -05:00
parent 97246a638a
commit 26fc2bd372

View File

@ -45,9 +45,7 @@
#include <cctype>
#include <chrono>
#include <climits>
#if !(__cplusplus >= 201402)
#include <cmath>
#endif
#include <cstddef>
#include <cstdint>
#include <cstdlib>
@ -6169,9 +6167,16 @@ long double
read_long_double(std::basic_istream<CharT, Traits>& is, unsigned m = 1, unsigned M = 10)
{
unsigned count = 0;
unsigned fcount = 0;
unsigned long long i = 0;
unsigned long long f = 0;
bool parsing_fraction = false;
#if ONLY_C_LOCALE
typename Traits::int_type decimal_point = '.';
#else
auto decimal_point = Traits::to_int_type(
std::use_facet<std::numpunct<CharT>>(is.getloc()).decimal_point());
std::string buf;
#endif
while (true)
{
auto ic = is.peek();
@ -6179,18 +6184,25 @@ read_long_double(std::basic_istream<CharT, Traits>& is, unsigned m = 1, unsigned
break;
if (Traits::eq_int_type(ic, decimal_point))
{
buf += '.';
decimal_point = Traits::eof();
is.get();
parsing_fraction = true;
}
else
{
auto c = static_cast<char>(Traits::to_char_type(ic));
if (!('0' <= c && c <= '9'))
break;
buf += c;
(void)is.get();
if (!parsing_fraction)
{
i = 10*i + static_cast<unsigned>(c - '0');
}
else
{
f = 10*f + static_cast<unsigned>(c - '0');
++fcount;
}
}
(void)is.get();
if (++count == M)
break;
}
@ -6199,7 +6211,7 @@ read_long_double(std::basic_istream<CharT, Traits>& is, unsigned m = 1, unsigned
is.setstate(std::ios::failbit);
return 0;
}
return std::stold(buf);
return i + f/std::pow(10.L, fcount);
}
struct rs