/*=============================================================================
- Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2019 Joel de Guzman
Copyright (c) 2001-2011 Hartmut Kaiser
http://spirit.sourceforge.net/
{
if (exp >= 0)
{
- int max_exp = std::numeric_limits<T>::max_exponent10;
+ int const max_exp = std::numeric_limits<T>::max_exponent10;
// return false if exp exceeds the max_exp
// do this check only for primitive types!
- if (is_floating_point<T>() && exp > max_exp)
+ if (is_floating_point<T>() && (exp > max_exp))
return false;
n = acc_n * pow10<T>(exp);
}
{
if (exp < std::numeric_limits<T>::min_exponent10)
{
- int min_exp = std::numeric_limits<T>::min_exponent10;
+ int const min_exp = std::numeric_limits<T>::min_exponent10;
detail::compensate_roundoff(n, acc_n);
n /= pow10<T>(-min_exp);
- // return false if (-exp + min_exp) exceeds the -min_exp
+ // return false if exp still exceeds the min_exp
// do this check only for primitive types!
- if (is_floating_point<T>() && (-exp + min_exp) > -min_exp)
+ exp += -min_exp;
+ if (is_floating_point<T>() && exp < min_exp)
return false;
- n /= pow10<T>(-exp + min_exp);
+ n /= pow10<T>(-exp);
}
else
{
return n;
}
- template <typename T>
- inline bool
- is_equal_to_one(T const& value)
- {
- return value == 1.0;
- }
-
- inline bool
- is_equal_to_one(unused_type)
- {
- // no-op for unused_type
- return false;
- }
-
template <typename T>
struct real_accumulator : mpl::identity<T> {};
namespace boost { namespace spirit { namespace qi { namespace detail
{
+ BOOST_MPL_HAS_XXX_TRAIT_DEF(version)
+
template <typename T, typename RealPolicies>
struct real_impl
{
+ template <typename Iterator>
+ static std::size_t
+ ignore_excess_digits(Iterator& first, Iterator const& last, mpl::false_)
+ {
+ return 0;
+ }
+
+ template <typename Iterator>
+ static std::size_t
+ ignore_excess_digits(Iterator& first, Iterator const& last, mpl::true_)
+ {
+ return RealPolicies::ignore_excess_digits(first, last);
+ }
+
+ template <typename Iterator>
+ static std::size_t
+ ignore_excess_digits(Iterator& first, Iterator const& last)
+ {
+ typedef mpl::bool_<has_version<RealPolicies>::value> has_version;
+ return ignore_excess_digits(first, last, has_version());
+ }
+
template <typename Iterator, typename Attribute>
static bool
parse(Iterator& first, Iterator const& last, Attribute& attr,
typename traits::real_accumulator<T>::type acc_n = 0;
bool got_a_number = p.parse_n(first, last, acc_n);
+ int excess_n = 0;
// If we did not get a number it might be a NaN, Inf or a leading
// dot.
return false;
}
}
+ else
+ {
+ // We got a number and we still see digits. This happens if acc_n (an integer)
+ // exceeds the integer's capacity. Collect the excess digits.
+ excess_n = static_cast<int>(ignore_excess_digits(first, last));
+ }
bool e_hit = false;
Iterator e_pos;
// We got the decimal point. Now we will try to parse
// the fraction if it is there. If not, it defaults
// to zero (0) only if we already got a number.
- if (p.parse_frac_n(first, last, acc_n, frac_digits))
+ if (excess_n != 0)
+ {
+ // We skip the fractions if we already exceeded our digits capacity
+ ignore_excess_digits(first, last);
+ }
+ else if (p.parse_frac_n(first, last, acc_n, frac_digits))
{
+ BOOST_ASSERT(frac_digits >= 0);
}
else if (!got_a_number || !p.allow_trailing_dot)
{
if (p.parse_exp_n(first, last, exp))
{
// Got the exponent value. Scale the number by
- // exp-frac_digits.
- if (!traits::scale(exp, frac_digits, n, acc_n))
+ // exp + excess_n - frac_digits.
+ if (!traits::scale(exp + excess_n, frac_digits, n, acc_n))
return false;
}
else
// by resetting 'first' prior to the exponent prefix (e|E)
first = e_pos;
// Scale the number by -frac_digits.
- traits::scale(-frac_digits, n, acc_n);
+ bool r = traits::scale(-frac_digits, n, acc_n);
+ BOOST_VERIFY(r);
}
}
else if (frac_digits)
{
// No exponent found. Scale the number by -frac_digits.
- traits::scale(-frac_digits, n, acc_n);
+ bool r = traits::scale(-frac_digits, n, acc_n);
+ BOOST_VERIFY(r);
}
- else if (traits::is_equal_to_one(acc_n))
+ else
{
- // There is a chance of having to parse one of the 1.0#...
- // styles some implementations use for representing NaN or Inf.
-
- // Check whether the number to parse is a NaN or Inf
- if (p.parse_nan(first, last, n) ||
- p.parse_inf(first, last, n))
+ if (excess_n)
{
- // If we got a negative sign, negate the number
- traits::assign_to(traits::negate(neg, n), attr);
- return true; // got a NaN or Inf, return immediately
+ if (!traits::scale(excess_n, n, acc_n))
+ return false;
+ }
+ else
+ {
+ n = static_cast<T>(acc_n);
}
-
- n = static_cast<T>(acc_n);
- }
- else
- {
- n = static_cast<T>(acc_n);
}
// If we got a negative sign, negate the number