/* * Copyright 2015, 2016 Tagir Valeev * * 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 one.util.streamex; import java.util.Spliterator; import java.util.function.Consumer; import one.util.streamex.StreamExInternals.TailSpliterator; /** * @author Tagir Valeev * * @param <T> type of the elements */ /* package */class PrependSpliterator<T> implements TailSpliterator<T> { private Spliterator<T> source; private T element; private int mode; public PrependSpliterator(Spliterator<T> source, T element) { this.source = source; this.element = element; this.mode = source.estimateSize() < Long.MAX_VALUE-1 ? 1 : 2; } @Override public boolean tryAdvance(Consumer<? super T> action) { if (mode == 0) return source.tryAdvance(action); action.accept(element); element = null; mode = 0; return true; } @Override public Spliterator<T> tryAdvanceOrTail(Consumer<? super T> action) { if (mode == 0) { Spliterator<T> s = source; source = null; return s; } action.accept(element); element = null; mode = 0; return this; } @Override public void forEachRemaining(Consumer<? super T> action) { if (mode != 0) action.accept(element); element = null; mode = 0; source.forEachRemaining(action); } @Override public Spliterator<T> forEachOrTail(Consumer<? super T> action) { if (mode != 0) { action.accept(element); } Spliterator<T> s = source; element = null; mode = 0; source = null; return s; } @Override public Spliterator<T> trySplit() { if (mode == 0) return source.trySplit(); mode = 0; return new ConstSpliterator.OfRef<>(element, 1, true); } @Override public long estimateSize() { long size = source.estimateSize(); return mode == 0 || size == Long.MAX_VALUE ? size : size + 1; } @Override public int characteristics() { switch(mode) { case 1: return source.characteristics() & (ORDERED | SIZED | SUBSIZED); case 2: return source.characteristics() & ORDERED; default: return source.characteristics(); } } }