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 42namespace std _GLIBCXX_VISIBILITY(default) 43{ 44_GLIBCXX_BEGIN_NAMESPACE_VERSION 45 46namespace __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 262namespace __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 296