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