addAllStartingAt method

void addAllStartingAt(
  1. Iterable<T> source, [
  2. int skipItems = 0,
  3. int? nrItems
])

Add all elements from source to this, after skipping skipItems items from the source. skipItems=0 is equivalent to calling addAll.

Implementation

void addAllStartingAt(Iterable<T> source, [int skipItems = 0, int? nrItems]) {
  if (nrItems != null && nrItems < 0) {
    throw (RangeError(
        'Incorrect number of items specified for addAllStartingAt: $nrItems'));
  }

  // If the collection doesn't care about sorting or it's already unsorted, go
  // ahead and add.
  if (sortingEnforcement == SortingEnforcement.notRequired || !sortedByTime) {
    _addAllStartingAt_NoSortingRequired(source, skipItems, nrItems);
    return;
  }

  // If the code arrives here, the current collection is sorted and cares
  // about sorting.

  // If the source is itself a collection, rely on its internal sorting
  // flags to determine the validity of the situation cheaply.
  if (source is GpsPointsCollection<T>) {
    _addAllStartingAt_CollectionSource(source, skipItems, nrItems);
    return;
  }

  // Source is some random iterable. Convert it to a collection and run it
  // through the procedure again. This is an expensive operation both in time
  // and in terms of memory. Memory could possibly be reduced by using an
  // async stream-based approach, but that's not worth the effort for now.

  // Pre-setting the capacity has a massive effect on speed - the benchmark
  // in point_addition.dart is about 3-4x faster with preset capacity than if
  // the list is grown incrementally with the natural capacity increasing
  // algo.
  int? copiedCapacity;
  if (source is RandomAccessIterable) {
    copiedCapacity = (source.length - skipItems);
  }

  final copiedSource =
      newEmpty(capacity: copiedCapacity) as GpsPointsCollection<T>;
  // Use same enforcement strategy as the target collection. That way if the
  // data is incorrect, it can be detected already while copying from the
  // iterable to the list.
  copiedSource.sortingEnforcement = sortingEnforcement;
  // Add the last item of the current collection, as that's going to be the
  // benchmark that everything else is compared to.
  if (isNotEmpty) {
    copiedSource.add(last);
  }
  // Only copy after any skipped items.
  final subSource = getSubSource(source, skipItems, nrItems);
  for (final element in subSource) {
    copiedSource.add(element);
  }
  // When adding, skip the reference item that we copied from the current
  // collection, if any.
  addAllStartingAt(copiedSource, isNotEmpty ? 1 : 0);
}