xref: /llvm-project/libcxx/test/support/locale_helpers.h (revision 480cd780d63fd9c658cc2f51d0c54416b8b1a5c3)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LIBCXX_TEST_SUPPORT_LOCALE_HELPERS_H
10 #define LIBCXX_TEST_SUPPORT_LOCALE_HELPERS_H
11 
12 #include <string>
13 #include "platform_support.h"
14 #include "test_macros.h"
15 #include "make_string.h"
16 
17 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
18 
19 #include <cwctype>
20 
21 #endif // TEST_HAS_NO_WIDE_CHARACTERS
22 
23 namespace LocaleHelpers {
24 
25 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
26 
convert_thousands_sep(std::wstring const & in,wchar_t sep)27 std::wstring convert_thousands_sep(std::wstring const& in, wchar_t sep) {
28   std::wstring out;
29   bool seen_num_start = false;
30   bool seen_decimal = false;
31   for (unsigned i = 0; i < in.size(); ++i) {
32     seen_decimal |= in[i] == L',';
33     seen_num_start |= in[i] == L'-' || std::iswdigit(in[i]);
34     if (seen_decimal || !seen_num_start || in[i] != L' ') {
35       out.push_back(in[i]);
36       continue;
37     }
38     assert(in[i] == L' ');
39     out.push_back(sep);
40   }
41   return out;
42 }
43 
44 // GLIBC 2.27 and newer use U+202F NARROW NO-BREAK SPACE as a thousands separator.
45 // This function converts the spaces in string inputs to U+202F if need
46 // be. FreeBSD's locale data also uses U+202F, since 2018.
47 // Windows uses U+00A0 NO-BREAK SPACE.
convert_thousands_sep_fr_FR(std::wstring const & in)48 std::wstring convert_thousands_sep_fr_FR(std::wstring const& in) {
49 #if defined(_CS_GNU_LIBC_VERSION)
50   if (glibc_version_less_than("2.27"))
51     return in;
52   else
53     return convert_thousands_sep(in, L'\u202F');
54 #elif defined(__FreeBSD__)
55   return convert_thousands_sep(in, L'\u202F');
56 #elif defined(_WIN32)
57   return convert_thousands_sep(in, L'\u00A0');
58 #else
59   return in;
60 #endif
61 }
62 
63 // GLIBC 2.27 uses U+202F NARROW NO-BREAK SPACE as a thousands separator.
64 // FreeBSD, AIX and Windows use U+00A0 NO-BREAK SPACE.
convert_thousands_sep_ru_RU(std::wstring const & in)65 std::wstring convert_thousands_sep_ru_RU(std::wstring const& in) {
66 #if defined(TEST_HAS_GLIBC)
67   return convert_thousands_sep(in, L'\u202F');
68 #  elif defined(__FreeBSD__) || defined(_WIN32) || defined(_AIX)
69   return convert_thousands_sep(in, L'\u00A0');
70 #  else
71   return in;
72 #  endif
73 }
74 
negate_en_US(std::wstring s)75 std::wstring negate_en_US(std::wstring s) {
76 #if defined(_WIN32)
77   return L"(" + s + L")";
78 #else
79   return L"-" + s;
80 #endif
81 }
82 
83 #endif // TEST_HAS_NO_WIDE_CHARACTERS
84 
negate_en_US(std::string s)85 std::string negate_en_US(std::string s) {
86 #if defined(_WIN32)
87   return "(" + s + ")";
88 #else
89   return "-" + s;
90 #endif
91 }
92 
currency_symbol_ru_RU()93 MultiStringType currency_symbol_ru_RU() {
94 #if defined(_CS_GNU_LIBC_VERSION)
95   if (glibc_version_less_than("2.24"))
96     return MKSTR("\u0440\u0443\u0431");
97   else
98     return MKSTR("\u20BD"); // U+20BD RUBLE SIGN
99 #elif defined(_WIN32) || defined(__FreeBSD__) || defined(_AIX)
100   return MKSTR("\u20BD"); // U+20BD RUBLE SIGN
101 #else
102   return MKSTR("\u0440\u0443\u0431.");
103 #endif
104 }
105 
currency_symbol_zh_CN()106 MultiStringType currency_symbol_zh_CN() {
107 #if defined(_WIN32)
108   return MKSTR("\u00A5"); // U+00A5 YEN SIGN
109 #else
110   return MKSTR("\uFFE5"); // U+FFE5 FULLWIDTH YEN SIGN
111 #endif
112 }
113 
114 } // namespace LocaleHelpers
115 
116 #endif // LIBCXX_TEST_SUPPORT_LOCALE_HELPERS_H
117