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