1227825Stheraven//===------------------------- string.cpp ---------------------------------===// 2227825Stheraven// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6227825Stheraven// 7227825Stheraven//===----------------------------------------------------------------------===// 8227825Stheraven 9227825Stheraven#include "string" 10353358Sdim#include "charconv" 11227825Stheraven#include "cstdlib" 12227825Stheraven#include "cwchar" 13227825Stheraven#include "cerrno" 14253146Stheraven#include "limits" 15253146Stheraven#include "stdexcept" 16261272Sdim#include <stdio.h> 17353358Sdim#include "__debug" 18227825Stheraven 19227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD 20227825Stheraven 21314564Sdimtemplate class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common<true>; 22227825Stheraven 23314564Sdimtemplate class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<char>; 24314564Sdimtemplate class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<wchar_t>; 25227825Stheraven 26227825Stheraventemplate 27227825Stheraven string 28227825Stheraven operator+<char, char_traits<char>, allocator<char> >(char const*, string const&); 29227825Stheraven 30253146Stheravennamespace 31227825Stheraven{ 32253146Stheraven 33253146Stheraventemplate<typename T> 34253146Stheraveninline 35253146Stheravenvoid throw_helper( const string& msg ) 36253146Stheraven{ 37253146Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 38253146Stheraven throw T( msg ); 39253146Stheraven#else 40288943Sdim fprintf(stderr, "%s\n", msg.c_str()); 41314564Sdim _VSTD::abort(); 42253146Stheraven#endif 43253146Stheraven} 44253146Stheraven 45253146Stheraveninline 46253146Stheravenvoid throw_from_string_out_of_range( const string& func ) 47253146Stheraven{ 48253146Stheraven throw_helper<out_of_range>(func + ": out of range"); 49253146Stheraven} 50253146Stheraven 51253146Stheraveninline 52253146Stheravenvoid throw_from_string_invalid_arg( const string& func ) 53253146Stheraven{ 54253146Stheraven throw_helper<invalid_argument>(func + ": no conversion"); 55253146Stheraven} 56253146Stheraven 57253146Stheraven// as_integer 58253146Stheraven 59253146Stheraventemplate<typename V, typename S, typename F> 60253146Stheraveninline 61253146StheravenV 62253146Stheravenas_integer_helper(const string& func, const S& str, size_t* idx, int base, F f) 63253146Stheraven{ 64276792Sdim typename S::value_type* ptr = nullptr; 65253146Stheraven const typename S::value_type* const p = str.c_str(); 66246468Stheraven typename remove_reference<decltype(errno)>::type errno_save = errno; 67246468Stheraven errno = 0; 68253146Stheraven V r = f(p, &ptr, base); 69246468Stheraven swap(errno, errno_save); 70253146Stheraven if (errno_save == ERANGE) 71253146Stheraven throw_from_string_out_of_range(func); 72246468Stheraven if (ptr == p) 73253146Stheraven throw_from_string_invalid_arg(func); 74227825Stheraven if (idx) 75227825Stheraven *idx = static_cast<size_t>(ptr - p); 76253146Stheraven return r; 77253146Stheraven} 78253146Stheraven 79253146Stheraventemplate<typename V, typename S> 80253146Stheraveninline 81253146StheravenV 82253146Stheravenas_integer(const string& func, const S& s, size_t* idx, int base); 83253146Stheraven 84253146Stheraven// string 85253146Stheraventemplate<> 86253146Stheraveninline 87253146Stheravenint 88253146Stheravenas_integer(const string& func, const string& s, size_t* idx, int base ) 89253146Stheraven{ 90261272Sdim // Use long as no Standard string to integer exists. 91253146Stheraven long r = as_integer_helper<long>( func, s, idx, base, strtol ); 92253146Stheraven if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) 93253146Stheraven throw_from_string_out_of_range(func); 94227825Stheraven return static_cast<int>(r); 95227825Stheraven} 96227825Stheraven 97253146Stheraventemplate<> 98253146Stheraveninline 99253146Stheravenlong 100253146Stheravenas_integer(const string& func, const string& s, size_t* idx, int base ) 101253146Stheraven{ 102253146Stheraven return as_integer_helper<long>( func, s, idx, base, strtol ); 103253146Stheraven} 104253146Stheraven 105253146Stheraventemplate<> 106253146Stheraveninline 107253146Stheravenunsigned long 108253146Stheravenas_integer( const string& func, const string& s, size_t* idx, int base ) 109253146Stheraven{ 110253146Stheraven return as_integer_helper<unsigned long>( func, s, idx, base, strtoul ); 111253146Stheraven} 112253146Stheraven 113253146Stheraventemplate<> 114253146Stheraveninline 115253146Stheravenlong long 116253146Stheravenas_integer( const string& func, const string& s, size_t* idx, int base ) 117253146Stheraven{ 118253146Stheraven return as_integer_helper<long long>( func, s, idx, base, strtoll ); 119253146Stheraven} 120253146Stheraven 121253146Stheraventemplate<> 122253146Stheraveninline 123253146Stheravenunsigned long long 124253146Stheravenas_integer( const string& func, const string& s, size_t* idx, int base ) 125253146Stheraven{ 126253146Stheraven return as_integer_helper<unsigned long long>( func, s, idx, base, strtoull ); 127253146Stheraven} 128253146Stheraven 129253146Stheraven// wstring 130253146Stheraventemplate<> 131253146Stheraveninline 132227825Stheravenint 133253146Stheravenas_integer( const string& func, const wstring& s, size_t* idx, int base ) 134227825Stheraven{ 135253146Stheraven // Use long as no Stantard string to integer exists. 136253146Stheraven long r = as_integer_helper<long>( func, s, idx, base, wcstol ); 137253146Stheraven if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) 138253146Stheraven throw_from_string_out_of_range(func); 139227825Stheraven return static_cast<int>(r); 140227825Stheraven} 141227825Stheraven 142253146Stheraventemplate<> 143253146Stheraveninline 144227825Stheravenlong 145253146Stheravenas_integer( const string& func, const wstring& s, size_t* idx, int base ) 146227825Stheraven{ 147253146Stheraven return as_integer_helper<long>( func, s, idx, base, wcstol ); 148253146Stheraven} 149253146Stheraven 150253146Stheraventemplate<> 151253146Stheraveninline 152253146Stheravenunsigned long 153253146Stheravenas_integer( const string& func, const wstring& s, size_t* idx, int base ) 154253146Stheraven{ 155253146Stheraven return as_integer_helper<unsigned long>( func, s, idx, base, wcstoul ); 156253146Stheraven} 157253146Stheraven 158253146Stheraventemplate<> 159253146Stheraveninline 160253146Stheravenlong long 161253146Stheravenas_integer( const string& func, const wstring& s, size_t* idx, int base ) 162253146Stheraven{ 163253146Stheraven return as_integer_helper<long long>( func, s, idx, base, wcstoll ); 164253146Stheraven} 165253146Stheraven 166253146Stheraventemplate<> 167253146Stheraveninline 168253146Stheravenunsigned long long 169253146Stheravenas_integer( const string& func, const wstring& s, size_t* idx, int base ) 170253146Stheraven{ 171253146Stheraven return as_integer_helper<unsigned long long>( func, s, idx, base, wcstoull ); 172253146Stheraven} 173253146Stheraven 174253146Stheraven// as_float 175253146Stheraven 176353358Sdimtemplate<typename V, typename S, typename F> 177253146Stheraveninline 178253146StheravenV 179253146Stheravenas_float_helper(const string& func, const S& str, size_t* idx, F f ) 180253146Stheraven{ 181276792Sdim typename S::value_type* ptr = nullptr; 182253146Stheraven const typename S::value_type* const p = str.c_str(); 183246468Stheraven typename remove_reference<decltype(errno)>::type errno_save = errno; 184246468Stheraven errno = 0; 185253146Stheraven V r = f(p, &ptr); 186246468Stheraven swap(errno, errno_save); 187246468Stheraven if (errno_save == ERANGE) 188253146Stheraven throw_from_string_out_of_range(func); 189246468Stheraven if (ptr == p) 190253146Stheraven throw_from_string_invalid_arg(func); 191227825Stheraven if (idx) 192227825Stheraven *idx = static_cast<size_t>(ptr - p); 193227825Stheraven return r; 194227825Stheraven} 195227825Stheraven 196253146Stheraventemplate<typename V, typename S> 197253146Stheraveninline 198253146StheravenV as_float( const string& func, const S& s, size_t* idx = nullptr ); 199253146Stheraven 200253146Stheraventemplate<> 201253146Stheraveninline 202253146Stheravenfloat 203253146Stheravenas_float( const string& func, const string& s, size_t* idx ) 204253146Stheraven{ 205253146Stheraven return as_float_helper<float>( func, s, idx, strtof ); 206253146Stheraven} 207253146Stheraven 208253146Stheraventemplate<> 209253146Stheraveninline 210253146Stheravendouble 211253146Stheravenas_float(const string& func, const string& s, size_t* idx ) 212253146Stheraven{ 213253146Stheraven return as_float_helper<double>( func, s, idx, strtod ); 214253146Stheraven} 215253146Stheraven 216253146Stheraventemplate<> 217253146Stheraveninline 218253146Stheravenlong double 219253146Stheravenas_float( const string& func, const string& s, size_t* idx ) 220253146Stheraven{ 221253146Stheraven return as_float_helper<long double>( func, s, idx, strtold ); 222253146Stheraven} 223253146Stheraven 224253146Stheraventemplate<> 225253146Stheraveninline 226253146Stheravenfloat 227253146Stheravenas_float( const string& func, const wstring& s, size_t* idx ) 228253146Stheraven{ 229253146Stheraven return as_float_helper<float>( func, s, idx, wcstof ); 230253146Stheraven} 231253146Stheraven 232253146Stheraventemplate<> 233253146Stheraveninline 234253146Stheravendouble 235253146Stheravenas_float( const string& func, const wstring& s, size_t* idx ) 236253146Stheraven{ 237253146Stheraven return as_float_helper<double>( func, s, idx, wcstod ); 238253146Stheraven} 239253146Stheraven 240253146Stheraventemplate<> 241253146Stheraveninline 242253146Stheravenlong double 243253146Stheravenas_float( const string& func, const wstring& s, size_t* idx ) 244253146Stheraven{ 245253146Stheraven return as_float_helper<long double>( func, s, idx, wcstold ); 246253146Stheraven} 247253146Stheraven 248253146Stheraven} // unnamed namespace 249253146Stheraven 250253146Stheravenint 251253146Stheravenstoi(const string& str, size_t* idx, int base) 252253146Stheraven{ 253253146Stheraven return as_integer<int>( "stoi", str, idx, base ); 254253146Stheraven} 255253146Stheraven 256253146Stheravenint 257253146Stheravenstoi(const wstring& str, size_t* idx, int base) 258253146Stheraven{ 259253146Stheraven return as_integer<int>( "stoi", str, idx, base ); 260253146Stheraven} 261253146Stheraven 262227825Stheravenlong 263253146Stheravenstol(const string& str, size_t* idx, int base) 264253146Stheraven{ 265253146Stheraven return as_integer<long>( "stol", str, idx, base ); 266253146Stheraven} 267253146Stheraven 268253146Stheravenlong 269227825Stheravenstol(const wstring& str, size_t* idx, int base) 270227825Stheraven{ 271253146Stheraven return as_integer<long>( "stol", str, idx, base ); 272227825Stheraven} 273227825Stheraven 274227825Stheravenunsigned long 275227825Stheravenstoul(const string& str, size_t* idx, int base) 276227825Stheraven{ 277253146Stheraven return as_integer<unsigned long>( "stoul", str, idx, base ); 278227825Stheraven} 279227825Stheraven 280227825Stheravenunsigned long 281227825Stheravenstoul(const wstring& str, size_t* idx, int base) 282227825Stheraven{ 283253146Stheraven return as_integer<unsigned long>( "stoul", str, idx, base ); 284227825Stheraven} 285227825Stheraven 286227825Stheravenlong long 287227825Stheravenstoll(const string& str, size_t* idx, int base) 288227825Stheraven{ 289253146Stheraven return as_integer<long long>( "stoll", str, idx, base ); 290227825Stheraven} 291227825Stheraven 292227825Stheravenlong long 293227825Stheravenstoll(const wstring& str, size_t* idx, int base) 294227825Stheraven{ 295253146Stheraven return as_integer<long long>( "stoll", str, idx, base ); 296227825Stheraven} 297227825Stheraven 298227825Stheravenunsigned long long 299227825Stheravenstoull(const string& str, size_t* idx, int base) 300227825Stheraven{ 301253146Stheraven return as_integer<unsigned long long>( "stoull", str, idx, base ); 302227825Stheraven} 303227825Stheraven 304227825Stheravenunsigned long long 305227825Stheravenstoull(const wstring& str, size_t* idx, int base) 306227825Stheraven{ 307253146Stheraven return as_integer<unsigned long long>( "stoull", str, idx, base ); 308227825Stheraven} 309227825Stheraven 310227825Stheravenfloat 311227825Stheravenstof(const string& str, size_t* idx) 312227825Stheraven{ 313253146Stheraven return as_float<float>( "stof", str, idx ); 314227825Stheraven} 315227825Stheraven 316227825Stheravenfloat 317227825Stheravenstof(const wstring& str, size_t* idx) 318227825Stheraven{ 319253146Stheraven return as_float<float>( "stof", str, idx ); 320227825Stheraven} 321227825Stheraven 322227825Stheravendouble 323227825Stheravenstod(const string& str, size_t* idx) 324227825Stheraven{ 325253146Stheraven return as_float<double>( "stod", str, idx ); 326227825Stheraven} 327227825Stheraven 328227825Stheravendouble 329227825Stheravenstod(const wstring& str, size_t* idx) 330227825Stheraven{ 331253146Stheraven return as_float<double>( "stod", str, idx ); 332227825Stheraven} 333227825Stheraven 334227825Stheravenlong double 335227825Stheravenstold(const string& str, size_t* idx) 336227825Stheraven{ 337253146Stheraven return as_float<long double>( "stold", str, idx ); 338227825Stheraven} 339227825Stheraven 340227825Stheravenlong double 341227825Stheravenstold(const wstring& str, size_t* idx) 342227825Stheraven{ 343253146Stheraven return as_float<long double>( "stold", str, idx ); 344227825Stheraven} 345227825Stheraven 346253146Stheraven// to_string 347253146Stheraven 348253146Stheravennamespace 349227825Stheraven{ 350253146Stheraven 351253146Stheraven// as_string 352253146Stheraven 353253146Stheraventemplate<typename S, typename P, typename V > 354253146Stheraveninline 355253146StheravenS 356253146Stheravenas_string(P sprintf_like, S s, const typename S::value_type* fmt, V a) 357253146Stheraven{ 358253146Stheraven typedef typename S::size_type size_type; 359253146Stheraven size_type available = s.size(); 360227825Stheraven while (true) 361227825Stheraven { 362253146Stheraven int status = sprintf_like(&s[0], available + 1, fmt, a); 363253146Stheraven if ( status >= 0 ) 364227825Stheraven { 365253146Stheraven size_type used = static_cast<size_type>(status); 366253146Stheraven if ( used <= available ) 367253146Stheraven { 368253146Stheraven s.resize( used ); 369253146Stheraven break; 370253146Stheraven } 371253146Stheraven available = used; // Assume this is advice of how much space we need. 372227825Stheraven } 373253146Stheraven else 374253146Stheraven available = available * 2 + 1; 375253146Stheraven s.resize(available); 376227825Stheraven } 377227825Stheraven return s; 378227825Stheraven} 379227825Stheraven 380353358Sdimtemplate <class S> 381253146Stheravenstruct initial_string; 382253146Stheraven 383353358Sdimtemplate <> 384353358Sdimstruct initial_string<string> 385227825Stheraven{ 386253146Stheraven string 387253146Stheraven operator()() const 388227825Stheraven { 389253146Stheraven string s; 390253146Stheraven s.resize(s.capacity()); 391253146Stheraven return s; 392227825Stheraven } 393253146Stheraven}; 394227825Stheraven 395353358Sdimtemplate <> 396353358Sdimstruct initial_string<wstring> 397227825Stheraven{ 398253146Stheraven wstring 399253146Stheraven operator()() const 400227825Stheraven { 401253146Stheraven wstring s(20, wchar_t()); 402253146Stheraven s.resize(s.capacity()); 403253146Stheraven return s; 404227825Stheraven } 405253146Stheraven}; 406253146Stheraven 407253146Stheraventypedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...); 408253146Stheraven 409253146Stheraveninline 410253146Stheravenwide_printf 411253146Stheravenget_swprintf() 412253146Stheraven{ 413261272Sdim#ifndef _LIBCPP_MSVCRT 414253146Stheraven return swprintf; 415253146Stheraven#else 416321369Sdim return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(_snwprintf); 417253146Stheraven#endif 418227825Stheraven} 419227825Stheraven 420353358Sdimtemplate <typename S, typename V> 421353358SdimS i_to_string(const V v) 422253146Stheraven{ 423353358Sdim// numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers. 424353358Sdim// For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented), 425353358Sdim// so we need +1 here. 426353358Sdim constexpr size_t bufsize = numeric_limits<V>::digits10 + 2; // +1 for minus, +1 for digits10 427353358Sdim char buf[bufsize]; 428353358Sdim const auto res = to_chars(buf, buf + bufsize, v); 429353358Sdim _LIBCPP_ASSERT(res.ec == errc(), "bufsize must be large enough to accomodate the value"); 430353358Sdim return S(buf, res.ptr); 431253146Stheraven} 432253146Stheraven 433353358Sdim} // unnamed namespace 434253146Stheraven 435353358Sdimstring to_string (int val) { return i_to_string< string>(val); } 436353358Sdimstring to_string (long val) { return i_to_string< string>(val); } 437353358Sdimstring to_string (long long val) { return i_to_string< string>(val); } 438353358Sdimstring to_string (unsigned val) { return i_to_string< string>(val); } 439353358Sdimstring to_string (unsigned long val) { return i_to_string< string>(val); } 440353358Sdimstring to_string (unsigned long long val) { return i_to_string< string>(val); } 441253146Stheraven 442353358Sdimwstring to_wstring(int val) { return i_to_string<wstring>(val); } 443353358Sdimwstring to_wstring(long val) { return i_to_string<wstring>(val); } 444353358Sdimwstring to_wstring(long long val) { return i_to_string<wstring>(val); } 445353358Sdimwstring to_wstring(unsigned val) { return i_to_string<wstring>(val); } 446353358Sdimwstring to_wstring(unsigned long val) { return i_to_string<wstring>(val); } 447353358Sdimwstring to_wstring(unsigned long long val) { return i_to_string<wstring>(val); } 448253146Stheraven 449227825Stheraven 450353358Sdimstring to_string (float val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } 451353358Sdimstring to_string (double val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } 452353358Sdimstring to_string (long double val) { return as_string(snprintf, initial_string< string>()(), "%Lf", val); } 453227825Stheraven 454353358Sdimwstring to_wstring(float val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } 455353358Sdimwstring to_wstring(double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } 456353358Sdimwstring to_wstring(long double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%Lf", val); } 457227825Stheraven 458227825Stheraven_LIBCPP_END_NAMESPACE_STD 459