parse_numbers.h 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. // Components for compile-time parsing of numbers -*- C++ -*-
  2. // Copyright (C) 2013-2022 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file bits/parse_numbers.h
  21. * This is an internal header file, included by other library headers.
  22. * Do not attempt to use it directly. @headername{chrono}
  23. */
  24. #ifndef _GLIBCXX_PARSE_NUMBERS_H
  25. #define _GLIBCXX_PARSE_NUMBERS_H 1
  26. #pragma GCC system_header
  27. // From n3642.pdf except I added binary literals and digit separator '\''.
  28. #if __cplusplus >= 201402L
  29. #include <type_traits>
  30. #include <ext/numeric_traits.h>
  31. namespace std _GLIBCXX_VISIBILITY(default)
  32. {
  33. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  34. namespace __parse_int
  35. {
  36. template<unsigned _Base, char _Dig>
  37. struct _Digit;
  38. template<unsigned _Base>
  39. struct _Digit<_Base, '0'> : integral_constant<unsigned, 0>
  40. {
  41. using __valid = true_type;
  42. };
  43. template<unsigned _Base>
  44. struct _Digit<_Base, '1'> : integral_constant<unsigned, 1>
  45. {
  46. using __valid = true_type;
  47. };
  48. template<unsigned _Base, unsigned _Val>
  49. struct _Digit_impl : integral_constant<unsigned, _Val>
  50. {
  51. static_assert(_Base > _Val, "invalid digit");
  52. using __valid = true_type;
  53. };
  54. template<unsigned _Base>
  55. struct _Digit<_Base, '2'> : _Digit_impl<_Base, 2>
  56. { };
  57. template<unsigned _Base>
  58. struct _Digit<_Base, '3'> : _Digit_impl<_Base, 3>
  59. { };
  60. template<unsigned _Base>
  61. struct _Digit<_Base, '4'> : _Digit_impl<_Base, 4>
  62. { };
  63. template<unsigned _Base>
  64. struct _Digit<_Base, '5'> : _Digit_impl<_Base, 5>
  65. { };
  66. template<unsigned _Base>
  67. struct _Digit<_Base, '6'> : _Digit_impl<_Base, 6>
  68. { };
  69. template<unsigned _Base>
  70. struct _Digit<_Base, '7'> : _Digit_impl<_Base, 7>
  71. { };
  72. template<unsigned _Base>
  73. struct _Digit<_Base, '8'> : _Digit_impl<_Base, 8>
  74. { };
  75. template<unsigned _Base>
  76. struct _Digit<_Base, '9'> : _Digit_impl<_Base, 9>
  77. { };
  78. template<unsigned _Base>
  79. struct _Digit<_Base, 'a'> : _Digit_impl<_Base, 0xa>
  80. { };
  81. template<unsigned _Base>
  82. struct _Digit<_Base, 'A'> : _Digit_impl<_Base, 0xa>
  83. { };
  84. template<unsigned _Base>
  85. struct _Digit<_Base, 'b'> : _Digit_impl<_Base, 0xb>
  86. { };
  87. template<unsigned _Base>
  88. struct _Digit<_Base, 'B'> : _Digit_impl<_Base, 0xb>
  89. { };
  90. template<unsigned _Base>
  91. struct _Digit<_Base, 'c'> : _Digit_impl<_Base, 0xc>
  92. { };
  93. template<unsigned _Base>
  94. struct _Digit<_Base, 'C'> : _Digit_impl<_Base, 0xc>
  95. { };
  96. template<unsigned _Base>
  97. struct _Digit<_Base, 'd'> : _Digit_impl<_Base, 0xd>
  98. { };
  99. template<unsigned _Base>
  100. struct _Digit<_Base, 'D'> : _Digit_impl<_Base, 0xd>
  101. { };
  102. template<unsigned _Base>
  103. struct _Digit<_Base, 'e'> : _Digit_impl<_Base, 0xe>
  104. { };
  105. template<unsigned _Base>
  106. struct _Digit<_Base, 'E'> : _Digit_impl<_Base, 0xe>
  107. { };
  108. template<unsigned _Base>
  109. struct _Digit<_Base, 'f'> : _Digit_impl<_Base, 0xf>
  110. { };
  111. template<unsigned _Base>
  112. struct _Digit<_Base, 'F'> : _Digit_impl<_Base, 0xf>
  113. { };
  114. // Digit separator
  115. template<unsigned _Base>
  116. struct _Digit<_Base, '\''> : integral_constant<unsigned, 0>
  117. {
  118. using __valid = false_type;
  119. };
  120. //------------------------------------------------------------------------------
  121. template<unsigned long long _Val>
  122. using __ull_constant = integral_constant<unsigned long long, _Val>;
  123. template<unsigned _Base, char _Dig, char... _Digs>
  124. struct _Power_help
  125. {
  126. using __next = typename _Power_help<_Base, _Digs...>::type;
  127. using __valid_digit = typename _Digit<_Base, _Dig>::__valid;
  128. using type
  129. = __ull_constant<__next::value * (__valid_digit{} ? _Base : 1ULL)>;
  130. };
  131. template<unsigned _Base, char _Dig>
  132. struct _Power_help<_Base, _Dig>
  133. {
  134. using __valid_digit = typename _Digit<_Base, _Dig>::__valid;
  135. using type = __ull_constant<__valid_digit::value>;
  136. };
  137. template<unsigned _Base, char... _Digs>
  138. struct _Power : _Power_help<_Base, _Digs...>::type
  139. { };
  140. template<unsigned _Base>
  141. struct _Power<_Base> : __ull_constant<0>
  142. { };
  143. //------------------------------------------------------------------------------
  144. template<unsigned _Base, unsigned long long _Pow, char _Dig, char... _Digs>
  145. struct _Number_help
  146. {
  147. using __digit = _Digit<_Base, _Dig>;
  148. using __valid_digit = typename __digit::__valid;
  149. using __next = _Number_help<_Base,
  150. __valid_digit::value ? _Pow / _Base : _Pow,
  151. _Digs...>;
  152. using type = __ull_constant<_Pow * __digit::value + __next::type::value>;
  153. static_assert((type::value / _Pow) == __digit::value,
  154. "integer literal does not fit in unsigned long long");
  155. };
  156. // Skip past digit separators:
  157. template<unsigned _Base, unsigned long long _Pow, char _Dig, char..._Digs>
  158. struct _Number_help<_Base, _Pow, '\'', _Dig, _Digs...>
  159. : _Number_help<_Base, _Pow, _Dig, _Digs...>
  160. { };
  161. // Terminating case for recursion:
  162. template<unsigned _Base, char _Dig>
  163. struct _Number_help<_Base, 1ULL, _Dig>
  164. {
  165. using type = __ull_constant<_Digit<_Base, _Dig>::value>;
  166. };
  167. template<unsigned _Base, char... _Digs>
  168. struct _Number
  169. : _Number_help<_Base, _Power<_Base, _Digs...>::value, _Digs...>::type
  170. { };
  171. template<unsigned _Base>
  172. struct _Number<_Base>
  173. : __ull_constant<0>
  174. { };
  175. //------------------------------------------------------------------------------
  176. template<char... _Digs>
  177. struct _Parse_int;
  178. template<char... _Digs>
  179. struct _Parse_int<'0', 'b', _Digs...>
  180. : _Number<2U, _Digs...>::type
  181. { };
  182. template<char... _Digs>
  183. struct _Parse_int<'0', 'B', _Digs...>
  184. : _Number<2U, _Digs...>::type
  185. { };
  186. template<char... _Digs>
  187. struct _Parse_int<'0', 'x', _Digs...>
  188. : _Number<16U, _Digs...>::type
  189. { };
  190. template<char... _Digs>
  191. struct _Parse_int<'0', 'X', _Digs...>
  192. : _Number<16U, _Digs...>::type
  193. { };
  194. template<char... _Digs>
  195. struct _Parse_int<'0', _Digs...>
  196. : _Number<8U, _Digs...>::type
  197. { };
  198. template<char... _Digs>
  199. struct _Parse_int
  200. : _Number<10U, _Digs...>::type
  201. { };
  202. } // namespace __parse_int
  203. namespace __select_int
  204. {
  205. template<unsigned long long _Val, typename... _Ints>
  206. struct _Select_int_base;
  207. template<unsigned long long _Val, typename _IntType, typename... _Ints>
  208. struct _Select_int_base<_Val, _IntType, _Ints...>
  209. : __conditional_t<(_Val <= __gnu_cxx::__int_traits<_IntType>::__max),
  210. integral_constant<_IntType, (_IntType)_Val>,
  211. _Select_int_base<_Val, _Ints...>>
  212. { };
  213. template<unsigned long long _Val>
  214. struct _Select_int_base<_Val>
  215. { };
  216. template<char... _Digs>
  217. using _Select_int = typename _Select_int_base<
  218. __parse_int::_Parse_int<_Digs...>::value,
  219. unsigned char,
  220. unsigned short,
  221. unsigned int,
  222. unsigned long,
  223. unsigned long long
  224. >::type;
  225. } // namespace __select_int
  226. _GLIBCXX_END_NAMESPACE_VERSION
  227. } // namespace std
  228. #endif // C++14
  229. #endif // _GLIBCXX_PARSE_NUMBERS_H