]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/libc++/src/string.cpp
MFC r261283:
[FreeBSD/stable/9.git] / contrib / libc++ / src / string.cpp
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 = 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
207 as_float( const string& func, const string& s, size_t* idx )
208 {
209     return as_float_helper<float>( func, s, idx, strtof );
210 }
211
212 template<>
213 inline
214 double
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
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
231 as_float( const string& func, const wstring& s, size_t* idx )
232 {
233     return as_float_helper<float>( func, s, idx, wcstof );
234 }
235
236 template<>
237 inline
238 double
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
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
255 stoi(const string& str, size_t* idx, int base)
256 {
257     return as_integer<int>( "stoi", str, idx, base );
258 }
259
260 int
261 stoi(const wstring& str, size_t* idx, int base)
262 {
263     return as_integer<int>( "stoi", str, idx, base );
264 }
265
266 long
267 stol(const string& str, size_t* idx, int base)
268 {
269     return as_integer<long>( "stol", str, idx, base );
270 }
271
272 long
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
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
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
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
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
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
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
315 stof(const string& str, size_t* idx)
316 {
317     return as_float<float>( "stof", str, idx );
318 }
319
320 float
321 stof(const wstring& str, size_t* idx)
322 {
323     return as_float<float>( "stof", str, idx );
324 }
325
326 double
327 stod(const string& str, size_t* idx)
328 {
329     return as_float<double>( "stod", str, idx );
330 }
331
332 double
333 stod(const wstring& str, size_t* idx)
334 {
335     return as_float<double>( "stod", str, idx );
336 }
337
338 long double
339 stold(const string& str, size_t* idx)
340 {
341     return as_float<long double>( "stold", str, idx );
342 }
343
344 long double
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
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
391     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
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
414 template <class V>
415 struct 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
426 typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...);
427
428 inline
429 wide_printf
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
441 string to_string(int val)
442 {
443     return as_string(snprintf, initial_string<string, int>()(), "%d", val);
444 }
445
446 string to_string(unsigned val)
447 {
448     return as_string(snprintf, initial_string<string, unsigned>()(), "%u", val);
449 }
450
451 string to_string(long val)
452 {
453     return as_string(snprintf, initial_string<string, long>()(), "%ld", val);
454 }
455
456 string to_string(unsigned long val)
457 {
458     return as_string(snprintf, initial_string<string, unsigned long>()(), "%lu", val);
459 }
460
461 string to_string(long long val)
462 {
463     return as_string(snprintf, initial_string<string, long long>()(), "%lld", val);
464 }
465
466 string to_string(unsigned long long val)
467 {
468     return as_string(snprintf, initial_string<string, unsigned long long>()(), "%llu", val);
469 }
470
471 string to_string(float val)
472 {
473     return as_string(snprintf, initial_string<string, float>()(), "%f", val);
474 }
475
476 string to_string(double val)
477 {
478     return as_string(snprintf, initial_string<string, double>()(), "%f", val);
479 }
480
481 string to_string(long double val)
482 {
483     return as_string(snprintf, initial_string<string, long double>()(), "%Lf", val);
484 }
485
486 wstring to_wstring(int val)
487 {
488     return as_string(get_swprintf(), initial_string<wstring, int>()(), L"%d", val);
489 }
490
491 wstring to_wstring(unsigned val)
492 {
493     return as_string(get_swprintf(), initial_string<wstring, unsigned>()(), L"%u", val);
494 }
495
496 wstring to_wstring(long val)
497 {
498     return as_string(get_swprintf(), initial_string<wstring, long>()(), L"%ld", val);
499 }
500
501 wstring to_wstring(unsigned long val)
502 {
503     return as_string(get_swprintf(), initial_string<wstring, unsigned long>()(), L"%lu", val);
504 }
505
506 wstring to_wstring(long long val)
507 {
508     return as_string(get_swprintf(), initial_string<wstring, long long>()(), L"%lld", val);
509 }
510
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
516 wstring to_wstring(float val)
517 {
518     return as_string(get_swprintf(), initial_string<wstring, float>()(), L"%f", val);
519 }
520
521 wstring to_wstring(double val)
522 {
523     return as_string(get_swprintf(), initial_string<wstring, double>()(), L"%f", val);
524 }
525
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