diff --git a/src/RangeSet.cpp b/src/RangeSet.cpp new file mode 100644 index 000000000..94b8a00e4 --- /dev/null +++ b/src/RangeSet.cpp @@ -0,0 +1,112 @@ + +#include "RangeSet.h" + +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; +} + +int RangeSet::getFirst() const +{ + const_iterator it = begin(); + if (it == end()) + return RangeSetAbsent; + return it->first; +} + +int RangeSet::getNext(int v) const +{ + for (const_iterator it = begin(); it != end(); ++it) + { + if (it->second > v) + return min(v + 1, it->first); + } + return RangeSetAbsent; +} + +int RangeSet::getLast() const +{ + const_reverse_iterator it = rbegin(); + if (it == rend()) + return RangeSetAbsent; + return it->second; +} + +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); + } + return RangeSetAbsent; +} + +bool 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; +} + +void RangeSet::setRange(int minV, int maxV) +{ +} + +bool 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; +} + +void RangeSet::clearRange(int minV, int maxV) +{ +} diff --git a/src/RangeSet.h b/src/RangeSet.h new file mode 100644 index 000000000..eaa625615 --- /dev/null +++ b/src/RangeSet.h @@ -0,0 +1,67 @@ +#ifndef RANGESET__H +#define RANGESET__H + +#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; + static const int RangeSetAbsent = -1; + +protected: + + std::list mRanges; + +public: + + RangeSet() { ; } + + bool hasValue(int) const; + int getFirst() const; + int getNext(int) const; + int getLast() const; + int getPrev(int) const; + + bool setValue(int); + void setRange(int, int); + bool clearValue(int); + void clearRange(int, int); + + // 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(); } +}; + +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; + }; +} + +#endif