// Nickolay Mladenov, for the implementation of operator+=
// Revision History
+// 20 Oct 06 Fix operator bool_type for CW 8.3 (Joaquín M López Muñoz)
+// 18 Oct 06 Use EXPLICIT_TEMPLATE_TYPE helper macros from Boost.Config
+// (Joaquín M López Muñoz)
// 27 Dec 05 Add Boolean conversion operator (Daryle Walker)
// 28 Sep 02 Use _left versions of operators from operators.hpp
// 05 Jul 01 Recode gcd(), avoiding std::swap (Helmut Zeisel)
#include <cstdlib> // for std::abs
#include <boost/call_traits.hpp> // for boost::call_traits
#include <boost/config.hpp> // for BOOST_NO_STDC_NAMESPACE, BOOST_MSVC
+#include <boost/detail/workaround.hpp> // for BOOST_WORKAROUND
namespace boost {
bool operator!() const { return !num; }
// Boolean conversion
+
+#if BOOST_WORKAROUND(__MWERKS__,<=0x3003)
+ // The "ISO C++ Template Parser" option in CW 8.3 chokes on the
+ // following, hence we selectively disable that option for the
+ // offending memfun.
+#pragma parse_mfunc_templ off
+#endif
+
operator bool_type() const { return operator !() ? 0 : &helper::parts; }
+#if BOOST_WORKAROUND(__MWERKS__,<=0x3003)
+#pragma parse_mfunc_templ reset
+#endif
+
// Comparison operators
bool operator< (const rational& r) const;
bool operator== (const rational& r) const;
// Type conversion
template <typename T, typename IntType>
-inline T rational_cast(const rational<IntType>& src)
+inline T rational_cast(
+ const rational<IntType>& src BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(T))
{
return static_cast<T>(src.numerator())/src.denominator();
}
// matching flags in use:
match_flag_type m_match_flags;
// how many states we have examined so far:
- difference_type state_count;
+ boost::uintmax_t state_count;
// max number of states to examine before giving up:
- difference_type max_state_count;
+ boost::uintmax_t max_state_count;
// whether we should ignore case or not:
bool icase;
// set to true when (position == last), indicates that we may have a partial match:
template <class BidiIterator, class Allocator, class traits>
void perl_matcher<BidiIterator, Allocator, traits>::estimate_max_state_count(std::random_access_iterator_tag*)
{
- static const difference_type k = 100000;
- difference_type dist = boost::re_detail::distance(base, last);
- traits_size_type states = static_cast<traits_size_type>(re.size());
+ //
+ // How many states should we allow our machine to visit before giving up?
+ // This is a heuristic: it takes the greater of O(N^2) and O(NS^2)
+ // where N is the length of the string, and S is the number of states
+ // in the machine. It's tempting to up this to O(N^2S) or even O(N^2S^2)
+ // but these take unreasonably amounts of time to bale out in pathological
+ // cases.
+ //
+ // Calculate NS^2 first:
+ //
+ static const boost::uintmax_t k = 100000;
+ boost::uintmax_t dist = boost::re_detail::distance(base, last);
+ if(dist == 0)
+ dist = 1;
+ boost::uintmax_t states = re.size();
+ if(states == 0)
+ states = 1;
states *= states;
- difference_type lim = ((std::numeric_limits<difference_type>::max)() - k) / states;
- if(dist >= lim)
- max_state_count = (std::numeric_limits<difference_type>::max)();
- else
- max_state_count = k + states * dist;
+ if((std::numeric_limits<boost::uintmax_t>::max)() / dist < states)
+ {
+ max_state_count = (std::numeric_limits<boost::uintmax_t>::max)() - 2;
+ return;
+ }
+ states *= dist;
+ if((std::numeric_limits<boost::uintmax_t>::max)() - k < states)
+ {
+ max_state_count = (std::numeric_limits<boost::uintmax_t>::max)() - 2;
+ return;
+ }
+ states += k;
+
+ max_state_count = states;
+
+ //
+ // Now calculate N^2:
+ //
+ states = dist;
+ if((std::numeric_limits<boost::uintmax_t>::max)() / dist < states)
+ {
+ max_state_count = (std::numeric_limits<boost::uintmax_t>::max)() - 2;
+ return;
+ }
+ states *= dist;
+ if((std::numeric_limits<boost::uintmax_t>::max)() - k < states)
+ {
+ max_state_count = (std::numeric_limits<boost::uintmax_t>::max)() - 2;
+ return;
+ }
+ states += k;
+ //
+ // N^2 can be a very large number indeed, to prevent things getting out
+ // of control, cap the max states:
+ //
+ if(states > BOOST_REGEX_MAX_STATE_COUNT)
+ states = BOOST_REGEX_MAX_STATE_COUNT;
+ //
+ // If (the possibly capped) N^2 is larger than our first estimate,
+ // use this instead:
+ //
+ if(states > max_state_count)
+ max_state_count = states;
}
template <class BidiIterator, class Allocator, class traits>