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