]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/boost/spirit/home/qi/numeric/detail/real_impl.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / spirit / home / qi / numeric / detail / real_impl.hpp
index c8d20876fa7dd66687309d4e1e67901cd09471bd..7ae9f0b10d2b9b32150cfce5619aaad2bc4f4786 100644 (file)
@@ -1,5 +1,5 @@
 /*=============================================================================
-    Copyright (c) 2001-2011 Joel de Guzman
+    Copyright (c) 2001-2019 Joel de Guzman
     Copyright (c) 2001-2011 Hartmut Kaiser
     http://spirit.sourceforge.net/
 
@@ -65,11 +65,11 @@ namespace boost { namespace spirit { namespace traits
     {
         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);
         }
@@ -77,7 +77,7 @@ namespace boost { namespace spirit { namespace traits
         {
             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);
 
@@ -150,20 +150,6 @@ namespace boost { namespace spirit { namespace traits
         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> {};
 
@@ -178,9 +164,33 @@ namespace boost { namespace spirit { namespace traits
 
 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,
@@ -199,6 +209,7 @@ namespace boost { namespace spirit { namespace qi  { namespace detail
 
             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.
@@ -221,6 +232,12 @@ namespace boost { namespace spirit { namespace qi  { namespace detail
                     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;
@@ -232,7 +249,12 @@ namespace boost { namespace spirit { namespace qi  { namespace detail
                 // 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);
                 }
@@ -277,8 +299,8 @@ namespace boost { namespace spirit { namespace qi  { namespace detail
                 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
@@ -297,25 +319,17 @@ namespace boost { namespace spirit { namespace qi  { namespace detail
                 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