Skip to content

Commit 88cca8e

Browse files
authored
[libc++] Add more missing bits to the locale base API (llvm#122531)
This patch adds the following pieces to the locale base API: - __setlocale (for std::setlocale) - __lconv_t (for std::lconv) - _LIBCPP_FOO_MASK and _LIBCPP_LC_ALL This should be sufficient to implement all of the platform-agnostic localization support in libc++ without relying directly on any public API names from the C library. This makes it possible to port libc++ to platforms that don't provide the usual locale APIs.
1 parent 658f850 commit 88cca8e

File tree

8 files changed

+112
-54
lines changed

8 files changed

+112
-54
lines changed

libcxx/include/__locale

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@ public:
6060

6161
static const category // values assigned here are for exposition only
6262
none = 0,
63-
collate = LC_COLLATE_MASK, ctype = LC_CTYPE_MASK, monetary = LC_MONETARY_MASK, numeric = LC_NUMERIC_MASK,
64-
time = LC_TIME_MASK, messages = LC_MESSAGES_MASK, all = collate | ctype | monetary | numeric | time | messages;
63+
collate = _LIBCPP_COLLATE_MASK, ctype = _LIBCPP_CTYPE_MASK, monetary = _LIBCPP_MONETARY_MASK,
64+
numeric = _LIBCPP_NUMERIC_MASK, time = _LIBCPP_TIME_MASK, messages = _LIBCPP_MESSAGES_MASK,
65+
all = collate | ctype | monetary | numeric | time | messages;
6566

6667
// construct/copy/destroy:
6768
locale() _NOEXCEPT;

libcxx/include/__locale_dir/locale_base_api.h

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,22 @@
2929
// -----------------
3030
// namespace __locale {
3131
// using __locale_t = implementation-defined;
32+
// using __lconv_t = implementation-defined;
3233
// __locale_t __newlocale(int, const char*, __locale_t);
3334
// void __freelocale(__locale_t);
34-
// lconv* __localeconv(__locale_t&);
35+
// char* __setlocale(int, const char*);
36+
// __lconv_t* __localeconv(__locale_t&);
3537
// }
3638
//
39+
// #define _LIBCPP_COLLATE_MASK /* implementation-defined */
40+
// #define _LIBCPP_CTYPE_MASK /* implementation-defined */
41+
// #define _LIBCPP_MONETARY_MASK /* implementation-defined */
42+
// #define _LIBCPP_NUMERIC_MASK /* implementation-defined */
43+
// #define _LIBCPP_TIME_MASK /* implementation-defined */
44+
// #define _LIBCPP_MESSAGES_MASK /* implementation-defined */
45+
// #define _LIBCPP_ALL_MASK /* implementation-defined */
46+
// #define _LIBCPP_LC_ALL /* implementation-defined */
47+
//
3748
// Strtonum functions
3849
// ------------------
3950
// namespace __locale {
@@ -133,14 +144,28 @@ namespace __locale {
133144
// Locale management
134145
//
135146
using __locale_t _LIBCPP_NODEBUG = locale_t;
147+
using __lconv_t _LIBCPP_NODEBUG = lconv;
136148

137149
inline _LIBCPP_HIDE_FROM_ABI __locale_t __newlocale(int __category_mask, const char* __name, __locale_t __loc) {
138150
return newlocale(__category_mask, __name, __loc);
139151
}
140152

153+
inline _LIBCPP_HIDE_FROM_ABI char* __setlocale(int __category, char const* __locale) {
154+
return ::setlocale(__category, __locale);
155+
}
156+
141157
inline _LIBCPP_HIDE_FROM_ABI void __freelocale(__locale_t __loc) { freelocale(__loc); }
142158

143-
inline _LIBCPP_HIDE_FROM_ABI lconv* __localeconv(__locale_t& __loc) { return __libcpp_localeconv_l(__loc); }
159+
inline _LIBCPP_HIDE_FROM_ABI __lconv_t* __localeconv(__locale_t& __loc) { return __libcpp_localeconv_l(__loc); }
160+
161+
# define _LIBCPP_COLLATE_MASK LC_COLLATE_MASK
162+
# define _LIBCPP_CTYPE_MASK LC_CTYPE_MASK
163+
# define _LIBCPP_MONETARY_MASK LC_MONETARY_MASK
164+
# define _LIBCPP_NUMERIC_MASK LC_NUMERIC_MASK
165+
# define _LIBCPP_TIME_MASK LC_TIME_MASK
166+
# define _LIBCPP_MESSAGES_MASK LC_MESSAGES_MASK
167+
# define _LIBCPP_ALL_MASK LC_ALL_MASK
168+
# define _LIBCPP_LC_ALL LC_ALL
144169

145170
//
146171
// Strtonum functions

libcxx/include/__locale_dir/support/bsd_like.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,29 @@ namespace __locale {
3636
//
3737
// Locale management
3838
//
39+
#define _LIBCPP_COLLATE_MASK LC_COLLATE_MASK
40+
#define _LIBCPP_CTYPE_MASK LC_CTYPE_MASK
41+
#define _LIBCPP_MONETARY_MASK LC_MONETARY_MASK
42+
#define _LIBCPP_NUMERIC_MASK LC_NUMERIC_MASK
43+
#define _LIBCPP_TIME_MASK LC_TIME_MASK
44+
#define _LIBCPP_MESSAGES_MASK LC_MESSAGES_MASK
45+
#define _LIBCPP_ALL_MASK LC_ALL_MASK
46+
#define _LIBCPP_LC_ALL LC_ALL
47+
3948
using __locale_t = ::locale_t;
49+
using __lconv_t = std::lconv;
4050

4151
inline _LIBCPP_HIDE_FROM_ABI __locale_t __newlocale(int __category_mask, const char* __locale, __locale_t __base) {
4252
return ::newlocale(__category_mask, __locale, __base);
4353
}
4454

4555
inline _LIBCPP_HIDE_FROM_ABI void __freelocale(__locale_t __loc) { ::freelocale(__loc); }
4656

47-
inline _LIBCPP_HIDE_FROM_ABI lconv* __localeconv(__locale_t& __loc) { return ::localeconv_l(__loc); }
57+
inline _LIBCPP_HIDE_FROM_ABI char* __setlocale(int __category, char const* __locale) {
58+
return ::setlocale(__category, __locale);
59+
}
60+
61+
inline _LIBCPP_HIDE_FROM_ABI __lconv_t* __localeconv(__locale_t& __loc) { return ::localeconv_l(__loc); }
4862

4963
//
5064
// Strtonum functions

libcxx/include/__locale_dir/support/fuchsia.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,29 @@ struct __locale_guard {
4040
//
4141
// Locale management
4242
//
43+
#define _LIBCPP_COLLATE_MASK LC_COLLATE_MASK
44+
#define _LIBCPP_CTYPE_MASK LC_CTYPE_MASK
45+
#define _LIBCPP_MONETARY_MASK LC_MONETARY_MASK
46+
#define _LIBCPP_NUMERIC_MASK LC_NUMERIC_MASK
47+
#define _LIBCPP_TIME_MASK LC_TIME_MASK
48+
#define _LIBCPP_MESSAGES_MASK LC_MESSAGES_MASK
49+
#define _LIBCPP_ALL_MASK LC_ALL_MASK
50+
#define _LIBCPP_LC_ALL LC_ALL
51+
4352
using __locale_t = locale_t;
53+
using __lconv_t = std::lconv;
4454

4555
inline _LIBCPP_HIDE_FROM_ABI __locale_t __newlocale(int __category_mask, const char* __name, __locale_t __loc) {
4656
return ::newlocale(__category_mask, __name, __loc);
4757
}
4858

4959
inline _LIBCPP_HIDE_FROM_ABI void __freelocale(__locale_t __loc) { ::freelocale(__loc); }
5060

51-
inline _LIBCPP_HIDE_FROM_ABI lconv* __localeconv(__locale_t& __loc) {
61+
inline _LIBCPP_HIDE_FROM_ABI char* __setlocale(int __category, char const* __locale) {
62+
return ::setlocale(__category, __locale);
63+
}
64+
65+
inline _LIBCPP_HIDE_FROM_ABI __lconv_t* __localeconv(__locale_t& __loc) {
5266
__locale_guard __current(__loc);
5367
return std::localeconv();
5468
}

libcxx/include/__locale_dir/support/windows.h

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,14 @@
2626
# pragma GCC system_header
2727
#endif
2828

29-
#define _CATMASK(n) ((1 << (n)) >> 1)
30-
#define LC_COLLATE_MASK _CATMASK(LC_COLLATE)
31-
#define LC_CTYPE_MASK _CATMASK(LC_CTYPE)
32-
#define LC_MONETARY_MASK _CATMASK(LC_MONETARY)
33-
#define LC_NUMERIC_MASK _CATMASK(LC_NUMERIC)
34-
#define LC_TIME_MASK _CATMASK(LC_TIME)
35-
#define LC_MESSAGES_MASK _CATMASK(6)
36-
#define LC_ALL_MASK \
37-
(LC_COLLATE_MASK | LC_CTYPE_MASK | LC_MESSAGES_MASK | LC_MONETARY_MASK | LC_NUMERIC_MASK | LC_TIME_MASK)
38-
3929
_LIBCPP_BEGIN_NAMESPACE_STD
4030
namespace __locale {
4131

32+
using __lconv_t = std::lconv;
33+
4234
class __lconv_storage {
4335
public:
44-
__lconv_storage(const lconv* __lc_input) {
36+
__lconv_storage(const __lconv_t* __lc_input) {
4537
__lc_ = *__lc_input;
4638

4739
__decimal_point_ = __lc_input->decimal_point;
@@ -67,10 +59,10 @@ class __lconv_storage {
6759
__lc_.negative_sign = const_cast<char*>(__negative_sign_.c_str());
6860
}
6961

70-
std::lconv* __get() { return &__lc_; }
62+
__lconv_t* __get() { return &__lc_; }
7163

7264
private:
73-
std::lconv __lc_;
65+
__lconv_t __lc_;
7466
std::string __decimal_point_;
7567
std::string __thousands_sep_;
7668
std::string __grouping_;
@@ -86,6 +78,18 @@ class __lconv_storage {
8678
//
8779
// Locale management
8880
//
81+
#define _CATMASK(n) ((1 << (n)) >> 1)
82+
#define _LIBCPP_COLLATE_MASK _CATMASK(LC_COLLATE)
83+
#define _LIBCPP_CTYPE_MASK _CATMASK(LC_CTYPE)
84+
#define _LIBCPP_MONETARY_MASK _CATMASK(LC_MONETARY)
85+
#define _LIBCPP_NUMERIC_MASK _CATMASK(LC_NUMERIC)
86+
#define _LIBCPP_TIME_MASK _CATMASK(LC_TIME)
87+
#define _LIBCPP_MESSAGES_MASK _CATMASK(6)
88+
#define _LIBCPP_ALL_MASK \
89+
(_LIBCPP_COLLATE_MASK | _LIBCPP_CTYPE_MASK | _LIBCPP_MESSAGES_MASK | _LIBCPP_MONETARY_MASK | _LIBCPP_NUMERIC_MASK | \
90+
_LIBCPP_TIME_MASK)
91+
#define _LIBCPP_LC_ALL LC_ALL
92+
8993
class __locale_t {
9094
public:
9195
__locale_t() : __locale_(nullptr), __locale_str_(nullptr), __lc_(nullptr) {}
@@ -137,7 +141,7 @@ class __locale_t {
137141

138142
operator ::_locale_t() const { return __locale_; }
139143

140-
std::lconv* __store_lconv(const std::lconv* __input_lc) {
144+
__lconv_t* __store_lconv(const __lconv_t* __input_lc) {
141145
delete __lc_;
142146
__lc_ = new __lconv_storage(__input_lc);
143147
return __lc_->__get();
@@ -151,7 +155,13 @@ class __locale_t {
151155

152156
_LIBCPP_EXPORTED_FROM_ABI __locale_t __newlocale(int __mask, const char* __locale, __locale_t __base);
153157
inline _LIBCPP_HIDE_FROM_ABI void __freelocale(__locale_t __loc) { ::_free_locale(__loc); }
154-
_LIBCPP_EXPORTED_FROM_ABI lconv* __localeconv(__locale_t& __loc);
158+
inline _LIBCPP_HIDE_FROM_ABI char* __setlocale(int __category, const char* __locale) {
159+
char* __new_locale = ::setlocale(__category, __locale);
160+
if (__new_locale == nullptr)
161+
std::__throw_bad_alloc();
162+
return __new_locale;
163+
}
164+
_LIBCPP_EXPORTED_FROM_ABI __lconv_t* __localeconv(__locale_t& __loc);
155165

156166
//
157167
// Strtonum functions
@@ -292,7 +302,7 @@ struct __locale_guard {
292302
// Setting the locale can be expensive even when the locale given is
293303
// already the current locale, so do an explicit check to see if the
294304
// current locale is already the one we want.
295-
const char* __lc = __setlocale(nullptr);
305+
const char* __lc = __locale::__setlocale(LC_ALL, nullptr);
296306
// If every category is the same, the locale string will simply be the
297307
// locale name, otherwise it will be a semicolon-separated string listing
298308
// each category. In the second case, we know at least one category won't
@@ -301,7 +311,7 @@ struct __locale_guard {
301311
__locale_all = _strdup(__lc);
302312
if (__locale_all == nullptr)
303313
__throw_bad_alloc();
304-
__setlocale(__l.__get_locale());
314+
__locale::__setlocale(LC_ALL, __l.__get_locale());
305315
}
306316
}
307317
_LIBCPP_HIDE_FROM_ABI ~__locale_guard() {
@@ -310,17 +320,11 @@ struct __locale_guard {
310320
// for the different categories in the same format as returned by
311321
// setlocale(LC_ALL, nullptr).
312322
if (__locale_all != nullptr) {
313-
__setlocale(__locale_all);
323+
__locale::__setlocale(LC_ALL, __locale_all);
314324
free(__locale_all);
315325
}
316326
_configthreadlocale(__status);
317327
}
318-
_LIBCPP_HIDE_FROM_ABI static const char* __setlocale(const char* __locale) {
319-
const char* __new_locale = setlocale(LC_ALL, __locale);
320-
if (__new_locale == nullptr)
321-
__throw_bad_alloc();
322-
return __new_locale;
323-
}
324328
int __status;
325329
char* __locale_all = nullptr;
326330
};

libcxx/src/iostream.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ alignas(wostream) _LIBCPP_EXPORTED_FROM_ABI char wclog[sizeof(wostream)]
103103
static void force_locale_initialization() {
104104
#if defined(_LIBCPP_MSVCRT_LIKE)
105105
static bool once = []() {
106-
auto loc = __locale::__newlocale(LC_ALL_MASK, "C", 0);
106+
auto loc = __locale::__newlocale(_LIBCPP_ALL_MASK, "C", 0);
107107
{
108108
__locale::__locale_guard g(loc); // forces initialization of locale TLS
109109
((void)g);

0 commit comments

Comments
 (0)