parse_numbers.h revision 1.3
1// Components for compile-time parsing of numbers -*- C++ -*- 2 3// Copyright (C) 2013-2017 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, unsigned long long _Pow, char _Dig> 208 struct _Number_help<_Base, _Pow, _Dig> 209 { 210 //static_assert(_Pow == 1U, "power should be one"); 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 <= std::numeric_limits<_IntType>::max()), 270 integral_constant<_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 // __cplusplus > 201103L 294 295#endif // _GLIBCXX_PARSE_NUMBERS_H 296