xref: /freebsd/contrib/llvm-project/libcxx/src/string.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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 
35349cc55cSDimitry Andric void __basic_string_common<true>::__throw_length_error() const {
361838bd0fSDimitry Andric     std::__throw_length_error("basic_string");
371838bd0fSDimitry Andric }
381838bd0fSDimitry Andric void __basic_string_common<true>::__throw_out_of_range() const {
391838bd0fSDimitry Andric     std::__throw_out_of_range("basic_string");
40349cc55cSDimitry Andric }
41349cc55cSDimitry Andric 
421838bd0fSDimitry Andric #endif // _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON
430b57cec5SDimitry Andric 
44fe6060f1SDimitry Andric #define _LIBCPP_EXTERN_TEMPLATE_DEFINE(...) template __VA_ARGS__;
455ffd83dbSDimitry Andric #ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
465ffd83dbSDimitry Andric     _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char)
47349cc55cSDimitry Andric #   ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
485ffd83dbSDimitry Andric         _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t)
49349cc55cSDimitry Andric #   endif
505ffd83dbSDimitry Andric #else
515ffd83dbSDimitry Andric     _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char)
52349cc55cSDimitry Andric #   ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
535ffd83dbSDimitry Andric         _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t)
545ffd83dbSDimitry Andric #   endif
55349cc55cSDimitry Andric #endif
56fe6060f1SDimitry Andric #undef _LIBCPP_EXTERN_TEMPLATE_DEFINE
570b57cec5SDimitry Andric 
58fe6060f1SDimitry Andric template string operator+<char, char_traits<char>, allocator<char>>(char const*, string const&);
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric namespace
610b57cec5SDimitry Andric {
620b57cec5SDimitry Andric 
6381ad6265SDimitry Andric inline void throw_from_string_out_of_range(const string& func) {
64*06c3fb27SDimitry Andric     std::__throw_out_of_range((func + ": out of range").c_str());
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric 
6781ad6265SDimitry Andric inline void throw_from_string_invalid_arg(const string& func) {
68*06c3fb27SDimitry Andric     std::__throw_invalid_argument((func + ": no conversion").c_str());
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric // as_integer
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric template<typename V, typename S, typename F>
7481ad6265SDimitry Andric inline V as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f) {
750b57cec5SDimitry Andric     typename S::value_type* ptr = nullptr;
760b57cec5SDimitry Andric     const typename S::value_type* const p = str.c_str();
77bdd1243dSDimitry Andric     __libcpp_remove_reference_t<decltype(errno)> errno_save = errno;
780b57cec5SDimitry Andric     errno = 0;
790b57cec5SDimitry Andric     V r = f(p, &ptr, base);
800b57cec5SDimitry Andric     swap(errno, errno_save);
810b57cec5SDimitry Andric     if (errno_save == ERANGE)
820b57cec5SDimitry Andric         throw_from_string_out_of_range(func);
830b57cec5SDimitry Andric     if (ptr == p)
840b57cec5SDimitry Andric         throw_from_string_invalid_arg(func);
850b57cec5SDimitry Andric     if (idx)
860b57cec5SDimitry Andric         *idx = static_cast<size_t>(ptr - p);
870b57cec5SDimitry Andric     return r;
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric template<typename V, typename S>
9181ad6265SDimitry Andric inline V as_integer(const string& func, const S& s, size_t* idx, int base);
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric // string
940b57cec5SDimitry Andric template<>
9581ad6265SDimitry Andric inline int as_integer(const string& func, const string& s, size_t* idx, int base) {
960b57cec5SDimitry Andric     // Use long as no Standard string to integer exists.
970b57cec5SDimitry Andric     long r = as_integer_helper<long>(func, s, idx, base, strtol);
980b57cec5SDimitry Andric     if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
990b57cec5SDimitry Andric         throw_from_string_out_of_range(func);
1000b57cec5SDimitry Andric     return static_cast<int>(r);
1010b57cec5SDimitry Andric }
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric template<>
10481ad6265SDimitry Andric inline long as_integer(const string& func, const string& s, size_t* idx, int base) {
1050b57cec5SDimitry Andric     return as_integer_helper<long>(func, s, idx, base, strtol);
1060b57cec5SDimitry Andric }
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric template<>
10981ad6265SDimitry Andric inline unsigned long as_integer(const string& func, const string& s, size_t* idx, int base) {
1100b57cec5SDimitry Andric     return as_integer_helper<unsigned long>(func, s, idx, base, strtoul);
1110b57cec5SDimitry Andric }
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric template<>
11481ad6265SDimitry Andric inline long long as_integer(const string& func, const string& s, size_t* idx, int base) {
1150b57cec5SDimitry Andric     return as_integer_helper<long long>(func, s, idx, base, strtoll);
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric template<>
11981ad6265SDimitry Andric inline unsigned long long as_integer(const string& func, const string& s, size_t* idx, int base) {
1200b57cec5SDimitry Andric     return as_integer_helper<unsigned long long>(func, s, idx, base, strtoull);
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric 
123349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1240b57cec5SDimitry Andric // wstring
1250b57cec5SDimitry Andric template<>
12681ad6265SDimitry Andric inline int as_integer(const string& func, const wstring& s, size_t* idx, int base) {
1270b57cec5SDimitry Andric     // Use long as no Stantard string to integer exists.
1280b57cec5SDimitry Andric     long r = as_integer_helper<long>(func, s, idx, base, wcstol);
1290b57cec5SDimitry Andric     if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
1300b57cec5SDimitry Andric         throw_from_string_out_of_range(func);
1310b57cec5SDimitry Andric     return static_cast<int>(r);
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric template<>
13581ad6265SDimitry Andric inline long as_integer(const string& func, const wstring& s, size_t* idx, int base) {
1360b57cec5SDimitry Andric     return as_integer_helper<long>(func, s, idx, base, wcstol);
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric template<>
1400b57cec5SDimitry Andric inline
1410b57cec5SDimitry Andric unsigned long
1420b57cec5SDimitry Andric as_integer(const string& func, const wstring& s, size_t* idx, int base)
1430b57cec5SDimitry Andric {
1440b57cec5SDimitry Andric     return as_integer_helper<unsigned long>(func, s, idx, base, wcstoul);
1450b57cec5SDimitry Andric }
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric template<>
14881ad6265SDimitry Andric inline long long as_integer(const string& func, const wstring& s, size_t* idx, int base) {
1490b57cec5SDimitry Andric     return as_integer_helper<long long>(func, s, idx, base, wcstoll);
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric template<>
15381ad6265SDimitry Andric inline unsigned long long as_integer(const string& func, const wstring& s, size_t* idx, int base) {
1540b57cec5SDimitry Andric     return as_integer_helper<unsigned long long>(func, s, idx, base, wcstoull);
1550b57cec5SDimitry Andric }
156349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric // as_float
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric template<typename V, typename S, typename F>
16181ad6265SDimitry Andric inline V as_float_helper(const string& func, const S& str, size_t* idx, F f) {
1620b57cec5SDimitry Andric     typename S::value_type* ptr = nullptr;
1630b57cec5SDimitry Andric     const typename S::value_type* const p = str.c_str();
164bdd1243dSDimitry Andric     __libcpp_remove_reference_t<decltype(errno)> errno_save = errno;
1650b57cec5SDimitry Andric     errno = 0;
1660b57cec5SDimitry Andric     V r = f(p, &ptr);
1670b57cec5SDimitry Andric     swap(errno, errno_save);
1680b57cec5SDimitry Andric     if (errno_save == ERANGE)
1690b57cec5SDimitry Andric         throw_from_string_out_of_range(func);
1700b57cec5SDimitry Andric     if (ptr == p)
1710b57cec5SDimitry Andric         throw_from_string_invalid_arg(func);
1720b57cec5SDimitry Andric     if (idx)
1730b57cec5SDimitry Andric         *idx = static_cast<size_t>(ptr - p);
1740b57cec5SDimitry Andric     return r;
1750b57cec5SDimitry Andric }
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric template<typename V, typename S>
17881ad6265SDimitry Andric inline V as_float(const string& func, const S& s, size_t* idx = nullptr);
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric template<>
18181ad6265SDimitry Andric inline float as_float(const string& func, const string& s, size_t* idx) {
1820b57cec5SDimitry Andric     return as_float_helper<float>(func, s, idx, strtof);
1830b57cec5SDimitry Andric }
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric template<>
18681ad6265SDimitry Andric inline double as_float(const string& func, const string& s, size_t* idx) {
1870b57cec5SDimitry Andric     return as_float_helper<double>(func, s, idx, strtod);
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric template<>
19181ad6265SDimitry Andric inline long double as_float(const string& func, const string& s, size_t* idx) {
1920b57cec5SDimitry Andric     return as_float_helper<long double>(func, s, idx, strtold);
1930b57cec5SDimitry Andric }
1940b57cec5SDimitry Andric 
195349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1960b57cec5SDimitry Andric template<>
19781ad6265SDimitry Andric inline float as_float(const string& func, const wstring& s, size_t* idx) {
1980b57cec5SDimitry Andric     return as_float_helper<float>(func, s, idx, wcstof);
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric template<>
20281ad6265SDimitry Andric inline double as_float(const string& func, const wstring& s, size_t* idx) {
2030b57cec5SDimitry Andric     return as_float_helper<double>(func, s, idx, wcstod);
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric template<>
20781ad6265SDimitry Andric inline long double as_float(const string& func, const wstring& s, size_t* idx) {
2080b57cec5SDimitry Andric     return as_float_helper<long double>(func, s, idx, wcstold);
2090b57cec5SDimitry Andric }
210349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric }  // unnamed namespace
2130b57cec5SDimitry Andric 
21481ad6265SDimitry Andric int stoi(const string& str, size_t* idx, int base) {
2150b57cec5SDimitry Andric     return as_integer<int>("stoi", str, idx, base);
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric 
21881ad6265SDimitry Andric long stol(const string& str, size_t* idx, int base) {
2190b57cec5SDimitry Andric     return as_integer<long>("stol", str, idx, base);
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric 
22281ad6265SDimitry Andric unsigned long stoul(const string& str, size_t* idx, int base) {
2230b57cec5SDimitry Andric     return as_integer<unsigned long>("stoul", str, idx, base);
2240b57cec5SDimitry Andric }
2250b57cec5SDimitry Andric 
22681ad6265SDimitry Andric long long stoll(const string& str, size_t* idx, int base) {
2270b57cec5SDimitry Andric     return as_integer<long long>("stoll", str, idx, base);
2280b57cec5SDimitry Andric }
2290b57cec5SDimitry Andric 
23081ad6265SDimitry Andric unsigned long long stoull(const string& str, size_t* idx, int base) {
2310b57cec5SDimitry Andric     return as_integer<unsigned long long>("stoull", str, idx, base);
2320b57cec5SDimitry Andric }
2330b57cec5SDimitry Andric 
23481ad6265SDimitry Andric float stof(const string& str, size_t* idx) {
2350b57cec5SDimitry Andric     return as_float<float>("stof", str, idx);
2360b57cec5SDimitry Andric }
2370b57cec5SDimitry Andric 
23881ad6265SDimitry Andric double stod(const string& str, size_t* idx) {
2390b57cec5SDimitry Andric     return as_float<double>("stod", str, idx);
2400b57cec5SDimitry Andric }
2410b57cec5SDimitry Andric 
24281ad6265SDimitry Andric long double stold(const string& str, size_t* idx) {
2430b57cec5SDimitry Andric     return as_float<long double>("stold", str, idx);
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric 
246349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
24781ad6265SDimitry Andric int stoi(const wstring& str, size_t* idx, int base) {
24881ad6265SDimitry Andric     return as_integer<int>("stoi", str, idx, base);
24981ad6265SDimitry Andric }
25081ad6265SDimitry Andric 
25181ad6265SDimitry Andric long stol(const wstring& str, size_t* idx, int base) {
25281ad6265SDimitry Andric     return as_integer<long>("stol", str, idx, base);
25381ad6265SDimitry Andric }
25481ad6265SDimitry Andric 
25581ad6265SDimitry Andric unsigned long stoul(const wstring& str, size_t* idx, int base) {
25681ad6265SDimitry Andric     return as_integer<unsigned long>("stoul", str, idx, base);
25781ad6265SDimitry Andric }
25881ad6265SDimitry Andric 
25981ad6265SDimitry Andric long long stoll(const wstring& str, size_t* idx, int base) {
26081ad6265SDimitry Andric     return as_integer<long long>("stoll", str, idx, base);
26181ad6265SDimitry Andric }
26281ad6265SDimitry Andric 
26381ad6265SDimitry Andric unsigned long long stoull(const wstring& str, size_t* idx, int base) {
26481ad6265SDimitry Andric     return as_integer<unsigned long long>("stoull", str, idx, base);
26581ad6265SDimitry Andric }
26681ad6265SDimitry Andric 
26781ad6265SDimitry Andric float stof(const wstring& str, size_t* idx) {
26881ad6265SDimitry Andric     return as_float<float>("stof", str, idx);
26981ad6265SDimitry Andric }
27081ad6265SDimitry Andric 
27181ad6265SDimitry Andric double stod(const wstring& str, size_t* idx) {
27281ad6265SDimitry Andric     return as_float<double>("stod", str, idx);
27381ad6265SDimitry Andric }
27481ad6265SDimitry Andric 
27581ad6265SDimitry Andric long double stold(const wstring& str, size_t* idx) {
2760b57cec5SDimitry Andric     return as_float<long double>("stold", str, idx);
2770b57cec5SDimitry Andric }
27881ad6265SDimitry Andric #endif // !_LIBCPP_HAS_NO_WIDE_CHARACTERS
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric // to_string
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric namespace
2830b57cec5SDimitry Andric {
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric // as_string
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric template<typename S, typename P, typename V >
28881ad6265SDimitry Andric inline S as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a) {
2890b57cec5SDimitry Andric     typedef typename S::size_type size_type;
2900b57cec5SDimitry Andric     size_type available = s.size();
29181ad6265SDimitry Andric     while (true) {
2920b57cec5SDimitry Andric         int status = sprintf_like(&s[0], available + 1, fmt, a);
29381ad6265SDimitry Andric         if (status >= 0) {
2940b57cec5SDimitry Andric             size_type used = static_cast<size_type>(status);
29581ad6265SDimitry Andric             if (used <= available) {
2960b57cec5SDimitry Andric                 s.resize(used);
2970b57cec5SDimitry Andric                 break;
2980b57cec5SDimitry Andric             }
2990b57cec5SDimitry Andric             available = used; // Assume this is advice of how much space we need.
3000b57cec5SDimitry Andric         }
3010b57cec5SDimitry Andric         else
3020b57cec5SDimitry Andric             available = available * 2 + 1;
3030b57cec5SDimitry Andric         s.resize(available);
3040b57cec5SDimitry Andric     }
3050b57cec5SDimitry Andric     return s;
3060b57cec5SDimitry Andric }
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric template <class S>
3090b57cec5SDimitry Andric struct initial_string;
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric template <>
31281ad6265SDimitry Andric struct initial_string<string> {
31381ad6265SDimitry Andric     string operator()() const {
3140b57cec5SDimitry Andric         string s;
3150b57cec5SDimitry Andric         s.resize(s.capacity());
3160b57cec5SDimitry Andric         return s;
3170b57cec5SDimitry Andric     }
3180b57cec5SDimitry Andric };
3190b57cec5SDimitry Andric 
320349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3210b57cec5SDimitry Andric template <>
32281ad6265SDimitry Andric struct initial_string<wstring> {
32381ad6265SDimitry Andric     wstring operator()() const {
3240b57cec5SDimitry Andric         wstring s(20, wchar_t());
3250b57cec5SDimitry Andric         s.resize(s.capacity());
3260b57cec5SDimitry Andric         return s;
3270b57cec5SDimitry Andric     }
3280b57cec5SDimitry Andric };
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...);
3310b57cec5SDimitry Andric 
33281ad6265SDimitry Andric inline wide_printf get_swprintf() {
3330b57cec5SDimitry Andric #ifndef _LIBCPP_MSVCRT
3340b57cec5SDimitry Andric     return swprintf;
3350b57cec5SDimitry Andric #else
3360b57cec5SDimitry Andric     return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(_snwprintf);
3370b57cec5SDimitry Andric #endif
3380b57cec5SDimitry Andric }
339349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric template <typename S, typename V>
34281ad6265SDimitry Andric S i_to_string(V v) {
3430b57cec5SDimitry Andric //  numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers.
3440b57cec5SDimitry Andric //  For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented),
3450b57cec5SDimitry Andric //  so we need +1 here.
3460b57cec5SDimitry Andric     constexpr size_t bufsize = numeric_limits<V>::digits10 + 2;  // +1 for minus, +1 for digits10
3470b57cec5SDimitry Andric     char buf[bufsize];
3480b57cec5SDimitry Andric     const auto res = to_chars(buf, buf + bufsize, v);
349*06c3fb27SDimitry Andric     _LIBCPP_ASSERT_INTERNAL(res.ec == errc(), "bufsize must be large enough to accomodate the value");
3500b57cec5SDimitry Andric     return S(buf, res.ptr);
3510b57cec5SDimitry Andric }
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric }  // unnamed namespace
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric string  to_string (int val)                { return i_to_string< string>(val); }
3560b57cec5SDimitry Andric string  to_string (long val)               { return i_to_string< string>(val); }
3570b57cec5SDimitry Andric string  to_string (long long val)          { return i_to_string< string>(val); }
3580b57cec5SDimitry Andric string  to_string (unsigned val)           { return i_to_string< string>(val); }
3590b57cec5SDimitry Andric string  to_string (unsigned long val)      { return i_to_string< string>(val); }
3600b57cec5SDimitry Andric string  to_string (unsigned long long val) { return i_to_string< string>(val); }
3610b57cec5SDimitry Andric 
362349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3630b57cec5SDimitry Andric wstring to_wstring(int val)                { return i_to_string<wstring>(val); }
3640b57cec5SDimitry Andric wstring to_wstring(long val)               { return i_to_string<wstring>(val); }
3650b57cec5SDimitry Andric wstring to_wstring(long long val)          { return i_to_string<wstring>(val); }
3660b57cec5SDimitry Andric wstring to_wstring(unsigned val)           { return i_to_string<wstring>(val); }
3670b57cec5SDimitry Andric wstring to_wstring(unsigned long val)      { return i_to_string<wstring>(val); }
3680b57cec5SDimitry Andric wstring to_wstring(unsigned long long val) { return i_to_string<wstring>(val); }
369349cc55cSDimitry Andric #endif
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric string  to_string (float val)       { return as_string(snprintf,       initial_string< string>()(),   "%f", val); }
3720b57cec5SDimitry Andric string  to_string (double val)      { return as_string(snprintf,       initial_string< string>()(),   "%f", val); }
3730b57cec5SDimitry Andric string  to_string (long double val) { return as_string(snprintf,       initial_string< string>()(),  "%Lf", val); }
3740b57cec5SDimitry Andric 
375349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3760b57cec5SDimitry Andric wstring to_wstring(float val)       { return as_string(get_swprintf(), initial_string<wstring>()(),  L"%f", val); }
3770b57cec5SDimitry Andric wstring to_wstring(double val)      { return as_string(get_swprintf(), initial_string<wstring>()(),  L"%f", val); }
3780b57cec5SDimitry Andric wstring to_wstring(long double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%Lf", val); }
379349cc55cSDimitry Andric #endif
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric _LIBCPP_END_NAMESPACE_STD
382