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&);
65 inline void throw_helper(const string
& msg
) {
66 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
69 fprintf(stderr
, "%s\n", msg
.c_str());
74 inline void throw_from_string_out_of_range(const string
& func
) {
75 throw_helper
<out_of_range
>(func
+ ": out of range");
78 inline void throw_from_string_invalid_arg(const string
& func
) {
79 throw_helper
<invalid_argument
>(func
+ ": no conversion");
84 template<typename V
, typename S
, typename F
>
85 inline V
as_integer_helper(const string
& func
, const S
& str
, size_t* idx
, int base
, F f
) {
86 typename
S::value_type
* ptr
= nullptr;
87 const typename
S::value_type
* const p
= str
.c_str();
88 __libcpp_remove_reference_t
<decltype(errno
)> errno_save
= errno
;
90 V r
= f(p
, &ptr
, base
);
91 swap(errno
, errno_save
);
92 if (errno_save
== ERANGE
)
93 throw_from_string_out_of_range(func
);
95 throw_from_string_invalid_arg(func
);
97 *idx
= static_cast<size_t>(ptr
- p
);
101 template<typename V
, typename S
>
102 inline V
as_integer(const string
& func
, const S
& s
, size_t* idx
, int base
);
106 inline int as_integer(const string
& func
, const string
& s
, size_t* idx
, int base
) {
107 // Use long as no Standard string to integer exists.
108 long r
= as_integer_helper
<long>(func
, s
, idx
, base
, strtol
);
109 if (r
< numeric_limits
<int>::min() || numeric_limits
<int>::max() < r
)
110 throw_from_string_out_of_range(func
);
111 return static_cast<int>(r
);
115 inline long as_integer(const string
& func
, const string
& s
, size_t* idx
, int base
) {
116 return as_integer_helper
<long>(func
, s
, idx
, base
, strtol
);
120 inline unsigned long as_integer(const string
& func
, const string
& s
, size_t* idx
, int base
) {
121 return as_integer_helper
<unsigned long>(func
, s
, idx
, base
, strtoul
);
125 inline long long as_integer(const string
& func
, const string
& s
, size_t* idx
, int base
) {
126 return as_integer_helper
<long long>(func
, s
, idx
, base
, strtoll
);
130 inline unsigned long long as_integer(const string
& func
, const string
& s
, size_t* idx
, int base
) {
131 return as_integer_helper
<unsigned long long>(func
, s
, idx
, base
, strtoull
);
134 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
137 inline int as_integer(const string
& func
, const wstring
& s
, size_t* idx
, int base
) {
138 // Use long as no Stantard string to integer exists.
139 long r
= as_integer_helper
<long>(func
, s
, idx
, base
, wcstol
);
140 if (r
< numeric_limits
<int>::min() || numeric_limits
<int>::max() < r
)
141 throw_from_string_out_of_range(func
);
142 return static_cast<int>(r
);
146 inline long as_integer(const string
& func
, const wstring
& s
, size_t* idx
, int base
) {
147 return as_integer_helper
<long>(func
, s
, idx
, base
, wcstol
);
153 as_integer(const string
& func
, const wstring
& s
, size_t* idx
, int base
)
155 return as_integer_helper
<unsigned long>(func
, s
, idx
, base
, wcstoul
);
159 inline long long as_integer(const string
& func
, const wstring
& s
, size_t* idx
, int base
) {
160 return as_integer_helper
<long long>(func
, s
, idx
, base
, wcstoll
);
164 inline unsigned long long as_integer(const string
& func
, const wstring
& s
, size_t* idx
, int base
) {
165 return as_integer_helper
<unsigned long long>(func
, s
, idx
, base
, wcstoull
);
167 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
171 template<typename V
, typename S
, typename F
>
172 inline V
as_float_helper(const string
& func
, const S
& str
, size_t* idx
, F f
) {
173 typename
S::value_type
* ptr
= nullptr;
174 const typename
S::value_type
* const p
= str
.c_str();
175 __libcpp_remove_reference_t
<decltype(errno
)> errno_save
= errno
;
178 swap(errno
, errno_save
);
179 if (errno_save
== ERANGE
)
180 throw_from_string_out_of_range(func
);
182 throw_from_string_invalid_arg(func
);
184 *idx
= static_cast<size_t>(ptr
- p
);
188 template<typename V
, typename S
>
189 inline V
as_float(const string
& func
, const S
& s
, size_t* idx
= nullptr);
192 inline float as_float(const string
& func
, const string
& s
, size_t* idx
) {
193 return as_float_helper
<float>(func
, s
, idx
, strtof
);
197 inline double as_float(const string
& func
, const string
& s
, size_t* idx
) {
198 return as_float_helper
<double>(func
, s
, idx
, strtod
);
202 inline long double as_float(const string
& func
, const string
& s
, size_t* idx
) {
203 return as_float_helper
<long double>(func
, s
, idx
, strtold
);
206 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
208 inline float as_float(const string
& func
, const wstring
& s
, size_t* idx
) {
209 return as_float_helper
<float>(func
, s
, idx
, wcstof
);
213 inline double as_float(const string
& func
, const wstring
& s
, size_t* idx
) {
214 return as_float_helper
<double>(func
, s
, idx
, wcstod
);
218 inline long double as_float(const string
& func
, const wstring
& s
, size_t* idx
) {
219 return as_float_helper
<long double>(func
, s
, idx
, wcstold
);
221 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
223 } // unnamed namespace
225 int stoi(const string
& str
, size_t* idx
, int base
) {
226 return as_integer
<int>("stoi", str
, idx
, base
);
229 long stol(const string
& str
, size_t* idx
, int base
) {
230 return as_integer
<long>("stol", str
, idx
, base
);
233 unsigned long stoul(const string
& str
, size_t* idx
, int base
) {
234 return as_integer
<unsigned long>("stoul", str
, idx
, base
);
237 long long stoll(const string
& str
, size_t* idx
, int base
) {
238 return as_integer
<long long>("stoll", str
, idx
, base
);
241 unsigned long long stoull(const string
& str
, size_t* idx
, int base
) {
242 return as_integer
<unsigned long long>("stoull", str
, idx
, base
);
245 float stof(const string
& str
, size_t* idx
) {
246 return as_float
<float>("stof", str
, idx
);
249 double stod(const string
& str
, size_t* idx
) {
250 return as_float
<double>("stod", str
, idx
);
253 long double stold(const string
& str
, size_t* idx
) {
254 return as_float
<long double>("stold", str
, idx
);
257 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
258 int stoi(const wstring
& str
, size_t* idx
, int base
) {
259 return as_integer
<int>("stoi", str
, idx
, base
);
262 long stol(const wstring
& str
, size_t* idx
, int base
) {
263 return as_integer
<long>("stol", str
, idx
, base
);
266 unsigned long stoul(const wstring
& str
, size_t* idx
, int base
) {
267 return as_integer
<unsigned long>("stoul", str
, idx
, base
);
270 long long stoll(const wstring
& str
, size_t* idx
, int base
) {
271 return as_integer
<long long>("stoll", str
, idx
, base
);
274 unsigned long long stoull(const wstring
& str
, size_t* idx
, int base
) {
275 return as_integer
<unsigned long long>("stoull", str
, idx
, base
);
278 float stof(const wstring
& str
, size_t* idx
) {
279 return as_float
<float>("stof", str
, idx
);
282 double stod(const wstring
& str
, size_t* idx
) {
283 return as_float
<double>("stod", str
, idx
);
286 long double stold(const wstring
& str
, size_t* idx
) {
287 return as_float
<long double>("stold", str
, idx
);
289 #endif // !_LIBCPP_HAS_NO_WIDE_CHARACTERS
298 template<typename S
, typename P
, typename V
>
299 inline S
as_string(P sprintf_like
, S s
, const typename
S::value_type
* fmt
, V a
) {
300 typedef typename
S::size_type size_type
;
301 size_type available
= s
.size();
303 int status
= sprintf_like(&s
[0], available
+ 1, fmt
, a
);
305 size_type used
= static_cast<size_type
>(status
);
306 if (used
<= available
) {
310 available
= used
; // Assume this is advice of how much space we need.
313 available
= available
* 2 + 1;
320 struct initial_string
;
323 struct initial_string
<string
> {
324 string
operator()() const {
326 s
.resize(s
.capacity());
331 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
333 struct initial_string
<wstring
> {
334 wstring
operator()() const {
335 wstring
s(20, wchar_t());
336 s
.resize(s
.capacity());
341 typedef int (*wide_printf
)(wchar_t* __restrict
, size_t, const wchar_t*__restrict
, ...);
343 inline wide_printf
get_swprintf() {
344 #ifndef _LIBCPP_MSVCRT
347 return static_cast<int (__cdecl
*)(wchar_t* __restrict
, size_t, const wchar_t*__restrict
, ...)>(_snwprintf
);
350 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
352 template <typename S
, typename V
>
354 // numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers.
355 // For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented),
356 // so we need +1 here.
357 constexpr size_t bufsize
= numeric_limits
<V
>::digits10
+ 2; // +1 for minus, +1 for digits10
359 const auto res
= to_chars(buf
, buf
+ bufsize
, v
);
360 _LIBCPP_ASSERT(res
.ec
== errc(), "bufsize must be large enough to accomodate the value");
361 return S(buf
, res
.ptr
);
364 } // unnamed namespace
366 string
to_string (int val
) { return i_to_string
< string
>(val
); }
367 string
to_string (long val
) { return i_to_string
< string
>(val
); }
368 string
to_string (long long val
) { return i_to_string
< string
>(val
); }
369 string
to_string (unsigned val
) { return i_to_string
< string
>(val
); }
370 string
to_string (unsigned long val
) { return i_to_string
< string
>(val
); }
371 string
to_string (unsigned long long val
) { return i_to_string
< string
>(val
); }
373 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
374 wstring
to_wstring(int val
) { return i_to_string
<wstring
>(val
); }
375 wstring
to_wstring(long val
) { return i_to_string
<wstring
>(val
); }
376 wstring
to_wstring(long long val
) { return i_to_string
<wstring
>(val
); }
377 wstring
to_wstring(unsigned val
) { return i_to_string
<wstring
>(val
); }
378 wstring
to_wstring(unsigned long val
) { return i_to_string
<wstring
>(val
); }
379 wstring
to_wstring(unsigned long long val
) { return i_to_string
<wstring
>(val
); }
382 string
to_string (float val
) { return as_string(snprintf
, initial_string
< string
>()(), "%f", val
); }
383 string
to_string (double val
) { return as_string(snprintf
, initial_string
< string
>()(), "%f", val
); }
384 string
to_string (long double val
) { return as_string(snprintf
, initial_string
< string
>()(), "%Lf", val
); }
386 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
387 wstring
to_wstring(float val
) { return as_string(get_swprintf(), initial_string
<wstring
>()(), L
"%f", val
); }
388 wstring
to_wstring(double val
) { return as_string(get_swprintf(), initial_string
<wstring
>()(), L
"%f", val
); }
389 wstring
to_wstring(long double val
) { return as_string(get_swprintf(), initial_string
<wstring
>()(), L
"%Lf", val
); }
392 _LIBCPP_END_NAMESPACE_STD