diff --git a/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_long_double_fr_FR.pass.cpp b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_long_double_fr_FR.pass.cpp --- a/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_long_double_fr_FR.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_long_double_fr_FR.pass.cpp @@ -28,6 +28,7 @@ #include #include "test_iterators.h" +#include "locale_helpers.h" #include "platform_support.h" // locale name macros #include "test_macros.h" @@ -52,36 +53,8 @@ : Fw(refs) {} }; -// GLIBC 2.27 and newer use U+202F NARROW NO-BREAK SPACE as a thousands separator. -// This function converts the spaces in string inputs to U+202F if need -// be. FreeBSD's locale data also uses U+202F, since 2018. -// Windows uses U+00A0 NO-BREAK SPACE. static std::wstring convert_thousands_sep(std::wstring const& in) { -#if defined(_CS_GNU_LIBC_VERSION) || defined(__FreeBSD__) || defined(_WIN32) -#if defined(_CS_GNU_LIBC_VERSION) - if (glibc_version_less_than("2.27")) - return in; -#endif - std::wstring out; - unsigned I = 0; - bool seen_decimal = false; - for (; I < in.size(); ++I) { - if (seen_decimal || in[I] != L' ') { - seen_decimal |= in[I] == L','; - out.push_back(in[I]); - continue; - } - assert(in[I] == L' '); -#if defined(_WIN32) - out.push_back(L'\u00A0'); -#else - out.push_back(L'\u202F'); -#endif - } - return out; -#else - return in; -#endif + return LocaleHelpers::convert_thousands_sep_fr_FR(in); } #endif // TEST_HAS_NO_WIDE_CHARACTERS 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 // @@ -33,6 +25,7 @@ #include "test_macros.h" #include "test_iterators.h" +#include "locale_helpers.h" #include "platform_support.h" // locale name macros typedef std::money_get > Fn; @@ -55,7 +48,11 @@ explicit my_facetw(std::size_t refs = 0) : Fw(refs) {} }; -#endif + +static std::wstring convert_thousands_sep(std::wstring const& in) { + return LocaleHelpers::convert_thousands_sep_ru_RU(in); +} +#endif // TEST_HAS_NO_WIDE_CHARACTERS int main(int, char**) { @@ -71,6 +68,7 @@ ios.imbue(std::locale(ios.getloc(), new std::moneypunct_byname(loc_name))); #endif + std::string symbol(LocaleHelpers::currency_symbol_ru_RU()); { const my_facet f(1); // char, national @@ -130,7 +128,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 +139,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 +152,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 +163,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 +176,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 +187,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 +200,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 +380,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 +392,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 +404,7 @@ } } #ifndef TEST_HAS_NO_WIDE_CHARACTERS + std::wstring wsymbol(LocaleHelpers::currency_symbol_ru_RU()); { const my_facetw f(1); // wchar_t, national @@ -432,7 +431,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 +442,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 +464,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 +475,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 +488,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 +499,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 +512,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 +523,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 +536,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 +549,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 +561,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 +598,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 +609,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 +679,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 +690,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 +703,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 +716,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 +728,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_fr_FR.pass.cpp b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_long_double_fr_FR.pass.cpp --- a/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_long_double_fr_FR.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_long_double_fr_FR.pass.cpp @@ -28,6 +28,7 @@ #include #include "test_iterators.h" +#include "locale_helpers.h" #include "platform_support.h" // locale name macros #include "test_macros.h" @@ -52,38 +53,8 @@ : Fw(refs) {} }; -// GLIBC 2.27 and newer use U+202F NARROW NO-BREAK SPACE as a thousands separator. -// This function converts the spaces in string inputs to U+202F if need -// be. FreeBSD's locale data also uses U+202F, since 2018. -// Windows uses U+00A0 NO-BREAK SPACE. static std::wstring convert_thousands_sep(std::wstring const& in) { -#if defined(_CS_GNU_LIBC_VERSION) || defined(__FreeBSD__) || defined(_WIN32) -#if defined(_CS_GNU_LIBC_VERSION) - if (glibc_version_less_than("2.27")) - return in; -#endif - 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] == '-' || 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) - out.push_back(L'\u00A0'); -#else - out.push_back(L'\u202F'); -#endif - } - return out; -#else - return in; -#endif + return LocaleHelpers::convert_thousands_sep_fr_FR(in); } #endif // TEST_HAS_NO_WIDE_CHARACTERS 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 // @@ -33,6 +25,7 @@ #include "test_macros.h" #include "test_iterators.h" +#include "locale_helpers.h" #include "platform_support.h" // locale name macros typedef std::money_put > Fn; @@ -55,7 +48,11 @@ explicit my_facetw(std::size_t refs = 0) : Fw(refs) {} }; -#endif + +static std::wstring convert_thousands_sep(std::wstring const& in) { + return LocaleHelpers::convert_thousands_sep_ru_RU(in); +} +#endif // TEST_HAS_NO_WIDE_CHARACTERS int main(int, char**) { @@ -72,6 +69,7 @@ new std::moneypunct_byname(loc_name))); #endif { + std::string symbol(LocaleHelpers::currency_symbol_ru_RU()); const my_facet f(1); // char, national { // zero @@ -108,7 +106,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 +114,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 +122,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 +130,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 +265,7 @@ } #ifndef TEST_HAS_NO_WIDE_CHARACTERS { + std::wstring symbol(LocaleHelpers::currency_symbol_ru_RU()); const my_facetw f(1); // wchar_t, national std::noshowbase(ios); @@ -290,14 +289,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 +304,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 +312,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 +320,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 +328,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 +386,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 +417,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 +425,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 +435,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 +446,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 +457,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); } } diff --git a/libcxx/test/std/localization/locale.categories/category.monetary/locale.moneypunct.byname/curr_symbol.pass.cpp b/libcxx/test/std/localization/locale.categories/category.monetary/locale.moneypunct.byname/curr_symbol.pass.cpp --- a/libcxx/test/std/localization/locale.categories/category.monetary/locale.moneypunct.byname/curr_symbol.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.monetary/locale.moneypunct.byname/curr_symbol.pass.cpp @@ -25,6 +25,7 @@ #include #include "test_macros.h" +#include "locale_helpers.h" #include "platform_support.h" // locale name macros class Fnf @@ -140,19 +141,7 @@ { Fnf f(LOCALE_ru_RU_UTF_8, 1); -#if defined(_CS_GNU_LIBC_VERSION) - // GLIBC <= 2.23 uses currency_symbol="" - // GLIBC >= 2.24 uses currency_symbol="" - // See also: http://www.fileformat.info/info/unicode/char/20bd/index.htm - if (!glibc_version_less_than("2.24")) - assert(f.curr_symbol() == " \xE2\x82\xBD"); // \u20BD - else - assert(f.curr_symbol() == " \xD1\x80\xD1\x83\xD0\xB1"); // \u0440\u0443\u0431 -#elif defined(_WIN32) || defined(__FreeBSD__) - assert(f.curr_symbol() == " \xE2\x82\xBD"); // \u20BD -#else - assert(f.curr_symbol() == " \xD1\x80\xD1\x83\xD0\xB1."); // \u0440\u0443\u0431. -#endif + assert(f.curr_symbol() == " " + static_cast(LocaleHelpers::currency_symbol_ru_RU())); } { Fnt f(LOCALE_ru_RU_UTF_8, 1); @@ -161,16 +150,7 @@ #ifndef TEST_HAS_NO_WIDE_CHARACTERS { Fwf f(LOCALE_ru_RU_UTF_8, 1); -#if defined(_CS_GNU_LIBC_VERSION) - if (!glibc_version_less_than("2.24")) - assert(f.curr_symbol() == L" \u20BD"); - else - assert(f.curr_symbol() == L" \u0440\u0443\u0431"); -#elif defined(_WIN32) || defined(__FreeBSD__) - assert(f.curr_symbol() == L" \u20BD"); -#else - assert(f.curr_symbol() == L" \u0440\u0443\u0431."); -#endif + assert(f.curr_symbol() == L" " + static_cast(LocaleHelpers::currency_symbol_ru_RU())); } { diff --git a/libcxx/test/support/locale_helpers.h b/libcxx/test/support/locale_helpers.h new file mode 100644 --- /dev/null +++ b/libcxx/test/support/locale_helpers.h @@ -0,0 +1,91 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef LIBCXX_TEST_SUPPORT_LOCALE_HELPERS_H +#define LIBCXX_TEST_SUPPORT_LOCALE_HELPERS_H + +#include +#include "platform_support.h" +#include "test_macros.h" +#include "make_string.h" + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + +#include + +#endif // TEST_HAS_NO_WIDE_CHARACTERS + +namespace LocaleHelpers { + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + +std::wstring convert_thousands_sep(std::wstring const& in, wchar_t sep) { + std::wstring out; + bool seen_num_start = false; + bool seen_decimal = false; + for (unsigned i = 0; 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' '); + out.push_back(sep); + } + return out; +} + +// GLIBC 2.27 and newer use U+202F NARROW NO-BREAK SPACE as a thousands separator. +// This function converts the spaces in string inputs to U+202F if need +// be. FreeBSD's locale data also uses U+202F, since 2018. +// Windows uses U+00A0 NO-BREAK SPACE. +std::wstring convert_thousands_sep_fr_FR(std::wstring const& in) { +#if defined(_CS_GNU_LIBC_VERSION) + if (glibc_version_less_than("2.27")) + return in; + else + return convert_thousands_sep(in, L'\u202F'); +#elif defined(__FreeBSD__) + return convert_thousands_sep(in, L'\u202F'); +#elif defined(_WIN32) + return convert_thousands_sep(in, L'\u00A0'); +#else + return in; +#endif +} + +// GLIBC 2.27 uses U+202F NARROW NO-BREAK SPACE as a thousands separator. +// FreeBSD and Windows use U+00A0 NO-BREAK SPACE. +std::wstring convert_thousands_sep_ru_RU(std::wstring const& in) { +#if defined(TEST_HAS_GLIBC) + return convert_thousands_sep(in, L'\u202F'); +#elif defined(__FreeBSD__) || defined(_WIN32) + return convert_thousands_sep(in, L'\u00A0'); +#else + return in; +#endif +} + +#endif // TEST_HAS_NO_WIDE_CHARACTERS + +MultiStringType currency_symbol_ru_RU() { +#if defined(_CS_GNU_LIBC_VERSION) + if (glibc_version_less_than("2.24")) + return MKSTR("\u0440\u0443\u0431"); + else + return MKSTR("\u20BD"); // U+20BD RUBLE SIGN +#elif defined(_WIN32) || defined(__FreeBSD__) + return MKSTR("\u20BD"); // U+20BD RUBLE SIGN +#else + return MKSTR("\u0440\u0443\u0431."); +#endif +} + +} // namespace LocaleHelpers + +#endif // LIBCXX_TEST_SUPPORT_LOCALE_HELPERS_H