[libcxx-commits] [libcxx] df1e43c - [libcxx] [test] Fix get/put long_double_ru_RU on Glibc, FreeBSD and Windows

Martin Storsjö via libcxx-commits libcxx-commits at lists.llvm.org
Thu Mar 3 03:31:57 PST 2022


Author: Martin Storsjö
Date: 2022-03-03T13:30:59+02:00
New Revision: df1e43c496b43e998f66c610b0e15a0951f316b3

URL: https://github.com/llvm/llvm-project/commit/df1e43c496b43e998f66c610b0e15a0951f316b3
DIFF: https://github.com/llvm/llvm-project/commit/df1e43c496b43e998f66c610b0e15a0951f316b3.diff

LOG: [libcxx] [test] Fix get/put long_double_ru_RU on Glibc, FreeBSD and Windows

Note, reducing ios.width() in put_long_double instead of using variable
padding, when using a variable width symbol. Some of those tests didn't
actually trigger any padding in the existing form, with a longer
currency symbol; reduce the width so there's no actual padding with the
slightly shorter currency symbol either.

The tests for the international currency symbol use the same amount of
padding on all platforms, so they still exercise the padding properly.

Differential Revision: https://reviews.llvm.org/D120317

Added: 
    libcxx/test/support/locale_helpers.h

Modified: 
    libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_long_double_fr_FR.pass.cpp
    libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_long_double_ru_RU.pass.cpp
    libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_long_double_fr_FR.pass.cpp
    libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_long_double_ru_RU.pass.cpp
    libcxx/test/std/localization/locale.categories/category.monetary/locale.moneypunct.byname/curr_symbol.pass.cpp

Removed: 
    


################################################################################
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
index 16fc12feac62b..ffc57e6236d8f 100644
--- 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 <cassert>
 #include "test_iterators.h"
 
+#include "locale_helpers.h"
 #include "platform_support.h" // locale name macros
 #include "test_macros.h"
 
@@ -52,36 +53,8 @@ class my_facetw
         : 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
index f4644ab2df242..a72d0c4d210ee 100644
--- 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
 
 // <locale>
@@ -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<char, cpp17_input_iterator<const char*> > Fn;
@@ -55,7 +48,11 @@ class my_facetw
     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 @@ int main(int, char**)
     ios.imbue(std::locale(ios.getloc(),
                           new std::moneypunct_byname<wchar_t, true>(loc_name)));
 #endif
+    std::string symbol(LocaleHelpers::currency_symbol_ru_RU());
     {
         const my_facet f(1);
         // char, national
@@ -130,7 +128,7 @@ int main(int, char**)
             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<const char*> I;
             long double ex;
             std::ios_base::iostate err = std::ios_base::goodbit;
@@ -141,7 +139,7 @@ int main(int, char**)
             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<const char*> I;
             long double ex;
@@ -154,7 +152,7 @@ int main(int, char**)
             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<const char*> I;
             long double ex;
             std::ios_base::iostate err = std::ios_base::goodbit;
@@ -165,7 +163,7 @@ int main(int, char**)
             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<const char*> I;
             long double ex;
@@ -178,7 +176,7 @@ int main(int, char**)
             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<const char*> I;
             long double ex;
             std::ios_base::iostate err = std::ios_base::goodbit;
@@ -189,7 +187,7 @@ int main(int, char**)
             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<const char*> I;
             long double ex;
@@ -202,7 +200,7 @@ int main(int, char**)
             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<const char*> I;
             long double ex;
@@ -382,7 +380,7 @@ int main(int, char**)
             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<const char*> I;
             long double ex;
@@ -394,7 +392,7 @@ int main(int, char**)
             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<const char*> I;
             long double ex;
             std::ios_base::iostate err = std::ios_base::goodbit;
@@ -406,6 +404,7 @@ int main(int, char**)
         }
     }
 #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 @@ int main(int, char**)
             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<const wchar_t*> I;
             long double ex;
             std::ios_base::iostate err = std::ios_base::goodbit;
