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
44namespace std _GLIBCXX_VISIBILITY(default)
45{
46_GLIBCXX_BEGIN_NAMESPACE_VERSION
47
48namespace __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
264namespace __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.