Replace a multibyte decimal point in dump() of a long double (#5993)

The snprintf path of dump_float(), used when number_float_t is neither
IEEE single nor double (a long double on x86-64 and aarch64 Linux), read
localeconv()->decimal_point and ->thousands_sep as single chars. Under a
locale with a multibyte decimal point (glibc's ps_AF: U+066B), it removed
the first byte as a "thousands separator" and left the second one in the
output, so 1.5L dumped as "1\xab5.0".

Find the whole decimal point with std::search and replace it with '.',
as the parser already does since #5660. Drop the thousands-separator
removal: %g never groups digits.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann committed 2026-11-01 22:48:42 +01:00
1 parent b2674a4a2f
commit 3720e4b3aa
3 files changed
+46 -40

No files matched your search

+8
View File
@@ -397,6 +397,14 @@ TEST_CASE("locale with a multi-byte decimal point")
// a value the locale-independent paths convert is not affected
CHECK(json::parse("12.5") == 12.5);
// dump() of a long double that takes the snprintf path replaces the
// whole decimal point, not only its first byte (#5993)
CHECK(long_double_json(1.5L).dump() == "1.5");
CHECK(long_double_json(2.0L).dump() == "2.0");
CHECK(long_double_json(-0.25L).dump() == "-0.25");
CHECK(long_double_json::parse(long_double_json(1.5e-7L).dump()) == long_double_json(1.5e-7L));
CHECK(long_double_json::parse(ld.dump()) == expected_long_double);
}
if (!tested)
{