@@ -443,7 +442,7 @@ int main(int, char**)
             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<const wchar_t*> I;
             long double ex;
             std::ios_base::iostate err = std::ios_base::goodbit;
@@ -465,7 +464,7 @@ int main(int, char**)
             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<const wchar_t*> I;
             long double ex;
             std::ios_base::iostate err = std::ios_base::goodbit;
@@ -476,7 +475,7 @@ int main(int, char**)
             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<const wchar_t*> I;
             long double ex;
@@ -489,7 +488,7 @@ int main(int, char**)
             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<const wchar_t*> I;
             long double ex;
             std::ios_base::iostate err = std::ios_base::goodbit;
@@ -500,7 +499,7 @@ int main(int, char**)
             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<const wchar_t*> I;
             long double ex;
@@ -513,7 +512,7 @@ int main(int, char**)
             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<const wchar_t*> I;
             long double ex;
             std::ios_base::iostate err = std::ios_base::goodbit;
@@ -524,7 +523,7 @@ int main(int, char**)
             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<const wchar_t*> I;
             long double ex;
@@ -537,7 +536,7 @@ int main(int, char**)
             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<const wchar_t*> I;
             long double ex;
@@ -550,7 +549,7 @@ int main(int, char**)
             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<const wchar_t*> I;
             long double ex;
@@ -562,7 +561,7 @@ int main(int, char**)
             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<const wchar_t*> I;
             long double ex;
             std::ios_base::iostate err = std::ios_base::goodbit;
@@ -599,7 +598,7 @@ int main(int, char**)
             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<const wchar_t*> I;
             long double ex;
             std::ios_base::iostate err = std::ios_base::goodbit;
@@ -610,7 +609,7 @@ int main(int, char**)
             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<const wchar_t*> I;
             long double ex;
             std::ios_base::iostate err = std::ios_base::goodbit;
@@ -680,7 +679,7 @@ int main(int, char**)
             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<const wchar_t*> I;
             long double ex;
             std::ios_base::iostate err = std::ios_base::goodbit;
@@ -691,7 +690,7 @@ int main(int, char**)
             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<const wchar_t*> I;
             long double ex;
@@ -704,7 +703,7 @@ int main(int, char**)
             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<const wchar_t*> I;
             long double ex;
@@ -717,7 +716,7 @@ int main(int, char**)
             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<const wchar_t*> I;
             long double ex;
@@ -729,7 +728,7 @@ int main(int, char**)
             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<const wchar_t*> 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
index becb46e091590..79241674d935e 100644
--- 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 <cassert>
 #include "test_iterators.h"
 
+#include "locale_helpers.h"
 #include "platform_support.h" // locale name macros
 #include "test_macros.h"
 
@@ -52,38 +53,8 @@ class my_facetw
         : 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
index 975b9ed156486..b980df12a18a1 100644
--- 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
 
 // <locale>
