xref: /freebsd/contrib/llvm-project/libcxx/src/string.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
981ad6265SDimitry Andric #include <__assert>
1081ad6265SDimitry Andric #include <cerrno>
1181ad6265SDimitry Andric #include <charconv>
1281ad6265SDimitry Andric #include <cstdlib>
1381ad6265SDimitry Andric #include <limits>
1481ad6265SDimitry Andric #include <stdexcept>
150b57cec5SDimitry Andric #include <stdio.h>
1681ad6265SDimitry Andric #include <string>
170b57cec5SDimitry Andric 
18349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1981ad6265SDimitry Andric #  include <cwchar>
20349cc55cSDimitry Andric #endif
21349cc55cSDimitry Andric 
220b57cec5SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
230b57cec5SDimitry Andric 
241838bd0fSDimitry Andric #ifndef _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON
251838bd0fSDimitry Andric 
261838bd0fSDimitry Andric template <bool>
271838bd0fSDimitry Andric struct __basic_string_common;
281838bd0fSDimitry Andric 
291838bd0fSDimitry Andric // The struct isn't declared anymore in the headers. It's only here for ABI compatibility.
301838bd0fSDimitry Andric template <>
311838bd0fSDimitry Andric struct __basic_string_common<true> {
321838bd0fSDimitry Andric     _LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __throw_length_error() const;
331838bd0fSDimitry Andric     _LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __throw_out_of_range() const;
341838bd0fSDimitry Andric };
351838bd0fSDimitry Andric 
36349cc55cSDimitry Andric void __basic_string_common<true>::__throw_length_error() const {
371838bd0fSDimitry Andric     std::__throw_length_error("basic_string");
381838bd0fSDimitry Andric }
391838bd0fSDimitry Andric void __basic_string_common<true>::__throw_out_of_range() const {
401838bd0fSDimitry Andric     std::__throw_out_of_range("basic_string");
41349cc55cSDimitry Andric }
42349cc55cSDimitry Andric 
431838bd0fSDimitry Andric #endif // _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON
440b57cec5SDimitry Andric 
45fe6060f1SDimitry Andric #define _LIBCPP_EXTERN_TEMPLATE_DEFINE(...) template __VA_ARGS__;
465ffd83dbSDimitry Andric #ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
475ffd83dbSDimitry Andric     _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char)
48349cc55cSDimitry Andric #   ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
495ffd83dbSDimitry Andric         _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t)
50349cc55cSDimitry Andric #   endif
515ffd83dbSDimitry Andric #else
525ffd83dbSDimitry Andric     _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char)
53349cc55cSDimitry Andric #   ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
545ffd83dbSDimitry Andric         _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t)
555ffd83dbSDimitry Andric #   endif
56349cc55cSDimitry Andric #endif
57fe6060f1SDimitry Andric #undef _LIBCPP_EXTERN_TEMPLATE_DEFINE
580b57cec5SDimitry Andric 
59fe6060f1SDimitry Andric template string operator+<char, char_traits<char>, allocator<char>>(char const*, string const&);
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric namespace
620b57cec5SDimitry Andric {
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric template<typename T>
6581ad6265SDimitry Andric inline void throw_helper(const string& msg) {
660b57cec5SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
670b57cec5SDimitry Andric     throw T(msg);
680b57cec5SDimitry Andric #else
690b57cec5SDimitry Andric     fprintf(stderr, "%s\n", msg.c_str());
700b57cec5SDimitry Andric     _VSTD::abort();
710b57cec5SDimitry Andric #endif
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric 
7481ad6265SDimitry Andric inline void throw_from_string_out_of_range(const string& func) {
750b57cec5SDimitry Andric     throw_helper<out_of_range>(func + ": out of range");
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric 
7881ad6265SDimitry Andric inline void throw_from_string_invalid_arg(const string& func) {
790b57cec5SDimitry Andric     throw_helper<invalid_argument>(func + ": no conversion");
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric // as_integer
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric template<typename V, typename S, typename F>
8581ad6265SDimitry Andric inline V as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f) {
860b57cec5SDimitry Andric     typename S::value_type* ptr = nullptr;
870b57cec5SDimitry Andric     const typename S::value_type* const p = str.c_str();
88*bdd1243dSDimitry Andric     __libcpp_remove_reference_t<decltype(errno)> errno_save = errno;
890b57cec5SDimitry Andric     errno = 0;
900b57cec5SDimitry Andric     V r = f(p, &ptr, base);
910b57cec5SDimitry Andric     swap(errno, errno_save);
920b57cec5SDimitry Andric     if (errno_save == ERANGE)
930b57cec5SDimitry Andric         throw_from_string_out_of_range(func);
940b57cec5SDimitry Andric     if (ptr == p)
950b57cec5SDimitry Andric         throw_from_string_invalid_arg(func);
960b57cec5SDimitry Andric     if (idx)
970b57cec5SDimitry Andric         *idx = static_cast<size_t>(ptr - p);
980b57cec5SDimitry Andric     return r;
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric template<typename V, typename S>
10281ad6265SDimitry Andric inline V as_integer(const string& func, const S& s, size_t* idx, int base);
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric // string
1050b57cec5SDimitry Andric template<>
10681ad6265SDimitry Andric inline int as_integer(const string& func, const string& s, size_t* idx, int base) {
1070b57cec5SDimitry Andric     // Use long as no Standard string to integer exists.
1080b57cec5SDimitry Andric     long r = as_integer_helper<long>(func, s, idx, base, strtol);
1090b57cec5SDimitry Andric     if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
1100b57cec5SDimitry Andric         throw_from_string_out_of_range(func);
1110b57cec5SDimitry Andric     return static_cast<int>(r);
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric template<>
11581ad6265SDimitry Andric inline long as_integer(const string& func, const string& s, size_t* idx, int base) {
1160b57cec5SDimitry Andric     return as_integer_helper<long>(func, s, idx, base, strtol);
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric template<>
12081ad6265SDimitry Andric inline unsigned long as_integer(const string& func, const string& s, size_t* idx, int base) {
1210b57cec5SDimitry Andric     return as_integer_helper<unsigned long>(func, s, idx, base, strtoul);
1220b57cec5SDimitry Andric }
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric template<>
12581ad6265SDimitry Andric inline long long as_integer(const string& func, const string& s, size_t* idx, int base) {
1260b57cec5SDimitry Andric     return as_integer_helper<long long>(func, s, idx, base, strtoll);
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric template<>
13081ad6265SDimitry Andric inline unsigned long long as_integer(const string& func, const string& s, size_t* idx, int base) {
1310b57cec5SDimitry Andric     return as_integer_helper<unsigned long long>(func, s, idx, base, strtoull);
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric 
134349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1350b57cec5SDimitry Andric // wstring
1360b57cec5SDimitry Andric template<>
13781ad6265SDimitry Andric inline int as_integer(const string& func, const wstring& s, size_t* idx, int base) {
1380b57cec5SDimitry Andric     // Use long as no Stantard string to integer exists.
1390b57cec5SDimitry Andric     long r = as_integer_helper<long>(func, s, idx, base, wcstol);
1400b57cec5SDimitry Andric     if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
1410b57cec5SDimitry Andric         throw_from_string_out_of_range(func);
1420b57cec5SDimitry Andric     return static_cast<int>(r);
1430b57cec5SDimitry Andric }
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric template<>
14681ad6265SDimitry Andric inline long as_integer(const string& func, const wstring& s, size_t* idx, int base) {
1470b57cec5SDimitry Andric     return as_integer_helper<long>(func, s, idx, base, wcstol);
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric template<>
1510b57cec5SDimitry Andric inline
1520b57cec5SDimitry Andric unsigned long
1530b57cec5SDimitry Andric as_integer(const string& func, const wstring& s, size_t* idx, int base)
1540b57cec5SDimitry Andric {
1550b57cec5SDimitry Andric     return as_integer_helper<unsigned long>(func, s, idx, base, wcstoul);
1560b57cec5SDimitry Andric }
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric template<>
15981ad6265SDimitry Andric inline long long as_integer(const string& func, const wstring& s, size_t* idx, int base) {
1600b57cec5SDimitry Andric     return as_integer_helper<long long>(func, s, idx, base, wcstoll);
1610b57cec5SDimitry Andric }
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric template<>
16481ad6265SDimitry Andric inline unsigned long long as_integer(const string& func, const wstring& s, size_t* idx, int base) {
1650b57cec5SDimitry Andric     return as_integer_helper<unsigned long long>(func, s, idx, base, wcstoull);
1660b57cec5SDimitry Andric }
167349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric // as_float
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric template<typename V, typename S, typename F>
17281ad6265SDimitry Andric inline V as_float_helper(const string& func, const S& str, size_t* idx, F f) {
1730b57cec5SDimitry Andric     typename S::value_type* ptr = nullptr;
1740b57cec5SDimitry Andric     const typename S::value_type* const p = str.c_str();
175*bdd1243dSDimitry Andric     __libcpp_remove_reference_t<decltype(errno)> errno_save = errno;
1760b57cec5SDimitry Andric     errno = 0;
1770b57cec5SDimitry Andric     V r = f(p, &ptr);
1780b57cec5SDimitry Andric     swap(errno, errno_save);
1790b57cec5SDimitry Andric     if (errno_save == ERANGE)
1800b57cec5SDimitry Andric         throw_from_string_out_of_range(func);
1810b57cec5SDimitry Andric     if (ptr == p)
1820b57cec5SDimitry Andric         throw_from_string_invalid_arg(func);
1830b57cec5SDimitry Andric     if (idx)
1840b57cec5SDimitry Andric         *idx = static_cast<size_t>(ptr - p);
1850b57cec5SDimitry Andric     return r;
1860b57cec5SDimitry Andric }
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric template<typename V, typename S>
18981ad6265SDimitry Andric inline V as_float(const string& func, const S& s, size_t* idx = nullptr);
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric template<>
19281ad6265SDimitry Andric inline float as_float(const string& func, const string& s, size_t* idx) {
1930b57cec5SDimitry Andric     return as_float_helper<float>(func, s, idx, strtof);
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric template<>
19781ad6265SDimitry Andric inline double as_float(const string& func, const string& s, size_t* idx) {
1980b57cec5SDimitry Andric     return as_float_helper<double>(func, s, idx, strtod);
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric template<>
20281ad6265SDimitry Andric inline long double as_float(const string& func, const string& s, size_t* idx) {
2030b57cec5SDimitry Andric     return as_float_helper<long double>(func, s, idx, strtold);
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric 
206349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
2070b57cec5SDimitry Andric template<>
20881ad6265SDimitry Andric inline float as_float(const string& func, const wstring& s, size_t* idx) {
2090b57cec5SDimitry Andric     return as_float_helper<float>(func, s, idx, wcstof);
2100b57cec5SDimitry Andric }
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric template<>
21381ad6265SDimitry Andric inline double as_float(const string& func, const wstring& s, size_t* idx) {
2140b57cec5SDimitry Andric     return as_float_helper<double>(func, s, idx, wcstod);
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric template<>
21881ad6265SDimitry Andric inline long double as_float(const string& func, const wstring& s, size_t* idx) {
2190b57cec5SDimitry Andric     return as_float_helper<long double>(func, s, idx, wcstold);
2200b57cec5SDimitry Andric }
221349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric }  // unnamed namespace
2240b57cec5SDimitry Andric 
22581ad6265SDimitry Andric int stoi(const string& str, size_t* idx, int base) {
2260b57cec5SDimitry Andric     return as_integer<int>("stoi", str, idx, base);
2270b57cec5SDimitry Andric }
2280b57cec5SDimitry Andric 
22981ad6265SDimitry Andric long stol(const string& str, size_t* idx, int base) {
2300b57cec5SDimitry Andric     return as_integer<long>("stol", str, idx, base);
2310b57cec5SDimitry Andric }
2320b57cec5SDimitry Andric 
23381ad6265SDimitry Andric unsigned long stoul(const string& str, size_t* idx, int base) {
2340b57cec5SDimitry Andric     return as_integer<unsigned long>("stoul", str, idx, base);
2350b57cec5SDimitry Andric }
2360b57cec5SDimitry Andric 
23781ad6265SDimitry Andric long long stoll(const string& str, size_t* idx, int base) {
2380b57cec5SDimitry Andric     return as_integer<long long>("stoll", str, idx, base);
2390b57cec5SDimitry Andric }
2400b57cec5SDimitry Andric 
24181ad6265SDimitry Andric unsigned long long stoull(const string& str, size_t* idx, int base) {
2420b57cec5SDimitry Andric     return as_integer<unsigned long long>("stoull", str, idx, base);
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric 
24581ad6265SDimitry Andric float stof(const string& str, size_t* idx) {
2460b57cec5SDimitry Andric     return as_float<float>("stof", str, idx);
2470b57cec5SDimitry Andric }
2480b57cec5SDimitry Andric 
24981ad6265SDimitry Andric double stod(const string& str, size_t* idx) {
2500b57cec5SDimitry Andric     return as_float<double>("stod", str, idx);
2510b57cec5SDimitry Andric }
2520b57cec5SDimitry Andric 
25381ad6265SDimitry Andric long double stold(const string& str, size_t* idx) {
2540b57cec5SDimitry Andric     return as_float<long double>("stold", str, idx);
2550b57cec5SDimitry Andric }
2560b57cec5SDimitry Andric 
257349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
25881ad6265SDimitry Andric int stoi(const wstring& str, size_t* idx, int base) {
25981ad6265SDimitry Andric     return as_integer<int>("stoi", str, idx, base);
26081ad6265SDimitry Andric }
26181ad6265SDimitry Andric 
26281ad6265SDimitry Andric long stol(const wstring& str, size_t* idx, int base) {
26381ad6265SDimitry Andric     return as_integer<long>("stol", str, idx, base);
26481ad6265SDimitry Andric }
26581ad6265SDimitry Andric 
26681ad6265SDimitry Andric unsigned long stoul(const wstring& str, size_t* idx, int base) {
26781ad6265SDimitry Andric     return as_integer<unsigned long>("stoul", str, idx, base);
26881ad6265SDimitry Andric }
26981ad6265SDimitry Andric 
27081ad6265SDimitry Andric long long stoll(const wstring& str, size_t* idx, int base) {
27181ad6265SDimitry Andric     return as_integer<long long>("stoll", str, idx, base);
27281ad6265SDimitry Andric }
27381ad6265SDimitry Andric 
27481ad6265SDimitry Andric unsigned long long stoull(const wstring& str, size_t* idx, int base) {
27581ad6265SDimitry Andric     return as_integer<unsigned long long>("stoull", str, idx, base);
27681ad6265SDimitry Andric }
27781ad6265SDimitry Andric 
27881ad6265SDimitry Andric float stof(const wstring& str, size_t* idx) {
27981ad6265SDimitry Andric     return as_float<float>("stof", str, idx);
28081ad6265SDimitry Andric }
28181ad6265SDimitry Andric 
28281ad6265SDimitry Andric double stod(const wstring& str, size_t* idx) {
28381ad6265SDimitry Andric     return as_float<double>("stod", str, idx);
28481ad6265SDimitry Andric }
28581ad6265SDimitry Andric 
28681ad6265SDimitry Andric long double stold(const wstring& str, size_t* idx) {
2870b57cec5SDimitry Andric     return as_float<long double>("stold", str, idx);
2880b57cec5SDimitry Andric }
28981ad6265SDimitry Andric #endif // !_LIBCPP_HAS_NO_WIDE_CHARACTERS
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric // to_string
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric namespace
2940b57cec5SDimitry Andric {
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric // as_string
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric template<typename S, typename P, typename V >
29981ad6265SDimitry Andric inline S as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a) {
3000b57cec5SDimitry Andric     typedef typename S::size_type size_type;
3010b57cec5SDimitry Andric     size_type available = s.size();
30281ad6265SDimitry Andric     while (true) {
3030b57cec5SDimitry Andric         int status = sprintf_like(&s[0], available + 1, fmt, a);
30481ad6265SDimitry Andric         if (status >= 0) {
3050b57cec5SDimitry Andric             size_type used = static_cast<size_type>(status);
30681ad6265SDimitry Andric             if (used <= available) {
3070b57cec5SDimitry Andric                 s.resize(used);
3080b57cec5SDimitry Andric                 break;
3090b57cec5SDimitry Andric             }
3100b57cec5SDimitry Andric             available = used; // Assume this is advice of how much space we need.
3110b57cec5SDimitry Andric         }
3120b57cec5SDimitry Andric         else
3130b57cec5SDimitry Andric             available = available * 2 + 1;
3140b57cec5SDimitry Andric         s.resize(available);
3150b57cec5SDimitry Andric     }
3160b57cec5SDimitry Andric     return s;
3170b57cec5SDimitry Andric }
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric template <class S>
3200b57cec5SDimitry Andric struct initial_string;
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric template <>
32381ad6265SDimitry Andric struct initial_string<string> {
32481ad6265SDimitry Andric     string operator()() const {
3250b57cec5SDimitry Andric         string s;
3260b57cec5SDimitry Andric         s.resize(s.capacity());
3270b57cec5SDimitry Andric         return s;
3280b57cec5SDimitry Andric     }
3290b57cec5SDimitry Andric };
3300b57cec5SDimitry Andric 
331349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3320b57cec5SDimitry Andric template <>
33381ad6265SDimitry Andric struct initial_string<wstring> {
33481ad6265SDimitry Andric     wstring operator()() const {
3350b57cec5SDimitry Andric         wstring s(20, wchar_t());
3360b57cec5SDimitry Andric         s.resize(s.capacity());
3370b57cec5SDimitry Andric         return s;
3380b57cec5SDimitry Andric     }
3390b57cec5SDimitry Andric };
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...);
3420b57cec5SDimitry Andric 
34381ad6265SDimitry Andric inline wide_printf get_swprintf() {
3440b57cec5SDimitry Andric #ifndef _LIBCPP_MSVCRT
3450b57cec5SDimitry Andric     return swprintf;
3460b57cec5SDimitry Andric #else
3470b57cec5SDimitry Andric     return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(_snwprintf);
3480b57cec5SDimitry Andric #endif
3490b57cec5SDimitry Andric }
350349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric template <typename S, typename V>
35381ad6265SDimitry Andric S i_to_string(V v) {
3540b57cec5SDimitry Andric //  numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers.
3550b57cec5SDimitry Andric //  For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented),
3560b57cec5SDimitry Andric //  so we need +1 here.
3570b57cec5SDimitry Andric     constexpr size_t bufsize = numeric_limits<V>::digits10 + 2;  // +1 for minus, +1 for digits10
3580b57cec5SDimitry Andric     char buf[bufsize];
3590b57cec5SDimitry Andric     const auto res = to_chars(buf, buf + bufsize, v);
3600b57cec5SDimitry Andric     _LIBCPP_ASSERT(res.ec == errc(), "bufsize must be large enough to accomodate the value");
3610b57cec5SDimitry Andric     return S(buf, res.ptr);
3620b57cec5SDimitry Andric }
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric }  // unnamed namespace
3650b57cec5SDimitry Andric 
3660b57cec5SDimitry Andric string  to_string (int val)                { return i_to_string< string>(val); }
3670b57cec5SDimitry Andric string  to_string (long val)               { return i_to_string< string>(val); }
3680b57cec5SDimitry Andric string  to_string (long long val)          { return i_to_string< string>(val); }
3690b57cec5SDimitry Andric string  to_string (unsigned val)           { return i_to_string< string>(val); }
3700b57cec5SDimitry Andric string  to_string (unsigned long val)      { return i_to_string< string>(val); }
3710b57cec5SDimitry Andric string  to_string (unsigned long long val) { return i_to_string< string>(val); }
3720b57cec5SDimitry Andric 
373349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3740b57cec5SDimitry Andric wstring to_wstring(int val)                { return i_to_string<wstring>(val); }
3750b57cec5SDimitry Andric wstring to_wstring(long val)               { return i_to_string<wstring>(val); }
3760b57cec5SDimitry Andric wstring to_wstring(long long val)          { return i_to_string<wstring>(val); }
3770b57cec5SDimitry Andric wstring to_wstring(unsigned val)           { return i_to_string<wstring>(val); }
3780b57cec5SDimitry Andric wstring to_wstring(unsigned long val)      { return i_to_string<wstring>(val); }
3790b57cec5SDimitry Andric wstring to_wstring(unsigned long long val) { return i_to_string<wstring>(val); }
380349cc55cSDimitry Andric #endif
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric string  to_string (float val)       { return as_string(snprintf,       initial_string< string>()(),   "%f", val); }
3830b57cec5SDimitry Andric string  to_string (double val)      { return as_string(snprintf,       initial_string< string>()(),   "%f", val); }
3840b57cec5SDimitry Andric string  to_string (long double val) { return as_string(snprintf,       initial_string< string>()(),  "%Lf", val); }
3850b57cec5SDimitry Andric 
386349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3870b57cec5SDimitry Andric wstring to_wstring(float val)       { return as_string(get_swprintf(), initial_string<wstring>()(),  L"%f", val); }
3880b57cec5SDimitry Andric wstring to_wstring(double val)      { return as_string(get_swprintf(), initial_string<wstring>()(),  L"%f", val); }
3890b57cec5SDimitry Andric wstring to_wstring(long double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%Lf", val); }
390349cc55cSDimitry Andric #endif
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric _LIBCPP_END_NAMESPACE_STD
393