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