update method

RangeSet<T> update(
  1. RangeSetUpdate<T> updateSpec
)

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,
          )),
  );
}