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