1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
17 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
21 _LIBCPP_BEGIN_NAMESPACE_STD
23 #ifndef _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON
26 struct __basic_string_common
;
28 // The struct isn't declared anymore in the headers. It's only here for ABI compatibility.
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;
35 void __basic_string_common
<true>::__throw_length_error() const {
36 std::__throw_length_error("basic_string");
38 void __basic_string_common
<true>::__throw_out_of_range() const {
39 std::__throw_out_of_range("basic_string");
42 #endif // _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON
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)
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)
56 #undef _LIBCPP_EXTERN_TEMPLATE_DEFINE
58 template string
operator+<char, char_traits
<char>, allocator
<char>>(char const*, string
const&);
63 inline void throw_from_string_out_of_range(const string
& func
) {
64 std::__throw_out_of_range((func
+ ": out of range").c_str());
67 inline void throw_from_string_invalid_arg(const string
& func
) {
68 std::__throw_invalid_argument((func
+ ": no conversion").c_str());
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
;
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
);
84 throw_from_string_invalid_arg(func
);
86 *idx
= static_cast<size_t>(ptr
- p
);
90 template<typename V
, typename S
>
91 inline V
as_integer(const string
& func
, const S
& s
, size_t* idx
, int base
);
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
);
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
);
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
);
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
);
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
);
123 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
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
);
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
);
142 as_integer(const string
& func
, const wstring
& s
, size_t* idx
, int base
)
144 return as_integer_helper
<unsigned long>(func
, s
, idx
, base
, wcstoul
);
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
);
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
);
156 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
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
;
167 swap(errno
, errno_save
);
168 if (errno_save
== ERANGE
)
169 throw_from_string_out_of_range(func
);
171 throw_from_string_invalid_arg(func
);
173 *idx
= static_cast<size_t>(ptr
- p
);
177 template<typename V
, typename S
>
178 inline V
as_float(const string
& func
, const S
& s
, size_t* idx
= nullptr);
181 inline float as_float(const string
& func
, const string
& s
, size_t* idx
) {
182 return as_float_helper
<float>(func
, s
, idx
, strtof
);
186 inline double as_float(const string
& func
, const string
& s
, size_t* idx
) {
187 return as_float_helper
<double>(func
, s
, idx
, strtod
);
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
);
195 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
197 inline float as_float(const string
& func
, const wstring
& s
, size_t* idx
) {
198 return as_float_helper
<float>(func
, s
, idx
, wcstof
);
202 inline double as_float(const string
& func
, const wstring
& s
, size_t* idx
) {
203 return as_float_helper
<double>(func
, s
, idx
, wcstod
);
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
);
210 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
212 } // unnamed namespace
214 int stoi(const string
& str
, size_t* idx
, int base
) {
215 return as_integer
<int>("stoi", str
, idx
, base
);
218 long stol(const string
& str
, size_t* idx
, int base
) {
219 return as_integer
<long>("stol", str
, idx
, base
);
222 unsigned long stoul(const string
& str
, size_t* idx
, int base
) {
223 return as_integer
<unsigned long>("stoul", str
, idx
, base
);
226 long long stoll(const string
& str
, size_t* idx
, int base
) {
227 return as_integer
<long long>("stoll", str
, idx
, base
);
230 unsigned long long stoull(const string
& str
, size_t* idx
, int base
) {
231 return as_integer
<unsigned long long>("stoull", str
, idx
, base
);
234 float stof(const string
& str
, size_t* idx
) {
235 return as_float
<float>("stof", str
, idx
);
238 double stod(const string
& str
, size_t* idx
) {
239 return as_float
<double>("stod", str
, idx
);
242 long double stold(const string
& str
, size_t* idx
) {
243 return as_float
<long double>("stold", str
, idx
);
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
);
251 long stol(const wstring
& str
, size_t* idx
, int base
) {
252 return as_integer
<long>("stol", str
, idx
, base
);
255 unsigned long stoul(const wstring
& str
, size_t* idx
, int base
) {
256 return as_integer
<unsigned long>("stoul", str
, idx
, base
);
259 long long stoll(const wstring
& str
, size_t* idx
, int base
) {
260 return as_integer
<long long>("stoll", str
, idx
, base
);
263 unsigned long long stoull(const wstring
& str
, size_t* idx
, int base
) {
264 return as_integer
<unsigned long long>("stoull", str
, idx
, base
);
267 float stof(const wstring
& str
, size_t* idx
) {
268 return as_float
<float>("stof", str
, idx
);
271 double stod(const wstring
& str
, size_t* idx
) {
272 return as_float
<double>("stod", str
, idx
);
275 long double stold(const wstring
& str
, size_t* idx
) {
276 return as_float
<long double>("stold", str
, idx
);
278 #endif // !_LIBCPP_HAS_NO_WIDE_CHARACTERS
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();
292 int status
= sprintf_like(&s
[0], available
+ 1, fmt
, a
);
294 size_type used
= static_cast<size_type
>(status
);
295 if (used
<= available
) {
299 available
= used
; // Assume this is advice of how much space we need.
302 available
= available
* 2 + 1;
309 struct initial_string
;
312 struct initial_string
<string
> {
313 string
operator()() const {
315 s
.resize(s
.capacity());
320 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
322 struct initial_string
<wstring
> {
323 wstring
operator()() const {
324 wstring
s(20, wchar_t());
325 s
.resize(s
.capacity());
330 typedef int (*wide_printf
)(wchar_t* __restrict
, size_t, const wchar_t*__restrict
, ...);
332 inline wide_printf
get_swprintf() {
333 #ifndef _LIBCPP_MSVCRT
336 return static_cast<int (__cdecl
*)(wchar_t* __restrict
, size_t, const wchar_t*__restrict
, ...)>(_snwprintf
);
339 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
341 template <typename S
, typename 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
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
);
353 } // unnamed namespace
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
); }
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
); }
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
); }
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
); }
381 _LIBCPP_END_NAMESPACE_STD