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 |