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