/* */ #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() { seg_.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(!seg_.empty()) { std::sort(seg_.begin(), seg_.end()); std::vector > s; s.push_back(seg_.front()); for(size_t i = 1, len = seg_.size(); i < len; ++i) { const std::pair& x = seg_[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(seg_); index_ = 0; val_ = seg_.front().first; } } // Add segment [a, b). If a >= b, do nothing. void add(T a, T b) { if(a < b) { if(seg_.empty()) { val_ = std::max(val_, a); } seg_.push_back(std::make_pair(a, b)); } } // Returns true if next value is available. Otherwise returns false. bool hasNext() const { return index_ < seg_.size() && val_ < seg_[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; if(index_ < seg_.size()) { res = val_++; if(val_ == seg_[index_].second) { ++index_; val_ = seg_[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_ < seg_.size()) { res = val_; } else { res = 0; } return res; } private: std::vector > seg_; size_t index_; T val_; }; } // namespace aria2 #endif // D_SEG_LIST_H