1 //===------------------------- string.cpp ---------------------------------===//
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 //===----------------------------------------------------------------------===//
19 _LIBCPP_BEGIN_NAMESPACE_STD
21 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common
<true>;
23 #ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
24 _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE
, char)
25 _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE
, wchar_t)
27 _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE
, char)
28 _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE
, wchar_t)
33 operator+<char, char_traits
<char>, allocator
<char> >(char const*, string
const&);
40 void throw_helper( const string
& msg
)
42 #ifndef _LIBCPP_NO_EXCEPTIONS
45 fprintf(stderr
, "%s\n", msg
.c_str());
51 void throw_from_string_out_of_range( const string
& func
)
53 throw_helper
<out_of_range
>(func
+ ": out of range");
57 void throw_from_string_invalid_arg( const string
& func
)
59 throw_helper
<invalid_argument
>(func
+ ": no conversion");
64 template<typename V
, typename S
, typename F
>
67 as_integer_helper(const string
& func
, const S
& str
, size_t* idx
, int base
, F f
)
69 typename
S::value_type
* ptr
= nullptr;
70 const typename
S::value_type
* const p
= str
.c_str();
71 typename remove_reference
<decltype(errno
)>::type errno_save
= errno
;
73 V r
= f(p
, &ptr
, base
);
74 swap(errno
, errno_save
);
75 if (errno_save
== ERANGE
)
76 throw_from_string_out_of_range(func
);
78 throw_from_string_invalid_arg(func
);
80 *idx
= static_cast<size_t>(ptr
- p
);
84 template<typename V
, typename S
>
87 as_integer(const string
& func
, const S
& s
, size_t* idx
, int base
);
93 as_integer(const string
& func
, const string
& s
, size_t* idx
, int base
)
95 // Use long as no Standard string to integer exists.
96 long r
= as_integer_helper
<long>( func
, s
, idx
, base
, strtol
);
97 if (r
< numeric_limits
<int>::min() || numeric_limits
<int>::max() < r
)
98 throw_from_string_out_of_range(func
);
99 return static_cast<int>(r
);
105 as_integer(const string
& func
, const string
& s
, size_t* idx
, int base
)
107 return as_integer_helper
<long>( func
, s
, idx
, base
, strtol
);
113 as_integer( const string
& func
, const string
& s
, size_t* idx
, int base
)
115 return as_integer_helper
<unsigned long>( func
, s
, idx
, base
, strtoul
);
121 as_integer( const string
& func
, const string
& s
, size_t* idx
, int base
)
123 return as_integer_helper
<long long>( func
, s
, idx
, base
, strtoll
);
129 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
);
138 as_integer( const string
& func
, const wstring
& s
, size_t* idx
, int base
)
140 // Use long as no Stantard string to integer exists.
141 long r
= as_integer_helper
<long>( func
, s
, idx
, base
, wcstol
);
142 if (r
< numeric_limits
<int>::min() || numeric_limits
<int>::max() < r
)
143 throw_from_string_out_of_range(func
);
144 return static_cast<int>(r
);
150 as_integer( const string
& func
, const wstring
& s
, size_t* idx
, int base
)
152 return as_integer_helper
<long>( func
, s
, idx
, base
, wcstol
);
158 as_integer( const string
& func
, const wstring
& s
, size_t* idx
, int base
)
160 return as_integer_helper
<unsigned long>( func
, s
, idx
, base
, wcstoul
);
166 as_integer( const string
& func
, const wstring
& s
, size_t* idx
, int base
)
168 return as_integer_helper
<long long>( func
, s
, idx
, base
, wcstoll
);
174 as_integer( const string
& func
, const wstring
& s
, size_t* idx
, int base
)
176 return as_integer_helper
<unsigned long long>( func
, s
, idx
, base
, wcstoull
);
181 template<typename V
, typename S
, typename F
>
184 as_float_helper(const string
& func
, const S
& str
, size_t* idx
, F f
)
186 typename
S::value_type
* ptr
= nullptr;
187 const typename
S::value_type
* const p
= str
.c_str();
188 typename remove_reference
<decltype(errno
)>::type errno_save
= errno
;
191 swap(errno
, errno_save
);
192 if (errno_save
== ERANGE
)
193 throw_from_string_out_of_range(func
);
195 throw_from_string_invalid_arg(func
);
197 *idx
= static_cast<size_t>(ptr
- p
);
201 template<typename V
, typename S
>
203 V
as_float( const string
& func
, const S
& s
, size_t* idx
= nullptr );
208 as_float( const string
& func
, const string
& s
, size_t* idx
)
210 return as_float_helper
<float>( func
, s
, idx
, strtof
);
216 as_float(const string
& func
, const string
& s
, size_t* idx
)
218 return as_float_helper
<double>( func
, s
, idx
, strtod
);
224 as_float( const string
& func
, const string
& s
, size_t* idx
)
226 return as_float_helper
<long double>( func
, s
, idx
, strtold
);
232 as_float( const string
& func
, const wstring
& s
, size_t* idx
)
234 return as_float_helper
<float>( func
, s
, idx
, wcstof
);
240 as_float( const string
& func
, const wstring
& s
, size_t* idx
)
242 return as_float_helper
<double>( func
, s
, idx
, wcstod
);
248 as_float( const string
& func
, const wstring
& s
, size_t* idx
)
250 return as_float_helper
<long double>( func
, s
, idx
, wcstold
);
253 } // unnamed namespace
256 stoi(const string
& str
, size_t* idx
, int base
)
258 return as_integer
<int>( "stoi", str
, idx
, base
);
262 stoi(const wstring
& str
, size_t* idx
, int base
)
264 return as_integer
<int>( "stoi", str
, idx
, base
);
268 stol(const string
& str
, size_t* idx
, int base
)
270 return as_integer
<long>( "stol", str
, idx
, base
);
274 stol(const wstring
& str
, size_t* idx
, int base
)
276 return as_integer
<long>( "stol", str
, idx
, base
);
280 stoul(const string
& str
, size_t* idx
, int base
)
282 return as_integer
<unsigned long>( "stoul", str
, idx
, base
);
286 stoul(const wstring
& str
, size_t* idx
, int base
)
288 return as_integer
<unsigned long>( "stoul", str
, idx
, base
);
292 stoll(const string
& str
, size_t* idx
, int base
)
294 return as_integer
<long long>( "stoll", str
, idx
, base
);
298 stoll(const wstring
& str
, size_t* idx
, int base
)
300 return as_integer
<long long>( "stoll", str
, idx
, base
);
304 stoull(const string
& str
, size_t* idx
, int base
)
306 return as_integer
<unsigned long long>( "stoull", str
, idx
, base
);
310 stoull(const wstring
& str
, size_t* idx
, int base
)
312 return as_integer
<unsigned long long>( "stoull", str
, idx
, base
);
316 stof(const string
& str
, size_t* idx
)
318 return as_float
<float>( "stof", str
, idx
);
322 stof(const wstring
& str
, size_t* idx
)
324 return as_float
<float>( "stof", str
, idx
);
328 stod(const string
& str
, size_t* idx
)
330 return as_float
<double>( "stod", str
, idx
);
334 stod(const wstring
& str
, size_t* idx
)
336 return as_float
<double>( "stod", str
, idx
);
340 stold(const string
& str
, size_t* idx
)
342 return as_float
<long double>( "stold", str
, idx
);
346 stold(const wstring
& str
, size_t* idx
)
348 return as_float
<long double>( "stold", str
, idx
);
358 template<typename S
, typename P
, typename V
>
361 as_string(P sprintf_like
, S s
, const typename
S::value_type
* fmt
, V a
)
363 typedef typename
S::size_type size_type
;
364 size_type available
= s
.size();
367 int status
= sprintf_like(&s
[0], available
+ 1, fmt
, a
);
370 size_type used
= static_cast<size_type
>(status
);
371 if ( used
<= available
)
376 available
= used
; // Assume this is advice of how much space we need.
379 available
= available
* 2 + 1;
386 struct initial_string
;
389 struct initial_string
<string
>
395 s
.resize(s
.capacity());
401 struct initial_string
<wstring
>
406 wstring
s(20, wchar_t());
407 s
.resize(s
.capacity());
412 typedef int (*wide_printf
)(wchar_t* __restrict
, size_t, const wchar_t*__restrict
, ...);
418 #ifndef _LIBCPP_MSVCRT
421 return static_cast<int (__cdecl
*)(wchar_t* __restrict
, size_t, const wchar_t*__restrict
, ...)>(_snwprintf
);
425 template <typename S
, typename V
>
426 S
i_to_string(const V v
)
428 // numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers.
429 // For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented),
430 // so we need +1 here.
431 constexpr size_t bufsize
= numeric_limits
<V
>::digits10
+ 2; // +1 for minus, +1 for digits10
433 const auto res
= to_chars(buf
, buf
+ bufsize
, v
);
434 _LIBCPP_ASSERT(res
.ec
== errc(), "bufsize must be large enough to accomodate the value");
435 return S(buf
, res
.ptr
);
438 } // unnamed namespace
440 string
to_string (int val
) { return i_to_string
< string
>(val
); }
441 string
to_string (long val
) { return i_to_string
< string
>(val
); }
442 string
to_string (long long val
) { return i_to_string
< string
>(val
); }
443 string
to_string (unsigned val
) { return i_to_string
< string
>(val
); }
444 string
to_string (unsigned long val
) { return i_to_string
< string
>(val
); }
445 string
to_string (unsigned long long val
) { return i_to_string
< string
>(val
); }
447 wstring
to_wstring(int val
) { return i_to_string
<wstring
>(val
); }
448 wstring
to_wstring(long val
) { return i_to_string
<wstring
>(val
); }
449 wstring
to_wstring(long long val
) { return i_to_string
<wstring
>(val
); }
450 wstring
to_wstring(unsigned val
) { return i_to_string
<wstring
>(val
); }
451 wstring
to_wstring(unsigned long val
) { return i_to_string
<wstring
>(val
); }
452 wstring
to_wstring(unsigned long long val
) { return i_to_string
<wstring
>(val
); }
455 string
to_string (float val
) { return as_string(snprintf
, initial_string
< string
>()(), "%f", val
); }
456 string
to_string (double val
) { return as_string(snprintf
, initial_string
< string
>()(), "%f", val
); }
457 string
to_string (long double val
) { return as_string(snprintf
, initial_string
< string
>()(), "%Lf", val
); }
459 wstring
to_wstring(float val
) { return as_string(get_swprintf(), initial_string
<wstring
>()(), L
"%f", val
); }
460 wstring
to_wstring(double val
) { return as_string(get_swprintf(), initial_string
<wstring
>()(), L
"%f", val
); }
461 wstring
to_wstring(long double val
) { return as_string(get_swprintf(), initial_string
<wstring
>()(), L
"%Lf", val
); }
463 _LIBCPP_END_NAMESPACE_STD