1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include <__locale_dir/support/windows.h>
10 #include <clocale> // std::localeconv() & friends
11 #include <cstdarg> // va_start & friends
13 #include <cstdio> // std::vsnprintf & friends
14 #include <cstdlib> // std::strtof & friends
15 #include <ctime> // std::strftime
16 #include <cwchar> // wide char manipulation
18 _LIBCPP_BEGIN_NAMESPACE_STD
24 // FIXME: base and mask currently unused. Needs manual work to construct the new locale
25 __locale_t
__newlocale(int /*mask*/, const char* locale
, __locale_t
/*base*/) {
26 return {::_create_locale(LC_ALL
, locale
), locale
};
29 lconv
* __localeconv(__locale_t
& loc
) {
30 __locale_guard
__current(loc
);
31 lconv
* lc
= std::localeconv();
34 return loc
.__store_lconv(lc
);
40 #if !defined(_LIBCPP_MSVCRT)
41 float __strtof(const char* nptr
, char** endptr
, __locale_t loc
) {
42 __locale_guard
__current(loc
);
43 return std::strtof(nptr
, endptr
);
46 long double __strtold(const char* nptr
, char** endptr
, __locale_t loc
) {
47 __locale_guard
__current(loc
);
48 return std::strtold(nptr
, endptr
);
53 // Character manipulation functions
55 #if defined(__MINGW32__) && __MSVCRT_VERSION__ < 0x0800
56 size_t __strftime(char* ret
, size_t n
, const char* format
, const struct tm
* tm
, __locale_t loc
) {
57 __locale_guard
__current(loc
);
58 return std::strftime(ret
, n
, format
, tm
);
65 decltype(MB_CUR_MAX
) __mb_len_max(__locale_t __l
) {
66 #if defined(_LIBCPP_MSVCRT)
67 return ::___mb_cur_max_l_func(__l
);
69 __locale_guard
__current(__l
);
74 wint_t __btowc(int c
, __locale_t loc
) {
75 __locale_guard
__current(loc
);
79 int __wctob(wint_t c
, __locale_t loc
) {
80 __locale_guard
__current(loc
);
84 size_t __wcsnrtombs(char* __restrict dst
,
85 const wchar_t** __restrict src
,
88 mbstate_t* __restrict ps
,
90 __locale_guard
__current(loc
);
91 return ::wcsnrtombs(dst
, src
, nwc
, len
, ps
);
94 size_t __wcrtomb(char* __restrict s
, wchar_t wc
, mbstate_t* __restrict ps
, __locale_t loc
) {
95 __locale_guard
__current(loc
);
96 return std::wcrtomb(s
, wc
, ps
);
99 size_t __mbsnrtowcs(wchar_t* __restrict dst
,
100 const char** __restrict src
,
103 mbstate_t* __restrict ps
,
105 __locale_guard
__current(loc
);
106 return ::mbsnrtowcs(dst
, src
, nms
, len
, ps
);
110 __mbrtowc(wchar_t* __restrict pwc
, const char* __restrict s
, size_t n
, mbstate_t* __restrict ps
, __locale_t loc
) {
111 __locale_guard
__current(loc
);
112 return std::mbrtowc(pwc
, s
, n
, ps
);
115 size_t __mbrlen(const char* __restrict s
, size_t n
, mbstate_t* __restrict ps
, __locale_t loc
) {
116 __locale_guard
__current(loc
);
117 return std::mbrlen(s
, n
, ps
);
121 wchar_t* __restrict dst
, const char** __restrict src
, size_t len
, mbstate_t* __restrict ps
, __locale_t loc
) {
122 __locale_guard
__current(loc
);
123 return std::mbsrtowcs(dst
, src
, len
, ps
);
126 int __snprintf(char* ret
, size_t n
, __locale_t loc
, const char* format
, ...) {
128 va_start(ap
, format
);
129 #if defined(_LIBCPP_MSVCRT)
130 // FIXME: Remove usage of internal CRT function and globals.
131 int result
= ::__stdio_common_vsprintf(
132 _CRT_INTERNAL_LOCAL_PRINTF_OPTIONS
| _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR
, ret
, n
, format
, loc
, ap
);
134 __locale_guard
__current(loc
);
135 _LIBCPP_DIAGNOSTIC_PUSH
136 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")
137 int result
= std::vsnprintf(ret
, n
, format
, ap
);
138 _LIBCPP_DIAGNOSTIC_POP
144 // Like sprintf, but when return value >= 0 it returns
145 // a pointer to a malloc'd string in *sptr.
146 // If return >= 0, use free to delete *sptr.
147 int __libcpp_vasprintf(char** sptr
, const char* __restrict format
, va_list ap
) {
149 // Query the count required.
151 va_copy(ap_copy
, ap
);
152 _LIBCPP_DIAGNOSTIC_PUSH
153 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")
154 int count
= vsnprintf(nullptr, 0, format
, ap_copy
);
155 _LIBCPP_DIAGNOSTIC_POP
159 size_t buffer_size
= static_cast<size_t>(count
) + 1;
160 char* p
= static_cast<char*>(malloc(buffer_size
));
163 // If we haven't used exactly what was required, something is wrong.
164 // Maybe bug in vsnprintf. Report the error and return.
165 _LIBCPP_DIAGNOSTIC_PUSH
166 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")
167 if (vsnprintf(p
, buffer_size
, format
, ap
) != count
) {
168 _LIBCPP_DIAGNOSTIC_POP
172 // All good. This is returning memory to the caller not freeing it.
177 int __asprintf(char** ret
, __locale_t loc
, const char* format
, ...) {
179 va_start(ap
, format
);
180 __locale_guard
__current(loc
);
181 return __libcpp_vasprintf(ret
, format
, ap
);
184 } // namespace __locale
185 _LIBCPP_END_NAMESPACE_STD