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 22 template class __basic_string_common<true>; 23 24 template class basic_string<char>; 25 template class basic_string<wchar_t>; 26 27 template 28 string 29 operator+<char, char_traits<char>, allocator<char> >(char const*, string const&); 30 31 namespace 32 { 33 34 template<typename T> 35 inline 36 void throw_helper( const string& msg ) 37 { 38 #ifndef _LIBCPP_NO_EXCEPTIONS 39 throw T( msg ); 40 #else 41 abort(); 42 #endif 43 } 44 45 inline 46 void throw_from_string_out_of_range( const string& func ) 47 { 48 throw_helper<out_of_range>(func + ": out of range"); 49 } 50 51 inline 52 void throw_from_string_invalid_arg( const string& func ) 53 { 54 throw_helper<invalid_argument>(func + ": no conversion"); 55 } 56 57 // as_integer 58 59 template<typename V, typename S, typename F> 60 inline 61 V 62 as_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 79 template<typename V, typename S> 80 inline 81 V 82 as_integer(const string& func, const S& s, size_t* idx, int base); 83 84 // string 85 template<> 86 inline 87 int 88 as_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 97 template<> 98 inline 99 long 100 as_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 105 template<> 106 inline 107 unsigned long 108 as_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 113 template<> 114 inline 115 long long 116 as_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 121 template<> 122 inline 123 unsigned long long 124 as_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 130 template<> 131 inline 132 int 133 as_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 142 template<> 143 inline 144 long 145 as_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 150 template<> 151 inline 152 unsigned long 153 as_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 158 template<> 159 inline 160 long long 161 as_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 166 template<> 167 inline 168 unsigned long long 169 as_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 176 template<typename V, typename S, typename F> 177 inline 178 V 179 as_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 196 template<typename V, typename S> 197 inline 198 V as_float( const string& func, const S& s, size_t* idx = nullptr ); 199 200 template<> 201 inline 202 float 203 as_float( const string& func, const string& s, size_t* idx ) 204 { 205 return as_float_helper<float>( func, s, idx, strtof ); 206 } 207 208 template<> 209 inline 210 double 211 as_float(const string& func, const string& s, size_t* idx ) 212 { 213 return as_float_helper<double>( func, s, idx, strtod ); 214 } 215 216 template<> 217 inline 218 long double 219 as_float( const string& func, const string& s, size_t* idx ) 220 { 221 return as_float_helper<long double>( func, s, idx, strtold ); 222 } 223 224 template<> 225 inline 226 float 227 as_float( const string& func, const wstring& s, size_t* idx ) 228 { 229 return as_float_helper<float>( func, s, idx, wcstof ); 230 } 231 232 template<> 233 inline 234 double 235 as_float( const string& func, const wstring& s, size_t* idx ) 236 { 237 return as_float_helper<double>( func, s, idx, wcstod ); 238 } 239 240 template<> 241 inline 242 long double 243 as_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 250 int 251 stoi(const string& str, size_t* idx, int base) 252 { 253 return as_integer<int>( "stoi", str, idx, base ); 254 } 255 256 int 257 stoi(const wstring& str, size_t* idx, int base) 258 { 259 return as_integer<int>( "stoi", str, idx, base ); 260 } 261 262 long 263 stol(const string& str, size_t* idx, int base) 264 { 265 return as_integer<long>( "stol", str, idx, base ); 266 } 267 268 long 269 stol(const wstring& str, size_t* idx, int base) 270 { 271 return as_integer<long>( "stol", str, idx, base ); 272 } 273 274 unsigned long 275 stoul(const string& str, size_t* idx, int base) 276 { 277 return as_integer<unsigned long>( "stoul", str, idx, base ); 278 } 279 280 unsigned long 281 stoul(const wstring& str, size_t* idx, int base) 282 { 283 return as_integer<unsigned long>( "stoul", str, idx, base ); 284 } 285 286 long long 287 stoll(const string& str, size_t* idx, int base) 288 { 289 return as_integer<long long>( "stoll", str, idx, base ); 290 } 291 292 long long 293 stoll(const wstring& str, size_t* idx, int base) 294 { 295 return as_integer<long long>( "stoll", str, idx, base ); 296 } 297 298 unsigned long long 299 stoull(const string& str, size_t* idx, int base) 300 { 301 return as_integer<unsigned long long>( "stoull", str, idx, base ); 302 } 303 304 unsigned long long 305 stoull(const wstring& str, size_t* idx, int base) 306 { 307 return as_integer<unsigned long long>( "stoull", str, idx, base ); 308 } 309 310 float 311 stof(const string& str, size_t* idx) 312 { 313 return as_float<float>( "stof", str, idx ); 314 } 315 316 float 317 stof(const wstring& str, size_t* idx) 318 { 319 return as_float<float>( "stof", str, idx ); 320 } 321 322 double 323 stod(const string& str, size_t* idx) 324 { 325 return as_float<double>( "stod", str, idx ); 326 } 327 328 double 329 stod(const wstring& str, size_t* idx) 330 { 331 return as_float<double>( "stod", str, idx ); 332 } 333 334 long double 335 stold(const string& str, size_t* idx) 336 { 337 return as_float<long double>( "stold", str, idx ); 338 } 339 340 long double 341 stold(const wstring& str, size_t* idx) 342 { 343 return as_float<long double>( "stold", str, idx ); 344 } 345 346 // to_string 347 348 namespace 349 { 350 351 // as_string 352 353 template<typename S, typename P, typename V > 354 inline 355 S 356 as_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 380 template <class S, class V, bool = is_floating_point<V>::value> 381 struct initial_string; 382 383 template <class V, bool b> 384 struct 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 395 template <class V> 396 struct 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 410 template <class V> 411 struct 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 422 typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...); 423 424 inline 425 wide_printf 426 get_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 437 string to_string(int val) 438 { 439 return as_string(snprintf, initial_string<string, int>()(), "%d", val); 440 } 441 442 string to_string(unsigned val) 443 { 444 return as_string(snprintf, initial_string<string, unsigned>()(), "%u", val); 445 } 446 447 string to_string(long val) 448 { 449 return as_string(snprintf, initial_string<string, long>()(), "%ld", val); 450 } 451 452 string to_string(unsigned long val) 453 { 454 return as_string(snprintf, initial_string<string, unsigned long>()(), "%lu", val); 455 } 456 457 string to_string(long long val) 458 { 459 return as_string(snprintf, initial_string<string, long long>()(), "%lld", val); 460 } 461 462 string to_string(unsigned long long val) 463 { 464 return as_string(snprintf, initial_string<string, unsigned long long>()(), "%llu", val); 465 } 466 467 string to_string(float val) 468 { 469 return as_string(snprintf, initial_string<string, float>()(), "%f", val); 470 } 471 472 string to_string(double val) 473 { 474 return as_string(snprintf, initial_string<string, double>()(), "%f", val); 475 } 476 477 string to_string(long double val) 478 { 479 return as_string(snprintf, initial_string<string, long double>()(), "%Lf", val); 480 } 481 482 wstring to_wstring(int val) 483 { 484 return as_string(get_swprintf(), initial_string<wstring, int>()(), L"%d", val); 485 } 486 487 wstring to_wstring(unsigned val) 488 { 489 return as_string(get_swprintf(), initial_string<wstring, unsigned>()(), L"%u", val); 490 } 491 492 wstring to_wstring(long val) 493 { 494 return as_string(get_swprintf(), initial_string<wstring, long>()(), L"%ld", val); 495 } 496 497 wstring to_wstring(unsigned long val) 498 { 499 return as_string(get_swprintf(), initial_string<wstring, unsigned long>()(), L"%lu", val); 500 } 501 502 wstring to_wstring(long long val) 503 { 504 return as_string(get_swprintf(), initial_string<wstring, long long>()(), L"%lld", val); 505 } 506 507 wstring to_wstring(unsigned long long val) 508 { 509 return as_string(get_swprintf(), initial_string<wstring, unsigned long long>()(), L"%llu", val); 510 } 511 512 wstring to_wstring(float val) 513 { 514 return as_string(get_swprintf(), initial_string<wstring, float>()(), L"%f", val); 515 } 516 517 wstring to_wstring(double val) 518 { 519 return as_string(get_swprintf(), initial_string<wstring, double>()(), L"%f", val); 520 } 521 522 wstring 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