Revert "[lldb][test] Remove compiler version check and use regex" (#124101)
[llvm-project.git] / libcxx / src / support / win32 / locale_win32.cpp
blobec2dd7f36ec709270c289139e4388f54cd55cc07
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 //===----------------------------------------------------------------------===//
9 #include <__locale_dir/support/windows.h>
10 #include <clocale> // std::localeconv() & friends
11 #include <cstdarg> // va_start & friends
12 #include <cstddef>
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
19 namespace __locale {
22 // Locale management
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();
32 if (!lc)
33 return lc;
34 return loc.__store_lconv(lc);
38 // Strtonum functions
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);
50 #endif
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);
60 #endif
63 // Other functions
65 decltype(MB_CUR_MAX) __mb_len_max(__locale_t __l) {
66 #if defined(_LIBCPP_MSVCRT)
67 return ::___mb_cur_max_l_func(__l);
68 #else
69 __locale_guard __current(__l);
70 return MB_CUR_MAX;
71 #endif
74 wint_t __btowc(int c, __locale_t loc) {
75 __locale_guard __current(loc);
76 return std::btowc(c);
79 int __wctob(wint_t c, __locale_t loc) {
80 __locale_guard __current(loc);
81 return std::wctob(c);
84 size_t __wcsnrtombs(char* __restrict dst,
85 const wchar_t** __restrict src,
86 size_t nwc,
87 size_t len,
88 mbstate_t* __restrict ps,
89 __locale_t loc) {
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,
101 size_t nms,
102 size_t len,
103 mbstate_t* __restrict ps,
104 __locale_t loc) {
105 __locale_guard __current(loc);
106 return ::mbsnrtowcs(dst, src, nms, len, ps);
109 size_t
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);
120 size_t __mbsrtowcs(
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, ...) {
127 va_list ap;
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);
133 #else
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
139 #endif
140 va_end(ap);
141 return result;
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) {
148 *sptr = nullptr;
149 // Query the count required.
150 va_list ap_copy;
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
156 va_end(ap_copy);
157 if (count < 0)
158 return count;
159 size_t buffer_size = static_cast<size_t>(count) + 1;
160 char* p = static_cast<char*>(malloc(buffer_size));
161 if (!p)
162 return -1;
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
169 free(p);
170 return -1;
172 // All good. This is returning memory to the caller not freeing it.
173 *sptr = p;
174 return count;
177 int __asprintf(char** ret, __locale_t loc, const char* format, ...) {
178 va_list ap;
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