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