-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[libc++] Add more missing bits to the locale base API #122531
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-libcxx Author: Louis Dionne (ldionne) ChangesThis patch adds the following pieces to the locale base API:
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 a BSD-like public API. Patch is 20.24 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/122531.diff 7 Files Affected:
diff --git a/libcxx/include/__locale b/libcxx/include/__locale
index 01c3a2e3456ba1..79e4b198a64803 100644
--- a/libcxx/include/__locale
+++ b/libcxx/include/__locale
@@ -60,8 +60,9 @@ public:
static const category // values assigned here are for exposition only
none = 0,
- collate = LC_COLLATE_MASK, ctype = LC_CTYPE_MASK, monetary = LC_MONETARY_MASK, numeric = LC_NUMERIC_MASK,
- time = LC_TIME_MASK, messages = LC_MESSAGES_MASK, all = collate | ctype | monetary | numeric | time | messages;
+ collate = _LIBCPP_COLLATE_MASK, ctype = _LIBCPP_CTYPE_MASK, monetary = _LIBCPP_MONETARY_MASK,
+ numeric = _LIBCPP_NUMERIC_MASK, time = _LIBCPP_TIME_MASK, messages = _LIBCPP_MESSAGES_MASK,
+ all = collate | ctype | monetary | numeric | time | messages;
// construct/copy/destroy:
locale() _NOEXCEPT;
diff --git a/libcxx/include/__locale_dir/locale_base_api.h b/libcxx/include/__locale_dir/locale_base_api.h
index bb0da889f4c845..a8709f535042ee 100644
--- a/libcxx/include/__locale_dir/locale_base_api.h
+++ b/libcxx/include/__locale_dir/locale_base_api.h
@@ -29,11 +29,22 @@
// -----------------
// namespace __locale {
// using __locale_t = implementation-defined;
+// using __lconv_t = implementation-defined;
// __locale_t __newlocale(int, const char*, __locale_t);
// void __freelocale(__locale_t);
-// lconv* __localeconv(__locale_t&);
+// char* __setlocale(int, const char*);
+// __lconv_t* __localeconv(__locale_t&);
// }
//
+// #define _LIBCPP_COLLATE_MASK /* implementation-defined */
+// #define _LIBCPP_CTYPE_MASK /* implementation-defined */
+// #define _LIBCPP_MONETARY_MASK /* implementation-defined */
+// #define _LIBCPP_NUMERIC_MASK /* implementation-defined */
+// #define _LIBCPP_TIME_MASK /* implementation-defined */
+// #define _LIBCPP_MESSAGES_MASK /* implementation-defined */
+// #define _LIBCPP_ALL_MASK /* implementation-defined */
+// #define _LIBCPP_LC_ALL /* implementation-defined */
+//
// Strtonum functions
// ------------------
// namespace __locale {
@@ -133,14 +144,28 @@ namespace __locale {
// Locale management
//
using __locale_t _LIBCPP_NODEBUG = locale_t;
+using __lconv_t _LIBCPP_NODEBUG = lconv;
inline _LIBCPP_HIDE_FROM_ABI __locale_t __newlocale(int __category_mask, const char* __name, __locale_t __loc) {
return newlocale(__category_mask, __name, __loc);
}
+inline _LIBCPP_HIDE_FROM_ABI char* __setlocale(int __category, char const* __locale) {
+ return ::setlocale(__category, __locale);
+}
+
inline _LIBCPP_HIDE_FROM_ABI void __freelocale(__locale_t __loc) { freelocale(__loc); }
-inline _LIBCPP_HIDE_FROM_ABI lconv* __localeconv(__locale_t& __loc) { return __libcpp_localeconv_l(__loc); }
+inline _LIBCPP_HIDE_FROM_ABI __lconv_t* __localeconv(__locale_t& __loc) { return __libcpp_localeconv_l(__loc); }
+
+# define _LIBCPP_COLLATE_MASK LC_COLLATE_MASK
+# define _LIBCPP_CTYPE_MASK LC_CTYPE_MASK
+# define _LIBCPP_MONETARY_MASK LC_MONETARY_MASK
+# define _LIBCPP_NUMERIC_MASK LC_NUMERIC_MASK
+# define _LIBCPP_TIME_MASK LC_TIME_MASK
+# define _LIBCPP_MESSAGES_MASK LC_MESSAGES_MASK
+# define _LIBCPP_ALL_MASK LC_ALL_MASK
+# define _LIBCPP_LC_ALL LC_ALL
//
// Strtonum functions
diff --git a/libcxx/include/__locale_dir/support/bsd_like.h b/libcxx/include/__locale_dir/support/bsd_like.h
index b3933c71c6b26d..c0080b13a08cf3 100644
--- a/libcxx/include/__locale_dir/support/bsd_like.h
+++ b/libcxx/include/__locale_dir/support/bsd_like.h
@@ -36,7 +36,17 @@ namespace __locale {
//
// Locale management
//
+#define _LIBCPP_COLLATE_MASK LC_COLLATE_MASK
+#define _LIBCPP_CTYPE_MASK LC_CTYPE_MASK
+#define _LIBCPP_MONETARY_MASK LC_MONETARY_MASK
+#define _LIBCPP_NUMERIC_MASK LC_NUMERIC_MASK
+#define _LIBCPP_TIME_MASK LC_TIME_MASK
+#define _LIBCPP_MESSAGES_MASK LC_MESSAGES_MASK
+#define _LIBCPP_ALL_MASK LC_ALL_MASK
+#define _LIBCPP_LC_ALL LC_ALL
+
using __locale_t = ::locale_t;
+using __lconv_t = std::lconv;
inline _LIBCPP_HIDE_FROM_ABI __locale_t __newlocale(int __category_mask, const char* __locale, __locale_t __base) {
return ::newlocale(__category_mask, __locale, __base);
@@ -44,7 +54,11 @@ inline _LIBCPP_HIDE_FROM_ABI __locale_t __newlocale(int __category_mask, const c
inline _LIBCPP_HIDE_FROM_ABI void __freelocale(__locale_t __loc) { ::freelocale(__loc); }
-inline _LIBCPP_HIDE_FROM_ABI lconv* __localeconv(__locale_t& __loc) { return ::localeconv_l(__loc); }
+inline _LIBCPP_HIDE_FROM_ABI char* __setlocale(int __category, char const* __locale) {
+ return ::setlocale(__category, __locale);
+}
+
+inline _LIBCPP_HIDE_FROM_ABI __lconv_t* __localeconv(__locale_t& __loc) { return ::localeconv_l(__loc); }
//
// Strtonum functions
diff --git a/libcxx/include/__locale_dir/support/windows.h b/libcxx/include/__locale_dir/support/windows.h
index eca0e17d94c85a..ff89d3e87eb44e 100644
--- a/libcxx/include/__locale_dir/support/windows.h
+++ b/libcxx/include/__locale_dir/support/windows.h
@@ -26,22 +26,14 @@
# pragma GCC system_header
#endif
-#define _CATMASK(n) ((1 << (n)) >> 1)
-#define LC_COLLATE_MASK _CATMASK(LC_COLLATE)
-#define LC_CTYPE_MASK _CATMASK(LC_CTYPE)
-#define LC_MONETARY_MASK _CATMASK(LC_MONETARY)
-#define LC_NUMERIC_MASK _CATMASK(LC_NUMERIC)
-#define LC_TIME_MASK _CATMASK(LC_TIME)
-#define LC_MESSAGES_MASK _CATMASK(6)
-#define LC_ALL_MASK \
- (LC_COLLATE_MASK | LC_CTYPE_MASK | LC_MESSAGES_MASK | LC_MONETARY_MASK | LC_NUMERIC_MASK | LC_TIME_MASK)
-
_LIBCPP_BEGIN_NAMESPACE_STD
namespace __locale {
+using __lconv_t = std::lconv;
+
class __lconv_storage {
public:
- __lconv_storage(const lconv* __lc_input) {
+ __lconv_storage(const __lconv_t* __lc_input) {
__lc_ = *__lc_input;
__decimal_point_ = __lc_input->decimal_point;
@@ -67,10 +59,10 @@ class __lconv_storage {
__lc_.negative_sign = const_cast<char*>(__negative_sign_.c_str());
}
- std::lconv* __get() { return &__lc_; }
+ __lconv_t* __get() { return &__lc_; }
private:
- std::lconv __lc_;
+ __lconv_t __lc_;
std::string __decimal_point_;
std::string __thousands_sep_;
std::string __grouping_;
@@ -86,6 +78,18 @@ class __lconv_storage {
//
// Locale management
//
+#define _CATMASK(n) ((1 << (n)) >> 1)
+#define _LIBCPP_COLLATE_MASK _CATMASK(LC_COLLATE)
+#define _LIBCPP_CTYPE_MASK _CATMASK(LC_CTYPE)
+#define _LIBCPP_MONETARY_MASK _CATMASK(LC_MONETARY)
+#define _LIBCPP_NUMERIC_MASK _CATMASK(LC_NUMERIC)
+#define _LIBCPP_TIME_MASK _CATMASK(LC_TIME)
+#define _LIBCPP_MESSAGES_MASK _CATMASK(6)
+#define _LIBCPP_ALL_MASK \
+ (_LIBCPP_COLLATE_MASK | _LIBCPP_CTYPE_MASK | _LIBCPP_MESSAGES_MASK | _LIBCPP_MONETARY_MASK | _LIBCPP_NUMERIC_MASK | \
+ _LIBCPP_TIME_MASK)
+#define _LIBCPP_LC_ALL LC_ALL
+
class __locale_t {
public:
__locale_t() : __locale_(nullptr), __locale_str_(nullptr), __lc_(nullptr) {}
@@ -137,7 +141,7 @@ class __locale_t {
operator ::_locale_t() const { return __locale_; }
- std::lconv* __store_lconv(const std::lconv* __input_lc) {
+ __lconv_t* __store_lconv(const __lconv_t* __input_lc) {
delete __lc_;
__lc_ = new __lconv_storage(__input_lc);
return __lc_->__get();
@@ -151,7 +155,13 @@ class __locale_t {
_LIBCPP_EXPORTED_FROM_ABI __locale_t __newlocale(int __mask, const char* __locale, __locale_t __base);
inline _LIBCPP_HIDE_FROM_ABI void __freelocale(__locale_t __loc) { ::_free_locale(__loc); }
-_LIBCPP_EXPORTED_FROM_ABI lconv* __localeconv(__locale_t& __loc);
+inline _LIBCPP_HIDE_FROM_ABI char* __setlocale(int __category, const char* __locale) {
+ char* __new_locale = ::setlocale(__category, __locale);
+ if (__new_locale == nullptr)
+ std::__throw_bad_alloc();
+ return __new_locale;
+}
+_LIBCPP_EXPORTED_FROM_ABI __lconv_t* __localeconv(__locale_t& __loc);
//
// Strtonum functions
@@ -292,7 +302,7 @@ struct __locale_guard {
// Setting the locale can be expensive even when the locale given is
// already the current locale, so do an explicit check to see if the
// current locale is already the one we want.
- const char* __lc = __setlocale(nullptr);
+ const char* __lc = __locale::__setlocale(LC_ALL, nullptr);
// If every category is the same, the locale string will simply be the
// locale name, otherwise it will be a semicolon-separated string listing
// each category. In the second case, we know at least one category won't
@@ -301,7 +311,7 @@ struct __locale_guard {
__locale_all = _strdup(__lc);
if (__locale_all == nullptr)
__throw_bad_alloc();
- __setlocale(__l.__get_locale());
+ __locale::__setlocale(LC_ALL, __l.__get_locale());
}
}
_LIBCPP_HIDE_FROM_ABI ~__locale_guard() {
@@ -310,17 +320,11 @@ struct __locale_guard {
// for the different categories in the same format as returned by
// setlocale(LC_ALL, nullptr).
if (__locale_all != nullptr) {
- __setlocale(__locale_all);
+ __locale::__setlocale(LC_ALL, __locale_all);
free(__locale_all);
}
_configthreadlocale(__status);
}
- _LIBCPP_HIDE_FROM_ABI static const char* __setlocale(const char* __locale) {
- const char* __new_locale = setlocale(LC_ALL, __locale);
- if (__new_locale == nullptr)
- __throw_bad_alloc();
- return __new_locale;
- }
int __status;
char* __locale_all = nullptr;
};
diff --git a/libcxx/src/iostream.cpp b/libcxx/src/iostream.cpp
index 6db02d56037947..9bc9ec0531a4b2 100644
--- a/libcxx/src/iostream.cpp
+++ b/libcxx/src/iostream.cpp
@@ -103,7 +103,7 @@ alignas(wostream) _LIBCPP_EXPORTED_FROM_ABI char wclog[sizeof(wostream)]
static void force_locale_initialization() {
#if defined(_LIBCPP_MSVCRT_LIKE)
static bool once = []() {
- auto loc = __locale::__newlocale(LC_ALL_MASK, "C", 0);
+ auto loc = __locale::__newlocale(_LIBCPP_ALL_MASK, "C", 0);
{
__locale::__locale_guard g(loc); // forces initialization of locale TLS
((void)g);
diff --git a/libcxx/src/locale.cpp b/libcxx/src/locale.cpp
index fb67a729cd0f23..81f3ad49743901 100644
--- a/libcxx/src/locale.cpp
+++ b/libcxx/src/locale.cpp
@@ -51,7 +51,7 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD
struct __libcpp_unique_locale {
- __libcpp_unique_locale(const char* nm) : __loc_(__locale::__newlocale(LC_ALL_MASK, nm, 0)) {}
+ __libcpp_unique_locale(const char* nm) : __loc_(__locale::__newlocale(_LIBCPP_ALL_MASK, nm, 0)) {}
~__libcpp_unique_locale() {
if (__loc_)
@@ -74,7 +74,7 @@ __locale::__locale_t __cloc() {
// In theory this could create a race condition. In practice
// the race condition is non-fatal since it will just create
// a little resource leak. Better approach would be appreciated.
- static __locale::__locale_t result = __locale::__newlocale(LC_ALL_MASK, "C", 0);
+ static __locale::__locale_t result = __locale::__newlocale(_LIBCPP_ALL_MASK, "C", 0);
return result;
}
#endif // __cloc_defined
@@ -570,7 +570,7 @@ locale locale::global(const locale& loc) {
locale r = g;
g = loc;
if (g.name() != "*")
- setlocale(LC_ALL, g.name().c_str());
+ __locale::__setlocale(_LIBCPP_LC_ALL, g.name().c_str());
return r;
}
@@ -600,7 +600,7 @@ long locale::id::__get() {
// template <> class collate_byname<char>
collate_byname<char>::collate_byname(const char* n, size_t refs)
- : collate<char>(refs), __l_(__locale::__newlocale(LC_ALL_MASK, n, 0)) {
+ : collate<char>(refs), __l_(__locale::__newlocale(_LIBCPP_ALL_MASK, n, 0)) {
if (__l_ == 0)
__throw_runtime_error(
("collate_byname<char>::collate_byname"
@@ -610,7 +610,7 @@ collate_byname<char>::collate_byname(const char* n, size_t refs)
}
collate_byname<char>::collate_byname(const string& name, size_t refs)
- : collate<char>(refs), __l_(__locale::__newlocale(LC_ALL_MASK, name.c_str(), 0)) {
+ : collate<char>(refs), __l_(__locale::__newlocale(_LIBCPP_ALL_MASK, name.c_str(), 0)) {
if (__l_ == 0)
__throw_runtime_error(
("collate_byname<char>::collate_byname"
@@ -644,7 +644,7 @@ collate_byname<char>::string_type collate_byname<char>::do_transform(const char_
#if _LIBCPP_HAS_WIDE_CHARACTERS
collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
- : collate<wchar_t>(refs), __l_(__locale::__newlocale(LC_ALL_MASK, n, 0)) {
+ : collate<wchar_t>(refs), __l_(__locale::__newlocale(_LIBCPP_ALL_MASK, n, 0)) {
if (__l_ == 0)
__throw_runtime_error(
("collate_byname<wchar_t>::collate_byname(size_t refs)"
@@ -654,7 +654,7 @@ collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
}
collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
- : collate<wchar_t>(refs), __l_(__locale::__newlocale(LC_ALL_MASK, name.c_str(), 0)) {
+ : collate<wchar_t>(refs), __l_(__locale::__newlocale(_LIBCPP_ALL_MASK, name.c_str(), 0)) {
if (__l_ == 0)
__throw_runtime_error(
("collate_byname<wchar_t>::collate_byname(size_t refs)"
@@ -1047,7 +1047,7 @@ const unsigned short* ctype<char>::__classic_upper_table() _NOEXCEPT {
// template <> class ctype_byname<char>
ctype_byname<char>::ctype_byname(const char* name, size_t refs)
- : ctype<char>(0, false, refs), __l_(__locale::__newlocale(LC_ALL_MASK, name, 0)) {
+ : ctype<char>(0, false, refs), __l_(__locale::__newlocale(_LIBCPP_ALL_MASK, name, 0)) {
if (__l_ == 0)
__throw_runtime_error(
("ctype_byname<char>::ctype_byname"
@@ -1057,7 +1057,7 @@ ctype_byname<char>::ctype_byname(const char* name, size_t refs)
}
ctype_byname<char>::ctype_byname(const string& name, size_t refs)
- : ctype<char>(0, false, refs), __l_(__locale::__newlocale(LC_ALL_MASK, name.c_str(), 0)) {
+ : ctype<char>(0, false, refs), __l_(__locale::__newlocale(_LIBCPP_ALL_MASK, name.c_str(), 0)) {
if (__l_ == 0)
__throw_runtime_error(
("ctype_byname<char>::ctype_byname"
@@ -1092,7 +1092,7 @@ const char* ctype_byname<char>::do_tolower(char_type* low, const char_type* high
#if _LIBCPP_HAS_WIDE_CHARACTERS
ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
- : ctype<wchar_t>(refs), __l_(__locale::__newlocale(LC_ALL_MASK, name, 0)) {
+ : ctype<wchar_t>(refs), __l_(__locale::__newlocale(_LIBCPP_ALL_MASK, name, 0)) {
if (__l_ == 0)
__throw_runtime_error(
("ctype_byname<wchar_t>::ctype_byname"
@@ -1102,7 +1102,7 @@ ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
}
ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
- : ctype<wchar_t>(refs), __l_(__locale::__newlocale(LC_ALL_MASK, name.c_str(), 0)) {
+ : ctype<wchar_t>(refs), __l_(__locale::__newlocale(_LIBCPP_ALL_MASK, name.c_str(), 0)) {
if (__l_ == 0)
__throw_runtime_error(
("ctype_byname<wchar_t>::ctype_byname"
@@ -1342,7 +1342,7 @@ constinit locale::id codecvt<wchar_t, char, mbstate_t>::id;
codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs) : locale::facet(refs), __l_(_LIBCPP_GET_C_LOCALE) {}
codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
- : locale::facet(refs), __l_(__locale::__newlocale(LC_ALL_MASK, nm, 0)) {
+ : locale::facet(refs), __l_(__locale::__newlocale(_LIBCPP_ALL_MASK, nm, 0)) {
if (__l_ == 0)
__throw_runtime_error(
("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
@@ -4067,7 +4067,7 @@ void numpunct_byname<char>::__init(const char* nm) {
string(nm))
.c_str());
- lconv* lc = __locale::__localeconv(loc.get());
+ __locale::__lconv_t* lc = __locale::__localeconv(loc.get());
if (!checked_string_to_char_convert(__decimal_point_, lc->decimal_point, loc.get()))
__decimal_point_ = base::do_decimal_point();
if (!checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep, loc.get()))
@@ -4098,7 +4098,7 @@ void numpunct_byname<wchar_t>::__init(const char* nm) {
string(nm))
.c_str());
- lconv* lc = __locale::__localeconv(loc.get());
+ __locale::__lconv_t* lc = __locale::__localeconv(loc.get());
checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point, loc.get());
checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep, loc.get());
__grouping_ = lc->grouping;
@@ -4442,12 +4442,12 @@ const wstring& __time_get_c_storage<wchar_t>::__r() const {
// time_get_byname
-__time_get::__time_get(const char* nm) : __loc_(__locale::__newlocale(LC_ALL_MASK, nm, 0)) {
+__time_get::__time_get(const char* nm) : __loc_(__locale::__newlocale(_LIBCPP_ALL_MASK, nm, 0)) {
if (__loc_ == 0)
__throw_runtime_error(("time_get_byname failed to construct for " + string(nm)).c_str());
}
-__time_get::__time_get(const string& nm) : __loc_(__locale::__newlocale(LC_ALL_MASK, nm.c_str(), 0)) {
+__time_get::__time_get(const string& nm) : __loc_(__locale::__newlocale(_LIBCPP_ALL_MASK, nm.c_str(), 0)) {
if (__loc_ == 0)
__throw_runtime_error(("time_get_byname failed to construct for " + nm).c_str());
}
@@ -5027,12 +5027,12 @@ time_base::dateorder __time_get_storage<wchar_t>::__do_date_order() const {
// time_put
-__time_put::__time_put(const char* nm) : __loc_(__locale::__newlocale(LC_ALL_MASK, nm, 0)) {
+__time_put::__time_put(const char* nm) : __loc_(__locale::__newlocale(_LIBCPP_ALL_MASK, nm, 0)) {
if (__loc_ == 0)
__throw_runtime_error(("time_put_byname failed to construct for " + string(nm)).c_str());
}
-__time_put::__time_put(const string& nm) : __loc_(__locale::__newlocale(LC_ALL_MASK, nm.c_str(), 0)) {
+__time_put::__time_put(const string& nm) : __loc_(__locale::__newlocale(_LIBCPP_ALL_MASK, nm.c_str(), 0)) {
if (__loc_ == 0)
__throw_runtime_error(("time_put_byname failed to construct for " + nm).c_str());
}
@@ -5433,7 +5433,7 @@ void moneypunct_byname<char, false>::init(const char* nm) {
if (!loc)
__throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str());
- lconv* lc = __locale::__localeconv(loc.get());
+ __locale::__lconv_t* lc = __locale::__localeconv(loc.get());
if (!checked_string_to_char_convert(__decimal_point_, lc->mon_decimal_point, loc.get()))
__decimal_point_ = base::do_decimal_point();
if (!checked_string_to_char_convert(__thousands_sep_, lc->mon_thousands_sep, loc.get()))
@@ -5468,7 +5468,7 @@ void moneypunct_byname<char, true>::init(const char* nm) {
if (!loc)
__throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str());
- lconv* lc = __locale::__localeconv(loc.get());
+ __locale::__lconv_t* lc = __locale::__localeconv(loc.get());
if (!checked_string_to_char_convert(__decimal_point_, lc->mon_decimal_point, loc.get()))
__decimal_point_ = base::do_decimal_point();
if (!checked_string_to_char_convert(__thousands_sep_, lc->mon_thousands_sep, loc.get()))
@@ -5523,7 +5523,7 @@ void moneypunct_byname<wchar_t, false>::init(const char* nm) {
__libcpp_unique_locale loc(nm);
if (!loc)
__throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str());
- lconv* lc = __locale::__localeconv(loc.get());
+ __locale::__lconv_t* lc = __locale::__localeconv(loc.get());
if (!checked_string_to_wchar_convert(__decimal_point_, lc->mon_decimal_point, loc.get()))
__decimal_point_ = base::do_decimal_point();
if (!checked_string_to_wchar_convert(__thousands_sep_, lc->mon_thousands_sep, loc.get()))
@@ -5578,7 +5578,7 @@ void moneypunct_byname<wchar_t, true>::init(const char* nm) {
if (!loc)
__throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str());
- lconv* lc = __locale::__localeconv(loc.get());
+ __locale::__lconv_t* lc = __locale::__localeconv(loc.get());
if (!checked_string_to_wchar_convert(__decimal_point_, lc->mon_decimal_point, loc.get()))
__decimal_point_ = base::do_decimal_point();
if (!checked_string_to_wchar_convert(__thousands_sep_, lc->mon_thousands_sep, loc.get()))
diff --git a/libcxx/src/support/win32/locale_win32.cpp b/libcxx/src/support/win32/locale_win32.cpp
index ec2dd7f36ec709..24402e818d95d5 100644
--- a/libcxx/src/support/win32/locale_win32.cpp
+++ b/libcxx/src/support/win32/locale_win32.cpp
@@ -26,7 +26,7 @@ __locale_t __newlocale(int /*mask*/, const char* locale, ...
[truncated]
|
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 a BSD-like public API.
c710a41
to
79525c9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need this if we already have the standard std::lconv
? Same for setlocale. For the mask ones, are these equivalent to the standard versions without the _MASK
prefix, or do the mask versions represent something distinct?
The issue is that platforms who don't provide localization support generally don't provide
I think it depends on the platform. Some platforms provide those macros (e.g. https://man7.org/linux/man-pages/man3/newlocale.3.html) but other platforms don't. In the case of platforms that do provide these macros, I don't know if they are equivalent to our definition in libc++, but I'd assume they might not be. Was that your question? Basically, this patch makes it such that the whole localization support of libc++ is implemented on top of the API documented in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need this if we already have the standard
std::lconv
? Same for setlocale.The issue is that platforms who don't provide localization support generally don't provide
lconv
andsetlocale
. I am moving towards emulating the C locale on such platforms in the_LIBCPP_HAS_LOCALIZATION == 0
case, and without introducing these internal names, I'd have to introduce these names when the underlying platform doesn't provide them.For the mask ones, are these equivalent to the standard versions without the
_MASK
prefix, or do the mask versions represent something distinct?I think it depends on the platform. Some platforms provide those macros (e.g. https://man7.org/linux/man-pages/man3/newlocale.3.html) but other platforms don't. In the case of platforms that do provide these macros, I don't know if they are equivalent to our definition in libc++, but I'd assume they might not be. Was that your question?
I was mostly wondering what exactly the difference between the two is, since it's not at all clear to me.
Basically, this patch makes it such that the whole localization support of libc++ is implemented on top of the API documented in
locale_base_api.h
, which gives us more flexibility to implement a locale emulation layer in the no-localization config, makes it easier to port to new platforms, etc. I do imagine that the API can then be simplified further, but this was the shortest path I could find to lifting all this API surface into something libc++ specific.
With the additional information that this is for support of platforms which don't support locales at all this patch makes a lot of sense. I think I was really confused by the commit message saying this is about non-BSD-like platforms. Could you update the commit message to just not mention BSD-like platforms at all? I think that would make it a lot clearer. Otherwise LGTM.
This patch adds the following pieces to the locale base API:
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.