xref: /freebsd/contrib/llvm-project/libcxx/src/string.cpp (revision 1838bd0f4839006b42d41a02a787b7f578655223)
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 
90b57cec5SDimitry Andric #include "string"
100b57cec5SDimitry Andric #include "charconv"
110b57cec5SDimitry Andric #include "cstdlib"
120b57cec5SDimitry Andric #include "cerrno"
130b57cec5SDimitry Andric #include "limits"
140b57cec5SDimitry Andric #include "stdexcept"
150b57cec5SDimitry Andric #include <stdio.h>
160b57cec5SDimitry Andric #include "__debug"
170b57cec5SDimitry Andric 
18349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
19349cc55cSDimitry Andric #   include "cwchar"
20349cc55cSDimitry Andric #endif
21349cc55cSDimitry Andric 
220b57cec5SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
230b57cec5SDimitry Andric 
24*1838bd0fSDimitry Andric #ifndef _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON
25*1838bd0fSDimitry Andric 
26*1838bd0fSDimitry Andric template <bool>
27*1838bd0fSDimitry Andric struct __basic_string_common;
28*1838bd0fSDimitry Andric 
29*1838bd0fSDimitry Andric // The struct isn't declared anymore in the headers. It's only here for ABI compatibility.
30*1838bd0fSDimitry Andric template <>
31*1838bd0fSDimitry Andric struct __basic_string_common<true> {
32*1838bd0fSDimitry Andric     _LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __throw_length_error() const;
33*1838bd0fSDimitry Andric     _LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __throw_out_of_range() const;
34*1838bd0fSDimitry Andric };
35*1838bd0fSDimitry Andric 
36349cc55cSDimitry Andric void __basic_string_common<true>::__throw_length_error() const {
37*1838bd0fSDimitry Andric     std::__throw_length_error("basic_string");
38*1838bd0fSDimitry Andric }
39*1838bd0fSDimitry Andric void __basic_string_common<true>::__throw_out_of_range() const {
40*1838bd0fSDimitry Andric     std::__throw_out_of_range("basic_string");
41349cc55cSDimitry Andric }
42349cc55cSDimitry Andric 
43*1838bd0fSDimitry 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>
650b57cec5SDimitry Andric inline
660b57cec5SDimitry Andric void throw_helper( const string& msg )
670b57cec5SDimitry Andric {
680b57cec5SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
690b57cec5SDimitry Andric     throw T( msg );
700b57cec5SDimitry Andric #else
710b57cec5SDimitry Andric     fprintf(stderr, "%s\n", msg.c_str());
720b57cec5SDimitry Andric     _VSTD::abort();
730b57cec5SDimitry Andric #endif
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric inline
770b57cec5SDimitry Andric void throw_from_string_out_of_range( const string& func )
780b57cec5SDimitry Andric {
790b57cec5SDimitry Andric     throw_helper<out_of_range>(func + ": out of range");
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric inline
830b57cec5SDimitry Andric void throw_from_string_invalid_arg( const string& func )
840b57cec5SDimitry Andric {
850b57cec5SDimitry Andric     throw_helper<invalid_argument>(func + ": no conversion");
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric // as_integer
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric template<typename V, typename S, typename F>
910b57cec5SDimitry Andric inline
920b57cec5SDimitry Andric V
930b57cec5SDimitry Andric as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f)
940b57cec5SDimitry Andric {
950b57cec5SDimitry Andric     typename S::value_type* ptr = nullptr;
960b57cec5SDimitry Andric     const typename S::value_type* const p = str.c_str();
970b57cec5SDimitry Andric     typename remove_reference<decltype(errno)>::type errno_save = errno;
980b57cec5SDimitry Andric     errno = 0;
990b57cec5SDimitry Andric     V r = f(p, &ptr, base);
1000b57cec5SDimitry Andric     swap(errno, errno_save);
1010b57cec5SDimitry Andric     if (errno_save == ERANGE)
1020b57cec5SDimitry Andric         throw_from_string_out_of_range(func);
1030b57cec5SDimitry Andric     if (ptr == p)
1040b57cec5SDimitry Andric         throw_from_string_invalid_arg(func);
1050b57cec5SDimitry Andric     if (idx)
1060b57cec5SDimitry Andric         *idx = static_cast<size_t>(ptr - p);
1070b57cec5SDimitry Andric     return r;
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric template<typename V, typename S>
1110b57cec5SDimitry Andric inline
1120b57cec5SDimitry Andric V
1130b57cec5SDimitry Andric as_integer(const string& func, const S& s, size_t* idx, int base);
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric // string
1160b57cec5SDimitry Andric template<>
1170b57cec5SDimitry Andric inline
1180b57cec5SDimitry Andric int
1190b57cec5SDimitry Andric as_integer(const string& func, const string& s, size_t* idx, int base )
1200b57cec5SDimitry Andric {
1210b57cec5SDimitry Andric     // Use long as no Standard string to integer exists.
1220b57cec5SDimitry Andric     long r = as_integer_helper<long>( func, s, idx, base, strtol );
1230b57cec5SDimitry Andric     if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
1240b57cec5SDimitry Andric         throw_from_string_out_of_range(func);
1250b57cec5SDimitry Andric     return static_cast<int>(r);
1260b57cec5SDimitry Andric }
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric template<>
1290b57cec5SDimitry Andric inline
1300b57cec5SDimitry Andric long
1310b57cec5SDimitry Andric as_integer(const string& func, const string& s, size_t* idx, int base )
1320b57cec5SDimitry Andric {
1330b57cec5SDimitry Andric     return as_integer_helper<long>( func, s, idx, base, strtol );
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric template<>
1370b57cec5SDimitry Andric inline
1380b57cec5SDimitry Andric unsigned long
1390b57cec5SDimitry Andric as_integer( const string& func, const string& s, size_t* idx, int base )
1400b57cec5SDimitry Andric {
1410b57cec5SDimitry Andric     return as_integer_helper<unsigned long>( func, s, idx, base, strtoul );
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric template<>
1450b57cec5SDimitry Andric inline
1460b57cec5SDimitry Andric long long
1470b57cec5SDimitry Andric as_integer( const string& func, const string& s, size_t* idx, int base )
1480b57cec5SDimitry Andric {
1490b57cec5SDimitry Andric     return as_integer_helper<long long>( func, s, idx, base, strtoll );
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric template<>
1530b57cec5SDimitry Andric inline
1540b57cec5SDimitry Andric unsigned long long
1550b57cec5SDimitry Andric as_integer( const string& func, const string& s, size_t* idx, int base )
1560b57cec5SDimitry Andric {
1570b57cec5SDimitry Andric     return as_integer_helper<unsigned long long>( func, s, idx, base, strtoull );
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric 
160349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1610b57cec5SDimitry Andric // wstring
1620b57cec5SDimitry Andric template<>
1630b57cec5SDimitry Andric inline
1640b57cec5SDimitry Andric int
1650b57cec5SDimitry Andric as_integer( const string& func, const wstring& s, size_t* idx, int base )
1660b57cec5SDimitry Andric {
1670b57cec5SDimitry Andric     // Use long as no Stantard string to integer exists.
1680b57cec5SDimitry Andric     long r = as_integer_helper<long>( func, s, idx, base, wcstol );
1690b57cec5SDimitry Andric     if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
1700b57cec5SDimitry Andric         throw_from_string_out_of_range(func);
1710b57cec5SDimitry Andric     return static_cast<int>(r);
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric template<>
1750b57cec5SDimitry Andric inline
1760b57cec5SDimitry Andric long
1770b57cec5SDimitry Andric as_integer( const string& func, const wstring& s, size_t* idx, int base )
1780b57cec5SDimitry Andric {
1790b57cec5SDimitry Andric     return as_integer_helper<long>( func, s, idx, base, wcstol );
1800b57cec5SDimitry Andric }
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric template<>
1830b57cec5SDimitry Andric inline
1840b57cec5SDimitry Andric unsigned long
1850b57cec5SDimitry Andric as_integer( const string& func, const wstring& s, size_t* idx, int base )
1860b57cec5SDimitry Andric {
1870b57cec5SDimitry Andric     return as_integer_helper<unsigned long>( func, s, idx, base, wcstoul );
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric template<>
1910b57cec5SDimitry Andric inline
1920b57cec5SDimitry Andric long long
1930b57cec5SDimitry Andric as_integer( const string& func, const wstring& s, size_t* idx, int base )
1940b57cec5SDimitry Andric {
1950b57cec5SDimitry Andric     return as_integer_helper<long long>( func, s, idx, base, wcstoll );
1960b57cec5SDimitry Andric }
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric template<>
1990b57cec5SDimitry Andric inline
2000b57cec5SDimitry Andric unsigned long long
2010b57cec5SDimitry Andric as_integer( const string& func, const wstring& s, size_t* idx, int base )
2020b57cec5SDimitry Andric {
2030b57cec5SDimitry Andric     return as_integer_helper<unsigned long long>( func, s, idx, base, wcstoull );
2040b57cec5SDimitry Andric }
205349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric // as_float
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric template<typename V, typename S, typename F>
2100b57cec5SDimitry Andric inline
2110b57cec5SDimitry Andric V
2120b57cec5SDimitry Andric as_float_helper(const string& func, const S& str, size_t* idx, F f )
2130b57cec5SDimitry Andric {
2140b57cec5SDimitry Andric     typename S::value_type* ptr = nullptr;
2150b57cec5SDimitry Andric     const typename S::value_type* const p = str.c_str();
2160b57cec5SDimitry Andric     typename remove_reference<decltype(errno)>::type errno_save = errno;
2170b57cec5SDimitry Andric     errno = 0;
2180b57cec5SDimitry Andric     V r = f(p, &ptr);
2190b57cec5SDimitry Andric     swap(errno, errno_save);
2200b57cec5SDimitry Andric     if (errno_save == ERANGE)
2210b57cec5SDimitry Andric         throw_from_string_out_of_range(func);
2220b57cec5SDimitry Andric     if (ptr == p)
2230b57cec5SDimitry Andric         throw_from_string_invalid_arg(func);
2240b57cec5SDimitry Andric     if (idx)
2250b57cec5SDimitry Andric         *idx = static_cast<size_t>(ptr - p);
2260b57cec5SDimitry Andric     return r;
2270b57cec5SDimitry Andric }
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric template<typename V, typename S>
2300b57cec5SDimitry Andric inline
2310b57cec5SDimitry Andric V as_float( const string& func, const S& s, size_t* idx = nullptr );
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric template<>
2340b57cec5SDimitry Andric inline
2350b57cec5SDimitry Andric float
2360b57cec5SDimitry Andric as_float( const string& func, const string& s, size_t* idx )
2370b57cec5SDimitry Andric {
2380b57cec5SDimitry Andric     return as_float_helper<float>( func, s, idx, strtof );
2390b57cec5SDimitry Andric }
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric template<>
2420b57cec5SDimitry Andric inline
2430b57cec5SDimitry Andric double
2440b57cec5SDimitry Andric as_float(const string& func, const string& s, size_t* idx )
2450b57cec5SDimitry Andric {
2460b57cec5SDimitry Andric     return as_float_helper<double>( func, s, idx, strtod );
2470b57cec5SDimitry Andric }
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric template<>
2500b57cec5SDimitry Andric inline
2510b57cec5SDimitry Andric long double
2520b57cec5SDimitry Andric as_float( const string& func, const string& s, size_t* idx )
2530b57cec5SDimitry Andric {
2540b57cec5SDimitry Andric     return as_float_helper<long double>( func, s, idx, strtold );
2550b57cec5SDimitry Andric }
2560b57cec5SDimitry Andric 
257349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
2580b57cec5SDimitry Andric template<>
2590b57cec5SDimitry Andric inline
2600b57cec5SDimitry Andric float
2610b57cec5SDimitry Andric as_float( const string& func, const wstring& s, size_t* idx )
2620b57cec5SDimitry Andric {
2630b57cec5SDimitry Andric     return as_float_helper<float>( func, s, idx, wcstof );
2640b57cec5SDimitry Andric }
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric template<>
2670b57cec5SDimitry Andric inline
2680b57cec5SDimitry Andric double
2690b57cec5SDimitry Andric as_float( const string& func, const wstring& s, size_t* idx )
2700b57cec5SDimitry Andric {
2710b57cec5SDimitry Andric     return as_float_helper<double>( func, s, idx, wcstod );
2720b57cec5SDimitry Andric }
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric template<>
2750b57cec5SDimitry Andric inline
2760b57cec5SDimitry Andric long double
2770b57cec5SDimitry Andric as_float( const string& func, const wstring& s, size_t* idx )
2780b57cec5SDimitry Andric {
2790b57cec5SDimitry Andric     return as_float_helper<long double>( func, s, idx, wcstold );
2800b57cec5SDimitry Andric }
281349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric }  // unnamed namespace
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric int
2860b57cec5SDimitry Andric stoi(const string& str, size_t* idx, int base)
2870b57cec5SDimitry Andric {
2880b57cec5SDimitry Andric     return as_integer<int>( "stoi", str, idx, base );
2890b57cec5SDimitry Andric }
2900b57cec5SDimitry Andric 
291349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
2920b57cec5SDimitry Andric int
2930b57cec5SDimitry Andric stoi(const wstring& str, size_t* idx, int base)
2940b57cec5SDimitry Andric {
2950b57cec5SDimitry Andric     return as_integer<int>( "stoi", str, idx, base );
2960b57cec5SDimitry Andric }
297349cc55cSDimitry Andric #endif
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric long
3000b57cec5SDimitry Andric stol(const string& str, size_t* idx, int base)
3010b57cec5SDimitry Andric {
3020b57cec5SDimitry Andric     return as_integer<long>( "stol", str, idx, base );
3030b57cec5SDimitry Andric }
3040b57cec5SDimitry Andric 
305349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3060b57cec5SDimitry Andric long
3070b57cec5SDimitry Andric stol(const wstring& str, size_t* idx, int base)
3080b57cec5SDimitry Andric {
3090b57cec5SDimitry Andric     return as_integer<long>( "stol", str, idx, base );
3100b57cec5SDimitry Andric }
311349cc55cSDimitry Andric #endif
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric unsigned long
3140b57cec5SDimitry Andric stoul(const string& str, size_t* idx, int base)
3150b57cec5SDimitry Andric {
3160b57cec5SDimitry Andric     return as_integer<unsigned long>( "stoul", str, idx, base );
3170b57cec5SDimitry Andric }
3180b57cec5SDimitry Andric 
319349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3200b57cec5SDimitry Andric unsigned long
3210b57cec5SDimitry Andric stoul(const wstring& str, size_t* idx, int base)
3220b57cec5SDimitry Andric {
3230b57cec5SDimitry Andric     return as_integer<unsigned long>( "stoul", str, idx, base );
3240b57cec5SDimitry Andric }
325349cc55cSDimitry Andric #endif
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric long long
3280b57cec5SDimitry Andric stoll(const string& str, size_t* idx, int base)
3290b57cec5SDimitry Andric {
3300b57cec5SDimitry Andric     return as_integer<long long>( "stoll", str, idx, base );
3310b57cec5SDimitry Andric }
3320b57cec5SDimitry Andric 
333349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3340b57cec5SDimitry Andric long long
3350b57cec5SDimitry Andric stoll(const wstring& str, size_t* idx, int base)
3360b57cec5SDimitry Andric {
3370b57cec5SDimitry Andric     return as_integer<long long>( "stoll", str, idx, base );
3380b57cec5SDimitry Andric }
339349cc55cSDimitry Andric #endif
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric unsigned long long
3420b57cec5SDimitry Andric stoull(const string& str, size_t* idx, int base)
3430b57cec5SDimitry Andric {
3440b57cec5SDimitry Andric     return as_integer<unsigned long long>( "stoull", str, idx, base );
3450b57cec5SDimitry Andric }
3460b57cec5SDimitry Andric 
347349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3480b57cec5SDimitry Andric unsigned long long
3490b57cec5SDimitry Andric stoull(const wstring& str, size_t* idx, int base)
3500b57cec5SDimitry Andric {
3510b57cec5SDimitry Andric     return as_integer<unsigned long long>( "stoull", str, idx, base );
3520b57cec5SDimitry Andric }
353349cc55cSDimitry Andric #endif
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric float
3560b57cec5SDimitry Andric stof(const string& str, size_t* idx)
3570b57cec5SDimitry Andric {
3580b57cec5SDimitry Andric     return as_float<float>( "stof", str, idx );
3590b57cec5SDimitry Andric }
3600b57cec5SDimitry Andric 
361349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3620b57cec5SDimitry Andric float
3630b57cec5SDimitry Andric stof(const wstring& str, size_t* idx)
3640b57cec5SDimitry Andric {
3650b57cec5SDimitry Andric     return as_float<float>( "stof", str, idx );
3660b57cec5SDimitry Andric }
367349cc55cSDimitry Andric #endif
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric double
3700b57cec5SDimitry Andric stod(const string& str, size_t* idx)
3710b57cec5SDimitry Andric {
3720b57cec5SDimitry Andric     return as_float<double>( "stod", str, idx );
3730b57cec5SDimitry Andric }
3740b57cec5SDimitry Andric 
375349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3760b57cec5SDimitry Andric double
3770b57cec5SDimitry Andric stod(const wstring& str, size_t* idx)
3780b57cec5SDimitry Andric {
3790b57cec5SDimitry Andric     return as_float<double>( "stod", str, idx );
3800b57cec5SDimitry Andric }
381349cc55cSDimitry Andric #endif
3820b57cec5SDimitry Andric 
3830b57cec5SDimitry Andric long double
3840b57cec5SDimitry Andric stold(const string& str, size_t* idx)
3850b57cec5SDimitry Andric {
3860b57cec5SDimitry Andric     return as_float<long double>( "stold", str, idx );
3870b57cec5SDimitry Andric }
3880b57cec5SDimitry Andric 
389349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3900b57cec5SDimitry Andric long double
3910b57cec5SDimitry Andric stold(const wstring& str, size_t* idx)
3920b57cec5SDimitry Andric {
3930b57cec5SDimitry Andric     return as_float<long double>( "stold", str, idx );
3940b57cec5SDimitry Andric }
395349cc55cSDimitry Andric #endif
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric // to_string
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric namespace
4000b57cec5SDimitry Andric {
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric // as_string
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric template<typename S, typename P, typename V >
4050b57cec5SDimitry Andric inline
4060b57cec5SDimitry Andric S
4070b57cec5SDimitry Andric as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a)
4080b57cec5SDimitry Andric {
4090b57cec5SDimitry Andric     typedef typename S::size_type size_type;
4100b57cec5SDimitry Andric     size_type available = s.size();
4110b57cec5SDimitry Andric     while (true)
4120b57cec5SDimitry Andric     {
4130b57cec5SDimitry Andric         int status = sprintf_like(&s[0], available + 1, fmt, a);
4140b57cec5SDimitry Andric         if ( status >= 0 )
4150b57cec5SDimitry Andric         {
4160b57cec5SDimitry Andric             size_type used = static_cast<size_type>(status);
4170b57cec5SDimitry Andric             if ( used <= available )
4180b57cec5SDimitry Andric             {
4190b57cec5SDimitry Andric                 s.resize( used );
4200b57cec5SDimitry Andric                 break;
4210b57cec5SDimitry Andric             }
4220b57cec5SDimitry Andric             available = used; // Assume this is advice of how much space we need.
4230b57cec5SDimitry Andric         }
4240b57cec5SDimitry Andric         else
4250b57cec5SDimitry Andric             available = available * 2 + 1;
4260b57cec5SDimitry Andric         s.resize(available);
4270b57cec5SDimitry Andric     }
4280b57cec5SDimitry Andric     return s;
4290b57cec5SDimitry Andric }
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric template <class S>
4320b57cec5SDimitry Andric struct initial_string;
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric template <>
4350b57cec5SDimitry Andric struct initial_string<string>
4360b57cec5SDimitry Andric {
4370b57cec5SDimitry Andric     string
4380b57cec5SDimitry Andric     operator()() const
4390b57cec5SDimitry Andric     {
4400b57cec5SDimitry Andric         string s;
4410b57cec5SDimitry Andric         s.resize(s.capacity());
4420b57cec5SDimitry Andric         return s;
4430b57cec5SDimitry Andric     }
4440b57cec5SDimitry Andric };
4450b57cec5SDimitry Andric 
446349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4470b57cec5SDimitry Andric template <>
4480b57cec5SDimitry Andric struct initial_string<wstring>
4490b57cec5SDimitry Andric {
4500b57cec5SDimitry Andric     wstring
4510b57cec5SDimitry Andric     operator()() const
4520b57cec5SDimitry Andric     {
4530b57cec5SDimitry Andric         wstring s(20, wchar_t());
4540b57cec5SDimitry Andric         s.resize(s.capacity());
4550b57cec5SDimitry Andric         return s;
4560b57cec5SDimitry Andric     }
4570b57cec5SDimitry Andric };
4580b57cec5SDimitry Andric 
4590b57cec5SDimitry Andric typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...);
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric inline
4620b57cec5SDimitry Andric wide_printf
4630b57cec5SDimitry Andric get_swprintf()
4640b57cec5SDimitry Andric {
4650b57cec5SDimitry Andric #ifndef _LIBCPP_MSVCRT
4660b57cec5SDimitry Andric     return swprintf;
4670b57cec5SDimitry Andric #else
4680b57cec5SDimitry Andric     return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(_snwprintf);
4690b57cec5SDimitry Andric #endif
4700b57cec5SDimitry Andric }
471349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4720b57cec5SDimitry Andric 
4730b57cec5SDimitry Andric template <typename S, typename V>
474fe6060f1SDimitry Andric S i_to_string(V v)
4750b57cec5SDimitry Andric {
4760b57cec5SDimitry Andric //  numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers.
4770b57cec5SDimitry Andric //  For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented),
4780b57cec5SDimitry Andric //  so we need +1 here.
4790b57cec5SDimitry Andric     constexpr size_t bufsize = numeric_limits<V>::digits10 + 2;  // +1 for minus, +1 for digits10
4800b57cec5SDimitry Andric     char buf[bufsize];
4810b57cec5SDimitry Andric     const auto res = to_chars(buf, buf + bufsize, v);
4820b57cec5SDimitry Andric     _LIBCPP_ASSERT(res.ec == errc(), "bufsize must be large enough to accomodate the value");
4830b57cec5SDimitry Andric     return S(buf, res.ptr);
4840b57cec5SDimitry Andric }
4850b57cec5SDimitry Andric 
4860b57cec5SDimitry Andric }  // unnamed namespace
4870b57cec5SDimitry Andric 
4880b57cec5SDimitry Andric string  to_string (int val)                { return i_to_string< string>(val); }
4890b57cec5SDimitry Andric string  to_string (long val)               { return i_to_string< string>(val); }
4900b57cec5SDimitry Andric string  to_string (long long val)          { return i_to_string< string>(val); }
4910b57cec5SDimitry Andric string  to_string (unsigned val)           { return i_to_string< string>(val); }
4920b57cec5SDimitry Andric string  to_string (unsigned long val)      { return i_to_string< string>(val); }
4930b57cec5SDimitry Andric string  to_string (unsigned long long val) { return i_to_string< string>(val); }
4940b57cec5SDimitry Andric 
495349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4960b57cec5SDimitry Andric wstring to_wstring(int val)                { return i_to_string<wstring>(val); }
4970b57cec5SDimitry Andric wstring to_wstring(long val)               { return i_to_string<wstring>(val); }
4980b57cec5SDimitry Andric wstring to_wstring(long long val)          { return i_to_string<wstring>(val); }
4990b57cec5SDimitry Andric wstring to_wstring(unsigned val)           { return i_to_string<wstring>(val); }
5000b57cec5SDimitry Andric wstring to_wstring(unsigned long val)      { return i_to_string<wstring>(val); }
5010b57cec5SDimitry Andric wstring to_wstring(unsigned long long val) { return i_to_string<wstring>(val); }
502349cc55cSDimitry Andric #endif
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric string  to_string (float val)       { return as_string(snprintf,       initial_string< string>()(),   "%f", val); }
5050b57cec5SDimitry Andric string  to_string (double val)      { return as_string(snprintf,       initial_string< string>()(),   "%f", val); }
5060b57cec5SDimitry Andric string  to_string (long double val) { return as_string(snprintf,       initial_string< string>()(),  "%Lf", val); }
5070b57cec5SDimitry Andric 
508349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5090b57cec5SDimitry Andric wstring to_wstring(float val)       { return as_string(get_swprintf(), initial_string<wstring>()(),  L"%f", val); }
5100b57cec5SDimitry Andric wstring to_wstring(double val)      { return as_string(get_swprintf(), initial_string<wstring>()(),  L"%f", val); }
5110b57cec5SDimitry Andric wstring to_wstring(long double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%Lf", val); }
512349cc55cSDimitry Andric #endif
5130b57cec5SDimitry Andric 
5140b57cec5SDimitry Andric _LIBCPP_END_NAMESPACE_STD
515