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