1//===-----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef _LIBCPP___LOCALE_DIR_SUPPORT_LINUX_H
10#define _LIBCPP___LOCALE_DIR_SUPPORT_LINUX_H
11
12#include <__config>
13#include <__cstddef/size_t.h>
14#include <__std_mbstate_t.h>
15#include <__utility/forward.h>
16#include <clocale> // std::lconv
17#include <cstdio>
18#include <cstdlib>
19#include <ctype.h>
20#if defined(_LIBCPP_BUILDING_LIBRARY)
21# include <langinfo.h>
22#endif
23#include <stdarg.h>
24#include <string.h>
25#include <time.h>
26#if _LIBCPP_HAS_WIDE_CHARACTERS
27# include <cwchar>
28# include <wctype.h>
29#endif
30
31#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
32# pragma GCC system_header
33#endif
34
35_LIBCPP_BEGIN_NAMESPACE_STD
36namespace __locale {
37
38struct __locale_guard {
39 _LIBCPP_HIDE_FROM_ABI __locale_guard(locale_t __loc) : __old_loc_(::uselocale(dataset: __loc)) {}
40
41 _LIBCPP_HIDE_FROM_ABI ~__locale_guard() {
42 if (__old_loc_)
43 ::uselocale(dataset: __old_loc_);
44 }
45
46 locale_t __old_loc_;
47
48 __locale_guard(__locale_guard const&) = delete;
49 __locale_guard& operator=(__locale_guard const&) = delete;
50};
51
52//
53// Locale management
54//
55#define _LIBCPP_COLLATE_MASK LC_COLLATE_MASK
56#define _LIBCPP_CTYPE_MASK LC_CTYPE_MASK
57#define _LIBCPP_MONETARY_MASK LC_MONETARY_MASK
58#define _LIBCPP_NUMERIC_MASK LC_NUMERIC_MASK
59#define _LIBCPP_TIME_MASK LC_TIME_MASK
60#define _LIBCPP_MESSAGES_MASK LC_MESSAGES_MASK
61#define _LIBCPP_ALL_MASK LC_ALL_MASK
62#define _LIBCPP_LC_ALL LC_ALL
63
64using __locale_t _LIBCPP_NODEBUG = ::locale_t;
65
66// Forward declared for use below.
67inline __locale_t __get_c_locale();
68
69#if defined(_LIBCPP_BUILDING_LIBRARY)
70using __lconv_t _LIBCPP_NODEBUG = std::lconv;
71
72inline _LIBCPP_HIDE_FROM_ABI __locale_t __newlocale(int __category_mask, const char* __locale, __locale_t __base) {
73 return ::newlocale(__category_mask, __locale, __base);
74}
75
76inline _LIBCPP_HIDE_FROM_ABI void __freelocale(__locale_t __loc) { ::freelocale(dataset: __loc); }
77
78inline _LIBCPP_HIDE_FROM_ABI char* __setlocale(int __category, char const* __locale) {
79 return ::setlocale(__category, __locale);
80}
81
82inline _LIBCPP_HIDE_FROM_ABI __lconv_t* __localeconv(__locale_t& __loc) {
83 __locale_guard __current(__loc);
84 return std::localeconv();
85}
86#endif // _LIBCPP_BUILDING_LIBRARY
87
88//
89// Strtonum functions
90//
91template <class _FloatT>
92_LIBCPP_HIDE_FROM_ABI _FloatT __str_to_float_c_locale(const char* __nptr, char** __endptr);
93
94template <>
95inline _LIBCPP_HIDE_FROM_ABI float __str_to_float_c_locale<float>(const char* __nptr, char** __endptr) {
96 return ::strtof_l(__nptr, __endptr, loc: __get_c_locale());
97}
98
99template <>
100inline _LIBCPP_HIDE_FROM_ABI double __str_to_float_c_locale<double>(const char* __nptr, char** __endptr) {
101 return ::strtod_l(__nptr, __endptr, loc: __get_c_locale());
102}
103
104template <>
105inline _LIBCPP_HIDE_FROM_ABI long double __str_to_float_c_locale<long double>(const char* __nptr, char** __endptr) {
106 return ::strtold_l(__nptr, __endptr, loc: __get_c_locale());
107}
108
109//
110// Character manipulation functions
111//
112#if defined(_LIBCPP_BUILDING_LIBRARY)
113inline _LIBCPP_HIDE_FROM_ABI int __toupper(int __c, __locale_t __loc) { return toupper_l(__c, l: __loc); }
114
115inline _LIBCPP_HIDE_FROM_ABI int __tolower(int __c, __locale_t __loc) { return tolower_l(__c, l: __loc); }
116
117inline _LIBCPP_HIDE_FROM_ABI int __strcoll(const char* __s1, const char* __s2, __locale_t __loc) {
118 return strcoll_l(__s1, __s2, l: __loc);
119}
120
121inline _LIBCPP_HIDE_FROM_ABI size_t __strxfrm(char* __dest, const char* __src, size_t __n, __locale_t __loc) {
122 return strxfrm_l(__dest, __src, __n, l: __loc);
123}
124
125# if _LIBCPP_HAS_WIDE_CHARACTERS
126inline _LIBCPP_HIDE_FROM_ABI int __iswctype(wint_t __c, wctype_t __type, __locale_t __loc) {
127 return iswctype_l(wc: __c, desc: __type, locale: __loc);
128}
129
130inline _LIBCPP_HIDE_FROM_ABI int __iswspace(wint_t __c, __locale_t __loc) { return iswspace_l(wc: __c, locale: __loc); }
131
132inline _LIBCPP_HIDE_FROM_ABI int __iswprint(wint_t __c, __locale_t __loc) { return iswprint_l(wc: __c, locale: __loc); }
133
134inline _LIBCPP_HIDE_FROM_ABI int __iswcntrl(wint_t __c, __locale_t __loc) { return iswcntrl_l(wc: __c, locale: __loc); }
135
136inline _LIBCPP_HIDE_FROM_ABI int __iswupper(wint_t __c, __locale_t __loc) { return iswupper_l(wc: __c, locale: __loc); }
137
138inline _LIBCPP_HIDE_FROM_ABI int __iswlower(wint_t __c, __locale_t __loc) { return iswlower_l(wc: __c, locale: __loc); }
139
140inline _LIBCPP_HIDE_FROM_ABI int __iswalpha(wint_t __c, __locale_t __loc) { return iswalpha_l(wc: __c, locale: __loc); }
141
142inline _LIBCPP_HIDE_FROM_ABI int __iswblank(wint_t __c, __locale_t __loc) { return iswblank_l(wc: __c, locale: __loc); }
143
144inline _LIBCPP_HIDE_FROM_ABI int __iswdigit(wint_t __c, __locale_t __loc) { return iswdigit_l(wc: __c, locale: __loc); }
145
146inline _LIBCPP_HIDE_FROM_ABI int __iswpunct(wint_t __c, __locale_t __loc) { return iswpunct_l(wc: __c, locale: __loc); }
147
148inline _LIBCPP_HIDE_FROM_ABI int __iswxdigit(wint_t __c, __locale_t __loc) { return iswxdigit_l(wc: __c, locale: __loc); }
149
150inline _LIBCPP_HIDE_FROM_ABI wint_t __towupper(wint_t __c, __locale_t __loc) { return towupper_l(wc: __c, locale: __loc); }
151
152inline _LIBCPP_HIDE_FROM_ABI wint_t __towlower(wint_t __c, __locale_t __loc) { return towlower_l(wc: __c, locale: __loc); }
153
154inline _LIBCPP_HIDE_FROM_ABI int __wcscoll(const wchar_t* __ws1, const wchar_t* __ws2, __locale_t __loc) {
155 return wcscoll_l(s1: __ws1, s2: __ws2, __loc);
156}
157
158inline _LIBCPP_HIDE_FROM_ABI size_t __wcsxfrm(wchar_t* __dest, const wchar_t* __src, size_t __n, __locale_t __loc) {
159 return wcsxfrm_l(s1: __dest, s2: __src, __n, __loc);
160}
161# endif // _LIBCPP_HAS_WIDE_CHARACTERS
162
163inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_ATTRIBUTE_FORMAT(__strftime__, 3, 0) size_t
164 __strftime(char* __s, size_t __max, const char* __format, const struct tm* __tm, __locale_t __loc) {
165 return strftime_l(__s, maxsize: __max, __format, tp: __tm, __loc);
166}
167
168//
169// Other functions
170//
171inline _LIBCPP_HIDE_FROM_ABI decltype(MB_CUR_MAX) __mb_len_max(__locale_t __loc) {
172 __locale_guard __current(__loc);
173 return MB_CUR_MAX;
174}
175
176# if _LIBCPP_HAS_WIDE_CHARACTERS
177inline _LIBCPP_HIDE_FROM_ABI wint_t __btowc(int __c, __locale_t __loc) {
178 __locale_guard __current(__loc);
179 return std::btowc(__c);
180}
181
182inline _LIBCPP_HIDE_FROM_ABI int __wctob(wint_t __c, __locale_t __loc) {
183 __locale_guard __current(__loc);
184 return std::wctob(wc: __c);
185}
186
187inline _LIBCPP_HIDE_FROM_ABI size_t
188__wcsnrtombs(char* __dest, const wchar_t** __src, size_t __nwc, size_t __len, mbstate_t* __ps, __locale_t __loc) {
189 __locale_guard __current(__loc);
190 return ::wcsnrtombs(dst: __dest, __src, __nwc, __len, __ps); // non-standard
191}
192
193inline _LIBCPP_HIDE_FROM_ABI size_t __wcrtomb(char* __s, wchar_t __wc, mbstate_t* __ps, __locale_t __loc) {
194 __locale_guard __current(__loc);
195 return std::wcrtomb(__s, __wc, __ps);
196}
197
198inline _LIBCPP_HIDE_FROM_ABI size_t
199__mbsnrtowcs(wchar_t* __dest, const char** __src, size_t __nms, size_t __len, mbstate_t* __ps, __locale_t __loc) {
200 __locale_guard __current(__loc);
201 return ::mbsnrtowcs(dst: __dest, __src, nmc: __nms, __len, __ps); // non-standard
202}
203
204inline _LIBCPP_HIDE_FROM_ABI size_t
205__mbrtowc(wchar_t* __pwc, const char* __s, size_t __n, mbstate_t* __ps, __locale_t __loc) {
206 __locale_guard __current(__loc);
207 return std::mbrtowc(__pwc, __s, __n, p: __ps);
208}
209
210inline _LIBCPP_HIDE_FROM_ABI int __mbtowc(wchar_t* __pwc, const char* __pmb, size_t __max, __locale_t __loc) {
211 __locale_guard __current(__loc);
212 return std::mbtowc(__pwc, s: __pmb, n: __max);
213}
214
215inline _LIBCPP_HIDE_FROM_ABI size_t __mbrlen(const char* __s, size_t __n, mbstate_t* __ps, __locale_t __loc) {
216 __locale_guard __current(__loc);
217 return std::mbrlen(__s, __n, __ps);
218}
219
220inline _LIBCPP_HIDE_FROM_ABI size_t
221__mbsrtowcs(wchar_t* __dest, const char** __src, size_t __len, mbstate_t* __ps, __locale_t __loc) {
222 __locale_guard __current(__loc);
223 return std::mbsrtowcs(dst: __dest, __src, __len, __ps);
224}
225# endif // _LIBCPP_HAS_WIDE_CHARACTERS
226
227inline _LIBCPP_HIDE_FROM_ABI const char* __get_locale_encoding([[maybe_unused]] __locale_t __loc) {
228# if defined(__ANDROID__)
229 return "UTF-8";
230# else
231 return ::nl_langinfo_l(CODESET, l: __loc);
232# endif
233}
234#endif // _LIBCPP_BUILDING_LIBRARY
235
236#ifndef _LIBCPP_COMPILER_GCC // GCC complains that this can't be always_inline due to C-style varargs
237_LIBCPP_HIDE_FROM_ABI
238#endif
239inline _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 4, 5) int __snprintf(
240 char* __s, size_t __n, __locale_t __loc, const char* __format, ...) {
241 va_list __va;
242 va_start(__va, __format);
243 __locale_guard __current(__loc);
244 int __res = std::vsnprintf(__s, maxlen: __n, __format, arg: __va);
245 va_end(__va);
246 return __res;
247}
248
249#ifndef _LIBCPP_COMPILER_GCC // GCC complains that this can't be always_inline due to C-style varargs
250_LIBCPP_HIDE_FROM_ABI
251#endif
252inline _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 4) int __asprintf(
253 char** __s, __locale_t __loc, const char* __format, ...) {
254 va_list __va;
255 va_start(__va, __format);
256 __locale_guard __current(__loc);
257 int __res = ::vasprintf(ptr: __s, f: __format, arg: __va); // non-standard
258 va_end(__va);
259 return __res;
260}
261} // namespace __locale
262_LIBCPP_END_NAMESPACE_STD
263
264#if defined(__BIONIC__) || _LIBCPP_HAS_MUSL_LIBC
265# define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE 1
266#else
267# define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE 0
268#endif
269
270#include <__locale_dir/support/default/get_c_locale.h>
271
272#endif // _LIBCPP___LOCALE_DIR_SUPPORT_LINUX_H
273