Update of /cvsroot/boost/boost/boost/spirit/core/primitives/impl
In directory 
sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv17307/boost/spirit/core/primitives/impl

Modified Files:
        numerics.ipp 
Log Message:
Fixed an integer overflow bug preventing to fail parsing on certain large 
integers.

Index: numerics.ipp
===================================================================
RCS file: /cvsroot/boost/boost/boost/spirit/core/primitives/impl/numerics.ipp,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- numerics.ipp        28 Nov 2006 00:56:33 -0000      1.12
+++ numerics.ipp        4 Jul 2007 18:10:23 -0000       1.13
@@ -11,6 +11,7 @@
 #define BOOST_SPIRIT_NUMERICS_IPP
 
 #include <cmath>
+#include <limits>
 
 #if defined(BOOST_NO_STDC_NAMESPACE)
 #  define BOOST_SPIRIT_IMPL_STD_NS
@@ -50,14 +51,11 @@
         //
         //  Traits class for radix specific number conversion
         //
-        //      Test the validity of a single character:
-        //
-        //          template<typename CharT> static bool is_valid(CharT ch);
-        //
-        //      Convert a digit from character representation to binary
-        //      representation:
+        //      Convert a digit from character representation, ch, to binary
+        //      representation, returned in val. 
+        //      Returns whether the conversion was successful.
         //
-        //          template<typename CharT> static int digit(CharT ch);
+        //        template<typename CharT> static bool digit(CharT ch, T& val);
         //
         ///////////////////////////////////////////////////////////////////////
         template<const int Radix>
@@ -67,69 +65,55 @@
         template<>
         struct radix_traits<2>
         {
-            template<typename CharT>
-            static bool is_valid(CharT ch)
+            template<typename CharT, typename T>
+            static bool digit(CharT ch, T& val)
             {
+                val = ch - '0'; 
                 return ('0' == ch || '1' == ch);
             }
-
-            template<typename CharT>
-            static int digit(CharT ch)
-            {
-                return ch - '0';
-            }
         };
 
         ////////////////////////////////// Octal
         template<>
         struct radix_traits<8>
         {
-            template<typename CharT>
-            static bool is_valid(CharT ch)
+            template<typename CharT, typename T>
+            static bool digit(CharT ch, T& val)
             {
+                val = ch - '0';
                 return ('0' <= ch && ch <= '7');
             }
-
-            template<typename CharT>
-            static int digit(CharT ch)
-            {
-                return ch - '0';
-            }
         };
 
         ////////////////////////////////// Decimal
         template<>
         struct radix_traits<10>
         {
-            template<typename CharT>
-            static bool is_valid(CharT ch)
+            template<typename CharT, typename T>
+            static bool digit(CharT ch, T& val)
             {
+                val = ch - '0';
                 return impl::isdigit_(ch);
             }
-
-            template<typename CharT>
-            static int digit(CharT ch)
-            {
-                return ch - '0';
-            }
         };
 
         ////////////////////////////////// Hexadecimal
         template<>
         struct radix_traits<16>
         {
-            template<typename CharT>
-            static bool is_valid(CharT ch)
+            template<typename CharT, typename T>
+            static bool digit(CharT ch, T& val)
             {
-                return impl::isxdigit_(ch);
-            }
+                if (radix_traits<10>::digit(ch, val))
+                    return true;
 
-            template<typename CharT>
-            static int digit(CharT ch)
-            {
-                if (impl::isdigit_(ch))
-                    return ch - '0';
-                return impl::tolower_(ch) - 'a' + 10;
+                CharT lc = impl::tolower_(ch);
+                if ('a' <= lc && lc <= 'f')
+                {
+                    val = lc - 'a' + 10;
+                    return true;
+                }
+                return false;
             }
         };
 
@@ -161,140 +145,74 @@
         //
         //      NOTE:
         //              Returns a non-match, if the number to parse
-        //              overflows (or underflows) the used integral type.
-        //              Overflow (or underflow) is detected when an
-        //              operation wraps a value from its maximum to its
-        //              minimum (or vice-versa). For example, overflow
-        //              occurs when the result of the expression n * x is
-        //              less than n (assuming n is positive and x is
-        //              greater than 1).
+        //              overflows (or underflows) the used type.
         //
         //      BEWARE:
         //              the parameters 'n' and 'count' should be properly
         //              initialized before calling this function.
         //
         ///////////////////////////////////////////////////////////////////////
-        template <int Radix>
+        template <typename T, int Radix>
         struct positive_accumulate
         {
             //  Use this accumulator if number is positive
-
-            template <typename T>
-            static bool check(T const& n, T const& prev)
-            {
-                return n < prev;
-            }
-
-            template <typename T, typename CharT>
-            static void add(T& n, CharT ch)
+            static bool add(T& n, T digit)
             {
-                n += radix_traits<Radix>::digit(ch);
+                static T const max = (std::numeric_limits<T>::max)();
+                static T const max_div_radix = max/Radix;
+                
+                if (n > max_div_radix)
+                    return false;
+                n *= Radix;
+                
+                if (n > max - digit)
+                    return false;
+                n += digit;
+                
+                return true;
             }
         };
