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-2022 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
integral_constant< bool, true > true_type
The type used as a compile-time boolean with true value.
Definition: type_traits:82
integral_constant< bool, false > false_type
The type used as a compile-time boolean with false value.
Definition: type_traits:85
ISO C++ entities toplevel namespace is std.