
org.javimmutable.collections.iterators.GenericIterator Maven / Gradle / Ivy
///###////////////////////////////////////////////////////////////////////////
//
// Burton Computer Corporation
// http://www.burton-computer.com
//
// Copyright (c) 2019, Burton Computer Corporation
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.
//
// Neither the name of the Burton Computer Corporation nor the names
// of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package org.javimmutable.collections.iterators;
import org.javimmutable.collections.Func1;
import org.javimmutable.collections.Indexed;
import org.javimmutable.collections.SplitIterator;
import org.javimmutable.collections.SplitableIterable;
import org.javimmutable.collections.SplitableIterator;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import java.util.NoSuchElementException;
@ThreadSafe
public class GenericIterator
extends AbstractSplitableIterator
{
static final int MIN_SIZE_FOR_SPLIT = 32;
private final Iterable root;
private final int limit;
private int offset;
private boolean uninitialized;
private State state;
public GenericIterator(@Nonnull Iterable root,
int offset,
int limit)
{
assert offset <= limit;
this.root = root;
this.limit = limit;
this.offset = offset;
uninitialized = true;
}
public interface Iterable
extends SplitableIterable
{
@Nullable
State iterateOverRange(@Nullable State parent,
int offset,
int limit);
int iterableSize();
@Nonnull
default SplitableIterator iterator()
{
return new GenericIterator<>(this, 0, iterableSize());
}
}
public interface State
{
default boolean hasValue()
{
return false;
}
default T value()
{
throw new NoSuchElementException();
}
State advance();
}
@Override
public synchronized boolean hasNext()
{
return prepare();
}
@Override
public synchronized T next()
{
if (!prepare()) {
throw new NoSuchElementException();
}
final T answer = state.value();
offset += 1;
if (offset < limit) {
state = state.advance();
} else {
state = null;
}
assert offset <= limit;
return answer;
}
@Override
public synchronized boolean isSplitAllowed()
{
return (limit - offset) >= MIN_SIZE_FOR_SPLIT;
}
@Nonnull
@Override
public synchronized SplitIterator splitIterator()
{
final int splitIndex = offset + (limit - offset) / 2;
return new SplitIterator<>(new GenericIterator<>(root, offset, splitIndex),
new GenericIterator<>(root, splitIndex, limit));
}
private boolean prepare()
{
if (uninitialized) {
state = root.iterateOverRange(null, offset, limit);
uninitialized = false;
}
while (state != null) {
if (state.hasValue()) {
return true;
}
state = state.advance();
}
return false;
}
public static State valueState(State parent,
T value)
{
return new SingleValueState<>(parent, value);
}
public static Iterable valueIterable(T value)
{
return new Iterable()
{
@Override
public State iterateOverRange(@Nullable State parent,
int offset,
int limit)
{
assert offset >= 0 && offset <= limit && limit <= 1;
if (offset == limit) {
return parent;
} else {
return new SingleValueState(parent, value);
}
}
@Override
public int iterableSize()
{
return 1;
}
};
}
public static State multiValueState(@Nullable State parent,
@Nonnull Indexed values,
int offset,
int limit)
{
assert offset >= 0 && offset <= limit && limit <= values.size();
return new MultiValueState<>(parent, values, offset, limit);
}
public static State indexedState(State parent,
Indexed extends Iterable> children,
int offset,
int limit)
{
assert 0 <= offset && offset <= limit;
if (offset == limit) {
return parent;
} else {
return new IndexedState<>(parent, children, offset, limit);
}
}
public static State transformState(State parent,
State source,
Func1 transforminator)
{
if (source == null) {
return parent;
} else {
return new TransformState<>(parent, source, transforminator);
}
}
private static class SingleValueState
implements State
{
private final State parent;
private final T value;
private boolean available;
private SingleValueState(State parent,
T value)
{
this.parent = parent;
this.value = value;
available = true;
}
@Override
public boolean hasValue()
{
return available;
}
@Override
public T value()
{
assert available;
available = false;
return value;
}
@Override
public State advance()
{
assert !available;
return parent;
}
}
private static class MultiValueState
implements GenericIterator.State
{
private final GenericIterator.State parent;
private final Indexed values;
private final int limit;
private int offset;
private MultiValueState(@Nullable GenericIterator.State parent,
@Nonnull Indexed values,
int offset,
int limit)
{
this.parent = parent;
this.values = values;
this.offset = offset;
this.limit = limit;
}
@Override
public boolean hasValue()
{
return offset < limit;
}
@Override
public T value()
{
return values.get(offset);
}
@Nullable
@Override
public GenericIterator.State advance()
{
offset += 1;
if (offset < limit) {
return this;
} else {
return parent;
}
}
}
private static class IndexedState
implements State
{
private final State parent;
private final Indexed extends Iterable> children;
private int offset;
private int limit;
private int index;
public IndexedState(State parent,
Indexed extends Iterable> children,
int offset,
int limit)
{
this.parent = parent;
this.children = children;
this.limit = limit;
this.offset = offset;
index = 0;
}
@Override
public State advance()
{
final Iterable child = children.get(index);
final int size = child.iterableSize();
if (offset >= size) {
index += 1;
offset -= size;
limit -= size;
return this;
} else if (limit <= size) {
return child.iterateOverRange(parent, offset, limit);
} else {
final State answer = child.iterateOverRange(this, offset, size);
index += 1;
offset = 0;
limit -= size;
return answer;
}
}
}
private static class TransformState
implements GenericIterator.State
{
private final Func1 transforminator;
private final GenericIterator.State parent;
private GenericIterator.State source;
private TransformState(@Nullable GenericIterator.State parent,
@Nonnull GenericIterator.State source,
@Nonnull Func1 transforminator)
{
this.transforminator = transforminator;
this.parent = parent;
this.source = source;
}
@Override
public boolean hasValue()
{
return source.hasValue();
}
@Override
public B value()
{
return transforminator.apply(source.value());
}
@Nullable
@Override
public GenericIterator.State advance()
{
source = source.advance();
if (source == null) {
return parent;
} else {
return this;
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy