From 366361d6b3ae59fae0d5f80e86641afb7439ef6b Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 24 Oct 2012 18:33:37 -0700 Subject: [PATCH] Traverse functions have not been fully tested. --- src/RangeSet.cpp | 134 ++++++++++++++++++++++++++--------------------- src/RangeSet.h | 27 +++++++--- 2 files changed, 94 insertions(+), 67 deletions(-) diff --git a/src/RangeSet.cpp b/src/RangeSet.cpp index 94b8a00e40..7e576761fd 100644 --- a/src/RangeSet.cpp +++ b/src/RangeSet.cpp @@ -1,17 +1,19 @@ #include "RangeSet.h" +#include +#include + +#include "Log.h" + +SETUP_LOG(); + inline int min(int x, int y) { return (x < y) ? x : y; } inline int max(int x, int y) { return (x > y) ? x : y; } bool RangeSet::hasValue(int v) const { - for (const_iterator it = begin(); it != end(); ++it) - { - if ((v >= it->first) && (v <= it->second)) - return true; - } - return false; + return mRanges.find(v) != mRanges.end(); } int RangeSet::getFirst() const @@ -19,15 +21,15 @@ int RangeSet::getFirst() const const_iterator it = begin(); if (it == end()) return RangeSetAbsent; - return it->first; + return it->lower(); } int RangeSet::getNext(int v) const { for (const_iterator it = begin(); it != end(); ++it) { - if (it->second > v) - return min(v + 1, it->first); + if ((it->upper() - 1) > v) + return max(v + 1, it->lower()); } return RangeSetAbsent; } @@ -37,76 +39,90 @@ int RangeSet::getLast() const const_reverse_iterator it = rbegin(); if (it == rend()) return RangeSetAbsent; - return it->second; + return it->upper() - 1; } int RangeSet::getPrev(int v) const { for (const_reverse_iterator it = rbegin(); it != rend(); ++it) { - if (it->first < v) - return max(v - 1, it->second); + if (it->lower() < v) + return min(v - 1, it->upper() - 1); } return RangeSetAbsent; } -bool RangeSet::setValue(int v) +void RangeSet::setValue(int v) { - for (iterator it = begin(); it != end(); ++it) - { - if (it->first >= v) - { // entry goes before or in this entry - if (it->second <= v) - return false; - if (it->first > (v - 1)) - { - mRanges.insert(it, std::make_pair(v, v)); - return true; - } - else if (it->first == (v - 1)) - { - it->first = v; - // WRITEME: check for consolidation - } - // WRITEME - } - } - mRanges.push_back(std::make_pair(v, v)); - return true; + setRange(v, v); } void RangeSet::setRange(int minV, int maxV) { + mRanges.add(boost::icl::discrete_interval(minV, maxV + 1)); } -bool RangeSet::clearValue(int v) +void RangeSet::clearValue(int v) { - for (iterator it = begin(); it != end(); ++it) - { - if (it->first >= v) - { // we are at or past the value we need to clear - - if (it->second > v) - return false; - - if ((it->first == v) && (it->second == v)) - mRanges.erase(it); - else if (it->first == v) - ++it->first; - else if (it->second == v) - --it->second; - else - { // this pokes a hole - int first = it->first; - it->first = v + 1; - mRanges.insert(it, std::make_pair(first, v - 1)); - } - return true; - } - } - return false; + clearRange(v, v); } void RangeSet::clearRange(int minV, int maxV) { + mRanges.erase(boost::icl::discrete_interval(minV, maxV + 1)); } + +std::string RangeSet::toString() const +{ + std::string ret; + for (const_iterator it = begin(); it != end(); ++it) + { + if (!ret.empty()) + ret += ","; + if (it->lower() == (it->upper() - 1)) + ret += boost::lexical_cast(it->lower()); + else + ret += boost::lexical_cast(it->lower()) + "-" + + boost::lexical_cast(it->upper() - 1); + } + if (ret.empty()) + return "empty"; + return ret; +} + +BOOST_AUTO_TEST_SUITE(RangeSet_suite) + +BOOST_AUTO_TEST_CASE(RangeSet_test) +{ + cLog(lsTRACE) << "RangeSet test begins"; + + RangeSet r1, r2; + + if (r1 != r2) BOOST_FAIL("RangeSet fail"); + + r1.setValue(1); + if (r1 == r2) BOOST_FAIL("RangeSet fail"); + r2.setRange(1, 1); + if (r1 != r2) BOOST_FAIL("RangeSet fail"); + + r1.clear(); + r1.setRange(1,10); + r1.clearValue(5); + r1.setRange(11, 20); + + r2.clear(); + r2.setRange(1, 4); + r2.setRange(6, 10); + r2.setRange(10, 20); + if (r1 != r2) BOOST_FAIL("RangeSet fail"); + if (r1.hasValue(5)) BOOST_FAIL("RangeSet fail"); + if (!r2.hasValue(9)) BOOST_FAIL("RangeSet fail"); + + // TODO: Traverse functions must be tested + + cLog(lsTRACE) << "RangeSet test complete"; +} + +BOOST_AUTO_TEST_SUITE_END() + +// vim:ts=4 diff --git a/src/RangeSet.h b/src/RangeSet.h index eaa6256152..3a395a5ed0 100644 --- a/src/RangeSet.h +++ b/src/RangeSet.h @@ -2,24 +2,26 @@ #define RANGESET__H #include +#include #include +#include class RangeSet { public: - typedef std::pair Range; - typedef std::list::iterator iterator; - typedef std::list::const_iterator const_iterator; - typedef std::list::reverse_iterator reverse_iterator; - typedef std::list::const_reverse_iterator const_reverse_iterator; + 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 int RangeSetAbsent = -1; protected: - std::list mRanges; + iRangeSet mRanges; public: @@ -31,11 +33,13 @@ public: int getLast() const; int getPrev(int) const; - bool setValue(int); + void setValue(int); void setRange(int, int); - bool clearValue(int); + void clearValue(int); void clearRange(int, int); + void clear() { mRanges.clear(); } + // iterator stuff iterator begin() { return mRanges.begin(); } iterator end() { return mRanges.end(); } @@ -45,6 +49,11 @@ public: reverse_iterator rend() { return mRanges.rend(); } const_reverse_iterator rbegin() const { return mRanges.rbegin(); } const_reverse_iterator rend() const { return mRanges.rend(); } + + bool operator!=(const RangeSet& r) const { return mRanges != r.mRanges; } + bool operator==(const RangeSet& r) const { return mRanges == r.mRanges; } + + std::string toString() const; }; inline RangeSet::const_iterator range_begin(const RangeSet& r) { return r.begin(); } @@ -65,3 +74,5 @@ namespace boost } #endif + +// vim:ts=4