1*0b57cec5SDimitry Andric //===------------------------- string.cpp ---------------------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "string" 10*0b57cec5SDimitry Andric #include "charconv" 11*0b57cec5SDimitry Andric #include "cstdlib" 12*0b57cec5SDimitry Andric #include "cwchar" 13*0b57cec5SDimitry Andric #include "cerrno" 14*0b57cec5SDimitry Andric #include "limits" 15*0b57cec5SDimitry Andric #include "stdexcept" 16*0b57cec5SDimitry Andric #include <stdio.h> 17*0b57cec5SDimitry Andric #include "__debug" 18*0b57cec5SDimitry Andric 19*0b57cec5SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 20*0b57cec5SDimitry Andric 21*0b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common<true>; 22*0b57cec5SDimitry Andric 23*0b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<char>; 24*0b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<wchar_t>; 25*0b57cec5SDimitry Andric 26*0b57cec5SDimitry Andric template 27*0b57cec5SDimitry Andric string 28*0b57cec5SDimitry Andric operator+<char, char_traits<char>, allocator<char> >(char const*, string const&); 29*0b57cec5SDimitry Andric 30*0b57cec5SDimitry Andric namespace 31*0b57cec5SDimitry Andric { 32*0b57cec5SDimitry Andric 33*0b57cec5SDimitry Andric template<typename T> 34*0b57cec5SDimitry Andric inline 35*0b57cec5SDimitry Andric void throw_helper( const string& msg ) 36*0b57cec5SDimitry Andric { 37*0b57cec5SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS 38*0b57cec5SDimitry Andric throw T( msg ); 39*0b57cec5SDimitry Andric #else 40*0b57cec5SDimitry Andric fprintf(stderr, "%s\n", msg.c_str()); 41*0b57cec5SDimitry Andric _VSTD::abort(); 42*0b57cec5SDimitry Andric #endif 43*0b57cec5SDimitry Andric } 44*0b57cec5SDimitry Andric 45*0b57cec5SDimitry Andric inline 46*0b57cec5SDimitry Andric void throw_from_string_out_of_range( const string& func ) 47*0b57cec5SDimitry Andric { 48*0b57cec5SDimitry Andric throw_helper<out_of_range>(func + ": out of range"); 49*0b57cec5SDimitry Andric } 50*0b57cec5SDimitry Andric 51*0b57cec5SDimitry Andric inline 52*0b57cec5SDimitry Andric void throw_from_string_invalid_arg( const string& func ) 53*0b57cec5SDimitry Andric { 54*0b57cec5SDimitry Andric throw_helper<invalid_argument>(func + ": no conversion"); 55*0b57cec5SDimitry Andric } 56*0b57cec5SDimitry Andric 57*0b57cec5SDimitry Andric // as_integer 58*0b57cec5SDimitry Andric 59*0b57cec5SDimitry Andric template<typename V, typename S, typename F> 60*0b57cec5SDimitry Andric inline 61*0b57cec5SDimitry Andric V 62*0b57cec5SDimitry Andric as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f) 63*0b57cec5SDimitry Andric { 64*0b57cec5SDimitry Andric typename S::value_type* ptr = nullptr; 65*0b57cec5SDimitry Andric const typename S::value_type* const p = str.c_str(); 66*0b57cec5SDimitry Andric typename remove_reference<decltype(errno)>::type errno_save = errno; 67*0b57cec5SDimitry Andric errno = 0; 68*0b57cec5SDimitry Andric V r = f(p, &ptr, base); 69*0b57cec5SDimitry Andric swap(errno, errno_save); 70*0b57cec5SDimitry Andric if (errno_save == ERANGE) 71*0b57cec5SDimitry Andric throw_from_string_out_of_range(func); 72*0b57cec5SDimitry Andric if (ptr == p) 73*0b57cec5SDimitry Andric throw_from_string_invalid_arg(func); 74*0b57cec5SDimitry Andric if (idx) 75*0b57cec5SDimitry Andric *idx = static_cast<size_t>(ptr - p); 76*0b57cec5SDimitry Andric return r; 77*0b57cec5SDimitry Andric } 78*0b57cec5SDimitry Andric 79*0b57cec5SDimitry Andric template<typename V, typename S> 80*0b57cec5SDimitry Andric inline 81*0b57cec5SDimitry Andric V 82*0b57cec5SDimitry Andric as_integer(const string& func, const S& s, size_t* idx, int base); 83*0b57cec5SDimitry Andric 84*0b57cec5SDimitry Andric // string 85*0b57cec5SDimitry Andric template<> 86*0b57cec5SDimitry Andric inline 87*0b57cec5SDimitry Andric int 88*0b57cec5SDimitry Andric as_integer(const string& func, const string& s, size_t* idx, int base ) 89*0b57cec5SDimitry Andric { 90*0b57cec5SDimitry Andric // Use long as no Standard string to integer exists. 91*0b57cec5SDimitry Andric long r = as_integer_helper<long>( func, s, idx, base, strtol ); 92*0b57cec5SDimitry Andric if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) 93*0b57cec5SDimitry Andric throw_from_string_out_of_range(func); 94*0b57cec5SDimitry Andric return static_cast<int>(r); 95*0b57cec5SDimitry Andric } 96*0b57cec5SDimitry Andric 97*0b57cec5SDimitry Andric template<> 98*0b57cec5SDimitry Andric inline 99*0b57cec5SDimitry Andric long 100*0b57cec5SDimitry Andric as_integer(const string& func, const string& s, size_t* idx, int base ) 101*0b57cec5SDimitry Andric { 102*0b57cec5SDimitry Andric return as_integer_helper<long>( func, s, idx, base, strtol ); 103*0b57cec5SDimitry Andric } 104*0b57cec5SDimitry Andric 105*0b57cec5SDimitry Andric template<> 106*0b57cec5SDimitry Andric inline 107*0b57cec5SDimitry Andric unsigned long 108*0b57cec5SDimitry Andric as_integer( const string& func, const string& s, size_t* idx, int base ) 109*0b57cec5SDimitry Andric { 110*0b57cec5SDimitry Andric return as_integer_helper<unsigned long>( func, s, idx, base, strtoul ); 111*0b57cec5SDimitry Andric } 112*0b57cec5SDimitry Andric 113*0b57cec5SDimitry Andric template<> 114*0b57cec5SDimitry Andric inline 115*0b57cec5SDimitry Andric long long 116*0b57cec5SDimitry Andric as_integer( const string& func, const string& s, size_t* idx, int base ) 117*0b57cec5SDimitry Andric { 118*0b57cec5SDimitry Andric return as_integer_helper<long long>( func, s, idx, base, strtoll ); 119*0b57cec5SDimitry Andric } 120*0b57cec5SDimitry Andric 121*0b57cec5SDimitry Andric template<> 122*0b57cec5SDimitry Andric inline 123*0b57cec5SDimitry Andric unsigned long long 124*0b57cec5SDimitry Andric as_integer( const string& func, const string& s, size_t* idx, int base ) 125*0b57cec5SDimitry Andric { 126*0b57cec5SDimitry Andric return as_integer_helper<unsigned long long>( func, s, idx, base, strtoull ); 127*0b57cec5SDimitry Andric } 128*0b57cec5SDimitry Andric 129*0b57cec5SDimitry Andric // wstring 130*0b57cec5SDimitry Andric template<> 131*0b57cec5SDimitry Andric inline 132*0b57cec5SDimitry Andric int 133*0b57cec5SDimitry Andric as_integer( const string& func, const wstring& s, size_t* idx, int base ) 134*0b57cec5SDimitry Andric { 135*0b57cec5SDimitry Andric // Use long as no Stantard string to integer exists. 136*0b57cec5SDimitry Andric long r = as_integer_helper<long>( func, s, idx, base, wcstol ); 137*0b57cec5SDimitry Andric if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) 138*0b57cec5SDimitry Andric throw_from_string_out_of_range(func); 139*0b57cec5SDimitry Andric return static_cast<int>(r); 140*0b57cec5SDimitry Andric } 141*0b57cec5SDimitry Andric 142*0b57cec5SDimitry Andric template<> 143*0b57cec5SDimitry Andric inline 144*0b57cec5SDimitry Andric long 145*0b57cec5SDimitry Andric as_integer( const string& func, const wstring& s, size_t* idx, int base ) 146*0b57cec5SDimitry Andric { 147*0b57cec5SDimitry Andric return as_integer_helper<long>( func, s, idx, base, wcstol ); 148*0b57cec5SDimitry Andric } 149*0b57cec5SDimitry Andric 150*0b57cec5SDimitry Andric template<> 151*0b57cec5SDimitry Andric inline 152*0b57cec5SDimitry Andric unsigned long 153*0b57cec5SDimitry Andric as_integer( const string& func, const wstring& s, size_t* idx, int base ) 154*0b57cec5SDimitry Andric { 155*0b57cec5SDimitry Andric return as_integer_helper<unsigned long>( func, s, idx, base, wcstoul ); 156*0b57cec5SDimitry Andric } 157*0b57cec5SDimitry Andric 158*0b57cec5SDimitry Andric template<> 159*0b57cec5SDimitry Andric inline 160*0b57cec5SDimitry Andric long long 161*0b57cec5SDimitry Andric as_integer( const string& func, const wstring& s, size_t* idx, int base ) 162*0b57cec5SDimitry Andric { 163*0b57cec5SDimitry Andric return as_integer_helper<long long>( func, s, idx, base, wcstoll ); 164*0b57cec5SDimitry Andric } 165*0b57cec5SDimitry Andric 166*0b57cec5SDimitry Andric template<> 167*0b57cec5SDimitry Andric inline 168*0b57cec5SDimitry Andric unsigned long long 169*0b57cec5SDimitry Andric as_integer( const string& func, const wstring& s, size_t* idx, int base ) 170*0b57cec5SDimitry Andric { 171*0b57cec5SDimitry Andric return as_integer_helper<unsigned long long>( func, s, idx, base, wcstoull ); 172*0b57cec5SDimitry Andric } 173*0b57cec5SDimitry Andric 174*0b57cec5SDimitry Andric // as_float 175*0b57cec5SDimitry Andric 176*0b57cec5SDimitry Andric template<typename V, typename S, typename F> 177*0b57cec5SDimitry Andric inline 178*0b57cec5SDimitry Andric V 179*0b57cec5SDimitry Andric as_float_helper(const string& func, const S& str, size_t* idx, F f ) 180*0b57cec5SDimitry Andric { 181*0b57cec5SDimitry Andric typename S::value_type* ptr = nullptr; 182*0b57cec5SDimitry Andric const typename S::value_type* const p = str.c_str(); 183*0b57cec5SDimitry Andric typename remove_reference<decltype(errno)>::type errno_save = errno; 184*0b57cec5SDimitry Andric errno = 0; 185*0b57cec5SDimitry Andric V r = f(p, &ptr); 186*0b57cec5SDimitry Andric swap(errno, errno_save); 187*0b57cec5SDimitry Andric if (errno_save == ERANGE) 188*0b57cec5SDimitry Andric throw_from_string_out_of_range(func); 189*0b57cec5SDimitry Andric if (ptr == p) 190*0b57cec5SDimitry Andric throw_from_string_invalid_arg(func); 191*0b57cec5SDimitry Andric if (idx) 192*0b57cec5SDimitry Andric *idx = static_cast<size_t>(ptr - p); 193*0b57cec5SDimitry Andric return r; 194*0b57cec5SDimitry Andric } 195*0b57cec5SDimitry Andric 196*0b57cec5SDimitry Andric template<typename V, typename S> 197*0b57cec5SDimitry Andric inline 198*0b57cec5SDimitry Andric V as_float( const string& func, const S& s, size_t* idx = nullptr ); 199*0b57cec5SDimitry Andric 200*0b57cec5SDimitry Andric template<> 201*0b57cec5SDimitry Andric inline 202*0b57cec5SDimitry Andric float 203*0b57cec5SDimitry Andric as_float( const string& func, const string& s, size_t* idx ) 204*0b57cec5SDimitry Andric { 205*0b57cec5SDimitry Andric return as_float_helper<float>( func, s, idx, strtof ); 206*0b57cec5SDimitry Andric } 207*0b57cec5SDimitry Andric 208*0b57cec5SDimitry Andric template<> 209*0b57cec5SDimitry Andric inline 210*0b57cec5SDimitry Andric double 211*0b57cec5SDimitry Andric as_float(const string& func, const string& s, size_t* idx ) 212*0b57cec5SDimitry Andric { 213*0b57cec5SDimitry Andric return as_float_helper<double>( func, s, idx, strtod ); 214*0b57cec5SDimitry Andric } 215*0b57cec5SDimitry Andric 216*0b57cec5SDimitry Andric template<> 217*0b57cec5SDimitry Andric inline 218*0b57cec5SDimitry Andric long double 219*0b57cec5SDimitry Andric as_float( const string& func, const string& s, size_t* idx ) 220*0b57cec5SDimitry Andric { 221*0b57cec5SDimitry Andric return as_float_helper<long double>( func, s, idx, strtold ); 222*0b57cec5SDimitry Andric } 223*0b57cec5SDimitry Andric 224*0b57cec5SDimitry Andric template<> 225*0b57cec5SDimitry Andric inline 226*0b57cec5SDimitry Andric float 227*0b57cec5SDimitry Andric as_float( const string& func, const wstring& s, size_t* idx ) 228*0b57cec5SDimitry Andric { 229*0b57cec5SDimitry Andric return as_float_helper<float>( func, s, idx, wcstof ); 230*0b57cec5SDimitry Andric } 231*0b57cec5SDimitry Andric 232*0b57cec5SDimitry Andric template<> 233*0b57cec5SDimitry Andric inline 234*0b57cec5SDimitry Andric double 235*0b57cec5SDimitry Andric as_float( const string& func, const wstring& s, size_t* idx ) 236*0b57cec5SDimitry Andric { 237*0b57cec5SDimitry Andric return as_float_helper<double>( func, s, idx, wcstod ); 238*0b57cec5SDimitry Andric } 239*0b57cec5SDimitry Andric 240*0b57cec5SDimitry Andric template<> 241*0b57cec5SDimitry Andric inline 242*0b57cec5SDimitry Andric long double 243*0b57cec5SDimitry Andric as_float( const string& func, const wstring& s, size_t* idx ) 244*0b57cec5SDimitry Andric { 245*0b57cec5SDimitry Andric return as_float_helper<long double>( func, s, idx, wcstold ); 246*0b57cec5SDimitry Andric } 247*0b57cec5SDimitry Andric 248*0b57cec5SDimitry Andric } // unnamed namespace 249*0b57cec5SDimitry Andric 250*0b57cec5SDimitry Andric int 251*0b57cec5SDimitry Andric stoi(const string& str, size_t* idx, int base) 252*0b57cec5SDimitry Andric { 253*0b57cec5SDimitry Andric return as_integer<int>( "stoi", str, idx, base ); 254*0b57cec5SDimitry Andric } 255*0b57cec5SDimitry Andric 256*0b57cec5SDimitry Andric int 257*0b57cec5SDimitry Andric stoi(const wstring& str, size_t* idx, int base) 258*0b57cec5SDimitry Andric { 259*0b57cec5SDimitry Andric return as_integer<int>( "stoi", str, idx, base ); 260*0b57cec5SDimitry Andric } 261*0b57cec5SDimitry Andric 262*0b57cec5SDimitry Andric long 263*0b57cec5SDimitry Andric stol(const string& str, size_t* idx, int base) 264*0b57cec5SDimitry Andric { 265*0b57cec5SDimitry Andric return as_integer<long>( "stol", str, idx, base ); 266*0b57cec5SDimitry Andric } 267*0b57cec5SDimitry Andric 268*0b57cec5SDimitry Andric long 269*0b57cec5SDimitry Andric stol(const wstring& str, size_t* idx, int base) 270*0b57cec5SDimitry Andric { 271*0b57cec5SDimitry Andric return as_integer<long>( "stol", str, idx, base ); 272*0b57cec5SDimitry Andric } 273*0b57cec5SDimitry Andric 274*0b57cec5SDimitry Andric unsigned long 275*0b57cec5SDimitry Andric stoul(const string& str, size_t* idx, int base) 276*0b57cec5SDimitry Andric { 277*0b57cec5SDimitry Andric return as_integer<unsigned long>( "stoul", str, idx, base ); 278*0b57cec5SDimitry Andric } 279*0b57cec5SDimitry Andric 280*0b57cec5SDimitry Andric unsigned long 281*0b57cec5SDimitry Andric stoul(const wstring& str, size_t* idx, int base) 282*0b57cec5SDimitry Andric { 283*0b57cec5SDimitry Andric return as_integer<unsigned long>( "stoul", str, idx, base ); 284*0b57cec5SDimitry Andric } 285*0b57cec5SDimitry Andric 286*0b57cec5SDimitry Andric long long 287*0b57cec5SDimitry Andric stoll(const string& str, size_t* idx, int base) 288*0b57cec5SDimitry Andric { 289*0b57cec5SDimitry Andric return as_integer<long long>( "stoll", str, idx, base ); 290*0b57cec5SDimitry Andric } 291*0b57cec5SDimitry Andric 292*0b57cec5SDimitry Andric long long 293*0b57cec5SDimitry Andric stoll(const wstring& str, size_t* idx, int base) 294*0b57cec5SDimitry Andric { 295*0b57cec5SDimitry Andric return as_integer<long long>( "stoll", str, idx, base ); 296*0b57cec5SDimitry Andric } 297*0b57cec5SDimitry Andric 298*0b57cec5SDimitry Andric unsigned long long 299*0b57cec5SDimitry Andric stoull(const string& str, size_t* idx, int base) 300*0b57cec5SDimitry Andric { 301*0b57cec5SDimitry Andric return as_integer<unsigned long long>( "stoull", str, idx, base ); 302*0b57cec5SDimitry Andric } 303*0b57cec5SDimitry Andric 304*0b57cec5SDimitry Andric unsigned long long 305*0b57cec5SDimitry Andric stoull(const wstring& str, size_t* idx, int base) 306*0b57cec5SDimitry Andric { 307*0b57cec5SDimitry Andric return as_integer<unsigned long long>( "stoull", str, idx, base ); 308*0b57cec5SDimitry Andric } 309*0b57cec5SDimitry Andric 310*0b57cec5SDimitry Andric float 311*0b57cec5SDimitry Andric stof(const string& str, size_t* idx) 312*0b57cec5SDimitry Andric { 313*0b57cec5SDimitry Andric return as_float<float>( "stof", str, idx ); 314*0b57cec5SDimitry Andric } 315*0b57cec5SDimitry Andric 316*0b57cec5SDimitry Andric float 317*0b57cec5SDimitry Andric stof(const wstring& str, size_t* idx) 318*0b57cec5SDimitry Andric { 319*0b57cec5SDimitry Andric return as_float<float>( "stof", str, idx ); 320*0b57cec5SDimitry Andric } 321*0b57cec5SDimitry Andric 322*0b57cec5SDimitry Andric double 323*0b57cec5SDimitry Andric stod(const string& str, size_t* idx) 324*0b57cec5SDimitry Andric { 325*0b57cec5SDimitry Andric return as_float<double>( "stod", str, idx ); 326*0b57cec5SDimitry Andric } 327*0b57cec5SDimitry Andric 328*0b57cec5SDimitry Andric double 329*0b57cec5SDimitry Andric stod(const wstring& str, size_t* idx) 330*0b57cec5SDimitry Andric { 331*0b57cec5SDimitry Andric return as_float<double>( "stod", str, idx ); 332*0b57cec5SDimitry Andric } 333*0b57cec5SDimitry Andric 334*0b57cec5SDimitry Andric long double 335*0b57cec5SDimitry Andric stold(const string& str, size_t* idx) 336*0b57cec5SDimitry Andric { 337*0b57cec5SDimitry Andric return as_float<long double>( "stold", str, idx ); 338*0b57cec5SDimitry Andric } 339*0b57cec5SDimitry Andric 340*0b57cec5SDimitry Andric long double 341*0b57cec5SDimitry Andric stold(const wstring& str, size_t* idx) 342*0b57cec5SDimitry Andric { 343*0b57cec5SDimitry Andric return as_float<long double>( "stold", str, idx ); 344*0b57cec5SDimitry Andric } 345*0b57cec5SDimitry Andric 346*0b57cec5SDimitry Andric // to_string 347*0b57cec5SDimitry Andric 348*0b57cec5SDimitry Andric namespace 349*0b57cec5SDimitry Andric { 350*0b57cec5SDimitry Andric 351*0b57cec5SDimitry Andric // as_string 352*0b57cec5SDimitry Andric 353*0b57cec5SDimitry Andric template<typename S, typename P, typename V > 354*0b57cec5SDimitry Andric inline 355*0b57cec5SDimitry Andric S 356*0b57cec5SDimitry Andric as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a) 357*0b57cec5SDimitry Andric { 358*0b57cec5SDimitry Andric typedef typename S::size_type size_type; 359*0b57cec5SDimitry Andric size_type available = s.size(); 360*0b57cec5SDimitry Andric while (true) 361*0b57cec5SDimitry Andric { 362*0b57cec5SDimitry Andric int status = sprintf_like(&s[0], available + 1, fmt, a); 363*0b57cec5SDimitry Andric if ( status >= 0 ) 364*0b57cec5SDimitry Andric { 365*0b57cec5SDimitry Andric size_type used = static_cast<size_type>(status); 366*0b57cec5SDimitry Andric if ( used <= available ) 367*0b57cec5SDimitry Andric { 368*0b57cec5SDimitry Andric s.resize( used ); 369*0b57cec5SDimitry Andric break; 370*0b57cec5SDimitry Andric } 371*0b57cec5SDimitry Andric available = used; // Assume this is advice of how much space we need. 372*0b57cec5SDimitry Andric } 373*0b57cec5SDimitry Andric else 374*0b57cec5SDimitry Andric available = available * 2 + 1; 375*0b57cec5SDimitry Andric s.resize(available); 376*0b57cec5SDimitry Andric } 377*0b57cec5SDimitry Andric return s; 378*0b57cec5SDimitry Andric } 379*0b57cec5SDimitry Andric 380*0b57cec5SDimitry Andric template <class S> 381*0b57cec5SDimitry Andric struct initial_string; 382*0b57cec5SDimitry Andric 383*0b57cec5SDimitry Andric template <> 384*0b57cec5SDimitry Andric struct initial_string<string> 385*0b57cec5SDimitry Andric { 386*0b57cec5SDimitry Andric string 387*0b57cec5SDimitry Andric operator()() const 388*0b57cec5SDimitry Andric { 389*0b57cec5SDimitry Andric string s; 390*0b57cec5SDimitry Andric s.resize(s.capacity()); 391*0b57cec5SDimitry Andric return s; 392*0b57cec5SDimitry Andric } 393*0b57cec5SDimitry Andric }; 394*0b57cec5SDimitry Andric 395*0b57cec5SDimitry Andric template <> 396*0b57cec5SDimitry Andric struct initial_string<wstring> 397*0b57cec5SDimitry Andric { 398*0b57cec5SDimitry Andric wstring 399*0b57cec5SDimitry Andric operator()() const 400*0b57cec5SDimitry Andric { 401*0b57cec5SDimitry Andric wstring s(20, wchar_t()); 402*0b57cec5SDimitry Andric s.resize(s.capacity()); 403*0b57cec5SDimitry Andric return s; 404*0b57cec5SDimitry Andric } 405*0b57cec5SDimitry Andric }; 406*0b57cec5SDimitry Andric 407*0b57cec5SDimitry Andric typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...); 408*0b57cec5SDimitry Andric 409*0b57cec5SDimitry Andric inline 410*0b57cec5SDimitry Andric wide_printf 411*0b57cec5SDimitry Andric get_swprintf() 412*0b57cec5SDimitry Andric { 413*0b57cec5SDimitry Andric #ifndef _LIBCPP_MSVCRT 414*0b57cec5SDimitry Andric return swprintf; 415*0b57cec5SDimitry Andric #else 416*0b57cec5SDimitry Andric return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(_snwprintf); 417*0b57cec5SDimitry Andric #endif 418*0b57cec5SDimitry Andric } 419*0b57cec5SDimitry Andric 420*0b57cec5SDimitry Andric template <typename S, typename V> 421*0b57cec5SDimitry Andric S i_to_string(const V v) 422*0b57cec5SDimitry Andric { 423*0b57cec5SDimitry Andric // numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers. 424*0b57cec5SDimitry Andric // For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented), 425*0b57cec5SDimitry Andric // so we need +1 here. 426*0b57cec5SDimitry Andric constexpr size_t bufsize = numeric_limits<V>::digits10 + 2; // +1 for minus, +1 for digits10 427*0b57cec5SDimitry Andric char buf[bufsize]; 428*0b57cec5SDimitry Andric const auto res = to_chars(buf, buf + bufsize, v); 429*0b57cec5SDimitry Andric _LIBCPP_ASSERT(res.ec == errc(), "bufsize must be large enough to accomodate the value"); 430*0b57cec5SDimitry Andric return S(buf, res.ptr); 431*0b57cec5SDimitry Andric } 432*0b57cec5SDimitry Andric 433*0b57cec5SDimitry Andric } // unnamed namespace 434*0b57cec5SDimitry Andric 435*0b57cec5SDimitry Andric string to_string (int val) { return i_to_string< string>(val); } 436*0b57cec5SDimitry Andric string to_string (long val) { return i_to_string< string>(val); } 437*0b57cec5SDimitry Andric string to_string (long long val) { return i_to_string< string>(val); } 438*0b57cec5SDimitry Andric string to_string (unsigned val) { return i_to_string< string>(val); } 439*0b57cec5SDimitry Andric string to_string (unsigned long val) { return i_to_string< string>(val); } 440*0b57cec5SDimitry Andric string to_string (unsigned long long val) { return i_to_string< string>(val); } 441*0b57cec5SDimitry Andric 442*0b57cec5SDimitry Andric wstring to_wstring(int val) { return i_to_string<wstring>(val); } 443*0b57cec5SDimitry Andric wstring to_wstring(long val) { return i_to_string<wstring>(val); } 444*0b57cec5SDimitry Andric wstring to_wstring(long long val) { return i_to_string<wstring>(val); } 445*0b57cec5SDimitry Andric wstring to_wstring(unsigned val) { return i_to_string<wstring>(val); } 446*0b57cec5SDimitry Andric wstring to_wstring(unsigned long val) { return i_to_string<wstring>(val); } 447*0b57cec5SDimitry Andric wstring to_wstring(unsigned long long val) { return i_to_string<wstring>(val); } 448*0b57cec5SDimitry Andric 449*0b57cec5SDimitry Andric 450*0b57cec5SDimitry Andric string to_string (float val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } 451*0b57cec5SDimitry Andric string to_string (double val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } 452*0b57cec5SDimitry Andric string to_string (long double val) { return as_string(snprintf, initial_string< string>()(), "%Lf", val); } 453*0b57cec5SDimitry Andric 454*0b57cec5SDimitry Andric wstring to_wstring(float val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } 455*0b57cec5SDimitry Andric wstring to_wstring(double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } 456*0b57cec5SDimitry Andric wstring to_wstring(long double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%Lf", val); } 457*0b57cec5SDimitry Andric 458*0b57cec5SDimitry Andric _LIBCPP_END_NAMESPACE_STD 459