pgLab/core/IntegerRange.h
eelke 62c6ad5bfb Improved support from removing rows in crud tabs.
It can handle now complex selections and reports back errors encountered
when removing the rows fails.
2018-12-15 11:24:58 +01:00

136 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