string.cpp revision 314564
1227825Stheraven//===------------------------- string.cpp ---------------------------------===// 2227825Stheraven// 3227825Stheraven// The LLVM Compiler Infrastructure 4227825Stheraven// 5227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open 6227825Stheraven// Source Licenses. See LICENSE.TXT for details. 7227825Stheraven// 8227825Stheraven//===----------------------------------------------------------------------===// 9227825Stheraven 10227825Stheraven#include "string" 11227825Stheraven#include "cstdlib" 12227825Stheraven#include "cwchar" 13227825Stheraven#include "cerrno" 14253146Stheraven#include "limits" 15253146Stheraven#include "stdexcept" 16261272Sdim#ifdef _LIBCPP_MSVCRT 17227825Stheraven#include "support/win32/support.h" 18261272Sdim#endif // _LIBCPP_MSVCRT 19261272Sdim#include <stdio.h> 20227825Stheraven 21227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD 22227825Stheraven 23314564Sdimtemplate class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common<true>; 24227825Stheraven 25314564Sdimtemplate class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<char>; 26314564Sdimtemplate class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<wchar_t>; 27227825Stheraven 28227825Stheraventemplate 29227825Stheraven string 30227825Stheraven operator+<char, char_traits<char>, allocator<char> >(char const*, string const&); 31227825Stheraven 32253146Stheravennamespace 33227825Stheraven{ 34253146Stheraven 35253146Stheraventemplate<typename T> 36253146Stheraveninline 37253146Stheravenvoid throw_helper( const string& msg ) 38253146Stheraven{ 39253146Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 40253146Stheraven throw T( msg ); 41253146Stheraven#else 42288943Sdim fprintf(stderr, "%s\n", msg.c_str()); 43314564Sdim _VSTD::abort(); 44253146Stheraven#endif 45253146Stheraven} 46253146Stheraven 47253146Stheraveninline 48253146Stheravenvoid throw_from_string_out_of_range( const string& func ) 49253146Stheraven{ 50253146Stheraven throw_helper<out_of_range>(func + ": out of range"); 51253146Stheraven} 52253146Stheraven 53253146Stheraveninline 54253146Stheravenvoid throw_from_string_invalid_arg( const string& func ) 55253146Stheraven{ 56253146Stheraven throw_helper<invalid_argument>(func + ": no conversion"); 57253146Stheraven} 58253146Stheraven 59253146Stheraven// as_integer 60253146Stheraven 61253146Stheraventemplate<typename V, typename S, typename F> 62253146Stheraveninline 63253146StheravenV 64253146Stheravenas_integer_helper(const string& func, const S& str, size_t* idx, int base, F f) 65253146Stheraven{ 66276792Sdim typename S::value_type* ptr = nullptr; 67253146Stheraven const typename S::value_type* const p = str.c_str(); 68246468Stheraven typename remove_reference<decltype(errno)>::type errno_save = errno; 69246468Stheraven errno = 0; 70253146Stheraven V r = f(p, &ptr, base); 71246468Stheraven swap(errno, errno_save); 72253146Stheraven if (errno_save == ERANGE) 73253146Stheraven throw_from_string_out_of_range(func); 74246468Stheraven if (ptr == p) 75253146Stheraven throw_from_string_invalid_arg(func); 76227825Stheraven if (idx) 77227825Stheraven *idx = static_cast<size_t>(ptr - p); 78253146Stheraven return r; 79253146Stheraven} 80253146Stheraven 81253146Stheraventemplate<typename V, typename S> 82253146Stheraveninline 83253146StheravenV 84253146Stheravenas_integer(const string& func, const S& s, size_t* idx, int base); 85253146Stheraven 86253146Stheraven// string 87253146Stheraventemplate<> 88253146Stheraveninline 89253146Stheravenint 90253146Stheravenas_integer(const string& func, const string& s, size_t* idx, int base ) 91253146Stheraven{ 92261272Sdim // Use long as no Standard string to integer exists. 93253146Stheraven long r = as_integer_helper<long>( func, s, idx, base, strtol ); 94253146Stheraven if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) 95253146Stheraven throw_from_string_out_of_range(func); 96227825Stheraven return static_cast<int>(r); 97227825Stheraven} 98227825Stheraven 99253146Stheraventemplate<> 100253146Stheraveninline 101253146Stheravenlong 102253146Stheravenas_integer(const string& func, const string& s, size_t* idx, int base ) 103253146Stheraven{ 104253146Stheraven return as_integer_helper<long>( func, s, idx, base, strtol ); 105253146Stheraven} 106253146Stheraven 107253146Stheraventemplate<> 108253146Stheraveninline 109253146Stheravenunsigned long 110253146Stheravenas_integer( const string& func, const string& s, size_t* idx, int base ) 111253146Stheraven{ 112253146Stheraven return as_integer_helper<unsigned long>( func, s, idx, base, strtoul ); 113253146Stheraven} 114253146Stheraven 115253146Stheraventemplate<> 116253146Stheraveninline 117253146Stheravenlong long 118253146Stheravenas_integer( const string& func, const string& s, size_t* idx, int base ) 119253146Stheraven{ 120253146Stheraven return as_integer_helper<long long>( func, s, idx, base, strtoll ); 121253146Stheraven} 122253146Stheraven 123253146Stheraventemplate<> 124253146Stheraveninline 125253146Stheravenunsigned long long 126253146Stheravenas_integer( const string& func, const string& s, size_t* idx, int base ) 127253146Stheraven{ 128253146Stheraven return as_integer_helper<unsigned long long>( func, s, idx, base, strtoull ); 129253146Stheraven} 130253146Stheraven 131253146Stheraven// wstring 132253146Stheraventemplate<> 133253146Stheraveninline 134227825Stheravenint 135253146Stheravenas_integer( const string& func, const wstring& s, size_t* idx, int base ) 136227825Stheraven{ 137253146Stheraven // Use long as no Stantard string to integer exists. 138253146Stheraven long r = as_integer_helper<long>( func, s, idx, base, wcstol ); 139253146Stheraven if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) 140253146Stheraven throw_from_string_out_of_range(func); 141227825Stheraven return static_cast<int>(r); 142227825Stheraven} 143227825Stheraven 144253146Stheraventemplate<> 145253146Stheraveninline 146227825Stheravenlong 147253146Stheravenas_integer( const string& func, const wstring& s, size_t* idx, int base ) 148227825Stheraven{ 149253146Stheraven return as_integer_helper<long>( func, s, idx, base, wcstol ); 150253146Stheraven} 151253146Stheraven 152253146Stheraventemplate<> 153253146Stheraveninline 154253146Stheravenunsigned long 155253146Stheravenas_integer( const string& func, const wstring& s, size_t* idx, int base ) 156253146Stheraven{ 157253146Stheraven return as_integer_helper<unsigned long>( func, s, idx, base, wcstoul ); 158253146Stheraven} 159253146Stheraven 160253146Stheraventemplate<> 161253146Stheraveninline 162253146Stheravenlong long 163253146Stheravenas_integer( const string& func, const wstring& s, size_t* idx, int base ) 164253146Stheraven{ 165253146Stheraven return as_integer_helper<long long>( func, s, idx, base, wcstoll ); 166253146Stheraven} 167253146Stheraven 168253146Stheraventemplate<> 169253146Stheraveninline 170253146Stheravenunsigned long long 171253146Stheravenas_integer( const string& func, const wstring& s, size_t* idx, int base ) 172253146Stheraven{ 173253146Stheraven return as_integer_helper<unsigned long long>( func, s, idx, base, wcstoull ); 174253146Stheraven} 175253146Stheraven 176253146Stheraven// as_float 177253146Stheraven 178253146Stheraventemplate<typename V, typename S, typename F> 179253146Stheraveninline 180253146StheravenV 181253146Stheravenas_float_helper(const string& func, const S& str, size_t* idx, F f ) 182253146Stheraven{ 183276792Sdim typename S::value_type* ptr = nullptr; 184253146Stheraven const typename S::value_type* const p = str.c_str(); 185246468Stheraven typename remove_reference<decltype(errno)>::type errno_save = errno; 186246468Stheraven errno = 0; 187253146Stheraven V r = f(p, &ptr); 188246468Stheraven swap(errno, errno_save); 189246468Stheraven if (errno_save == ERANGE) 190253146Stheraven throw_from_string_out_of_range(func); 191246468Stheraven if (ptr == p) 192253146Stheraven throw_from_string_invalid_arg(func); 193227825Stheraven if (idx) 194227825Stheraven *idx = static_cast<size_t>(ptr - p); 195227825Stheraven return r; 196227825Stheraven} 197227825Stheraven 198253146Stheraventemplate<typename V, typename S> 199253146Stheraveninline 200253146StheravenV as_float( const string& func, const S& s, size_t* idx = nullptr ); 201253146Stheraven 202253146Stheraventemplate<> 203253146Stheraveninline 204253146Stheravenfloat 205253146Stheravenas_float( const string& func, const string& s, size_t* idx ) 206253146Stheraven{ 207253146Stheraven return as_float_helper<float>( func, s, idx, strtof ); 208253146Stheraven} 209253146Stheraven 210253146Stheraventemplate<> 211253146Stheraveninline 212253146Stheravendouble 213253146Stheravenas_float(const string& func, const string& s, size_t* idx ) 214253146Stheraven{ 215253146Stheraven return as_float_helper<double>( func, s, idx, strtod ); 216253146Stheraven} 217253146Stheraven 218253146Stheraventemplate<> 219253146Stheraveninline 220253146Stheravenlong double 221253146Stheravenas_float( const string& func, const string& s, size_t* idx ) 222253146Stheraven{ 223253146Stheraven return as_float_helper<long double>( func, s, idx, strtold ); 224253146Stheraven} 225253146Stheraven 226253146Stheraventemplate<> 227253146Stheraveninline 228253146Stheravenfloat 229253146Stheravenas_float( const string& func, const wstring& s, size_t* idx ) 230253146Stheraven{ 231253146Stheraven return as_float_helper<float>( func, s, idx, wcstof ); 232253146Stheraven} 233253146Stheraven 234253146Stheraventemplate<> 235253146Stheraveninline 236253146Stheravendouble 237253146Stheravenas_float( const string& func, const wstring& s, size_t* idx ) 238253146Stheraven{ 239253146Stheraven return as_float_helper<double>( func, s, idx, wcstod ); 240253146Stheraven} 241253146Stheraven 242253146Stheraventemplate<> 243253146Stheraveninline 244253146Stheravenlong double 245253146Stheravenas_float( const string& func, const wstring& s, size_t* idx ) 246253146Stheraven{ 247253146Stheraven return as_float_helper<long double>( func, s, idx, wcstold ); 248253146Stheraven} 249253146Stheraven 250253146Stheraven} // unnamed namespace 251253146Stheraven 252253146Stheravenint 253253146Stheravenstoi(const string& str, size_t* idx, int base) 254253146Stheraven{ 255253146Stheraven return as_integer<int>( "stoi", str, idx, base ); 256253146Stheraven} 257253146Stheraven 258253146Stheravenint 259253146Stheravenstoi(const wstring& str, size_t* idx, int base) 260253146Stheraven{ 261253146Stheraven return as_integer<int>( "stoi", str, idx, base ); 262253146Stheraven} 263253146Stheraven 264227825Stheravenlong 265253146Stheravenstol(const string& str, size_t* idx, int base) 266253146Stheraven{ 267253146Stheraven return as_integer<long>( "stol", str, idx, base ); 268253146Stheraven} 269253146Stheraven 270253146Stheravenlong 271227825Stheravenstol(const wstring& str, size_t* idx, int base) 272227825Stheraven{ 273253146Stheraven return as_integer<long>( "stol", str, idx, base ); 274227825Stheraven} 275227825Stheraven 276227825Stheravenunsigned long 277227825Stheravenstoul(const string& str, size_t* idx, int base) 278227825Stheraven{ 279253146Stheraven return as_integer<unsigned long>( "stoul", str, idx, base ); 280227825Stheraven} 281227825Stheraven 282227825Stheravenunsigned long 283227825Stheravenstoul(const wstring& str, size_t* idx, int base) 284227825Stheraven{ 285253146Stheraven return as_integer<unsigned long>( "stoul", str, idx, base ); 286227825Stheraven} 287227825Stheraven 288227825Stheravenlong long 289227825Stheravenstoll(const string& str, size_t* idx, int base) 290227825Stheraven{ 291253146Stheraven return as_integer<long long>( "stoll", str, idx, base ); 292227825Stheraven} 293227825Stheraven 294227825Stheravenlong long 295227825Stheravenstoll(const wstring& str, size_t* idx, int base) 296227825Stheraven{ 297253146Stheraven return as_integer<long long>( "stoll", str, idx, base ); 298227825Stheraven} 299227825Stheraven 300227825Stheravenunsigned long long 301227825Stheravenstoull(const string& str, size_t* idx, int base) 302227825Stheraven{ 303253146Stheraven return as_integer<unsigned long long>( "stoull", str, idx, base ); 304227825Stheraven} 305227825Stheraven 306227825Stheravenunsigned long long 307227825Stheravenstoull(const wstring& str, size_t* idx, int base) 308227825Stheraven{ 309253146Stheraven return as_integer<unsigned long long>( "stoull", str, idx, base ); 310227825Stheraven} 311227825Stheraven 312227825Stheravenfloat 313227825Stheravenstof(const string& str, size_t* idx) 314227825Stheraven{ 315253146Stheraven return as_float<float>( "stof", str, idx ); 316227825Stheraven} 317227825Stheraven 318227825Stheravenfloat 319227825Stheravenstof(const wstring& str, size_t* idx) 320227825Stheraven{ 321253146Stheraven return as_float<float>( "stof", str, idx ); 322227825Stheraven} 323227825Stheraven 324227825Stheravendouble 325227825Stheravenstod(const string& str, size_t* idx) 326227825Stheraven{ 327253146Stheraven return as_float<double>( "stod", str, idx ); 328227825Stheraven} 329227825Stheraven 330227825Stheravendouble 331227825Stheravenstod(const wstring& str, size_t* idx) 332227825Stheraven{ 333253146Stheraven return as_float<double>( "stod", str, idx ); 334227825Stheraven} 335227825Stheraven 336227825Stheravenlong double 337227825Stheravenstold(const string& str, size_t* idx) 338227825Stheraven{ 339253146Stheraven return as_float<long double>( "stold", str, idx ); 340227825Stheraven} 341227825Stheraven 342227825Stheravenlong double 343227825Stheravenstold(const wstring& str, size_t* idx) 344227825Stheraven{ 345253146Stheraven return as_float<long double>( "stold", str, idx ); 346227825Stheraven} 347227825Stheraven 348253146Stheraven// to_string 349253146Stheraven 350253146Stheravennamespace 351227825Stheraven{ 352253146Stheraven 353253146Stheraven// as_string 354253146Stheraven 355253146Stheraventemplate<typename S, typename P, typename V > 356253146Stheraveninline 357253146StheravenS 358253146Stheravenas_string(P sprintf_like, S s, const typename S::value_type* fmt, V a) 359253146Stheraven{ 360253146Stheraven typedef typename S::size_type size_type; 361253146Stheraven size_type available = s.size(); 362227825Stheraven while (true) 363227825Stheraven { 364253146Stheraven int status = sprintf_like(&s[0], available + 1, fmt, a); 365253146Stheraven if ( status >= 0 ) 366227825Stheraven { 367253146Stheraven size_type used = static_cast<size_type>(status); 368253146Stheraven if ( used <= available ) 369253146Stheraven { 370253146Stheraven s.resize( used ); 371253146Stheraven break; 372253146Stheraven } 373253146Stheraven available = used; // Assume this is advice of how much space we need. 374227825Stheraven } 375253146Stheraven else 376253146Stheraven available = available * 2 + 1; 377253146Stheraven s.resize(available); 378227825Stheraven } 379227825Stheraven return s; 380227825Stheraven} 381227825Stheraven 382253146Stheraventemplate <class S, class V, bool = is_floating_point<V>::value> 383253146Stheravenstruct initial_string; 384253146Stheraven 385253146Stheraventemplate <class V, bool b> 386253146Stheravenstruct initial_string<string, V, b> 387227825Stheraven{ 388253146Stheraven string 389253146Stheraven operator()() const 390227825Stheraven { 391253146Stheraven string s; 392253146Stheraven s.resize(s.capacity()); 393253146Stheraven return s; 394227825Stheraven } 395253146Stheraven}; 396227825Stheraven 397253146Stheraventemplate <class V> 398253146Stheravenstruct initial_string<wstring, V, false> 399227825Stheraven{ 400253146Stheraven wstring 401253146Stheraven operator()() const 402227825Stheraven { 403253146Stheraven const size_t n = (numeric_limits<unsigned long long>::digits / 3) 404253146Stheraven + ((numeric_limits<unsigned long long>::digits % 3) != 0) 405253146Stheraven + 1; 406253146Stheraven wstring s(n, wchar_t()); 407253146Stheraven s.resize(s.capacity()); 408253146Stheraven return s; 409227825Stheraven } 410253146Stheraven}; 411227825Stheraven 412253146Stheraventemplate <class V> 413253146Stheravenstruct initial_string<wstring, V, true> 414227825Stheraven{ 415253146Stheraven wstring 416253146Stheraven operator()() const 417227825Stheraven { 418253146Stheraven wstring s(20, wchar_t()); 419253146Stheraven s.resize(s.capacity()); 420253146Stheraven return s; 421227825Stheraven } 422253146Stheraven}; 423253146Stheraven 424253146Stheraventypedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...); 425253146Stheraven 426253146Stheraveninline 427253146Stheravenwide_printf 428253146Stheravenget_swprintf() 429253146Stheraven{ 430261272Sdim#ifndef _LIBCPP_MSVCRT 431253146Stheraven return swprintf; 432253146Stheraven#else 433253146Stheraven return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(swprintf); 434253146Stheraven#endif 435227825Stheraven} 436227825Stheraven 437253146Stheraven} // unnamed namespace 438253146Stheraven 439253146Stheravenstring to_string(int val) 440253146Stheraven{ 441253146Stheraven return as_string(snprintf, initial_string<string, int>()(), "%d", val); 442253146Stheraven} 443253146Stheraven 444253146Stheravenstring to_string(unsigned val) 445253146Stheraven{ 446253146Stheraven return as_string(snprintf, initial_string<string, unsigned>()(), "%u", val); 447253146Stheraven} 448253146Stheraven 449253146Stheravenstring to_string(long val) 450253146Stheraven{ 451253146Stheraven return as_string(snprintf, initial_string<string, long>()(), "%ld", val); 452253146Stheraven} 453253146Stheraven 454253146Stheravenstring to_string(unsigned long val) 455253146Stheraven{ 456253146Stheraven return as_string(snprintf, initial_string<string, unsigned long>()(), "%lu", val); 457253146Stheraven} 458253146Stheraven 459227825Stheravenstring to_string(long long val) 460227825Stheraven{ 461253146Stheraven return as_string(snprintf, initial_string<string, long long>()(), "%lld", val); 462227825Stheraven} 463227825Stheraven 464227825Stheravenstring to_string(unsigned long long val) 465227825Stheraven{ 466253146Stheraven return as_string(snprintf, initial_string<string, unsigned long long>()(), "%llu", val); 467227825Stheraven} 468227825Stheraven 469227825Stheravenstring to_string(float val) 470227825Stheraven{ 471253146Stheraven return as_string(snprintf, initial_string<string, float>()(), "%f", val); 472227825Stheraven} 473227825Stheraven 474227825Stheravenstring to_string(double val) 475227825Stheraven{ 476253146Stheraven return as_string(snprintf, initial_string<string, double>()(), "%f", val); 477227825Stheraven} 478227825Stheraven 479227825Stheravenstring to_string(long double val) 480227825Stheraven{ 481253146Stheraven return as_string(snprintf, initial_string<string, long double>()(), "%Lf", val); 482227825Stheraven} 483227825Stheraven 484227825Stheravenwstring to_wstring(int val) 485227825Stheraven{ 486253146Stheraven return as_string(get_swprintf(), initial_string<wstring, int>()(), L"%d", val); 487227825Stheraven} 488227825Stheraven 489227825Stheravenwstring to_wstring(unsigned val) 490227825Stheraven{ 491253146Stheraven return as_string(get_swprintf(), initial_string<wstring, unsigned>()(), L"%u", val); 492227825Stheraven} 493227825Stheraven 494227825Stheravenwstring to_wstring(long val) 495227825Stheraven{ 496253146Stheraven return as_string(get_swprintf(), initial_string<wstring, long>()(), L"%ld", val); 497227825Stheraven} 498227825Stheraven 499227825Stheravenwstring to_wstring(unsigned long val) 500227825Stheraven{ 501253146Stheraven return as_string(get_swprintf(), initial_string<wstring, unsigned long>()(), L"%lu", val); 502227825Stheraven} 503227825Stheraven 504227825Stheravenwstring to_wstring(long long val) 505227825Stheraven{ 506253146Stheraven return as_string(get_swprintf(), initial_string<wstring, long long>()(), L"%lld", val); 507227825Stheraven} 508227825Stheraven 509227825Stheravenwstring to_wstring(unsigned long long val) 510227825Stheraven{ 511253146Stheraven return as_string(get_swprintf(), initial_string<wstring, unsigned long long>()(), L"%llu", val); 512227825Stheraven} 513227825Stheraven 514227825Stheravenwstring to_wstring(float val) 515227825Stheraven{ 516253146Stheraven return as_string(get_swprintf(), initial_string<wstring, float>()(), L"%f", val); 517227825Stheraven} 518227825Stheraven 519227825Stheravenwstring to_wstring(double val) 520227825Stheraven{ 521253146Stheraven return as_string(get_swprintf(), initial_string<wstring, double>()(), L"%f", val); 522227825Stheraven} 523227825Stheraven 524227825Stheravenwstring to_wstring(long double val) 525227825Stheraven{ 526253146Stheraven return as_string(get_swprintf(), initial_string<wstring, long double>()(), L"%Lf", val); 527227825Stheraven} 528227825Stheraven_LIBCPP_END_NAMESPACE_STD 529