4 #ifndef LEXY_DSL_INTEGER_HPP_INCLUDED
5 #define LEXY_DSL_INTEGER_HPP_INCLUDED
17 template <
typename Integer>
25 std::size_t result = 0;
28 value = Integer(value / Integer(radix));
41 static constexpr
auto _max = [] {
42 if constexpr (std::is_same_v<T, char>)
44 else if constexpr (std::is_same_v<T, signed char>)
46 else if constexpr (std::is_same_v<T, unsigned char>)
48 else if constexpr (std::is_same_v<T, wchar_t>)
51 else if constexpr (std::is_same_v<T, char8_t>)
54 else if constexpr (std::is_same_v<T, char16_t>)
55 return UINT_LEAST16_MAX;
56 else if constexpr (std::is_same_v<T, char32_t>)
57 return UINT_LEAST32_MAX;
58 else if constexpr (std::is_same_v<T, signed short>)
60 else if constexpr (std::is_same_v<T, unsigned short>)
62 else if constexpr (std::is_same_v<T, signed int>)
64 else if constexpr (std::is_same_v<T, unsigned int>)
66 else if constexpr (std::is_same_v<T, signed long>)
68 else if constexpr (std::is_same_v<T, unsigned long>)
70 else if constexpr (std::is_same_v<T, signed long long>)
72 else if constexpr (std::is_same_v<T, unsigned long long>)
74 #ifdef __SIZEOF_INT128__
75 else if constexpr (std::is_same_v<T, __int128_t>)
76 return __int128_t(~__uint128_t{} >> 1);
77 else if constexpr (std::is_same_v<T, __uint128_t>)
78 return ~__uint128_t{};
81 static_assert(_detail::error<T>,
82 "specialize integer_traits for your custom integer types");
90 result = T(result * T(Radix) + T(
digit));
96 constexpr
auto can_use_unsigned = [] {
97 if constexpr (
sizeof(T) >=
sizeof(
unsigned))
103 auto worst_case =
static_cast<unsigned>(
_max);
110 if constexpr (can_use_unsigned)
113 auto value =
static_cast<unsigned>(result) * Radix +
digit;
116 if (value >
static_cast<unsigned>(
_max))
120 result =
static_cast<T
>(value);
127 constexpr
auto max_per_radix = T(
_max / Radix);
128 if (result > max_per_radix)
130 result = T(result * Radix);
135 result = T(result + T(
digit));
153 static constexpr void add_digit_unchecked(type& result, unsigned digit)
155 std::uint_least32_t value = result.value();
156 integer_traits<std::uint_least32_t>::add_digit_unchecked<Radix>(value, digit);
157 result = code_point(value);
160 static constexpr bool add_digit_checked(type& result, unsigned digit)
162 std::uint_least32_t value = result.value();
163 if (!integer_traits<std::uint_least32_t>::add_digit_checked<Radix>(value, digit))
165 result = code_point(value);
166 return result.is_valid();
170 template <typename T>
173 template <typename T>
174 struct integer_traits<unbounded<T>>
176 using type = typename integer_traits<T>::type;
177 static constexpr auto is_bounded = false;
180 static constexpr void add_digit_unchecked(type& result, unsigned digit)
182 integer_traits<T>::template add_digit_unchecked<Radix>(result, digit);
186 template <typename T, T Max>
189 template <typename T, T Max>
190 struct integer_traits<bounded<T, Max>>
192 using type = typename integer_traits<T>::type;
193 static constexpr auto is_bounded = true;
196 static constexpr std::size_t max_digit_count = _digit_count(Radix, Max);
199 static constexpr void add_digit_unchecked(type& result, unsigned digit)
201 integer_traits<T>::template add_digit_unchecked<Radix>(result, digit);
204 static constexpr bool add_digit_checked(type& result, unsigned digit)
206 return integer_traits<T>::template add_digit_checked<Radix>(result, digit) && result <= Max;
213 struct integer_overflow
215 static LEXY_CONSTEVAL auto name()
217 return "integer overflow";
224 template <typename T>
225 constexpr bool _is_bounded = lexy::integer_traits<T>::is_bounded;
227 template <typename T, std::size_t N, int Radix>
228 constexpr bool _ndigits_can_overflow()
230 using traits = lexy::integer_traits<T>;
231 auto max_digit_count = traits::template max_digit_count<Radix>;
232 // We don't know whether the maximal value is a power of Radix,
238 template <
typename T,
typename Base>
244 static constexpr
auto radix = Base::digit_radix;
252 template <
typename Iterator>
260 auto digit = Base::digit_value(*cur++);
261 if (
digit >= Base::digit_radix)
265 traits::template add_digit_unchecked<radix>(value,
digit);
273 template <
typename T,
typename Base,
bool AssumeOnlyDigits>
279 static constexpr
auto radix = Base::digit_radix;
280 static constexpr
auto max_digit_count = traits::template max_digit_count<radix>;
281 static_assert(max_digit_count > 1,
"integer must be able to store all possible digit values");
289 template <
typename Iterator>
295 auto first_digit = 0u;
301 first_digit = Base::digit_value(*cur++);
302 if (first_digit != 0 && first_digit < radix)
311 for (std::size_t digit_count = 1; digit_count < max_digit_count; ++digit_count)
318 return {value,
false};
320 digit = Base::digit_value(*cur++);
322 }
while (AssumeOnlyDigits ?
false :
digit >= Base::digit_radix);
326 if (digit_count == max_digit_count - 1)
329 if (!traits::template add_digit_checked<radix>(value,
digit))
330 return {value,
true};
335 traits::template add_digit_unchecked<radix>(value,
digit);
341 return {value, cur !=
end};
344 template <
typename T,
typename Base,
bool AssumeOnlyDigits>
346 = std::conditional_t<_is_bounded<T>, _bounded_integer_parser<T, Base, AssumeOnlyDigits>,
349 template <
typename T,
typename Digits>
351 template <
typename T,
typename Base>
356 template <
typename T,
typename Base>
361 template <
typename T,
typename Base,
typename Sep>
366 template <
typename T,
typename Base,
typename Sep>
371 template <
typename T, std::
size_t N,
typename Base>
374 using value_type = std::conditional_t<_ndigits_can_overflow<T, N, Base::digit_radix>(), T,
378 template <
typename T, std::
size_t N,
typename Base,
typename Sep>
381 using value_type = std::conditional_t<_ndigits_can_overflow<T, N, Base::digit_radix>(), T,
386 template <
typename T,
typename Digits>
389 template <
typename Token,
typename IntParser,
typename Tag>
392 template <
typename NextParser>
395 template <
typename Context,
typename Reader,
typename... Args>
397 typename Reader::iterator
begin,
398 typename Reader::iterator
end, Args&&... args)
414 template <
typename Reader>
417 typename Reader::marker
end;
419 constexpr
auto try_parse(
const void*,
const Reader& reader)
422 auto result = parser.try_parse(reader);
427 template <
typename Context>
431 template <
typename NextParser,
typename Context,
typename... Args>
434 auto begin = reader.position();
443 template <
typename NextParser>
446 template <
typename Context,
typename Reader,
typename... Args>
449 auto begin = reader.position();
453 parser.end.position());
454 reader.reset(parser.end);
458 parser.report_error(context, reader);
459 reader.reset(parser.end);
466 auto recovery_end = reader.position();
467 if (
begin == recovery_end)
482 auto end = reader.position();
489 template <
typename T,
typename Base>
491 _integer_parser_for<T, _digits<lexy::_detail::type_or<Base, decimal>>>, void>
493 template <
typename Digits>
496 static_assert(lexy::is_token_rule<Digits>);
497 if constexpr (std::is_void_v<Base>)
512 template <
typename T,
typename Base =
void>
523 return "invalid code point";
531 template <std::
size_t N,
typename Base = hex>
533 using type = std::conditional_t<_ndigits_can_overflow<lexy::code_point, N, Base::digit_radix>(),
547 return "invalid code unit";
555 template <
typename Encoding, std::
size_t N,
typename Base = hex>
558 using type = std::conditional_t<_ndigits_can_overflow<char_type, N, Base::digit_radix>(),
565 #endif // LEXY_DSL_INTEGER_HPP_INCLUDED