1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
|
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include <__locale_dir/support/windows.h>
#include <clocale> // std::localeconv() & friends
#include <cstdarg> // va_start & friends
#include <cstddef>
#include <cstdio> // std::vsnprintf & friends
#include <cstdlib> // std::strtof & friends
#include <ctime> // std::strftime
#include <cwchar> // wide char manipulation
_LIBCPP_BEGIN_NAMESPACE_STD
namespace __locale {
//
// Locale management
//
// FIXME: base and mask currently unused. Needs manual work to construct the new locale
__locale_t __newlocale(int /*mask*/, const char* locale, __locale_t /*base*/) {
return {::_create_locale(LC_ALL, locale), locale};
}
__lconv_t* __localeconv(__locale_t& loc) {
__locale_guard __current(loc);
lconv* lc = std::localeconv();
if (!lc)
return lc;
return loc.__store_lconv(lc);
}
//
// Strtonum functions
//
#if !defined(_LIBCPP_MSVCRT)
float __strtof(const char* nptr, char** endptr, __locale_t loc) {
__locale_guard __current(loc);
return std::strtof(nptr, endptr);
}
long double __strtold(const char* nptr, char** endptr, __locale_t loc) {
__locale_guard __current(loc);
return std::strtold(nptr, endptr);
}
#endif
//
// Character manipulation functions
//
#if defined(__MINGW32__) && __MSVCRT_VERSION__ < 0x0800
size_t __strftime(char* ret, size_t n, const char* format, const struct tm* tm, __locale_t loc) {
__locale_guard __current(loc);
return std::strftime(ret, n, format, tm);
}
#endif
//
// Other functions
//
decltype(MB_CUR_MAX) __mb_len_max(__locale_t __l) {
#if defined(_LIBCPP_MSVCRT)
return ::___mb_cur_max_l_func(__l);
#else
__locale_guard __current(__l);
return MB_CUR_MAX;
#endif
}
wint_t __btowc(int c, __locale_t loc) {
__locale_guard __current(loc);
return std::btowc(c);
}
int __wctob(wint_t c, __locale_t loc) {
__locale_guard __current(loc);
return std::wctob(c);
}
size_t __wcsnrtombs(char* __restrict dst,
const wchar_t** __restrict src,
size_t nwc,
size_t len,
mbstate_t* __restrict ps,
__locale_t loc) {
__locale_guard __current(loc);
return ::wcsnrtombs(dst, src, nwc, len, ps);
}
size_t __wcrtomb(char* __restrict s, wchar_t wc, mbstate_t* __restrict ps, __locale_t loc) {
__locale_guard __current(loc);
return std::wcrtomb(s, wc, ps);
}
size_t __mbsnrtowcs(wchar_t* __restrict dst,
const char** __restrict src,
size_t nms,
size_t len,
mbstate_t* __restrict ps,
__locale_t loc) {
__locale_guard __current(loc);
return ::mbsnrtowcs(dst, src, nms, len, ps);
}
size_t
__mbrtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n, mbstate_t* __restrict ps, __locale_t loc) {
__locale_guard __current(loc);
return std::mbrtowc(pwc, s, n, ps);
}
size_t __mbrlen(const char* __restrict s, size_t n, mbstate_t* __restrict ps, __locale_t loc) {
__locale_guard __current(loc);
return std::mbrlen(s, n, ps);
}
size_t __mbsrtowcs(
wchar_t* __restrict dst, const char** __restrict src, size_t len, mbstate_t* __restrict ps, __locale_t loc) {
__locale_guard __current(loc);
return std::mbsrtowcs(dst, src, len, ps);
}
int __snprintf(char* ret, size_t n, __locale_t loc, const char* format, ...) {
va_list ap;
va_start(ap, format);
#if defined(_LIBCPP_MSVCRT)
// FIXME: Remove usage of internal CRT function and globals.
int result = ::__stdio_common_vsprintf(
_CRT_INTERNAL_LOCAL_PRINTF_OPTIONS | _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, ret, n, format, loc, ap);
#else
__locale_guard __current(loc);
_LIBCPP_DIAGNOSTIC_PUSH
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")
int result = std::vsnprintf(ret, n, format, ap);
_LIBCPP_DIAGNOSTIC_POP
#endif
va_end(ap);
return result;
}
// Like sprintf, but when return value >= 0 it returns
// a pointer to a malloc'd string in *sptr.
// If return >= 0, use free to delete *sptr.
int __libcpp_vasprintf(char** sptr, const char* __restrict format, va_list ap) {
*sptr = nullptr;
// Query the count required.
va_list ap_copy;
va_copy(ap_copy, ap);
_LIBCPP_DIAGNOSTIC_PUSH
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")
int count = vsnprintf(nullptr, 0, format, ap_copy);
_LIBCPP_DIAGNOSTIC_POP
va_end(ap_copy);
if (count < 0)
return count;
size_t buffer_size = static_cast<size_t>(count) + 1;
char* p = static_cast<char*>(malloc(buffer_size));
if (!p)
return -1;
// If we haven't used exactly what was required, something is wrong.
// Maybe bug in vsnprintf. Report the error and return.
_LIBCPP_DIAGNOSTIC_PUSH
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")
if (vsnprintf(p, buffer_size, format, ap) != count) {
_LIBCPP_DIAGNOSTIC_POP
free(p);
return -1;
}
// All good. This is returning memory to the caller not freeing it.
*sptr = p;
return count;
}
int __asprintf(char** ret, __locale_t loc, const char* format, ...) {
va_list ap;
va_start(ap, format);
__locale_guard __current(loc);
return __libcpp_vasprintf(ret, format, ap);
}
} // namespace __locale
_LIBCPP_END_NAMESPACE_STD
|