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