5 #include <interval-tree/interval_tree.hpp>
6 #include <interval-tree/tree_hooks.hpp>
26 template <
typename ValueType,
typename IntervalKind = lib_
interval_tree::closed>
27 class RangeStateInterval;
29 template <
typename ValueType,
typename IntervalKind>
48 return lhs.start_ == rhs.start_ && lhs.end_ == rhs.end_ && lhs.type_ == rhs.type_;
78 return low_ <= h && l <= high_;
87 return low_ <= h + 1 && l - 1 <= high_;
91 return low_ <= other.high_ + 1 && other.low_ - 1 <= high_;
99 return interval_kind::within(low_, high_, value);
103 return low_ <= other.low_ && high_ >= other.high_;
117 return high_ < other.low_;
123 if (high_ < other.low_)
124 return other.low_ - high_;
126 return low_ - other.high_;
135 const auto low = std::min(low_, other.low_);
153 :
public lib_interval_tree::node<long, RangeStateInterval<long>, CustomIntervalTreeNode>
159 this->interval_.low(this->interval_.low() + offset);
160 this->interval_.high(this->interval_.high() + offset);
161 this->max_ = this->max_ + offset;
166 this->interval_.low(this->interval_.low() - offset);
167 this->interval_.high(this->interval_.high() - offset);
168 this->max_ = this->max_ - offset;
178 template <
typename T,
typename Kind>
181 os <<
"[" << interval.
low() <<
", " << interval.
high() <<
"]";
195 , nextEraseOverride_{std::nullopt}
196 , fullRangeUpdate_{false}
197 , disableOptimizations_{disableOptimizations}
208 fullRangeUpdate_ =
true;
215 fullRangeUpdate_ || disableOptimizations_ || trackedRanges_.empty())
218 return eraseModificationFixup(low, high);
220 return eraseInsertionFixup(low, high);
224 return eraseNotify(
static_cast<long>(low),
static_cast<long>(high));
228 if (disableOptimizations_)
230 fullRangeUpdate_ =
true;
236 operationType_ = type;
238 else if (operationType_ != type)
248 trackedRanges_.insert_overlap({low, high});
253 insertInsertRange(low, high);
258 if (nextEraseOverride_)
260 insertEraseRange(nextEraseOverride_->low(), nextEraseOverride_->high());
261 nextEraseOverride_ = std::nullopt;
264 insertEraseRange(low, high);
275 void reset(
bool requireFullRangeUpdate =
false)
277 trackedRanges_.clear();
278 fullRangeUpdate_ = requireFullRangeUpdate;
287 return fullRangeUpdate_;
291 return trackedRanges_.begin();
295 return trackedRanges_.end();
299 return trackedRanges_.rbegin();
303 return trackedRanges_.rend();
307 return operationType_;
311 void insertInsertRange(
long low,
long high)
317 auto it = trackedRanges_.find(newRange, [](
auto const& a,
auto const& b) {
318 return a.low() == b.low();
321 if (it != trackedRanges_.end())
323 newRange = it->expand(newRange);
324 trackedRanges_.erase(it);
325 it = trackedRanges_.insert(newRange);
329 it = trackedRanges_.insert(newRange);
331 if (it != std::end(trackedRanges_))
336 for (; it != trackedRanges_.end(); ++it)
338 it.node()->shiftRight(high - low + 1);
341 void insertEraseRange(
long low,
long high)
343 auto newRange = Detail::RangeStateInterval<long>{low, high};
344 const bool processed = [&newRange,
this]() {
345 for (
auto it = trackedRanges_.begin(); it != trackedRanges_.end(); ++it)
349 if (it->low() < newRange.low())
352 newRange.shiftRight(it->size() + 1);
354 else if (it->overlapsOrIsAdjacent(newRange))
358 newRange = it->expand(newRange);
361 it = trackedRanges_.erase(it);
362 }
while (it != trackedRanges_.end() && it->overlapsOrIsAdjacent(newRange));
363 trackedRanges_.insert(newRange);
375 trackedRanges_.insert_overlap(newRange);
385 bool eraseInsertionFixup(
long low,
long high)
387 const auto lastInterval = *trackedRanges_.rbegin();
392 if (high < lastInterval.high())
395 auto eraseRange = Detail::RangeStateInterval<long>{low, high};
396 auto eraseRangeOrig = eraseRange;
398 auto iter = trackedRanges_.overlap_find(eraseRange,
true);
400 for (; iter != trackedRanges_.end(); iter = trackedRanges_.overlap_find(eraseRangeOrig,
true))
402 if (iter == trackedRanges_.end())
404 const auto insertInterval = *iter;
407 if (eraseRangeOrig.high() >= insertInterval.high())
409 trackedRanges_.erase(iter);
411 if (insertInterval.low() < eraseRangeOrig.low())
413 trackedRanges_.insert({insertInterval.low(), eraseRangeOrig.low() - 1});
414 eraseRangeOrig.high(-insertInterval.high() + eraseRangeOrig.low() + eraseRangeOrig.high() - 1);
417 eraseRange.high(eraseRange.high() - insertInterval.size() - 1);
425 if (eraseRange.high() != high)
426 nextEraseOverride_ = eraseRange;
440 bool eraseModificationFixup(
long low,
long high)
442 auto range = Detail::RangeStateInterval<long>{low, high};
444 auto iter = trackedRanges_.overlap_find(
range,
false);
446 if (iter == trackedRanges_.end())
451 const auto lastInterval = *trackedRanges_.rbegin();
455 if (high < lastInterval.low())
462 for (; iter != trackedRanges_.end(); iter = trackedRanges_.overlap_find(
range,
false))
464 const auto modInterval = *iter;
465 trackedRanges_.erase(iter);
469 if (modInterval.within(
range))
471 if (modInterval.low() <
range.low())
472 trackedRanges_.insert({modInterval.low(),
range.low() - 1});
473 if (
range.high() < modInterval.high())
474 trackedRanges_.insert({
range.high() + 1, modInterval.high()});
477 else if (modInterval.low() <
range.low())
480 trackedRanges_.insert({modInterval.low(),
range.low() - 1});
487 else if (
range.high() < modInterval.high())
490 trackedRanges_.insert({
range.high() + 1, modInterval.high()});
497 else if (
range.within(modInterval))
504 NUI_ASSERT(
false,
"Overlap without overlapping?");
511 lib_interval_tree::interval_tree<Detail::RangeStateInterval<long>, Detail::IntervalTreeHook> trackedRanges_;
513 std::optional<Detail::RangeStateInterval<long>> nextEraseOverride_;
514 bool fullRangeUpdate_;
515 bool disableOptimizations_;
#define NUI_ASSERT(condition, message)
Definition: assert.hpp:31
Definition: range_event_context.hpp:31
bool overlaps(RangeStateInterval const &other) const
Definition: range_event_context.hpp:80
friend bool operator==(RangeStateInterval const &lhs, RangeStateInterval const &rhs)
Definition: range_event_context.hpp:46
bool overlaps_exclusive(RangeStateInterval const &other) const
Definition: range_event_context.hpp:93
bool within(RangeStateInterval const &other) const
Definition: range_event_context.hpp:101
RangeStateInterval join(RangeStateInterval const &other) const
Definition: range_event_context.hpp:142
bool isLeftOf(RangeStateInterval const &other) const
Definition: range_event_context.hpp:115
IntervalKind interval_kind
Definition: range_event_context.hpp:34
void high(value_type value)
Definition: range_event_context.hpp:66
value_type high() const
Definition: range_event_context.hpp:58
void low(value_type value)
Definition: range_event_context.hpp:62
bool overlaps(value_type l, value_type h) const
Definition: range_event_context.hpp:70
value_type operator-(RangeStateInterval const &other) const
Definition: range_event_context.hpp:119
ValueType value_type
Definition: range_event_context.hpp:33
friend bool operator!=(RangeStateInterval const &lhs, RangeStateInterval const &rhs)
Definition: range_event_context.hpp:50
bool overlapsOrIsAdjacent(value_type l, value_type h) const
Definition: range_event_context.hpp:85
bool within(value_type value) const
Definition: range_event_context.hpp:97
void reset(value_type low, value_type high)
Definition: range_event_context.hpp:41
void shiftLeft(value_type offset)
Definition: range_event_context.hpp:110
bool overlaps_exclusive(value_type l, value_type h) const
Definition: range_event_context.hpp:76
RangeStateInterval expand(RangeStateInterval const &other) const
Definition: range_event_context.hpp:133
bool overlapsOrIsAdjacent(RangeStateInterval const &other) const
Definition: range_event_context.hpp:89
value_type size() const
Definition: range_event_context.hpp:128
void shiftRight(value_type offset)
Definition: range_event_context.hpp:105
RangeStateInterval(value_type low, value_type high)
Definition: range_event_context.hpp:37
value_type low() const
Definition: range_event_context.hpp:54
Definition: range_event_context.hpp:187
auto begin() const
Definition: range_event_context.hpp:289
InsertResult insertModificationRange(long low, long high, RangeOperationType type)
Definition: range_event_context.hpp:226
bool eraseNotify(std::size_t low, std::size_t high)
Definition: range_event_context.hpp:222
RangeOperationType operationType() const noexcept
Definition: range_event_context.hpp:305
bool isFullRangeUpdate() const noexcept
Definition: range_event_context.hpp:285
auto rend() const
Definition: range_event_context.hpp:301
auto rbegin() const
Definition: range_event_context.hpp:297
bool isInDefaultState() const
Definition: range_event_context.hpp:281
void reset(bool requireFullRangeUpdate=false)
Definition: range_event_context.hpp:275
InsertResult insertModificationRange(std::size_t low, std::size_t high, RangeOperationType type)
Definition: range_event_context.hpp:271
RangeEventContext()
Definition: range_event_context.hpp:189
RangeEventContext(bool disableOptimizations)
Definition: range_event_context.hpp:192
auto end() const
Definition: range_event_context.hpp:293
void performFullRangeUpdate()
Definition: range_event_context.hpp:206
InsertResult
Definition: range_event_context.hpp:200
bool eraseNotify(long low, long high)
Done before the erasure is performed:
Definition: range_event_context.hpp:212
std::ostream & operator<<(std::ostream &os, RangeStateInterval< T, Kind > const &interval)
Definition: range_event_context.hpp:179
Definition: file_dialog.hpp:6
UnoptimizedRange< IteratorAccessor< ContainerT const >, std::decay_t< Detail::ObservedAddReference_t< Observed > >... > range(ContainerT const &container, Observed &&... observed)
Definition: range.hpp:97
RangeOperationType
Definition: range_event_context.hpp:17
@ Modify
Definition: range_event_context.hpp:19
@ Insert
Definition: range_event_context.hpp:20
@ Erase
Definition: range_event_context.hpp:21
@ Keep
Definition: range_event_context.hpp:18
Definition: range_event_context.hpp:154
void shiftRight(long offset)
Definition: range_event_context.hpp:157
void shiftLeft(long offset)
Definition: range_event_context.hpp:164
Definition: range_event_context.hpp:173