]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/include/std/charconv
Add new helper traits for signed/unsigned integer types
[thirdparty/gcc.git] / libstdc++-v3 / include / std / charconv
CommitLineData
6b513475 1// Primitive numeric conversions (to_chars and from_chars) -*- C++ -*-
2
fbd26352 3// Copyright (C) 2017-2019 Free Software Foundation, Inc.
6b513475 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#if __cplusplus >= 201402L
35
36#include <type_traits>
37#include <limits>
38#include <cctype>
00f08bc3 39#include <bits/charconv.h> // for __to_chars_len, __to_chars_10_impl
6b513475 40#include <bits/error_constants.h> // for std::errc
41
00f08bc3 42// Define when floating point is supported: #define __cpp_lib_to_chars 201611L
43
6b513475 44namespace std _GLIBCXX_VISIBILITY(default)
45{
46_GLIBCXX_BEGIN_NAMESPACE_VERSION
47
48 /// Result type of std::to_chars
49 struct to_chars_result
50 {
51 char* ptr;
52 errc ec;
53 };
54
55 /// Result type of std::from_chars
56 struct from_chars_result
57 {
58 const char* ptr;
59 errc ec;
60 };
61
62namespace __detail
63{
6b513475 64 template<typename _Tp>
65 using __integer_to_chars_result_type
95d16249 66 = enable_if_t<__or_v<__is_signed_integer<_Tp>,
67 __is_unsigned_integer<_Tp>,
68 is_same<char, remove_cv_t<_Tp>>>,
69 to_chars_result>;
6b513475 70
00f08bc3 71 // Pick an unsigned type of suitable size. This is used to reduce the
72 // number of specializations of __to_chars_len, __to_chars etc. that
73 // get instantiated. For example, to_chars<char> and to_chars<short>
74 // and to_chars<unsigned> will all use the same code, and so will
75 // to_chars<long> when sizeof(int) == sizeof(long).
6b513475 76 template<typename _Tp>
00f08bc3 77 struct __to_chars_unsigned_type : __make_unsigned_selector_base
78 {
79 using _UInts = _List<unsigned int, unsigned long, unsigned long long
50521ed1 80#if _GLIBCXX_USE_INT128
00f08bc3 81 , unsigned __int128
50521ed1 82#endif
00f08bc3 83 >;
84 using type = typename __select<sizeof(_Tp), _UInts>::__type;
85 };
86
87 template<typename _Tp>
88 using __unsigned_least_t = typename __to_chars_unsigned_type<_Tp>::type;
6b513475 89
90 // Generic implementation for arbitrary bases.
00f08bc3 91 // Defined in <bits/charconv.h>.
6b513475 92 template<typename _Tp>
93 constexpr unsigned
00f08bc3 94 __to_chars_len(_Tp __value, int __base /* = 10 */) noexcept;
6b513475 95
96 template<typename _Tp>
97 constexpr unsigned
98 __to_chars_len_2(_Tp __value) noexcept
99 {
100 static_assert(is_integral<_Tp>::value, "implementation bug");
101 static_assert(is_unsigned<_Tp>::value, "implementation bug");
102
103 constexpr size_t __nbits = __CHAR_BIT__ * sizeof(_Tp);
104
105 // N.B. __builtin_clzll is undefined if __value == 0, but std::to_chars
106 // handles zero values directly.
107
108 // For sizeof(_Tp) > 1 this is an order of magnitude faster than
109 // the generic __to_chars_len.
110 return __nbits
111 - (__builtin_clzll(__value)
112 - ((__CHAR_BIT__ * sizeof(long long)) - __nbits));
113 }
114
115 template<typename _Tp>
116 constexpr unsigned
117 __to_chars_len_8(_Tp __value) noexcept
118 {
119 static_assert(is_integral<_Tp>::value, "implementation bug");
120 static_assert(is_unsigned<_Tp>::value, "implementation bug");
121
122 constexpr size_t __nbits = __CHAR_BIT__ * sizeof(_Tp);
123
124 if _GLIBCXX17_CONSTEXPR (__nbits <= 16)
125 {
126 return __value > 077777u ? 6u
127 : __value > 07777u ? 5u
128 : __value > 0777u ? 4u
129 : __value > 077u ? 3u
130 : __value > 07u ? 2u
131 : 1u;
132 }
133 else
134 return __to_chars_len(__value, 8);
135 }
136
137 // Generic implementation for arbitrary bases.
138 template<typename _Tp>
139 to_chars_result
140 __to_chars(char* __first, char* __last, _Tp __val, int __base) noexcept
141 {
142 static_assert(is_integral<_Tp>::value, "implementation bug");
143 static_assert(is_unsigned<_Tp>::value, "implementation bug");
144
145 to_chars_result __res;
146
147 const unsigned __len = __to_chars_len(__val, __base);
148
149 if (__builtin_expect((__last - __first) < __len, 0))
150 {
151 __res.ptr = __last;
152 __res.ec = errc::value_too_large;
153 return __res;
154 }
155
156 unsigned __pos = __len - 1;
157
158 static constexpr char __digits[]
159 = "0123456789abcdefghijklmnopqrstuvwxyz";
160
161 while (__val >= __base)
162 {
163 auto const __quo = __val / __base;
164 auto const __rem = __val % __base;
165 __first[__pos--] = __digits[__rem];
166 __val = __quo;
167 }
168 *__first = __digits[__val];
169
170 __res.ptr = __first + __len;
171 __res.ec = {};
172 return __res;
173 }
174
175 template<typename _Tp>
176 __integer_to_chars_result_type<_Tp>
177 __to_chars_16(char* __first, char* __last, _Tp __val) noexcept
178 {
179 static_assert(is_integral<_Tp>::value, "implementation bug");
180 static_assert(is_unsigned<_Tp>::value, "implementation bug");
181
182 to_chars_result __res;
183
184 const unsigned __len = __to_chars_len(__val, 0x10);
185
186 if (__builtin_expect((__last - __first) < __len, 0))
187 {
188 __res.ptr = __last;
189 __res.ec = errc::value_too_large;
190 return __res;
191 }
192
193 static constexpr char __digits[513] =
194 "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
195 "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"
196 "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"
197 "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f"
198 "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f"
199 "a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
200 "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
201 "e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
202 unsigned __pos = __len - 1;
203 while (__val >= 0x100)
204 {
205 auto const __num = (__val % 0x100) * 2;
206 __val /= 0x100;
207 __first[__pos] = __digits[__num + 1];
208 __first[__pos - 1] = __digits[__num];
209 __pos -= 2;
210 }
211 if (__val >= 0x10)
212 {
213 auto const __num = __val * 2;
214 __first[__pos] = __digits[__num + 1];
215 __first[__pos - 1] = __digits[__num];
216 }
217 else
218 __first[__pos] = "0123456789abcdef"[__val];
219 __res.ptr = __first + __len;
220 __res.ec = {};
221 return __res;
222 }
223
224 template<typename _Tp>
00f08bc3 225 inline __integer_to_chars_result_type<_Tp>
6b513475 226 __to_chars_10(char* __first, char* __last, _Tp __val) noexcept
227 {
228 static_assert(is_integral<_Tp>::value, "implementation bug");
229 static_assert(is_unsigned<_Tp>::value, "implementation bug");
230
231 to_chars_result __res;
232
233 const unsigned __len = __to_chars_len(__val, 10);
234
235 if (__builtin_expect((__last - __first) < __len, 0))
236 {
237 __res.ptr = __last;
238 __res.ec = errc::value_too_large;
239 return __res;
240 }
241
00f08bc3 242 __detail::__to_chars_10_impl(__first, __len, __val);
6b513475 243 __res.ptr = __first + __len;
244 __res.ec = {};
245 return __res;
246 }
247
248 template<typename _Tp>
249 __integer_to_chars_result_type<_Tp>
250 __to_chars_8(char* __first, char* __last, _Tp __val) noexcept
251 {
252 static_assert(is_integral<_Tp>::value, "implementation bug");
253 static_assert(is_unsigned<_Tp>::value, "implementation bug");
254
255 to_chars_result __res;
256
257 const unsigned __len = __to_chars_len_8(__val);
258
259 if (__builtin_expect((__last - __first) < __len, 0))
260 {
261 __res.ptr = __last;
262 __res.ec = errc::value_too_large;
263 return __res;
264 }
265
266 static constexpr char __digits[129] =
267 "00010203040506071011121314151617"
268 "20212223242526273031323334353637"
269 "40414243444546475051525354555657"
270 "60616263646566677071727374757677";
271 unsigned __pos = __len - 1;
272 while (__val >= 0100)
273 {
274 auto const __num = (__val % 0100) * 2;
275 __val /= 0100;
276 __first[__pos] = __digits[__num + 1];
277 __first[__pos - 1] = __digits[__num];
278 __pos -= 2;
279 }
280 if (__val >= 010)
281 {
282 auto const __num = __val * 2;
283 __first[__pos] = __digits[__num + 1];
284 __first[__pos - 1] = __digits[__num];
285 }
286 else
287 __first[__pos] = '0' + __val;
288 __res.ptr = __first + __len;
289 __res.ec = {};
290 return __res;
291 }
292
293 template<typename _Tp>
294 __integer_to_chars_result_type<_Tp>
295 __to_chars_2(char* __first, char* __last, _Tp __val) noexcept
296 {
297 static_assert(is_integral<_Tp>::value, "implementation bug");
298 static_assert(is_unsigned<_Tp>::value, "implementation bug");
299
300 to_chars_result __res;
301
302 const unsigned __len = __to_chars_len_2(__val);
303
304 if (__builtin_expect((__last - __first) < __len, 0))
305 {
306 __res.ptr = __last;
307 __res.ec = errc::value_too_large;
308 return __res;
309 }
310
311 unsigned __pos = __len - 1;
312
313 while (__pos)
314 {
315 __first[__pos--] = '0' + (__val & 1);
316 __val >>= 1;
317 }
318 *__first = '0' + (__val & 1);
319
320 __res.ptr = __first + __len;
321 __res.ec = {};
322 return __res;
323 }
324
325} // namespace __detail
326
327 template<typename _Tp>
328 __detail::__integer_to_chars_result_type<_Tp>
329 to_chars(char* __first, char* __last, _Tp __value, int __base = 10)
330 {
331 __glibcxx_assert(2 <= __base && __base <= 36);
332
333 using _Up = __detail::__unsigned_least_t<_Tp>;
334 _Up __unsigned_val = __value;
335
336 if (__value == 0 && __first != __last)
337 {
338 *__first = '0';
339 return { __first + 1, errc{} };
340 }
341
342 if _GLIBCXX17_CONSTEXPR (std::is_signed<_Tp>::value)
343 if (__value < 0)
344 {
345 if (__builtin_expect(__first != __last, 1))
346 *__first++ = '-';
347 __unsigned_val = _Up(~__value) + _Up(1);
348 }
349
350 switch (__base)
351 {
352 case 16:
353 return __detail::__to_chars_16(__first, __last, __unsigned_val);
354 case 10:
355 return __detail::__to_chars_10(__first, __last, __unsigned_val);
356 case 8:
357 return __detail::__to_chars_8(__first, __last, __unsigned_val);
358 case 2:
359 return __detail::__to_chars_2(__first, __last, __unsigned_val);
360 default:
361 return __detail::__to_chars(__first, __last, __unsigned_val, __base);
362 }
363 }
364
365namespace __detail
366{
367 template<typename _Tp>
368 bool
369 __raise_and_add(_Tp& __val, int __base, unsigned char __c)
370 {
371 if (__builtin_mul_overflow(__val, __base, &__val)
372 || __builtin_add_overflow(__val, __c, &__val))
373 return false;
374 return true;
375 }
376
377 /// std::from_chars implementation for integers in base 2.
378 template<typename _Tp>
379 bool
380 __from_chars_binary(const char*& __first, const char* __last, _Tp& __val)
381 {
382 static_assert(is_integral<_Tp>::value, "implementation bug");
383 static_assert(is_unsigned<_Tp>::value, "implementation bug");
384
385 const ptrdiff_t __len = __last - __first;
386 int __i = 0;
387 while (__i < __len)
388 {
389 const unsigned char __c = (unsigned)__first[__i] - '0';
390 if (__c < 2)
391 __val = (__val << 1) | __c;
392 else
393 break;
394 __i++;
395 }
396 __first += __i;
397 return __i <= (sizeof(_Tp) * __CHAR_BIT__);
398 }
399
400 /// std::from_chars implementation for integers in bases 3 to 10.
401 template<typename _Tp>
402 bool
403 __from_chars_digit(const char*& __first, const char* __last, _Tp& __val,
404 int __base)
405 {
406 static_assert(is_integral<_Tp>::value, "implementation bug");
407 static_assert(is_unsigned<_Tp>::value, "implementation bug");
408
409 auto __matches = [__base](char __c) {
410 return '0' <= __c && __c <= ('0' + (__base - 1));
411 };
412
413 while (__first != __last)
414 {
415 const char __c = *__first;
416 if (__matches(__c))
417 {
418 if (!__raise_and_add(__val, __base, __c - '0'))
419 {
420 while (++__first != __last && __matches(*__first))
421 ;
422 return false;
423 }
424 __first++;
425 }
426 else
427 return true;
428 }
429 return true;
430 }
431
432 constexpr unsigned char
433 __from_chars_alpha_to_num(char __c)
434 {
435 switch (__c)
436 {
437 case 'a':
438 case 'A':
439 return 10;
440 case 'b':
441 case 'B':
442 return 11;
443 case 'c':
444 case 'C':
445 return 12;
446 case 'd':
447 case 'D':
448 return 13;
449 case 'e':
450 case 'E':
451 return 14;
452 case 'f':
453 case 'F':
454 return 15;
455 case 'g':
456 case 'G':
457 return 16;
458 case 'h':
459 case 'H':
460 return 17;
461 case 'i':
462 case 'I':
463 return 18;
464 case 'j':
465 case 'J':
466 return 19;
467 case 'k':
468 case 'K':
469 return 20;
470 case 'l':
471 case 'L':
472 return 21;
473 case 'm':
474 case 'M':
475 return 22;
476 case 'n':
477 case 'N':
478 return 23;
479 case 'o':
480 case 'O':
481 return 24;
482 case 'p':
483 case 'P':
484 return 25;
485 case 'q':
486 case 'Q':
487 return 26;
488 case 'r':
489 case 'R':
490 return 27;
491 case 's':
492 case 'S':
493 return 28;
494 case 't':
495 case 'T':
496 return 29;
497 case 'u':
498 case 'U':
499 return 30;
500 case 'v':
501 case 'V':
502 return 31;
503 case 'w':
504 case 'W':
505 return 32;
506 case 'x':
507 case 'X':
508 return 33;
509 case 'y':
510 case 'Y':
511 return 34;
512 case 'z':
513 case 'Z':
514 return 35;
515 }
516 return std::numeric_limits<unsigned char>::max();
517 }
518
519 /// std::from_chars implementation for integers in bases 11 to 26.
520 template<typename _Tp>
521 bool
522 __from_chars_alnum(const char*& __first, const char* __last, _Tp& __val,
523 int __base)
524 {
525 bool __valid = true;
526 while (__first != __last)
527 {
528 unsigned char __c = *__first;
529 if (std::isdigit(__c))
530 __c -= '0';
531 else
532 {
533 __c = __from_chars_alpha_to_num(__c);
534 if (__c >= __base)
535 break;
536 }
537
538 if (__builtin_expect(__valid, 1))
539 __valid = __raise_and_add(__val, __base, __c);
540 __first++;
541 }
542 return __valid;
543 }
544
545 template<typename _Tp>
546 using __integer_from_chars_result_type
95d16249 547 = enable_if_t<__or_v<__is_signed_integer<_Tp>,
548 __is_unsigned_integer<_Tp>,
549 is_same<char, remove_cv_t<_Tp>>>,
550 from_chars_result>;
6b513475 551
552} // namespace __detail
553
554 /// std::from_chars for integral types.
555 template<typename _Tp>
556 __detail::__integer_from_chars_result_type<_Tp>
557 from_chars(const char* __first, const char* __last, _Tp& __value,
558 int __base = 10)
559 {
560 __glibcxx_assert(2 <= __base && __base <= 36);
561
562 from_chars_result __res{__first, {}};
563
564 int __sign = 1;
565 if _GLIBCXX17_CONSTEXPR (std::is_signed<_Tp>::value)
566 if (__first != __last && *__first == '-')
567 {
568 __sign = -1;
569 ++__first;
570 }
571
572 using _Up = __detail::__unsigned_least_t<_Tp>;
573 _Up __val = 0;
574
575 const auto __start = __first;
576 bool __valid;
577 if (__base == 2)
578 __valid = __detail::__from_chars_binary(__first, __last, __val);
579 else if (__base <= 10)
580 __valid = __detail::__from_chars_digit(__first, __last, __val, __base);
581 else
582 __valid = __detail::__from_chars_alnum(__first, __last, __val, __base);
583
584 if (__builtin_expect(__first == __start, 0))
585 __res.ec = errc::invalid_argument;
586 else
587 {
588 __res.ptr = __first;
589 if (!__valid)
590 __res.ec = errc::result_out_of_range;
591 else
592 {
593 if _GLIBCXX17_CONSTEXPR (std::is_signed<_Tp>::value)
594 {
595 _Tp __tmp;
596 if (__builtin_mul_overflow(__val, __sign, &__tmp))
597 __res.ec = errc::result_out_of_range;
598 else
599 __value = __tmp;
600 }
601 else
602 {
603 if _GLIBCXX17_CONSTEXPR
604 (numeric_limits<_Up>::max() > numeric_limits<_Tp>::max())
605 {
606 if (__val > numeric_limits<_Tp>::max())
607 __res.ec = errc::result_out_of_range;
608 else
609 __value = __val;
610 }
611 else
612 __value = __val;
613 }
614 }
615 }
616 return __res;
617 }
618
619_GLIBCXX_END_NAMESPACE_VERSION
620} // namespace std
621#endif // C++14
622#endif // _GLIBCXX_CHARCONV