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