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