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 { std::__throw_length_error("basic_string"); } 36 void __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 54 template string operator+ <char, char_traits<char>, allocator<char>>(char const*, string const&); 55 56 namespace { 57 58 inline void throw_from_string_out_of_range(const string& func) { 59 std::__throw_out_of_range((func + ": out of range").c_str()); 60 } 61 62 inline 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 68 template <typename V, typename S, typename F> 69 inline 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 85 template <typename V, typename S> 86 inline V as_integer(const string& func, const S& s, size_t* idx, int base); 87 88 // string 89 template <> 90 inline 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 98 template <> 99 inline 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 103 template <> 104 inline 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 108 template <> 109 inline 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 113 template <> 114 inline 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 120 template <> 121 inline 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 129 template <> 130 inline 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 134 template <> 135 inline 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 139 template <> 140 inline 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 144 template <> 145 inline 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 152 template <typename V, typename S, typename F> 153 inline 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 169 template <typename V, typename S> 170 inline V as_float(const string& func, const S& s, size_t* idx = nullptr); 171 172 template <> 173 inline float as_float(const string& func, const string& s, size_t* idx) { 174 return as_float_helper<float>(func, s, idx, strtof); 175 } 176 177 template <> 178 inline double as_float(const string& func, const string& s, size_t* idx) { 179 return as_float_helper<double>(func, s, idx, strtod); 180 } 181 182 template <> 183 inline 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 188 template <> 189 inline float as_float(const string& func, const wstring& s, size_t* idx) { 190 return as_float_helper<float>(func, s, idx, wcstof); 191 } 192 193 template <> 194 inline double as_float(const string& func, const wstring& s, size_t* idx) { 195 return as_float_helper<double>(func, s, idx, wcstod); 196 } 197 198 template <> 199 inline 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 206 int stoi(const string& str, size_t* idx, int base) { return as_integer<int>("stoi", str, idx, base); } 207 208 long stol(const string& str, size_t* idx, int base) { return as_integer<long>("stol", str, idx, base); } 209 210 unsigned long stoul(const string& str, size_t* idx, int base) { 211 return as_integer<unsigned long>("stoul", str, idx, base); 212 } 213 214 long long stoll(const string& str, size_t* idx, int base) { return as_integer<long long>("stoll", str, idx, base); } 215 216 unsigned long long stoull(const string& str, size_t* idx, int base) { 217 return as_integer<unsigned long long>("stoull", str, idx, base); 218 } 219 220 float stof(const string& str, size_t* idx) { return as_float<float>("stof", str, idx); } 221 222 double stod(const string& str, size_t* idx) { return as_float<double>("stod", str, idx); } 223 224 long double stold(const string& str, size_t* idx) { return as_float<long double>("stold", str, idx); } 225 226 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 227 int stoi(const wstring& str, size_t* idx, int base) { return as_integer<int>("stoi", str, idx, base); } 228 229 long stol(const wstring& str, size_t* idx, int base) { return as_integer<long>("stol", str, idx, base); } 230 231 unsigned long stoul(const wstring& str, size_t* idx, int base) { 232 return as_integer<unsigned long>("stoul", str, idx, base); 233 } 234 235 long long stoll(const wstring& str, size_t* idx, int base) { return as_integer<long long>("stoll", str, idx, base); } 236 237 unsigned long long stoull(const wstring& str, size_t* idx, int base) { 238 return as_integer<unsigned long long>("stoull", str, idx, base); 239 } 240 241 float stof(const wstring& str, size_t* idx) { return as_float<float>("stof", str, idx); } 242 243 double stod(const wstring& str, size_t* idx) { return as_float<double>("stod", str, idx); } 244 245 long 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 250 namespace { 251 252 // as_string 253 254 template <typename S, typename P, typename V > 255 inline 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 274 template <class S> 275 struct initial_string; 276 277 template <> 278 struct 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 287 template <> 288 struct initial_string<wstring> { 289 wstring operator()() const { 290 wstring s(20, wchar_t()); 291 s.resize(s.capacity()); 292 return s; 293 } 294 }; 295 296 typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t* __restrict, ...); 297 298 inline 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 307 template <typename S, typename V> 308 S 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 321 string to_string(int val) { return i_to_string< string>(val); } 322 string to_string(long val) { return i_to_string< string>(val); } 323 string to_string(long long val) { return i_to_string< string>(val); } 324 string to_string(unsigned val) { return i_to_string< string>(val); } 325 string to_string(unsigned long val) { return i_to_string< string>(val); } 326 string to_string(unsigned long long val) { return i_to_string< string>(val); } 327 328 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 329 wstring to_wstring(int val) { return i_to_string<wstring>(val); } 330 wstring to_wstring(long val) { return i_to_string<wstring>(val); } 331 wstring to_wstring(long long val) { return i_to_string<wstring>(val); } 332 wstring to_wstring(unsigned val) { return i_to_string<wstring>(val); } 333 wstring to_wstring(unsigned long val) { return i_to_string<wstring>(val); } 334 wstring to_wstring(unsigned long long val) { return i_to_string<wstring>(val); } 335 #endif 336 337 string to_string(float val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } 338 string to_string(double val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } 339 string to_string(long double val) { return as_string(snprintf, initial_string< string>()(), "%Lf", val); } 340 341 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 342 wstring to_wstring(float val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } 343 wstring to_wstring(double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } 344 wstring 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