xref: /llvm-project-15.0.7/libcxx/src/string.cpp (revision 851b96e7)
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 #include "string"
11 #include "cstdlib"
12 #include "cwchar"
13 #include "cerrno"
14 
15 _LIBCPP_BEGIN_NAMESPACE_STD
16 
17 template class __basic_string_common<true>;
18 
19 template class basic_string<char>;
20 template class basic_string<wchar_t>;
21 
22 template
23     string
24     operator+<char, char_traits<char>, allocator<char> >(char const*, string const&);
25 
26 int
27 stoi(const string& str, size_t* idx, int base)
28 {
29     char* ptr;
30     const char* const p = str.c_str();
31     long r = strtol(p, &ptr, base);
32     if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
33         ptr = const_cast<char*>(p);
34     if (ptr == p)
35     {
36 #ifndef _LIBCPP_NO_EXCEPTIONS
37         if (r == 0)
38             throw invalid_argument("stoi: no conversion");
39         throw out_of_range("stoi: out of range");
40 #endif  // _LIBCPP_NO_EXCEPTIONS
41     }
42     if (idx)
43         *idx = static_cast<size_t>(ptr - p);
44     return static_cast<int>(r);
45 }
46 
47 int
48 stoi(const wstring& str, size_t* idx, int base)
49 {
50     wchar_t* ptr;
51     const wchar_t* const p = str.c_str();
52     long r = wcstol(p, &ptr, base);
53     if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
54         ptr = const_cast<wchar_t*>(p);
55     if (ptr == p)
56     {
57 #ifndef _LIBCPP_NO_EXCEPTIONS
58         if (r == 0)
59             throw invalid_argument("stoi: no conversion");
60         throw out_of_range("stoi: out of range");
61 #endif  // _LIBCPP_NO_EXCEPTIONS
62     }
63     if (idx)
64         *idx = static_cast<size_t>(ptr - p);
65     return static_cast<int>(r);
66 }
67 
68 long
69 stol(const string& str, size_t* idx, int base)
70 {
71     char* ptr;
72     const char* const p = str.c_str();
73     long r = strtol(p, &ptr, base);
74     if (ptr == p)
75     {
76 #ifndef _LIBCPP_NO_EXCEPTIONS
77         if (r == 0)
78             throw invalid_argument("stol: no conversion");
79         throw out_of_range("stol: out of range");
80 #endif  // _LIBCPP_NO_EXCEPTIONS
81     }
82     if (idx)
83         *idx = static_cast<size_t>(ptr - p);
84     return r;
85 }
86 
87 long
88 stol(const wstring& str, size_t* idx, int base)
89 {
90     wchar_t* ptr;
91     const wchar_t* const p = str.c_str();
92     long r = wcstol(p, &ptr, base);
93     if (ptr == p)
94     {
95 #ifndef _LIBCPP_NO_EXCEPTIONS
96         if (r == 0)
97             throw invalid_argument("stol: no conversion");
98         throw out_of_range("stol: out of range");
99 #endif  // _LIBCPP_NO_EXCEPTIONS
100     }
101     if (idx)
102         *idx = static_cast<size_t>(ptr - p);
103     return r;
104 }
105 
106 unsigned long
107 stoul(const string& str, size_t* idx, int base)
108 {
109     char* ptr;
110     const char* const p = str.c_str();
111     unsigned long r = strtoul(p, &ptr, base);
112     if (ptr == p)
113     {
114 #ifndef _LIBCPP_NO_EXCEPTIONS
115         if (r == 0)
116             throw invalid_argument("stoul: no conversion");
117         throw out_of_range("stoul: out of range");
118 #endif  // _LIBCPP_NO_EXCEPTIONS
119     }
120     if (idx)
121         *idx = static_cast<size_t>(ptr - p);
122     return r;
123 }
124 
125 unsigned long
126 stoul(const wstring& str, size_t* idx, int base)
127 {
128     wchar_t* ptr;
129     const wchar_t* const p = str.c_str();
130     unsigned long r = wcstoul(p, &ptr, base);
131     if (ptr == p)
132     {
133 #ifndef _LIBCPP_NO_EXCEPTIONS
134         if (r == 0)
135             throw invalid_argument("stoul: no conversion");
136         throw out_of_range("stoul: out of range");
137 #endif  // _LIBCPP_NO_EXCEPTIONS
138     }
139     if (idx)
140         *idx = static_cast<size_t>(ptr - p);
141     return r;
142 }
143 
144 long long
145 stoll(const string& str, size_t* idx, int base)
146 {
147     char* ptr;
148     const char* const p = str.c_str();
149     long long r = strtoll(p, &ptr, base);
150     if (ptr == p)
151     {
152 #ifndef _LIBCPP_NO_EXCEPTIONS
153         if (r == 0)
154             throw invalid_argument("stoll: no conversion");
155         throw out_of_range("stoll: out of range");
156 #endif  // _LIBCPP_NO_EXCEPTIONS
157     }
158     if (idx)
159         *idx = static_cast<size_t>(ptr - p);
160     return r;
161 }
162 
163 long long
164 stoll(const wstring& str, size_t* idx, int base)
165 {
166     wchar_t* ptr;
167     const wchar_t* const p = str.c_str();
168     long long r = wcstoll(p, &ptr, base);
169     if (ptr == p)
170     {
171 #ifndef _LIBCPP_NO_EXCEPTIONS
172         if (r == 0)
173             throw invalid_argument("stoll: no conversion");
174         throw out_of_range("stoll: out of range");
175 #endif  // _LIBCPP_NO_EXCEPTIONS
176     }
177     if (idx)
178         *idx = static_cast<size_t>(ptr - p);
179     return r;
180 }
181 
182 unsigned long long
183 stoull(const string& str, size_t* idx, int base)
184 {
185     char* ptr;
186     const char* const p = str.c_str();
187     unsigned long long r = strtoull(p, &ptr, base);
188     if (ptr == p)
189     {
190 #ifndef _LIBCPP_NO_EXCEPTIONS
191         if (r == 0)
192             throw invalid_argument("stoull: no conversion");
193         throw out_of_range("stoull: out of range");
194 #endif  // _LIBCPP_NO_EXCEPTIONS
195     }
196     if (idx)
197         *idx = static_cast<size_t>(ptr - p);
198     return r;
199 }
200 
201 unsigned long long
202 stoull(const wstring& str, size_t* idx, int base)
203 {
204     wchar_t* ptr;
205     const wchar_t* const p = str.c_str();
206     unsigned long long r = wcstoull(p, &ptr, base);
207     if (ptr == p)
208     {
209 #ifndef _LIBCPP_NO_EXCEPTIONS
210         if (r == 0)
211             throw invalid_argument("stoull: no conversion");
212         throw out_of_range("stoull: out of range");
213 #endif  // _LIBCPP_NO_EXCEPTIONS
214     }
215     if (idx)
216         *idx = static_cast<size_t>(ptr - p);
217     return r;
218 }
219 
220 float
221 stof(const string& str, size_t* idx)
222 {
223     char* ptr;
224     const char* const p = str.c_str();
225     int errno_save = errno;
226     errno = 0;
227     double r = strtod(p, &ptr);
228     swap(errno, errno_save);
229 #ifndef _LIBCPP_NO_EXCEPTIONS
230     if (errno_save == ERANGE)
231         throw out_of_range("stof: out of range");
232     if (ptr == p)
233         throw invalid_argument("stof: no conversion");
234 #endif  // _LIBCPP_NO_EXCEPTIONS
235     if (idx)
236         *idx = static_cast<size_t>(ptr - p);
237     return static_cast<float>(r);
238 }
239 
240 float
241 stof(const wstring& str, size_t* idx)
242 {
243     wchar_t* ptr;
244     const wchar_t* const p = str.c_str();
245     int errno_save = errno;
246     errno = 0;
247     double r = wcstod(p, &ptr);
248     swap(errno, errno_save);
249 #ifndef _LIBCPP_NO_EXCEPTIONS
250     if (errno_save == ERANGE)
251         throw out_of_range("stof: out of range");
252     if (ptr == p)
253         throw invalid_argument("stof: no conversion");
254 #endif  // _LIBCPP_NO_EXCEPTIONS
255     if (idx)
256         *idx = static_cast<size_t>(ptr - p);
257     return static_cast<float>(r);
258 }
259 
260 double
261 stod(const string& str, size_t* idx)
262 {
263     char* ptr;
264     const char* const p = str.c_str();
265     int errno_save = errno;
266     errno = 0;
267     double r = strtod(p, &ptr);
268     swap(errno, errno_save);
269 #ifndef _LIBCPP_NO_EXCEPTIONS
270     if (errno_save == ERANGE)
271         throw out_of_range("stod: out of range");
272     if (ptr == p)
273         throw invalid_argument("stod: no conversion");
274 #endif  // _LIBCPP_NO_EXCEPTIONS
275     if (idx)
276         *idx = static_cast<size_t>(ptr - p);
277     return r;
278 }
279 
280 double
281 stod(const wstring& str, size_t* idx)
282 {
283     wchar_t* ptr;
284     const wchar_t* const p = str.c_str();
285     int errno_save = errno;
286     errno = 0;
287     double r = wcstod(p, &ptr);
288     swap(errno, errno_save);
289 #ifndef _LIBCPP_NO_EXCEPTIONS
290     if (errno_save == ERANGE)
291         throw out_of_range("stod: out of range");
292     if (ptr == p)
293         throw invalid_argument("stod: no conversion");
294 #endif  // _LIBCPP_NO_EXCEPTIONS
295     if (idx)
296         *idx = static_cast<size_t>(ptr - p);
297     return r;
298 }
299 
300 long double
301 stold(const string& str, size_t* idx)
302 {
303     char* ptr;
304     const char* const p = str.c_str();
305     int errno_save = errno;
306     errno = 0;
307     long double r = strtold(p, &ptr);
308     swap(errno, errno_save);
309 #ifndef _LIBCPP_NO_EXCEPTIONS
310     if (errno_save == ERANGE)
311         throw out_of_range("stold: out of range");
312     if (ptr == p)
313         throw invalid_argument("stold: no conversion");
314 #endif  // _LIBCPP_NO_EXCEPTIONS
315     if (idx)
316         *idx = static_cast<size_t>(ptr - p);
317     return r;
318 }
319 
320 long double
321 stold(const wstring& str, size_t* idx)
322 {
323     wchar_t* ptr;
324     const wchar_t* const p = str.c_str();
325     int errno_save = errno;
326     errno = 0;
327     long double r = wcstold(p, &ptr);
328     swap(errno, errno_save);
329 #ifndef _LIBCPP_NO_EXCEPTIONS
330     if (errno_save == ERANGE)
331         throw out_of_range("stold: out of range");
332     if (ptr == p)
333         throw invalid_argument("stold: no conversion");
334 #endif  // _LIBCPP_NO_EXCEPTIONS
335     if (idx)
336         *idx = static_cast<size_t>(ptr - p);
337     return r;
338 }
339 
340 string to_string(int val)
341 {
342     string s;
343     s.resize(s.capacity());
344     while (true)
345     {
346         int n2 = snprintf(&s[0], s.size()+1, "%d", val);
347         if (n2 <= s.size())
348         {
349             s.resize(n2);
350             break;
351         }
352         s.resize(n2);
353     }
354     return s;
355 }
356 
357 string to_string(unsigned val)
358 {
359     string s;
360     s.resize(s.capacity());
361     while (true)
362     {
363         int n2 = snprintf(&s[0], s.size()+1, "%u", val);
364         if (n2 <= s.size())
365         {
366             s.resize(n2);
367             break;
368         }
369         s.resize(n2);
370     }
371     return s;
372 }
373 
374 string to_string(long val)
375 {
376     string s;
377     s.resize(s.capacity());
378     while (true)
379     {
380         int n2 = snprintf(&s[0], s.size()+1, "%ld", val);
381         if (n2 <= s.size())
382         {
383             s.resize(n2);
384             break;
385         }
386         s.resize(n2);
387     }
388     return s;
389 }
390 
391 string to_string(unsigned long val)
392 {
393     string s;
394     s.resize(s.capacity());
395     while (true)
396     {
397         int n2 = snprintf(&s[0], s.size()+1, "%lu", val);
398         if (n2 <= s.size())
399         {
400             s.resize(n2);
401             break;
402         }
403         s.resize(n2);
404     }
405     return s;
406 }
407 
408 string to_string(long long val)
409 {
410     string s;
411     s.resize(s.capacity());
412     while (true)
413     {
414         int n2 = snprintf(&s[0], s.size()+1, "%lld", val);
415         if (n2 <= s.size())
416         {
417             s.resize(n2);
418             break;
419         }
420         s.resize(n2);
421     }
422     return s;
423 }
424 
425 string to_string(unsigned long long val)
426 {
427     string s;
428     s.resize(s.capacity());
429     while (true)
430     {
431         int n2 = snprintf(&s[0], s.size()+1, "%llu", val);
432         if (n2 <= s.size())
433         {
434             s.resize(n2);
435             break;
436         }
437         s.resize(n2);
438     }
439     return s;
440 }
441 
442 string to_string(float val)
443 {
444     string s;
445     s.resize(s.capacity());
446     while (true)
447     {
448         int n2 = snprintf(&s[0], s.size()+1, "%f", val);
449         if (n2 <= s.size())
450         {
451             s.resize(n2);
452             break;
453         }
454         s.resize(n2);
455     }
456     return s;
457 }
458 
459 string to_string(double val)
460 {
461     string s;
462     s.resize(s.capacity());
463     while (true)
464     {
465         int n2 = snprintf(&s[0], s.size()+1, "%f", val);
466         if (n2 <= s.size())
467         {
468             s.resize(n2);
469             break;
470         }
471         s.resize(n2);
472     }
473     return s;
474 }
475 
476 string to_string(long double val)
477 {
478     string s;
479     s.resize(s.capacity());
480     while (true)
481     {
482         int n2 = snprintf(&s[0], s.size()+1, "%Lf", val);
483         if (n2 <= s.size())
484         {
485             s.resize(n2);
486             break;
487         }
488         s.resize(n2);
489     }
490     return s;
491 }
492 
493 wstring to_wstring(int val)
494 {
495     const size_t n = (numeric_limits<int>::digits / 3)
496           + ((numeric_limits<int>::digits % 3) != 0)
497           + 1;
498     wstring s(n, wchar_t());
499     s.resize(s.capacity());
500     while (true)
501     {
502         int n2 = swprintf(&s[0], s.size()+1, L"%d", val);
503         if (n2 > 0)
504         {
505             s.resize(n2);
506             break;
507         }
508         s.resize(2*s.size());
509         s.resize(s.capacity());
510     }
511     return s;
512 }
513 
514 wstring to_wstring(unsigned val)
515 {
516     const size_t n = (numeric_limits<unsigned>::digits / 3)
517           + ((numeric_limits<unsigned>::digits % 3) != 0)
518           + 1;
519     wstring s(n, wchar_t());
520     s.resize(s.capacity());
521     while (true)
522     {
523         int n2 = swprintf(&s[0], s.size()+1, L"%u", val);
524         if (n2 > 0)
525         {
526             s.resize(n2);
527             break;
528         }
529         s.resize(2*s.size());
530         s.resize(s.capacity());
531     }
532     return s;
533 }
534 
535 wstring to_wstring(long val)
536 {
537     const size_t n = (numeric_limits<long>::digits / 3)
538           + ((numeric_limits<long>::digits % 3) != 0)
539           + 1;
540     wstring s(n, wchar_t());
541     s.resize(s.capacity());
542     while (true)
543     {
544         int n2 = swprintf(&s[0], s.size()+1, L"%ld", val);
545         if (n2 > 0)
546         {
547             s.resize(n2);
548             break;
549         }
550         s.resize(2*s.size());
551         s.resize(s.capacity());
552     }
553     return s;
554 }
555 
556 wstring to_wstring(unsigned long val)
557 {
558     const size_t n = (numeric_limits<unsigned long>::digits / 3)
559           + ((numeric_limits<unsigned long>::digits % 3) != 0)
560           + 1;
561     wstring s(n, wchar_t());
562     s.resize(s.capacity());
563     while (true)
564     {
565         int n2 = swprintf(&s[0], s.size()+1, L"%lu", val);
566         if (n2 > 0)
567         {
568             s.resize(n2);
569             break;
570         }
571         s.resize(2*s.size());
572         s.resize(s.capacity());
573     }
574     return s;
575 }
576 
577 wstring to_wstring(long long val)
578 {
579     const size_t n = (numeric_limits<long long>::digits / 3)
580           + ((numeric_limits<long long>::digits % 3) != 0)
581           + 1;
582     wstring s(n, wchar_t());
583     s.resize(s.capacity());
584     while (true)
585     {
586         int n2 = swprintf(&s[0], s.size()+1, L"%lld", val);
587         if (n2 > 0)
588         {
589             s.resize(n2);
590             break;
591         }
592         s.resize(2*s.size());
593         s.resize(s.capacity());
594     }
595     return s;
596 }
597 
598 wstring to_wstring(unsigned long long val)
599 {
600     const size_t n = (numeric_limits<unsigned long long>::digits / 3)
601           + ((numeric_limits<unsigned long long>::digits % 3) != 0)
602           + 1;
603     wstring s(n, wchar_t());
604     s.resize(s.capacity());
605     while (true)
606     {
607         int n2 = swprintf(&s[0], s.size()+1, L"%llu", val);
608         if (n2 > 0)
609         {
610             s.resize(n2);
611             break;
612         }
613         s.resize(2*s.size());
614         s.resize(s.capacity());
615     }
616     return s;
617 }
618 
619 wstring to_wstring(float val)
620 {
621     const size_t n = 20;
622     wstring s(n, wchar_t());
623     s.resize(s.capacity());
624     while (true)
625     {
626         int n2 = swprintf(&s[0], s.size()+1, L"%f", val);
627         if (n2 > 0)
628         {
629             s.resize(n2);
630             break;
631         }
632         s.resize(2*s.size());
633         s.resize(s.capacity());
634     }
635     return s;
636 }
637 
638 wstring to_wstring(double val)
639 {
640     const size_t n = 20;
641     wstring s(n, wchar_t());
642     s.resize(s.capacity());
643     while (true)
644     {
645         int n2 = swprintf(&s[0], s.size()+1, L"%f", val);
646         if (n2 > 0)
647         {
648             s.resize(n2);
649             break;
650         }
651         s.resize(2*s.size());
652         s.resize(s.capacity());
653     }
654     return s;
655 }
656 
657 wstring to_wstring(long double val)
658 {
659     const size_t n = 20;
660     wstring s(n, wchar_t());
661     s.resize(s.capacity());
662     while (true)
663     {
664         int n2 = swprintf(&s[0], s.size()+1, L"%Lf", val);
665         if (n2 > 0)
666         {
667             s.resize(n2);
668             break;
669         }
670         s.resize(2*s.size());
671         s.resize(s.capacity());
672     }
673     return s;
674 }
675 
676 _LIBCPP_END_NAMESPACE_STD
677