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 //===----------------------------------------------------------------------===//
18 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
22 _LIBCPP_BEGIN_NAMESPACE_STD
24 #ifndef _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON
27 struct __basic_string_common
;
29 // The struct isn't declared anymore in the headers. It's only here for ABI compatibility.
31 struct __basic_string_common
<true> {
32 _LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI
void __throw_length_error() const;
33 _LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI
void __throw_out_of_range() const;
36 void __basic_string_common
<true>::__throw_length_error() const {
37 std::__throw_length_error("basic_string");
39 void __basic_string_common
<true>::__throw_out_of_range() const {
40 std::__throw_out_of_range("basic_string");
43 #endif // _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON
45 #define _LIBCPP_EXTERN_TEMPLATE_DEFINE(...) template __VA_ARGS__;
46 #ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
47 _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE
, char)
48 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
49 _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE
, wchar_t)
52 _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE
, char)
53 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
54 _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE
, wchar_t)
57 #undef _LIBCPP_EXTERN_TEMPLATE_DEFINE
59 template string
operator+<char, char_traits
<char>, allocator
<char> >(char const*, string
const&);
66 void throw_helper( const string
& msg
)
68 #ifndef _LIBCPP_NO_EXCEPTIONS
71 fprintf(stderr
, "%s\n", msg
.c_str());
77 void throw_from_string_out_of_range( const string
& func
)
79 throw_helper
<out_of_range
>(func
+ ": out of range");
83 void throw_from_string_invalid_arg( const string
& func
)
85 throw_helper
<invalid_argument
>(func
+ ": no conversion");
90 template<typename V
, typename S
, typename F
>
93 as_integer_helper(const string
& func
, const S
& str
, size_t* idx
, int base
, F f
)
95 typename
S::value_type
* ptr
= nullptr;
96 const typename
S::value_type
* const p
= str
.c_str();
97 typename remove_reference
<decltype(errno
)>::type errno_save
= errno
;
99 V r
= f(p
, &ptr
, base
);
100 swap(errno
, errno_save
);
101 if (errno_save
== ERANGE
)
102 throw_from_string_out_of_range(func
);
104 throw_from_string_invalid_arg(func
);
106 *idx
= static_cast<size_t>(ptr
- p
);
110 template<typename V
, typename S
>
113 as_integer(const string
& func
, const S
& s
, size_t* idx
, int base
);
119 as_integer(const string
& func
, const string
& s
, size_t* idx
, int base
)
121 // Use long as no Standard string to integer exists.
122 long r
= as_integer_helper
<long>( func
, s
, idx
, base
, strtol
);
123 if (r
< numeric_limits
<int>::min() || numeric_limits
<int>::max() < r
)
124 throw_from_string_out_of_range(func
);
125 return static_cast<int>(r
);
131 as_integer(const string
& func
, const string
& s
, size_t* idx
, int base
)
133 return as_integer_helper
<long>( func
, s
, idx
, base
, strtol
);
139 as_integer( const string
& func
, const string
& s
, size_t* idx
, int base
)
141 return as_integer_helper
<unsigned long>( func
, s
, idx
, base
, strtoul
);
147 as_integer( const string
& func
, const string
& s
, size_t* idx
, int base
)
149 return as_integer_helper
<long long>( func
, s
, idx
, base
, strtoll
);
155 as_integer( const string
& func
, const string
& s
, size_t* idx
, int base
)
157 return as_integer_helper
<unsigned long long>( func
, s
, idx
, base
, strtoull
);
160 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
165 as_integer( const string
& func
, const wstring
& s
, size_t* idx
, int base
)
167 // Use long as no Stantard string to integer exists.
168 long r
= as_integer_helper
<long>( func
, s
, idx
, base
, wcstol
);
169 if (r
< numeric_limits
<int>::min() || numeric_limits
<int>::max() < r
)
170 throw_from_string_out_of_range(func
);
171 return static_cast<int>(r
);
177 as_integer( const string
& func
, const wstring
& s
, size_t* idx
, int base
)
179 return as_integer_helper
<long>( func
, s
, idx
, base
, wcstol
);
185 as_integer( const string
& func
, const wstring
& s
, size_t* idx
, int base
)
187 return as_integer_helper
<unsigned long>( func
, s
, idx
, base
, wcstoul
);
193 as_integer( const string
& func
, const wstring
& s
, size_t* idx
, int base
)
195 return as_integer_helper
<long long>( func
, s
, idx
, base
, wcstoll
);
201 as_integer( const string
& func
, const wstring
& s
, size_t* idx
, int base
)
203 return as_integer_helper
<unsigned long long>( func
, s
, idx
, base
, wcstoull
);
205 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
209 template<typename V
, typename S
, typename F
>
212 as_float_helper(const string
& func
, const S
& str
, size_t* idx
, F f
)
214 typename
S::value_type
* ptr
= nullptr;
215 const typename
S::value_type
* const p
= str
.c_str();
216 typename remove_reference
<decltype(errno
)>::type errno_save
= errno
;
219 swap(errno
, errno_save
);
220 if (errno_save
== ERANGE
)
221 throw_from_string_out_of_range(func
);
223 throw_from_string_invalid_arg(func
);
225 *idx
= static_cast<size_t>(ptr
- p
);
229 template<typename V
, typename S
>
231 V
as_float( const string
& func
, const S
& s
, size_t* idx
= nullptr );
236 as_float( const string
& func
, const string
& s
, size_t* idx
)
238 return as_float_helper
<float>( func
, s
, idx
, strtof
);
244 as_float(const string
& func
, const string
& s
, size_t* idx
)
246 return as_float_helper
<double>( func
, s
, idx
, strtod
);
252 as_float( const string
& func
, const string
& s
, size_t* idx
)
254 return as_float_helper
<long double>( func
, s
, idx
, strtold
);
257 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
261 as_float( const string
& func
, const wstring
& s
, size_t* idx
)
263 return as_float_helper
<float>( func
, s
, idx
, wcstof
);
269 as_float( const string
& func
, const wstring
& s
, size_t* idx
)
271 return as_float_helper
<double>( func
, s
, idx
, wcstod
);
277 as_float( const string
& func
, const wstring
& s
, size_t* idx
)
279 return as_float_helper
<long double>( func
, s
, idx
, wcstold
);
281 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
283 } // unnamed namespace
286 stoi(const string
& str
, size_t* idx
, int base
)
288 return as_integer
<int>( "stoi", str
, idx
, base
);
291 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
293 stoi(const wstring
& str
, size_t* idx
, int base
)
295 return as_integer
<int>( "stoi", str
, idx
, base
);
300 stol(const string
& str
, size_t* idx
, int base
)
302 return as_integer
<long>( "stol", str
, idx
, base
);
305 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
307 stol(const wstring
& str
, size_t* idx
, int base
)
309 return as_integer
<long>( "stol", str
, idx
, base
);
314 stoul(const string
& str
, size_t* idx
, int base
)
316 return as_integer
<unsigned long>( "stoul", str
, idx
, base
);
319 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
321 stoul(const wstring
& str
, size_t* idx
, int base
)
323 return as_integer
<unsigned long>( "stoul", str
, idx
, base
);
328 stoll(const string
& str
, size_t* idx
, int base
)
330 return as_integer
<long long>( "stoll", str
, idx
, base
);
333 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
335 stoll(const wstring
& str
, size_t* idx
, int base
)
337 return as_integer
<long long>( "stoll", str
, idx
, base
);
342 stoull(const string
& str
, size_t* idx
, int base
)
344 return as_integer
<unsigned long long>( "stoull", str
, idx
, base
);
347 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
349 stoull(const wstring
& str
, size_t* idx
, int base
)
351 return as_integer
<unsigned long long>( "stoull", str
, idx
, base
);
356 stof(const string
& str
, size_t* idx
)
358 return as_float
<float>( "stof", str
, idx
);
361 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
363 stof(const wstring
& str
, size_t* idx
)
365 return as_float
<float>( "stof", str
, idx
);
370 stod(const string
& str
, size_t* idx
)
372 return as_float
<double>( "stod", str
, idx
);
375 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
377 stod(const wstring
& str
, size_t* idx
)
379 return as_float
<double>( "stod", str
, idx
);
384 stold(const string
& str
, size_t* idx
)
386 return as_float
<long double>( "stold", str
, idx
);
389 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
391 stold(const wstring
& str
, size_t* idx
)
393 return as_float
<long double>( "stold", str
, idx
);
404 template<typename S
, typename P
, typename V
>
407 as_string(P sprintf_like
, S s
, const typename
S::value_type
* fmt
, V a
)
409 typedef typename
S::size_type size_type
;
410 size_type available
= s
.size();
413 int status
= sprintf_like(&s
[0], available
+ 1, fmt
, a
);
416 size_type used
= static_cast<size_type
>(status
);
417 if ( used
<= available
)
422 available
= used
; // Assume this is advice of how much space we need.
425 available
= available
* 2 + 1;
432 struct initial_string
;
435 struct initial_string
<string
>
441 s
.resize(s
.capacity());
446 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
448 struct initial_string
<wstring
>
453 wstring
s(20, wchar_t());
454 s
.resize(s
.capacity());
459 typedef int (*wide_printf
)(wchar_t* __restrict
, size_t, const wchar_t*__restrict
, ...);
465 #ifndef _LIBCPP_MSVCRT
468 return static_cast<int (__cdecl
*)(wchar_t* __restrict
, size_t, const wchar_t*__restrict
, ...)>(_snwprintf
);
471 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
473 template <typename S
, typename V
>
476 // numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers.
477 // For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented),
478 // so we need +1 here.
479 constexpr size_t bufsize
= numeric_limits
<V
>::digits10
+ 2; // +1 for minus, +1 for digits10
481 const auto res
= to_chars(buf
, buf
+ bufsize
, v
);
482 _LIBCPP_ASSERT(res
.ec
== errc(), "bufsize must be large enough to accomodate the value");
483 return S(buf
, res
.ptr
);
486 } // unnamed namespace
488 string
to_string (int val
) { return i_to_string
< string
>(val
); }
489 string
to_string (long val
) { return i_to_string
< string
>(val
); }
490 string
to_string (long long val
) { return i_to_string
< string
>(val
); }
491 string
to_string (unsigned val
) { return i_to_string
< string
>(val
); }
492 string
to_string (unsigned long val
) { return i_to_string
< string
>(val
); }
493 string
to_string (unsigned long long val
) { return i_to_string
< string
>(val
); }
495 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
496 wstring
to_wstring(int val
) { return i_to_string
<wstring
>(val
); }
497 wstring
to_wstring(long val
) { return i_to_string
<wstring
>(val
); }
498 wstring
to_wstring(long long val
) { return i_to_string
<wstring
>(val
); }
499 wstring
to_wstring(unsigned val
) { return i_to_string
<wstring
>(val
); }
500 wstring
to_wstring(unsigned long val
) { return i_to_string
<wstring
>(val
); }
501 wstring
to_wstring(unsigned long long val
) { return i_to_string
<wstring
>(val
); }
504 string
to_string (float val
) { return as_string(snprintf
, initial_string
< string
>()(), "%f", val
); }
505 string
to_string (double val
) { return as_string(snprintf
, initial_string
< string
>()(), "%f", val
); }
506 string
to_string (long double val
) { return as_string(snprintf
, initial_string
< string
>()(), "%Lf", val
); }
508 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
509 wstring
to_wstring(float val
) { return as_string(get_swprintf(), initial_string
<wstring
>()(), L
"%f", val
); }
510 wstring
to_wstring(double val
) { return as_string(get_swprintf(), initial_string
<wstring
>()(), L
"%f", val
); }
511 wstring
to_wstring(long double val
) { return as_string(get_swprintf(), initial_string
<wstring
>()(), L
"%Lf", val
); }
514 _LIBCPP_END_NAMESPACE_STD