addAllStartingAt method Null safety
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);
}