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