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 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common<true>; 22 23 #ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION 24 _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) 25 _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) 26 #else 27 _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) 28 _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) 29 #endif 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> 386 struct initial_string; 387 388 template <> 389 struct initial_string<string> 390 { 391 string 392 operator()() const 393 { 394 string s; 395 s.resize(s.capacity()); 396 return s; 397 } 398 }; 399 400 template <> 401 struct initial_string<wstring> 402 { 403 wstring 404 operator()() const 405 { 406 wstring s(20, wchar_t()); 407 s.resize(s.capacity()); 408 return s; 409 } 410 }; 411 412 typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...); 413 414 inline 415 wide_printf 416 get_swprintf() 417 { 418 #ifndef _LIBCPP_MSVCRT 419 return swprintf; 420 #else 421 return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(_snwprintf); 422 #endif 423 } 424 425 template <typename S, typename V> 426 S i_to_string(const V v) 427 { 428 // numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers. 429 // For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented), 430 // so we need +1 here. 431 constexpr size_t bufsize = numeric_limits<V>::digits10 + 2; // +1 for minus, +1 for digits10 432 char buf[bufsize]; 433 const auto res = to_chars(buf, buf + bufsize, v); 434 _LIBCPP_ASSERT(res.ec == errc(), "bufsize must be large enough to accomodate the value"); 435 return S(buf, res.ptr); 436 } 437 438 } // unnamed namespace 439 440 string to_string (int val) { return i_to_string< string>(val); } 441 string to_string (long val) { return i_to_string< string>(val); } 442 string to_string (long long val) { return i_to_string< string>(val); } 443 string to_string (unsigned val) { return i_to_string< string>(val); } 444 string to_string (unsigned long val) { return i_to_string< string>(val); } 445 string to_string (unsigned long long val) { return i_to_string< string>(val); } 446 447 wstring to_wstring(int val) { return i_to_string<wstring>(val); } 448 wstring to_wstring(long val) { return i_to_string<wstring>(val); } 449 wstring to_wstring(long long val) { return i_to_string<wstring>(val); } 450 wstring to_wstring(unsigned val) { return i_to_string<wstring>(val); } 451 wstring to_wstring(unsigned long val) { return i_to_string<wstring>(val); } 452 wstring to_wstring(unsigned long long val) { return i_to_string<wstring>(val); } 453 454 455 string to_string (float val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } 456 string to_string (double val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } 457 string to_string (long double val) { return as_string(snprintf, initial_string< string>()(), "%Lf", val); } 458 459 wstring to_wstring(float val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } 460 wstring to_wstring(double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } 461 wstring to_wstring(long double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%Lf", val); } 462 463 _LIBCPP_END_NAMESPACE_STD 464