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