1 // Components for compile-time parsing of numbers -*- C++ -*- 2 3 // Copyright (C) 2013-2018 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 41 namespace std _GLIBCXX_VISIBILITY(default) 42 { 43 _GLIBCXX_BEGIN_NAMESPACE_VERSION 44 45 namespace __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 261 namespace __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