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