master
  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 <__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
 17
 18_LIBCPP_BEGIN_NAMESPACE_STD
 19namespace __locale {
 20
 21//
 22// Locale management
 23//
 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};
 27}
 28
 29__lconv_t* __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);
 35}
 36
 37//
 38// Strtonum functions
 39//
 40#if !defined(_LIBCPP_MSVCRT)
 41float __strtof(const char* nptr, char** endptr, __locale_t loc) {
 42  __locale_guard __current(loc);
 43  return std::strtof(nptr, endptr);
 44}
 45
 46long double __strtold(const char* nptr, char** endptr, __locale_t loc) {
 47  __locale_guard __current(loc);
 48  return std::strtold(nptr, endptr);
 49}
 50#endif
 51
 52//
 53// Character manipulation functions
 54//
 55#if defined(__MINGW32__) && __MSVCRT_VERSION__ < 0x0800
 56size_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);
 59}
 60#endif
 61
 62//
 63// Other functions
 64//
 65decltype(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
 72}
 73
 74wint_t __btowc(int c, __locale_t loc) {
 75  __locale_guard __current(loc);
 76  return std::btowc(c);
 77}
 78
 79int __wctob(wint_t c, __locale_t loc) {
 80  __locale_guard __current(loc);
 81  return std::wctob(c);
 82}
 83
 84size_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);
 92}
 93
 94size_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);
 97}
 98
 99size_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);
107}
108
109size_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);
113}
114
115size_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);
118}
119
120size_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);
124}
125
126int __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;
142}
143
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.
147int __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;
171  }
172  // All good. This is returning memory to the caller not freeing it.
173  *sptr = p;
174  return count;
175}
176
177int __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);
182}
183
184} // namespace __locale
185_LIBCPP_END_NAMESPACE_STD