Skip to content

Commit

Permalink
Refactored iterator of iterator into a single class that does both
Browse files Browse the repository at this point in the history
  • Loading branch information
DavyLandman committed Sep 22, 2024
1 parent 82c9844 commit b47627c
Showing 1 changed file with 36 additions and 65 deletions.
101 changes: 36 additions & 65 deletions src/main/java/io/usethesource/vallang/impl/primitive/StringValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -1257,104 +1257,75 @@ public AbstractString rotateLeftRight() {
@Override
public OfInt iterator() {
return new OfInt() {
IteratorOfIterators<OfInt> current = new IteratorOfIterators<>(leftMostIterator(), IStringTreeNode::iterator);
final InOrderIterator<OfInt> it = new InOrderIterator<>(IStringTreeNode::iterator);

@Override
public boolean hasNext() {
return current.hasNext();
return it.getActive().hasNext();
}

@Override
public int nextInt() {
return current.currentIterator().nextInt();
return it.getActive().nextInt();
}
};
}

@Override
public Iterator<CharBuffer> iterateParts() {
return new Iterator<> () {
IteratorOfIterators<Iterator<CharBuffer>> current = new IteratorOfIterators<>(leftMostIterator(), IStringTreeNode::iterateParts);
final InOrderIterator<Iterator<CharBuffer>> it = new InOrderIterator<>(IStringTreeNode::iterateParts);

@Override
public boolean hasNext() {
return current.hasNext();
return it.getActive().hasNext();
}

@Override
public CharBuffer next() {
return current.currentIterator().next();
return it.getActive().next();
}
};
}

private static class IteratorOfIterators<T extends Iterator<?>> {
private final Iterator<IStringTreeNode> base;
private final Function<IStringTreeNode, T> nested;
private @Nullable T current = null;

IteratorOfIterators(Iterator<IStringTreeNode> base, Function<IStringTreeNode, T> nested) {
this.base = base;
this.nested = nested;
}

boolean hasNext() {
return base.hasNext() || (current != null && current.hasNext());
/**
* An in order traversel of the leafs of the concat tree.
* We then for every leaf call the desired iterator, and replace it when the next when it's consumed
*/
private class InOrderIterator<T extends Iterator<?>> {
private final Deque<AbstractString> todo = new ArrayDeque<>(depth);
private final Function<IStringTreeNode, T> getActualIterator;
private T activeIterator;

InOrderIterator( Function<IStringTreeNode, T> getActualIterator) {
this.getActualIterator = getActualIterator;
activeIterator = getActualIterator.apply(leftmostLeaf(todo, LazyConcatString.this));
}

T currentIterator() {
if (current == null || !current.hasNext()) {
current = nested.apply(base.next());
T getActive() {
while (!activeIterator.hasNext() && !todo.isEmpty()) {
activeIterator = getActualIterator.apply(leftmostLeaf(todo, todo.pop()));
}
return current;
return activeIterator;
}

}

private Iterator<IStringTreeNode> leftMostIterator() {
return new Iterator<>() {
final Deque<AbstractString> todo = new ArrayDeque<>(depth);
IStringTreeNode nextNode = leftmostLeaf(todo, LazyConcatString.this);


@Override
public boolean hasNext() {
return nextNode != null; /* || !todo.isEmpty() is unnecessary due to post-condition of next() */
/**
* helper function for the iterator() method.
*
* It finds the left-most leaf of the tree, and collects
* the path of nodes to this leaf as a side-effect in the todo
* stack.
*/
private IStringTreeNode leftmostLeaf(Deque<AbstractString> todo, IStringTreeNode start) {
IStringTreeNode cur = start;

while (cur.depth() > 1) {
todo.push(cur.right());
cur = cur.left();
}

@Override
public IStringTreeNode next() {
var result = nextNode;
if (result == null) {
throw new NoSuchElementException();
}
if (todo.isEmpty()) {
nextNode = null;
}
else {
nextNode = leftmostLeaf(todo, todo.pop());
}
return result;
}
};
}

/**
* Static helper function for the iterator() method.
*
* It finds the left-most leaf of the tree, and collects
* the path of nodes to this leaf as a side-effect in the todo
* stack.
*/
private static IStringTreeNode leftmostLeaf(Deque<AbstractString> todo, IStringTreeNode start) {
IStringTreeNode cur = start;

while (cur.depth() > 1) {
todo.push(cur.right());
cur = cur.left();
return cur;
}

return cur;
}

}
Expand Down

0 comments on commit b47627c

Please sign in to comment.