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-2014 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 _PARSE_NUMBERS_H
31 #define _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 > 201103L
38 
39 namespace std _GLIBCXX_VISIBILITY(default)
40 {
41 _GLIBCXX_BEGIN_NAMESPACE_VERSION
42 
43 namespace __parse_int {
44 
45  template<unsigned _Base, char _Dig>
46  struct _Digit;
47 
48  template<unsigned _Base>
49  struct _Digit<_Base, '0'>
50  {
51  static constexpr bool valid{true};
52  static constexpr unsigned value{0};
53  };
54 
55  template<unsigned _Base>
56  struct _Digit<_Base, '1'>
57  {
58  static constexpr bool valid{true};
59  static constexpr unsigned value{1};
60  };
61 
62  template<unsigned _Base>
63  struct _Digit<_Base, '2'>
64  {
65  static_assert(_Base > 2, "invalid digit");
66  static constexpr bool valid{true};
67  static constexpr unsigned value{2};
68  };
69 
70  template<unsigned _Base>
71  struct _Digit<_Base, '3'>
72  {
73  static_assert(_Base > 3, "invalid digit");
74  static constexpr bool valid{true};
75  static constexpr unsigned value{3};
76  };
77 
78  template<unsigned _Base>
79  struct _Digit<_Base, '4'>
80  {
81  static_assert(_Base > 4, "invalid digit");
82  static constexpr bool valid{true};
83  static constexpr unsigned value{4};
84  };
85 
86  template<unsigned _Base>
87  struct _Digit<_Base, '5'>
88  {
89  static_assert(_Base > 5, "invalid digit");
90  static constexpr bool valid{true};
91  static constexpr unsigned value{5};
92  };
93 
94  template<unsigned _Base>
95  struct _Digit<_Base, '6'>
96  {
97  static_assert(_Base > 6, "invalid digit");
98  static constexpr bool valid{true};
99  static constexpr unsigned value{6};
100  };
101 
102  template<unsigned _Base>
103  struct _Digit<_Base, '7'>
104  {
105  static_assert(_Base > 7, "invalid digit");
106  static constexpr bool valid{true};
107  static constexpr unsigned value{7};
108  };
109 
110  template<unsigned _Base>
111  struct _Digit<_Base, '8'>
112  {
113  static_assert(_Base > 8, "invalid digit");
114  static constexpr bool valid{true};
115  static constexpr unsigned value{8};
116  };
117 
118  template<unsigned _Base>
119  struct _Digit<_Base, '9'>
120  {
121  static_assert(_Base > 9, "invalid digit");
122  static constexpr bool valid{true};
123  static constexpr unsigned value{9};
124  };
125 
126  template<unsigned _Base>
127  struct _Digit<_Base, 'a'>
128  {
129  static_assert(_Base > 0xa, "invalid digit");
130  static constexpr bool valid{true};
131  static constexpr unsigned value{0xa};
132  };
133 
134  template<unsigned _Base>
135  struct _Digit<_Base, 'A'>
136  {
137  static_assert(_Base > 0xa, "invalid digit");
138  static constexpr bool valid{true};
139  static constexpr unsigned value{0xa};
140  };
141 
142  template<unsigned _Base>
143  struct _Digit<_Base, 'b'>
144  {
145  static_assert(_Base > 0xb, "invalid digit");
146  static constexpr bool valid{true};
147  static constexpr unsigned value{0xb};
148  };
149 
150  template<unsigned _Base>
151  struct _Digit<_Base, 'B'>
152  {
153  static_assert(_Base > 0xb, "invalid digit");
154  static constexpr bool valid{true};
155  static constexpr unsigned value{0xb};
156  };
157 
158  template<unsigned _Base>
159  struct _Digit<_Base, 'c'>
160  {
161  static_assert(_Base > 0xc, "invalid digit");
162  static constexpr bool valid{true};
163  static constexpr unsigned value{0xc};
164  };
165 
166  template<unsigned _Base>
167  struct _Digit<_Base, 'C'>
168  {
169  static_assert(_Base > 0xc, "invalid digit");
170  static constexpr bool valid{true};
171  static constexpr unsigned value{0xc};
172  };
173 
174  template<unsigned _Base>
175  struct _Digit<_Base, 'd'>
176  {
177  static_assert(_Base > 0xd, "invalid digit");
178  static constexpr bool valid{true};
179  static constexpr unsigned value{0xd};
180  };
181 
182  template<unsigned _Base>
183  struct _Digit<_Base, 'D'>
184  {
185  static_assert(_Base > 0xd, "invalid digit");
186  static constexpr bool valid{true};
187  static constexpr unsigned value{0xd};
188  };
189 
190  template<unsigned _Base>
191  struct _Digit<_Base, 'e'>
192  {
193  static_assert(_Base > 0xe, "invalid digit");
194  static constexpr bool valid{true};
195  static constexpr unsigned value{0xe};
196  };
197 
198  template<unsigned _Base>
199  struct _Digit<_Base, 'E'>
200  {
201  static_assert(_Base > 0xe, "invalid digit");
202  static constexpr bool valid{true};
203  static constexpr unsigned value{0xe};
204  };
205 
206  template<unsigned _Base>
207  struct _Digit<_Base, 'f'>
208  {
209  static_assert(_Base > 0xf, "invalid digit");
210  static constexpr bool valid{true};
211  static constexpr unsigned value{0xf};
212  };
213 
214  template<unsigned _Base>
215  struct _Digit<_Base, 'F'>
216  {
217  static_assert(_Base > 0xf, "invalid digit");
218  static constexpr bool valid{true};
219  static constexpr unsigned value{0xf};
220  };
221 
222  // Digit separator
223  template<unsigned _Base>
224  struct _Digit<_Base, '\''>
225  {
226  static constexpr bool valid{false};
227  static constexpr unsigned value{0};
228  };
229 
230 
231 //------------------------------------------------------------------------------
232 
233  template<unsigned _Base, char _Dig, char... _Digs>
234  struct _Digits_help
235  {
236  static constexpr unsigned
237  value{_Digit<_Base, _Dig>::valid ?
238  1U + _Digits_help<_Base, _Digs...>::value :
239  _Digits_help<_Base, _Digs...>::value};
240  };
241 
242  template<unsigned _Base, char _Dig>
243  struct _Digits_help<_Base, _Dig>
244  {
245  static constexpr unsigned value{_Digit<_Base, _Dig>::valid ? 1U : 0U};
246  };
247 
248  template<unsigned _Base, char... _Digs>
249  struct _Digits
250  {
251  static constexpr unsigned value{_Digits_help<_Base, _Digs...>::value};
252  };
253 
254  template<unsigned _Base>
255  struct _Digits<_Base>
256  {
257  static constexpr unsigned value{0U};
258  };
259 
260 //------------------------------------------------------------------------------
261 
262  template<unsigned _Base, char _Dig, char... _Digs>
263  struct _Power_help
264  {
265  static constexpr unsigned
266  value{_Digit<_Base, _Dig>::valid ?
267  _Base * _Power_help<_Base, _Digs...>::value :
268  _Power_help<_Base, _Digs...>::value};
269  };
270 
271  template<unsigned _Base, char _Dig>
272  struct _Power_help<_Base, _Dig>
273  {
274  static constexpr unsigned value{_Digit<_Base, _Dig>::valid ? 1U : 0U};
275  };
276 
277  template<unsigned _Base, char... _Digs>
278  struct _Power
279  {
280  static constexpr unsigned value{_Power_help<_Base, _Digs...>::value};
281  };
282 
283  template<unsigned _Base>
284  struct _Power<_Base>
285  {
286  static constexpr unsigned value{0U};
287  };
288 
289 //------------------------------------------------------------------------------
290 
291  template<unsigned _Base, unsigned _Pow, char _Dig, char... _Digs>
292  struct _Number_help
293  {
294  static constexpr unsigned
295  value{_Digit<_Base, _Dig>::valid ?
296  _Pow * _Digit<_Base, _Dig>::value
297  + _Number_help<_Base, _Pow / _Base, _Digs...>::value :
298  _Number_help<_Base, _Pow, _Digs...>::value};
299  };
300 
301  template<unsigned _Base, unsigned _Pow, char _Dig>
302  struct _Number_help<_Base, _Pow, _Dig>
303  {
304  //static_assert(_Pow == 1U, "power should be one");
305  static constexpr unsigned
306  value{_Digit<_Base, _Dig>::valid ? _Digit<_Base, _Dig>::value : 0U};
307  };
308 
309  template<unsigned _Base, char... _Digs>
310  struct _Number
311  {
312  static constexpr unsigned
313  value{_Number_help<_Base, _Power<_Base, _Digs...>::value,
314  _Digs...>::value};
315  };
316 
317  template<unsigned _Base>
318  struct _Number<_Base>
319  {
320  static constexpr unsigned value{0U};
321  };
322 
323 //------------------------------------------------------------------------------
324 // This _Parse_int is the same 'level' as the old _Base_dispatch.
325 
326  template<char... _Digs>
327  struct _Parse_int;
328 
329  template<char... _Digs>
330  struct _Parse_int<'0', 'b', _Digs...>
331  {
332  static constexpr unsigned long long
333  value{_Number<2U, _Digs...>::value};
334  };
335 
336  template<char... _Digs>
337  struct _Parse_int<'0', 'B', _Digs...>
338  {
339  static constexpr unsigned long long
340  value{_Number<2U, _Digs...>::value};
341  };
342 
343  template<char... _Digs>
344  struct _Parse_int<'0', 'x', _Digs...>
345  {
346  static constexpr unsigned long long
347  value{_Number<16U, _Digs...>::value};
348  };
349 
350  template<char... _Digs>
351  struct _Parse_int<'0', 'X', _Digs...>
352  {
353  static constexpr unsigned long long
354  value{_Number<16U, _Digs...>::value};
355  };
356 
357  template<char... _Digs>
358  struct _Parse_int<'0', _Digs...>
359  {
360  static constexpr unsigned long long
361  value{_Number<8U, _Digs...>::value};
362  };
363 
364  template<char... _Digs>
365  struct _Parse_int
366  {
367  static constexpr unsigned long long
368  value{_Number<10U, _Digs...>::value};
369  };
370 
371 } // namespace __parse_int
372 
373 
374 namespace __select_int {
375 
376  template<unsigned long long _Val, typename... _Ints>
377  struct _Select_int_base;
378 
379  template<unsigned long long _Val, typename _IntType, typename... _Ints>
380  struct _Select_int_base<_Val, _IntType, _Ints...>
381  : integral_constant
382  <
383  typename conditional
384  <
385  _Val <= static_cast<unsigned long long>
386  (std::numeric_limits<_IntType>::max()),
387  _IntType,
388  typename _Select_int_base<_Val, _Ints...>::value_type
389  >::type,
390  _Val
391  >
392  { };
393 
394  template<unsigned long long _Val>
395  struct _Select_int_base<_Val> : integral_constant<unsigned long long, _Val>
396  { };
397 
398  template<char... _Digs>
399  struct _Select_int
400  : _Select_int_base<
401  __parse_int::_Parse_int<_Digs...>::value,
402  unsigned char,
403  unsigned short,
404  unsigned int,
405  unsigned long,
406  unsigned long long
407  >
408  { };
409 
410 } // namespace __select_int
411 
412 _GLIBCXX_END_NAMESPACE_VERSION
413 } // namespace std
414 
415 #endif // __cplusplus > 201103L
416 
417 #endif // _PARSE_NUMBERS_H