(root)/
gcc-13.2.0/
libstdc++-v3/
include/
bits/
parse_numbers.h
       1  // Components for compile-time parsing of numbers -*- C++ -*-
       2  
       3  // Copyright (C) 2013-2023 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 bits/parse_numbers.h
      26   *  This is an internal header file, included by other library headers.
      27   *  Do not attempt to use it directly. @headername{chrono}
      28   */
      29  
      30  #ifndef _GLIBCXX_PARSE_NUMBERS_H
      31  #define _GLIBCXX_PARSE_NUMBERS_H 1
      32  
      33  #pragma GCC system_header
      34  
      35  // From n3642.pdf except I added binary literals and digit separator '\''.
      36  
      37  #if __cplusplus >= 201402L
      38  
      39  #include <type_traits>
      40  #include <ext/numeric_traits.h>
      41  
      42  namespace std _GLIBCXX_VISIBILITY(default)
      43  {
      44  _GLIBCXX_BEGIN_NAMESPACE_VERSION
      45  
      46  namespace __parse_int
      47  {
      48    template<unsigned _Base, char _Dig>
      49      struct _Digit;
      50  
      51    template<unsigned _Base>
      52      struct _Digit<_Base, '0'> : integral_constant<unsigned, 0>
      53      {
      54        using __valid = true_type;
      55      };
      56  
      57    template<unsigned _Base>
      58      struct _Digit<_Base, '1'> : integral_constant<unsigned, 1>
      59      {
      60        using __valid = true_type;
      61      };
      62  
      63    template<unsigned _Base, unsigned _Val>
      64      struct _Digit_impl : integral_constant<unsigned, _Val>
      65      {
      66        static_assert(_Base > _Val, "invalid digit");
      67        using __valid = true_type;
      68      };
      69  
      70    template<unsigned _Base>
      71      struct _Digit<_Base, '2'> : _Digit_impl<_Base, 2>
      72      { };
      73  
      74    template<unsigned _Base>
      75      struct _Digit<_Base, '3'> : _Digit_impl<_Base, 3>
      76      { };
      77  
      78    template<unsigned _Base>
      79      struct _Digit<_Base, '4'> : _Digit_impl<_Base, 4>
      80      { };
      81  
      82    template<unsigned _Base>
      83      struct _Digit<_Base, '5'> : _Digit_impl<_Base, 5>
      84      { };
      85  
      86    template<unsigned _Base>
      87      struct _Digit<_Base, '6'> : _Digit_impl<_Base, 6>
      88      { };
      89  
      90    template<unsigned _Base>
      91      struct _Digit<_Base, '7'> : _Digit_impl<_Base, 7>
      92      { };
      93  
      94    template<unsigned _Base>
      95      struct _Digit<_Base, '8'> : _Digit_impl<_Base, 8>
      96      { };
      97  
      98    template<unsigned _Base>
      99      struct _Digit<_Base, '9'> : _Digit_impl<_Base, 9>
     100      { };
     101  
     102    template<unsigned _Base>
     103      struct _Digit<_Base, 'a'> : _Digit_impl<_Base, 0xa>
     104      { };
     105  
     106    template<unsigned _Base>
     107      struct _Digit<_Base, 'A'> : _Digit_impl<_Base, 0xa>
     108      { };
     109  
     110    template<unsigned _Base>
     111      struct _Digit<_Base, 'b'> : _Digit_impl<_Base, 0xb>
     112      { };
     113  
     114    template<unsigned _Base>
     115      struct _Digit<_Base, 'B'> : _Digit_impl<_Base, 0xb>
     116      { };
     117  
     118    template<unsigned _Base>
     119      struct _Digit<_Base, 'c'> : _Digit_impl<_Base, 0xc>
     120      { };
     121  
     122    template<unsigned _Base>
     123      struct _Digit<_Base, 'C'> : _Digit_impl<_Base, 0xc>
     124      { };
     125  
     126    template<unsigned _Base>
     127      struct _Digit<_Base, 'd'> : _Digit_impl<_Base, 0xd>
     128      { };
     129  
     130    template<unsigned _Base>
     131      struct _Digit<_Base, 'D'> : _Digit_impl<_Base, 0xd>
     132      { };
     133  
     134    template<unsigned _Base>
     135      struct _Digit<_Base, 'e'> : _Digit_impl<_Base, 0xe>
     136      { };
     137  
     138    template<unsigned _Base>
     139      struct _Digit<_Base, 'E'> : _Digit_impl<_Base, 0xe>
     140      { };
     141  
     142    template<unsigned _Base>
     143      struct _Digit<_Base, 'f'> : _Digit_impl<_Base, 0xf>
     144      { };
     145  
     146    template<unsigned _Base>
     147      struct _Digit<_Base, 'F'> : _Digit_impl<_Base, 0xf>
     148      { };
     149  
     150    //  Digit separator
     151    template<unsigned _Base>
     152      struct _Digit<_Base, '\''> : integral_constant<unsigned, 0>
     153      {
     154        using __valid = false_type;
     155      };
     156  
     157  //------------------------------------------------------------------------------
     158  
     159    template<unsigned long long _Val>
     160      using __ull_constant = integral_constant<unsigned long long, _Val>;
     161  
     162    template<unsigned _Base, char _Dig, char... _Digs>
     163      struct _Power_help
     164      {
     165        using __next = typename _Power_help<_Base, _Digs...>::type;
     166        using __valid_digit = typename _Digit<_Base, _Dig>::__valid;
     167        using type
     168  	= __ull_constant<__next::value * (__valid_digit{} ? _Base : 1ULL)>;
     169      };
     170  
     171    template<unsigned _Base, char _Dig>
     172      struct _Power_help<_Base, _Dig>
     173      {
     174        using __valid_digit = typename _Digit<_Base, _Dig>::__valid;
     175        using type = __ull_constant<__valid_digit::value>;
     176      };
     177  
     178    template<unsigned _Base, char... _Digs>
     179      struct _Power : _Power_help<_Base, _Digs...>::type
     180      { };
     181  
     182    template<unsigned _Base>
     183      struct _Power<_Base> : __ull_constant<0>
     184      { };
     185  
     186  //------------------------------------------------------------------------------
     187  
     188    template<unsigned _Base, unsigned long long _Pow, char _Dig, char... _Digs>
     189      struct _Number_help
     190      {
     191        using __digit = _Digit<_Base, _Dig>;
     192        using __valid_digit = typename __digit::__valid;
     193        using __next = _Number_help<_Base,
     194  				  __valid_digit::value ? _Pow / _Base : _Pow,
     195  				  _Digs...>;
     196        using type = __ull_constant<_Pow * __digit::value + __next::type::value>;
     197        static_assert((type::value / _Pow) == __digit::value,
     198  		    "integer literal does not fit in unsigned long long");
     199      };
     200  
     201    // Skip past digit separators:
     202    template<unsigned _Base, unsigned long long _Pow, char _Dig, char..._Digs>
     203      struct _Number_help<_Base, _Pow, '\'', _Dig, _Digs...>
     204      : _Number_help<_Base, _Pow, _Dig, _Digs...>
     205      { };
     206  
     207    // Terminating case for recursion:
     208    template<unsigned _Base, char _Dig>
     209      struct _Number_help<_Base, 1ULL, _Dig>
     210      {
     211        using type = __ull_constant<_Digit<_Base, _Dig>::value>;
     212      };
     213  
     214    template<unsigned _Base, char... _Digs>
     215      struct _Number
     216      : _Number_help<_Base, _Power<_Base, _Digs...>::value, _Digs...>::type
     217      { };
     218  
     219    template<unsigned _Base>
     220      struct _Number<_Base>
     221      : __ull_constant<0>
     222      { };
     223  
     224  //------------------------------------------------------------------------------
     225  
     226    template<char... _Digs>
     227      struct _Parse_int;
     228  
     229    template<char... _Digs>
     230      struct _Parse_int<'0', 'b', _Digs...>
     231      : _Number<2U, _Digs...>::type
     232      { };
     233  
     234    template<char... _Digs>
     235      struct _Parse_int<'0', 'B', _Digs...>
     236      : _Number<2U, _Digs...>::type
     237      { };
     238  
     239    template<char... _Digs>
     240      struct _Parse_int<'0', 'x', _Digs...>
     241      : _Number<16U, _Digs...>::type
     242      { };
     243  
     244    template<char... _Digs>
     245      struct _Parse_int<'0', 'X', _Digs...>
     246      : _Number<16U, _Digs...>::type
     247      { };
     248  
     249    template<char... _Digs>
     250      struct _Parse_int<'0', _Digs...>
     251      : _Number<8U, _Digs...>::type
     252      { };
     253  
     254    template<char... _Digs>
     255      struct _Parse_int
     256      : _Number<10U, _Digs...>::type
     257      { };
     258  
     259  } // namespace __parse_int
     260  
     261  
     262  namespace __select_int
     263  {
     264    template<unsigned long long _Val, typename... _Ints>
     265      struct _Select_int_base;
     266  
     267    template<unsigned long long _Val, typename _IntType, typename... _Ints>
     268      struct _Select_int_base<_Val, _IntType, _Ints...>
     269      : __conditional_t<(_Val <= __gnu_cxx::__int_traits<_IntType>::__max),
     270  		      integral_constant<_IntType, (_IntType)_Val>,
     271  		      _Select_int_base<_Val, _Ints...>>
     272      { };
     273  
     274    template<unsigned long long _Val>
     275      struct _Select_int_base<_Val>
     276      { };
     277  
     278    template<char... _Digs>
     279      using _Select_int = typename _Select_int_base<
     280  	__parse_int::_Parse_int<_Digs...>::value,
     281  	unsigned char,
     282  	unsigned short,
     283  	unsigned int,
     284  	unsigned long,
     285  	unsigned long long
     286        >::type;
     287  
     288  } // namespace __select_int
     289  
     290  _GLIBCXX_END_NAMESPACE_VERSION
     291  } // namespace std
     292  
     293  #endif // C++14
     294  
     295  #endif // _GLIBCXX_PARSE_NUMBERS_H