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