1 | // Primitive numeric conversions (to_chars and from_chars) -*- C++ -*- |
2 | |
3 | // Copyright (C) 2017-2024 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 | #include <bits/requires_hosted.h> // for error codes |
35 | |
36 | // As an extension we support <charconv> in C++14, but this header should not |
37 | // be included by any other library headers in C++14 mode. This ensures that |
38 | // the names defined in this header are not added to namespace std unless a |
39 | // user explicitly includes <charconv> in C++14 code. |
40 | #if __cplusplus >= 201402L |
41 | |
42 | #include <type_traits> |
43 | #include <bit> // for __bit_width |
44 | #include <bits/charconv.h> // for __to_chars_len, __to_chars_10_impl |
45 | #include <bits/error_constants.h> // for std::errc |
46 | #include <ext/numeric_traits.h> |
47 | |
48 | #define __glibcxx_want_to_chars |
49 | #define __glibcxx_want_constexpr_charconv |
50 | #include <bits/version.h> |
51 | |
52 | namespace std _GLIBCXX_VISIBILITY(default) |
53 | { |
54 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
55 | |
56 | /// Result type of std::to_chars |
57 | struct to_chars_result |
58 | { |
59 | char* ptr; |
60 | errc ec; |
61 | |
62 | #if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L |
63 | friend bool |
64 | operator==(const to_chars_result&, const to_chars_result&) = default; |
65 | #endif |
66 | #if __cplusplus > 202302L |
67 | constexpr explicit operator bool() const noexcept { return ec == errc{}; } |
68 | #endif |
69 | }; |
70 | |
71 | /// Result type of std::from_chars |
72 | struct from_chars_result |
73 | { |
74 | const char* ptr; |
75 | errc ec; |
76 | |
77 | #if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L |
78 | friend bool |
79 | operator==(const from_chars_result&, const from_chars_result&) = default; |
80 | #endif |
81 | #if __cplusplus > 202302L |
82 | constexpr explicit operator bool() const noexcept { return ec == errc{}; } |
83 | #endif |
84 | }; |
85 | |
86 | namespace __detail |
87 | { |
88 | // Pick an unsigned type of suitable size. This is used to reduce the |
89 | // number of specializations of __to_chars_len, __to_chars etc. that |
90 | // get instantiated. For example, to_chars<char> and to_chars<short> |
91 | // and to_chars<unsigned> will all use the same code, and so will |
92 | // to_chars<long> when sizeof(int) == sizeof(long). |
93 | template<typename _Tp> |
94 | struct __to_chars_unsigned_type : __make_unsigned_selector_base |
95 | { |
96 | using _UInts = _List<unsigned int, unsigned long, unsigned long long |
97 | #if __SIZEOF_INT128__ > __SIZEOF_LONG_LONG__ |
98 | , unsigned __int128 |
99 | #endif |
100 | >; |
101 | using type = typename __select<sizeof(_Tp), _UInts>::__type; |
102 | }; |
103 | |
104 | template<typename _Tp> |
105 | using __unsigned_least_t = typename __to_chars_unsigned_type<_Tp>::type; |
106 | |
107 | // Generic implementation for arbitrary bases. |
108 | // Defined in <bits/charconv.h>. |
109 | template<typename _Tp> |
110 | constexpr unsigned |
111 | __to_chars_len(_Tp __value, int __base /* = 10 */) noexcept; |
112 | |
113 | template<typename _Tp> |
114 | constexpr unsigned |
115 | __to_chars_len_2(_Tp __value) noexcept |
116 | { return std::__bit_width(__value); } |
117 | |
118 | // Generic implementation for arbitrary bases. |
119 | template<typename _Tp> |
120 | constexpr to_chars_result |
121 | __to_chars(char* __first, char* __last, _Tp __val, int __base) noexcept |
122 | { |
123 | static_assert(__integer_to_chars_is_unsigned<_Tp>, "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 | |
138 | 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 | }; |
144 | |
145 | while (__val >= (unsigned)__base) |
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 | constexpr to_chars_result |
161 | __to_chars_16(char* __first, char* __last, _Tp __val) noexcept |
162 | { |
163 | static_assert(__integer_to_chars_is_unsigned<_Tp>, "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 | 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 | constexpr to_chars_result |
207 | __to_chars_10(char* __first, char* __last, _Tp __val) noexcept |
208 | { |
209 | static_assert(__integer_to_chars_is_unsigned<_Tp>, "implementation bug" ); |
210 | |
211 | to_chars_result __res; |
212 | |
213 | const unsigned __len = __to_chars_len(__val, 10); |
214 | |
215 | if (__builtin_expect((__last - __first) < __len, 0)) |
216 | { |
217 | __res.ptr = __last; |
218 | __res.ec = errc::value_too_large; |
219 | return __res; |
220 | } |
221 | |
222 | __detail::__to_chars_10_impl(__first, __len, __val); |
223 | __res.ptr = __first + __len; |
224 | __res.ec = {}; |
225 | return __res; |
226 | } |
227 | |
228 | template<typename _Tp> |
229 | constexpr to_chars_result |
230 | __to_chars_8(char* __first, char* __last, _Tp __val) noexcept |
231 | { |
232 | static_assert(__integer_to_chars_is_unsigned<_Tp>, "implementation bug" ); |
233 | |
234 | to_chars_result __res; |
235 | unsigned __len = 0; |
236 | |
237 | if _GLIBCXX17_CONSTEXPR (__gnu_cxx::__int_traits<_Tp>::__digits <= 16) |
238 | { |
239 | __len = __val > 077777u ? 6u |
240 | : __val > 07777u ? 5u |
241 | : __val > 0777u ? 4u |
242 | : __val > 077u ? 3u |
243 | : __val > 07u ? 2u |
244 | : 1u; |
245 | } |
246 | else |
247 | __len = (__to_chars_len_2(__val) + 2) / 3; |
248 | |
249 | if (__builtin_expect((__last - __first) < __len, 0)) |
250 | { |
251 | __res.ptr = __last; |
252 | __res.ec = errc::value_too_large; |
253 | return __res; |
254 | } |
255 | |
256 | unsigned __pos = __len - 1; |
257 | while (__val >= 0100) |
258 | { |
259 | auto __num = __val & 7; |
260 | __val >>= 3; |
261 | __first[__pos] = '0' + __num; |
262 | __num = __val & 7; |
263 | __val >>= 3; |
264 | __first[__pos - 1] = '0' + __num; |
265 | __pos -= 2; |
266 | } |
267 | if (__val >= 010) |
268 | { |
269 | auto const __num = __val & 7; |
270 | __val >>= 3; |
271 | __first[1] = '0' + __num; |
272 | __first[0] = '0' + __val; |
273 | } |
274 | else |
275 | __first[0] = '0' + __val; |
276 | __res.ptr = __first + __len; |
277 | __res.ec = {}; |
278 | return __res; |
279 | } |
280 | |
281 | template<typename _Tp> |
282 | constexpr to_chars_result |
283 | __to_chars_2(char* __first, char* __last, _Tp __val) noexcept |
284 | { |
285 | static_assert(__integer_to_chars_is_unsigned<_Tp>, "implementation bug" ); |
286 | |
287 | to_chars_result __res; |
288 | |
289 | const unsigned __len = __to_chars_len_2(__val); |
290 | |
291 | if (__builtin_expect((__last - __first) < __len, 0)) |
292 | { |
293 | __res.ptr = __last; |
294 | __res.ec = errc::value_too_large; |
295 | return __res; |
296 | } |
297 | |
298 | unsigned __pos = __len - 1; |
299 | |
300 | while (__pos) |
301 | { |
302 | __first[__pos--] = '0' + (__val & 1); |
303 | __val >>= 1; |
304 | } |
305 | // First digit is always '1' because __to_chars_len_2 skips |
306 | // leading zero bits and std::to_chars handles zero values |
307 | // directly. |
308 | __first[0] = '1'; |
309 | |
310 | __res.ptr = __first + __len; |
311 | __res.ec = {}; |
312 | return __res; |
313 | } |
314 | |
315 | } // namespace __detail |
316 | |
317 | template<typename _Tp> |
318 | constexpr to_chars_result |
319 | __to_chars_i(char* __first, char* __last, _Tp __value, int __base = 10) |
320 | { |
321 | __glibcxx_assert(2 <= __base && __base <= 36); |
322 | |
323 | using _Up = __detail::__unsigned_least_t<_Tp>; |
324 | _Up __unsigned_val = __value; |
325 | |
326 | if (__first == __last) [[__unlikely__]] |
327 | return { .ptr: __last, .ec: errc::value_too_large }; |
328 | |
329 | if (__value == 0) |
330 | { |
331 | *__first = '0'; |
332 | return { .ptr: __first + 1, .ec: errc{} }; |
333 | } |
334 | else if _GLIBCXX17_CONSTEXPR (std::is_signed<_Tp>::value) |
335 | if (__value < 0) |
336 | { |
337 | *__first++ = '-'; |
338 | __unsigned_val = _Up(~__value) + _Up(1); |
339 | } |
340 | |
341 | switch (__base) |
342 | { |
343 | case 16: |
344 | return __detail::__to_chars_16(__first, __last, __unsigned_val); |
345 | case 10: |
346 | return __detail::__to_chars_10(__first, __last, __unsigned_val); |
347 | case 8: |
348 | return __detail::__to_chars_8(__first, __last, __unsigned_val); |
349 | case 2: |
350 | return __detail::__to_chars_2(__first, __last, __unsigned_val); |
351 | default: |
352 | return __detail::__to_chars(__first, __last, __unsigned_val, __base); |
353 | } |
354 | } |
355 | |
356 | #define _GLIBCXX_TO_CHARS(T) \ |
357 | _GLIBCXX23_CONSTEXPR inline to_chars_result \ |
358 | to_chars(char* __first, char* __last, T __value, int __base = 10) \ |
359 | { return std::__to_chars_i<T>(__first, __last, __value, __base); } |
360 | _GLIBCXX_TO_CHARS(char) |
361 | _GLIBCXX_TO_CHARS(signed char) |
362 | _GLIBCXX_TO_CHARS(unsigned char) |
363 | _GLIBCXX_TO_CHARS(signed short) |
364 | _GLIBCXX_TO_CHARS(unsigned short) |
365 | _GLIBCXX_TO_CHARS(signed int) |
366 | _GLIBCXX_TO_CHARS(unsigned int) |
367 | _GLIBCXX_TO_CHARS(signed long) |
368 | _GLIBCXX_TO_CHARS(unsigned long) |
369 | _GLIBCXX_TO_CHARS(signed long long) |
370 | _GLIBCXX_TO_CHARS(unsigned long long) |
371 | #if defined(__GLIBCXX_TYPE_INT_N_0) |
372 | _GLIBCXX_TO_CHARS(signed __GLIBCXX_TYPE_INT_N_0) |
373 | _GLIBCXX_TO_CHARS(unsigned __GLIBCXX_TYPE_INT_N_0) |
374 | #endif |
375 | #if defined(__GLIBCXX_TYPE_INT_N_1) |
376 | _GLIBCXX_TO_CHARS(signed __GLIBCXX_TYPE_INT_N_1) |
377 | _GLIBCXX_TO_CHARS(unsigned __GLIBCXX_TYPE_INT_N_1) |
378 | #endif |
379 | #if defined(__GLIBCXX_TYPE_INT_N_2) |
380 | _GLIBCXX_TO_CHARS(signed __GLIBCXX_TYPE_INT_N_2) |
381 | _GLIBCXX_TO_CHARS(unsigned __GLIBCXX_TYPE_INT_N_2) |
382 | #endif |
383 | #if defined(__GLIBCXX_TYPE_INT_N_3) |
384 | _GLIBCXX_TO_CHARS(signed __GLIBCXX_TYPE_INT_N_3) |
385 | _GLIBCXX_TO_CHARS(unsigned __GLIBCXX_TYPE_INT_N_3) |
386 | #endif |
387 | #undef _GLIBCXX_TO_CHARS |
388 | |
389 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
390 | // 3266. to_chars(bool) should be deleted |
391 | to_chars_result to_chars(char*, char*, bool, int = 10) = delete; |
392 | |
393 | namespace __detail |
394 | { |
395 | template<typename _Tp> |
396 | constexpr bool |
397 | __raise_and_add(_Tp& __val, int __base, unsigned char __c) |
398 | { |
399 | if (__builtin_mul_overflow(__val, __base, &__val) |
400 | || __builtin_add_overflow(__val, __c, &__val)) |
401 | return false; |
402 | return true; |
403 | } |
404 | |
405 | template<bool _DecOnly> |
406 | struct __from_chars_alnum_to_val_table |
407 | { |
408 | struct type { unsigned char __data[1u << __CHAR_BIT__] = {}; }; |
409 | |
410 | // Construct and return a lookup table that maps 0-9, A-Z and a-z to their |
411 | // corresponding base-36 value and maps all other characters to 127. |
412 | static constexpr type |
413 | _S_make_table() |
414 | { |
415 | constexpr unsigned char __lower_letters[27] = "abcdefghijklmnopqrstuvwxyz" ; |
416 | constexpr unsigned char __upper_letters[27] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ; |
417 | type __table; |
418 | for (auto& __entry : __table.__data) |
419 | __entry = 127; |
420 | for (int __i = 0; __i < 10; ++__i) |
421 | __table.__data['0' + __i] = __i; |
422 | for (int __i = 0; __i < 26; ++__i) |
423 | { |
424 | __table.__data[__lower_letters[__i]] = 10 + __i; |
425 | __table.__data[__upper_letters[__i]] = 10 + __i; |
426 | } |
427 | return __table; |
428 | } |
429 | |
430 | // This initializer is made superficially dependent in order |
431 | // to prevent the compiler from wastefully constructing the |
432 | // table ahead of time when it's not needed. |
433 | static constexpr type value = (_DecOnly, _S_make_table()); |
434 | }; |
435 | |
436 | #if ! __cpp_inline_variables |
437 | template<bool _DecOnly> |
438 | const typename __from_chars_alnum_to_val_table<_DecOnly>::type |
439 | __from_chars_alnum_to_val_table<_DecOnly>::value; |
440 | #endif |
441 | |
442 | // If _DecOnly is true: if the character is a decimal digit, then |
443 | // return its corresponding base-10 value, otherwise return a value >= 127. |
444 | // If _DecOnly is false: if the character is an alphanumeric digit, then |
445 | // return its corresponding base-36 value, otherwise return a value >= 127. |
446 | template<bool _DecOnly = false> |
447 | _GLIBCXX20_CONSTEXPR unsigned char |
448 | __from_chars_alnum_to_val(unsigned char __c) |
449 | { |
450 | if _GLIBCXX17_CONSTEXPR (_DecOnly) |
451 | return static_cast<unsigned char>(__c - '0'); |
452 | else |
453 | return __from_chars_alnum_to_val_table<_DecOnly>::value.__data[__c]; |
454 | } |
455 | |
456 | /// std::from_chars implementation for integers in a power-of-two base. |
457 | /// If _DecOnly is true, then we may assume __base is at most 8. |
458 | template<bool _DecOnly, typename _Tp> |
459 | _GLIBCXX23_CONSTEXPR bool |
460 | __from_chars_pow2_base(const char*& __first, const char* __last, _Tp& __val, |
461 | int __base) |
462 | { |
463 | static_assert(is_integral<_Tp>::value, "implementation bug" ); |
464 | static_assert(is_unsigned<_Tp>::value, "implementation bug" ); |
465 | |
466 | // __glibcxx_assert((__base & (__base - 1)) == 0); |
467 | // __glibcxx_assert(_DecOnly ? __base <= 8 : __base <= 32); |
468 | const int __log2_base = __countr_zero(x: unsigned(__base & 0x3f)); |
469 | |
470 | const ptrdiff_t __len = __last - __first; |
471 | ptrdiff_t __i = 0; |
472 | while (__i < __len && __first[__i] == '0') |
473 | ++__i; |
474 | const ptrdiff_t __leading_zeroes = __i; |
475 | if (__i >= __len) [[__unlikely__]] |
476 | { |
477 | __first += __i; |
478 | return true; |
479 | } |
480 | |
481 | // Remember the leading significant digit value if necessary. |
482 | unsigned char __leading_c = 0; |
483 | if (__base != 2) |
484 | { |
485 | __leading_c = __from_chars_alnum_to_val<_DecOnly>(__first[__i]); |
486 | // __glibcxx_assert(__leading_c != 0); |
487 | if (__leading_c >= __base) [[__unlikely__]] |
488 | { |
489 | __first += __i; |
490 | return true; |
491 | } |
492 | __val = __leading_c; |
493 | ++__i; |
494 | } |
495 | |
496 | for (; __i < __len; ++__i) |
497 | { |
498 | const unsigned char __c = __from_chars_alnum_to_val<_DecOnly>(__first[__i]); |
499 | if (__c >= __base) |
500 | break; |
501 | __val = (__val << __log2_base) | __c; |
502 | } |
503 | __first += __i; |
504 | auto __significant_bits = (__i - __leading_zeroes) * __log2_base; |
505 | if (__base != 2) |
506 | // Compensate for a leading significant digit that didn't use all |
507 | // of its available bits. |
508 | __significant_bits -= __log2_base - __bit_width(x: __leading_c); |
509 | // __glibcxx_assert(__significant_bits >= 0); |
510 | return __significant_bits <= __gnu_cxx::__int_traits<_Tp>::__digits; |
511 | } |
512 | |
513 | /// std::from_chars implementation for integers in any base. |
514 | /// If _DecOnly is true, then we may assume __base is at most 10. |
515 | template<bool _DecOnly, typename _Tp> |
516 | constexpr bool |
517 | __from_chars_alnum(const char*& __first, const char* __last, _Tp& __val, |
518 | int __base) |
519 | { |
520 | // __glibcxx_assert(_DecOnly ? __base <= 10 : __base <= 36); |
521 | |
522 | const int __bits_per_digit = __bit_width(x: unsigned(__base & 0x3f)); |
523 | int __unused_bits_lower_bound = __gnu_cxx::__int_traits<_Tp>::__digits; |
524 | for (; __first != __last; ++__first) |
525 | { |
526 | const unsigned char __c = __from_chars_alnum_to_val<_DecOnly>(*__first); |
527 | if (__c >= __base) |
528 | return true; |
529 | |
530 | __unused_bits_lower_bound -= __bits_per_digit; |
531 | if (__unused_bits_lower_bound >= 0) [[__likely__]] |
532 | // We're definitely not going to overflow. |
533 | __val = __val * __base + __c; |
534 | else if (!__raise_and_add(__val, __base, __c)) [[__unlikely__]] |
535 | { |
536 | while (++__first != __last |
537 | && __from_chars_alnum_to_val<_DecOnly>(*__first) < __base) |
538 | ; |
539 | return false; |
540 | } |
541 | } |
542 | return true; |
543 | } |
544 | |
545 | } // namespace __detail |
546 | |
547 | /// std::from_chars for integral types. |
548 | template<typename _Tp, |
549 | enable_if_t<__or_<__is_standard_integer<_Tp>, |
550 | is_same<char, remove_cv_t<_Tp>>>::value, int> = 0> |
551 | _GLIBCXX23_CONSTEXPR from_chars_result |
552 | from_chars(const char* __first, const char* __last, _Tp& __value, |
553 | int __base = 10) |
554 | { |
555 | __glibcxx_assert(2 <= __base && __base <= 36); |
556 | |
557 | from_chars_result __res{.ptr: __first, .ec: {}}; |
558 | |
559 | int __sign = 1; |
560 | if _GLIBCXX17_CONSTEXPR (std::is_signed<_Tp>::value) |
561 | if (__first != __last && *__first == '-') |
562 | { |
563 | __sign = -1; |
564 | ++__first; |
565 | } |
566 | |
567 | using _Up = __detail::__unsigned_least_t<_Tp>; |
568 | _Up __val = 0; |
569 | |
570 | const auto __start = __first; |
571 | bool __valid; |
572 | if ((__base & (__base - 1)) == 0) |
573 | { |
574 | if (__base <= 8) |
575 | __valid = __detail::__from_chars_pow2_base<true>(__first, __last, __val, __base); |
576 | else |
577 | __valid = __detail::__from_chars_pow2_base<false>(__first, __last, __val, __base); |
578 | } |
579 | else if (__base <= 10) |
580 | __valid = __detail::__from_chars_alnum<true>(__first, __last, __val, __base); |
581 | else |
582 | __valid = __detail::__from_chars_alnum<false>(__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 (__gnu_cxx::__int_traits<_Up>::__max |
604 | > __gnu_cxx::__int_traits<_Tp>::__max) |
605 | { |
606 | if (__val > __gnu_cxx::__int_traits<_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 | /// floating-point format for primitive numerical conversion |
620 | enum class chars_format |
621 | { |
622 | scientific = 1, fixed = 2, hex = 4, general = fixed | scientific |
623 | }; |
624 | |
625 | [[nodiscard]] |
626 | constexpr chars_format |
627 | operator|(chars_format __lhs, chars_format __rhs) noexcept |
628 | { return (chars_format)((unsigned)__lhs | (unsigned)__rhs); } |
629 | |
630 | [[nodiscard]] |
631 | constexpr chars_format |
632 | operator&(chars_format __lhs, chars_format __rhs) noexcept |
633 | { return (chars_format)((unsigned)__lhs & (unsigned)__rhs); } |
634 | |
635 | [[nodiscard]] |
636 | constexpr chars_format |
637 | operator^(chars_format __lhs, chars_format __rhs) noexcept |
638 | { return (chars_format)((unsigned)__lhs ^ (unsigned)__rhs); } |
639 | |
640 | [[nodiscard]] |
641 | constexpr chars_format |
642 | operator~(chars_format __fmt) noexcept |
643 | { return (chars_format)~(unsigned)__fmt; } |
644 | |
645 | constexpr chars_format& |
646 | operator|=(chars_format& __lhs, chars_format __rhs) noexcept |
647 | { return __lhs = __lhs | __rhs; } |
648 | |
649 | constexpr chars_format& |
650 | operator&=(chars_format& __lhs, chars_format __rhs) noexcept |
651 | { return __lhs = __lhs & __rhs; } |
652 | |
653 | constexpr chars_format& |
654 | operator^=(chars_format& __lhs, chars_format __rhs) noexcept |
655 | { return __lhs = __lhs ^ __rhs; } |
656 | |
657 | #if defined __cpp_lib_to_chars || _GLIBCXX_HAVE_USELOCALE |
658 | from_chars_result |
659 | from_chars(const char* __first, const char* __last, float& __value, |
660 | chars_format __fmt = chars_format::general) noexcept; |
661 | |
662 | from_chars_result |
663 | from_chars(const char* __first, const char* __last, double& __value, |
664 | chars_format __fmt = chars_format::general) noexcept; |
665 | |
666 | from_chars_result |
667 | from_chars(const char* __first, const char* __last, long double& __value, |
668 | chars_format __fmt = chars_format::general) noexcept; |
669 | |
670 | // Library routines for 16-bit extended floating point formats |
671 | // using float as interchange format. |
672 | from_chars_result |
673 | __from_chars_float16_t(const char* __first, const char* __last, |
674 | float& __value, |
675 | chars_format __fmt = chars_format::general) noexcept; |
676 | from_chars_result |
677 | __from_chars_bfloat16_t(const char* __first, const char* __last, |
678 | float& __value, |
679 | chars_format __fmt = chars_format::general) noexcept; |
680 | |
681 | #if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) \ |
682 | && defined(__cpp_lib_to_chars) |
683 | inline from_chars_result |
684 | from_chars(const char* __first, const char* __last, _Float16& __value, |
685 | chars_format __fmt = chars_format::general) noexcept |
686 | { |
687 | float __val; |
688 | from_chars_result __res |
689 | = __from_chars_float16_t(__first, __last, __val, __fmt); |
690 | if (__res.ec == errc{}) |
691 | __value = _Float16(__val); |
692 | return __res; |
693 | } |
694 | #endif |
695 | |
696 | #if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) |
697 | inline from_chars_result |
698 | from_chars(const char* __first, const char* __last, _Float32& __value, |
699 | chars_format __fmt = chars_format::general) noexcept |
700 | { |
701 | float __val; |
702 | from_chars_result __res = from_chars(__first, __last, __val, __fmt); |
703 | if (__res.ec == errc{}) |
704 | __value = _Float32(__val); |
705 | return __res; |
706 | } |
707 | #endif |
708 | |
709 | #if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) |
710 | inline from_chars_result |
711 | from_chars(const char* __first, const char* __last, _Float64& __value, |
712 | chars_format __fmt = chars_format::general) noexcept |
713 | { |
714 | double __val; |
715 | from_chars_result __res = from_chars(__first, __last, __val, __fmt); |
716 | if (__res.ec == errc{}) |
717 | __value = _Float64(__val); |
718 | return __res; |
719 | } |
720 | #endif |
721 | |
722 | #if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) |
723 | inline from_chars_result |
724 | from_chars(const char* __first, const char* __last, _Float128& __value, |
725 | chars_format __fmt = chars_format::general) noexcept |
726 | { |
727 | long double __val; |
728 | from_chars_result __res = from_chars(__first, __last, __val, __fmt); |
729 | if (__res.ec == errc{}) |
730 | __value = _Float128(__val); |
731 | return __res; |
732 | } |
733 | #elif defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_HAVE_FLOAT128_MATH) |
734 | #ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT |
735 | __extension__ from_chars_result |
736 | from_chars(const char* __first, const char* __last, __ieee128& __value, |
737 | chars_format __fmt = chars_format::general) noexcept; |
738 | |
739 | inline from_chars_result |
740 | from_chars(const char* __first, const char* __last, _Float128& __value, |
741 | chars_format __fmt = chars_format::general) noexcept |
742 | { |
743 | __extension__ __ieee128 __val; |
744 | from_chars_result __res = from_chars(__first, __last, __val, __fmt); |
745 | if (__res.ec == errc{}) |
746 | __value = _Float128(__val); |
747 | return __res; |
748 | } |
749 | #else |
750 | from_chars_result |
751 | from_chars(const char* __first, const char* __last, _Float128& __value, |
752 | chars_format __fmt = chars_format::general) noexcept; |
753 | #endif |
754 | #endif |
755 | |
756 | #if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) \ |
757 | && defined(__cpp_lib_to_chars) |
758 | inline from_chars_result |
759 | from_chars(const char* __first, const char* __last, |
760 | __gnu_cxx::__bfloat16_t & __value, |
761 | chars_format __fmt = chars_format::general) noexcept |
762 | { |
763 | float __val; |
764 | from_chars_result __res |
765 | = __from_chars_bfloat16_t(__first, __last, __val, __fmt); |
766 | if (__res.ec == errc{}) |
767 | __value = __gnu_cxx::__bfloat16_t(__val); |
768 | return __res; |
769 | } |
770 | #endif |
771 | #endif |
772 | |
773 | #if defined __cpp_lib_to_chars |
774 | // Floating-point std::to_chars |
775 | |
776 | // Overloads for float. |
777 | to_chars_result to_chars(char* __first, char* __last, float __value) noexcept; |
778 | to_chars_result to_chars(char* __first, char* __last, float __value, |
779 | chars_format __fmt) noexcept; |
780 | to_chars_result to_chars(char* __first, char* __last, float __value, |
781 | chars_format __fmt, int __precision) noexcept; |
782 | |
783 | // Overloads for double. |
784 | to_chars_result to_chars(char* __first, char* __last, double __value) noexcept; |
785 | to_chars_result to_chars(char* __first, char* __last, double __value, |
786 | chars_format __fmt) noexcept; |
787 | to_chars_result to_chars(char* __first, char* __last, double __value, |
788 | chars_format __fmt, int __precision) noexcept; |
789 | |
790 | // Overloads for long double. |
791 | to_chars_result to_chars(char* __first, char* __last, long double __value) |
792 | noexcept; |
793 | to_chars_result to_chars(char* __first, char* __last, long double __value, |
794 | chars_format __fmt) noexcept; |
795 | to_chars_result to_chars(char* __first, char* __last, long double __value, |
796 | chars_format __fmt, int __precision) noexcept; |
797 | |
798 | // Library routines for 16-bit extended floating point formats |
799 | // using float as interchange format. |
800 | to_chars_result __to_chars_float16_t(char* __first, char* __last, |
801 | float __value, |
802 | chars_format __fmt) noexcept; |
803 | to_chars_result __to_chars_bfloat16_t(char* __first, char* __last, |
804 | float __value, |
805 | chars_format __fmt) noexcept; |
806 | |
807 | #if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) |
808 | inline to_chars_result |
809 | to_chars(char* __first, char* __last, _Float16 __value) noexcept |
810 | { |
811 | return __to_chars_float16_t(__first, __last, float(__value), |
812 | chars_format{}); |
813 | } |
814 | inline to_chars_result |
815 | to_chars(char* __first, char* __last, _Float16 __value, |
816 | chars_format __fmt) noexcept |
817 | { return __to_chars_float16_t(__first, __last, float(__value), __fmt); } |
818 | inline to_chars_result |
819 | to_chars(char* __first, char* __last, _Float16 __value, |
820 | chars_format __fmt, int __precision) noexcept |
821 | { return to_chars(__first, __last, float(__value), __fmt, __precision); } |
822 | #endif |
823 | |
824 | #if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) |
825 | inline to_chars_result |
826 | to_chars(char* __first, char* __last, _Float32 __value) noexcept |
827 | { return to_chars(__first, __last, float(__value)); } |
828 | inline to_chars_result |
829 | to_chars(char* __first, char* __last, _Float32 __value, |
830 | chars_format __fmt) noexcept |
831 | { return to_chars(__first, __last, float(__value), __fmt); } |
832 | inline to_chars_result |
833 | to_chars(char* __first, char* __last, _Float32 __value, |
834 | chars_format __fmt, int __precision) noexcept |
835 | { return to_chars(__first, __last, float(__value), __fmt, __precision); } |
836 | #endif |
837 | |
838 | #if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) |
839 | inline to_chars_result |
840 | to_chars(char* __first, char* __last, _Float64 __value) noexcept |
841 | { return to_chars(__first, __last, double(__value)); } |
842 | inline to_chars_result |
843 | to_chars(char* __first, char* __last, _Float64 __value, |
844 | chars_format __fmt) noexcept |
845 | { return to_chars(__first, __last, double(__value), __fmt); } |
846 | inline to_chars_result |
847 | to_chars(char* __first, char* __last, _Float64 __value, |
848 | chars_format __fmt, int __precision) noexcept |
849 | { return to_chars(__first, __last, double(__value), __fmt, __precision); } |
850 | #endif |
851 | |
852 | #if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) |
853 | inline to_chars_result |
854 | to_chars(char* __first, char* __last, _Float128 __value) noexcept |
855 | { return to_chars(__first, __last, static_cast<long double>(__value)); } |
856 | inline to_chars_result |
857 | to_chars(char* __first, char* __last, _Float128 __value, |
858 | chars_format __fmt) noexcept |
859 | { |
860 | return to_chars(__first, __last, static_cast<long double>(__value), __fmt); |
861 | } |
862 | inline to_chars_result |
863 | to_chars(char* __first, char* __last, _Float128 __value, |
864 | chars_format __fmt, int __precision) noexcept |
865 | { |
866 | return to_chars(__first, __last, static_cast<long double>(__value), __fmt, |
867 | __precision); |
868 | } |
869 | #elif defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_HAVE_FLOAT128_MATH) |
870 | #ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT |
871 | __extension__ to_chars_result |
872 | to_chars(char* __first, char* __last, __float128 __value) noexcept; |
873 | __extension__ to_chars_result |
874 | to_chars(char* __first, char* __last, __float128 __value, |
875 | chars_format __fmt) noexcept; |
876 | __extension__ to_chars_result |
877 | to_chars(char* __first, char* __last, __float128 __value, |
878 | chars_format __fmt, int __precision) noexcept; |
879 | |
880 | inline to_chars_result |
881 | to_chars(char* __first, char* __last, _Float128 __value) noexcept |
882 | { |
883 | return __extension__ to_chars(__first, __last, |
884 | static_cast<__float128>(__value)); |
885 | } |
886 | inline to_chars_result |
887 | to_chars(char* __first, char* __last, _Float128 __value, |
888 | chars_format __fmt) noexcept |
889 | { |
890 | |
891 | return __extension__ to_chars(__first, __last, |
892 | static_cast<__float128>(__value), __fmt); |
893 | } |
894 | inline to_chars_result |
895 | to_chars(char* __first, char* __last, _Float128 __value, |
896 | chars_format __fmt, int __precision) noexcept |
897 | { |
898 | |
899 | return __extension__ to_chars(__first, __last, |
900 | static_cast<__float128>(__value), __fmt, |
901 | __precision); |
902 | } |
903 | #else |
904 | to_chars_result to_chars(char* __first, char* __last, _Float128 __value) |
905 | noexcept; |
906 | to_chars_result to_chars(char* __first, char* __last, _Float128 __value, |
907 | chars_format __fmt) noexcept; |
908 | to_chars_result to_chars(char* __first, char* __last, _Float128 __value, |
909 | chars_format __fmt, int __precision) noexcept; |
910 | #endif |
911 | #endif |
912 | |
913 | #if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) |
914 | inline to_chars_result |
915 | to_chars(char* __first, char* __last, |
916 | __gnu_cxx::__bfloat16_t __value) noexcept |
917 | { |
918 | return __to_chars_bfloat16_t(__first, __last, float(__value), |
919 | chars_format{}); |
920 | } |
921 | inline to_chars_result |
922 | to_chars(char* __first, char* __last, __gnu_cxx::__bfloat16_t __value, |
923 | chars_format __fmt) noexcept |
924 | { return __to_chars_bfloat16_t(__first, __last, float(__value), __fmt); } |
925 | inline to_chars_result |
926 | to_chars(char* __first, char* __last, __gnu_cxx::__bfloat16_t __value, |
927 | chars_format __fmt, int __precision) noexcept |
928 | { return to_chars(__first, __last, float(__value), __fmt, __precision); } |
929 | #endif |
930 | #endif |
931 | |
932 | _GLIBCXX_END_NAMESPACE_VERSION |
933 | } // namespace std |
934 | #endif // C++14 |
935 | #endif // _GLIBCXX_CHARCONV |
936 | |