1227825Stheraven//===------------------------- string.cpp ---------------------------------===//
2227825Stheraven//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6227825Stheraven//
7227825Stheraven//===----------------------------------------------------------------------===//
8227825Stheraven
9227825Stheraven#include "string"
10353358Sdim#include "charconv"
11227825Stheraven#include "cstdlib"
12227825Stheraven#include "cwchar"
13227825Stheraven#include "cerrno"
14253146Stheraven#include "limits"
15253146Stheraven#include "stdexcept"
16261272Sdim#include <stdio.h>
17353358Sdim#include "__debug"
18227825Stheraven
19227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD
20227825Stheraven
21314564Sdimtemplate class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common<true>;
22227825Stheraven
23314564Sdimtemplate class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<char>;
24314564Sdimtemplate class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<wchar_t>;
25227825Stheraven
26227825Stheraventemplate
27227825Stheraven    string
28227825Stheraven    operator+<char, char_traits<char>, allocator<char> >(char const*, string const&);
29227825Stheraven
30253146Stheravennamespace
31227825Stheraven{
32253146Stheraven
33253146Stheraventemplate<typename T>
34253146Stheraveninline
35253146Stheravenvoid throw_helper( const string& msg )
36253146Stheraven{
37253146Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
38253146Stheraven    throw T( msg );
39253146Stheraven#else
40288943Sdim    fprintf(stderr, "%s\n", msg.c_str());
41314564Sdim    _VSTD::abort();
42253146Stheraven#endif
43253146Stheraven}
44253146Stheraven
45253146Stheraveninline
46253146Stheravenvoid throw_from_string_out_of_range( const string& func )
47253146Stheraven{
48253146Stheraven    throw_helper<out_of_range>(func + ": out of range");
49253146Stheraven}
50253146Stheraven
51253146Stheraveninline
52253146Stheravenvoid throw_from_string_invalid_arg( const string& func )
53253146Stheraven{
54253146Stheraven    throw_helper<invalid_argument>(func + ": no conversion");
55253146Stheraven}
56253146Stheraven
57253146Stheraven// as_integer
58253146Stheraven
59253146Stheraventemplate<typename V, typename S, typename F>
60253146Stheraveninline
61253146StheravenV
62253146Stheravenas_integer_helper(const string& func, const S& str, size_t* idx, int base, F f)
63253146Stheraven{
64276792Sdim    typename S::value_type* ptr = nullptr;
65253146Stheraven    const typename S::value_type* const p = str.c_str();
66246468Stheraven    typename remove_reference<decltype(errno)>::type errno_save = errno;
67246468Stheraven    errno = 0;
68253146Stheraven    V r = f(p, &ptr, base);
69246468Stheraven    swap(errno, errno_save);
70253146Stheraven    if (errno_save == ERANGE)
71253146Stheraven        throw_from_string_out_of_range(func);
72246468Stheraven    if (ptr == p)
73253146Stheraven        throw_from_string_invalid_arg(func);
74227825Stheraven    if (idx)
75227825Stheraven        *idx = static_cast<size_t>(ptr - p);
76253146Stheraven    return r;
77253146Stheraven}
78253146Stheraven
79253146Stheraventemplate<typename V, typename S>
80253146Stheraveninline
81253146StheravenV
82253146Stheravenas_integer(const string& func, const S& s, size_t* idx, int base);
83253146Stheraven
84253146Stheraven// string
85253146Stheraventemplate<>
86253146Stheraveninline
87253146Stheravenint
88253146Stheravenas_integer(const string& func, const string& s, size_t* idx, int base )
89253146Stheraven{
90261272Sdim    // Use long as no Standard string to integer exists.
91253146Stheraven    long r = as_integer_helper<long>( func, s, idx, base, strtol );
92253146Stheraven    if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
93253146Stheraven        throw_from_string_out_of_range(func);
94227825Stheraven    return static_cast<int>(r);
95227825Stheraven}
96227825Stheraven
97253146Stheraventemplate<>
98253146Stheraveninline
99253146Stheravenlong
100253146Stheravenas_integer(const string& func, const string& s, size_t* idx, int base )
101253146Stheraven{
102253146Stheraven    return as_integer_helper<long>( func, s, idx, base, strtol );
103253146Stheraven}
104253146Stheraven
105253146Stheraventemplate<>
106253146Stheraveninline
107253146Stheravenunsigned long
108253146Stheravenas_integer( const string& func, const string& s, size_t* idx, int base )
109253146Stheraven{
110253146Stheraven    return as_integer_helper<unsigned long>( func, s, idx, base, strtoul );
111253146Stheraven}
112253146Stheraven
113253146Stheraventemplate<>
114253146Stheraveninline
115253146Stheravenlong long
116253146Stheravenas_integer( const string& func, const string& s, size_t* idx, int base )
117253146Stheraven{
118253146Stheraven    return as_integer_helper<long long>( func, s, idx, base, strtoll );
119253146Stheraven}
120253146Stheraven
121253146Stheraventemplate<>
122253146Stheraveninline
123253146Stheravenunsigned long long
124253146Stheravenas_integer( const string& func, const string& s, size_t* idx, int base )
125253146Stheraven{
126253146Stheraven    return as_integer_helper<unsigned long long>( func, s, idx, base, strtoull );
127253146Stheraven}
128253146Stheraven
129253146Stheraven// wstring
130253146Stheraventemplate<>
131253146Stheraveninline
132227825Stheravenint
133253146Stheravenas_integer( const string& func, const wstring& s, size_t* idx, int base )
134227825Stheraven{
135253146Stheraven    // Use long as no Stantard string to integer exists.
136253146Stheraven    long r = as_integer_helper<long>( func, s, idx, base, wcstol );
137253146Stheraven    if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
138253146Stheraven        throw_from_string_out_of_range(func);
139227825Stheraven    return static_cast<int>(r);
140227825Stheraven}
141227825Stheraven
142253146Stheraventemplate<>
143253146Stheraveninline
144227825Stheravenlong
145253146Stheravenas_integer( const string& func, const wstring& s, size_t* idx, int base )
146227825Stheraven{
147253146Stheraven    return as_integer_helper<long>( func, s, idx, base, wcstol );
148253146Stheraven}
149253146Stheraven
150253146Stheraventemplate<>
151253146Stheraveninline
152253146Stheravenunsigned long
153253146Stheravenas_integer( const string& func, const wstring& s, size_t* idx, int base )
154253146Stheraven{
155253146Stheraven    return as_integer_helper<unsigned long>( func, s, idx, base, wcstoul );
156253146Stheraven}
157253146Stheraven
158253146Stheraventemplate<>
159253146Stheraveninline
160253146Stheravenlong long
161253146Stheravenas_integer( const string& func, const wstring& s, size_t* idx, int base )
162253146Stheraven{
163253146Stheraven    return as_integer_helper<long long>( func, s, idx, base, wcstoll );
164253146Stheraven}
165253146Stheraven
166253146Stheraventemplate<>
167253146Stheraveninline
168253146Stheravenunsigned long long
169253146Stheravenas_integer( const string& func, const wstring& s, size_t* idx, int base )
170253146Stheraven{
171253146Stheraven    return as_integer_helper<unsigned long long>( func, s, idx, base, wcstoull );
172253146Stheraven}
173253146Stheraven
174253146Stheraven// as_float
175253146Stheraven
176353358Sdimtemplate<typename V, typename S, typename F>
177253146Stheraveninline
178253146StheravenV
179253146Stheravenas_float_helper(const string& func, const S& str, size_t* idx, F f )
180253146Stheraven{
181276792Sdim    typename S::value_type* ptr = nullptr;
182253146Stheraven    const typename S::value_type* const p = str.c_str();
183246468Stheraven    typename remove_reference<decltype(errno)>::type errno_save = errno;
184246468Stheraven    errno = 0;
185253146Stheraven    V r = f(p, &ptr);
186246468Stheraven    swap(errno, errno_save);
187246468Stheraven    if (errno_save == ERANGE)
188253146Stheraven        throw_from_string_out_of_range(func);
189246468Stheraven    if (ptr == p)
190253146Stheraven        throw_from_string_invalid_arg(func);
191227825Stheraven    if (idx)
192227825Stheraven        *idx = static_cast<size_t>(ptr - p);
193227825Stheraven    return r;
194227825Stheraven}
195227825Stheraven
196253146Stheraventemplate<typename V, typename S>
197253146Stheraveninline
198253146StheravenV as_float( const string& func, const S& s, size_t* idx = nullptr );
199253146Stheraven
200253146Stheraventemplate<>
201253146Stheraveninline
202253146Stheravenfloat
203253146Stheravenas_float( const string& func, const string& s, size_t* idx )
204253146Stheraven{
205253146Stheraven    return as_float_helper<float>( func, s, idx, strtof );
206253146Stheraven}
207253146Stheraven
208253146Stheraventemplate<>
209253146Stheraveninline
210253146Stheravendouble
211253146Stheravenas_float(const string& func, const string& s, size_t* idx )
212253146Stheraven{
213253146Stheraven    return as_float_helper<double>( func, s, idx, strtod );
214253146Stheraven}
215253146Stheraven
216253146Stheraventemplate<>
217253146Stheraveninline
218253146Stheravenlong double
219253146Stheravenas_float( const string& func, const string& s, size_t* idx )
220253146Stheraven{
221253146Stheraven    return as_float_helper<long double>( func, s, idx, strtold );
222253146Stheraven}
223253146Stheraven
224253146Stheraventemplate<>
225253146Stheraveninline
226253146Stheravenfloat
227253146Stheravenas_float( const string& func, const wstring& s, size_t* idx )
228253146Stheraven{
229253146Stheraven    return as_float_helper<float>( func, s, idx, wcstof );
230253146Stheraven}
231253146Stheraven
232253146Stheraventemplate<>
233253146Stheraveninline
234253146Stheravendouble
235253146Stheravenas_float( const string& func, const wstring& s, size_t* idx )
236253146Stheraven{
237253146Stheraven    return as_float_helper<double>( func, s, idx, wcstod );
238253146Stheraven}
239253146Stheraven
240253146Stheraventemplate<>
241253146Stheraveninline
242253146Stheravenlong double
243253146Stheravenas_float( const string& func, const wstring& s, size_t* idx )
244253146Stheraven{
245253146Stheraven    return as_float_helper<long double>( func, s, idx, wcstold );
246253146Stheraven}
247253146Stheraven
248253146Stheraven}  // unnamed namespace
249253146Stheraven
250253146Stheravenint
251253146Stheravenstoi(const string& str, size_t* idx, int base)
252253146Stheraven{
253253146Stheraven    return as_integer<int>( "stoi", str, idx, base );
254253146Stheraven}
255253146Stheraven
256253146Stheravenint
257253146Stheravenstoi(const wstring& str, size_t* idx, int base)
258253146Stheraven{
259253146Stheraven    return as_integer<int>( "stoi", str, idx, base );
260253146Stheraven}
261253146Stheraven
262227825Stheravenlong
263253146Stheravenstol(const string& str, size_t* idx, int base)
264253146Stheraven{
265253146Stheraven    return as_integer<long>( "stol", str, idx, base );
266253146Stheraven}
267253146Stheraven
268253146Stheravenlong
269227825Stheravenstol(const wstring& str, size_t* idx, int base)
270227825Stheraven{
271253146Stheraven    return as_integer<long>( "stol", str, idx, base );
272227825Stheraven}
273227825Stheraven
274227825Stheravenunsigned long
275227825Stheravenstoul(const string& str, size_t* idx, int base)
276227825Stheraven{
277253146Stheraven    return as_integer<unsigned long>( "stoul", str, idx, base );
278227825Stheraven}
279227825Stheraven
280227825Stheravenunsigned long
281227825Stheravenstoul(const wstring& str, size_t* idx, int base)
282227825Stheraven{
283253146Stheraven    return as_integer<unsigned long>( "stoul", str, idx, base );
284227825Stheraven}
285227825Stheraven
286227825Stheravenlong long
287227825Stheravenstoll(const string& str, size_t* idx, int base)
288227825Stheraven{
289253146Stheraven    return as_integer<long long>( "stoll", str, idx, base );
290227825Stheraven}
291227825Stheraven
292227825Stheravenlong long
293227825Stheravenstoll(const wstring& str, size_t* idx, int base)
294227825Stheraven{
295253146Stheraven    return as_integer<long long>( "stoll", str, idx, base );
296227825Stheraven}
297227825Stheraven
298227825Stheravenunsigned long long
299227825Stheravenstoull(const string& str, size_t* idx, int base)
300227825Stheraven{
301253146Stheraven    return as_integer<unsigned long long>( "stoull", str, idx, base );
302227825Stheraven}
303227825Stheraven
304227825Stheravenunsigned long long
305227825Stheravenstoull(const wstring& str, size_t* idx, int base)
306227825Stheraven{
307253146Stheraven    return as_integer<unsigned long long>( "stoull", str, idx, base );
308227825Stheraven}
309227825Stheraven
310227825Stheravenfloat
311227825Stheravenstof(const string& str, size_t* idx)
312227825Stheraven{
313253146Stheraven    return as_float<float>( "stof", str, idx );
314227825Stheraven}
315227825Stheraven
316227825Stheravenfloat
317227825Stheravenstof(const wstring& str, size_t* idx)
318227825Stheraven{
319253146Stheraven    return as_float<float>( "stof", str, idx );
320227825Stheraven}
321227825Stheraven
322227825Stheravendouble
323227825Stheravenstod(const string& str, size_t* idx)
324227825Stheraven{
325253146Stheraven    return as_float<double>( "stod", str, idx );
326227825Stheraven}
327227825Stheraven
328227825Stheravendouble
329227825Stheravenstod(const wstring& str, size_t* idx)
330227825Stheraven{
331253146Stheraven    return as_float<double>( "stod", str, idx );
332227825Stheraven}
333227825Stheraven
334227825Stheravenlong double
335227825Stheravenstold(const string& str, size_t* idx)
336227825Stheraven{
337253146Stheraven    return as_float<long double>( "stold", str, idx );
338227825Stheraven}
339227825Stheraven
340227825Stheravenlong double
341227825Stheravenstold(const wstring& str, size_t* idx)
342227825Stheraven{
343253146Stheraven    return as_float<long double>( "stold", str, idx );
344227825Stheraven}
345227825Stheraven
346253146Stheraven// to_string
347253146Stheraven
348253146Stheravennamespace
349227825Stheraven{
350253146Stheraven
351253146Stheraven// as_string
352253146Stheraven
353253146Stheraventemplate<typename S, typename P, typename V >
354253146Stheraveninline
355253146StheravenS
356253146Stheravenas_string(P sprintf_like, S s, const typename S::value_type* fmt, V a)
357253146Stheraven{
358253146Stheraven    typedef typename S::size_type size_type;
359253146Stheraven    size_type available = s.size();
360227825Stheraven    while (true)
361227825Stheraven    {
362253146Stheraven        int status = sprintf_like(&s[0], available + 1, fmt, a);
363253146Stheraven        if ( status >= 0 )
364227825Stheraven        {
365253146Stheraven            size_type used = static_cast<size_type>(status);
366253146Stheraven            if ( used <= available )
367253146Stheraven            {
368253146Stheraven                s.resize( used );
369253146Stheraven                break;
370253146Stheraven            }
371253146Stheraven            available = used; // Assume this is advice of how much space we need.
372227825Stheraven        }
373253146Stheraven        else
374253146Stheraven            available = available * 2 + 1;
375253146Stheraven        s.resize(available);
376227825Stheraven    }
377227825Stheraven    return s;
378227825Stheraven}
379227825Stheraven
380353358Sdimtemplate <class S>
381253146Stheravenstruct initial_string;
382253146Stheraven
383353358Sdimtemplate <>
384353358Sdimstruct initial_string<string>
385227825Stheraven{
386253146Stheraven    string
387253146Stheraven    operator()() const
388227825Stheraven    {
389253146Stheraven        string s;
390253146Stheraven        s.resize(s.capacity());
391253146Stheraven        return s;
392227825Stheraven    }
393253146Stheraven};
394227825Stheraven
395353358Sdimtemplate <>
396353358Sdimstruct initial_string<wstring>
397227825Stheraven{
398253146Stheraven    wstring
399253146Stheraven    operator()() const
400227825Stheraven    {
401253146Stheraven        wstring s(20, wchar_t());
402253146Stheraven        s.resize(s.capacity());
403253146Stheraven        return s;
404227825Stheraven    }
405253146Stheraven};
406253146Stheraven
407253146Stheraventypedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...);
408253146Stheraven
409253146Stheraveninline
410253146Stheravenwide_printf
411253146Stheravenget_swprintf()
412253146Stheraven{
413261272Sdim#ifndef _LIBCPP_MSVCRT
414253146Stheraven    return swprintf;
415253146Stheraven#else
416321369Sdim    return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(_snwprintf);
417253146Stheraven#endif
418227825Stheraven}
419227825Stheraven
420353358Sdimtemplate <typename S, typename V>
421353358SdimS i_to_string(const V v)
422253146Stheraven{
423353358Sdim//  numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers.
424353358Sdim//  For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented),
425353358Sdim//  so we need +1 here.
426353358Sdim    constexpr size_t bufsize = numeric_limits<V>::digits10 + 2;  // +1 for minus, +1 for digits10
427353358Sdim    char buf[bufsize];
428353358Sdim    const auto res = to_chars(buf, buf + bufsize, v);
429353358Sdim    _LIBCPP_ASSERT(res.ec == errc(), "bufsize must be large enough to accomodate the value");
430353358Sdim    return S(buf, res.ptr);
431253146Stheraven}
432253146Stheraven
433353358Sdim}  // unnamed namespace
434253146Stheraven
435353358Sdimstring  to_string (int val)                { return i_to_string< string>(val); }
436353358Sdimstring  to_string (long val)               { return i_to_string< string>(val); }
437353358Sdimstring  to_string (long long val)          { return i_to_string< string>(val); }
438353358Sdimstring  to_string (unsigned val)           { return i_to_string< string>(val); }
439353358Sdimstring  to_string (unsigned long val)      { return i_to_string< string>(val); }
440353358Sdimstring  to_string (unsigned long long val) { return i_to_string< string>(val); }
441253146Stheraven
442353358Sdimwstring to_wstring(int val)                { return i_to_string<wstring>(val); }
443353358Sdimwstring to_wstring(long val)               { return i_to_string<wstring>(val); }
444353358Sdimwstring to_wstring(long long val)          { return i_to_string<wstring>(val); }
445353358Sdimwstring to_wstring(unsigned val)           { return i_to_string<wstring>(val); }
446353358Sdimwstring to_wstring(unsigned long val)      { return i_to_string<wstring>(val); }
447353358Sdimwstring to_wstring(unsigned long long val) { return i_to_string<wstring>(val); }
448253146Stheraven
449227825Stheraven
450353358Sdimstring  to_string (float val)       { return as_string(snprintf,       initial_string< string>()(),   "%f", val); }
451353358Sdimstring  to_string (double val)      { return as_string(snprintf,       initial_string< string>()(),   "%f", val); }
452353358Sdimstring  to_string (long double val) { return as_string(snprintf,       initial_string< string>()(),  "%Lf", val); }
453227825Stheraven
454353358Sdimwstring to_wstring(float val)       { return as_string(get_swprintf(), initial_string<wstring>()(),  L"%f", val); }
455353358Sdimwstring to_wstring(double val)      { return as_string(get_swprintf(), initial_string<wstring>()(),  L"%f", val); }
456353358Sdimwstring to_wstring(long double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%Lf", val); }
457227825Stheraven
458227825Stheraven_LIBCPP_END_NAMESPACE_STD
459