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 #if _LIBCPP_HAS_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 [[noreturn
]] _LIBCPP_EXPORTED_FROM_ABI
void __throw_length_error() const;
32 [[noreturn
]] _LIBCPP_EXPORTED_FROM_ABI
void __throw_out_of_range() const;
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"); }
38 #endif // _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON
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 # if _LIBCPP_HAS_WIDE_CHARACTERS
44 _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE
, wchar_t)
47 _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE
, char)
48 # if _LIBCPP_HAS_WIDE_CHARACTERS
49 _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE
, wchar_t)
52 #undef _LIBCPP_EXTERN_TEMPLATE_DEFINE
54 template string
operator+ <char, char_traits
<char>, allocator
<char>>(char const*, string
const&);
58 inline void throw_from_string_out_of_range(const string
& func
) {
59 std::__throw_out_of_range((func
+ ": out of range").c_str());
62 inline void throw_from_string_invalid_arg(const string
& func
) {
63 std::__throw_invalid_argument((func
+ ": no conversion").c_str());
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
;
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
);
79 throw_from_string_invalid_arg(func
);
81 *idx
= static_cast<size_t>(ptr
- p
);
85 template <typename V
, typename S
>
86 inline V
as_integer(const string
& func
, const S
& s
, size_t* idx
, int base
);
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
);
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
);
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
);
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
);
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
);
118 #if _LIBCPP_HAS_WIDE_CHARACTERS
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
);
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
);
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
);
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
);
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
);
148 #endif // _LIBCPP_HAS_WIDE_CHARACTERS
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
;
159 swap(errno
, errno_save
);
160 if (errno_save
== ERANGE
)
161 throw_from_string_out_of_range(func
);
163 throw_from_string_invalid_arg(func
);
165 *idx
= static_cast<size_t>(ptr
- p
);
169 template <typename V
, typename S
>
170 inline V
as_float(const string
& func
, const S
& s
, size_t* idx
= nullptr);
173 inline float as_float(const string
& func
, const string
& s
, size_t* idx
) {
174 return as_float_helper
<float>(func
, s
, idx
, strtof
);
178 inline double as_float(const string
& func
, const string
& s
, size_t* idx
) {
179 return as_float_helper
<double>(func
, s
, idx
, strtod
);
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
);
187 #if _LIBCPP_HAS_WIDE_CHARACTERS
189 inline float as_float(const string
& func
, const wstring
& s
, size_t* idx
) {
190 return as_float_helper
<float>(func
, s
, idx
, wcstof
);
194 inline double as_float(const string
& func
, const wstring
& s
, size_t* idx
) {
195 return as_float_helper
<double>(func
, s
, idx
, wcstod
);
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
);
202 #endif // _LIBCPP_HAS_WIDE_CHARACTERS
204 } // unnamed namespace
206 int stoi(const string
& str
, size_t* idx
, int base
) { return as_integer
<int>("stoi", str
, idx
, base
); }
208 long stol(const string
& str
, size_t* idx
, int base
) { return as_integer
<long>("stol", str
, idx
, base
); }
210 unsigned long stoul(const string
& str
, size_t* idx
, int base
) {
211 return as_integer
<unsigned long>("stoul", str
, idx
, base
);
214 long long stoll(const string
& str
, size_t* idx
, int base
) { return as_integer
<long long>("stoll", str
, idx
, base
); }
216 unsigned long long stoull(const string
& str
, size_t* idx
, int base
) {
217 return as_integer
<unsigned long long>("stoull", str
, idx
, base
);
220 float stof(const string
& str
, size_t* idx
) { return as_float
<float>("stof", str
, idx
); }
222 double stod(const string
& str
, size_t* idx
) { return as_float
<double>("stod", str
, idx
); }
224 long double stold(const string
& str
, size_t* idx
) { return as_float
<long double>("stold", str
, idx
); }
226 #if _LIBCPP_HAS_WIDE_CHARACTERS
227 int stoi(const wstring
& str
, size_t* idx
, int base
) { return as_integer
<int>("stoi", str
, idx
, base
); }
229 long stol(const wstring
& str
, size_t* idx
, int base
) { return as_integer
<long>("stol", str
, idx
, base
); }
231 unsigned long stoul(const wstring
& str
, size_t* idx
, int base
) {
232 return as_integer
<unsigned long>("stoul", str
, idx
, base
);
235 long long stoll(const wstring
& str
, size_t* idx
, int base
) { return as_integer
<long long>("stoll", str
, idx
, base
); }
237 unsigned long long stoull(const wstring
& str
, size_t* idx
, int base
) {
238 return as_integer
<unsigned long long>("stoull", str
, idx
, base
);
241 float stof(const wstring
& str
, size_t* idx
) { return as_float
<float>("stof", str
, idx
); }
243 double stod(const wstring
& str
, size_t* idx
) { return as_float
<double>("stod", str
, idx
); }
245 long double stold(const wstring
& str
, size_t* idx
) { return as_float
<long double>("stold", str
, idx
); }
246 #endif // _LIBCPP_HAS_WIDE_CHARACTERS
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();
259 int status
= sprintf_like(&s
[0], available
+ 1, fmt
, a
);
261 size_type used
= static_cast<size_type
>(status
);
262 if (used
<= available
) {
266 available
= used
; // Assume this is advice of how much space we need.
268 available
= available
* 2 + 1;
275 struct initial_string
;
278 struct initial_string
<string
> {
279 string
operator()() const {
281 s
.resize(s
.capacity());
286 #if _LIBCPP_HAS_WIDE_CHARACTERS
288 struct initial_string
<wstring
> {
289 wstring
operator()() const {
290 wstring
s(20, wchar_t());
291 s
.resize(s
.capacity());
296 typedef int (*wide_printf
)(wchar_t* __restrict
, size_t, const wchar_t* __restrict
, ...);
298 inline wide_printf
get_swprintf() {
299 # ifndef _LIBCPP_MSVCRT
302 return static_cast<int(__cdecl
*)(wchar_t* __restrict
, size_t, const wchar_t* __restrict
, ...)>(_snwprintf
);
305 #endif // _LIBCPP_HAS_WIDE_CHARACTERS
307 template <typename S
, typename 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
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
);
319 } // unnamed namespace
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
); }
328 #if _LIBCPP_HAS_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
); }
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
); }
341 #if _LIBCPP_HAS_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
); }
347 _LIBCPP_END_NAMESPACE_STD