update method
Update the range set, optionally adding new ranges or filtering out existing ones.
Implementation
RangeSet<T> update(RangeSetUpdate<T> updateSpec) {
var add = updateSpec.add;
final sort = updateSpec.sort;
final filterFrom = updateSpec.filterFrom;
final filterTo = updateSpec.filterTo ?? length;
final filter = updateSpec.filter;
if (add.isEmpty && filter == null) return this;
if (sort) {
add = List.of(add)..sort(_cmpRange);
}
if (isEmpty) return add.isNotEmpty ? RangeSet.of(add) : this;
final cur = _LayerCursor<T>(this, null, -1).goto(0);
var i = 0;
final spill = <Range<T>>[];
final builder = RangeSetBuilder<T>();
while (cur.value != null || i < add.length) {
if (i < add.length &&
(cur.from - add[i].from != 0
? cur.from - add[i].from
: cur._startSide - add[i].value.startSide) >=
0) {
final range = add[i++];
if (!builder._addInner(range.from, range.to, range.value)) {
spill.add(range);
}
} else if (cur._rangeIndex == 1 &&
cur._chunkIndex < chunk.length &&
(i == add.length || _chunkEnd(cur._chunkIndex) < add[i].from) &&
(filter == null ||
filterFrom > _chunkEnd(cur._chunkIndex) ||
filterTo < chunkPos[cur._chunkIndex]) &&
builder._addChunk(chunkPos[cur._chunkIndex], chunk[cur._chunkIndex])) {
cur._nextChunk();
} else {
if (filter == null ||
filterFrom > cur.to ||
filterTo < cur.from ||
filter(cur.from, cur.to, cur.value as T)) {
if (!builder._addInner(cur.from, cur.to, cur.value as T)) {
spill.add(Range.create(cur.from, cur.to, cur.value as T));
}
}
cur.next();
}
}
return builder._finishInner(
nextLayer.isEmpty && spill.isEmpty
? RangeSet.empty<T>()
: nextLayer.update(RangeSetUpdate<T>(
add: spill,
filter: filter,
filterFrom: filterFrom,
filterTo: filterTo,
)),
);
}