1 //===----------------------------------------------------------------------===// 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 <__assert> 10 #include <cerrno> 11 #include <charconv> 12 #include <cstdlib> 13 #include <limits> 14 #include <stdexcept> 15 #include <string> 16 17 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 18 # include <cwchar> 19 #endif 20 21 _LIBCPP_BEGIN_NAMESPACE_STD 22 23 #ifndef _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON 24 25 template <bool> 26 struct __basic_string_common; 27 28 // The struct isn't declared anymore in the headers. It's only here for ABI compatibility. 29 template <> 30 struct __basic_string_common<true> { 31 _LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __throw_length_error() const; 32 _LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __throw_out_of_range() const; 33 }; 34 35 void __basic_string_common<true>::__throw_length_error() const { 36 std::__throw_length_error("basic_string"); 37 } 38 void __basic_string_common<true>::__throw_out_of_range() const { 39 std::__throw_out_of_range("basic_string"); 40 } 41 42 #endif // _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON 43 44 #define _LIBCPP_EXTERN_TEMPLATE_DEFINE(...) template __VA_ARGS__; 45 #ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION 46 _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) 47 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 48 _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) 49 # endif 50 #else 51 _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) 52 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 53 _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) 54 # endif 55 #endif 56 #undef _LIBCPP_EXTERN_TEMPLATE_DEFINE 57 58 template string operator+<char, char_traits<char>, allocator<char>>(char const*, string const&); 59 60 namespace 61 { 62 63 inline void throw_from_string_out_of_range(const string& func) { 64 std::__throw_out_of_range((func + ": out of range").c_str()); 65 } 66 67 inline void throw_from_string_invalid_arg(const string& func) { 68 std::__throw_invalid_argument((func + ": no conversion").c_str()); 69 } 70 71 // as_integer 72 73 template<typename V, typename S, typename F> 74 inline V as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f) { 75 typename S::value_type* ptr = nullptr; 76 const typename S::value_type* const p = str.c_str(); 77 __libcpp_remove_reference_t<decltype(errno)> 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 V as_integer(const string& func, const S& s, size_t* idx, int base); 92 93 // string 94 template<> 95 inline int as_integer(const string& func, const string& s, size_t* idx, int base) { 96 // Use long as no Standard string to integer exists. 97 long r = as_integer_helper<long>(func, s, idx, base, strtol); 98 if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) 99 throw_from_string_out_of_range(func); 100 return static_cast<int>(r); 101 } 102 103 template<> 104 inline long as_integer(const string& func, const string& s, size_t* idx, int base) { 105 return as_integer_helper<long>(func, s, idx, base, strtol); 106 } 107 108 template<> 109 inline unsigned long as_integer(const string& func, const string& s, size_t* idx, int base) { 110 return as_integer_helper<unsigned long>(func, s, idx, base, strtoul); 111 } 112 113 template<> 114 inline long long as_integer(const string& func, const string& s, size_t* idx, int base) { 115 return as_integer_helper<long long>(func, s, idx, base, strtoll); 116 } 117 118 template<> 119 inline unsigned long long as_integer(const string& func, const string& s, size_t* idx, int base) { 120 return as_integer_helper<unsigned long long>(func, s, idx, base, strtoull); 121 } 122 123 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 124 // wstring 125 template<> 126 inline int as_integer(const string& func, const wstring& s, size_t* idx, int base) { 127 // Use long as no Stantard string to integer exists. 128 long r = as_integer_helper<long>(func, s, idx, base, wcstol); 129 if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) 130 throw_from_string_out_of_range(func); 131 return static_cast<int>(r); 132 } 133 134 template<> 135 inline long as_integer(const string& func, const wstring& s, size_t* idx, int base) { 136 return as_integer_helper<long>(func, s, idx, base, wcstol); 137 } 138 139 template<> 140 inline 141 unsigned long 142 as_integer(const string& func, const wstring& s, size_t* idx, int base) 143 { 144 return as_integer_helper<unsigned long>(func, s, idx, base, wcstoul); 145 } 146 147 template<> 148 inline long long as_integer(const string& func, const wstring& s, size_t* idx, int base) { 149 return as_integer_helper<long long>(func, s, idx, base, wcstoll); 150 } 151 152 template<> 153 inline unsigned long long as_integer(const string& func, const wstring& s, size_t* idx, int base) { 154 return as_integer_helper<unsigned long long>(func, s, idx, base, wcstoull); 155 } 156 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 157 158 // as_float 159 160 template<typename V, typename S, typename F> 161 inline V as_float_helper(const string& func, const S& str, size_t* idx, F f) { 162 typename S::value_type* ptr = nullptr; 163 const typename S::value_type* const p = str.c_str(); 164 __libcpp_remove_reference_t<decltype(errno)> errno_save = errno; 165 errno = 0; 166 V r = f(p, &ptr); 167 swap(errno, errno_save); 168 if (errno_save == ERANGE) 169 throw_from_string_out_of_range(func); 170 if (ptr == p) 171 throw_from_string_invalid_arg(func); 172 if (idx) 173 *idx = static_cast<size_t>(ptr - p); 174 return r; 175 } 176 177 template<typename V, typename S> 178 inline V as_float(const string& func, const S& s, size_t* idx = nullptr); 179 180 template<> 181 inline float as_float(const string& func, const string& s, size_t* idx) { 182 return as_float_helper<float>(func, s, idx, strtof); 183 } 184 185 template<> 186 inline double as_float(const string& func, const string& s, size_t* idx) { 187 return as_float_helper<double>(func, s, idx, strtod); 188 } 189 190 template<> 191 inline long double as_float(const string& func, const string& s, size_t* idx) { 192 return as_float_helper<long double>(func, s, idx, strtold); 193 } 194 195 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 196 template<> 197 inline float as_float(const string& func, const wstring& s, size_t* idx) { 198 return as_float_helper<float>(func, s, idx, wcstof); 199 } 200 201 template<> 202 inline double as_float(const string& func, const wstring& s, size_t* idx) { 203 return as_float_helper<double>(func, s, idx, wcstod); 204 } 205 206 template<> 207 inline long double as_float(const string& func, const wstring& s, size_t* idx) { 208 return as_float_helper<long double>(func, s, idx, wcstold); 209 } 210 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 211 212 } // unnamed namespace 213 214 int stoi(const string& str, size_t* idx, int base) { 215 return as_integer<int>("stoi", str, idx, base); 216 } 217 218 long stol(const string& str, size_t* idx, int base) { 219 return as_integer<long>("stol", str, idx, base); 220 } 221 222 unsigned long stoul(const string& str, size_t* idx, int base) { 223 return as_integer<unsigned long>("stoul", str, idx, base); 224 } 225 226 long long stoll(const string& str, size_t* idx, int base) { 227 return as_integer<long long>("stoll", str, idx, base); 228 } 229 230 unsigned long long stoull(const string& str, size_t* idx, int base) { 231 return as_integer<unsigned long long>("stoull", str, idx, base); 232 } 233 234 float stof(const string& str, size_t* idx) { 235 return as_float<float>("stof", str, idx); 236 } 237 238 double stod(const string& str, size_t* idx) { 239 return as_float<double>("stod", str, idx); 240 } 241 242 long double stold(const string& str, size_t* idx) { 243 return as_float<long double>("stold", str, idx); 244 } 245 246 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 247 int stoi(const wstring& str, size_t* idx, int base) { 248 return as_integer<int>("stoi", str, idx, base); 249 } 250 251 long stol(const wstring& str, size_t* idx, int base) { 252 return as_integer<long>("stol", str, idx, base); 253 } 254 255 unsigned long stoul(const wstring& str, size_t* idx, int base) { 256 return as_integer<unsigned long>("stoul", str, idx, base); 257 } 258 259 long long stoll(const wstring& str, size_t* idx, int base) { 260 return as_integer<long long>("stoll", str, idx, base); 261 } 262 263 unsigned long long stoull(const wstring& str, size_t* idx, int base) { 264 return as_integer<unsigned long long>("stoull", str, idx, base); 265 } 266 267 float stof(const wstring& str, size_t* idx) { 268 return as_float<float>("stof", str, idx); 269 } 270 271 double stod(const wstring& str, size_t* idx) { 272 return as_float<double>("stod", str, idx); 273 } 274 275 long double stold(const wstring& str, size_t* idx) { 276 return as_float<long double>("stold", str, idx); 277 } 278 #endif // !_LIBCPP_HAS_NO_WIDE_CHARACTERS 279 280 // to_string 281 282 namespace 283 { 284 285 // as_string 286 287 template<typename S, typename P, typename V > 288 inline S as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a) { 289 typedef typename S::size_type size_type; 290 size_type available = s.size(); 291 while (true) { 292 int status = sprintf_like(&s[0], available + 1, fmt, a); 293 if (status >= 0) { 294 size_type used = static_cast<size_type>(status); 295 if (used <= available) { 296 s.resize(used); 297 break; 298 } 299 available = used; // Assume this is advice of how much space we need. 300 } 301 else 302 available = available * 2 + 1; 303 s.resize(available); 304 } 305 return s; 306 } 307 308 template <class S> 309 struct initial_string; 310 311 template <> 312 struct initial_string<string> { 313 string operator()() const { 314 string s; 315 s.resize(s.capacity()); 316 return s; 317 } 318 }; 319 320 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 321 template <> 322 struct initial_string<wstring> { 323 wstring operator()() const { 324 wstring s(20, wchar_t()); 325 s.resize(s.capacity()); 326 return s; 327 } 328 }; 329 330 typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...); 331 332 inline wide_printf get_swprintf() { 333 #ifndef _LIBCPP_MSVCRT 334 return swprintf; 335 #else 336 return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(_snwprintf); 337 #endif 338 } 339 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 340 341 template <typename S, typename V> 342 S i_to_string(V v) { 343 // numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers. 344 // For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented), 345 // so we need +1 here. 346 constexpr size_t bufsize = numeric_limits<V>::digits10 + 2; // +1 for minus, +1 for digits10 347 char buf[bufsize]; 348 const auto res = to_chars(buf, buf + bufsize, v); 349 _LIBCPP_ASSERT_INTERNAL(res.ec == errc(), "bufsize must be large enough to accomodate the value"); 350 return S(buf, res.ptr); 351 } 352 353 } // unnamed namespace 354 355 string to_string (int val) { return i_to_string< string>(val); } 356 string to_string (long val) { return i_to_string< string>(val); } 357 string to_string (long long val) { return i_to_string< string>(val); } 358 string to_string (unsigned val) { return i_to_string< string>(val); } 359 string to_string (unsigned long val) { return i_to_string< string>(val); } 360 string to_string (unsigned long long val) { return i_to_string< string>(val); } 361 362 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 363 wstring to_wstring(int val) { return i_to_string<wstring>(val); } 364 wstring to_wstring(long val) { return i_to_string<wstring>(val); } 365 wstring to_wstring(long long val) { return i_to_string<wstring>(val); } 366 wstring to_wstring(unsigned val) { return i_to_string<wstring>(val); } 367 wstring to_wstring(unsigned long val) { return i_to_string<wstring>(val); } 368 wstring to_wstring(unsigned long long val) { return i_to_string<wstring>(val); } 369 #endif 370 371 string to_string (float val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } 372 string to_string (double val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } 373 string to_string (long double val) { return as_string(snprintf, initial_string< string>()(), "%Lf", val); } 374 375 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 376 wstring to_wstring(float val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } 377 wstring to_wstring(double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } 378 wstring to_wstring(long double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%Lf", val); } 379 #endif 380 381 _LIBCPP_END_NAMESPACE_STD 382