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 | #include <cstdarg> // va_start, va_end |
10 | #include <locale> |
11 | #include <memory> |
12 | #include <type_traits> |
13 | |
14 | #include <__locale_dir/locale_base_api/locale_guard.h> |
15 | |
16 | int __libcpp_vasprintf(char** sptr, const char* __restrict fmt, va_list ap); |
17 | |
18 | using std::__libcpp_locale_guard; |
19 | |
20 | // FIXME: base and mask currently unused. Needs manual work to construct the new locale |
21 | locale_t newlocale(int /*mask*/, const char* locale, locale_t /*base*/) { |
22 | return {_create_locale(LC_ALL, locale), locale}; |
23 | } |
24 | |
25 | decltype(MB_CUR_MAX) MB_CUR_MAX_L(locale_t __l) { |
26 | #if defined(_LIBCPP_MSVCRT) |
27 | return ___mb_cur_max_l_func(__l); |
28 | #else |
29 | __libcpp_locale_guard __current(__l); |
30 | return MB_CUR_MAX; |
31 | #endif |
32 | } |
33 | |
34 | lconv* localeconv_l(locale_t& loc) { |
35 | __libcpp_locale_guard __current(loc); |
36 | lconv* lc = localeconv(); |
37 | if (!lc) |
38 | return lc; |
39 | return loc.__store_lconv(lc); |
40 | } |
41 | size_t mbrlen_l(const char* __restrict s, size_t n, mbstate_t* __restrict ps, locale_t loc) { |
42 | __libcpp_locale_guard __current(loc); |
43 | return mbrlen(s: s, n: n, ps: ps); |
44 | } |
45 | size_t |
46 | mbsrtowcs_l(wchar_t* __restrict dst, const char** __restrict src, size_t len, mbstate_t* __restrict ps, locale_t loc) { |
47 | __libcpp_locale_guard __current(loc); |
48 | return mbsrtowcs(dst: dst, src: src, len: len, ps: ps); |
49 | } |
50 | size_t wcrtomb_l(char* __restrict s, wchar_t wc, mbstate_t* __restrict ps, locale_t loc) { |
51 | __libcpp_locale_guard __current(loc); |
52 | return wcrtomb(s: s, wc: wc, ps: ps); |
53 | } |
54 | size_t mbrtowc_l(wchar_t* __restrict pwc, const char* __restrict s, size_t n, mbstate_t* __restrict ps, locale_t loc) { |
55 | __libcpp_locale_guard __current(loc); |
56 | return mbrtowc(pwc: pwc, s: s, n: n, p: ps); |
57 | } |
58 | size_t mbsnrtowcs_l(wchar_t* __restrict dst, |
59 | const char** __restrict src, |
60 | size_t nms, |
61 | size_t len, |
62 | mbstate_t* __restrict ps, |
63 | locale_t loc) { |
64 | __libcpp_locale_guard __current(loc); |
65 | return mbsnrtowcs(dst: dst, src: src, nmc: nms, len: len, ps: ps); |
66 | } |
67 | size_t wcsnrtombs_l(char* __restrict dst, |
68 | const wchar_t** __restrict src, |
69 | size_t nwc, |
70 | size_t len, |
71 | mbstate_t* __restrict ps, |
72 | locale_t loc) { |
73 | __libcpp_locale_guard __current(loc); |
74 | return wcsnrtombs(dst: dst, src: src, nwc: nwc, len: len, ps: ps); |
75 | } |
76 | wint_t btowc_l(int c, locale_t loc) { |
77 | __libcpp_locale_guard __current(loc); |
78 | return btowc(c: c); |
79 | } |
80 | int wctob_l(wint_t c, locale_t loc) { |
81 | __libcpp_locale_guard __current(loc); |
82 | return wctob(c: c); |
83 | } |
84 | |
85 | int snprintf_l(char* ret, size_t n, locale_t loc, const char* format, ...) { |
86 | va_list ap; |
87 | va_start(ap, format); |
88 | #if defined(_LIBCPP_MSVCRT) |
89 | // FIXME: Remove usage of internal CRT function and globals. |
90 | int result = __stdio_common_vsprintf( |
91 | _CRT_INTERNAL_LOCAL_PRINTF_OPTIONS | _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, ret, n, format, loc, ap); |
92 | #else |
93 | __libcpp_locale_guard __current(loc); |
94 | _LIBCPP_DIAGNOSTIC_PUSH |
95 | _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral" ) |
96 | int result = vsnprintf(s: ret, maxlen: n, format: format, arg: ap); |
97 | _LIBCPP_DIAGNOSTIC_POP |
98 | #endif |
99 | va_end(ap); |
100 | return result; |
101 | } |
102 | |
103 | int asprintf_l(char** ret, locale_t loc, const char* format, ...) { |
104 | va_list ap; |
105 | va_start(ap, format); |
106 | int result = vasprintf_l(ret, loc, format, ap); |
107 | va_end(ap); |
108 | return result; |
109 | } |
110 | int vasprintf_l(char** ret, locale_t loc, const char* format, va_list ap) { |
111 | __libcpp_locale_guard __current(loc); |
112 | return __libcpp_vasprintf(sptr: ret, fmt: format, ap); |
113 | } |
114 | |
115 | #if !defined(_LIBCPP_MSVCRT) |
116 | float strtof_l(const char* nptr, char** endptr, locale_t loc) { |
117 | __libcpp_locale_guard __current(loc); |
118 | return strtof(nptr: nptr, endptr: endptr); |
119 | } |
120 | |
121 | long double strtold_l(const char* nptr, char** endptr, locale_t loc) { |
122 | __libcpp_locale_guard __current(loc); |
123 | return strtold(nptr: nptr, endptr: endptr); |
124 | } |
125 | #endif |
126 | |
127 | #if defined(__MINGW32__) && __MSVCRT_VERSION__ < 0x0800 |
128 | size_t strftime_l(char* ret, size_t n, const char* format, const struct tm* tm, locale_t loc) { |
129 | __libcpp_locale_guard __current(loc); |
130 | return strftime(ret, n, format, tm); |
131 | } |
132 | #endif |
133 | |