libstdc++
charconv
Go to the documentation of this file.
1// Primitive numeric conversions (to_chars and from_chars) -*- C++ -*-
2
3// Copyright (C) 2017-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file include/charconv
26 * This is a Standard C++ Library header.
27 */
28
29#ifndef _GLIBCXX_CHARCONV
30#define _GLIBCXX_CHARCONV 1
31
32#pragma GCC system_header
33
34// As an extension we support <charconv> in C++14, but this header should not
35// be included by any other library headers in C++14 mode. This ensures that
36// the names defined in this header are not added to namespace std unless a
37// user explicitly includes <charconv> in C++14 code.
38#if __cplusplus >= 201402L
39
40#include <type_traits>
41#include <bit> // for __bit_width
42#include <bits/charconv.h> // for __to_chars_len, __to_chars_10_impl
43#include <bits/error_constants.h> // for std::errc
44#include <ext/numeric_traits.h>
45
46// FIXME: Define when floating point is supported:
47// #define __cpp_lib_to_chars 201611L
48
49namespace std _GLIBCXX_VISIBILITY(default)
50{
51_GLIBCXX_BEGIN_NAMESPACE_VERSION
52
53 /// Result type of std::to_chars
54 struct to_chars_result
55 {
56 char* ptr;
57 errc ec;
58
59#if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L
60 friend bool
61 operator==(const to_chars_result&, const to_chars_result&) = default;
62#endif
63 };
64
65 /// Result type of std::from_chars
66 struct from_chars_result
67 {
68 const char* ptr;
69 errc ec;
70
71#if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L
72 friend bool
73 operator==(const from_chars_result&, const from_chars_result&) = default;
74#endif
75 };
76
77namespace __detail
78{
79 template<typename _Tp>
80 using __integer_to_chars_result_type
81 = enable_if_t<__or_<__is_signed_integer<_Tp>,
82 __is_unsigned_integer<_Tp>,
83 is_same<char, remove_cv_t<_Tp>>>::value,
84 to_chars_result>;
85
86 // Pick an unsigned type of suitable size. This is used to reduce the
87 // number of specializations of __to_chars_len, __to_chars etc. that
88 // get instantiated. For example, to_chars<char> and to_chars<short>
89 // and to_chars<unsigned> will all use the same code, and so will
90 // to_chars<long> when sizeof(int) == sizeof(long).
91 template<typename _Tp>
92 struct __to_chars_unsigned_type : __make_unsigned_selector_base
93 {
94 using _UInts = _List<unsigned int, unsigned long, unsigned long long
95#if _GLIBCXX_USE_INT128
96 , unsigned __int128
97#endif
98 >;
99 using type = typename __select<sizeof(_Tp), _UInts>::__type;
100 };
101
102 template<typename _Tp>
103 using __unsigned_least_t = typename __to_chars_unsigned_type<_Tp>::type;
104
105 // Generic implementation for arbitrary bases.
106 // Defined in <bits/charconv.h>.
107 template<typename _Tp>
108 constexpr unsigned
109 __to_chars_len(_Tp __value, int __base /* = 10 */) noexcept;
110
111 template<typename _Tp>
112 constexpr unsigned
113 __to_chars_len_2(_Tp __value) noexcept
114 { return std::__bit_width(__value); }
115
116 // Generic implementation for arbitrary bases.
117 template<typename _Tp>
118 to_chars_result
119 __to_chars(char* __first, char* __last, _Tp __val, int __base) noexcept
120 {
121 static_assert(is_integral<_Tp>::value, "implementation bug");
122 static_assert(is_unsigned<_Tp>::value, "implementation bug");
123
124 to_chars_result __res;
125
126 const unsigned __len = __to_chars_len(__val, __base);
127
128 if (__builtin_expect((__last - __first) < __len, 0))
129 {
130 __res.ptr = __last;
131 __res.ec = errc::value_too_large;
132 return __res;
133 }
134
135 unsigned __pos = __len - 1;
136
137 static constexpr char __digits[] = {
138 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
139 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
140 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
141 'u', 'v', 'w', 'x', 'y', 'z'
142 };
143
144 while (__val >= (unsigned)__base)
145 {
146 auto const __quo = __val / __base;
147 auto const __rem = __val % __base;
148 __first[__pos--] = __digits[__rem];
149 __val = __quo;
150 }
151 *__first = __digits[__val];
152
153 __res.ptr = __first + __len;
154 __res.ec = {};
155 return __res;
156 }
157
158 template<typename _Tp>
159 __integer_to_chars_result_type<_Tp>
160 __to_chars_16(char* __first, char* __last, _Tp __val) noexcept
161 {
162 static_assert(is_integral<_Tp>::value, "implementation bug");
163 static_assert(is_unsigned<_Tp>::value, "implementation bug");
164
165 to_chars_result __res;
166
167 const unsigned __len = (__to_chars_len_2(__val) + 3) / 4;
168
169 if (__builtin_expect((__last - __first) < __len, 0))
170 {
171 __res.ptr = __last;
172 __res.ec = errc::value_too_large;
173 return __res;
174 }
175
176 static constexpr char __digits[] = {
177 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
178 'a', 'b', 'c', 'd', 'e', 'f'
179 };
180 unsigned __pos = __len - 1;
181 while (__val >= 0x100)
182 {
183 auto __num = __val & 0xF;
184 __val >>= 4;
185 __first[__pos] = __digits[__num];
186 __num = __val & 0xF;
187 __val >>= 4;
188 __first[__pos - 1] = __digits[__num];
189 __pos -= 2;
190 }
191 if (__val >= 0x10)
192 {
193 const auto __num = __val & 0xF;
194 __val >>= 4;
195 __first[1] = __digits[__num];
196 __first[0] = __digits[__val];
197 }
198 else
199 __first[0] = __digits[__val];
200 __res.ptr = __first + __len;
201 __res.ec = {};
202 return __res;
203 }
204
205 template<typename _Tp>
206 inline __integer_to_chars_result_type<_Tp>
207 __to_chars_10(char* __first, char* __last, _Tp __val) noexcept
208 {
209 static_assert(is_integral<_Tp>::value, "implementation bug");
210 static_assert(is_unsigned<_Tp>::value, "implementation bug");
211
212 to_chars_result __res;
213
214 const unsigned __len = __to_chars_len(__val, 10);
215
216 if (__builtin_expect((__last - __first) < __len, 0))
217 {
218 __res.ptr = __last;
219 __res.ec = errc::value_too_large;
220 return __res;
221 }
222
223 __detail::__to_chars_10_impl(__first, __len, __val);
224 __res.ptr = __first + __len;
225 __res.ec = {};
226 return __res;
227 }
228
229 template<typename _Tp>
230 __integer_to_chars_result_type<_Tp>
231 __to_chars_8(char* __first, char* __last, _Tp __val) noexcept
232 {
233 static_assert(is_integral<_Tp>::value, "implementation bug");
234 static_assert(is_unsigned<_Tp>::value, "implementation bug");
235
236 to_chars_result __res;
237 unsigned __len;
238
239 if _GLIBCXX17_CONSTEXPR (__gnu_cxx::__int_traits<_Tp>::__digits <= 16)
240 {
241 __len = __val > 077777u ? 6u
242 : __val > 07777u ? 5u
243 : __val > 0777u ? 4u
244 : __val > 077u ? 3u
245 : __val > 07u ? 2u
246 : 1u;
247 }
248 else
249 __len = (__to_chars_len_2(__val) + 2) / 3;
250
251 if (__builtin_expect((__last - __first) < __len, 0))
252 {
253 __res.ptr = __last;
254 __res.ec = errc::value_too_large;
255 return __res;
256 }
257
258 unsigned __pos = __len - 1;
259 while (__val >= 0100)
260 {
261 auto __num = __val & 7;
262 __val >>= 3;
263 __first[__pos] = '0' + __num;
264 __num = __val & 7;
265 __val >>= 3;
266 __first[__pos - 1] = '0' + __num;
267 __pos -= 2;
268 }
269 if (__val >= 010)
270 {
271 auto const __num = __val & 7;
272 __val >>= 3;
273 __first[1] = '0' + __num;
274 __first[0] = '0' + __val;
275 }
276 else
277 __first[0] = '0' + __val;
278 __res.ptr = __first + __len;
279 __res.ec = {};
280 return __res;
281 }
282
283 template<typename _Tp>
284 __integer_to_chars_result_type<_Tp>
285 __to_chars_2(char* __first, char* __last, _Tp __val) noexcept
286 {
287 static_assert(is_integral<_Tp>::value, "implementation bug");
288 static_assert(is_unsigned<_Tp>::value, "implementation bug");
289
290 to_chars_result __res;
291
292 const unsigned __len = __to_chars_len_2(__val);
293
294 if (__builtin_expect((__last - __first) < __len, 0))
295 {
296 __res.ptr = __last;
297 __res.ec = errc::value_too_large;
298 return __res;
299 }
300
301 unsigned __pos = __len - 1;
302
303 while (__pos)
304 {
305 __first[__pos--] = '0' + (__val & 1);
306 __val >>= 1;
307 }
308 // First digit is always '1' because __to_chars_len_2 skips
309 // leading zero bits and std::to_chars handles zero values
310 // directly.
311 __first[0] = '1';
312
313 __res.ptr = __first + __len;
314 __res.ec = {};
315 return __res;
316 }
317
318} // namespace __detail
319
320 template<typename _Tp>
321 __detail::__integer_to_chars_result_type<_Tp>
322 __to_chars_i(char* __first, char* __last, _Tp __value, int __base = 10)
323 {
324 __glibcxx_assert(2 <= __base && __base <= 36);
325
326 using _Up = __detail::__unsigned_least_t<_Tp>;
327 _Up __unsigned_val = __value;
328
329 if (__first == __last) [[__unlikely__]]
330 return { __last, errc::value_too_large };
331
332 if (__value == 0)
333 {
334 *__first = '0';
335 return { __first + 1, errc{} };
336 }
337 else if _GLIBCXX17_CONSTEXPR (std::is_signed<_Tp>::value)
338 if (__value < 0)
339 {
340 *__first++ = '-';
341 __unsigned_val = _Up(~__value) + _Up(1);
342 }
343
344 switch (__base)
345 {
346 case 16:
347 return __detail::__to_chars_16(__first, __last, __unsigned_val);
348 case 10:
349 return __detail::__to_chars_10(__first, __last, __unsigned_val);
350 case 8:
351 return __detail::__to_chars_8(__first, __last, __unsigned_val);
352 case 2:
353 return __detail::__to_chars_2(__first, __last, __unsigned_val);
354 default:
355 return __detail::__to_chars(__first, __last, __unsigned_val, __base);
356 }
357 }
358
359#define _GLIBCXX_TO_CHARS(T) \
360 inline to_chars_result \
361 to_chars(char* __first, char* __last, T __value, int __base = 10) \
362 { return std::__to_chars_i<T>(__first, __last, __value, __base); }
363_GLIBCXX_TO_CHARS(char)
364_GLIBCXX_TO_CHARS(signed char)
365_GLIBCXX_TO_CHARS(unsigned char)
366_GLIBCXX_TO_CHARS(signed short)
367_GLIBCXX_TO_CHARS(unsigned short)
368_GLIBCXX_TO_CHARS(signed int)
369_GLIBCXX_TO_CHARS(unsigned int)
370_GLIBCXX_TO_CHARS(signed long)
371_GLIBCXX_TO_CHARS(unsigned long)
372_GLIBCXX_TO_CHARS(signed long long)
373_GLIBCXX_TO_CHARS(unsigned long long)
374#if defined(__GLIBCXX_TYPE_INT_N_0)
375_GLIBCXX_TO_CHARS(signed __GLIBCXX_TYPE_INT_N_0)
376_GLIBCXX_TO_CHARS(unsigned __GLIBCXX_TYPE_INT_N_0)
377#endif
378#if defined(__GLIBCXX_TYPE_INT_N_1)
379_GLIBCXX_TO_CHARS(signed __GLIBCXX_TYPE_INT_N_1)
380_GLIBCXX_TO_CHARS(unsigned __GLIBCXX_TYPE_INT_N_1)
381#endif
382#if defined(__GLIBCXX_TYPE_INT_N_2)
383_GLIBCXX_TO_CHARS(signed __GLIBCXX_TYPE_INT_N_2)
384_GLIBCXX_TO_CHARS(unsigned __GLIBCXX_TYPE_INT_N_2)
385#endif
386#if defined(__GLIBCXX_TYPE_INT_N_3)
387_GLIBCXX_TO_CHARS(signed __GLIBCXX_TYPE_INT_N_3)
388_GLIBCXX_TO_CHARS(unsigned __GLIBCXX_TYPE_INT_N_3)
389#endif
390#undef _GLIBCXX_TO_CHARS
391
392 // _GLIBCXX_RESOLVE_LIB_DEFECTS
393 // 3266. to_chars(bool) should be deleted
394 to_chars_result to_chars(char*, char*, bool, int = 10) = delete;
395
396namespace __detail
397{
398 template<typename _Tp>
399 bool
400 __raise_and_add(_Tp& __val, int __base, unsigned char __c)
401 {
402 if (__builtin_mul_overflow(__val, __base, &__val)
403 || __builtin_add_overflow(__val, __c, &__val))
404 return false;
405 return true;
406 }
407
408 /// std::from_chars implementation for integers in base 2.
409 template<typename _Tp>
410 bool
411 __from_chars_binary(const char*& __first, const char* __last, _Tp& __val)
412 {
413 static_assert(is_integral<_Tp>::value, "implementation bug");
414 static_assert(is_unsigned<_Tp>::value, "implementation bug");
415
416 const ptrdiff_t __len = __last - __first;
417 ptrdiff_t __i = 0;
418 while (__i < __len && __first[__i] == '0')
419 ++__i;
420 const ptrdiff_t __leading_zeroes = __i;
421
422 while (__i < __len)
423 {
424 const unsigned char __c = (unsigned)__first[__i] - '0';
425 if (__c < 2)
426 __val = (__val << 1) | __c;
427 else
428 break;
429 __i++;
430 }
431 __first += __i;
432 return (__i - __leading_zeroes) <= __gnu_cxx::__int_traits<_Tp>::__digits;
433 }
434
435 /// std::from_chars implementation for integers in bases 3 to 10.
436 template<typename _Tp>
437 bool
438 __from_chars_digit(const char*& __first, const char* __last, _Tp& __val,
439 int __base)
440 {
441 static_assert(is_integral<_Tp>::value, "implementation bug");
442 static_assert(is_unsigned<_Tp>::value, "implementation bug");
443
444 auto __matches = [__base](char __c) {
445 return '0' <= __c && __c <= ('0' + (__base - 1));
446 };
447
448 while (__first != __last)
449 {
450 const char __c = *__first;
451 if (__matches(__c))
452 {
453 if (!__raise_and_add(__val, __base, __c - '0'))
454 {
455 while (++__first != __last && __matches(*__first))
456 ;
457 return false;
458 }
459 __first++;
460 }
461 else
462 return true;
463 }
464 return true;
465 }
466
467 constexpr char
468 __from_chars_alpha_to_num(char __c)
469 {
470 switch (__c)
471 {
472 case 'a':
473 case 'A':
474 return 10;
475 case 'b':
476 case 'B':
477 return 11;
478 case 'c':
479 case 'C':
480 return 12;
481 case 'd':
482 case 'D':
483 return 13;
484 case 'e':
485 case 'E':
486 return 14;
487 case 'f':
488 case 'F':
489 return 15;
490 case 'g':
491 case 'G':
492 return 16;
493 case 'h':
494 case 'H':
495 return 17;
496 case 'i':
497 case 'I':
498 return 18;
499 case 'j':
500 case 'J':
501 return 19;
502 case 'k':
503 case 'K':
504 return 20;
505 case 'l':
506 case 'L':
507 return 21;
508 case 'm':
509 case 'M':
510 return 22;
511 case 'n':
512 case 'N':
513 return 23;
514 case 'o':
515 case 'O':
516 return 24;
517 case 'p':
518 case 'P':
519 return 25;
520 case 'q':
521 case 'Q':
522 return 26;
523 case 'r':
524 case 'R':
525 return 27;
526 case 's':
527 case 'S':
528 return 28;
529 case 't':
530 case 'T':
531 return 29;
532 case 'u':
533 case 'U':
534 return 30;
535 case 'v':
536 case 'V':
537 return 31;
538 case 'w':
539 case 'W':
540 return 32;
541 case 'x':
542 case 'X':
543 return 33;
544 case 'y':
545 case 'Y':
546 return 34;
547 case 'z':
548 case 'Z':
549 return 35;
550 }
551 return 127;
552 }
553
554 /// std::from_chars implementation for integers in bases 11 to 36.
555 template<typename _Tp>
556 bool
557 __from_chars_alnum(const char*& __first, const char* __last, _Tp& __val,
558 int __base)
559 {
560 bool __valid = true;
561 while (__first != __last)
562 {
563 char __c = *__first;
564 if ('0' <= __c && __c <= '9') // isdigit
565 __c -= '0';
566 else
567 {
568 __c = __from_chars_alpha_to_num(__c);
569 if (__c >= __base)
570 break;
571 }
572
573 if (__builtin_expect(__valid, 1))
574 __valid = __raise_and_add(__val, __base, __c);
575 __first++;
576 }
577 return __valid;
578 }
579
580 template<typename _Tp>
581 using __integer_from_chars_result_type
582 = enable_if_t<__or_<__is_signed_integer<_Tp>,
583 __is_unsigned_integer<_Tp>,
584 is_same<char, remove_cv_t<_Tp>>>::value,
585 from_chars_result>;
586
587} // namespace __detail
588
589 /// std::from_chars for integral types.
590 template<typename _Tp>
591 __detail::__integer_from_chars_result_type<_Tp>
592 from_chars(const char* __first, const char* __last, _Tp& __value,
593 int __base = 10)
594 {
595 __glibcxx_assert(2 <= __base && __base <= 36);
596
597 from_chars_result __res{__first, {}};
598
599 int __sign = 1;
600 if _GLIBCXX17_CONSTEXPR (std::is_signed<_Tp>::value)
601 if (__first != __last && *__first == '-')
602 {
603 __sign = -1;
604 ++__first;
605 }
606
607 using _Up = __detail::__unsigned_least_t<_Tp>;
608 _Up __val = 0;
609
610 const auto __start = __first;
611 bool __valid;
612 if (__base == 2)
613 __valid = __detail::__from_chars_binary(__first, __last, __val);
614 else if (__base <= 10)
615 __valid = __detail::__from_chars_digit(__first, __last, __val, __base);
616 else
617 __valid = __detail::__from_chars_alnum(__first, __last, __val, __base);
618
619 if (__builtin_expect(__first == __start, 0))
620 __res.ec = errc::invalid_argument;
621 else
622 {
623 __res.ptr = __first;
624 if (!__valid)
625 __res.ec = errc::result_out_of_range;
626 else
627 {
628 if _GLIBCXX17_CONSTEXPR (std::is_signed<_Tp>::value)
629 {
630 _Tp __tmp;
631 if (__builtin_mul_overflow(__val, __sign, &__tmp))
632 __res.ec = errc::result_out_of_range;
633 else
634 __value = __tmp;
635 }
636 else
637 {
638 if _GLIBCXX17_CONSTEXPR (__gnu_cxx::__int_traits<_Up>::__max
639 > __gnu_cxx::__int_traits<_Tp>::__max)
640 {
641 if (__val > __gnu_cxx::__int_traits<_Tp>::__max)
642 __res.ec = errc::result_out_of_range;
643 else
644 __value = __val;
645 }
646 else
647 __value = __val;
648 }
649 }
650 }
651 return __res;
652 }
653
654 /// floating-point format for primitive numerical conversion
655 enum class chars_format
656 {
657 scientific = 1, fixed = 2, hex = 4, general = fixed | scientific
658 };
659
660 constexpr chars_format
661 operator|(chars_format __lhs, chars_format __rhs) noexcept
662 { return (chars_format)((unsigned)__lhs | (unsigned)__rhs); }
663
664 constexpr chars_format
665 operator&(chars_format __lhs, chars_format __rhs) noexcept
666 { return (chars_format)((unsigned)__lhs & (unsigned)__rhs); }
667
668 constexpr chars_format
669 operator^(chars_format __lhs, chars_format __rhs) noexcept
670 { return (chars_format)((unsigned)__lhs ^ (unsigned)__rhs); }
671
672 constexpr chars_format
673 operator~(chars_format __fmt) noexcept
674 { return (chars_format)~(unsigned)__fmt; }
675
676 constexpr chars_format&
677 operator|=(chars_format& __lhs, chars_format __rhs) noexcept
678 { return __lhs = __lhs | __rhs; }
679
680 constexpr chars_format&
681 operator&=(chars_format& __lhs, chars_format __rhs) noexcept
682 { return __lhs = __lhs & __rhs; }
683
684 constexpr chars_format&
685 operator^=(chars_format& __lhs, chars_format __rhs) noexcept
686 { return __lhs = __lhs ^ __rhs; }
687
688_GLIBCXX_END_NAMESPACE_VERSION
689} // namespace std
690#endif // C++14
691#endif // _GLIBCXX_CHARCONV