1//===------------------------- string.cpp ---------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
11
12#include "string"
13#include "cstdlib"
14#include "cwchar"
15#include "cerrno"
16#include "limits"
17#include "stdexcept"
18#ifdef _LIBCPP_MSVCRT
19#include "support/win32/support.h"
20#endif // _LIBCPP_MSVCRT
21#include <stdio.h>
22
23_LIBCPP_BEGIN_NAMESPACE_STD
24
25template class __basic_string_common<true>;
26
27template class basic_string<char>;
28template class basic_string<wchar_t>;
29
30template
31    string
32    operator+<char, char_traits<char>, allocator<char> >(char const*, string const&);
33
34namespace
35{
36
37template<typename T>
38inline
39void throw_helper( const string& msg )
40{
41#ifndef _LIBCPP_NO_EXCEPTIONS
42    throw T( msg );
43#else
44    printf("%s\n", msg.c_str());
45    abort();
46#endif
47}
48
49inline
50void throw_from_string_out_of_range( const string& func )
51{
52    throw_helper<out_of_range>(func + ": out of range");
53}
54
55inline
56void throw_from_string_invalid_arg( const string& func )
57{
58    throw_helper<invalid_argument>(func + ": no conversion");
59}
60
61// as_integer
62
63template<typename V, typename S, typename F>
64inline
65V
66as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f)
67{
68    typename S::value_type* ptr;
69    const typename S::value_type* const p = str.c_str();
70    typename remove_reference<decltype(errno)>::type errno_save = errno;
71    errno = 0;
72    V r = f(p, &ptr, base);
73    swap(errno, errno_save);
74    if (errno_save == ERANGE)
75        throw_from_string_out_of_range(func);
76    if (ptr == p)
77        throw_from_string_invalid_arg(func);
78    if (idx)
79        *idx = static_cast<size_t>(ptr - p);
80    return r;
81}
82
83template<typename V, typename S>
84inline
85V
86as_integer(const string& func, const S& s, size_t* idx, int base);
87
88// string
89template<>
90inline
91int
92as_integer(const string& func, const string& s, size_t* idx, int base )
93{
94    // Use long as no Standard string to integer exists.
95    long r = as_integer_helper<long>( func, s, idx, base, strtol );
96    if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
97        throw_from_string_out_of_range(func);
98    return static_cast<int>(r);
99}
100
101template<>
102inline
103long
104as_integer(const string& func, const string& s, size_t* idx, int base )
105{
106    return as_integer_helper<long>( func, s, idx, base, strtol );
107}
108
109template<>
110inline
111unsigned long
112as_integer( const string& func, const string& s, size_t* idx, int base )
113{
114    return as_integer_helper<unsigned long>( func, s, idx, base, strtoul );
115}
116
117template<>
118inline
119long long
120as_integer( const string& func, const string& s, size_t* idx, int base )
121{
122    return as_integer_helper<long long>( func, s, idx, base, strtoll );
123}
124
125template<>
126inline
127unsigned long long
128as_integer( const string& func, const string& s, size_t* idx, int base )
129{
130    return as_integer_helper<unsigned long long>( func, s, idx, base, strtoull );
131}
132
133// wstring
134template<>
135inline
136int
137as_integer( const string& func, const wstring& s, size_t* idx, int base )
138{
139    // Use long as no Stantard string to integer exists.
140    long r = as_integer_helper<long>( func, s, idx, base, wcstol );
141    if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
142        throw_from_string_out_of_range(func);
143    return static_cast<int>(r);
144}
145
146template<>
147inline
148long
149as_integer( const string& func, const wstring& s, size_t* idx, int base )
150{
151    return as_integer_helper<long>( func, s, idx, base, wcstol );
152}
153
154template<>
155inline
156unsigned long
157as_integer( const string& func, const wstring& s, size_t* idx, int base )
158{
159    return as_integer_helper<unsigned long>( func, s, idx, base, wcstoul );
160}
161
162template<>
163inline
164long long
165as_integer( const string& func, const wstring& s, size_t* idx, int base )
166{
167    return as_integer_helper<long long>( func, s, idx, base, wcstoll );
168}
169
170template<>
171inline
172unsigned long long
173as_integer( const string& func, const wstring& s, size_t* idx, int base )
174{
175    return as_integer_helper<unsigned long long>( func, s, idx, base, wcstoull );
176}
177
178// as_float
179
180template<typename V, typename S, typename F>
181inline
182V
183as_float_helper(const string& func, const S& str, size_t* idx, F f )
184{
185    typename S::value_type* ptr;
186    const typename S::value_type* const p = str.c_str();
187    typename remove_reference<decltype(errno)>::type errno_save = errno;
188    errno = 0;
189    V r = f(p, &ptr);
190    swap(errno, errno_save);
191    if (errno_save == ERANGE)
192        throw_from_string_out_of_range(func);
193    if (ptr == p)
194        throw_from_string_invalid_arg(func);
195    if (idx)
196        *idx = static_cast<size_t>(ptr - p);
197    return r;
198}
199
200template<typename V, typename S>
201inline
202V as_float( const string& func, const S& s, size_t* idx = nullptr );
203
204template<>
205inline
206float
207as_float( const string& func, const string& s, size_t* idx )
208{
209    return as_float_helper<float>( func, s, idx, strtof );
210}
211
212template<>
213inline
214double
215as_float(const string& func, const string& s, size_t* idx )
216{
217    return as_float_helper<double>( func, s, idx, strtod );
218}
219
220template<>
221inline
222long double
223as_float( const string& func, const string& s, size_t* idx )
224{
225    return as_float_helper<long double>( func, s, idx, strtold );
226}
227
228template<>
229inline
230float
231as_float( const string& func, const wstring& s, size_t* idx )
232{
233    return as_float_helper<float>( func, s, idx, wcstof );
234}
235
236template<>
237inline
238double
239as_float( const string& func, const wstring& s, size_t* idx )
240{
241    return as_float_helper<double>( func, s, idx, wcstod );
242}
243
244template<>
245inline
246long double
247as_float( const string& func, const wstring& s, size_t* idx )
248{
249    return as_float_helper<long double>( func, s, idx, wcstold );
250}
251
252}  // unnamed namespace
253
254int
255stoi(const string& str, size_t* idx, int base)
256{
257    return as_integer<int>( "stoi", str, idx, base );
258}
259
260int
261stoi(const wstring& str, size_t* idx, int base)
262{
263    return as_integer<int>( "stoi", str, idx, base );
264}
265
266long
267stol(const string& str, size_t* idx, int base)
268{
269    return as_integer<long>( "stol", str, idx, base );
270}
271
272long
273stol(const wstring& str, size_t* idx, int base)
274{
275    return as_integer<long>( "stol", str, idx, base );
276}
277
278unsigned long
279stoul(const string& str, size_t* idx, int base)
280{
281    return as_integer<unsigned long>( "stoul", str, idx, base );
282}
283
284unsigned long
285stoul(const wstring& str, size_t* idx, int base)
286{
287    return as_integer<unsigned long>( "stoul", str, idx, base );
288}
289
290long long
291stoll(const string& str, size_t* idx, int base)
292{
293    return as_integer<long long>( "stoll", str, idx, base );
294}
295
296long long
297stoll(const wstring& str, size_t* idx, int base)
298{
299    return as_integer<long long>( "stoll", str, idx, base );
300}
301
302unsigned long long
303stoull(const string& str, size_t* idx, int base)
304{
305    return as_integer<unsigned long long>( "stoull", str, idx, base );
306}
307
308unsigned long long
309stoull(const wstring& str, size_t* idx, int base)
310{
311    return as_integer<unsigned long long>( "stoull", str, idx, base );
312}
313
314float
315stof(const string& str, size_t* idx)
316{
317    return as_float<float>( "stof", str, idx );
318}
319
320float
321stof(const wstring& str, size_t* idx)
322{
323    return as_float<float>( "stof", str, idx );
324}
325
326double
327stod(const string& str, size_t* idx)
328{
329    return as_float<double>( "stod", str, idx );
330}
331
332double
333stod(const wstring& str, size_t* idx)
334{
335    return as_float<double>( "stod", str, idx );
336}
337
338long double
339stold(const string& str, size_t* idx)
340{
341    return as_float<long double>( "stold", str, idx );
342}
343
344long double
345stold(const wstring& str, size_t* idx)
346{
347    return as_float<long double>( "stold", str, idx );
348}
349
350// to_string
351
352namespace
353{
354
355// as_string
356
357template<typename S, typename P, typename V >
358inline
359S
360as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a)
361{
362    typedef typename S::size_type size_type;
363    size_type available = s.size();
364    while (true)
365    {
366        int status = sprintf_like(&s[0], available + 1, fmt, a);
367        if ( status >= 0 )
368        {
369            size_type used = static_cast<size_type>(status);
370            if ( used <= available )
371            {
372                s.resize( used );
373                break;
374            }
375            available = used; // Assume this is advice of how much space we need.
376        }
377        else
378            available = available * 2 + 1;
379        s.resize(available);
380    }
381    return s;
382}
383
384template <class S, class V, bool = is_floating_point<V>::value>
385struct initial_string;
386
387template <class V, bool b>
388struct initial_string<string, V, b>
389{
390    string
391    operator()() const
392    {
393        string s;
394        s.resize(s.capacity());
395        return s;
396    }
397};
398
399template <class V>
400struct initial_string<wstring, V, false>
401{
402    wstring
403    operator()() const
404    {
405        const size_t n = (numeric_limits<unsigned long long>::digits / 3)
406          + ((numeric_limits<unsigned long long>::digits % 3) != 0)
407          + 1;
408        wstring s(n, wchar_t());
409        s.resize(s.capacity());
410        return s;
411    }
412};
413
414template <class V>
415struct initial_string<wstring, V, true>
416{
417    wstring
418    operator()() const
419    {
420        wstring s(20, wchar_t());
421        s.resize(s.capacity());
422        return s;
423    }
424};
425
426typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...);
427
428inline
429wide_printf
430get_swprintf()
431{
432#ifndef _LIBCPP_MSVCRT
433    return swprintf;
434#else
435    return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(swprintf);
436#endif
437}
438
439}  // unnamed namespace
440
441string to_string(int val)
442{
443    return as_string(snprintf, initial_string<string, int>()(), "%d", val);
444}
445
446string to_string(unsigned val)
447{
448    return as_string(snprintf, initial_string<string, unsigned>()(), "%u", val);
449}
450
451string to_string(long val)
452{
453    return as_string(snprintf, initial_string<string, long>()(), "%ld", val);
454}
455
456string to_string(unsigned long val)
457{
458    return as_string(snprintf, initial_string<string, unsigned long>()(), "%lu", val);
459}
460
461string to_string(long long val)
462{
463    return as_string(snprintf, initial_string<string, long long>()(), "%lld", val);
464}
465
466string to_string(unsigned long long val)
467{
468    return as_string(snprintf, initial_string<string, unsigned long long>()(), "%llu", val);
469}
470
471string to_string(float val)
472{
473    return as_string(snprintf, initial_string<string, float>()(), "%f", val);
474}
475
476string to_string(double val)
477{
478    return as_string(snprintf, initial_string<string, double>()(), "%f", val);
479}
480
481string to_string(long double val)
482{
483    return as_string(snprintf, initial_string<string, long double>()(), "%Lf", val);
484}
485
486wstring to_wstring(int val)
487{
488    return as_string(get_swprintf(), initial_string<wstring, int>()(), L"%d", val);
489}
490
491wstring to_wstring(unsigned val)
492{
493    return as_string(get_swprintf(), initial_string<wstring, unsigned>()(), L"%u", val);
494}
495
496wstring to_wstring(long val)
497{
498    return as_string(get_swprintf(), initial_string<wstring, long>()(), L"%ld", val);
499}
500
501wstring to_wstring(unsigned long val)
502{
503    return as_string(get_swprintf(), initial_string<wstring, unsigned long>()(), L"%lu", val);
504}
505
506wstring to_wstring(long long val)
507{
508    return as_string(get_swprintf(), initial_string<wstring, long long>()(), L"%lld", val);
509}
510
511wstring to_wstring(unsigned long long val)
512{
513    return as_string(get_swprintf(), initial_string<wstring, unsigned long long>()(), L"%llu", val);
514}
515
516wstring to_wstring(float val)
517{
518    return as_string(get_swprintf(), initial_string<wstring, float>()(), L"%f", val);
519}
520
521wstring to_wstring(double val)
522{
523    return as_string(get_swprintf(), initial_string<wstring, double>()(), L"%f", val);
524}
525
526wstring to_wstring(long double val)
527{
528    return as_string(get_swprintf(), initial_string<wstring, long double>()(), L"%Lf", val);
529}
530_LIBCPP_END_NAMESPACE_STD
531