xref: /freebsd/contrib/llvm-project/libcxx/src/string.cpp (revision cb14a3fe5122c879eae1fb480ed7ce82a699ddb6)
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>
1581ad6265SDimitry Andric #include <string>
160b57cec5SDimitry Andric 
17349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1881ad6265SDimitry Andric #  include <cwchar>
19349cc55cSDimitry Andric #endif
20349cc55cSDimitry Andric 
210b57cec5SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
220b57cec5SDimitry Andric 
231838bd0fSDimitry Andric #ifndef _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON
241838bd0fSDimitry Andric 
251838bd0fSDimitry Andric template <bool>
261838bd0fSDimitry Andric struct __basic_string_common;
271838bd0fSDimitry Andric 
281838bd0fSDimitry Andric // The struct isn't declared anymore in the headers. It's only here for ABI compatibility.
291838bd0fSDimitry Andric template <>
301838bd0fSDimitry Andric struct __basic_string_common<true> {
311838bd0fSDimitry Andric   _LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __throw_length_error() const;
321838bd0fSDimitry Andric   _LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __throw_out_of_range() const;
331838bd0fSDimitry Andric };
341838bd0fSDimitry Andric 
35*cb14a3feSDimitry Andric void __basic_string_common<true>::__throw_length_error() const { std::__throw_length_error("basic_string"); }
36*cb14a3feSDimitry Andric void __basic_string_common<true>::__throw_out_of_range() const { std::__throw_out_of_range("basic_string"); }
37349cc55cSDimitry Andric 
381838bd0fSDimitry Andric #endif // _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON
390b57cec5SDimitry Andric 
40fe6060f1SDimitry Andric #define _LIBCPP_EXTERN_TEMPLATE_DEFINE(...) template __VA_ARGS__;
415ffd83dbSDimitry Andric #ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
425ffd83dbSDimitry Andric _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char)
43349cc55cSDimitry Andric #  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
445ffd83dbSDimitry Andric _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t)
45349cc55cSDimitry Andric #  endif
465ffd83dbSDimitry Andric #else
475ffd83dbSDimitry Andric _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char)
48349cc55cSDimitry Andric #  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
495ffd83dbSDimitry Andric _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t)
505ffd83dbSDimitry Andric #  endif
51349cc55cSDimitry Andric #endif
52fe6060f1SDimitry Andric #undef _LIBCPP_EXTERN_TEMPLATE_DEFINE
530b57cec5SDimitry Andric 
54fe6060f1SDimitry Andric template string operator+ <char, char_traits<char>, allocator<char>>(char const*, string const&);
550b57cec5SDimitry Andric 
56*cb14a3feSDimitry Andric namespace {
570b57cec5SDimitry Andric 
5881ad6265SDimitry Andric inline void throw_from_string_out_of_range(const string& func) {
5906c3fb27SDimitry Andric   std::__throw_out_of_range((func + ": out of range").c_str());
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric 
6281ad6265SDimitry Andric inline void throw_from_string_invalid_arg(const string& func) {
6306c3fb27SDimitry Andric   std::__throw_invalid_argument((func + ": no conversion").c_str());
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric // as_integer
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric template <typename V, typename S, typename F>
6981ad6265SDimitry Andric inline V as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f) {
700b57cec5SDimitry Andric   typename S::value_type* ptr                             = nullptr;
710b57cec5SDimitry Andric   const typename S::value_type* const p                   = str.c_str();
72bdd1243dSDimitry Andric   __libcpp_remove_reference_t<decltype(errno)> errno_save = errno;
730b57cec5SDimitry Andric   errno                                                   = 0;
740b57cec5SDimitry Andric   V r                                                     = f(p, &ptr, base);
750b57cec5SDimitry Andric   swap(errno, errno_save);
760b57cec5SDimitry Andric   if (errno_save == ERANGE)
770b57cec5SDimitry Andric     throw_from_string_out_of_range(func);
780b57cec5SDimitry Andric   if (ptr == p)
790b57cec5SDimitry Andric     throw_from_string_invalid_arg(func);
800b57cec5SDimitry Andric   if (idx)
810b57cec5SDimitry Andric     *idx = static_cast<size_t>(ptr - p);
820b57cec5SDimitry Andric   return r;
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric template <typename V, typename S>
8681ad6265SDimitry Andric inline V as_integer(const string& func, const S& s, size_t* idx, int base);
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric // string
890b57cec5SDimitry Andric template <>
9081ad6265SDimitry Andric inline int as_integer(const string& func, const string& s, size_t* idx, int base) {
910b57cec5SDimitry Andric   // Use long as no Standard string to integer exists.
920b57cec5SDimitry Andric   long r = as_integer_helper<long>(func, s, idx, base, strtol);
930b57cec5SDimitry Andric   if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
940b57cec5SDimitry Andric     throw_from_string_out_of_range(func);
950b57cec5SDimitry Andric   return static_cast<int>(r);
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric template <>
9981ad6265SDimitry Andric inline long as_integer(const string& func, const string& s, size_t* idx, int base) {
1000b57cec5SDimitry Andric   return as_integer_helper<long>(func, s, idx, base, strtol);
1010b57cec5SDimitry Andric }
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric template <>
10481ad6265SDimitry Andric inline unsigned long as_integer(const string& func, const string& s, size_t* idx, int base) {
1050b57cec5SDimitry Andric   return as_integer_helper<unsigned long>(func, s, idx, base, strtoul);
1060b57cec5SDimitry Andric }
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric template <>
10981ad6265SDimitry Andric inline long long as_integer(const string& func, const string& s, size_t* idx, int base) {
1100b57cec5SDimitry Andric   return as_integer_helper<long long>(func, s, idx, base, strtoll);
1110b57cec5SDimitry Andric }
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric template <>
11481ad6265SDimitry Andric inline unsigned long long as_integer(const string& func, const string& s, size_t* idx, int base) {
1150b57cec5SDimitry Andric   return as_integer_helper<unsigned long long>(func, s, idx, base, strtoull);
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric 
118349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1190b57cec5SDimitry Andric // wstring
1200b57cec5SDimitry Andric template <>
12181ad6265SDimitry Andric inline int as_integer(const string& func, const wstring& s, size_t* idx, int base) {
1220b57cec5SDimitry Andric   // Use long as no Stantard string to integer exists.
1230b57cec5SDimitry Andric   long r = as_integer_helper<long>(func, s, idx, base, wcstol);
1240b57cec5SDimitry Andric   if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
1250b57cec5SDimitry Andric     throw_from_string_out_of_range(func);
1260b57cec5SDimitry Andric   return static_cast<int>(r);
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric template <>
13081ad6265SDimitry Andric inline long as_integer(const string& func, const wstring& s, size_t* idx, int base) {
1310b57cec5SDimitry Andric   return as_integer_helper<long>(func, s, idx, base, wcstol);
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric template <>
135*cb14a3feSDimitry Andric inline unsigned long as_integer(const string& func, const wstring& s, size_t* idx, int base) {
1360b57cec5SDimitry Andric   return as_integer_helper<unsigned long>(func, s, idx, base, wcstoul);
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric template <>
14081ad6265SDimitry Andric inline long long as_integer(const string& func, const wstring& s, size_t* idx, int base) {
1410b57cec5SDimitry Andric   return as_integer_helper<long long>(func, s, idx, base, wcstoll);
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric template <>
14581ad6265SDimitry Andric inline unsigned long long as_integer(const string& func, const wstring& s, size_t* idx, int base) {
1460b57cec5SDimitry Andric   return as_integer_helper<unsigned long long>(func, s, idx, base, wcstoull);
1470b57cec5SDimitry Andric }
148349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric // as_float
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric template <typename V, typename S, typename F>
15381ad6265SDimitry Andric inline V as_float_helper(const string& func, const S& str, size_t* idx, F f) {
1540b57cec5SDimitry Andric   typename S::value_type* ptr                             = nullptr;
1550b57cec5SDimitry Andric   const typename S::value_type* const p                   = str.c_str();
156bdd1243dSDimitry Andric   __libcpp_remove_reference_t<decltype(errno)> errno_save = errno;
1570b57cec5SDimitry Andric   errno                                                   = 0;
1580b57cec5SDimitry Andric   V r                                                     = f(p, &ptr);
1590b57cec5SDimitry Andric   swap(errno, errno_save);
1600b57cec5SDimitry Andric   if (errno_save == ERANGE)
1610b57cec5SDimitry Andric     throw_from_string_out_of_range(func);
1620b57cec5SDimitry Andric   if (ptr == p)
1630b57cec5SDimitry Andric     throw_from_string_invalid_arg(func);
1640b57cec5SDimitry Andric   if (idx)
1650b57cec5SDimitry Andric     *idx = static_cast<size_t>(ptr - p);
1660b57cec5SDimitry Andric   return r;
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric template <typename V, typename S>
17081ad6265SDimitry Andric inline V as_float(const string& func, const S& s, size_t* idx = nullptr);
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric template <>
17381ad6265SDimitry Andric inline float as_float(const string& func, const string& s, size_t* idx) {
1740b57cec5SDimitry Andric   return as_float_helper<float>(func, s, idx, strtof);
1750b57cec5SDimitry Andric }
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric template <>
17881ad6265SDimitry Andric inline double as_float(const string& func, const string& s, size_t* idx) {
1790b57cec5SDimitry Andric   return as_float_helper<double>(func, s, idx, strtod);
1800b57cec5SDimitry Andric }
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric template <>
18381ad6265SDimitry Andric inline long double as_float(const string& func, const string& s, size_t* idx) {
1840b57cec5SDimitry Andric   return as_float_helper<long double>(func, s, idx, strtold);
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric 
187349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1880b57cec5SDimitry Andric template <>
18981ad6265SDimitry Andric inline float as_float(const string& func, const wstring& s, size_t* idx) {
1900b57cec5SDimitry Andric   return as_float_helper<float>(func, s, idx, wcstof);
1910b57cec5SDimitry Andric }
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric template <>
19481ad6265SDimitry Andric inline double as_float(const string& func, const wstring& s, size_t* idx) {
1950b57cec5SDimitry Andric   return as_float_helper<double>(func, s, idx, wcstod);
1960b57cec5SDimitry Andric }
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric template <>
19981ad6265SDimitry Andric inline long double as_float(const string& func, const wstring& s, size_t* idx) {
2000b57cec5SDimitry Andric   return as_float_helper<long double>(func, s, idx, wcstold);
2010b57cec5SDimitry Andric }
202349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric } // unnamed namespace
2050b57cec5SDimitry Andric 
206*cb14a3feSDimitry Andric int stoi(const string& str, size_t* idx, int base) { return as_integer<int>("stoi", str, idx, base); }
2070b57cec5SDimitry Andric 
208*cb14a3feSDimitry Andric long stol(const string& str, size_t* idx, int base) { return as_integer<long>("stol", str, idx, base); }
2090b57cec5SDimitry Andric 
21081ad6265SDimitry Andric unsigned long stoul(const string& str, size_t* idx, int base) {
2110b57cec5SDimitry Andric   return as_integer<unsigned long>("stoul", str, idx, base);
2120b57cec5SDimitry Andric }
2130b57cec5SDimitry Andric 
214*cb14a3feSDimitry Andric long long stoll(const string& str, size_t* idx, int base) { return as_integer<long long>("stoll", str, idx, base); }
2150b57cec5SDimitry Andric 
21681ad6265SDimitry Andric unsigned long long stoull(const string& str, size_t* idx, int base) {
2170b57cec5SDimitry Andric   return as_integer<unsigned long long>("stoull", str, idx, base);
2180b57cec5SDimitry Andric }
2190b57cec5SDimitry Andric 
220*cb14a3feSDimitry Andric float stof(const string& str, size_t* idx) { return as_float<float>("stof", str, idx); }
2210b57cec5SDimitry Andric 
222*cb14a3feSDimitry Andric double stod(const string& str, size_t* idx) { return as_float<double>("stod", str, idx); }
2230b57cec5SDimitry Andric 
224*cb14a3feSDimitry Andric long double stold(const string& str, size_t* idx) { return as_float<long double>("stold", str, idx); }
2250b57cec5SDimitry Andric 
226349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
227*cb14a3feSDimitry Andric int stoi(const wstring& str, size_t* idx, int base) { return as_integer<int>("stoi", str, idx, base); }
22881ad6265SDimitry Andric 
229*cb14a3feSDimitry Andric long stol(const wstring& str, size_t* idx, int base) { return as_integer<long>("stol", str, idx, base); }
23081ad6265SDimitry Andric 
23181ad6265SDimitry Andric unsigned long stoul(const wstring& str, size_t* idx, int base) {
23281ad6265SDimitry Andric   return as_integer<unsigned long>("stoul", str, idx, base);
23381ad6265SDimitry Andric }
23481ad6265SDimitry Andric 
235*cb14a3feSDimitry Andric long long stoll(const wstring& str, size_t* idx, int base) { return as_integer<long long>("stoll", str, idx, base); }
23681ad6265SDimitry Andric 
23781ad6265SDimitry Andric unsigned long long stoull(const wstring& str, size_t* idx, int base) {
23881ad6265SDimitry Andric   return as_integer<unsigned long long>("stoull", str, idx, base);
23981ad6265SDimitry Andric }
24081ad6265SDimitry Andric 
241*cb14a3feSDimitry Andric float stof(const wstring& str, size_t* idx) { return as_float<float>("stof", str, idx); }
24281ad6265SDimitry Andric 
243*cb14a3feSDimitry Andric double stod(const wstring& str, size_t* idx) { return as_float<double>("stod", str, idx); }
24481ad6265SDimitry Andric 
245*cb14a3feSDimitry Andric long double stold(const wstring& str, size_t* idx) { return as_float<long double>("stold", str, idx); }
24681ad6265SDimitry Andric #endif // !_LIBCPP_HAS_NO_WIDE_CHARACTERS
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric // to_string
2490b57cec5SDimitry Andric 
250*cb14a3feSDimitry Andric namespace {
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric // as_string
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric template <typename S, typename P, typename V >
25581ad6265SDimitry Andric inline S as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a) {
2560b57cec5SDimitry Andric   typedef typename S::size_type size_type;
2570b57cec5SDimitry Andric   size_type available = s.size();
25881ad6265SDimitry Andric   while (true) {
2590b57cec5SDimitry Andric     int status = sprintf_like(&s[0], available + 1, fmt, a);
26081ad6265SDimitry Andric     if (status >= 0) {
2610b57cec5SDimitry Andric       size_type used = static_cast<size_type>(status);
26281ad6265SDimitry Andric       if (used <= available) {
2630b57cec5SDimitry Andric         s.resize(used);
2640b57cec5SDimitry Andric         break;
2650b57cec5SDimitry Andric       }
2660b57cec5SDimitry Andric       available = used; // Assume this is advice of how much space we need.
267*cb14a3feSDimitry Andric     } else
2680b57cec5SDimitry Andric       available = available * 2 + 1;
2690b57cec5SDimitry Andric     s.resize(available);
2700b57cec5SDimitry Andric   }
2710b57cec5SDimitry Andric   return s;
2720b57cec5SDimitry Andric }
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric template <class S>
2750b57cec5SDimitry Andric struct initial_string;
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric template <>
27881ad6265SDimitry Andric struct initial_string<string> {
27981ad6265SDimitry Andric   string operator()() const {
2800b57cec5SDimitry Andric     string s;
2810b57cec5SDimitry Andric     s.resize(s.capacity());
2820b57cec5SDimitry Andric     return s;
2830b57cec5SDimitry Andric   }
2840b57cec5SDimitry Andric };
2850b57cec5SDimitry Andric 
286349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
2870b57cec5SDimitry Andric template <>
28881ad6265SDimitry Andric struct initial_string<wstring> {
28981ad6265SDimitry Andric   wstring operator()() const {
2900b57cec5SDimitry Andric     wstring s(20, wchar_t());
2910b57cec5SDimitry Andric     s.resize(s.capacity());
2920b57cec5SDimitry Andric     return s;
2930b57cec5SDimitry Andric   }
2940b57cec5SDimitry Andric };
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t* __restrict, ...);
2970b57cec5SDimitry Andric 
29881ad6265SDimitry Andric inline wide_printf get_swprintf() {
2990b57cec5SDimitry Andric #  ifndef _LIBCPP_MSVCRT
3000b57cec5SDimitry Andric   return swprintf;
3010b57cec5SDimitry Andric #  else
3020b57cec5SDimitry Andric   return static_cast<int(__cdecl*)(wchar_t* __restrict, size_t, const wchar_t* __restrict, ...)>(_snwprintf);
3030b57cec5SDimitry Andric #  endif
3040b57cec5SDimitry Andric }
305349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric template <typename S, typename V>
30881ad6265SDimitry Andric S i_to_string(V v) {
3090b57cec5SDimitry Andric   //  numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers.
3100b57cec5SDimitry Andric   //  For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented),
3110b57cec5SDimitry Andric   //  so we need +1 here.
3120b57cec5SDimitry Andric   constexpr size_t bufsize = numeric_limits<V>::digits10 + 2; // +1 for minus, +1 for digits10
3130b57cec5SDimitry Andric   char buf[bufsize];
3140b57cec5SDimitry Andric   const auto res = to_chars(buf, buf + bufsize, v);
31506c3fb27SDimitry Andric   _LIBCPP_ASSERT_INTERNAL(res.ec == errc(), "bufsize must be large enough to accomodate the value");
3160b57cec5SDimitry Andric   return S(buf, res.ptr);
3170b57cec5SDimitry Andric }
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric } // unnamed namespace
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric string to_string(int val) { return i_to_string< string>(val); }
3220b57cec5SDimitry Andric string to_string(long val) { return i_to_string< string>(val); }
3230b57cec5SDimitry Andric string to_string(long long val) { return i_to_string< string>(val); }
3240b57cec5SDimitry Andric string to_string(unsigned val) { return i_to_string< string>(val); }
3250b57cec5SDimitry Andric string to_string(unsigned long val) { return i_to_string< string>(val); }
3260b57cec5SDimitry Andric string to_string(unsigned long long val) { return i_to_string< string>(val); }
3270b57cec5SDimitry Andric 
328349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3290b57cec5SDimitry Andric wstring to_wstring(int val) { return i_to_string<wstring>(val); }
3300b57cec5SDimitry Andric wstring to_wstring(long val) { return i_to_string<wstring>(val); }
3310b57cec5SDimitry Andric wstring to_wstring(long long val) { return i_to_string<wstring>(val); }
3320b57cec5SDimitry Andric wstring to_wstring(unsigned val) { return i_to_string<wstring>(val); }
3330b57cec5SDimitry Andric wstring to_wstring(unsigned long val) { return i_to_string<wstring>(val); }
3340b57cec5SDimitry Andric wstring to_wstring(unsigned long long val) { return i_to_string<wstring>(val); }
335349cc55cSDimitry Andric #endif
3360b57cec5SDimitry Andric 
3370b57cec5SDimitry Andric string to_string(float val) { return as_string(snprintf, initial_string< string>()(), "%f", val); }
3380b57cec5SDimitry Andric string to_string(double val) { return as_string(snprintf, initial_string< string>()(), "%f", val); }
3390b57cec5SDimitry Andric string to_string(long double val) { return as_string(snprintf, initial_string< string>()(), "%Lf", val); }
3400b57cec5SDimitry Andric 
341349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3420b57cec5SDimitry Andric wstring to_wstring(float val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); }
3430b57cec5SDimitry Andric wstring to_wstring(double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); }
3440b57cec5SDimitry Andric wstring to_wstring(long double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%Lf", val); }
345349cc55cSDimitry Andric #endif
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric _LIBCPP_END_NAMESPACE_STD
348