/* */ #ifndef D_SEG_LIST_H #define D_SEG_LIST_H #include #include #include #include namespace aria2 { template class SegList { public: SegList() : index_(0), val_(std::numeric_limits::min()) {} void clear() { segs_.clear(); index_ = 0; val_ = std::numeric_limits::min(); } // Transforms list of segments so that they are sorted ascending // order of starting value and intersecting and touching segments // are all merged into one. This function resets current position. void normalize() { if(!segs_.empty()) { std::sort(segs_.begin(), segs_.end()); std::vector > s; s.push_back(segs_.front()); for(size_t i = 1, len = segs_.size(); i < len; ++i) { const std::pair& x = segs_[i]; if(x.first <= s.back().second) { if(s.back().second < x.second) { s.back().second = x.second; } } else { s.push_back(x); } } s.swap(segs_); index_ = 0; val_ = segs_.front().first; } } // Add segment [a, b). If a >= b, do nothing. void add(T a, T b) { if(a < b) { if(segs_.empty()) { val_ = std::max(val_, a); } segs_.push_back(std::make_pair(a, b)); } } // Returns true if next value is available. Otherwise returns false. bool hasNext() const { return index_ < segs_.size() && val_ < segs_[index_].second; } // Returns next value. Advance current position to the next. If // this fuction is called when hasNext() returns false, returns 0. T next() { T res; size_t len = segs_.size(); if(index_ < len) { res = val_++; if(val_ == segs_[index_].second) { ++index_; if(index_ < len) { val_ = segs_[index_].first; } } } else { res = 0; } return res; } // Returns next value. Current position is not advanced. If // this fuction is called when hasNext() returns false, returns 0. T peek() const { T res; if(index_ < segs_.size()) { res = val_; } else { res = 0; } return res; } private: std::vector > segs_; size_t index_; T val_; // Don't allow copying SegList(const SegList&); SegList& operator=(const SegList&); }; } // namespace aria2 #endif // D_SEG_LIST_H