186 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include <__locale_dir/support/windows.h>10#include <clocale> // std::localeconv() & friends11#include <cstdarg> // va_start & friends12#include <cstddef>13#include <cstdio> // std::vsnprintf & friends14#include <cstdlib> // std::strtof & friends15#include <ctime> // std::strftime16#include <cwchar> // wide char manipulation17 18_LIBCPP_BEGIN_NAMESPACE_STD19namespace __locale {20 21//22// Locale management23//24// FIXME: base and mask currently unused. Needs manual work to construct the new locale25__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 functions39//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#endif51 52//53// Character manipulation functions54//55#if defined(__MINGW32__) && __MSVCRT_VERSION__ < 0x080056size_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#endif61 62//63// Other functions64//65decltype(MB_CUR_MAX) __mb_len_max(__locale_t __l) {66#if defined(_LIBCPP_MSVCRT)67 return ::___mb_cur_max_l_func(__l);68#else69 __locale_guard __current(__l);70 return MB_CUR_MAX;71#endif72}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_t110__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#else134 __locale_guard __current(loc);135 _LIBCPP_DIAGNOSTIC_PUSH136 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")137 int result = std::vsnprintf(ret, n, format, ap);138 _LIBCPP_DIAGNOSTIC_POP139#endif140 va_end(ap);141 return result;142}143 144// Like sprintf, but when return value >= 0 it returns145// 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_PUSH153 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")154 int count = vsnprintf(nullptr, 0, format, ap_copy);155 _LIBCPP_DIAGNOSTIC_POP156 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_PUSH166 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")167 if (vsnprintf(p, buffer_size, format, ap) != count) {168 _LIBCPP_DIAGNOSTIC_POP169 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 __locale185_LIBCPP_END_NAMESPACE_STD186