-
-        template <int Radix>
+        
+        template <typename T, int Radix>
         struct negative_accumulate
         {
             //  Use this accumulator if number is negative
-
-            template <typename T>
-            static bool check(T const& n, T const& prev)
-            {
-                return n > prev;
-            }
-
-            template <typename T, typename CharT>
-            static void add(T& n, CharT ch)
-            {
-                n -= radix_traits<Radix>::digit(ch);
-            }
-        };
-
-        template <int Radix, typename Accumulate>
-        struct extract_int_base
-        {
-            //  Common code for extract_int specializations
-            template <typename ScannerT, typename T>
-            static bool
-            f(ScannerT& scan, T& n)
+            static bool add(T& n, T digit)
             {
-                T prev = n;
+                typedef std::numeric_limits<T> num_limits;
+                static T const min = 
+                    (!num_limits::is_integer && num_limits::is_signed && 
num_limits::has_denorm) ?
+                    -(num_limits::max)() : (num_limits::min)();
+                static T const min_div_radix = min/Radix;
+            
+                if (n < min_div_radix)
+                    return false;
                 n *= Radix;
-                if (Accumulate::check(n, prev))
-                    return false;   //  over/underflow!
-                prev = n;
-                Accumulate::add(n, *scan);
-                if (Accumulate::check(n, prev))
-                    return false;   //  over/underflow!
+                
+                if (n < min + digit)
+                    return false;
+                n -= digit;
+
                 return true;
             }
         };
 
-        template <bool Bounded>
-        struct extract_int_
-        {
-            template <
-                int Radix,
-                unsigned MinDigits,
-                int MaxDigits,
-                typename Accumulate
-            >
-            struct apply
-            {
-                typedef extract_int_base<Radix, Accumulate> base;
-                typedef radix_traits<Radix> check;
-
-                template <typename ScannerT, typename T>
-                static bool
-                f(ScannerT& scan, T& n, std::size_t& count)
-                {
-                    std::size_t i = 0;
-                    for (; (i < MaxDigits) && !scan.at_end()
-                        && check::is_valid(*scan);
-                        ++i, ++scan, ++count)
-                    {
-                        if (!base::f(scan, n))
-                            return false;   //  over/underflow!
-                    }
-                    return i >= MinDigits;
-                }
-            };
-        };
-
+        template <int MaxDigits> 
+        inline bool allow_more_digits(std::size_t i) 
+        { 
+            return i < MaxDigits; 
+        }
+        
         template <>
-        struct extract_int_<false>
+        inline bool allow_more_digits<-1>(std::size_t)
         {
-            template <
-                int Radix,
-                unsigned MinDigits,
-                int MaxDigits,
-                typename Accumulate
-            >
-            struct apply
-            {
-                typedef extract_int_base<Radix, Accumulate> base;
-                typedef radix_traits<Radix> check;
-
-                template <typename ScannerT, typename T>
-                static bool
-                f(ScannerT& scan, T& n, std::size_t& count)
-                {
-                    std::size_t i = 0;
-                    for (; !scan.at_end() && check::is_valid(*scan);
-                        ++i, ++scan, ++count)
-                    {
-                        if (!base::f(scan, n))
-                            return false;   //  over/underflow!
-                    }
-                    return i >= MinDigits;
-                }
-            };
-        };
-
+            return true;
+        }
+        
         //////////////////////////////////
         template <
             int Radix, unsigned MinDigits, int MaxDigits,
-            typename Accumulate = positive_accumulate<Radix>
+            typename Accumulate
         >
         struct extract_int
         {
@@ -302,9 +220,16 @@
             static bool
             f(ScannerT& scan, T& n, std::size_t& count)
             {
-                typedef typename extract_int_<(MaxDigits >= 0)>::template
-                    apply<Radix, MinDigits, MaxDigits, Accumulate> extractor;
-                return extractor::f(scan, n, count);
+                std::size_t i = 0;
+                T digit;
+                while( allow_more_digits<MaxDigits>(i) && !scan.at_end() &&
+                    radix_traits<Radix>::digit(*scan, digit) )
+                {
+                    if (!Accumulate::add(n, digit))
+                        return false; // Overflow
+                    ++i, ++scan, ++count;
+                }
+                return i >= MinDigits;
             }
         };
 
@@ -339,8 +264,8 @@
                     T n = 0;
                     std::size_t count = 0;
                     typename ScannerT::iterator_t save = scan.first;
-                    if (extract_int<Radix, MinDigits, MaxDigits>::
-                        f(scan, n, count))
+                    if (extract_int<Radix, MinDigits, MaxDigits, 
+                        positive_accumulate<T, Radix> >::f(scan, n, count))
                     {
                         return scan.create_match(count, n, save, scan.first);
                     }
@@ -377,9 +302,9 @@
             parse(ScannerT const& scan) const
             {
                 typedef extract_int<Radix, MinDigits, MaxDigits,
-                    negative_accumulate<Radix> > extract_int_neg_t;
-                typedef extract_int<Radix, MinDigits, MaxDigits>
-                    extract_int_pos_t;
+                    negative_accumulate<T, Radix> > extract_int_neg_t;
+                typedef extract_int<Radix, MinDigits, MaxDigits, 
+                    positive_accumulate<T, Radix> > extract_int_pos_t;
 
                 if (!scan.at_end())
                 {


-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Boost-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/boost-cvs

Reply via email to