@@ -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<char, cpp17_output_iterator<char*> > Fn;
@@ -55,7 +48,11 @@ class my_facetw
     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 @@ int main(int, char**)
                           new std::moneypunct_byname<wchar_t, true>(loc_name)));
 #endif
 {
+    std::string symbol(LocaleHelpers::currency_symbol_ru_RU());
     const my_facet f(1);
     // char, national
     {   // zero
@@ -108,7 +106,7 @@ int main(int, char**)
         char str[100];
         cpp17_output_iterator<char*> iter = f.put(cpp17_output_iterator<char*>(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 @@ int main(int, char**)
         char str[100];
         cpp17_output_iterator<char*> iter = f.put(cpp17_output_iterator<char*>(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 @@ int main(int, char**)
         char str[100];
         cpp17_output_iterator<char*> iter = f.put(cpp17_output_iterator<char*>(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 @@ int main(int, char**)
         char str[100];
         cpp17_output_iterator<char*> iter = f.put(cpp17_output_iterator<char*>(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<char*> iter = f.put(cpp17_output_iterator<char*>(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<char*> iter = f.put(cpp17_output_iterator<char*>(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<char*> iter = f.put(cpp17_output_iterator<char*>(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 @@ int main(int, char**)
 }
 #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 @@ int main(int, char**)
         wchar_t str[100];
         cpp17_output_iterator<wchar_t*> iter = f.put(cpp17_output_iterator<wchar_t*>(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<wchar_t*> iter = f.put(cpp17_output_iterator<wchar_t*>(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 @@ int main(int, char**)
         wchar_t str[100];
         cpp17_output_iterator<wchar_t*> iter = f.put(cpp17_output_iterator<wchar_t*>(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 @@ int main(int, char**)
         wchar_t str[100];
         cpp17_output_iterator<wchar_t*> iter = f.put(cpp17_output_iterator<wchar_t*>(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 @@ int main(int, char**)
         wchar_t str[100];
         cpp17_output_iterator<wchar_t*> iter = f.put(cpp17_output_iterator<wchar_t*>(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 @@ int main(int, char**)
         wchar_t str[100];
         cpp17_output_iterator<wchar_t*> iter = f.put(cpp17_output_iterator<wchar_t*>(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<wchar_t*> iter = f.put(cpp17_output_iterator<wchar_t*>(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<wchar_t*> iter = f.put(cpp17_output_iterator<wchar_t*>(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<wchar_t*> iter = f.put(cpp17_output_iterator<wchar_t*>(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 @@ int main(int, char**)
         wchar_t str[100];
         cpp17_output_iterator<wchar_t*> iter = f.put(cpp17_output_iterator<wchar_t*>(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<wchar_t*> iter = f.put(cpp17_output_iterator<wchar_t*>(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 @@ int main(int, char**)
         wchar_t str[100];
         cpp17_output_iterator<wchar_t*> iter = f.put(cpp17_output_iterator<wchar_t*>(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 @@ int main(int, char**)
         wchar_t str[100];
         cpp17_output_iterator<wchar_t*> iter = f.put(cpp17_output_iterator<wchar_t*>(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 @@ int main(int, char**)
         wchar_t str[100];
         cpp17_output_iterator<wchar_t*> iter = f.put(cpp17_output_iterator<wchar_t*>(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 @@ int main(int, char**)
         wchar_t str[100];
         cpp17_output_iterator<wchar_t*> iter = f.put(cpp17_output_iterator<wchar_t*>(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 @@ int main(int, char**)
         wchar_t str[100];
         cpp17_output_iterator<wchar_t*> iter = f.put(cpp17_output_iterator<wchar_t*>(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
index 407a08884c3d8..620703ed64762 100644
--- 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 <cassert>
 
 #include "test_macros.h"
+#include "locale_helpers.h"
 #include "platform_support.h" // locale name macros
 
 class Fnf
@@ -140,19 +141,7 @@ int main(int, char**)
 
     {
         Fnf f(LOCALE_ru_RU_UTF_8, 1);
-#if defined(_CS_GNU_LIBC_VERSION)
-        // GLIBC <= 2.23 uses currency_symbol="<U0440><U0443><U0431>"
-        // GLIBC >= 2.24 uses currency_symbol="<U20BD>"
-        // 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<std::string>(LocaleHelpers::currency_symbol_ru_RU()));
     }
     {
         Fnt f(LOCALE_ru_RU_UTF_8, 1);
@@ -161,16 +150,7 @@ int main(int, char**)
 #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<std::wstring>(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
index 0000000000000..9fb11b9941907
--- /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 <string>
+#include "platform_support.h"
+#include "test_macros.h"
+#include "make_string.h"
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+
+#include <cwctype>
+
+#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


        


More information about the libcxx-commits mailing list