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