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