inet.ipaddr.format.AddressSegmentSpliterator Maven / Gradle / Ivy
Show all versions of ipaddress Show documentation
package inet.ipaddr.format;
import java.math.BigInteger;
import java.util.Iterator;
import java.util.function.Consumer;
import java.util.function.Supplier;
import inet.ipaddr.AddressSegment;
import inet.ipaddr.format.AddressDivisionBase.IntBinaryIteratorProvider;
import inet.ipaddr.format.AddressDivisionBase.SegmentCreator;
import inet.ipaddr.format.util.AddressComponentSpliterator;
/**
* AddressSegmentSpliterator provides a {@link java.util.Spliterator} implementation for segment types in this library.
*
* The implementation of estimateSize() and getExactSizeIfKnown() provide exact sizes at all times.
*
* An AddressSegmentSpliterator instance has the spliterator characteristics of being concurrent, non-null, sorted, ordered, distinct, sized and sub-sized.
*
* Unlike the default spliterator that you get with any iterator, which has linear-time splitting, all instances of AddressSegmentSpliterator split in constant-time,
* therefore allowing for instant fully parallel iteration over subnets or subnet components.
*
* Any AddressSegmentSpliterator of size of 2 or larger can be split at any time.
*
* An instance of AddressSegmentSpliterator is not thread-safe.
* Parallel iteration derives from handing each additional AddressSegmentSpliterator returned from trySplit() to other threads.
*
*
* @author seancfoley
*
* @param
*/
class AddressSegmentSpliterator
extends SpliteratorBase implements AddressComponentSpliterator {
private Iterator iterator;
private T splitForIteration, currentForIteration;
// either segment values or segment prefix values
private int value;
private int upperValue;
private Supplier> iteratorProvider;
protected boolean isLowest;
private final boolean isHighest;
private final IntBinaryIteratorProvider subIteratorProvider;
private final SegmentCreator itemProvider;
AddressSegmentSpliterator(
int value,
int upperValue,
Supplier> iteratorProvider,
IntBinaryIteratorProvider subIteratorProvider,
SegmentCreator itemProvider) {
this(null, value, upperValue, iteratorProvider, subIteratorProvider, itemProvider);
}
AddressSegmentSpliterator(
T splitForIteration,
int value,
int upperValue,
Supplier> iteratorProvider,
IntBinaryIteratorProvider subIteratorProvider,
SegmentCreator itemProvider) {
this(value, upperValue, iteratorProvider, subIteratorProvider, true, true, itemProvider);
this.splitForIteration = splitForIteration;
}
private AddressSegmentSpliterator(
int value,
int upperValue,
Supplier> iteratorProvider,
IntBinaryIteratorProvider subIteratorProvider,
boolean isLowest,
boolean isHighest,
SegmentCreator itemProvider) {
this.iteratorProvider = iteratorProvider;
this.subIteratorProvider = subIteratorProvider;
this.isLowest = isLowest;
this.isHighest = isHighest;
this.itemProvider = itemProvider;
this.value = value;
this.upperValue = upperValue;
}
private int getCurrentValue() {
return value + ((int) iteratedCountL);
}
@Override
public BigInteger getSize() {
return BigInteger.valueOf(estimateSize());
}
/**
* Returns an exact count of the number of elements that would be
* encountered by a {@link #forEachRemaining} traversal.
* @return
*/
@Override
public long estimateSize() {
return ((long) upperValue) - getCurrentValue() + 1;
}
public T getCurrentItem() {
if(estimateSize() == 0) {
return null;
}
T item = currentForIteration;
if(item == null) {
currentForIteration = item = itemProvider.applyAsInt(getCurrentValue(), upperValue);
}
return item;
}
@Override
public T getAddressItem() {
T item = splitForIteration;
if(item == null) {
splitForIteration = item = itemProvider.applyAsInt(value, upperValue);
}
return item;
}
private Iterator provideIterator() {
if(iterator == null) {
if(iteratorProvider != null) {
iterator = iteratorProvider.get();
} else {
iterator = subIteratorProvider.applyAsInt(isLowest, isHighest, value, upperValue);
}
}
return iterator;
}
@Override
public boolean tryAdvance(Consumer super T> action) {
if(!inForEach && getCurrentValue() < upperValue) {
currentForIteration = null;
return tryAdvance(provideIterator(), action);
}
return false;
}
@Override
public void forEachRemaining(Consumer super T> action) {
if(inForEach) {
return;
}
inForEach = true;
try {
currentForIteration = null;
forEachRemaining(provideIterator(), action, (upperValue - value) + 1);
} finally {
inForEach = false;
}
}
@Override
public AddressComponentSpliterator trySplit() {
if(inForEach) {
return null;
}
int lower = getCurrentValue();
int size = upperValue - lower;
if(size <= 1) {
return null;
}
splitForIteration = null;
currentForIteration = null;
iteratorProvider = null;
int mid = lower + (size >>> 1);
value = mid + 1;
iteratedCountL = 0;
AddressSegmentSpliterator result = new AddressSegmentSpliterator(lower, mid, null, subIteratorProvider, isLowest, false, itemProvider);
result.iterator = iterator;
isLowest = false;
iterator = null;
return result;
}
}