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