libstdc++
|
00001 // Components for compile-time parsing of numbers -*- C++ -*- 00002 00003 // Copyright (C) 2013-2014 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 3, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 /** @file bits/parse_numbers.h 00026 * This is an internal header file, included by other library headers. 00027 * Do not attempt to use it directly. @headername{chrono} 00028 */ 00029 00030 #ifndef _PARSE_NUMBERS_H 00031 #define _PARSE_NUMBERS_H 1 00032 00033 #pragma GCC system_header 00034 00035 // From n3642.pdf except I added binary literals and digit separator '\''. 00036 00037 #if __cplusplus > 201103L 00038 00039 namespace std _GLIBCXX_VISIBILITY(default) 00040 { 00041 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00042 00043 namespace __parse_int { 00044 00045 template<unsigned _Base, char _Dig> 00046 struct _Digit; 00047 00048 template<unsigned _Base> 00049 struct _Digit<_Base, '0'> 00050 { 00051 static constexpr bool valid{true}; 00052 static constexpr unsigned value{0}; 00053 }; 00054 00055 template<unsigned _Base> 00056 struct _Digit<_Base, '1'> 00057 { 00058 static constexpr bool valid{true}; 00059 static constexpr unsigned value{1}; 00060 }; 00061 00062 template<unsigned _Base> 00063 struct _Digit<_Base, '2'> 00064 { 00065 static_assert(_Base > 2, "invalid digit"); 00066 static constexpr bool valid{true}; 00067 static constexpr unsigned value{2}; 00068 }; 00069 00070 template<unsigned _Base> 00071 struct _Digit<_Base, '3'> 00072 { 00073 static_assert(_Base > 3, "invalid digit"); 00074 static constexpr bool valid{true}; 00075 static constexpr unsigned value{3}; 00076 }; 00077 00078 template<unsigned _Base> 00079 struct _Digit<_Base, '4'> 00080 { 00081 static_assert(_Base > 4, "invalid digit"); 00082 static constexpr bool valid{true}; 00083 static constexpr unsigned value{4}; 00084 }; 00085 00086 template<unsigned _Base> 00087 struct _Digit<_Base, '5'> 00088 { 00089 static_assert(_Base > 5, "invalid digit"); 00090 static constexpr bool valid{true}; 00091 static constexpr unsigned value{5}; 00092 }; 00093 00094 template<unsigned _Base> 00095 struct _Digit<_Base, '6'> 00096 { 00097 static_assert(_Base > 6, "invalid digit"); 00098 static constexpr bool valid{true}; 00099 static constexpr unsigned value{6}; 00100 }; 00101 00102 template<unsigned _Base> 00103 struct _Digit<_Base, '7'> 00104 { 00105 static_assert(_Base > 7, "invalid digit"); 00106 static constexpr bool valid{true}; 00107 static constexpr unsigned value{7}; 00108 }; 00109 00110 template<unsigned _Base> 00111 struct _Digit<_Base, '8'> 00112 { 00113 static_assert(_Base > 8, "invalid digit"); 00114 static constexpr bool valid{true}; 00115 static constexpr unsigned value{8}; 00116 }; 00117 00118 template<unsigned _Base> 00119 struct _Digit<_Base, '9'> 00120 { 00121 static_assert(_Base > 9, "invalid digit"); 00122 static constexpr bool valid{true}; 00123 static constexpr unsigned value{9}; 00124 }; 00125 00126 template<unsigned _Base> 00127 struct _Digit<_Base, 'a'> 00128 { 00129 static_assert(_Base > 0xa, "invalid digit"); 00130 static constexpr bool valid{true}; 00131 static constexpr unsigned value{0xa}; 00132 }; 00133 00134 template<unsigned _Base> 00135 struct _Digit<_Base, 'A'> 00136 { 00137 static_assert(_Base > 0xa, "invalid digit"); 00138 static constexpr bool valid{true}; 00139 static constexpr unsigned value{0xa}; 00140 }; 00141 00142 template<unsigned _Base> 00143 struct _Digit<_Base, 'b'> 00144 { 00145 static_assert(_Base > 0xb, "invalid digit"); 00146 static constexpr bool valid{true}; 00147 static constexpr unsigned value{0xb}; 00148 }; 00149 00150 template<unsigned _Base> 00151 struct _Digit<_Base, 'B'> 00152 { 00153 static_assert(_Base > 0xb, "invalid digit"); 00154 static constexpr bool valid{true}; 00155 static constexpr unsigned value{0xb}; 00156 }; 00157 00158 template<unsigned _Base> 00159 struct _Digit<_Base, 'c'> 00160 { 00161 static_assert(_Base > 0xc, "invalid digit"); 00162 static constexpr bool valid{true}; 00163 static constexpr unsigned value{0xc}; 00164 }; 00165 00166 template<unsigned _Base> 00167 struct _Digit<_Base, 'C'> 00168 { 00169 static_assert(_Base > 0xc, "invalid digit"); 00170 static constexpr bool valid{true}; 00171 static constexpr unsigned value{0xc}; 00172 }; 00173 00174 template<unsigned _Base> 00175 struct _Digit<_Base, 'd'> 00176 { 00177 static_assert(_Base > 0xd, "invalid digit"); 00178 static constexpr bool valid{true}; 00179 static constexpr unsigned value{0xd}; 00180 }; 00181 00182 template<unsigned _Base> 00183 struct _Digit<_Base, 'D'> 00184 { 00185 static_assert(_Base > 0xd, "invalid digit"); 00186 static constexpr bool valid{true}; 00187 static constexpr unsigned value{0xd}; 00188 }; 00189 00190 template<unsigned _Base> 00191 struct _Digit<_Base, 'e'> 00192 { 00193 static_assert(_Base > 0xe, "invalid digit"); 00194 static constexpr bool valid{true}; 00195 static constexpr unsigned value{0xe}; 00196 }; 00197 00198 template<unsigned _Base> 00199 struct _Digit<_Base, 'E'> 00200 { 00201 static_assert(_Base > 0xe, "invalid digit"); 00202 static constexpr bool valid{true}; 00203 static constexpr unsigned value{0xe}; 00204 }; 00205 00206 template<unsigned _Base> 00207 struct _Digit<_Base, 'f'> 00208 { 00209 static_assert(_Base > 0xf, "invalid digit"); 00210 static constexpr bool valid{true}; 00211 static constexpr unsigned value{0xf}; 00212 }; 00213 00214 template<unsigned _Base> 00215 struct _Digit<_Base, 'F'> 00216 { 00217 static_assert(_Base > 0xf, "invalid digit"); 00218 static constexpr bool valid{true}; 00219 static constexpr unsigned value{0xf}; 00220 }; 00221 00222 // Digit separator 00223 template<unsigned _Base> 00224 struct _Digit<_Base, '\''> 00225 { 00226 static constexpr bool valid{false}; 00227 static constexpr unsigned value{0}; 00228 }; 00229 00230 00231 //------------------------------------------------------------------------------ 00232 00233 template<unsigned _Base, char _Dig, char... _Digs> 00234 struct _Digits_help 00235 { 00236 static constexpr unsigned 00237 value{_Digit<_Base, _Dig>::valid ? 00238 1U + _Digits_help<_Base, _Digs...>::value : 00239 _Digits_help<_Base, _Digs...>::value}; 00240 }; 00241 00242 template<unsigned _Base, char _Dig> 00243 struct _Digits_help<_Base, _Dig> 00244 { 00245 static constexpr unsigned value{_Digit<_Base, _Dig>::valid ? 1U : 0U}; 00246 }; 00247 00248 template<unsigned _Base, char... _Digs> 00249 struct _Digits 00250 { 00251 static constexpr unsigned value{_Digits_help<_Base, _Digs...>::value}; 00252 }; 00253 00254 template<unsigned _Base> 00255 struct _Digits<_Base> 00256 { 00257 static constexpr unsigned value{0U}; 00258 }; 00259 00260 //------------------------------------------------------------------------------ 00261 00262 template<unsigned _Base, char _Dig, char... _Digs> 00263 struct _Power_help 00264 { 00265 static constexpr unsigned 00266 value{_Digit<_Base, _Dig>::valid ? 00267 _Base * _Power_help<_Base, _Digs...>::value : 00268 _Power_help<_Base, _Digs...>::value}; 00269 }; 00270 00271 template<unsigned _Base, char _Dig> 00272 struct _Power_help<_Base, _Dig> 00273 { 00274 static constexpr unsigned value{_Digit<_Base, _Dig>::valid ? 1U : 0U}; 00275 }; 00276 00277 template<unsigned _Base, char... _Digs> 00278 struct _Power 00279 { 00280 static constexpr unsigned value{_Power_help<_Base, _Digs...>::value}; 00281 }; 00282 00283 template<unsigned _Base> 00284 struct _Power<_Base> 00285 { 00286 static constexpr unsigned value{0U}; 00287 }; 00288 00289 //------------------------------------------------------------------------------ 00290 00291 template<unsigned _Base, unsigned _Pow, char _Dig, char... _Digs> 00292 struct _Number_help 00293 { 00294 static constexpr unsigned 00295 value{_Digit<_Base, _Dig>::valid ? 00296 _Pow * _Digit<_Base, _Dig>::value 00297 + _Number_help<_Base, _Pow / _Base, _Digs...>::value : 00298 _Number_help<_Base, _Pow, _Digs...>::value}; 00299 }; 00300 00301 template<unsigned _Base, unsigned _Pow, char _Dig> 00302 struct _Number_help<_Base, _Pow, _Dig> 00303 { 00304 //static_assert(_Pow == 1U, "power should be one"); 00305 static constexpr unsigned 00306 value{_Digit<_Base, _Dig>::valid ? _Digit<_Base, _Dig>::value : 0U}; 00307 }; 00308 00309 template<unsigned _Base, char... _Digs> 00310 struct _Number 00311 { 00312 static constexpr unsigned 00313 value{_Number_help<_Base, _Power<_Base, _Digs...>::value, 00314 _Digs...>::value}; 00315 }; 00316 00317 template<unsigned _Base> 00318 struct _Number<_Base> 00319 { 00320 static constexpr unsigned value{0U}; 00321 }; 00322 00323 //------------------------------------------------------------------------------ 00324 // This _Parse_int is the same 'level' as the old _Base_dispatch. 00325 00326 template<char... _Digs> 00327 struct _Parse_int; 00328 00329 template<char... _Digs> 00330 struct _Parse_int<'0', 'b', _Digs...> 00331 { 00332 static constexpr unsigned long long 00333 value{_Number<2U, _Digs...>::value}; 00334 }; 00335 00336 template<char... _Digs> 00337 struct _Parse_int<'0', 'B', _Digs...> 00338 { 00339 static constexpr unsigned long long 00340 value{_Number<2U, _Digs...>::value}; 00341 }; 00342 00343 template<char... _Digs> 00344 struct _Parse_int<'0', 'x', _Digs...> 00345 { 00346 static constexpr unsigned long long 00347 value{_Number<16U, _Digs...>::value}; 00348 }; 00349 00350 template<char... _Digs> 00351 struct _Parse_int<'0', 'X', _Digs...> 00352 { 00353 static constexpr unsigned long long 00354 value{_Number<16U, _Digs...>::value}; 00355 }; 00356 00357 template<char... _Digs> 00358 struct _Parse_int<'0', _Digs...> 00359 { 00360 static constexpr unsigned long long 00361 value{_Number<8U, _Digs...>::value}; 00362 }; 00363 00364 template<char... _Digs> 00365 struct _Parse_int 00366 { 00367 static constexpr unsigned long long 00368 value{_Number<10U, _Digs...>::value}; 00369 }; 00370 00371 } // namespace __parse_int 00372 00373 00374 namespace __select_int { 00375 00376 template<unsigned long long _Val, typename... _Ints> 00377 struct _Select_int_base; 00378 00379 template<unsigned long long _Val, typename _IntType, typename... _Ints> 00380 struct _Select_int_base<_Val, _IntType, _Ints...> 00381 : integral_constant 00382 < 00383 typename conditional 00384 < 00385 _Val <= static_cast<unsigned long long> 00386 (std::numeric_limits<_IntType>::max()), 00387 _IntType, 00388 typename _Select_int_base<_Val, _Ints...>::value_type 00389 >::type, 00390 _Val 00391 > 00392 { }; 00393 00394 template<unsigned long long _Val> 00395 struct _Select_int_base<_Val> : integral_constant<unsigned long long, _Val> 00396 { }; 00397 00398 template<char... _Digs> 00399 struct _Select_int 00400 : _Select_int_base< 00401 __parse_int::_Parse_int<_Digs...>::value, 00402 unsigned char, 00403 unsigned short, 00404 unsigned int, 00405 unsigned long, 00406 unsigned long long 00407 > 00408 { }; 00409 00410 } // namespace __select_int 00411 00412 _GLIBCXX_END_NAMESPACE_VERSION 00413 } // namespace std 00414 00415 #endif // __cplusplus > 201103L 00416 00417 #endif // _PARSE_NUMBERS_H