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#if defined(_LIBCPP_BUILDING_LIBRARY)
67using __lconv_t _LIBCPP_NODEBUG = std::lconv;
68
69inline _LIBCPP_HIDE_FROM_ABI __locale_t __newlocale(int __category_mask, const char* __locale, __locale_t __base) {
70 return ::newlocale(__category_mask, __locale, __base);
71}
72
73inline _LIBCPP_HIDE_FROM_ABI void __freelocale(__locale_t __loc) { ::freelocale(dataset: __loc); }
74
75inline _LIBCPP_HIDE_FROM_ABI char* __setlocale(int __category, char const* __locale) {
76 return ::setlocale(__category, __locale);
77}
78
79inline _LIBCPP_HIDE_FROM_ABI __lconv_t* __localeconv(__locale_t& __loc) {
80 __locale_guard __current(__loc);
81 return std::localeconv();
82}
83#endif // _LIBCPP_BUILDING_LIBRARY
84
85//
86// Strtonum functions
87//
88inline _LIBCPP_HIDE_FROM_ABI float __strtof(const char* __nptr, char** __endptr, __locale_t __loc) {
89 return ::strtof_l(__nptr, __endptr, __loc);
90}
91
92inline _LIBCPP_HIDE_FROM_ABI double __strtod(const char* __nptr, char** __endptr, __locale_t __loc) {
93 return ::strtod_l(__nptr, __endptr, __loc);
94}
95
96inline _LIBCPP_HIDE_FROM_ABI long double __strtold(const char* __nptr, char** __endptr, __locale_t __loc) {
97 return ::strtold_l(__nptr, __endptr, __loc);
98}
99
100//
101// Character manipulation functions
102//
103#if defined(_LIBCPP_BUILDING_LIBRARY)
104inline _LIBCPP_HIDE_FROM_ABI int __toupper(int __c, __locale_t __loc) { return toupper_l(__c, l: __loc); }
105
106inline _LIBCPP_HIDE_FROM_ABI int __tolower(int __c, __locale_t __loc) { return tolower_l(__c, l: __loc); }
107
108inline _LIBCPP_HIDE_FROM_ABI int __strcoll(const char* __s1, const char* __s2, __locale_t __loc) {
109 return strcoll_l(__s1, __s2, l: __loc);
110}
111
112inline _LIBCPP_HIDE_FROM_ABI size_t __strxfrm(char* __dest, const char* __src, size_t __n, __locale_t __loc) {
113 return strxfrm_l(__dest, __src, __n, l: __loc);
114}
115
116# if _LIBCPP_HAS_WIDE_CHARACTERS
117inline _LIBCPP_HIDE_FROM_ABI int __iswctype(wint_t __c, wctype_t __type, __locale_t __loc) {
118 return iswctype_l(wc: __c, desc: __type, locale: __loc);
119}
120
121inline _LIBCPP_HIDE_FROM_ABI int __iswspace(wint_t __c, __locale_t __loc) { return iswspace_l(wc: __c, locale: __loc); }
122
123inline _LIBCPP_HIDE_FROM_ABI int __iswprint(wint_t __c, __locale_t __loc) { return iswprint_l(wc: __c, locale: __loc); }
124
125inline _LIBCPP_HIDE_FROM_ABI int __iswcntrl(wint_t __c, __locale_t __loc) { return iswcntrl_l(wc: __c, locale: __loc); }
126
127inline _LIBCPP_HIDE_FROM_ABI int __iswupper(wint_t __c, __locale_t __loc) { return iswupper_l(wc: __c, locale: __loc); }
128
129inline _LIBCPP_HIDE_FROM_ABI int __iswlower(wint_t __c, __locale_t __loc) { return iswlower_l(wc: __c, locale: __loc); }
130
131inline _LIBCPP_HIDE_FROM_ABI int __iswalpha(wint_t __c, __locale_t __loc) { return iswalpha_l(wc: __c, locale: __loc); }
132
133inline _LIBCPP_HIDE_FROM_ABI int __iswblank(wint_t __c, __locale_t __loc) { return iswblank_l(wc: __c, locale: __loc); }
134
135inline _LIBCPP_HIDE_FROM_ABI int __iswdigit(wint_t __c, __locale_t __loc) { return iswdigit_l(wc: __c, locale: __loc); }
136
137inline _LIBCPP_HIDE_FROM_ABI int __iswpunct(wint_t __c, __locale_t __loc) { return iswpunct_l(wc: __c, locale: __loc); }
138
139inline _LIBCPP_HIDE_FROM_ABI int __iswxdigit(wint_t __c, __locale_t __loc) { return iswxdigit_l(wc: __c, locale: __loc); }
140
141inline _LIBCPP_HIDE_FROM_ABI wint_t __towupper(wint_t __c, __locale_t __loc) { return towupper_l(wc: __c, locale: __loc); }
142
143inline _LIBCPP_HIDE_FROM_ABI wint_t __towlower(wint_t __c, __locale_t __loc) { return towlower_l(wc: __c, locale: __loc); }
144
145inline _LIBCPP_HIDE_FROM_ABI int __wcscoll(const wchar_t* __ws1, const wchar_t* __ws2, __locale_t __loc) {
146 return wcscoll_l(s1: __ws1, s2: __ws2, __loc);
147}
148
149inline _LIBCPP_HIDE_FROM_ABI size_t __wcsxfrm(wchar_t* __dest, const wchar_t* __src, size_t __n, __locale_t __loc) {
150 return wcsxfrm_l(s1: __dest, s2: __src, __n, __loc);
151}
152# endif // _LIBCPP_HAS_WIDE_CHARACTERS
153
154inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_ATTRIBUTE_FORMAT(__strftime__, 3, 0) size_t
155 __strftime(char* __s, size_t __max, const char* __format, const struct tm* __tm, __locale_t __loc) {
156 return strftime_l(__s, maxsize: __max, __format, tp: __tm, __loc);
157}
158
159//
160// Other functions
161//
162inline _LIBCPP_HIDE_FROM_ABI decltype(MB_CUR_MAX) __mb_len_max(__locale_t __loc) {
163 __locale_guard __current(__loc);
164 return MB_CUR_MAX;
165}
166
167# if _LIBCPP_HAS_WIDE_CHARACTERS
168inline _LIBCPP_HIDE_FROM_ABI wint_t __btowc(int __c, __locale_t __loc) {
169 __locale_guard __current(__loc);
170 return std::btowc(__c);
171}
172
173inline _LIBCPP_HIDE_FROM_ABI int __wctob(wint_t __c, __locale_t __loc) {
174 __locale_guard __current(__loc);
175 return std::wctob(wc: __c);
176}
177
178inline _LIBCPP_HIDE_FROM_ABI size_t
179__wcsnrtombs(char* __dest, const wchar_t** __src, size_t __nwc, size_t __len, mbstate_t* __ps, __locale_t __loc) {
180 __locale_guard __current(__loc);
181 return ::wcsnrtombs(dst: __dest, __src, __nwc, __len, __ps); // non-standard
182}
183
184inline _LIBCPP_HIDE_FROM_ABI size_t __wcrtomb(char* __s, wchar_t __wc, mbstate_t* __ps, __locale_t __loc) {
185 __locale_guard __current(__loc);
186 return std::wcrtomb(__s, __wc, __ps);
187}
188
189inline _LIBCPP_HIDE_FROM_ABI size_t
190__mbsnrtowcs(wchar_t* __dest, const char** __src, size_t __nms, size_t __len, mbstate_t* __ps, __locale_t __loc) {
191 __locale_guard __current(__loc);
192 return ::mbsnrtowcs(dst: __dest, __src, nmc: __nms, __len, __ps); // non-standard
193}
194
195inline _LIBCPP_HIDE_FROM_ABI size_t
196__mbrtowc(wchar_t* __pwc, const char* __s, size_t __n, mbstate_t* __ps, __locale_t __loc) {
197 __locale_guard __current(__loc);
198 return std::mbrtowc(__pwc, __s, __n, p: __ps);
199}
200
201inline _LIBCPP_HIDE_FROM_ABI int __mbtowc(wchar_t* __pwc, const char* __pmb, size_t __max, __locale_t __loc) {
202 __locale_guard __current(__loc);
203 return std::mbtowc(__pwc, s: __pmb, n: __max);
204}
205
206inline _LIBCPP_HIDE_FROM_ABI size_t __mbrlen(const char* __s, size_t __n, mbstate_t* __ps, __locale_t __loc) {
207 __locale_guard __current(__loc);
208 return std::mbrlen(__s, __n, __ps);
209}
210
211inline _LIBCPP_HIDE_FROM_ABI size_t
212__mbsrtowcs(wchar_t* __dest, const char** __src, size_t __len, mbstate_t* __ps, __locale_t __loc) {
213 __locale_guard __current(__loc);
214 return std::mbsrtowcs(dst: __dest, __src, __len, __ps);
215}
216# endif // _LIBCPP_HAS_WIDE_CHARACTERS
217
218inline _LIBCPP_HIDE_FROM_ABI const char* __get_locale_encoding([[maybe_unused]] __locale_t __loc) {
219# if defined(__ANDROID__)
220 return "UTF-8";
221# else
222 return ::nl_langinfo_l(CODESET, l: __loc);
223# endif
224}
225#endif // _LIBCPP_BUILDING_LIBRARY
226
227#ifndef _LIBCPP_COMPILER_GCC // GCC complains that this can't be always_inline due to C-style varargs
228_LIBCPP_HIDE_FROM_ABI
229#endif
230inline _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 4, 5) int __snprintf(
231 char* __s, size_t __n, __locale_t __loc, const char* __format, ...) {
232 va_list __va;
233 va_start(__va, __format);
234 __locale_guard __current(__loc);
235 int __res = std::vsnprintf(__s, maxlen: __n, __format, arg: __va);
236 va_end(__va);
237 return __res;
238}
239
240#ifndef _LIBCPP_COMPILER_GCC // GCC complains that this can't be always_inline due to C-style varargs
241_LIBCPP_HIDE_FROM_ABI
242#endif
243inline _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 4) int __asprintf(
244 char** __s, __locale_t __loc, const char* __format, ...) {
245 va_list __va;
246 va_start(__va, __format);
247 __locale_guard __current(__loc);
248 int __res = ::vasprintf(ptr: __s, f: __format, arg: __va); // non-standard
249 va_end(__va);
250 return __res;
251}
252} // namespace __locale
253_LIBCPP_END_NAMESPACE_STD
254
255#if defined(__BIONIC__) || _LIBCPP_HAS_MUSL_LIBC
256# define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE 1
257#else
258# define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE 0
259#endif
260
261#include <__locale_dir/support/default/get_c_locale.h>
262
263#endif // _LIBCPP___LOCALE_DIR_SUPPORT_LINUX_H
264