| /* |
| * Copyright 2016 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package java.util; |
| |
| import static javaemul.internal.InternalPreconditions.checkCriticalElement; |
| import static javaemul.internal.InternalPreconditions.checkCriticalState; |
| import static javaemul.internal.InternalPreconditions.checkNotNull; |
| |
| import java.util.function.Consumer; |
| import java.util.function.DoubleConsumer; |
| import java.util.function.IntConsumer; |
| import java.util.function.LongConsumer; |
| |
| /** |
| * See <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Spliterators.html"> |
| * the official Java API doc</a> for details. |
| * |
| * Since it's hard to implement parallel algorithms in the browser environment |
| * and to keep code simple, implementation does not provide splitting. |
| */ |
| public final class Spliterators { |
| |
| private abstract static class BaseSpliterator<T, S extends Spliterator<T>> |
| implements Spliterator<T> { |
| private final int characteristics; |
| private long sizeEstimate; |
| |
| BaseSpliterator(long size, int characteristics) { |
| this.sizeEstimate = size; |
| this.characteristics = (characteristics & Spliterator.SIZED) != 0 ? |
| characteristics | Spliterator.SUBSIZED : characteristics; |
| } |
| |
| public int characteristics() { |
| return characteristics; |
| } |
| |
| public long estimateSize() { |
| return sizeEstimate; |
| } |
| |
| public S trySplit() { |
| // see javadoc for java.util.Spliterator |
| return null; |
| } |
| } |
| |
| /** |
| * See <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Spliterators.AbstractSpliterator.html"> |
| * the official Java API doc</a> for details. |
| */ |
| public abstract static class AbstractSpliterator<T> |
| extends BaseSpliterator<T, Spliterator<T>> implements Spliterator<T> { |
| |
| protected AbstractSpliterator(long size, int characteristics) { |
| super(size, characteristics); |
| } |
| } |
| |
| /** |
| * See <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Spliterators.AbstractDoubleSpliterator.html"> |
| * the official Java API doc</a> for details. |
| */ |
| public abstract static class AbstractDoubleSpliterator |
| extends BaseSpliterator<Double, Spliterator.OfDouble> implements Spliterator.OfDouble { |
| |
| protected AbstractDoubleSpliterator(long size, int characteristics) { |
| super(size, characteristics); |
| } |
| } |
| |
| /** |
| * See <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Spliterators.AbstractIntSpliterator.html"> |
| * the official Java API doc</a> for details. |
| */ |
| public abstract static class AbstractIntSpliterator |
| extends BaseSpliterator<Integer, Spliterator.OfInt> implements Spliterator.OfInt { |
| |
| protected AbstractIntSpliterator(long size, int characteristics) { |
| super(size, characteristics); |
| } |
| } |
| |
| /** |
| * See <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Spliterators.AbstractLongSpliterator.html"> |
| * the official Java API doc</a> for details. |
| */ |
| public abstract static class AbstractLongSpliterator |
| extends BaseSpliterator<Long, Spliterator.OfLong> implements Spliterator.OfLong { |
| |
| protected AbstractLongSpliterator(long size, int characteristics) { |
| super(size, characteristics); |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| public static <T> Spliterator<T> emptySpliterator() { |
| return (Spliterator<T>) EmptySpliterator.OF_REF; |
| } |
| |
| public static Spliterator.OfDouble emptyDoubleSpliterator() { |
| return EmptySpliterator.OF_DOUBLE; |
| } |
| |
| public static Spliterator.OfInt emptyIntSpliterator() { |
| return EmptySpliterator.OF_INT; |
| } |
| |
| public static Spliterator.OfLong emptyLongSpliterator() { |
| return EmptySpliterator.OF_LONG; |
| } |
| |
| public static <T> Spliterator<T> spliterator(Object[] array, int characteristics) { |
| return new ArraySpliterator<>(array, characteristics); |
| } |
| |
| public static <T> Spliterator<T> spliterator(Object[] array, int fromIndex, int toIndex, |
| int characteristics) { |
| checkCriticalArrayBounds(fromIndex, toIndex, array.length); |
| return new ArraySpliterator<>(array, fromIndex, toIndex, characteristics); |
| } |
| |
| public static Spliterator.OfInt spliterator(int[] array, int characteristics) { |
| return new IntArraySpliterator(array, characteristics); |
| } |
| |
| public static Spliterator.OfInt spliterator(int[] array, int fromIndex, int toIndex, |
| int characteristics) { |
| checkCriticalArrayBounds(fromIndex, toIndex, array.length); |
| return new IntArraySpliterator(array, fromIndex, toIndex, characteristics); |
| } |
| |
| public static Spliterator.OfLong spliterator(long[] array, int characteristics) { |
| return new LongArraySpliterator(array, characteristics); |
| } |
| |
| public static Spliterator.OfLong spliterator(long[] array, int fromIndex, int toIndex, |
| int characteristics) { |
| checkCriticalArrayBounds(fromIndex, toIndex, array.length); |
| return new LongArraySpliterator(array, fromIndex, toIndex, characteristics); |
| } |
| |
| public static Spliterator.OfDouble spliterator(double[] array, int characteristics) { |
| return new DoubleArraySpliterator(array, characteristics); |
| } |
| |
| public static Spliterator.OfDouble spliterator(double[] array, int fromIndex, int toIndex, |
| int characteristics) { |
| checkCriticalArrayBounds(fromIndex, toIndex, array.length); |
| return new DoubleArraySpliterator(array, fromIndex, toIndex, characteristics); |
| } |
| |
| public static <T> Spliterator<T> spliterator(Collection<? extends T> c, int characteristics) { |
| return new IteratorSpliterator<>(c, characteristics); |
| } |
| |
| public static <T> Spliterator<T> spliterator(Iterator<? extends T> it, long size, |
| int characteristics) { |
| return new IteratorSpliterator<>(it, size, characteristics); |
| } |
| |
| public static <T> Spliterator<T> spliteratorUnknownSize(Iterator<? extends T> it, |
| int characteristics) { |
| return new IteratorSpliterator<>(it, characteristics); |
| } |
| |
| public static Spliterator.OfInt spliterator(PrimitiveIterator.OfInt it, long size, |
| int characteristics) { |
| return new IntIteratorSpliterator(it, size, characteristics); |
| } |
| |
| public static Spliterator.OfInt spliteratorUnknownSize(PrimitiveIterator.OfInt it, |
| int characteristics) { |
| return new IntIteratorSpliterator(it, characteristics); |
| } |
| |
| public static Spliterator.OfLong spliterator(PrimitiveIterator.OfLong it, long size, |
| int characteristics) { |
| return new LongIteratorSpliterator(it, size, characteristics); |
| } |
| |
| public static Spliterator.OfLong spliteratorUnknownSize(PrimitiveIterator.OfLong it, |
| int characteristics) { |
| return new LongIteratorSpliterator(it, characteristics); |
| } |
| |
| public static Spliterator.OfDouble spliterator(PrimitiveIterator.OfDouble it, long size, |
| int characteristics) { |
| return new DoubleIteratorSpliterator(it, size, characteristics); |
| } |
| |
| public static Spliterator.OfDouble spliteratorUnknownSize(PrimitiveIterator.OfDouble it, |
| int characteristics) { |
| return new DoubleIteratorSpliterator(it, characteristics); |
| } |
| |
| public static <T> Iterator<T> iterator(Spliterator<? extends T> spliterator) { |
| return new ConsumerIterator<>(spliterator); |
| } |
| |
| public static PrimitiveIterator.OfDouble iterator(Spliterator.OfDouble spliterator) { |
| return new DoubleConsumerIterator(spliterator); |
| } |
| |
| public static PrimitiveIterator.OfInt iterator(Spliterator.OfInt spliterator) { |
| return new IntConsumerIterator(spliterator); |
| } |
| |
| public static PrimitiveIterator.OfLong iterator(Spliterator.OfLong spliterator) { |
| return new LongConsumerIterator(spliterator); |
| } |
| |
| private abstract static class EmptySpliterator<T, S extends Spliterator<T>, C> |
| implements Spliterator<T> { |
| |
| static final Spliterator<Object> OF_REF = new EmptySpliterator.OfRef<>(); |
| static final Spliterator.OfDouble OF_DOUBLE = new EmptySpliterator.OfDouble(); |
| static final Spliterator.OfInt OF_INT = new EmptySpliterator.OfInt(); |
| static final Spliterator.OfLong OF_LONG = new EmptySpliterator.OfLong(); |
| |
| public int characteristics() { |
| return Spliterator.SIZED | Spliterator.SUBSIZED; |
| } |
| |
| public long estimateSize() { |
| return 0; |
| } |
| |
| public void forEachRemaining(C consumer) { |
| checkNotNull(consumer); |
| } |
| |
| public boolean tryAdvance(C consumer) { |
| checkNotNull(consumer); |
| return false; |
| } |
| |
| public S trySplit() { |
| return null; |
| } |
| |
| private static final class OfRef<T> |
| extends EmptySpliterator<T, Spliterator<T>, Consumer<? super T>> |
| implements Spliterator<T> { |
| |
| OfRef() { } |
| } |
| |
| private static final class OfDouble |
| extends EmptySpliterator<Double, Spliterator.OfDouble, DoubleConsumer> |
| implements Spliterator.OfDouble { |
| |
| OfDouble() { } |
| } |
| |
| private static final class OfInt |
| extends EmptySpliterator<Integer, Spliterator.OfInt, IntConsumer> |
| implements Spliterator.OfInt { |
| |
| OfInt() { } |
| } |
| |
| private static final class OfLong |
| extends EmptySpliterator<Long, Spliterator.OfLong, LongConsumer> |
| implements Spliterator.OfLong { |
| |
| OfLong() { } |
| } |
| } |
| |
| private static final class ConsumerIterator<T> implements Consumer<T>, Iterator<T> { |
| private final Spliterator<? extends T> spliterator; |
| private T nextElement; |
| private boolean hasElement = false; |
| |
| ConsumerIterator(Spliterator<? extends T> spliterator) { |
| this.spliterator = checkNotNull(spliterator); |
| } |
| |
| @Override |
| public void accept(T element) { |
| nextElement = element; |
| } |
| |
| @Override |
| public boolean hasNext() { |
| if (!hasElement) { |
| hasElement = spliterator.tryAdvance(this); |
| } |
| return hasElement; |
| } |
| |
| @Override |
| public T next() { |
| checkCriticalElement(hasNext()); |
| hasElement = false; |
| T element = nextElement; |
| nextElement = null; |
| return element; |
| } |
| } |
| |
| private static final class DoubleConsumerIterator |
| implements DoubleConsumer, PrimitiveIterator.OfDouble { |
| |
| private final Spliterator.OfDouble spliterator; |
| private double nextElement; |
| private boolean hasElement = false; |
| |
| DoubleConsumerIterator(Spliterator.OfDouble spliterator) { |
| this.spliterator = checkNotNull(spliterator); |
| } |
| |
| @Override |
| public void accept(double d) { |
| nextElement = d; |
| } |
| |
| @Override |
| public boolean hasNext() { |
| if (!hasElement) { |
| hasElement = spliterator.tryAdvance(this); |
| } |
| return hasElement; |
| } |
| |
| @Override |
| public double nextDouble() { |
| checkCriticalElement(hasNext()); |
| hasElement = false; |
| return nextElement; |
| } |
| } |
| |
| private static final class IntConsumerIterator |
| implements IntConsumer, PrimitiveIterator.OfInt { |
| |
| private final Spliterator.OfInt spliterator; |
| private int nextElement; |
| private boolean hasElement = false; |
| |
| IntConsumerIterator(Spliterator.OfInt spliterator) { |
| this.spliterator = checkNotNull(spliterator); |
| } |
| |
| @Override |
| public void accept(int i) { |
| nextElement = i; |
| } |
| |
| @Override |
| public boolean hasNext() { |
| if (!hasElement) { |
| hasElement = spliterator.tryAdvance(this); |
| } |
| return hasElement; |
| } |
| |
| @Override |
| public int nextInt() { |
| checkCriticalElement(hasNext()); |
| hasElement = false; |
| return nextElement; |
| } |
| } |
| |
| private static final class LongConsumerIterator |
| implements LongConsumer, PrimitiveIterator.OfLong { |
| |
| private final Spliterator.OfLong spliterator; |
| private long nextElement; |
| private boolean hasElement = false; |
| |
| LongConsumerIterator(Spliterator.OfLong spliterator) { |
| this.spliterator = checkNotNull(spliterator); |
| } |
| |
| @Override |
| public void accept(long l) { |
| nextElement = l; |
| } |
| |
| @Override |
| public boolean hasNext() { |
| if (!hasElement) { |
| hasElement = spliterator.tryAdvance(this); |
| } |
| return hasElement; |
| } |
| |
| @Override |
| public long nextLong() { |
| checkCriticalElement(hasNext()); |
| hasElement = false; |
| return nextElement; |
| } |
| } |
| |
| static class IteratorSpliterator<T> implements Spliterator<T> { |
| private Collection<? extends T> collection; |
| private Iterator<? extends T> it; |
| private final int characteristics; |
| private long estimateSize; |
| |
| IteratorSpliterator(Collection<? extends T> collection, int characteristics) { |
| this.collection = checkNotNull(collection); |
| this.characteristics = sizeKnownIteratorSpliteratorCharacteristics(characteristics); |
| } |
| |
| IteratorSpliterator(Iterator<? extends T> it, long size, int characteristics) { |
| this.it = checkNotNull(it); |
| this.characteristics = sizeKnownIteratorSpliteratorCharacteristics(characteristics); |
| this.estimateSize = size; |
| } |
| |
| IteratorSpliterator(Iterator<? extends T> it, int characteristics) { |
| this.it = checkNotNull(it); |
| this.characteristics = sizeUnknownSpliteratorCharacteristics(characteristics); |
| this.estimateSize = Long.MAX_VALUE; |
| } |
| |
| @Override |
| public int characteristics() { |
| return characteristics; |
| } |
| |
| @Override |
| public long estimateSize() { |
| initIterator(); |
| return estimateSize; |
| } |
| |
| @Override |
| public void forEachRemaining(Consumer<? super T> consumer) { |
| initIterator(); |
| it.forEachRemaining(consumer); |
| } |
| |
| @Override |
| public Comparator<? super T> getComparator() { |
| checkSorted(characteristics); |
| return null; |
| } |
| |
| @Override |
| public boolean tryAdvance(Consumer<? super T> consumer) { |
| checkNotNull(consumer); |
| initIterator(); |
| if (it.hasNext()) { |
| consumer.accept(it.next()); |
| return true; |
| } |
| return false; |
| } |
| |
| @Override |
| public Spliterator<T> trySplit() { |
| // see javadoc for java.util.Spliterator |
| return null; |
| } |
| |
| private void initIterator() { |
| if (it == null) { |
| it = collection.iterator(); |
| estimateSize = (long) collection.size(); |
| } |
| } |
| } |
| |
| private static final class DoubleIteratorSpliterator extends AbstractDoubleSpliterator { |
| private final PrimitiveIterator.OfDouble it; |
| |
| DoubleIteratorSpliterator(PrimitiveIterator.OfDouble it, long size, int characteristics) { |
| super(size, sizeKnownIteratorSpliteratorCharacteristics(characteristics)); |
| this.it = checkNotNull(it); |
| } |
| |
| DoubleIteratorSpliterator(PrimitiveIterator.OfDouble it, int characteristics) { |
| super(Long.MAX_VALUE, sizeUnknownSpliteratorCharacteristics(characteristics)); |
| this.it = checkNotNull(it); |
| } |
| |
| @Override |
| public void forEachRemaining(DoubleConsumer consumer) { |
| it.forEachRemaining(consumer); |
| } |
| |
| @Override |
| public Comparator<? super Double> getComparator() { |
| checkSorted(characteristics()); |
| return null; |
| } |
| |
| @Override |
| public boolean tryAdvance(DoubleConsumer consumer) { |
| checkNotNull(consumer); |
| if (it.hasNext()) { |
| consumer.accept(it.nextDouble()); |
| return true; |
| } |
| return false; |
| } |
| } |
| |
| private static final class IntIteratorSpliterator extends AbstractIntSpliterator { |
| private final PrimitiveIterator.OfInt it; |
| |
| IntIteratorSpliterator(PrimitiveIterator.OfInt it, long size, int characteristics) { |
| super(size, sizeKnownIteratorSpliteratorCharacteristics(characteristics)); |
| this.it = checkNotNull(it); |
| } |
| |
| IntIteratorSpliterator(PrimitiveIterator.OfInt it, int characteristics) { |
| super(Long.MAX_VALUE, sizeUnknownSpliteratorCharacteristics(characteristics)); |
| this.it = checkNotNull(it); |
| } |
| |
| @Override |
| public void forEachRemaining(IntConsumer consumer) { |
| it.forEachRemaining(consumer); |
| } |
| |
| @Override |
| public Comparator<? super Integer> getComparator() { |
| checkSorted(characteristics()); |
| return null; |
| } |
| |
| @Override |
| public boolean tryAdvance(IntConsumer consumer) { |
| checkNotNull(consumer); |
| if (it.hasNext()) { |
| consumer.accept(it.nextInt()); |
| return true; |
| } |
| return false; |
| } |
| } |
| |
| private static final class LongIteratorSpliterator extends AbstractLongSpliterator { |
| private final PrimitiveIterator.OfLong it; |
| |
| LongIteratorSpliterator(PrimitiveIterator.OfLong it, long size, int characteristics) { |
| super(size, sizeKnownIteratorSpliteratorCharacteristics(characteristics)); |
| this.it = checkNotNull(it); |
| } |
| |
| LongIteratorSpliterator(PrimitiveIterator.OfLong it, int characteristics) { |
| super(Long.MAX_VALUE, sizeUnknownSpliteratorCharacteristics(characteristics)); |
| this.it = checkNotNull(it); |
| } |
| |
| @Override |
| public void forEachRemaining(LongConsumer consumer) { |
| it.forEachRemaining(consumer); |
| } |
| |
| @Override |
| public Comparator<? super Long> getComparator() { |
| checkSorted(characteristics()); |
| return null; |
| } |
| |
| @Override |
| public boolean tryAdvance(LongConsumer consumer) { |
| checkNotNull(consumer); |
| if (it.hasNext()) { |
| consumer.accept(it.nextLong()); |
| return true; |
| } |
| return false; |
| } |
| } |
| |
| private abstract static class BaseArraySpliterator<T, S extends Spliterator<T>, C> |
| implements Spliterator<T> { |
| private int index; |
| private final int limit; |
| private final int characteristics; |
| |
| BaseArraySpliterator(int from, int limit, int characteristics) { |
| this.index = from; |
| this.limit = limit; |
| this.characteristics = sizeKnownSpliteratorCharacteristics(characteristics); |
| } |
| |
| public int characteristics() { |
| return characteristics; |
| } |
| |
| public long estimateSize() { |
| return limit - index; |
| } |
| |
| public void forEachRemaining(C consumer) { |
| checkNotNull(consumer); |
| while (index < limit) { |
| consume(consumer, index++); |
| } |
| } |
| |
| public Comparator<? super T> getComparator() { |
| checkSorted(characteristics); |
| return null; |
| } |
| |
| public boolean tryAdvance(C consumer) { |
| checkNotNull(consumer); |
| if (index < limit) { |
| consume(consumer, index++); |
| return true; |
| } |
| return false; |
| } |
| |
| public S trySplit() { |
| // see javadoc for java.util.Spliterator |
| return null; |
| } |
| |
| protected abstract void consume(C consumer, int index); |
| } |
| |
| private static final class ArraySpliterator<T> |
| extends BaseArraySpliterator<T, Spliterator<T>, Consumer<? super T>> |
| implements Spliterator<T> { |
| |
| private final Object[] array; |
| |
| ArraySpliterator(Object[] array, int characteristics) { |
| this(array, 0, array.length, characteristics); |
| } |
| |
| ArraySpliterator(Object[] array, int from, int limit, int characteristics) { |
| super(from, limit, characteristics); |
| this.array = array; |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| protected void consume(Consumer<? super T> consumer, int index) { |
| consumer.accept((T) array[index]); |
| } |
| } |
| |
| private static final class DoubleArraySpliterator |
| extends BaseArraySpliterator<Double, Spliterator.OfDouble, DoubleConsumer> |
| implements Spliterator.OfDouble { |
| |
| private final double[] array; |
| |
| DoubleArraySpliterator(double[] array, int characteristics) { |
| this(array, 0, array.length, characteristics); |
| } |
| |
| DoubleArraySpliterator(double[] array, int from, int limit, int characteristics) { |
| super(from, limit, characteristics); |
| this.array = array; |
| } |
| |
| @Override |
| protected void consume(DoubleConsumer consumer, int index) { |
| consumer.accept(array[index]); |
| } |
| } |
| |
| private static final class IntArraySpliterator |
| extends BaseArraySpliterator<Integer, Spliterator.OfInt, IntConsumer> |
| implements Spliterator.OfInt { |
| |
| private final int[] array; |
| |
| IntArraySpliterator(int[] array, int characteristics) { |
| this(array, 0, array.length, characteristics); |
| } |
| |
| IntArraySpliterator(int[] array, int from, int limit, int characteristics) { |
| super(from, limit, characteristics); |
| this.array = array; |
| } |
| |
| @Override |
| protected void consume(IntConsumer consumer, int index) { |
| consumer.accept(array[index]); |
| } |
| } |
| |
| private static final class LongArraySpliterator |
| extends BaseArraySpliterator<Long, Spliterator.OfLong, LongConsumer> |
| implements Spliterator.OfLong { |
| |
| private final long[] array; |
| |
| LongArraySpliterator(long[] array, int characteristics) { |
| this(array, 0, array.length, characteristics); |
| } |
| |
| LongArraySpliterator(long[] array, int from, int limit, int characteristics) { |
| super(from, limit, characteristics); |
| this.array = array; |
| } |
| |
| @Override |
| protected void consume(LongConsumer consumer, int index) { |
| consumer.accept(array[index]); |
| } |
| } |
| |
| private static void checkSorted(int characteristics) { |
| checkCriticalState((characteristics & Spliterator.SORTED) != 0); |
| } |
| |
| private static int sizeKnownSpliteratorCharacteristics(int characteristics) { |
| return characteristics | Spliterator.SIZED | Spliterator.SUBSIZED; |
| } |
| |
| private static int sizeKnownIteratorSpliteratorCharacteristics(int characteristics) { |
| return (characteristics & Spliterator.CONCURRENT) == 0 ? |
| sizeKnownSpliteratorCharacteristics(characteristics) : characteristics; |
| } |
| |
| private static int sizeUnknownSpliteratorCharacteristics(int characteristics) { |
| return characteristics & ~(Spliterator.SIZED | Spliterator.SUBSIZED); |
| } |
| |
| /** |
| * We cant use InternalPreconditions.checkCriticalArrayBounds here because |
| * Spliterators must throw only ArrayIndexOutOfBoundsException on range check by contract. |
| */ |
| private static void checkCriticalArrayBounds(int start, int end, int length) { |
| if (start > end || start < 0 || end > length) { |
| throw new ArrayIndexOutOfBoundsException( |
| "fromIndex: " + start + ", toIndex: " + end + ", length: " + length); |
| } |
| } |
| |
| private Spliterators() { } |
| |
| } |