From 514b4b494f135bbd3761a2dda3d7405c8bda3034 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Tue, 11 Jun 2013 21:12:19 -0700 Subject: [PATCH] Replace the boost range set code with our own --- .../containers/ripple_RangeSet.cpp | 124 +++++++++++++----- .../containers/ripple_RangeSet.h | 81 ++---------- modules/ripple_basics/ripple_basics.h | 1 - .../protocol/ripple_SerializedObject.cpp | 4 +- 4 files changed, 104 insertions(+), 106 deletions(-) diff --git a/modules/ripple_basics/containers/ripple_RangeSet.cpp b/modules/ripple_basics/containers/ripple_RangeSet.cpp index 5db2feda9f..5801510d87 100644 --- a/modules/ripple_basics/containers/ripple_RangeSet.cpp +++ b/modules/ripple_basics/containers/ripple_RangeSet.cpp @@ -6,100 +6,152 @@ inline uint32 max(uint32 x, uint32 y) { return (x > y) ? x : y; } bool RangeSet::hasValue(uint32 v) const { - return mRanges.find(v) != mRanges.end(); + BOOST_FOREACH(const value_type& it, mRanges) + { + if (contains(it, v)) + return true; + } + return false; } uint32 RangeSet::getFirst() const { - const_iterator it = begin(); - if (it == end()) + const_iterator it = mRanges.begin(); + if (it == mRanges.end()) return RangeSetAbsent; - return lower(it); + return it->first; } uint32 RangeSet::getNext(uint32 v) const { - for (const_iterator it = begin(); it != end(); ++it) + BOOST_FOREACH(const value_type& it, mRanges) { - if (upper(it) > v) - return max(v + 1, lower(it)); + if (it.first > v) + return it.first; + if (contains(it, v + 1)) + return v + 1; } return RangeSetAbsent; } uint32 RangeSet::getLast() const { - const_reverse_iterator it = rbegin(); - if (it == rend()) + const_reverse_iterator it = mRanges.rbegin(); + if (it == mRanges.rend()) return RangeSetAbsent; - return upper(it); + return it->second; } uint32 RangeSet::getPrev(uint32 v) const { - for (const_reverse_iterator it = rbegin(); it != rend(); ++it) + BOOST_REVERSE_FOREACH(const value_type& it, mRanges) { - if (lower(it) < v) - return min(v - 1, upper(it)); + if (it.second < v) + return it.second; + if (contains(it, v + 1)) + return v - 1; } return RangeSetAbsent; } uint32 RangeSet::prevMissing(uint32 v) const { // largest number not in the set that is less than the given number - WriteLog (lsTRACE, RangeSet) << "prevMissing(" << v << ") " << toString(); - for (const_reverse_iterator it = rbegin(); it != rend(); ++it) + BOOST_FOREACH(const value_type& it, mRanges) { - if ((upper(it) + 1) < v) - return upper(it) + 1; - if (lower(it) == 0) - return RangeSetAbsent; - if ((lower(it) - 1) < v) - return lower(it) - 1; + if (contains(it, v)) + return it.first - 1; + if (it.first > v) + return v + 1; } - if (v > 0) - return v - 1; return RangeSetAbsent; } void RangeSet::setValue(uint32 v) { - setRange(v, v); + if (!hasValue(v)) + { + mRanges[v] = v; + simplify(); + } } void RangeSet::setRange(uint32 minV, uint32 maxV) { - mRanges.add(boost::icl::discrete_interval(minV, maxV + 1)); + while (hasValue(minV)) + { + ++minV; + if (minV >= maxV) + return; + } + mRanges[minV] = maxV; + simplify(); } void RangeSet::clearValue(uint32 v) { - clearRange(v, v); -} - -void RangeSet::clearRange(uint32 minV, uint32 maxV) -{ - mRanges.erase(boost::icl::discrete_interval(minV, maxV + 1)); + for (iterator it = mRanges.begin(); it != mRanges.end(); ++it) + { + if (contains(*it, v)) + { + if (it->first == v) + { + if (it->second == v) + mRanges.erase(it); + else + { + mRanges[v + 1] = it->second; + it->second = v - 1; + } + } + else if (it->second == v) + --(it->second); + else + { + uint32 oldEnd = it->second; + it->second = v - 1; + mRanges[v + 1] = oldEnd; + } + return; + } + } } std::string RangeSet::toString() const { std::string ret; - for (const_iterator it = begin(); it != end(); ++it) + BOOST_FOREACH(value_type const& it, mRanges) { if (!ret.empty()) ret += ","; - if (lower(it) == upper(it)) - ret += boost::lexical_cast(lower(it)); + if (it.first == it.second) + ret += boost::lexical_cast((it.first)); else - ret += boost::lexical_cast(lower(it)) + "-" - + boost::lexical_cast(upper(it)); + ret += boost::lexical_cast(it.first) + "-" + + boost::lexical_cast(it.second); } if (ret.empty()) return "empty"; return ret; } +void RangeSet::simplify() +{ + iterator it = mRanges.begin(); + while (1) + { + iterator nit = it; + if (++nit == mRanges.end()) + return; + if (it->second >= (nit->first - 1)) + { // ranges overlap + it->second = nit->second; + mRanges.erase(nit); + } + else + it = nit; + } +} + BOOST_AUTO_TEST_SUITE(RangeSet_suite) BOOST_AUTO_TEST_CASE(RangeSet_test) diff --git a/modules/ripple_basics/containers/ripple_RangeSet.h b/modules/ripple_basics/containers/ripple_RangeSet.h index 9a311853cc..44dfa4045e 100644 --- a/modules/ripple_basics/containers/ripple_RangeSet.h +++ b/modules/ripple_basics/containers/ripple_RangeSet.h @@ -4,15 +4,22 @@ class RangeSet { public: - typedef boost::icl::interval_set iRangeSet; - typedef iRangeSet::iterator iterator; - typedef iRangeSet::const_iterator const_iterator; - typedef iRangeSet::reverse_iterator reverse_iterator; - typedef iRangeSet::const_reverse_iterator const_reverse_iterator; static const uint32 RangeSetAbsent = static_cast(-1); protected: - iRangeSet mRanges; + std::map mRanges; // First is lowest value in range, last is highest value in range + + typedef std::map::const_iterator const_iterator; + typedef std::map::const_reverse_iterator const_reverse_iterator; + typedef std::map::value_type value_type; + typedef std::map::iterator iterator; + + static bool contains(value_type const& it, uint32 v) + { + return (it.first <= v) && (it.second >= v); + } + + void simplify(); public: @@ -29,71 +36,10 @@ public: void setValue(uint32); void setRange(uint32, uint32); void clearValue(uint32); - void clearRange(uint32, uint32); - - - // iterator stuff - iterator begin() { return mRanges.begin(); } - iterator end() { return mRanges.end(); } - const_iterator begin() const { return mRanges.begin(); } - const_iterator end() const { return mRanges.end(); } - reverse_iterator rbegin() { return mRanges.rbegin(); } - reverse_iterator rend() { return mRanges.rend(); } - const_reverse_iterator rbegin() const { return mRanges.rbegin(); } - const_reverse_iterator rend() const { return mRanges.rend(); } - - static uint32 lower(const_iterator& it) { return it->lower(); } - static uint32 upper(const_iterator& it) { return it->upper() - 1; } - static uint32 lower(const_reverse_iterator& it) { return it->lower(); } - static uint32 upper(const_reverse_iterator& it) { return it->upper() - 1; } - std::string toString() const; }; -inline RangeSet::const_iterator range_begin(const RangeSet& r) { return r.begin(); } -inline RangeSet::iterator range_begin(RangeSet& r) { return r.begin(); } -inline RangeSet::const_iterator range_end(const RangeSet& r) { return r.end(); } -inline RangeSet::iterator range_end(RangeSet& r) { return r.end(); } - -namespace boost -{ - template<> struct range_mutable_iterator - { - typedef RangeSet::iterator type; - }; - template<> struct range_const_iterator - { - typedef RangeSet::const_iterator type; - }; -} - -// VFALCO Maybe not the best place for this but it sort of makes sense here - -// VFALCO NOTE these three are unused. -/* -template T range_check(const T& value, const T& minimum, const T& maximum) -{ - if ((value < minimum) || (value > maximum)) - throw std::runtime_error("Value out of range"); - return value; -} - -template T range_check_min(const T& value, const T& minimum) -{ - if (value < minimum) - throw std::runtime_error("Value out of range"); - return value; -} - -template T range_check_max(const T& value, const T& maximum) -{ - if (value > maximum) - throw std::runtime_error("Value out of range"); - return value; -} -*/ - // VFALCO TODO these parameters should not be const references. template T range_check_cast(const U& value, const T& minimum, const T& maximum) { @@ -102,6 +48,7 @@ template T range_check_cast(const U& value, const T& min return static_cast(value); } + #endif // vim:ts=4 diff --git a/modules/ripple_basics/ripple_basics.h b/modules/ripple_basics/ripple_basics.h index eb092665e8..34e57c8909 100644 --- a/modules/ripple_basics/ripple_basics.h +++ b/modules/ripple_basics/ripple_basics.h @@ -72,7 +72,6 @@ namespace boost { // RangeSet #include -#include // oof this one is ugly // InstanceCounter //#include diff --git a/modules/ripple_data/protocol/ripple_SerializedObject.cpp b/modules/ripple_data/protocol/ripple_SerializedObject.cpp index f4b7c362c4..b440510e75 100644 --- a/modules/ripple_data/protocol/ripple_SerializedObject.cpp +++ b/modules/ripple_data/protocol/ripple_SerializedObject.cpp @@ -1021,13 +1021,13 @@ UPTR_T STObject::parseJson(const Json::Value& object, SField::ref inNa else if (value.isInt()) { if (value.asInt() < 0 || value.asInt() > 255) - throw std::runtime_error("value out of rand"); + throw std::runtime_error("value out of range"); data.push_back(new STUInt8(field, range_check_cast(value.asInt(), 0, 255))); } else if (value.isUInt()) { if (value.asUInt() > 255) - throw std::runtime_error("value out of rand"); + throw std::runtime_error("value out of range"); data.push_back(new STUInt8(field, range_check_cast(value.asUInt(), 0, 255))); } else