xref: /openbsd-src/gnu/llvm/libcxx/include/__support/win32/locale_win32.h (revision 4bdff4bed0e3d54e55670334c7d0077db4170f86)
176d0caaeSpatrick // -*- C++ -*-
276d0caaeSpatrick //===-----------------------------------------------------------------------===//
376d0caaeSpatrick //
476d0caaeSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
576d0caaeSpatrick // See https://llvm.org/LICENSE.txt for license information.
676d0caaeSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
776d0caaeSpatrick //
876d0caaeSpatrick //===----------------------------------------------------------------------===//
976d0caaeSpatrick 
10*4bdff4beSrobert #ifndef _LIBCPP___SUPPORT_WIN32_LOCALE_WIN32_H
11*4bdff4beSrobert #define _LIBCPP___SUPPORT_WIN32_LOCALE_WIN32_H
1276d0caaeSpatrick 
1376d0caaeSpatrick #include <__config>
14*4bdff4beSrobert #include <cstddef>
1576d0caaeSpatrick #include <locale.h> // _locale_t
1676d0caaeSpatrick #include <stdio.h>
17*4bdff4beSrobert #include <string>
1876d0caaeSpatrick 
1976d0caaeSpatrick #define _X_ALL LC_ALL
2076d0caaeSpatrick #define _X_COLLATE LC_COLLATE
2176d0caaeSpatrick #define _X_CTYPE LC_CTYPE
2276d0caaeSpatrick #define _X_MONETARY LC_MONETARY
2376d0caaeSpatrick #define _X_NUMERIC LC_NUMERIC
2476d0caaeSpatrick #define _X_TIME LC_TIME
2576d0caaeSpatrick #define _X_MAX LC_MAX
2676d0caaeSpatrick #define _X_MESSAGES 6
2776d0caaeSpatrick #define _NCAT (_X_MESSAGES + 1)
2876d0caaeSpatrick 
2976d0caaeSpatrick #define _CATMASK(n) ((1 << (n)) >> 1)
3076d0caaeSpatrick #define _M_COLLATE _CATMASK(_X_COLLATE)
3176d0caaeSpatrick #define _M_CTYPE _CATMASK(_X_CTYPE)
3276d0caaeSpatrick #define _M_MONETARY _CATMASK(_X_MONETARY)
3376d0caaeSpatrick #define _M_NUMERIC _CATMASK(_X_NUMERIC)
3476d0caaeSpatrick #define _M_TIME _CATMASK(_X_TIME)
3576d0caaeSpatrick #define _M_MESSAGES _CATMASK(_X_MESSAGES)
3676d0caaeSpatrick #define _M_ALL (_CATMASK(_NCAT) - 1)
3776d0caaeSpatrick 
3876d0caaeSpatrick #define LC_COLLATE_MASK _M_COLLATE
3976d0caaeSpatrick #define LC_CTYPE_MASK _M_CTYPE
4076d0caaeSpatrick #define LC_MONETARY_MASK _M_MONETARY
4176d0caaeSpatrick #define LC_NUMERIC_MASK _M_NUMERIC
4276d0caaeSpatrick #define LC_TIME_MASK _M_TIME
4376d0caaeSpatrick #define LC_MESSAGES_MASK _M_MESSAGES
4476d0caaeSpatrick #define LC_ALL_MASK (  LC_COLLATE_MASK \
4576d0caaeSpatrick                      | LC_CTYPE_MASK \
4676d0caaeSpatrick                      | LC_MESSAGES_MASK \
4776d0caaeSpatrick                      | LC_MONETARY_MASK \
4876d0caaeSpatrick                      | LC_NUMERIC_MASK \
4976d0caaeSpatrick                      | LC_TIME_MASK )
5076d0caaeSpatrick 
5176d0caaeSpatrick class __lconv_storage {
5276d0caaeSpatrick public:
__lconv_storage(const lconv * __lc_input)5376d0caaeSpatrick     __lconv_storage(const lconv *__lc_input) {
54*4bdff4beSrobert         __lc_ = *__lc_input;
5576d0caaeSpatrick 
56*4bdff4beSrobert         __decimal_point_ = __lc_input->decimal_point;
57*4bdff4beSrobert         __thousands_sep_ = __lc_input->thousands_sep;
58*4bdff4beSrobert         __grouping_ = __lc_input->grouping;
59*4bdff4beSrobert         __int_curr_symbol_ = __lc_input->int_curr_symbol;
60*4bdff4beSrobert         __currency_symbol_ = __lc_input->currency_symbol;
61*4bdff4beSrobert         __mon_decimal_point_ = __lc_input->mon_decimal_point;
62*4bdff4beSrobert         __mon_thousands_sep_ = __lc_input->mon_thousands_sep;
63*4bdff4beSrobert         __mon_grouping_ = __lc_input->mon_grouping;
64*4bdff4beSrobert         __positive_sign_ = __lc_input->positive_sign;
65*4bdff4beSrobert         __negative_sign_ = __lc_input->negative_sign;
6676d0caaeSpatrick 
67*4bdff4beSrobert         __lc_.decimal_point = const_cast<char *>(__decimal_point_.c_str());
68*4bdff4beSrobert         __lc_.thousands_sep = const_cast<char *>(__thousands_sep_.c_str());
69*4bdff4beSrobert         __lc_.grouping = const_cast<char *>(__grouping_.c_str());
70*4bdff4beSrobert         __lc_.int_curr_symbol = const_cast<char *>(__int_curr_symbol_.c_str());
71*4bdff4beSrobert         __lc_.currency_symbol = const_cast<char *>(__currency_symbol_.c_str());
72*4bdff4beSrobert         __lc_.mon_decimal_point = const_cast<char *>(__mon_decimal_point_.c_str());
73*4bdff4beSrobert         __lc_.mon_thousands_sep = const_cast<char *>(__mon_thousands_sep_.c_str());
74*4bdff4beSrobert         __lc_.mon_grouping = const_cast<char *>(__mon_grouping_.c_str());
75*4bdff4beSrobert         __lc_.positive_sign = const_cast<char *>(__positive_sign_.c_str());
76*4bdff4beSrobert         __lc_.negative_sign = const_cast<char *>(__negative_sign_.c_str());
7776d0caaeSpatrick     }
7876d0caaeSpatrick 
__get()7976d0caaeSpatrick     lconv *__get() {
80*4bdff4beSrobert         return &__lc_;
8176d0caaeSpatrick     }
8276d0caaeSpatrick private:
83*4bdff4beSrobert     lconv __lc_;
84*4bdff4beSrobert     std::string __decimal_point_;
85*4bdff4beSrobert     std::string __thousands_sep_;
86*4bdff4beSrobert     std::string __grouping_;
87*4bdff4beSrobert     std::string __int_curr_symbol_;
88*4bdff4beSrobert     std::string __currency_symbol_;
89*4bdff4beSrobert     std::string __mon_decimal_point_;
90*4bdff4beSrobert     std::string __mon_thousands_sep_;
91*4bdff4beSrobert     std::string __mon_grouping_;
92*4bdff4beSrobert     std::string __positive_sign_;
93*4bdff4beSrobert     std::string __negative_sign_;
9476d0caaeSpatrick };
9576d0caaeSpatrick 
9676d0caaeSpatrick class locale_t {
9776d0caaeSpatrick public:
locale_t()9876d0caaeSpatrick     locale_t()
99*4bdff4beSrobert         : __locale_(nullptr), __locale_str_(nullptr), __lc_(nullptr) {}
locale_t(std::nullptr_t)10076d0caaeSpatrick     locale_t(std::nullptr_t)
101*4bdff4beSrobert         : __locale_(nullptr), __locale_str_(nullptr), __lc_(nullptr) {}
locale_t(_locale_t __xlocale,const char * __xlocale_str)10276d0caaeSpatrick     locale_t(_locale_t __xlocale, const char* __xlocale_str)
103*4bdff4beSrobert         : __locale_(__xlocale), __locale_str_(__xlocale_str), __lc_(nullptr) {}
locale_t(const locale_t & __l)10476d0caaeSpatrick     locale_t(const locale_t &__l)
105*4bdff4beSrobert         : __locale_(__l.__locale_), __locale_str_(__l.__locale_str_), __lc_(nullptr) {}
10676d0caaeSpatrick 
~locale_t()10776d0caaeSpatrick     ~locale_t() {
108*4bdff4beSrobert         delete __lc_;
10976d0caaeSpatrick     }
11076d0caaeSpatrick 
11176d0caaeSpatrick     locale_t &operator =(const locale_t &__l) {
112*4bdff4beSrobert         __locale_ = __l.__locale_;
113*4bdff4beSrobert         __locale_str_ = __l.__locale_str_;
114*4bdff4beSrobert         // __lc_ not copied
11576d0caaeSpatrick         return *this;
11676d0caaeSpatrick     }
11776d0caaeSpatrick 
11876d0caaeSpatrick     friend bool operator==(const locale_t& __left, const locale_t& __right) {
119*4bdff4beSrobert         return __left.__locale_ == __right.__locale_;
12076d0caaeSpatrick     }
12176d0caaeSpatrick 
12276d0caaeSpatrick     friend bool operator==(const locale_t& __left, int __right) {
123*4bdff4beSrobert         return __left.__locale_ == nullptr && __right == 0;
12476d0caaeSpatrick     }
12576d0caaeSpatrick 
12676d0caaeSpatrick     friend bool operator==(const locale_t& __left, long long __right) {
127*4bdff4beSrobert         return __left.__locale_ == nullptr && __right == 0;
12876d0caaeSpatrick     }
12976d0caaeSpatrick 
13076d0caaeSpatrick     friend bool operator==(const locale_t& __left, std::nullptr_t) {
131*4bdff4beSrobert         return __left.__locale_ == nullptr;
13276d0caaeSpatrick     }
13376d0caaeSpatrick 
13476d0caaeSpatrick     friend bool operator==(int __left, const locale_t& __right) {
135*4bdff4beSrobert         return __left == 0 && nullptr == __right.__locale_;
13676d0caaeSpatrick     }
13776d0caaeSpatrick 
13876d0caaeSpatrick     friend bool operator==(std::nullptr_t, const locale_t& __right) {
139*4bdff4beSrobert         return nullptr == __right.__locale_;
14076d0caaeSpatrick     }
14176d0caaeSpatrick 
14276d0caaeSpatrick     friend bool operator!=(const locale_t& __left, const locale_t& __right) {
14376d0caaeSpatrick         return !(__left == __right);
14476d0caaeSpatrick     }
14576d0caaeSpatrick 
14676d0caaeSpatrick     friend bool operator!=(const locale_t& __left, int __right) {
14776d0caaeSpatrick         return !(__left == __right);
14876d0caaeSpatrick     }
14976d0caaeSpatrick 
15076d0caaeSpatrick     friend bool operator!=(const locale_t& __left, long long __right) {
15176d0caaeSpatrick         return !(__left == __right);
15276d0caaeSpatrick     }
15376d0caaeSpatrick 
15476d0caaeSpatrick     friend bool operator!=(const locale_t& __left, std::nullptr_t __right) {
15576d0caaeSpatrick         return !(__left == __right);
15676d0caaeSpatrick     }
15776d0caaeSpatrick 
15876d0caaeSpatrick     friend bool operator!=(int __left, const locale_t& __right) {
15976d0caaeSpatrick         return !(__left == __right);
16076d0caaeSpatrick     }
16176d0caaeSpatrick 
16276d0caaeSpatrick     friend bool operator!=(std::nullptr_t __left, const locale_t& __right) {
16376d0caaeSpatrick         return !(__left == __right);
16476d0caaeSpatrick     }
16576d0caaeSpatrick 
16676d0caaeSpatrick     operator bool() const {
167*4bdff4beSrobert         return __locale_ != nullptr;
16876d0caaeSpatrick     }
16976d0caaeSpatrick 
__get_locale()170*4bdff4beSrobert     const char* __get_locale() const { return __locale_str_; }
17176d0caaeSpatrick 
_locale_t()17276d0caaeSpatrick     operator _locale_t() const {
173*4bdff4beSrobert         return __locale_;
17476d0caaeSpatrick     }
17576d0caaeSpatrick 
__store_lconv(const lconv * __input_lc)17676d0caaeSpatrick     lconv *__store_lconv(const lconv *__input_lc) {
177*4bdff4beSrobert         delete __lc_;
178*4bdff4beSrobert         __lc_ = new __lconv_storage(__input_lc);
179*4bdff4beSrobert         return __lc_->__get();
18076d0caaeSpatrick     }
18176d0caaeSpatrick private:
182*4bdff4beSrobert     _locale_t __locale_;
183*4bdff4beSrobert     const char* __locale_str_;
184*4bdff4beSrobert     __lconv_storage *__lc_ = nullptr;
18576d0caaeSpatrick };
18676d0caaeSpatrick 
18776d0caaeSpatrick // Locale management functions
18876d0caaeSpatrick #define freelocale _free_locale
18976d0caaeSpatrick // FIXME: base currently unused. Needs manual work to construct the new locale
190*4bdff4beSrobert locale_t newlocale( int __mask, const char * __locale, locale_t __base );
19176d0caaeSpatrick // uselocale can't be implemented on Windows because Windows allows partial modification
19276d0caaeSpatrick // of thread-local locale and so _get_current_locale() returns a copy while uselocale does
19376d0caaeSpatrick // not create any copies.
19476d0caaeSpatrick // We can still implement raii even without uselocale though.
19576d0caaeSpatrick 
19676d0caaeSpatrick 
197*4bdff4beSrobert lconv *localeconv_l( locale_t & __loc );
198*4bdff4beSrobert size_t mbrlen_l( const char *__restrict __s, size_t __n,
199*4bdff4beSrobert                  mbstate_t *__restrict __ps, locale_t __loc);
200*4bdff4beSrobert size_t mbsrtowcs_l( wchar_t *__restrict __dst, const char **__restrict __src,
201*4bdff4beSrobert                     size_t __len, mbstate_t *__restrict __ps, locale_t __loc );
202*4bdff4beSrobert size_t wcrtomb_l( char *__restrict __s, wchar_t __wc, mbstate_t *__restrict __ps,
203*4bdff4beSrobert                   locale_t __loc);
204*4bdff4beSrobert size_t mbrtowc_l( wchar_t *__restrict __pwc, const char *__restrict __s,
205*4bdff4beSrobert                   size_t __n, mbstate_t *__restrict __ps, locale_t __loc);
206*4bdff4beSrobert size_t mbsnrtowcs_l( wchar_t *__restrict __dst, const char **__restrict __src,
207*4bdff4beSrobert                      size_t __nms, size_t __len, mbstate_t *__restrict __ps, locale_t __loc);
208*4bdff4beSrobert size_t wcsnrtombs_l( char *__restrict __dst, const wchar_t **__restrict __src,
209*4bdff4beSrobert                      size_t __nwc, size_t __len, mbstate_t *__restrict __ps, locale_t __loc);
210*4bdff4beSrobert wint_t btowc_l( int __c, locale_t __loc );
211*4bdff4beSrobert int wctob_l( wint_t __c, locale_t __loc );
21276d0caaeSpatrick 
21376d0caaeSpatrick decltype(MB_CUR_MAX) MB_CUR_MAX_L( locale_t __l );
21476d0caaeSpatrick 
21576d0caaeSpatrick // the *_l functions are prefixed on Windows, only available for msvcr80+, VS2005+
21676d0caaeSpatrick #define mbtowc_l _mbtowc_l
21776d0caaeSpatrick #define strtoll_l _strtoi64_l
21876d0caaeSpatrick #define strtoull_l _strtoui64_l
21976d0caaeSpatrick #define strtod_l _strtod_l
22076d0caaeSpatrick #if defined(_LIBCPP_MSVCRT)
22176d0caaeSpatrick #define strtof_l _strtof_l
22276d0caaeSpatrick #define strtold_l _strtold_l
22376d0caaeSpatrick #else
22476d0caaeSpatrick _LIBCPP_FUNC_VIS float strtof_l(const char*, char**, locale_t);
22576d0caaeSpatrick _LIBCPP_FUNC_VIS long double strtold_l(const char*, char**, locale_t);
22676d0caaeSpatrick #endif
227*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI int
islower_l(int __c,_locale_t __loc)228*4bdff4beSrobert islower_l(int __c, _locale_t __loc)
22976d0caaeSpatrick {
230*4bdff4beSrobert  return _islower_l((int)__c, __loc);
23176d0caaeSpatrick }
23276d0caaeSpatrick 
233*4bdff4beSrobert inline _LIBCPP_HIDE_FROM_ABI int
isupper_l(int __c,_locale_t __loc)234*4bdff4beSrobert isupper_l(int __c, _locale_t __loc)
23576d0caaeSpatrick {
236*4bdff4beSrobert  return _isupper_l((int)__c, __loc);
23776d0caaeSpatrick }
23876d0caaeSpatrick 
23976d0caaeSpatrick #define isdigit_l _isdigit_l
24076d0caaeSpatrick #define isxdigit_l _isxdigit_l
24176d0caaeSpatrick #define strcoll_l _strcoll_l
24276d0caaeSpatrick #define strxfrm_l _strxfrm_l
24376d0caaeSpatrick #define wcscoll_l _wcscoll_l
24476d0caaeSpatrick #define wcsxfrm_l _wcsxfrm_l
24576d0caaeSpatrick #define toupper_l _toupper_l
24676d0caaeSpatrick #define tolower_l _tolower_l
24776d0caaeSpatrick #define iswspace_l _iswspace_l
24876d0caaeSpatrick #define iswprint_l _iswprint_l
24976d0caaeSpatrick #define iswcntrl_l _iswcntrl_l
25076d0caaeSpatrick #define iswupper_l _iswupper_l
25176d0caaeSpatrick #define iswlower_l _iswlower_l
25276d0caaeSpatrick #define iswalpha_l _iswalpha_l
25376d0caaeSpatrick #define iswdigit_l _iswdigit_l
25476d0caaeSpatrick #define iswpunct_l _iswpunct_l
25576d0caaeSpatrick #define iswxdigit_l _iswxdigit_l
25676d0caaeSpatrick #define towupper_l _towupper_l
25776d0caaeSpatrick #define towlower_l _towlower_l
25876d0caaeSpatrick #if defined(__MINGW32__) && __MSVCRT_VERSION__ < 0x0800
25976d0caaeSpatrick _LIBCPP_FUNC_VIS size_t strftime_l(char *ret, size_t n, const char *format,
26076d0caaeSpatrick                                    const struct tm *tm, locale_t loc);
26176d0caaeSpatrick #else
26276d0caaeSpatrick #define strftime_l _strftime_l
26376d0caaeSpatrick #endif
26476d0caaeSpatrick #define sscanf_l( __s, __l, __f, ...) _sscanf_l( __s, __f, __l, __VA_ARGS__ )
26576d0caaeSpatrick #define sprintf_l( __s, __l, __f, ... ) _sprintf_l( __s, __f, __l, __VA_ARGS__ )
26676d0caaeSpatrick #define vsprintf_l( __s, __l, __f, ... ) _vsprintf_l( __s, __f, __l, __VA_ARGS__ )
26776d0caaeSpatrick #define vsnprintf_l( __s, __n, __l, __f, ... ) _vsnprintf_l( __s, __n, __f, __l, __VA_ARGS__ )
268*4bdff4beSrobert _LIBCPP_FUNC_VIS int snprintf_l(char *__ret, size_t __n, locale_t __loc, const char *__format, ...);
269*4bdff4beSrobert _LIBCPP_FUNC_VIS int asprintf_l( char **__ret, locale_t __loc, const char *__format, ... );
270*4bdff4beSrobert _LIBCPP_FUNC_VIS int vasprintf_l( char **__ret, locale_t __loc, const char *__format, va_list __ap );
27176d0caaeSpatrick 
27276d0caaeSpatrick // not-so-pressing FIXME: use locale to determine blank characters
isblank_l(int __c,locale_t)273*4bdff4beSrobert inline int isblank_l( int __c, locale_t /*loc*/ )
27476d0caaeSpatrick {
275*4bdff4beSrobert     return ( __c == ' ' || __c == '\t' );
27676d0caaeSpatrick }
iswblank_l(wint_t __c,locale_t)277*4bdff4beSrobert inline int iswblank_l( wint_t __c, locale_t /*loc*/ )
27876d0caaeSpatrick {
279*4bdff4beSrobert     return ( __c == L' ' || __c == L'\t' );
28076d0caaeSpatrick }
28176d0caaeSpatrick 
282*4bdff4beSrobert #endif // _LIBCPP___SUPPORT_WIN32_LOCALE_WIN32_H
283