LCOV - code coverage report
Current view: top level - 11 - charconv (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 50 125 40.0 %
Date: 2025-08-24 09:11:10 Functions: 14 16 87.5 %

          Line data    Source code
       1             : // Primitive numeric conversions (to_chars and from_chars) -*- C++ -*-
       2             : 
       3             : // Copyright (C) 2017-2021 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             : #if _GLIBCXX_HAVE_USELOCALE
      47             : # define __cpp_lib_to_chars 201611L
      48             : #endif
      49             : 
      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;
      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
      64             :   };
      65             : 
      66             :   /// Result type of std::from_chars
      67             :   struct from_chars_result
      68             :   {
      69             :     const char* ptr;
      70             :     errc ec;
      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
      76             :   };
      77             : 
      78             : namespace __detail
      79             : {
      80             :   template<typename _Tp>
      81             :     using __integer_to_chars_result_type
      82             :       = enable_if_t<__or_<__is_signed_integer<_Tp>,
      83             :                           __is_unsigned_integer<_Tp>,
      84             :                           is_same<char, remove_cv_t<_Tp>>>::value,
      85             :                     to_chars_result>;
      86             : 
      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).
      92             :   template<typename _Tp>
      93             :     struct __to_chars_unsigned_type : __make_unsigned_selector_base
      94             :     {
      95             :       using _UInts = _List<unsigned int, unsigned long, unsigned long long
      96             : #if _GLIBCXX_USE_INT128
      97             :         , unsigned __int128
      98             : #endif
      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;
     105             : 
     106             :   // Generic implementation for arbitrary bases.
     107             :   // Defined in <bits/charconv.h>.
     108             :   template<typename _Tp>
     109             :     constexpr unsigned
     110             :     __to_chars_len(_Tp __value, int __base /* = 10 */) noexcept;
     111             : 
     112             :   template<typename _Tp>
     113             :     constexpr unsigned
     114             :     __to_chars_len_2(_Tp __value) noexcept
     115             :     { return std::__bit_width(__value); }
     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             : 
     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             :       };
     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             :     __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             : 
     168             :       const unsigned __len = (__to_chars_len_2(__val) + 3) / 4;
     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             : 
     177             :       static constexpr char __digits[] = {
     178             :         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
     179             :         'a', 'b', 'c', 'd', 'e', 'f'
     180             :       };
     181             :       unsigned __pos = __len - 1;
     182             :       while (__val >= 0x100)
     183             :         {
     184             :           auto __num = __val & 0xF;
     185             :           __val >>= 4;
     186             :           __first[__pos] = __digits[__num];
     187             :           __num = __val & 0xF;
     188             :           __val >>= 4;
     189             :           __first[__pos - 1] = __digits[__num];
     190             :           __pos -= 2;
     191             :         }
     192             :       if (__val >= 0x10)
     193             :         {
     194             :           const auto __num = __val & 0xF;
     195             :           __val >>= 4;
     196             :           __first[1] = __digits[__num];
     197             :           __first[0] = __digits[__val];
     198             :         }
     199             :       else
     200             :         __first[0] = __digits[__val];
     201             :       __res.ptr = __first + __len;
     202             :       __res.ec = {};
     203             :       return __res;
     204             :     }
     205             : 
     206             :   template<typename _Tp>
     207             :     inline __integer_to_chars_result_type<_Tp>
     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             : 
     224             :       __detail::__to_chars_10_impl(__first, __len, __val);
     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;
     238             :       unsigned __len;
     239             : 
     240             :       if _GLIBCXX17_CONSTEXPR (__gnu_cxx::__int_traits<_Tp>::__digits <= 16)
     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;
     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             : 
     259             :       unsigned __pos = __len - 1;
     260             :       while (__val >= 0100)
     261             :         {
     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;
     268             :           __pos -= 2;
     269             :         }
     270             :       if (__val >= 010)
     271             :         {
     272             :           auto const __num = __val & 7;
     273             :           __val >>= 3;
     274             :           __first[1] = '0' + __num;
     275             :           __first[0] = '0' + __val;
     276             :         }
     277             :       else
     278             :         __first[0] = '0' + __val;
     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             :         }
     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';
     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>
     323             :     __to_chars_i(char* __first, char* __last, _Tp __value, int __base = 10)
     324             :     {
     325             :       __glibcxx_assert(2 <= __base && __base <= 36);
     326             : 
     327             :       using _Up = __detail::__unsigned_least_t<_Tp>;
     328             :       _Up __unsigned_val = __value;
     329             : 
     330             :       if (__first == __last) [[__unlikely__]]
     331             :         return { __last, errc::value_too_large };
     332             : 
     333             :       if (__value == 0)
     334             :         {
     335             :           *__first = '0';
     336             :           return { __first + 1, errc{} };
     337             :         }
     338             :       else if _GLIBCXX17_CONSTEXPR (std::is_signed<_Tp>::value)
     339             :         if (__value < 0)
     340             :           {
     341             :             *__first++ = '-';
     342             :             __unsigned_val = _Up(~__value) + _Up(1);
     343             :           }
     344             : 
     345             :       switch (__base)
     346             :       {
     347             :       case 16:
     348             :         return __detail::__to_chars_16(__first, __last, __unsigned_val);
     349             :       case 10:
     350             :         return __detail::__to_chars_10(__first, __last, __unsigned_val);
     351             :       case 8:
     352             :         return __detail::__to_chars_8(__first, __last, __unsigned_val);
     353             :       case 2:
     354             :         return __detail::__to_chars_2(__first, __last, __unsigned_val);
     355             :       default:
     356             :         return __detail::__to_chars(__first, __last, __unsigned_val, __base);
     357             :       }
     358             :     }
     359             : 
     360             : #define _GLIBCXX_TO_CHARS(T) \
     361             :   inline to_chars_result \
     362             :   to_chars(char* __first, char* __last, T __value, int __base = 10) \
     363             :   { return std::__to_chars_i<T>(__first, __last, __value, __base); }
     364             : _GLIBCXX_TO_CHARS(char)
     365             : _GLIBCXX_TO_CHARS(signed char)
     366             : _GLIBCXX_TO_CHARS(unsigned char)
     367             : _GLIBCXX_TO_CHARS(signed short)
     368             : _GLIBCXX_TO_CHARS(unsigned short)
     369             : _GLIBCXX_TO_CHARS(signed int)
     370             : _GLIBCXX_TO_CHARS(unsigned int)
     371             : _GLIBCXX_TO_CHARS(signed long)
     372             : _GLIBCXX_TO_CHARS(unsigned long)
     373             : _GLIBCXX_TO_CHARS(signed long long)
     374             : _GLIBCXX_TO_CHARS(unsigned long long)
     375             : #if defined(__GLIBCXX_TYPE_INT_N_0)
     376             : _GLIBCXX_TO_CHARS(signed __GLIBCXX_TYPE_INT_N_0)
     377             : _GLIBCXX_TO_CHARS(unsigned __GLIBCXX_TYPE_INT_N_0)
     378             : #endif
     379             : #if defined(__GLIBCXX_TYPE_INT_N_1)
     380             : _GLIBCXX_TO_CHARS(signed __GLIBCXX_TYPE_INT_N_1)
     381             : _GLIBCXX_TO_CHARS(unsigned __GLIBCXX_TYPE_INT_N_1)
     382             : #endif
     383             : #if defined(__GLIBCXX_TYPE_INT_N_2)
     384             : _GLIBCXX_TO_CHARS(signed __GLIBCXX_TYPE_INT_N_2)
     385             : _GLIBCXX_TO_CHARS(unsigned __GLIBCXX_TYPE_INT_N_2)
     386             : #endif
     387             : #if defined(__GLIBCXX_TYPE_INT_N_3)
     388             : _GLIBCXX_TO_CHARS(signed __GLIBCXX_TYPE_INT_N_3)
     389             : _GLIBCXX_TO_CHARS(unsigned __GLIBCXX_TYPE_INT_N_3)
     390             : #endif
     391             : #undef _GLIBCXX_TO_CHARS
     392             : 
     393             :   // _GLIBCXX_RESOLVE_LIB_DEFECTS
     394             :   // 3266. to_chars(bool) should be deleted
     395             :   to_chars_result to_chars(char*, char*, bool, int = 10) = delete;
     396             : 
     397             : namespace __detail
     398             : {
     399             :   template<typename _Tp>
     400             :     bool
     401      104957 :     __raise_and_add(_Tp& __val, int __base, unsigned char __c)
     402             :     {
     403      209914 :       if (__builtin_mul_overflow(__val, __base, &__val)
     404      104957 :           || __builtin_add_overflow(__val, __c, &__val))
     405           0 :         return false;
     406      104957 :       return true;
     407             :     }
     408             : 
     409             :   /// std::from_chars implementation for integers in base 2.
     410             :   template<typename _Tp>
     411             :     bool
     412           0 :     __from_chars_binary(const char*& __first, const char* __last, _Tp& __val)
     413             :     {
     414             :       static_assert(is_integral<_Tp>::value, "implementation bug");
     415             :       static_assert(is_unsigned<_Tp>::value, "implementation bug");
     416             : 
     417           0 :       const ptrdiff_t __len = __last - __first;
     418           0 :       ptrdiff_t __i = 0;
     419           0 :       while (__i < __len && __first[__i] == '0')
     420           0 :         ++__i;
     421           0 :       const ptrdiff_t __leading_zeroes = __i;
     422             : 
     423           0 :       while (__i < __len)
     424             :         {
     425           0 :           const unsigned char __c = (unsigned)__first[__i] - '0';
     426           0 :           if (__c < 2)
     427           0 :             __val = (__val << 1) | __c;
     428             :           else
     429           0 :             break;
     430           0 :           __i++;
     431             :         }
     432           0 :       __first += __i;
     433           0 :       return (__i - __leading_zeroes) <= __gnu_cxx::__int_traits<_Tp>::__digits;
     434             :     }
     435             : 
     436             :   /// std::from_chars implementation for integers in bases 3 to 10.
     437             :   template<typename _Tp>
     438             :     bool
     439        7184 :     __from_chars_digit(const char*& __first, const char* __last, _Tp& __val,
     440             :                        int __base)
     441             :     {
     442             :       static_assert(is_integral<_Tp>::value, "implementation bug");
     443             :       static_assert(is_unsigned<_Tp>::value, "implementation bug");
     444             : 
     445       51994 :       auto __matches = [__base](char __c) {
     446       22405 :           return '0' <= __c && __c <= ('0' + (__base - 1));
     447             :       };
     448             : 
     449       29589 :       while (__first != __last)
     450             :         {
     451       22405 :           const char __c = *__first;
     452       22405 :           if (__matches(__c))
     453             :           {
     454       22405 :             if (!__raise_and_add(__val, __base, __c - '0'))
     455             :               {
     456           0 :                 while (++__first != __last && __matches(*__first))
     457             :                   ;
     458           0 :                 return false;
     459             :               }
     460       22405 :             __first++;
     461             :           }
     462             :           else
     463           0 :             return true;
     464             :         }
     465        7184 :       return true;
     466             :     }
     467             : 
     468             :   constexpr char
     469        1004 :   __from_chars_alpha_to_num(char __c)
     470             :   {
     471        1004 :     switch (__c)
     472             :     {
     473           0 :     case 'a':
     474             :     case 'A':
     475           0 :       return 10;
     476           0 :     case 'b':
     477             :     case 'B':
     478           0 :       return 11;
     479           0 :     case 'c':
     480             :     case 'C':
     481           0 :       return 12;
     482        1004 :     case 'd':
     483             :     case 'D':
     484        1004 :       return 13;
     485           0 :     case 'e':
     486             :     case 'E':
     487           0 :       return 14;
     488           0 :     case 'f':
     489             :     case 'F':
     490           0 :       return 15;
     491           0 :     case 'g':
     492             :     case 'G':
     493           0 :       return 16;
     494           0 :     case 'h':
     495             :     case 'H':
     496           0 :       return 17;
     497           0 :     case 'i':
     498             :     case 'I':
     499           0 :       return 18;
     500           0 :     case 'j':
     501             :     case 'J':
     502           0 :       return 19;
     503           0 :     case 'k':
     504             :     case 'K':
     505           0 :       return 20;
     506           0 :     case 'l':
     507             :     case 'L':
     508           0 :       return 21;
     509           0 :     case 'm':
     510             :     case 'M':
     511           0 :       return 22;
     512           0 :     case 'n':
     513             :     case 'N':
     514           0 :       return 23;
     515           0 :     case 'o':
     516             :     case 'O':
     517           0 :       return 24;
     518           0 :     case 'p':
     519             :     case 'P':
     520           0 :       return 25;
     521           0 :     case 'q':
     522             :     case 'Q':
     523           0 :       return 26;
     524           0 :     case 'r':
     525             :     case 'R':
     526           0 :       return 27;
     527           0 :     case 's':
     528             :     case 'S':
     529           0 :       return 28;
     530           0 :     case 't':
     531             :     case 'T':
     532           0 :       return 29;
     533           0 :     case 'u':
     534             :     case 'U':
     535           0 :       return 30;
     536           0 :     case 'v':
     537             :     case 'V':
     538           0 :       return 31;
     539           0 :     case 'w':
     540             :     case 'W':
     541           0 :       return 32;
     542           0 :     case 'x':
     543             :     case 'X':
     544           0 :       return 33;
     545           0 :     case 'y':
     546             :     case 'Y':
     547           0 :       return 34;
     548           0 :     case 'z':
     549             :     case 'Z':
     550           0 :       return 35;
     551             :     }
     552           0 :     return 127;
     553             :   }
     554             : 
     555             :   /// std::from_chars implementation for integers in bases 11 to 36.
     556             :   template<typename _Tp>
     557             :     bool
     558       20635 :     __from_chars_alnum(const char*& __first, const char* __last, _Tp& __val,
     559             :                        int __base)
     560             :     {
     561       20635 :       bool __valid = true;
     562      103187 :       while (__first != __last)
     563             :         {
     564       82552 :           char __c = *__first;
     565       82552 :           if ('0' <= __c && __c <= '9') // isdigit
     566       81548 :             __c -= '0';
     567             :           else
     568             :             {
     569        1004 :               __c = __from_chars_alpha_to_num(__c);
     570        1004 :               if (__c >= __base)
     571           0 :                 break;
     572             :             }
     573             : 
     574       82552 :           if (__builtin_expect(__valid, 1))
     575       82552 :             __valid = __raise_and_add(__val, __base, __c);
     576       82552 :           __first++;
     577             :         }
     578       20635 :       return __valid;
     579             :     }
     580             : 
     581             :   template<typename _Tp>
     582             :     using __integer_from_chars_result_type
     583             :       = enable_if_t<__or_<__is_signed_integer<_Tp>,
     584             :                           __is_unsigned_integer<_Tp>,
     585             :                           is_same<char, remove_cv_t<_Tp>>>::value,
     586             :                     from_chars_result>;
     587             : 
     588             : } // namespace __detail
     589             : 
     590             :   /// std::from_chars for integral types.
     591             :   template<typename _Tp>
     592             :     __detail::__integer_from_chars_result_type<_Tp>
     593       27819 :     from_chars(const char* __first, const char* __last, _Tp& __value,
     594             :                int __base = 10)
     595             :     {
     596             :       __glibcxx_assert(2 <= __base && __base <= 36);
     597             : 
     598       27819 :       from_chars_result __res{__first, {}};
     599             : 
     600       27819 :       int __sign = 1;
     601             :       if _GLIBCXX17_CONSTEXPR (std::is_signed<_Tp>::value)
     602        3498 :         if (__first != __last && *__first == '-')
     603             :           {
     604         692 :             __sign = -1;
     605         692 :             ++__first;
     606             :           }
     607             : 
     608             :       using _Up = __detail::__unsigned_least_t<_Tp>;
     609       27819 :       _Up __val = 0;
     610             : 
     611       27819 :       const auto __start = __first;
     612             :       bool __valid;
     613       27819 :       if (__base == 2)
     614           0 :         __valid = __detail::__from_chars_binary(__first, __last, __val);
     615       27819 :       else if (__base <= 10)
     616        7184 :         __valid = __detail::__from_chars_digit(__first, __last, __val, __base);
     617             :       else
     618       20635 :         __valid = __detail::__from_chars_alnum(__first, __last, __val, __base);
     619             : 
     620       27819 :       if (__builtin_expect(__first == __start, 0))
     621           0 :         __res.ec = errc::invalid_argument;
     622             :       else
     623             :         {
     624       27819 :           __res.ptr = __first;
     625       27819 :           if (!__valid)
     626           0 :             __res.ec = errc::result_out_of_range;
     627             :           else
     628             :             {
     629             :               if _GLIBCXX17_CONSTEXPR (std::is_signed<_Tp>::value)
     630             :                 {
     631             :                   _Tp __tmp;
     632        3498 :                   if (__builtin_mul_overflow(__val, __sign, &__tmp))
     633           0 :                     __res.ec = errc::result_out_of_range;
     634             :                   else
     635        3498 :                     __value = __tmp;
     636             :                 }
     637             :               else
     638             :                 {
     639             :                   if _GLIBCXX17_CONSTEXPR (__gnu_cxx::__int_traits<_Up>::__max
     640             :                       > __gnu_cxx::__int_traits<_Tp>::__max)
     641             :                     {
     642         708 :                       if (__val > __gnu_cxx::__int_traits<_Tp>::__max)
     643           0 :                         __res.ec = errc::result_out_of_range;
     644             :                       else
     645         708 :                         __value = __val;
     646             :                     }
     647             :                   else
     648       23613 :                     __value = __val;
     649             :                 }
     650             :             }
     651             :         }
     652       27819 :       return __res;
     653             :     }
     654             : 
     655             :   /// floating-point format for primitive numerical conversion
     656             :   enum class chars_format
     657             :   {
     658             :     scientific = 1, fixed = 2, hex = 4, general = fixed | scientific
     659             :   };
     660             : 
     661             :   constexpr chars_format
     662             :   operator|(chars_format __lhs, chars_format __rhs) noexcept
     663             :   { return (chars_format)((unsigned)__lhs | (unsigned)__rhs); }
     664             : 
     665             :   constexpr chars_format
     666             :   operator&(chars_format __lhs, chars_format __rhs) noexcept
     667             :   { return (chars_format)((unsigned)__lhs & (unsigned)__rhs); }
     668             : 
     669             :   constexpr chars_format
     670             :   operator^(chars_format __lhs, chars_format __rhs) noexcept
     671             :   { return (chars_format)((unsigned)__lhs ^ (unsigned)__rhs); }
     672             : 
     673             :   constexpr chars_format
     674             :   operator~(chars_format __fmt) noexcept
     675             :   { return (chars_format)~(unsigned)__fmt; }
     676             : 
     677             :   constexpr chars_format&
     678             :   operator|=(chars_format& __lhs, chars_format __rhs) noexcept
     679             :   { return __lhs = __lhs | __rhs; }
     680             : 
     681             :   constexpr chars_format&
     682             :   operator&=(chars_format& __lhs, chars_format __rhs) noexcept
     683             :   { return __lhs = __lhs & __rhs; }
     684             : 
     685             :   constexpr chars_format&
     686             :   operator^=(chars_format& __lhs, chars_format __rhs) noexcept
     687             :   { return __lhs = __lhs ^ __rhs; }
     688             : 
     689             : #if _GLIBCXX_HAVE_USELOCALE
     690             :   from_chars_result
     691             :   from_chars(const char* __first, const char* __last, float& __value,
     692             :              chars_format __fmt = chars_format::general) noexcept;
     693             : 
     694             :   from_chars_result
     695             :   from_chars(const char* __first, const char* __last, double& __value,
     696             :              chars_format __fmt = chars_format::general) noexcept;
     697             : 
     698             :   from_chars_result
     699             :   from_chars(const char* __first, const char* __last, long double& __value,
     700             :              chars_format __fmt = chars_format::general) noexcept;
     701             : #endif
     702             : 
     703             : #if _GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 \
     704             :     && __SIZE_WIDTH__ >= 32
     705             :   // Floating-point std::to_chars
     706             : 
     707             :   // Overloads for float.
     708             :   to_chars_result to_chars(char* __first, char* __last, float __value) noexcept;
     709             :   to_chars_result to_chars(char* __first, char* __last, float __value,
     710             :                            chars_format __fmt) noexcept;
     711             :   to_chars_result to_chars(char* __first, char* __last, float __value,
     712             :                            chars_format __fmt, int __precision) noexcept;
     713             : 
     714             :   // Overloads for double.
     715             :   to_chars_result to_chars(char* __first, char* __last, double __value) noexcept;
     716             :   to_chars_result to_chars(char* __first, char* __last, double __value,
     717             :                            chars_format __fmt) noexcept;
     718             :   to_chars_result to_chars(char* __first, char* __last, double __value,
     719             :                            chars_format __fmt, int __precision) noexcept;
     720             : 
     721             :   // Overloads for long double.
     722             :   to_chars_result to_chars(char* __first, char* __last, long double __value)
     723             :     noexcept;
     724             :   to_chars_result to_chars(char* __first, char* __last, long double __value,
     725             :                            chars_format __fmt) noexcept;
     726             :   to_chars_result to_chars(char* __first, char* __last, long double __value,
     727             :                            chars_format __fmt, int __precision) noexcept;
     728             : #endif
     729             : 
     730             : _GLIBCXX_END_NAMESPACE_VERSION
     731             : } // namespace std
     732             : #endif // C++14
     733             : #endif // _GLIBCXX_CHARCONV

Generated by: LCOV version 1.14