#ifndef BASE_RUN_SET_H #define BASE_RUN_SET_H #include "base/run.h" #include #include //---------------------------------------------------------------- namespace base { template class run_set { public: void clear() { runs_.clear(); } void add(T const &b) { add(run(b, b + 1)); } void add(T const &b, T const &e) { add(run(b, e)); } void add(run const &r_) { run r(r_); if (runs_.size()) { // Skip all blocks that end before r const_iterator it = runs_.lower_bound(r); if (it != runs_.begin()) --it; while (it != runs_.end() && it->end_ < r.begin_) ++it; // work out which runs overlap if (it != runs_.end()) { r.begin_ = min_maybe(it->begin_, r.begin_); const_iterator first = it; while (it != runs_.end() && it->begin_ <= r.end_) { r.end_ = max_maybe(it->end_, r.end_); ++it; } // remove overlapping runs runs_.erase(first, it); } } runs_.insert(r); } void merge(run_set const &rhs) { for (const_iterator it = rhs.begin(); it != rhs.end(); ++it) add(*it); } bool member(T const &v) const { if (!runs_.size()) return false; typename rset::const_iterator it = runs_.lower_bound(run(v)); if (it != runs_.end() && it->begin_ == v) return true; if (it != runs_.begin()) { it--; return it->contains(v); } return false; } struct compare_begin { bool operator ()(run const &r1, run const &r2) const { return r1.begin_ < r2.begin_; } }; typedef std::set, compare_begin> rset; typedef typename rset::const_iterator const_iterator; const_iterator begin() const { return runs_.begin(); } const_iterator end() const { return runs_.end(); } const_iterator lower_bound(T const &b) const { return runs_.lower_bound(run(b, b + 1)); } const_iterator upper_bound(T const &b) const { return runs_.upper_bound(run(b, b + 1)); } void negate() { rset replacement; if (runs_.begin() == runs_.end()) replacement.insert(run()); else { typename rset::const_iterator b = runs_.begin(); // Some versions of gcc give a spurious // warning here. So we initialize it to // get round it. maybe last(0); last = b->end_; if (b->begin_) replacement.insert(run(maybe(), *(b->begin_))); ++b; while (b != runs_.end()) { replacement.insert(run(last, b->begin_)); last = b->end_; ++b; } if (last) replacement.insert(run(last, maybe())); } runs_ = replacement; } private: typedef typename run::maybe maybe; static maybe min_maybe(maybe const &m1, maybe const &m2) { if (!m1 || !m2) return maybe(); return maybe(std::min(*m1, *m2)); } static maybe max_maybe(maybe const &m1, maybe const &m2) { if (!m1 || !m2) return maybe(); return maybe(std::max(*m1, *m2)); } rset runs_; }; } //---------------------------------------------------------------- #endif