You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

295 lines
7.8KB

  1. // Components for compile-time parsing of numbers -*- C++ -*-
  2. // Copyright (C) 2013-2020 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 <ext/numeric_traits.h>
  30. namespace std _GLIBCXX_VISIBILITY(default)
  31. {
  32. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  33. namespace __parse_int
  34. {
  35. template<unsigned _Base, char _Dig>
  36. struct _Digit;
  37. template<unsigned _Base>
  38. struct _Digit<_Base, '0'> : integral_constant<unsigned, 0>
  39. {
  40. using __valid = true_type;
  41. };
  42. template<unsigned _Base>
  43. struct _Digit<_Base, '1'> : integral_constant<unsigned, 1>
  44. {
  45. using __valid = true_type;
  46. };
  47. template<unsigned _Base, unsigned _Val>
  48. struct _Digit_impl : integral_constant<unsigned, _Val>
  49. {
  50. static_assert(_Base > _Val, "invalid digit");
  51. using __valid = true_type;
  52. };
  53. template<unsigned _Base>
  54. struct _Digit<_Base, '2'> : _Digit_impl<_Base, 2>
  55. { };
  56. template<unsigned _Base>
  57. struct _Digit<_Base, '3'> : _Digit_impl<_Base, 3>
  58. { };
  59. template<unsigned _Base>
  60. struct _Digit<_Base, '4'> : _Digit_impl<_Base, 4>
  61. { };
  62. template<unsigned _Base>
  63. struct _Digit<_Base, '5'> : _Digit_impl<_Base, 5>
  64. { };
  65. template<unsigned _Base>
  66. struct _Digit<_Base, '6'> : _Digit_impl<_Base, 6>
  67. { };
  68. template<unsigned _Base>
  69. struct _Digit<_Base, '7'> : _Digit_impl<_Base, 7>
  70. { };
  71. template<unsigned _Base>
  72. struct _Digit<_Base, '8'> : _Digit_impl<_Base, 8>
  73. { };
  74. template<unsigned _Base>
  75. struct _Digit<_Base, '9'> : _Digit_impl<_Base, 9>
  76. { };
  77. template<unsigned _Base>
  78. struct _Digit<_Base, 'a'> : _Digit_impl<_Base, 0xa>
  79. { };
  80. template<unsigned _Base>
  81. struct _Digit<_Base, 'A'> : _Digit_impl<_Base, 0xa>
  82. { };
  83. template<unsigned _Base>
  84. struct _Digit<_Base, 'b'> : _Digit_impl<_Base, 0xb>
  85. { };
  86. template<unsigned _Base>
  87. struct _Digit<_Base, 'B'> : _Digit_impl<_Base, 0xb>
  88. { };
  89. template<unsigned _Base>
  90. struct _Digit<_Base, 'c'> : _Digit_impl<_Base, 0xc>
  91. { };
  92. template<unsigned _Base>
  93. struct _Digit<_Base, 'C'> : _Digit_impl<_Base, 0xc>
  94. { };
  95. template<unsigned _Base>
  96. struct _Digit<_Base, 'd'> : _Digit_impl<_Base, 0xd>
  97. { };
  98. template<unsigned _Base>
  99. struct _Digit<_Base, 'D'> : _Digit_impl<_Base, 0xd>
  100. { };
  101. template<unsigned _Base>
  102. struct _Digit<_Base, 'e'> : _Digit_impl<_Base, 0xe>
  103. { };
  104. template<unsigned _Base>
  105. struct _Digit<_Base, 'E'> : _Digit_impl<_Base, 0xe>
  106. { };
  107. template<unsigned _Base>
  108. struct _Digit<_Base, 'f'> : _Digit_impl<_Base, 0xf>
  109. { };
  110. template<unsigned _Base>
  111. struct _Digit<_Base, 'F'> : _Digit_impl<_Base, 0xf>
  112. { };
  113. // Digit separator
  114. template<unsigned _Base>
  115. struct _Digit<_Base, '\''> : integral_constant<unsigned, 0>
  116. {
  117. using __valid = false_type;
  118. };
  119. //------------------------------------------------------------------------------
  120. template<unsigned long long _Val>
  121. using __ull_constant = integral_constant<unsigned long long, _Val>;
  122. template<unsigned _Base, char _Dig, char... _Digs>
  123. struct _Power_help
  124. {
  125. using __next = typename _Power_help<_Base, _Digs...>::type;
  126. using __valid_digit = typename _Digit<_Base, _Dig>::__valid;
  127. using type
  128. = __ull_constant<__next::value * (__valid_digit{} ? _Base : 1ULL)>;
  129. };
  130. template<unsigned _Base, char _Dig>
  131. struct _Power_help<_Base, _Dig>
  132. {
  133. using __valid_digit = typename _Digit<_Base, _Dig>::__valid;
  134. using type = __ull_constant<__valid_digit::value>;
  135. };
  136. template<unsigned _Base, char... _Digs>
  137. struct _Power : _Power_help<_Base, _Digs...>::type
  138. { };
  139. template<unsigned _Base>
  140. struct _Power<_Base> : __ull_constant<0>
  141. { };
  142. //------------------------------------------------------------------------------
  143. template<unsigned _Base, unsigned long long _Pow, char _Dig, char... _Digs>
  144. struct _Number_help
  145. {
  146. using __digit = _Digit<_Base, _Dig>;
  147. using __valid_digit = typename __digit::__valid;
  148. using __next = _Number_help<_Base,
  149. __valid_digit::value ? _Pow / _Base : _Pow,
  150. _Digs...>;
  151. using type = __ull_constant<_Pow * __digit::value + __next::type::value>;
  152. static_assert((type::value / _Pow) == __digit::value,
  153. "integer literal does not fit in unsigned long long");
  154. };
  155. // Skip past digit separators:
  156. template<unsigned _Base, unsigned long long _Pow, char _Dig, char..._Digs>
  157. struct _Number_help<_Base, _Pow, '\'', _Dig, _Digs...>
  158. : _Number_help<_Base, _Pow, _Dig, _Digs...>
  159. { };
  160. // Terminating case for recursion:
  161. template<unsigned _Base, char _Dig>
  162. struct _Number_help<_Base, 1ULL, _Dig>
  163. {
  164. using type = __ull_constant<_Digit<_Base, _Dig>::value>;
  165. };
  166. template<unsigned _Base, char... _Digs>
  167. struct _Number
  168. : _Number_help<_Base, _Power<_Base, _Digs...>::value, _Digs...>::type
  169. { };
  170. template<unsigned _Base>
  171. struct _Number<_Base>
  172. : __ull_constant<0>
  173. { };
  174. //------------------------------------------------------------------------------
  175. template<char... _Digs>
  176. struct _Parse_int;
  177. template<char... _Digs>
  178. struct _Parse_int<'0', 'b', _Digs...>
  179. : _Number<2U, _Digs...>::type
  180. { };
  181. template<char... _Digs>
  182. struct _Parse_int<'0', 'B', _Digs...>
  183. : _Number<2U, _Digs...>::type
  184. { };
  185. template<char... _Digs>
  186. struct _Parse_int<'0', 'x', _Digs...>
  187. : _Number<16U, _Digs...>::type
  188. { };
  189. template<char... _Digs>
  190. struct _Parse_int<'0', 'X', _Digs...>
  191. : _Number<16U, _Digs...>::type
  192. { };
  193. template<char... _Digs>
  194. struct _Parse_int<'0', _Digs...>
  195. : _Number<8U, _Digs...>::type
  196. { };
  197. template<char... _Digs>
  198. struct _Parse_int
  199. : _Number<10U, _Digs...>::type
  200. { };
  201. } // namespace __parse_int
  202. namespace __select_int
  203. {
  204. template<unsigned long long _Val, typename... _Ints>
  205. struct _Select_int_base;
  206. template<unsigned long long _Val, typename _IntType, typename... _Ints>
  207. struct _Select_int_base<_Val, _IntType, _Ints...>
  208. : conditional_t<(_Val <= __gnu_cxx::__int_traits<_IntType>::__max),
  209. integral_constant<_IntType, _Val>,
  210. _Select_int_base<_Val, _Ints...>>
  211. { };
  212. template<unsigned long long _Val>
  213. struct _Select_int_base<_Val>
  214. { };
  215. template<char... _Digs>
  216. using _Select_int = typename _Select_int_base<
  217. __parse_int::_Parse_int<_Digs...>::value,
  218. unsigned char,
  219. unsigned short,
  220. unsigned int,
  221. unsigned long,
  222. unsigned long long
  223. >::type;
  224. } // namespace __select_int
  225. _GLIBCXX_END_NAMESPACE_VERSION
  226. } // namespace std
  227. #endif // C++14
  228. #endif // _GLIBCXX_PARSE_NUMBERS_H