1// -*- C++ -*- 2//===-----------------------------------------------------------------------===// 3// 4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5// See https://llvm.org/LICENSE.txt for license information. 6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef _LIBCPP_SUPPORT_WIN32_LOCALE_WIN32_H 11#define _LIBCPP_SUPPORT_WIN32_LOCALE_WIN32_H 12 13#include <__config> 14#include <__nullptr> 15#include <locale.h> // _locale_t 16#include <stdio.h> 17 18#define _X_ALL LC_ALL 19#define _X_COLLATE LC_COLLATE 20#define _X_CTYPE LC_CTYPE 21#define _X_MONETARY LC_MONETARY 22#define _X_NUMERIC LC_NUMERIC 23#define _X_TIME LC_TIME 24#define _X_MAX LC_MAX 25#define _X_MESSAGES 6 26#define _NCAT (_X_MESSAGES + 1) 27 28#define _CATMASK(n) ((1 << (n)) >> 1) 29#define _M_COLLATE _CATMASK(_X_COLLATE) 30#define _M_CTYPE _CATMASK(_X_CTYPE) 31#define _M_MONETARY _CATMASK(_X_MONETARY) 32#define _M_NUMERIC _CATMASK(_X_NUMERIC) 33#define _M_TIME _CATMASK(_X_TIME) 34#define _M_MESSAGES _CATMASK(_X_MESSAGES) 35#define _M_ALL (_CATMASK(_NCAT) - 1) 36 37#define LC_COLLATE_MASK _M_COLLATE 38#define LC_CTYPE_MASK _M_CTYPE 39#define LC_MONETARY_MASK _M_MONETARY 40#define LC_NUMERIC_MASK _M_NUMERIC 41#define LC_TIME_MASK _M_TIME 42#define LC_MESSAGES_MASK _M_MESSAGES 43#define LC_ALL_MASK ( LC_COLLATE_MASK \ 44 | LC_CTYPE_MASK \ 45 | LC_MESSAGES_MASK \ 46 | LC_MONETARY_MASK \ 47 | LC_NUMERIC_MASK \ 48 | LC_TIME_MASK ) 49 50class __lconv_storage { 51public: 52 __lconv_storage(const lconv *__lc_input) { 53 __lc = *__lc_input; 54 55 __decimal_point = __lc_input->decimal_point; 56 __thousands_sep = __lc_input->thousands_sep; 57 __grouping = __lc_input->grouping; 58 __int_curr_symbol = __lc_input->int_curr_symbol; 59 __currency_symbol = __lc_input->currency_symbol; 60 __mon_decimal_point = __lc_input->mon_decimal_point; 61 __mon_thousands_sep = __lc_input->mon_thousands_sep; 62 __mon_grouping = __lc_input->mon_grouping; 63 __positive_sign = __lc_input->positive_sign; 64 __negative_sign = __lc_input->negative_sign; 65 66 __lc.decimal_point = const_cast<char *>(__decimal_point.c_str()); 67 __lc.thousands_sep = const_cast<char *>(__thousands_sep.c_str()); 68 __lc.grouping = const_cast<char *>(__grouping.c_str()); 69 __lc.int_curr_symbol = const_cast<char *>(__int_curr_symbol.c_str()); 70 __lc.currency_symbol = const_cast<char *>(__currency_symbol.c_str()); 71 __lc.mon_decimal_point = const_cast<char *>(__mon_decimal_point.c_str()); 72 __lc.mon_thousands_sep = const_cast<char *>(__mon_thousands_sep.c_str()); 73 __lc.mon_grouping = const_cast<char *>(__mon_grouping.c_str()); 74 __lc.positive_sign = const_cast<char *>(__positive_sign.c_str()); 75 __lc.negative_sign = const_cast<char *>(__negative_sign.c_str()); 76 } 77 78 lconv *__get() { 79 return &__lc; 80 } 81private: 82 lconv __lc; 83 std::string __decimal_point; 84 std::string __thousands_sep; 85 std::string __grouping; 86 std::string __int_curr_symbol; 87 std::string __currency_symbol; 88 std::string __mon_decimal_point; 89 std::string __mon_thousands_sep; 90 std::string __mon_grouping; 91 std::string __positive_sign; 92 std::string __negative_sign; 93}; 94 95class locale_t { 96public: 97 locale_t() 98 : __locale(nullptr), __locale_str(nullptr), __lc(nullptr) {} 99 locale_t(std::nullptr_t) 100 : __locale(nullptr), __locale_str(nullptr), __lc(nullptr) {} 101 locale_t(_locale_t __xlocale, const char* __xlocale_str) 102 : __locale(__xlocale), __locale_str(__xlocale_str), __lc(nullptr) {} 103 locale_t(const locale_t &__l) 104 : __locale(__l.__locale), __locale_str(__l.__locale_str), __lc(nullptr) {} 105 106 ~locale_t() { 107 delete __lc; 108 } 109 110 locale_t &operator =(const locale_t &__l) { 111 __locale = __l.__locale; 112 __locale_str = __l.__locale_str; 113 // __lc not copied 114 return *this; 115 } 116 117 friend bool operator==(const locale_t& __left, const locale_t& __right) { 118 return __left.__locale == __right.__locale; 119 } 120 121 friend bool operator==(const locale_t& __left, int __right) { 122 return __left.__locale == nullptr && __right == 0; 123 } 124 125 friend bool operator==(const locale_t& __left, long long __right) { 126 return __left.__locale == nullptr && __right == 0; 127 } 128 129 friend bool operator==(const locale_t& __left, std::nullptr_t) { 130 return __left.__locale == nullptr; 131 } 132 133 friend bool operator==(int __left, const locale_t& __right) { 134 return __left == 0 && nullptr == __right.__locale; 135 } 136 137 friend bool operator==(std::nullptr_t, const locale_t& __right) { 138 return nullptr == __right.__locale; 139 } 140 141 friend bool operator!=(const locale_t& __left, const locale_t& __right) { 142 return !(__left == __right); 143 } 144 145 friend bool operator!=(const locale_t& __left, int __right) { 146 return !(__left == __right); 147 } 148 149 friend bool operator!=(const locale_t& __left, long long __right) { 150 return !(__left == __right); 151 } 152 153 friend bool operator!=(const locale_t& __left, std::nullptr_t __right) { 154 return !(__left == __right); 155 } 156 157 friend bool operator!=(int __left, const locale_t& __right) { 158 return !(__left == __right); 159 } 160 161 friend bool operator!=(std::nullptr_t __left, const locale_t& __right) { 162 return !(__left == __right); 163 } 164 165 operator bool() const { 166 return __locale != nullptr; 167 } 168 169 const char* __get_locale() const { return __locale_str; } 170 171 operator _locale_t() const { 172 return __locale; 173 } 174 175 lconv *__store_lconv(const lconv *__input_lc) { 176 delete __lc; 177 __lc = new __lconv_storage(__input_lc); 178 return __lc->__get(); 179 } 180private: 181 _locale_t __locale; 182 const char* __locale_str; 183 __lconv_storage *__lc = nullptr; 184}; 185 186// Locale management functions 187#define freelocale _free_locale 188// FIXME: base currently unused. Needs manual work to construct the new locale 189locale_t newlocale( int mask, const char * locale, locale_t base ); 190// uselocale can't be implemented on Windows because Windows allows partial modification 191// of thread-local locale and so _get_current_locale() returns a copy while uselocale does 192// not create any copies. 193// We can still implement raii even without uselocale though. 194 195 196lconv *localeconv_l( locale_t &loc ); 197size_t mbrlen_l( const char *__restrict s, size_t n, 198 mbstate_t *__restrict ps, locale_t loc); 199size_t mbsrtowcs_l( wchar_t *__restrict dst, const char **__restrict src, 200 size_t len, mbstate_t *__restrict ps, locale_t loc ); 201size_t wcrtomb_l( char *__restrict s, wchar_t wc, mbstate_t *__restrict ps, 202 locale_t loc); 203size_t mbrtowc_l( wchar_t *__restrict pwc, const char *__restrict s, 204 size_t n, mbstate_t *__restrict ps, locale_t loc); 205size_t mbsnrtowcs_l( wchar_t *__restrict dst, const char **__restrict src, 206 size_t nms, size_t len, mbstate_t *__restrict ps, locale_t loc); 207size_t wcsnrtombs_l( char *__restrict dst, const wchar_t **__restrict src, 208 size_t nwc, size_t len, mbstate_t *__restrict ps, locale_t loc); 209wint_t btowc_l( int c, locale_t loc ); 210int wctob_l( wint_t c, locale_t loc ); 211 212decltype(MB_CUR_MAX) MB_CUR_MAX_L( locale_t __l ); 213 214// the *_l functions are prefixed on Windows, only available for msvcr80+, VS2005+ 215#define mbtowc_l _mbtowc_l 216#define strtoll_l _strtoi64_l 217#define strtoull_l _strtoui64_l 218#define strtod_l _strtod_l 219#if defined(_LIBCPP_MSVCRT) 220#define strtof_l _strtof_l 221#define strtold_l _strtold_l 222#else 223_LIBCPP_FUNC_VIS float strtof_l(const char*, char**, locale_t); 224_LIBCPP_FUNC_VIS long double strtold_l(const char*, char**, locale_t); 225#endif 226inline _LIBCPP_INLINE_VISIBILITY 227int 228islower_l(int c, _locale_t loc) 229{ 230 return _islower_l((int)c, loc); 231} 232 233inline _LIBCPP_INLINE_VISIBILITY 234int 235isupper_l(int c, _locale_t loc) 236{ 237 return _isupper_l((int)c, loc); 238} 239 240#define isdigit_l _isdigit_l 241#define isxdigit_l _isxdigit_l 242#define strcoll_l _strcoll_l 243#define strxfrm_l _strxfrm_l 244#define wcscoll_l _wcscoll_l 245#define wcsxfrm_l _wcsxfrm_l 246#define toupper_l _toupper_l 247#define tolower_l _tolower_l 248#define iswspace_l _iswspace_l 249#define iswprint_l _iswprint_l 250#define iswcntrl_l _iswcntrl_l 251#define iswupper_l _iswupper_l 252#define iswlower_l _iswlower_l 253#define iswalpha_l _iswalpha_l 254#define iswdigit_l _iswdigit_l 255#define iswpunct_l _iswpunct_l 256#define iswxdigit_l _iswxdigit_l 257#define towupper_l _towupper_l 258#define towlower_l _towlower_l 259#if defined(__MINGW32__) && __MSVCRT_VERSION__ < 0x0800 260_LIBCPP_FUNC_VIS size_t strftime_l(char *ret, size_t n, const char *format, 261 const struct tm *tm, locale_t loc); 262#else 263#define strftime_l _strftime_l 264#endif 265#define sscanf_l( __s, __l, __f, ...) _sscanf_l( __s, __f, __l, __VA_ARGS__ ) 266#define sprintf_l( __s, __l, __f, ... ) _sprintf_l( __s, __f, __l, __VA_ARGS__ ) 267#define vsprintf_l( __s, __l, __f, ... ) _vsprintf_l( __s, __f, __l, __VA_ARGS__ ) 268#define vsnprintf_l( __s, __n, __l, __f, ... ) _vsnprintf_l( __s, __n, __f, __l, __VA_ARGS__ ) 269_LIBCPP_FUNC_VIS int snprintf_l(char *ret, size_t n, locale_t loc, const char *format, ...); 270_LIBCPP_FUNC_VIS int asprintf_l( char **ret, locale_t loc, const char *format, ... ); 271_LIBCPP_FUNC_VIS int vasprintf_l( char **ret, locale_t loc, const char *format, va_list ap ); 272 273// not-so-pressing FIXME: use locale to determine blank characters 274inline int isblank_l( int c, locale_t /*loc*/ ) 275{ 276 return ( c == ' ' || c == '\t' ); 277} 278inline int iswblank_l( wint_t c, locale_t /*loc*/ ) 279{ 280 return ( c == L' ' || c == L'\t' ); 281} 282 283#endif // _LIBCPP_SUPPORT_WIN32_LOCALE_WIN32_H 284