137 lines
2.9 KiB
C
137 lines
2.9 KiB
C
|
|
#ifndef INTEGERRANGE_H
|
|||
|
|
#define INTEGERRANGE_H
|
|||
|
|
|
|||
|
|
#include <algorithm>
|
|||
|
|
|
|||
|
|
template <typename Value>
|
|||
|
|
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 <typename InputIt, typename OutputIt>
|
|||
|
|
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 <typename Container, typename RangeType>
|
|||
|
|
//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
|