1eb8650a7SLouis Dionne //===----------------------------------------------------------------------===// 2cbbf633eSHoward Hinnant // 357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6cbbf633eSHoward Hinnant // 7cbbf633eSHoward Hinnant //===----------------------------------------------------------------------===// 8cbbf633eSHoward Hinnant 9*bbb0f2c7SArthur O'Dwyer #include <__debug> 10*bbb0f2c7SArthur O'Dwyer #include <cerrno> 11*bbb0f2c7SArthur O'Dwyer #include <charconv> 12*bbb0f2c7SArthur O'Dwyer #include <cstdlib> 13*bbb0f2c7SArthur O'Dwyer #include <limits> 14*bbb0f2c7SArthur O'Dwyer #include <stdexcept> 151468d0ceSHoward Hinnant #include <stdio.h> 16*bbb0f2c7SArthur O'Dwyer #include <string> 17cbbf633eSHoward Hinnant 18f4c1258dSLouis Dionne #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 19*bbb0f2c7SArthur O'Dwyer # include <cwchar> 20f4c1258dSLouis Dionne #endif 21f4c1258dSLouis Dionne 22cbbf633eSHoward Hinnant _LIBCPP_BEGIN_NAMESPACE_STD 23cbbf633eSHoward Hinnant 245173f43cSNikolas Klauser #ifndef _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON 255173f43cSNikolas Klauser 265173f43cSNikolas Klauser template <bool> 275173f43cSNikolas Klauser struct __basic_string_common; 285173f43cSNikolas Klauser 295173f43cSNikolas Klauser // The struct isn't declared anymore in the headers. It's only here for ABI compatibility. 305173f43cSNikolas Klauser template <> 315173f43cSNikolas Klauser struct __basic_string_common<true> { 325173f43cSNikolas Klauser _LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __throw_length_error() const; 335173f43cSNikolas Klauser _LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __throw_out_of_range() const; 345173f43cSNikolas Klauser }; 355173f43cSNikolas Klauser 3684b0b52bSLouis Dionne void __basic_string_common<true>::__throw_length_error() const { 375173f43cSNikolas Klauser std::__throw_length_error("basic_string"); 385173f43cSNikolas Klauser } 395173f43cSNikolas Klauser void __basic_string_common<true>::__throw_out_of_range() const { 405173f43cSNikolas Klauser std::__throw_out_of_range("basic_string"); 4184b0b52bSLouis Dionne } 4284b0b52bSLouis Dionne 435173f43cSNikolas Klauser #endif // _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON 44cbbf633eSHoward Hinnant 45b648c611SLouis Dionne #define _LIBCPP_EXTERN_TEMPLATE_DEFINE(...) template __VA_ARGS__; 4667532646SMartijn Vels #ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION 47d8969a1cSMartijn Vels _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) 48f4c1258dSLouis Dionne # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 49d8969a1cSMartijn Vels _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) 50f4c1258dSLouis Dionne # endif 51d8969a1cSMartijn Vels #else 52d8969a1cSMartijn Vels _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) 53f4c1258dSLouis Dionne # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 54d8969a1cSMartijn Vels _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) 55d8969a1cSMartijn Vels # endif 56f4c1258dSLouis Dionne #endif 57b648c611SLouis Dionne #undef _LIBCPP_EXTERN_TEMPLATE_DEFINE 58cbbf633eSHoward Hinnant 59b648c611SLouis Dionne template string operator+<char, char_traits<char>, allocator<char> >(char const*, string const&); 60cbbf633eSHoward Hinnant 619daaf577SHoward Hinnant namespace 629daaf577SHoward Hinnant { 639daaf577SHoward Hinnant 649daaf577SHoward Hinnant template<typename T> 659daaf577SHoward Hinnant inline 669daaf577SHoward Hinnant void throw_helper( const string& msg ) 679daaf577SHoward Hinnant { 689daaf577SHoward Hinnant #ifndef _LIBCPP_NO_EXCEPTIONS 699daaf577SHoward Hinnant throw T( msg ); 709daaf577SHoward Hinnant #else 71c19393c7SEd Schouten fprintf(stderr, "%s\n", msg.c_str()); 72d437fa5cSMarshall Clow _VSTD::abort(); 739daaf577SHoward Hinnant #endif 749daaf577SHoward Hinnant } 759daaf577SHoward Hinnant 769daaf577SHoward Hinnant inline 779daaf577SHoward Hinnant void throw_from_string_out_of_range( const string& func ) 789daaf577SHoward Hinnant { 799daaf577SHoward Hinnant throw_helper<out_of_range>(func + ": out of range"); 809daaf577SHoward Hinnant } 819daaf577SHoward Hinnant 829daaf577SHoward Hinnant inline 839daaf577SHoward Hinnant void throw_from_string_invalid_arg( const string& func ) 849daaf577SHoward Hinnant { 859daaf577SHoward Hinnant throw_helper<invalid_argument>(func + ": no conversion"); 869daaf577SHoward Hinnant } 879daaf577SHoward Hinnant 889daaf577SHoward Hinnant // as_integer 899daaf577SHoward Hinnant 909daaf577SHoward Hinnant template<typename V, typename S, typename F> 919daaf577SHoward Hinnant inline 929daaf577SHoward Hinnant V 939daaf577SHoward Hinnant as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f) 949daaf577SHoward Hinnant { 95d6bd7bf6SEric Fiselier typename S::value_type* ptr = nullptr; 969daaf577SHoward Hinnant const typename S::value_type* const p = str.c_str(); 979daaf577SHoward Hinnant typename remove_reference<decltype(errno)>::type errno_save = errno; 989daaf577SHoward Hinnant errno = 0; 999daaf577SHoward Hinnant V r = f(p, &ptr, base); 1009daaf577SHoward Hinnant swap(errno, errno_save); 1019daaf577SHoward Hinnant if (errno_save == ERANGE) 1029daaf577SHoward Hinnant throw_from_string_out_of_range(func); 1039daaf577SHoward Hinnant if (ptr == p) 1049daaf577SHoward Hinnant throw_from_string_invalid_arg(func); 1059daaf577SHoward Hinnant if (idx) 1069daaf577SHoward Hinnant *idx = static_cast<size_t>(ptr - p); 1079daaf577SHoward Hinnant return r; 1089daaf577SHoward Hinnant } 1099daaf577SHoward Hinnant 1109daaf577SHoward Hinnant template<typename V, typename S> 1119daaf577SHoward Hinnant inline 1129daaf577SHoward Hinnant V 1139daaf577SHoward Hinnant as_integer(const string& func, const S& s, size_t* idx, int base); 1149daaf577SHoward Hinnant 1159daaf577SHoward Hinnant // string 1169daaf577SHoward Hinnant template<> 1179daaf577SHoward Hinnant inline 1189daaf577SHoward Hinnant int 1199daaf577SHoward Hinnant as_integer(const string& func, const string& s, size_t* idx, int base ) 1209daaf577SHoward Hinnant { 1218092c957SJoerg Sonnenberger // Use long as no Standard string to integer exists. 1229daaf577SHoward Hinnant long r = as_integer_helper<long>( func, s, idx, base, strtol ); 1239daaf577SHoward Hinnant if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) 1249daaf577SHoward Hinnant throw_from_string_out_of_range(func); 1259daaf577SHoward Hinnant return static_cast<int>(r); 1269daaf577SHoward Hinnant } 1279daaf577SHoward Hinnant 1289daaf577SHoward Hinnant template<> 1299daaf577SHoward Hinnant inline 1309daaf577SHoward Hinnant long 1319daaf577SHoward Hinnant as_integer(const string& func, const string& s, size_t* idx, int base ) 1329daaf577SHoward Hinnant { 1339daaf577SHoward Hinnant return as_integer_helper<long>( func, s, idx, base, strtol ); 1349daaf577SHoward Hinnant } 1359daaf577SHoward Hinnant 1369daaf577SHoward Hinnant template<> 1379daaf577SHoward Hinnant inline 1389daaf577SHoward Hinnant unsigned long 1399daaf577SHoward Hinnant as_integer( const string& func, const string& s, size_t* idx, int base ) 1409daaf577SHoward Hinnant { 1419daaf577SHoward Hinnant return as_integer_helper<unsigned long>( func, s, idx, base, strtoul ); 1429daaf577SHoward Hinnant } 1439daaf577SHoward Hinnant 1449daaf577SHoward Hinnant template<> 1459daaf577SHoward Hinnant inline 1469daaf577SHoward Hinnant long long 1479daaf577SHoward Hinnant as_integer( const string& func, const string& s, size_t* idx, int base ) 1489daaf577SHoward Hinnant { 1499daaf577SHoward Hinnant return as_integer_helper<long long>( func, s, idx, base, strtoll ); 1509daaf577SHoward Hinnant } 1519daaf577SHoward Hinnant 1529daaf577SHoward Hinnant template<> 1539daaf577SHoward Hinnant inline 1549daaf577SHoward Hinnant unsigned long long 1559daaf577SHoward Hinnant as_integer( const string& func, const string& s, size_t* idx, int base ) 1569daaf577SHoward Hinnant { 1579daaf577SHoward Hinnant return as_integer_helper<unsigned long long>( func, s, idx, base, strtoull ); 1589daaf577SHoward Hinnant } 1599daaf577SHoward Hinnant 160f4c1258dSLouis Dionne #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 1619daaf577SHoward Hinnant // wstring 1629daaf577SHoward Hinnant template<> 1639daaf577SHoward Hinnant inline 1649daaf577SHoward Hinnant int 1659daaf577SHoward Hinnant as_integer( const string& func, const wstring& s, size_t* idx, int base ) 1669daaf577SHoward Hinnant { 1679daaf577SHoward Hinnant // Use long as no Stantard string to integer exists. 1689daaf577SHoward Hinnant long r = as_integer_helper<long>( func, s, idx, base, wcstol ); 1699daaf577SHoward Hinnant if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) 1709daaf577SHoward Hinnant throw_from_string_out_of_range(func); 1719daaf577SHoward Hinnant return static_cast<int>(r); 1729daaf577SHoward Hinnant } 1739daaf577SHoward Hinnant 1749daaf577SHoward Hinnant template<> 1759daaf577SHoward Hinnant inline 1769daaf577SHoward Hinnant long 1779daaf577SHoward Hinnant as_integer( const string& func, const wstring& s, size_t* idx, int base ) 1789daaf577SHoward Hinnant { 1799daaf577SHoward Hinnant return as_integer_helper<long>( func, s, idx, base, wcstol ); 1809daaf577SHoward Hinnant } 1819daaf577SHoward Hinnant 1829daaf577SHoward Hinnant template<> 1839daaf577SHoward Hinnant inline 1849daaf577SHoward Hinnant unsigned long 1859daaf577SHoward Hinnant as_integer( const string& func, const wstring& s, size_t* idx, int base ) 1869daaf577SHoward Hinnant { 1879daaf577SHoward Hinnant return as_integer_helper<unsigned long>( func, s, idx, base, wcstoul ); 1889daaf577SHoward Hinnant } 1899daaf577SHoward Hinnant 1909daaf577SHoward Hinnant template<> 1919daaf577SHoward Hinnant inline 1929daaf577SHoward Hinnant long long 1939daaf577SHoward Hinnant as_integer( const string& func, const wstring& s, size_t* idx, int base ) 1949daaf577SHoward Hinnant { 1959daaf577SHoward Hinnant return as_integer_helper<long long>( func, s, idx, base, wcstoll ); 1969daaf577SHoward Hinnant } 1979daaf577SHoward Hinnant 1989daaf577SHoward Hinnant template<> 1999daaf577SHoward Hinnant inline 2009daaf577SHoward Hinnant unsigned long long 2019daaf577SHoward Hinnant as_integer( const string& func, const wstring& s, size_t* idx, int base ) 2029daaf577SHoward Hinnant { 2039daaf577SHoward Hinnant return as_integer_helper<unsigned long long>( func, s, idx, base, wcstoull ); 2049daaf577SHoward Hinnant } 205f4c1258dSLouis Dionne #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 2069daaf577SHoward Hinnant 2079daaf577SHoward Hinnant // as_float 2089daaf577SHoward Hinnant 2099daaf577SHoward Hinnant template<typename V, typename S, typename F> 2109daaf577SHoward Hinnant inline 2119daaf577SHoward Hinnant V 2129daaf577SHoward Hinnant as_float_helper(const string& func, const S& str, size_t* idx, F f ) 2139daaf577SHoward Hinnant { 214d6bd7bf6SEric Fiselier typename S::value_type* ptr = nullptr; 2159daaf577SHoward Hinnant const typename S::value_type* const p = str.c_str(); 2169daaf577SHoward Hinnant typename remove_reference<decltype(errno)>::type errno_save = errno; 2179daaf577SHoward Hinnant errno = 0; 2189daaf577SHoward Hinnant V r = f(p, &ptr); 2199daaf577SHoward Hinnant swap(errno, errno_save); 2209daaf577SHoward Hinnant if (errno_save == ERANGE) 2219daaf577SHoward Hinnant throw_from_string_out_of_range(func); 2229daaf577SHoward Hinnant if (ptr == p) 2239daaf577SHoward Hinnant throw_from_string_invalid_arg(func); 2249daaf577SHoward Hinnant if (idx) 2259daaf577SHoward Hinnant *idx = static_cast<size_t>(ptr - p); 2269daaf577SHoward Hinnant return r; 2279daaf577SHoward Hinnant } 2289daaf577SHoward Hinnant 2299daaf577SHoward Hinnant template<typename V, typename S> 2309daaf577SHoward Hinnant inline 2319daaf577SHoward Hinnant V as_float( const string& func, const S& s, size_t* idx = nullptr ); 2329daaf577SHoward Hinnant 2339daaf577SHoward Hinnant template<> 2349daaf577SHoward Hinnant inline 2359daaf577SHoward Hinnant float 2369daaf577SHoward Hinnant as_float( const string& func, const string& s, size_t* idx ) 2379daaf577SHoward Hinnant { 2389daaf577SHoward Hinnant return as_float_helper<float>( func, s, idx, strtof ); 2399daaf577SHoward Hinnant } 2409daaf577SHoward Hinnant 2419daaf577SHoward Hinnant template<> 2429daaf577SHoward Hinnant inline 2439daaf577SHoward Hinnant double 2449daaf577SHoward Hinnant as_float(const string& func, const string& s, size_t* idx ) 2459daaf577SHoward Hinnant { 2469daaf577SHoward Hinnant return as_float_helper<double>( func, s, idx, strtod ); 2479daaf577SHoward Hinnant } 2489daaf577SHoward Hinnant 2499daaf577SHoward Hinnant template<> 2509daaf577SHoward Hinnant inline 2519daaf577SHoward Hinnant long double 2529daaf577SHoward Hinnant as_float( const string& func, const string& s, size_t* idx ) 2539daaf577SHoward Hinnant { 2549daaf577SHoward Hinnant return as_float_helper<long double>( func, s, idx, strtold ); 2559daaf577SHoward Hinnant } 2569daaf577SHoward Hinnant 257f4c1258dSLouis Dionne #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 2589daaf577SHoward Hinnant template<> 2599daaf577SHoward Hinnant inline 2609daaf577SHoward Hinnant float 2619daaf577SHoward Hinnant as_float( const string& func, const wstring& s, size_t* idx ) 2629daaf577SHoward Hinnant { 2639daaf577SHoward Hinnant return as_float_helper<float>( func, s, idx, wcstof ); 2649daaf577SHoward Hinnant } 2659daaf577SHoward Hinnant 2669daaf577SHoward Hinnant template<> 2679daaf577SHoward Hinnant inline 2689daaf577SHoward Hinnant double 2699daaf577SHoward Hinnant as_float( const string& func, const wstring& s, size_t* idx ) 2709daaf577SHoward Hinnant { 2719daaf577SHoward Hinnant return as_float_helper<double>( func, s, idx, wcstod ); 2729daaf577SHoward Hinnant } 2739daaf577SHoward Hinnant 2749daaf577SHoward Hinnant template<> 2759daaf577SHoward Hinnant inline 2769daaf577SHoward Hinnant long double 2779daaf577SHoward Hinnant as_float( const string& func, const wstring& s, size_t* idx ) 2789daaf577SHoward Hinnant { 2799daaf577SHoward Hinnant return as_float_helper<long double>( func, s, idx, wcstold ); 2809daaf577SHoward Hinnant } 281f4c1258dSLouis Dionne #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 2829daaf577SHoward Hinnant 2839daaf577SHoward Hinnant } // unnamed namespace 2849daaf577SHoward Hinnant 285cbbf633eSHoward Hinnant int 286cbbf633eSHoward Hinnant stoi(const string& str, size_t* idx, int base) 287cbbf633eSHoward Hinnant { 2889daaf577SHoward Hinnant return as_integer<int>( "stoi", str, idx, base ); 289cbbf633eSHoward Hinnant } 290cbbf633eSHoward Hinnant 291f4c1258dSLouis Dionne #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 292cbbf633eSHoward Hinnant int 293cbbf633eSHoward Hinnant stoi(const wstring& str, size_t* idx, int base) 294cbbf633eSHoward Hinnant { 2959daaf577SHoward Hinnant return as_integer<int>( "stoi", str, idx, base ); 296cbbf633eSHoward Hinnant } 297f4c1258dSLouis Dionne #endif 298cbbf633eSHoward Hinnant 299cbbf633eSHoward Hinnant long 300cbbf633eSHoward Hinnant stol(const string& str, size_t* idx, int base) 301cbbf633eSHoward Hinnant { 3029daaf577SHoward Hinnant return as_integer<long>( "stol", str, idx, base ); 303cbbf633eSHoward Hinnant } 304cbbf633eSHoward Hinnant 305f4c1258dSLouis Dionne #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 306cbbf633eSHoward Hinnant long 307cbbf633eSHoward Hinnant stol(const wstring& str, size_t* idx, int base) 308cbbf633eSHoward Hinnant { 3099daaf577SHoward Hinnant return as_integer<long>( "stol", str, idx, base ); 310cbbf633eSHoward Hinnant } 311f4c1258dSLouis Dionne #endif 312cbbf633eSHoward Hinnant 313cbbf633eSHoward Hinnant unsigned long 314cbbf633eSHoward Hinnant stoul(const string& str, size_t* idx, int base) 315cbbf633eSHoward Hinnant { 3169daaf577SHoward Hinnant return as_integer<unsigned long>( "stoul", str, idx, base ); 317cbbf633eSHoward Hinnant } 318cbbf633eSHoward Hinnant 319f4c1258dSLouis Dionne #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 320cbbf633eSHoward Hinnant unsigned long 321cbbf633eSHoward Hinnant stoul(const wstring& str, size_t* idx, int base) 322cbbf633eSHoward Hinnant { 3239daaf577SHoward Hinnant return as_integer<unsigned long>( "stoul", str, idx, base ); 324cbbf633eSHoward Hinnant } 325f4c1258dSLouis Dionne #endif 326cbbf633eSHoward Hinnant 327cbbf633eSHoward Hinnant long long 328cbbf633eSHoward Hinnant stoll(const string& str, size_t* idx, int base) 329cbbf633eSHoward Hinnant { 3309daaf577SHoward Hinnant return as_integer<long long>( "stoll", str, idx, base ); 331cbbf633eSHoward Hinnant } 332cbbf633eSHoward Hinnant 333f4c1258dSLouis Dionne #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 334cbbf633eSHoward Hinnant long long 335cbbf633eSHoward Hinnant stoll(const wstring& str, size_t* idx, int base) 336cbbf633eSHoward Hinnant { 3379daaf577SHoward Hinnant return as_integer<long long>( "stoll", str, idx, base ); 338cbbf633eSHoward Hinnant } 339f4c1258dSLouis Dionne #endif 340cbbf633eSHoward Hinnant 341cbbf633eSHoward Hinnant unsigned long long 342cbbf633eSHoward Hinnant stoull(const string& str, size_t* idx, int base) 343cbbf633eSHoward Hinnant { 3449daaf577SHoward Hinnant return as_integer<unsigned long long>( "stoull", str, idx, base ); 345cbbf633eSHoward Hinnant } 346cbbf633eSHoward Hinnant 347f4c1258dSLouis Dionne #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 348cbbf633eSHoward Hinnant unsigned long long 349cbbf633eSHoward Hinnant stoull(const wstring& str, size_t* idx, int base) 350cbbf633eSHoward Hinnant { 3519daaf577SHoward Hinnant return as_integer<unsigned long long>( "stoull", str, idx, base ); 352cbbf633eSHoward Hinnant } 353f4c1258dSLouis Dionne #endif 354cbbf633eSHoward Hinnant 355cbbf633eSHoward Hinnant float 356cbbf633eSHoward Hinnant stof(const string& str, size_t* idx) 357cbbf633eSHoward Hinnant { 3589daaf577SHoward Hinnant return as_float<float>( "stof", str, idx ); 359cbbf633eSHoward Hinnant } 360cbbf633eSHoward Hinnant 361f4c1258dSLouis Dionne #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 362cbbf633eSHoward Hinnant float 363cbbf633eSHoward Hinnant stof(const wstring& str, size_t* idx) 364cbbf633eSHoward Hinnant { 3659daaf577SHoward Hinnant return as_float<float>( "stof", str, idx ); 366cbbf633eSHoward Hinnant } 367f4c1258dSLouis Dionne #endif 368cbbf633eSHoward Hinnant 369cbbf633eSHoward Hinnant double 370cbbf633eSHoward Hinnant stod(const string& str, size_t* idx) 371cbbf633eSHoward Hinnant { 3729daaf577SHoward Hinnant return as_float<double>( "stod", str, idx ); 373cbbf633eSHoward Hinnant } 374cbbf633eSHoward Hinnant 375f4c1258dSLouis Dionne #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 376cbbf633eSHoward Hinnant double 377cbbf633eSHoward Hinnant stod(const wstring& str, size_t* idx) 378cbbf633eSHoward Hinnant { 3799daaf577SHoward Hinnant return as_float<double>( "stod", str, idx ); 380cbbf633eSHoward Hinnant } 381f4c1258dSLouis Dionne #endif 382cbbf633eSHoward Hinnant 383cbbf633eSHoward Hinnant long double 384cbbf633eSHoward Hinnant stold(const string& str, size_t* idx) 385cbbf633eSHoward Hinnant { 3869daaf577SHoward Hinnant return as_float<long double>( "stold", str, idx ); 387cbbf633eSHoward Hinnant } 388cbbf633eSHoward Hinnant 389f4c1258dSLouis Dionne #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 390cbbf633eSHoward Hinnant long double 391cbbf633eSHoward Hinnant stold(const wstring& str, size_t* idx) 392cbbf633eSHoward Hinnant { 3939daaf577SHoward Hinnant return as_float<long double>( "stold", str, idx ); 394cbbf633eSHoward Hinnant } 395f4c1258dSLouis Dionne #endif 396cbbf633eSHoward Hinnant 3979daaf577SHoward Hinnant // to_string 3989daaf577SHoward Hinnant 3999daaf577SHoward Hinnant namespace 4009daaf577SHoward Hinnant { 4019daaf577SHoward Hinnant 4029daaf577SHoward Hinnant // as_string 4039daaf577SHoward Hinnant 4049daaf577SHoward Hinnant template<typename S, typename P, typename V > 4059daaf577SHoward Hinnant inline 4069daaf577SHoward Hinnant S 4079daaf577SHoward Hinnant as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a) 4089daaf577SHoward Hinnant { 4099daaf577SHoward Hinnant typedef typename S::size_type size_type; 4109daaf577SHoward Hinnant size_type available = s.size(); 4119daaf577SHoward Hinnant while (true) 4129daaf577SHoward Hinnant { 4139daaf577SHoward Hinnant int status = sprintf_like(&s[0], available + 1, fmt, a); 4149daaf577SHoward Hinnant if ( status >= 0 ) 4159daaf577SHoward Hinnant { 4169daaf577SHoward Hinnant size_type used = static_cast<size_type>(status); 4179daaf577SHoward Hinnant if ( used <= available ) 4189daaf577SHoward Hinnant { 4199daaf577SHoward Hinnant s.resize( used ); 4209daaf577SHoward Hinnant break; 4219daaf577SHoward Hinnant } 4229daaf577SHoward Hinnant available = used; // Assume this is advice of how much space we need. 4239daaf577SHoward Hinnant } 4249daaf577SHoward Hinnant else 4259daaf577SHoward Hinnant available = available * 2 + 1; 4269daaf577SHoward Hinnant s.resize(available); 4279daaf577SHoward Hinnant } 4289daaf577SHoward Hinnant return s; 4299daaf577SHoward Hinnant } 4309daaf577SHoward Hinnant 431141c2b76SMarshall Clow template <class S> 4329daaf577SHoward Hinnant struct initial_string; 4339daaf577SHoward Hinnant 434141c2b76SMarshall Clow template <> 435141c2b76SMarshall Clow struct initial_string<string> 4369daaf577SHoward Hinnant { 4379daaf577SHoward Hinnant string 4389daaf577SHoward Hinnant operator()() const 439cbbf633eSHoward Hinnant { 440cbbf633eSHoward Hinnant string s; 441cbbf633eSHoward Hinnant s.resize(s.capacity()); 442cbbf633eSHoward Hinnant return s; 443cbbf633eSHoward Hinnant } 4449daaf577SHoward Hinnant }; 445cbbf633eSHoward Hinnant 446f4c1258dSLouis Dionne #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 447141c2b76SMarshall Clow template <> 448141c2b76SMarshall Clow struct initial_string<wstring> 4499daaf577SHoward Hinnant { 4509daaf577SHoward Hinnant wstring 4519daaf577SHoward Hinnant operator()() const 4529daaf577SHoward Hinnant { 4539daaf577SHoward Hinnant wstring s(20, wchar_t()); 4549daaf577SHoward Hinnant s.resize(s.capacity()); 4559daaf577SHoward Hinnant return s; 4569daaf577SHoward Hinnant } 4579daaf577SHoward Hinnant }; 4589daaf577SHoward Hinnant 4599daaf577SHoward Hinnant typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...); 4609daaf577SHoward Hinnant 4619daaf577SHoward Hinnant inline 4629daaf577SHoward Hinnant wide_printf 4639daaf577SHoward Hinnant get_swprintf() 4649daaf577SHoward Hinnant { 4650be8f64cSHoward Hinnant #ifndef _LIBCPP_MSVCRT 4669daaf577SHoward Hinnant return swprintf; 4679daaf577SHoward Hinnant #else 4685d50aa32SEric Fiselier return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(_snwprintf); 4699daaf577SHoward Hinnant #endif 4709daaf577SHoward Hinnant } 471f4c1258dSLouis Dionne #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 4729daaf577SHoward Hinnant 473141c2b76SMarshall Clow template <typename S, typename V> 474a562853aSLouis Dionne S i_to_string(V v) 475141c2b76SMarshall Clow { 476141c2b76SMarshall Clow // numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers. 477141c2b76SMarshall Clow // For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented), 478141c2b76SMarshall Clow // so we need +1 here. 479141c2b76SMarshall Clow constexpr size_t bufsize = numeric_limits<V>::digits10 + 2; // +1 for minus, +1 for digits10 480141c2b76SMarshall Clow char buf[bufsize]; 481141c2b76SMarshall Clow const auto res = to_chars(buf, buf + bufsize, v); 482141c2b76SMarshall Clow _LIBCPP_ASSERT(res.ec == errc(), "bufsize must be large enough to accomodate the value"); 483141c2b76SMarshall Clow return S(buf, res.ptr); 484141c2b76SMarshall Clow } 485141c2b76SMarshall Clow 4869daaf577SHoward Hinnant } // unnamed namespace 4879daaf577SHoward Hinnant 488141c2b76SMarshall Clow string to_string (int val) { return i_to_string< string>(val); } 489141c2b76SMarshall Clow string to_string (long val) { return i_to_string< string>(val); } 490141c2b76SMarshall Clow string to_string (long long val) { return i_to_string< string>(val); } 491141c2b76SMarshall Clow string to_string (unsigned val) { return i_to_string< string>(val); } 492141c2b76SMarshall Clow string to_string (unsigned long val) { return i_to_string< string>(val); } 493141c2b76SMarshall Clow string to_string (unsigned long long val) { return i_to_string< string>(val); } 4949daaf577SHoward Hinnant 495f4c1258dSLouis Dionne #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 496141c2b76SMarshall Clow wstring to_wstring(int val) { return i_to_string<wstring>(val); } 497141c2b76SMarshall Clow wstring to_wstring(long val) { return i_to_string<wstring>(val); } 498141c2b76SMarshall Clow wstring to_wstring(long long val) { return i_to_string<wstring>(val); } 499141c2b76SMarshall Clow wstring to_wstring(unsigned val) { return i_to_string<wstring>(val); } 500141c2b76SMarshall Clow wstring to_wstring(unsigned long val) { return i_to_string<wstring>(val); } 501141c2b76SMarshall Clow wstring to_wstring(unsigned long long val) { return i_to_string<wstring>(val); } 502f4c1258dSLouis Dionne #endif 5039daaf577SHoward Hinnant 504141c2b76SMarshall Clow string to_string (float val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } 505141c2b76SMarshall Clow string to_string (double val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } 506141c2b76SMarshall Clow string to_string (long double val) { return as_string(snprintf, initial_string< string>()(), "%Lf", val); } 5079daaf577SHoward Hinnant 508f4c1258dSLouis Dionne #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 509141c2b76SMarshall Clow wstring to_wstring(float val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } 510141c2b76SMarshall Clow wstring to_wstring(double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } 511141c2b76SMarshall Clow wstring to_wstring(long double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%Lf", val); } 512f4c1258dSLouis Dionne #endif 5139daaf577SHoward Hinnant 514cbbf633eSHoward Hinnant _LIBCPP_END_NAMESPACE_STD 515