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 
25 template class __basic_string_common<true>;
26 
27 template class basic_string<char>;
28 template class basic_string<wchar_t>;
29 
30 template
31     string
32     operator+<char, char_traits<char>, allocator<char> >(char const*, string const&);
33 
34 namespace
35 {
36 
37 template<typename T>
38 inline
throw_helper(const string & msg)39 void 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 
49 inline
throw_from_string_out_of_range(const string & func)50 void throw_from_string_out_of_range( const string& func )
51 {
52     throw_helper<out_of_range>(func + ": out of range");
53 }
54 
55 inline
throw_from_string_invalid_arg(const string & func)56 void throw_from_string_invalid_arg( const string& func )
57 {
58     throw_helper<invalid_argument>(func + ": no conversion");
59 }
60 
61 // as_integer
62 
63 template<typename V, typename S, typename F>
64 inline
65 V
as_integer_helper(const string & func,const S & str,size_t * idx,int base,F f)66 as_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 
83 template<typename V, typename S>
84 inline
85 V
86 as_integer(const string& func, const S& s, size_t* idx, int base);
87 
88 // string
89 template<>
90 inline
91 int
as_integer(const string & func,const string & s,size_t * idx,int base)92 as_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 
101 template<>
102 inline
103 long
as_integer(const string & func,const string & s,size_t * idx,int base)104 as_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 
109 template<>
110 inline
111 unsigned long
as_integer(const string & func,const string & s,size_t * idx,int base)112 as_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 
117 template<>
118 inline
119 long long
as_integer(const string & func,const string & s,size_t * idx,int base)120 as_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 
125 template<>
126 inline
127 unsigned long long
as_integer(const string & func,const string & s,size_t * idx,int base)128 as_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
134 template<>
135 inline
136 int
as_integer(const string & func,const wstring & s,size_t * idx,int base)137 as_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 
146 template<>
147 inline
148 long
as_integer(const string & func,const wstring & s,size_t * idx,int base)149 as_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 
154 template<>
155 inline
156 unsigned long
as_integer(const string & func,const wstring & s,size_t * idx,int base)157 as_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 
162 template<>
163 inline
164 long long
as_integer(const string & func,const wstring & s,size_t * idx,int base)165 as_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 
170 template<>
171 inline
172 unsigned long long
as_integer(const string & func,const wstring & s,size_t * idx,int base)173 as_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 
180 template<typename V, typename S, typename F>
181 inline
182 V
as_float_helper(const string & func,const S & str,size_t * idx,F f)183 as_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 = static_cast<V>(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 
200 template<typename V, typename S>
201 inline
202 V as_float( const string& func, const S& s, size_t* idx = nullptr );
203 
204 template<>
205 inline
206 float
as_float(const string & func,const string & s,size_t * idx)207 as_float( const string& func, const string& s, size_t* idx )
208 {
209     return as_float_helper<float>( func, s, idx, strtod );
210 }
211 
212 template<>
213 inline
214 double
as_float(const string & func,const string & s,size_t * idx)215 as_float(const string& func, const string& s, size_t* idx )
216 {
217     return as_float_helper<double>( func, s, idx, strtod );
218 }
219 
220 template<>
221 inline
222 long double
as_float(const string & func,const string & s,size_t * idx)223 as_float( const string& func, const string& s, size_t* idx )
224 {
225     return as_float_helper<long double>( func, s, idx, strtold );
226 }
227 
228 template<>
229 inline
230 float
as_float(const string & func,const wstring & s,size_t * idx)231 as_float( const string& func, const wstring& s, size_t* idx )
232 {
233     return as_float_helper<float>( func, s, idx, wcstod );
234 }
235 
236 template<>
237 inline
238 double
as_float(const string & func,const wstring & s,size_t * idx)239 as_float( const string& func, const wstring& s, size_t* idx )
240 {
241     return as_float_helper<double>( func, s, idx, wcstod );
242 }
243 
244 template<>
245 inline
246 long double
as_float(const string & func,const wstring & s,size_t * idx)247 as_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 
254 int
stoi(const string & str,size_t * idx,int base)255 stoi(const string& str, size_t* idx, int base)
256 {
257     return as_integer<int>( "stoi", str, idx, base );
258 }
259 
260 int
stoi(const wstring & str,size_t * idx,int base)261 stoi(const wstring& str, size_t* idx, int base)
262 {
263     return as_integer<int>( "stoi", str, idx, base );
264 }
265 
266 long
stol(const string & str,size_t * idx,int base)267 stol(const string& str, size_t* idx, int base)
268 {
269     return as_integer<long>( "stol", str, idx, base );
270 }
271 
272 long
stol(const wstring & str,size_t * idx,int base)273 stol(const wstring& str, size_t* idx, int base)
274 {
275     return as_integer<long>( "stol", str, idx, base );
276 }
277 
278 unsigned long
stoul(const string & str,size_t * idx,int base)279 stoul(const string& str, size_t* idx, int base)
280 {
281     return as_integer<unsigned long>( "stoul", str, idx, base );
282 }
283 
284 unsigned long
stoul(const wstring & str,size_t * idx,int base)285 stoul(const wstring& str, size_t* idx, int base)
286 {
287     return as_integer<unsigned long>( "stoul", str, idx, base );
288 }
289 
290 long long
stoll(const string & str,size_t * idx,int base)291 stoll(const string& str, size_t* idx, int base)
292 {
293     return as_integer<long long>( "stoll", str, idx, base );
294 }
295 
296 long long
stoll(const wstring & str,size_t * idx,int base)297 stoll(const wstring& str, size_t* idx, int base)
298 {
299     return as_integer<long long>( "stoll", str, idx, base );
300 }
301 
302 unsigned long long
stoull(const string & str,size_t * idx,int base)303 stoull(const string& str, size_t* idx, int base)
304 {
305     return as_integer<unsigned long long>( "stoull", str, idx, base );
306 }
307 
308 unsigned long long
stoull(const wstring & str,size_t * idx,int base)309 stoull(const wstring& str, size_t* idx, int base)
310 {
311     return as_integer<unsigned long long>( "stoull", str, idx, base );
312 }
313 
314 float
stof(const string & str,size_t * idx)315 stof(const string& str, size_t* idx)
316 {
317     return as_float<float>( "stof", str, idx );
318 }
319 
320 float
stof(const wstring & str,size_t * idx)321 stof(const wstring& str, size_t* idx)
322 {
323     return as_float<float>( "stof", str, idx );
324 }
325 
326 double
stod(const string & str,size_t * idx)327 stod(const string& str, size_t* idx)
328 {
329     return as_float<double>( "stod", str, idx );
330 }
331 
332 double
stod(const wstring & str,size_t * idx)333 stod(const wstring& str, size_t* idx)
334 {
335     return as_float<double>( "stod", str, idx );
336 }
337 
338 long double
stold(const string & str,size_t * idx)339 stold(const string& str, size_t* idx)
340 {
341     return as_float<long double>( "stold", str, idx );
342 }
343 
344 long double
stold(const wstring & str,size_t * idx)345 stold(const wstring& str, size_t* idx)
346 {
347     return as_float<long double>( "stold", str, idx );
348 }
349 
350 // to_string
351 
352 namespace
353 {
354 
355 // as_string
356 
357 template<typename S, typename P, typename V >
358 inline
359 S
as_string(P sprintf_like,S s,const typename S::value_type * fmt,V a)360 as_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 
384 template <class S, class V, bool = is_floating_point<V>::value>
385 struct initial_string;
386 
387 template <class V, bool b>
388 struct initial_string<string, V, b>
389 {
390     string
operator ()__anoncc727eff0211::initial_string391     operator()() const
392     {
393         string s;
394         s.resize(s.capacity());
395         return s;
396     }
397 };
398 
399 template <class V>
400 struct initial_string<wstring, V, false>
401 {
402     wstring
operator ()__anoncc727eff0211::initial_string403     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 
414 template <class V>
415 struct initial_string<wstring, V, true>
416 {
417     wstring
operator ()__anoncc727eff0211::initial_string418     operator()() const
419     {
420         wstring s(20, wchar_t());
421         s.resize(s.capacity());
422         return s;
423     }
424 };
425 
426 typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...);
427 
428 inline
429 wide_printf
get_swprintf()430 get_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 
to_string(int val)441 string to_string(int val)
442 {
443     return as_string(snprintf, initial_string<string, int>()(), "%d", val);
444 }
445 
to_string(unsigned val)446 string to_string(unsigned val)
447 {
448     return as_string(snprintf, initial_string<string, unsigned>()(), "%u", val);
449 }
450 
to_string(long val)451 string to_string(long val)
452 {
453     return as_string(snprintf, initial_string<string, long>()(), "%ld", val);
454 }
455 
to_string(unsigned long val)456 string to_string(unsigned long val)
457 {
458     return as_string(snprintf, initial_string<string, unsigned long>()(), "%lu", val);
459 }
460 
to_string(long long val)461 string to_string(long long val)
462 {
463     return as_string(snprintf, initial_string<string, long long>()(), "%lld", val);
464 }
465 
to_string(unsigned long long val)466 string to_string(unsigned long long val)
467 {
468     return as_string(snprintf, initial_string<string, unsigned long long>()(), "%llu", val);
469 }
470 
to_string(float val)471 string to_string(float val)
472 {
473     return as_string(snprintf, initial_string<string, float>()(), "%f", val);
474 }
475 
to_string(double val)476 string to_string(double val)
477 {
478     return as_string(snprintf, initial_string<string, double>()(), "%f", val);
479 }
480 
to_string(long double val)481 string to_string(long double val)
482 {
483     return as_string(snprintf, initial_string<string, long double>()(), "%Lf", val);
484 }
485 
to_wstring(int val)486 wstring to_wstring(int val)
487 {
488     return as_string(get_swprintf(), initial_string<wstring, int>()(), L"%d", val);
489 }
490 
to_wstring(unsigned val)491 wstring to_wstring(unsigned val)
492 {
493     return as_string(get_swprintf(), initial_string<wstring, unsigned>()(), L"%u", val);
494 }
495 
to_wstring(long val)496 wstring to_wstring(long val)
497 {
498     return as_string(get_swprintf(), initial_string<wstring, long>()(), L"%ld", val);
499 }
500 
to_wstring(unsigned long val)501 wstring to_wstring(unsigned long val)
502 {
503     return as_string(get_swprintf(), initial_string<wstring, unsigned long>()(), L"%lu", val);
504 }
505 
to_wstring(long long val)506 wstring to_wstring(long long val)
507 {
508     return as_string(get_swprintf(), initial_string<wstring, long long>()(), L"%lld", val);
509 }
510 
to_wstring(unsigned long long val)511 wstring to_wstring(unsigned long long val)
512 {
513     return as_string(get_swprintf(), initial_string<wstring, unsigned long long>()(), L"%llu", val);
514 }
515 
to_wstring(float val)516 wstring to_wstring(float val)
517 {
518     return as_string(get_swprintf(), initial_string<wstring, float>()(), L"%f", val);
519 }
520 
to_wstring(double val)521 wstring to_wstring(double val)
522 {
523     return as_string(get_swprintf(), initial_string<wstring, double>()(), L"%f", val);
524 }
525 
to_wstring(long double val)526 wstring 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