diff --git a/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_long_double_ru_RU.pass.cpp b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_long_double_ru_RU.pass.cpp --- a/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_long_double_ru_RU.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_long_double_ru_RU.pass.cpp @@ -9,14 +9,6 @@ // NetBSD does not support LC_MONETARY at the moment // XFAIL: netbsd -// Failure related to GLIBC's use of U00A0 as mon_thousands_sep -// and U002E as mon_decimal_point. -// TODO: U00A0 should be investigated. -// Possibly related to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=16006 -// XFAIL: linux - -// XFAIL: LIBCXX-WINDOWS-FIXME - // REQUIRES: locale.ru_RU.UTF-8 // @@ -55,7 +47,35 @@ explicit my_facetw(std::size_t refs = 0) : Fw(refs) {} }; + +// GLIBC 2.27 uses U+202F NARROW NO-BREAK SPACE as a thousands separator. +// FreeBSD and Windows use U+00A0 NO-BREAK SPACE. +static std::wstring convert_thousands_sep(std::wstring const& in) { +#if defined(TEST_HAS_GLIBC) || defined(__FreeBSD__) || defined(_WIN32) + std::wstring out; + unsigned I = 0; + bool seen_num_start = false; + bool seen_decimal = false; + for (; I < in.size(); ++I) { + seen_decimal |= in[I] == L','; + seen_num_start |= in[I] == L'-' || std::iswdigit(in[I]); + if (seen_decimal || !seen_num_start || in[I] != L' ') { + out.push_back(in[I]); + continue; + } + assert(in[I] == L' '); +#if defined(_WIN32) || defined(__FreeBSD__) + out.push_back(L'\u00A0'); +#else + out.push_back(L'\u202F'); +#endif + } + return out; +#else + return in; #endif +} +#endif // TEST_HAS_NO_WIDE_CHARACTERS int main(int, char**) { @@ -70,6 +90,11 @@ new std::moneypunct_byname(loc_name))); ios.imbue(std::locale(ios.getloc(), new std::moneypunct_byname(loc_name))); +#endif +#if defined(TEST_HAS_GLIBC) || defined(__FreeBSD__) || defined(_WIN32) + std::string symbol = "\xE2\x82\xBD"; +#else + std::string symbol = "\xD1\x80\xD1\x83\xD0\xB1""."; #endif { const my_facet f(1); @@ -130,7 +155,7 @@ assert(ex == -123456789); } { // zero, showbase - std::string v = "0,00 \xD1\x80\xD1\x83\xD0\xB1""."; + std::string v = "0,00 " + symbol; typedef cpp17_input_iterator I; long double ex; std::ios_base::iostate err = std::ios_base::goodbit; @@ -141,7 +166,7 @@ assert(ex == 0); } { // zero, showbase - std::string v = "0,00 \xD1\x80\xD1\x83\xD0\xB1""."; + std::string v = "0,00 " + symbol; std::showbase(ios); typedef cpp17_input_iterator I; long double ex; @@ -154,7 +179,7 @@ std::noshowbase(ios); } { // negative one, showbase - std::string v = "-0,01 \xD1\x80\xD1\x83\xD0\xB1""."; + std::string v = "-0,01 " + symbol; typedef cpp17_input_iterator I; long double ex; std::ios_base::iostate err = std::ios_base::goodbit; @@ -165,7 +190,7 @@ assert(ex == -1); } { // negative one, showbase - std::string v = "-0,01 \xD1\x80\xD1\x83\xD0\xB1""."; + std::string v = "-0,01 " + symbol; std::showbase(ios); typedef cpp17_input_iterator I; long double ex; @@ -178,7 +203,7 @@ std::noshowbase(ios); } { // positive, showbase - std::string v = "1 234 567,89 \xD1\x80\xD1\x83\xD0\xB1""."; + std::string v = "1 234 567,89 " + symbol; typedef cpp17_input_iterator I; long double ex; std::ios_base::iostate err = std::ios_base::goodbit; @@ -189,7 +214,7 @@ assert(ex == 123456789); } { // positive, showbase - std::string v = "1 234 567,89 \xD1\x80\xD1\x83\xD0\xB1""."; + std::string v = "1 234 567,89 " + symbol; std::showbase(ios); typedef cpp17_input_iterator I; long double ex; @@ -202,7 +227,7 @@ std::noshowbase(ios); } { // negative, showbase - std::string v = "-1 234 567,89 \xD1\x80\xD1\x83\xD0\xB1""."; + std::string v = "-1 234 567,89 " + symbol; std::showbase(ios); typedef cpp17_input_iterator I; long double ex; @@ -382,7 +407,7 @@ std::noshowbase(ios); } { // negative, showbase - std::string v = "-1 234 567,89 \xD1\x80\xD1\x83\xD0\xB1""."; + std::string v = "-1 234 567,89 " + symbol; std::showbase(ios); typedef cpp17_input_iterator I; long double ex; @@ -394,7 +419,7 @@ std::noshowbase(ios); } { // negative, showbase - std::string v = "-1 234 567,89 \xD1\x80\xD1\x83\xD0\xB1""."; + std::string v = "-1 234 567,89 " + symbol; typedef cpp17_input_iterator I; long double ex; std::ios_base::iostate err = std::ios_base::goodbit; @@ -406,6 +431,11 @@ } } #ifndef TEST_HAS_NO_WIDE_CHARACTERS +#if defined(TEST_HAS_GLIBC) || defined(__FreeBSD__) || defined(_WIN32) + std::wstring wsymbol = L"\x20BD"; +#else + std::wstring wsymbol = L"\x440\x443\x431""."; +#endif { const my_facetw f(1); // wchar_t, national @@ -432,7 +462,7 @@ assert(ex == -1); } { // positive - std::wstring v = L"1 234 567,89 "; + std::wstring v = convert_thousands_sep(L"1 234 567,89 "); typedef cpp17_input_iterator I; long double ex; std::ios_base::iostate err = std::ios_base::goodbit; @@ -443,7 +473,7 @@ assert(ex == 123456789); } { // negative - std::wstring v = L"-1 234 567,89 "; + std::wstring v = convert_thousands_sep(L"-1 234 567,89 "); typedef cpp17_input_iterator I; long double ex; std::ios_base::iostate err = std::ios_base::goodbit; @@ -465,7 +495,7 @@ assert(ex == -123456789); } { // zero, showbase - std::wstring v = L"0,00 \x440\x443\x431""."; + std::wstring v = L"0,00 " + wsymbol; typedef cpp17_input_iterator I; long double ex; std::ios_base::iostate err = std::ios_base::goodbit; @@ -476,7 +506,7 @@ assert(ex == 0); } { // zero, showbase - std::wstring v = L"0,00 \x440\x443\x431""."; + std::wstring v = L"0,00 " + wsymbol; std::showbase(ios); typedef cpp17_input_iterator I; long double ex; @@ -489,7 +519,7 @@ std::noshowbase(ios); } { // negative one, showbase - std::wstring v = L"-0,01 \x440\x443\x431""."; + std::wstring v = L"-0,01 " + wsymbol; typedef cpp17_input_iterator I; long double ex; std::ios_base::iostate err = std::ios_base::goodbit; @@ -500,7 +530,7 @@ assert(ex == -1); } { // negative one, showbase - std::wstring v = L"-0,01 \x440\x443\x431""."; + std::wstring v = L"-0,01 " + wsymbol; std::showbase(ios); typedef cpp17_input_iterator I; long double ex; @@ -513,7 +543,7 @@ std::noshowbase(ios); } { // positive, showbase - std::wstring v = L"1 234 567,89 \x440\x443\x431""."; + std::wstring v = convert_thousands_sep(L"1 234 567,89 ") + wsymbol; typedef cpp17_input_iterator I; long double ex; std::ios_base::iostate err = std::ios_base::goodbit; @@ -524,7 +554,7 @@ assert(ex == 123456789); } { // positive, showbase - std::wstring v = L"1 234 567,89 \x440\x443\x431""."; + std::wstring v = convert_thousands_sep(L"1 234 567,89 ") + wsymbol; std::showbase(ios); typedef cpp17_input_iterator I; long double ex; @@ -537,7 +567,7 @@ std::noshowbase(ios); } { // negative, showbase - std::wstring v = L"-1 234 567,89 \x440\x443\x431""."; + std::wstring v = convert_thousands_sep(L"-1 234 567,89 ") + wsymbol; std::showbase(ios); typedef cpp17_input_iterator I; long double ex; @@ -550,7 +580,7 @@ std::noshowbase(ios); } { // negative, showbase - std::wstring v = L"-1 234 567,89 RUB"; + std::wstring v = convert_thousands_sep(L"-1 234 567,89 RUB"); std::showbase(ios); typedef cpp17_input_iterator I; long double ex; @@ -562,7 +592,7 @@ std::noshowbase(ios); } { // negative, showbase - std::wstring v = L"-1 234 567,89 RUB"; + std::wstring v = convert_thousands_sep(L"-1 234 567,89 RUB"); typedef cpp17_input_iterator I; long double ex; std::ios_base::iostate err = std::ios_base::goodbit; @@ -599,7 +629,7 @@ assert(ex == -1); } { // positive - std::wstring v = L"1 234 567,89 "; + std::wstring v = convert_thousands_sep(L"1 234 567,89 "); typedef cpp17_input_iterator I; long double ex; std::ios_base::iostate err = std::ios_base::goodbit; @@ -610,7 +640,7 @@ assert(ex == 123456789); } { // negative - std::wstring v = L"-1 234 567,89 "; + std::wstring v = convert_thousands_sep(L"-1 234 567,89 "); typedef cpp17_input_iterator I; long double ex; std::ios_base::iostate err = std::ios_base::goodbit; @@ -680,7 +710,7 @@ std::noshowbase(ios); } { // positive, showbase - std::wstring v = L"1 234 567,89 RUB"; + std::wstring v = convert_thousands_sep(L"1 234 567,89 RUB"); typedef cpp17_input_iterator I; long double ex; std::ios_base::iostate err = std::ios_base::goodbit; @@ -691,7 +721,7 @@ assert(ex == 123456789); } { // positive, showbase - std::wstring v = L"1 234 567,89 RUB"; + std::wstring v = convert_thousands_sep(L"1 234 567,89 RUB"); std::showbase(ios); typedef cpp17_input_iterator I; long double ex; @@ -704,7 +734,7 @@ std::noshowbase(ios); } { // negative, showbase - std::wstring v = L"-1 234 567,89 RUB"; + std::wstring v = convert_thousands_sep(L"-1 234 567,89 RUB"); std::showbase(ios); typedef cpp17_input_iterator I; long double ex; @@ -717,7 +747,7 @@ std::noshowbase(ios); } { // negative, showbase - std::wstring v = L"-1 234 567,89 \x440\x443\x431""."; + std::wstring v = convert_thousands_sep(L"-1 234 567,89 ") + wsymbol; std::showbase(ios); typedef cpp17_input_iterator I; long double ex; @@ -729,7 +759,7 @@ std::noshowbase(ios); } { // negative, showbase - std::wstring v = L"-1 234 567,89 \x440\x443\x431""."; + std::wstring v = convert_thousands_sep(L"-1 234 567,89 ") + wsymbol; typedef cpp17_input_iterator I; long double ex; std::ios_base::iostate err = std::ios_base::goodbit; diff --git a/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_long_double_ru_RU.pass.cpp b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_long_double_ru_RU.pass.cpp --- a/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_long_double_ru_RU.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_long_double_ru_RU.pass.cpp @@ -9,14 +9,6 @@ // NetBSD does not support LC_MONETARY at the moment // XFAIL: netbsd -// Failure related to GLIBC's use of U00A0 as mon_thousands_sep -// and U002E as mon_decimal_point. -// TODO: U00A0 should be investigated. -// Possibly related to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=16006 -// XFAIL: linux - -// XFAIL: LIBCXX-WINDOWS-FIXME - // REQUIRES: locale.ru_RU.UTF-8 // @@ -55,7 +47,35 @@ explicit my_facetw(std::size_t refs = 0) : Fw(refs) {} }; + +// GLIBC 2.27 uses U+202F NARROW NO-BREAK SPACE as a thousands separator. +// FreeBSD and Windows use U+00A0 NO-BREAK SPACE. +static std::wstring convert_thousands_sep(std::wstring const& in) { +#if defined(TEST_HAS_GLIBC) || defined(__FreeBSD__) || defined(_WIN32) + std::wstring out; + unsigned I = 0; + bool seen_num_start = false; + bool seen_decimal = false; + for (; I < in.size(); ++I) { + seen_decimal |= in[I] == L','; + seen_num_start |= in[I] == L'-' || std::iswdigit(in[I]); + if (seen_decimal || !seen_num_start || in[I] != L' ') { + out.push_back(in[I]); + continue; + } + assert(in[I] == L' '); +#if defined(_WIN32) || defined(__FreeBSD__) + out.push_back(L'\u00A0'); +#else + out.push_back(L'\u202F'); +#endif + } + return out; +#else + return in; #endif +} +#endif // TEST_HAS_NO_WIDE_CHARACTERS int main(int, char**) { @@ -72,6 +92,11 @@ new std::moneypunct_byname(loc_name))); #endif { +#if defined(TEST_HAS_GLIBC) || defined(__FreeBSD__) || defined(_WIN32) + std::string symbol = "\xE2\x82\xBD"; +#else + std::string symbol = "\xD1\x80\xD1\x83\xD0\xB1""."; +#endif const my_facet f(1); // char, national { // zero @@ -108,7 +133,7 @@ char str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), false, ios, '*', v); std::string ex(str, iter.base()); - assert(ex == "0,00 \xD1\x80\xD1\x83\xD0\xB1""."); + assert(ex == "0,00 " + symbol); } { // negative one, showbase long double v = -1; @@ -116,7 +141,7 @@ char str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), false, ios, '*', v); std::string ex(str, iter.base()); - assert(ex == "-0,01 \xD1\x80\xD1\x83\xD0\xB1""."); + assert(ex == "-0,01 " + symbol); } { // positive, showbase long double v = 123456789; @@ -124,7 +149,7 @@ char str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), false, ios, '*', v); std::string ex(str, iter.base()); - assert(ex == "1 234 567,89 \xD1\x80\xD1\x83\xD0\xB1""."); + assert(ex == "1 234 567,89 " + symbol); } { // negative, showbase long double v = -123456789; @@ -132,39 +157,39 @@ char str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), false, ios, '*', v); std::string ex(str, iter.base()); - assert(ex == "-1 234 567,89 \xD1\x80\xD1\x83\xD0\xB1""."); + assert(ex == "-1 234 567,89 " + symbol); } { // negative, showbase, left long double v = -123456789; std::showbase(ios); - ios.width(20); + ios.width(15); std::left(ios); char str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), false, ios, ' ', v); std::string ex(str, iter.base()); - assert(ex == "-1 234 567,89 \xD1\x80\xD1\x83\xD0\xB1""."); + assert(ex == "-1 234 567,89 " + symbol); assert(ios.width() == 0); } { // negative, showbase, internal long double v = -123456789; std::showbase(ios); - ios.width(20); + ios.width(15); std::internal(ios); char str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), false, ios, ' ', v); std::string ex(str, iter.base()); - assert(ex == "-1 234 567,89 \xD1\x80\xD1\x83\xD0\xB1""."); + assert(ex == "-1 234 567,89 " + symbol); assert(ios.width() == 0); } { // negative, showbase, right long double v = -123456789; std::showbase(ios); - ios.width(20); + ios.width(15); std::right(ios); char str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), false, ios, ' ', v); std::string ex(str, iter.base()); - assert(ex == "-1 234 567,89 \xD1\x80\xD1\x83\xD0\xB1""."); + assert(ex == "-1 234 567,89 " + symbol); assert(ios.width() == 0); } @@ -267,6 +292,11 @@ } #ifndef TEST_HAS_NO_WIDE_CHARACTERS { +#if defined(TEST_HAS_GLIBC) || defined(__FreeBSD__) || defined(_WIN32) + std::wstring symbol = L"\x20BD"; +#else + std::wstring symbol = L"\x440\x443\x431""."; +#endif const my_facetw f(1); // wchar_t, national std::noshowbase(ios); @@ -290,14 +320,14 @@ wchar_t str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), false, ios, '*', v); std::wstring ex(str, iter.base()); - assert(ex == L"1 234 567,89"); + assert(ex == convert_thousands_sep(L"1 234 567,89")); } { // negative long double v = -123456789; wchar_t str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), false, ios, '*', v); std::wstring ex(str, iter.base()); - assert(ex == L"-1 234 567,89"); + assert(ex == convert_thousands_sep(L"-1 234 567,89")); } { // zero, showbase long double v = 0; @@ -305,7 +335,7 @@ wchar_t str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), false, ios, '*', v); std::wstring ex(str, iter.base()); - assert(ex == L"0,00 \x440\x443\x431""."); + assert(ex == L"0,00 " + symbol); } { // negative one, showbase long double v = -1; @@ -313,7 +343,7 @@ wchar_t str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), false, ios, '*', v); std::wstring ex(str, iter.base()); - assert(ex == L"-0,01 \x440\x443\x431""."); + assert(ex == L"-0,01 " + symbol); } { // positive, showbase long double v = 123456789; @@ -321,7 +351,7 @@ wchar_t str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), false, ios, '*', v); std::wstring ex(str, iter.base()); - assert(ex == L"1 234 567,89 \x440\x443\x431""."); + assert(ex == convert_thousands_sep(L"1 234 567,89 ") + symbol); } { // negative, showbase long double v = -123456789; @@ -329,39 +359,39 @@ wchar_t str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), false, ios, '*', v); std::wstring ex(str, iter.base()); - assert(ex == L"-1 234 567,89 \x440\x443\x431""."); + assert(ex == convert_thousands_sep(L"-1 234 567,89 ") + symbol); } { // negative, showbase, left long double v = -123456789; std::showbase(ios); - ios.width(20); + ios.width(15); std::left(ios); wchar_t str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), false, ios, ' ', v); std::wstring ex(str, iter.base()); - assert(ex == L"-1 234 567,89 \x440\x443\x431"". "); + assert(ex == convert_thousands_sep(L"-1 234 567,89 ") + symbol); assert(ios.width() == 0); } { // negative, showbase, internal long double v = -123456789; std::showbase(ios); - ios.width(20); + ios.width(15); std::internal(ios); wchar_t str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), false, ios, ' ', v); std::wstring ex(str, iter.base()); - assert(ex == L"-1 234 567,89 \x440\x443\x431""."); + assert(ex == convert_thousands_sep(L"-1 234 567,89 ") + symbol); assert(ios.width() == 0); } { // negative, showbase, right long double v = -123456789; std::showbase(ios); - ios.width(20); + ios.width(15); std::right(ios); wchar_t str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), false, ios, ' ', v); std::wstring ex(str, iter.base()); - assert(ex == L" -1 234 567,89 \x440\x443\x431""."); + assert(ex == convert_thousands_sep(L"-1 234 567,89 ") + symbol); assert(ios.width() == 0); } @@ -387,14 +417,14 @@ wchar_t str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), true, ios, '*', v); std::wstring ex(str, iter.base()); - assert(ex == L"1 234 567,89"); + assert(ex == convert_thousands_sep(L"1 234 567,89")); } { // negative long double v = -123456789; wchar_t str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), true, ios, '*', v); std::wstring ex(str, iter.base()); - assert(ex == L"-1 234 567,89"); + assert(ex == convert_thousands_sep(L"-1 234 567,89")); } { // zero, showbase long double v = 0; @@ -418,7 +448,7 @@ wchar_t str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), true, ios, '*', v); std::wstring ex(str, iter.base()); - assert(ex == L"1 234 567,89 RUB"); + assert(ex == convert_thousands_sep(L"1 234 567,89 RUB")); } { // negative, showbase long double v = -123456789; @@ -426,7 +456,7 @@ wchar_t str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), true, ios, '*', v); std::wstring ex(str, iter.base()); - assert(ex == L"-1 234 567,89 RUB"); + assert(ex == convert_thousands_sep(L"-1 234 567,89 RUB")); } { // negative, showbase, left long double v = -123456789; @@ -436,7 +466,7 @@ wchar_t str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), true, ios, ' ', v); std::wstring ex(str, iter.base()); - assert(ex == L"-1 234 567,89 RUB "); + assert(ex == convert_thousands_sep(L"-1 234 567,89 RUB ")); assert(ios.width() == 0); } { // negative, showbase, internal @@ -447,7 +477,7 @@ wchar_t str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), true, ios, ' ', v); std::wstring ex(str, iter.base()); - assert(ex == L"-1 234 567,89 RUB"); + assert(ex == convert_thousands_sep(L"-1 234 567,89 RUB")); assert(ios.width() == 0); } { // negative, showbase, right @@ -458,7 +488,7 @@ wchar_t str[100]; cpp17_output_iterator iter = f.put(cpp17_output_iterator(str), true, ios, ' ', v); std::wstring ex(str, iter.base()); - assert(ex == L" -1 234 567,89 RUB"); + assert(ex == convert_thousands_sep(L" -1 234 567,89 RUB")); assert(ios.width() == 0); } }