#ifndef INTEGERRANGE_H #define INTEGERRANGE_H #include template class IntegerRange { public: using Val = Value; IntegerRange() = default; IntegerRange(Value start, Value length) : m_start(start) , m_length(length) {} bool canCombine(const IntegerRange &rhs) const { if (m_start == rhs.m_start) { return true; } if (m_start < rhs.m_start) { return m_start + m_length >= rhs.m_start; } else { return rhs.canCombine(*this); } } void setLength(Value length) { m_length = length; } Value length() const { return m_length; } void setStart(Value start) { m_start = start; } Value start() const { return m_start; } void setEnd(Value end) { m_length = end - m_start; } Value end() const { return m_start + m_length; } bool operator==(const IntegerRange &rhs) const { return m_start == rhs.m_start && m_length == rhs.m_length; } bool operator!=(const IntegerRange &rhs) const { return !operator==(rhs); } bool operator<(const IntegerRange &rhs) const { return m_start < rhs.m_start; } bool operator<=(const IntegerRange &rhs) const { return m_start < rhs.m_start || (m_start == rhs.m_start && m_length < rhs.m_length); } bool operator>(const IntegerRange &rhs) const { return m_start > rhs.m_start; } bool operator>=(const IntegerRange &rhs) const { return m_start > rhs.m_start || (m_start == rhs.m_start && m_length > rhs.m_length); } private: Value m_start = 0; Value m_length = 0; }; /// This function merges elements that overlap or touch into single elements /// and stores the resulting elements into the destination range starting at d_first /// /// Function assumes the input range is sorted template OutputIt merge_ranges(InputIt first, InputIt last, OutputIt d_first) { using Elem = typename InputIt::value_type; InputIt i = first; while (first != last) { Elem e = *first; ++first; while (first != last && e.canCombine(*first)) { if (first->end() > e.end()) e.setEnd(first->end()); ++first; } d_first = e; } return d_first; } //template //void insert(Container cont, RangeType range) //{ // auto ipos = std::lower_bound(begin(cont), end(cont), range); // // Maybe it can be combined with previous // if (ipos != begin(cont)) { // auto prev = ipos; // --prev; // if (prev->canCombine(range)) // prev->setEnd(range->end()); // } // else { // // We need to either insert it or combine with the next // if (ipos != end(cont) && range.canCombine(*ipos)) { // // remember where end of ipos range was // auto e = ipos->end(); // if (e > range.end()) // range.setEnd(e); // // We cannot modify element in set so we remove one element and add a new one // ipos = cont.erase(ipos); // cont.insert(ipos, range); // } // else { // cont->insert(ipos, range); // } // } //} #endif // INTEGERRANGE_H