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