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