fixed locale problems

This commit is contained in:
Niels 2016-04-05 21:55:51 +02:00
parent 43ee70cef8
commit 31bccc83b9
3 changed files with 93 additions and 62 deletions

View file

@ -6114,24 +6114,26 @@ class basic_json
case value_t::number_float: case value_t::number_float:
{ {
// buffer size: precision (2^8-1 = 255) + other ('-.e-xxx' = 7) + null (1)
char buf[263];
int len;
// check if number was parsed from a string // check if number was parsed from a string
if (m_type.bits.parsed) if (m_type.bits.parsed)
{ {
// check if parsed number had an exponent given // check if parsed number had an exponent given
if (m_type.bits.has_exp) if (m_type.bits.has_exp)
{ {
// buffer size: precision (2^8-1 = 255) + other ('-.e-xxx' = 7) + null (1)
char buf[263];
int len;
// handle capitalization of the exponent // handle capitalization of the exponent
if (m_type.bits.exp_cap) if (m_type.bits.exp_cap)
{ {
len = snprintf(buf, sizeof(buf), "%.*E", m_type.bits.precision, m_value.number_float) + 1; len = snprintf(buf, sizeof(buf), "%.*E",
m_type.bits.precision, m_value.number_float) + 1;
} }
else else
{ {
len = snprintf(buf, sizeof(buf), "%.*e", m_type.bits.precision, m_value.number_float) + 1; len = snprintf(buf, sizeof(buf), "%.*e",
m_type.bits.precision, m_value.number_float) + 1;
} }
// remove '+' sign from the exponent if necessary // remove '+' sign from the exponent if necessary
@ -6152,40 +6154,40 @@ class basic_json
} }
} }
} }
o << buf;
} }
else else
{ {
// no exponent - output as a decimal // no exponent - output as a decimal
snprintf(buf, sizeof(buf), "%.*f", std::stringstream ss;
m_type.bits.precision, m_value.number_float); ss.imbue(std::locale("C"));
ss << std::setprecision(m_type.bits.precision)
<< std::fixed << m_value.number_float;
o << ss.str();
} }
} }
else if (m_value.number_float == 0)
{
// special case for zero to get "0.0"/"-0.0"
if (std::signbit(m_value.number_float))
{
o << "-0.0";
}
else
{
o << "0.0";
}
return;
}
else else
{ {
// Otherwise 6, 15 or 16 digits of precision allows if (m_value.number_float == 0)
// round-trip IEEE 754 string->float->string, {
// string->double->string or string->long double->string; // special case for zero to get "0.0"/"-0.0"
// to be safe, we read this value from o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
// std::numeric_limits<number_float_t>::digits10 }
snprintf(buf, sizeof(buf), "%.*g", else
std::numeric_limits<double>::digits10, {
m_value.number_float); // Otherwise 6, 15 or 16 digits of precision allows
// round-trip IEEE 754 string->float->string,
// string->double->string or string->long double->string;
// to be safe, we read this value from
// std::numeric_limits<number_float_t>::digits10
std::stringstream ss;
ss.imbue(std::locale("C"));
ss << std::setprecision(std::numeric_limits<double>::digits10)
<< m_value.number_float;
o << ss.str();
}
} }
o << buf;
return; return;
} }

View file

@ -6114,24 +6114,26 @@ class basic_json
case value_t::number_float: case value_t::number_float:
{ {
// buffer size: precision (2^8-1 = 255) + other ('-.e-xxx' = 7) + null (1)
char buf[263];
int len;
// check if number was parsed from a string // check if number was parsed from a string
if (m_type.bits.parsed) if (m_type.bits.parsed)
{ {
// check if parsed number had an exponent given // check if parsed number had an exponent given
if (m_type.bits.has_exp) if (m_type.bits.has_exp)
{ {
// buffer size: precision (2^8-1 = 255) + other ('-.e-xxx' = 7) + null (1)
char buf[263];
int len;
// handle capitalization of the exponent // handle capitalization of the exponent
if (m_type.bits.exp_cap) if (m_type.bits.exp_cap)
{ {
len = snprintf(buf, sizeof(buf), "%.*E", m_type.bits.precision, m_value.number_float) + 1; len = snprintf(buf, sizeof(buf), "%.*E",
m_type.bits.precision, m_value.number_float) + 1;
} }
else else
{ {
len = snprintf(buf, sizeof(buf), "%.*e", m_type.bits.precision, m_value.number_float) + 1; len = snprintf(buf, sizeof(buf), "%.*e",
m_type.bits.precision, m_value.number_float) + 1;
} }
// remove '+' sign from the exponent if necessary // remove '+' sign from the exponent if necessary
@ -6152,40 +6154,40 @@ class basic_json
} }
} }
} }
o << buf;
} }
else else
{ {
// no exponent - output as a decimal // no exponent - output as a decimal
snprintf(buf, sizeof(buf), "%.*f", std::stringstream ss;
m_type.bits.precision, m_value.number_float); ss.imbue(std::locale("C")); // fix locale problems
ss << std::setprecision(m_type.bits.precision)
<< std::fixed << m_value.number_float;
o << ss.str();
} }
} }
else if (m_value.number_float == 0)
{
// special case for zero to get "0.0"/"-0.0"
if (std::signbit(m_value.number_float))
{
o << "-0.0";
}
else
{
o << "0.0";
}
return;
}
else else
{ {
// Otherwise 6, 15 or 16 digits of precision allows if (m_value.number_float == 0)
// round-trip IEEE 754 string->float->string, {
// string->double->string or string->long double->string; // special case for zero to get "0.0"/"-0.0"
// to be safe, we read this value from o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
// std::numeric_limits<number_float_t>::digits10 }
snprintf(buf, sizeof(buf), "%.*g", else
std::numeric_limits<double>::digits10, {
m_value.number_float); // Otherwise 6, 15 or 16 digits of precision allows
// round-trip IEEE 754 string->float->string,
// string->double->string or string->long double->string;
// to be safe, we read this value from
// std::numeric_limits<number_float_t>::digits10
std::stringstream ss;
ss.imbue(std::locale("C")); // fix locale problems
ss << std::setprecision(std::numeric_limits<double>::digits10)
<< m_value.number_float;
o << ss.str();
}
} }
o << buf;
return; return;
} }

View file

@ -12369,5 +12369,32 @@ TEST_CASE("regression tests")
j_long_double = 1.23e45L; j_long_double = 1.23e45L;
CHECK(j_long_double.get<long double>() == 1.23e45L); CHECK(j_long_double.get<long double>() == 1.23e45L);
} }
SECTION("issue #228 - double values are serialized with commas as decimal points")
{
json j1a = 23.42;
json j1b = json::parse("23.42");
json j2a = 2342e-2;
//issue #230
//json j2b = json::parse("2342e-2");
json j3a = 10E3;
json j3b = json::parse("10E3");
json j3c = json::parse("10e3");
std::locale::global(std::locale("de_DE"));
CHECK(j1a.dump() == "23.42");
CHECK(j1b.dump() == "23.42");
CHECK(j2a.dump() == "23.42");
//issue #230
//CHECK(j2b.dump() == "23.42");
CHECK(j3a.dump() == "10000");
CHECK(j3b.dump() == "1E04");
CHECK(j3c.dump() == "1e04");
}
} }