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