string.cpp revision 341825
1171095Ssam//===------------------------- string.cpp ---------------------------------===// 2171095Ssam// 3171095Ssam// The LLVM Compiler Infrastructure 4171095Ssam// 5171095Ssam// This file is dual licensed under the MIT and the University of Illinois Open 6171095Ssam// Source Licenses. See LICENSE.TXT for details. 7171095Ssam// 8171095Ssam//===----------------------------------------------------------------------===// 9171095Ssam 10171095Ssam#include "string" 11171095Ssam#include "cstdlib" 12171095Ssam#include "cwchar" 13171095Ssam#include "cerrno" 14171095Ssam#include "limits" 15171095Ssam#include "stdexcept" 16171095Ssam#include <stdio.h> 17171095Ssam 18171095Ssam_LIBCPP_BEGIN_NAMESPACE_STD 19171095Ssam 20171095Ssamtemplate class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common<true>; 21171095Ssam 22171095Ssamtemplate class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<char>; 23171095Ssamtemplate class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<wchar_t>; 24171095Ssam 25171095Ssamtemplate 26171095Ssam string 27171095Ssam operator+<char, char_traits<char>, allocator<char> >(char const*, string const&); 28171095Ssam 29171095Ssamnamespace 30171095Ssam{ 31171095Ssam 32171095Ssamtemplate<typename T> 33171095Ssaminline 34173139Srwatsonvoid throw_helper( const string& msg ) 35173139Srwatson{ 36173139Srwatson#ifndef _LIBCPP_NO_EXCEPTIONS 37173139Srwatson throw T( msg ); 38173139Srwatson#else 39173139Srwatson fprintf(stderr, "%s\n", msg.c_str()); 40173139Srwatson _VSTD::abort(); 41171095Ssam#endif 42171095Ssam} 43171095Ssam 44171095Ssaminline 45171095Ssamvoid throw_from_string_out_of_range( const string& func ) 46171095Ssam{ 47171095Ssam throw_helper<out_of_range>(func + ": out of range"); 48171095Ssam} 49173139Srwatson 50173139Srwatsoninline 51173139Srwatsonvoid throw_from_string_invalid_arg( const string& func ) 52173139Srwatson{ 53171095Ssam throw_helper<invalid_argument>(func + ": no conversion"); 54171095Ssam} 55171095Ssam 56171095Ssam// as_integer 57171095Ssam 58171095Ssamtemplate<typename V, typename S, typename F> 59171095Ssaminline 60171095SsamV 61171095Ssamas_integer_helper(const string& func, const S& str, size_t* idx, int base, F f) 62171095Ssam{ 63171095Ssam typename S::value_type* ptr = nullptr; 64171095Ssam const typename S::value_type* const p = str.c_str(); 65171095Ssam typename remove_reference<decltype(errno)>::type errno_save = errno; 66171095Ssam errno = 0; 67171095Ssam V r = f(p, &ptr, base); 68171095Ssam swap(errno, errno_save); 69171095Ssam if (errno_save == ERANGE) 70171095Ssam throw_from_string_out_of_range(func); 71171095Ssam if (ptr == p) 72171095Ssam throw_from_string_invalid_arg(func); 73171095Ssam if (idx) 74171095Ssam *idx = static_cast<size_t>(ptr - p); 75171095Ssam return r; 76171095Ssam} 77171095Ssam 78171095Ssamtemplate<typename V, typename S> 79171095Ssaminline 80173139SrwatsonV 81173139Srwatsonas_integer(const string& func, const S& s, size_t* idx, int base); 82173139Srwatson 83173139Srwatson// string 84173139Srwatsontemplate<> 85173139Srwatsoninline 86173139Srwatsonint 87173139Srwatsonas_integer(const string& func, const string& s, size_t* idx, int base ) 88171095Ssam{ 89171095Ssam // Use long as no Standard string to integer exists. 90171095Ssam long r = as_integer_helper<long>( func, s, idx, base, strtol ); 91171095Ssam if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) 92171095Ssam throw_from_string_out_of_range(func); 93171095Ssam return static_cast<int>(r); 94173139Srwatson} 95173139Srwatson 96171095Ssamtemplate<> 97171095Ssaminline 98171095Ssamlong 99171095Ssamas_integer(const string& func, const string& s, size_t* idx, int base ) 100171095Ssam{ 101171095Ssam return as_integer_helper<long>( func, s, idx, base, strtol ); 102171095Ssam} 103171095Ssam 104173139Srwatsontemplate<> 105173139Srwatsoninline 106173139Srwatsonunsigned long 107173139Srwatsonas_integer( const string& func, const string& s, size_t* idx, int base ) 108173139Srwatson{ 109173139Srwatson return as_integer_helper<unsigned long>( func, s, idx, base, strtoul ); 110173139Srwatson} 111171095Ssam 112171095Ssamtemplate<> 113171095Ssaminline 114171095Ssamlong long 115171095Ssamas_integer( const string& func, const string& s, size_t* idx, int base ) 116171095Ssam{ 117171095Ssam return as_integer_helper<long long>( func, s, idx, base, strtoll ); 118171095Ssam} 119171095Ssam 120171095Ssamtemplate<> 121173139Srwatsoninline 122173139Srwatsonunsigned long long 123173139Srwatsonas_integer( const string& func, const string& s, size_t* idx, int base ) 124173139Srwatson{ 125171095Ssam return as_integer_helper<unsigned long long>( func, s, idx, base, strtoull ); 126171095Ssam} 127171095Ssam 128171095Ssam// wstring 129173139Srwatsontemplate<> 130173139Srwatsoninline 131173139Srwatsonint 132173139Srwatsonas_integer( const string& func, const wstring& s, size_t* idx, int base ) 133173139Srwatson{ 134173139Srwatson // Use long as no Stantard string to integer exists. 135171095Ssam long r = as_integer_helper<long>( func, s, idx, base, wcstol ); 136173139Srwatson if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) 137173139Srwatson throw_from_string_out_of_range(func); 138171095Ssam return static_cast<int>(r); 139173139Srwatson} 140173139Srwatson 141173139Srwatsontemplate<> 142173139Srwatsoninline 143173139Srwatsonlong 144173139Srwatsonas_integer( const string& func, const wstring& s, size_t* idx, int base ) 145171095Ssam{ 146173139Srwatson return as_integer_helper<long>( func, s, idx, base, wcstol ); 147173139Srwatson} 148171095Ssam 149171095Ssamtemplate<> 150171095Ssaminline 151171095Ssamunsigned long 152171095Ssamas_integer( const string& func, const wstring& s, size_t* idx, int base ) 153171095Ssam{ 154171095Ssam return as_integer_helper<unsigned long>( func, s, idx, base, wcstoul ); 155171095Ssam} 156171095Ssam 157171095Ssamtemplate<> 158171095Ssaminline 159171095Ssamlong long 160171095Ssamas_integer( const string& func, const wstring& s, size_t* idx, int base ) 161171095Ssam{ 162171095Ssam return as_integer_helper<long long>( func, s, idx, base, wcstoll ); 163171095Ssam} 164171095Ssam 165171095Ssamtemplate<> 166171095Ssaminline 167171095Ssamunsigned long long 168171095Ssamas_integer( const string& func, const wstring& s, size_t* idx, int base ) 169171095Ssam{ 170171095Ssam return as_integer_helper<unsigned long long>( func, s, idx, base, wcstoull ); 171171095Ssam} 172171095Ssam 173171095Ssam// as_float 174171095Ssam 175173139Srwatsontemplate<typename V, typename S, typename F> 176171095Ssaminline 177171095SsamV 178173139Srwatsonas_float_helper(const string& func, const S& str, size_t* idx, F f ) 179171095Ssam{ 180171095Ssam typename S::value_type* ptr = nullptr; 181171095Ssam const typename S::value_type* const p = str.c_str(); 182173139Srwatson typename remove_reference<decltype(errno)>::type errno_save = errno; 183171095Ssam errno = 0; 184171095Ssam V r = f(p, &ptr); 185173139Srwatson swap(errno, errno_save); 186173139Srwatson if (errno_save == ERANGE) 187171095Ssam throw_from_string_out_of_range(func); 188171095Ssam if (ptr == p) 189171095Ssam throw_from_string_invalid_arg(func); 190171095Ssam if (idx) 191173139Srwatson *idx = static_cast<size_t>(ptr - p); 192171095Ssam return r; 193171095Ssam} 194171095Ssam 195171095Ssamtemplate<typename V, typename S> 196171095Ssaminline 197171095SsamV as_float( const string& func, const S& s, size_t* idx = nullptr ); 198173139Srwatson 199171095Ssamtemplate<> 200171095Ssaminline 201171095Ssamfloat 202171095Ssamas_float( const string& func, const string& s, size_t* idx ) 203173139Srwatson{ 204171095Ssam return as_float_helper<float>( func, s, idx, strtof ); 205171095Ssam} 206173139Srwatson 207171095Ssamtemplate<> 208171095Ssaminline 209171095Ssamdouble 210171095Ssamas_float(const string& func, const string& s, size_t* idx ) 211171095Ssam{ 212173139Srwatson return as_float_helper<double>( func, s, idx, strtod ); 213173139Srwatson} 214173139Srwatson 215171095Ssamtemplate<> 216171095Ssaminline 217171095Ssamlong double 218171095Ssamas_float( const string& func, const string& s, size_t* idx ) 219171095Ssam{ 220171095Ssam return as_float_helper<long double>( func, s, idx, strtold ); 221171095Ssam} 222171095Ssam 223171095Ssamtemplate<> 224171095Ssaminline 225171095Ssamfloat 226171095Ssamas_float( const string& func, const wstring& s, size_t* idx ) 227171095Ssam{ 228171095Ssam return as_float_helper<float>( func, s, idx, wcstof ); 229171095Ssam} 230171095Ssam 231171095Ssamtemplate<> 232171095Ssaminline 233171095Ssamdouble 234173139Srwatsonas_float( const string& func, const wstring& s, size_t* idx ) 235173139Srwatson{ 236171095Ssam return as_float_helper<double>( func, s, idx, wcstod ); 237171095Ssam} 238171095Ssam 239171095Ssamtemplate<> 240173139Srwatsoninline 241171095Ssamlong double 242171095Ssamas_float( const string& func, const wstring& s, size_t* idx ) 243171095Ssam{ 244173139Srwatson return as_float_helper<long double>( func, s, idx, wcstold ); 245173139Srwatson} 246171095Ssam 247171095Ssam} // unnamed namespace 248171095Ssam 249171095Ssamint 250171095Ssamstoi(const string& str, size_t* idx, int base) 251171095Ssam{ 252171095Ssam return as_integer<int>( "stoi", str, idx, base ); 253171095Ssam} 254171095Ssam 255173139Srwatsonint 256171095Ssamstoi(const wstring& str, size_t* idx, int base) 257171095Ssam{ 258173139Srwatson return as_integer<int>( "stoi", str, idx, base ); 259173139Srwatson} 260173139Srwatson 261173139Srwatsonlong 262173139Srwatsonstol(const string& str, size_t* idx, int base) 263173139Srwatson{ 264173139Srwatson return as_integer<long>( "stol", str, idx, base ); 265173139Srwatson} 266171095Ssam 267173139Srwatsonlong 268171095Ssamstol(const wstring& str, size_t* idx, int base) 269171095Ssam{ 270171095Ssam return as_integer<long>( "stol", str, idx, base ); 271173139Srwatson} 272173139Srwatson 273173139Srwatsonunsigned long 274171095Ssamstoul(const string& str, size_t* idx, int base) 275173139Srwatson{ 276173139Srwatson return as_integer<unsigned long>( "stoul", str, idx, base ); 277171095Ssam} 278171095Ssam 279173139Srwatsonunsigned long 280173139Srwatsonstoul(const wstring& str, size_t* idx, int base) 281173139Srwatson{ 282173139Srwatson return as_integer<unsigned long>( "stoul", str, idx, base ); 283173139Srwatson} 284173139Srwatson 285173139Srwatsonlong long 286171095Ssamstoll(const string& str, size_t* idx, int base) 287171095Ssam{ 288171095Ssam return as_integer<long long>( "stoll", str, idx, base ); 289173139Srwatson} 290173139Srwatson 291171095Ssamlong long 292171095Ssamstoll(const wstring& str, size_t* idx, int base) 293171095Ssam{ 294171095Ssam return as_integer<long long>( "stoll", str, idx, base ); 295171095Ssam} 296173139Srwatson 297173139Srwatsonunsigned long long 298171095Ssamstoull(const string& str, size_t* idx, int base) 299171095Ssam{ 300171095Ssam return as_integer<unsigned long long>( "stoull", str, idx, base ); 301173139Srwatson} 302173139Srwatson 303173139Srwatsonunsigned long long 304173139Srwatsonstoull(const wstring& str, size_t* idx, int base) 305171095Ssam{ 306171095Ssam return as_integer<unsigned long long>( "stoull", str, idx, base ); 307171095Ssam} 308171095Ssam 309173139Srwatsonfloat 310173139Srwatsonstof(const string& str, size_t* idx) 311171095Ssam{ 312171095Ssam return as_float<float>( "stof", str, idx ); 313171095Ssam} 314171095Ssam 315171095Ssamfloat 316171095Ssamstof(const wstring& str, size_t* idx) 317171095Ssam{ 318171095Ssam return as_float<float>( "stof", str, idx ); 319171095Ssam} 320171095Ssam 321171095Ssamdouble 322171095Ssamstod(const string& str, size_t* idx) 323171095Ssam{ 324173139Srwatson return as_float<double>( "stod", str, idx ); 325171095Ssam} 326171095Ssam 327171095Ssamdouble 328171095Ssamstod(const wstring& str, size_t* idx) 329171095Ssam{ 330171095Ssam return as_float<double>( "stod", str, idx ); 331171095Ssam} 332171095Ssam 333171095Ssamlong double 334171095Ssamstold(const string& str, size_t* idx) 335171095Ssam{ 336173139Srwatson return as_float<long double>( "stold", str, idx ); 337171095Ssam} 338173139Srwatson 339173139Srwatsonlong double 340171095Ssamstold(const wstring& str, size_t* idx) 341171095Ssam{ 342171095Ssam return as_float<long double>( "stold", str, idx ); 343171095Ssam} 344171095Ssam 345171095Ssam// to_string 346171095Ssam 347171095Ssamnamespace 348171095Ssam{ 349171095Ssam 350171095Ssam// as_string 351171095Ssam 352171095Ssamtemplate<typename S, typename P, typename V > 353171095Ssaminline 354171095SsamS 355171095Ssamas_string(P sprintf_like, S s, const typename S::value_type* fmt, V a) 356171095Ssam{ 357171095Ssam typedef typename S::size_type size_type; 358171095Ssam size_type available = s.size(); 359171095Ssam while (true) 360171095Ssam { 361171095Ssam int status = sprintf_like(&s[0], available + 1, fmt, a); 362171095Ssam if ( status >= 0 ) 363171095Ssam { 364171095Ssam size_type used = static_cast<size_type>(status); 365171095Ssam if ( used <= available ) 366171095Ssam { 367171095Ssam s.resize( used ); 368171095Ssam break; 369171095Ssam } 370171095Ssam available = used; // Assume this is advice of how much space we need. 371171095Ssam } 372171095Ssam else 373171095Ssam available = available * 2 + 1; 374171095Ssam s.resize(available); 375171095Ssam } 376171095Ssam return s; 377171095Ssam} 378173139Srwatson 379173139Srwatsontemplate <class S, class V, bool = is_floating_point<V>::value> 380173139Srwatsonstruct initial_string; 381173139Srwatson 382173139Srwatsontemplate <class V, bool b> 383171095Ssamstruct initial_string<string, V, b> 384173139Srwatson{ 385173139Srwatson string 386173139Srwatson operator()() const 387173139Srwatson { 388173139Srwatson string s; 389171095Ssam s.resize(s.capacity()); 390171095Ssam return s; 391173139Srwatson } 392173139Srwatson}; 393173139Srwatson 394173139Srwatsontemplate <class V> 395171095Ssamstruct initial_string<wstring, V, false> 396171095Ssam{ 397171095Ssam wstring 398171095Ssam operator()() const 399171095Ssam { 400173139Srwatson const size_t n = (numeric_limits<unsigned long long>::digits / 3) 401173139Srwatson + ((numeric_limits<unsigned long long>::digits % 3) != 0) 402171095Ssam + 1; 403173139Srwatson wstring s(n, wchar_t()); 404173139Srwatson s.resize(s.capacity()); 405173139Srwatson return s; 406173139Srwatson } 407173139Srwatson}; 408173139Srwatson 409173139Srwatsontemplate <class V> 410171095Ssamstruct initial_string<wstring, V, true> 411173139Srwatson{ 412173139Srwatson wstring 413173139Srwatson operator()() const 414173139Srwatson { 415173139Srwatson wstring s(20, wchar_t()); 416173139Srwatson s.resize(s.capacity()); 417173139Srwatson return s; 418173139Srwatson } 419173139Srwatson}; 420173139Srwatson 421173139Srwatsontypedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...); 422173139Srwatson 423173139Srwatsoninline 424173139Srwatsonwide_printf 425173139Srwatsonget_swprintf() 426173139Srwatson{ 427173139Srwatson#ifndef _LIBCPP_MSVCRT 428173139Srwatson return swprintf; 429173139Srwatson#else 430173139Srwatson return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(_snwprintf); 431171095Ssam#endif 432171095Ssam} 433171095Ssam 434171095Ssam} // unnamed namespace 435171095Ssam 436171095Ssamstring to_string(int val) 437171095Ssam{ 438171095Ssam return as_string(snprintf, initial_string<string, int>()(), "%d", val); 439171095Ssam} 440173139Srwatson 441173139Srwatsonstring to_string(unsigned val) 442173139Srwatson{ 443173139Srwatson return as_string(snprintf, initial_string<string, unsigned>()(), "%u", val); 444171095Ssam} 445171095Ssam 446171095Ssamstring to_string(long val) 447171095Ssam{ 448171095Ssam return as_string(snprintf, initial_string<string, long>()(), "%ld", val); 449171095Ssam} 450171095Ssam 451171095Ssamstring to_string(unsigned long val) 452173139Srwatson{ 453173139Srwatson return as_string(snprintf, initial_string<string, unsigned long>()(), "%lu", val); 454173139Srwatson} 455171095Ssam 456171095Ssamstring to_string(long long val) 457171095Ssam{ 458171095Ssam return as_string(snprintf, initial_string<string, long long>()(), "%lld", val); 459171095Ssam} 460171095Ssam 461171095Ssamstring to_string(unsigned long long val) 462173139Srwatson{ 463173139Srwatson return as_string(snprintf, initial_string<string, unsigned long long>()(), "%llu", val); 464171095Ssam} 465173139Srwatson 466173139Srwatsonstring to_string(float val) 467173139Srwatson{ 468173139Srwatson return as_string(snprintf, initial_string<string, float>()(), "%f", val); 469171095Ssam} 470173139Srwatson 471173139Srwatsonstring to_string(double val) 472173139Srwatson{ 473173139Srwatson return as_string(snprintf, initial_string<string, double>()(), "%f", val); 474173139Srwatson} 475173139Srwatson 476173139Srwatsonstring to_string(long double val) 477173139Srwatson{ 478173139Srwatson return as_string(snprintf, initial_string<string, long double>()(), "%Lf", val); 479173139Srwatson} 480173139Srwatson 481171095Ssamwstring to_wstring(int val) 482173139Srwatson{ 483173139Srwatson return as_string(get_swprintf(), initial_string<wstring, int>()(), L"%d", val); 484173139Srwatson} 485173139Srwatson 486171095Ssamwstring to_wstring(unsigned val) 487171095Ssam{ 488171095Ssam return as_string(get_swprintf(), initial_string<wstring, unsigned>()(), L"%u", val); 489171095Ssam} 490171095Ssam 491171095Ssamwstring to_wstring(long val) 492171095Ssam{ 493171095Ssam return as_string(get_swprintf(), initial_string<wstring, long>()(), L"%ld", val); 494171095Ssam} 495173139Srwatson 496171095Ssamwstring to_wstring(unsigned long val) 497171095Ssam{ 498171095Ssam return as_string(get_swprintf(), initial_string<wstring, unsigned long>()(), L"%lu", val); 499171095Ssam} 500171095Ssam 501171095Ssamwstring to_wstring(long long val) 502173139Srwatson{ 503173139Srwatson return as_string(get_swprintf(), initial_string<wstring, long long>()(), L"%lld", val); 504173139Srwatson} 505173139Srwatson 506173139Srwatsonwstring to_wstring(unsigned long long val) 507171095Ssam{ 508173139Srwatson return as_string(get_swprintf(), initial_string<wstring, unsigned long long>()(), L"%llu", val); 509171095Ssam} 510171095Ssam 511173139Srwatsonwstring to_wstring(float val) 512171095Ssam{ 513171095Ssam return as_string(get_swprintf(), initial_string<wstring, float>()(), L"%f", val); 514171095Ssam} 515171095Ssam 516171095Ssamwstring to_wstring(double val) 517171095Ssam{ 518171095Ssam return as_string(get_swprintf(), initial_string<wstring, double>()(), L"%f", val); 519171095Ssam} 520173139Srwatson 521171095Ssamwstring to_wstring(long double val) 522171095Ssam{ 523171095Ssam return as_string(get_swprintf(), initial_string<wstring, long double>()(), L"%Lf", val); 524171095Ssam} 525171095Ssam_LIBCPP_END_NAMESPACE_STD 526173139Srwatson