From b47627ce5544f19553fc6ba4865d58ce868d1cfc Mon Sep 17 00:00:00 2001 From: Davy Landman Date: Sun, 22 Sep 2024 11:28:35 +0200 Subject: [PATCH] Refactored iterator of iterator into a single class that does both --- .../vallang/impl/primitive/StringValue.java | 101 +++++++----------- 1 file changed, 36 insertions(+), 65 deletions(-) diff --git a/src/main/java/io/usethesource/vallang/impl/primitive/StringValue.java b/src/main/java/io/usethesource/vallang/impl/primitive/StringValue.java index 4c064c9a..26599bac 100644 --- a/src/main/java/io/usethesource/vallang/impl/primitive/StringValue.java +++ b/src/main/java/io/usethesource/vallang/impl/primitive/StringValue.java @@ -1257,16 +1257,16 @@ public AbstractString rotateLeftRight() { @Override public OfInt iterator() { return new OfInt() { - IteratorOfIterators current = new IteratorOfIterators<>(leftMostIterator(), IStringTreeNode::iterator); + final InOrderIterator 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(); } }; } @@ -1274,87 +1274,58 @@ public int nextInt() { @Override public Iterator iterateParts() { return new Iterator<> () { - IteratorOfIterators> current = new IteratorOfIterators<>(leftMostIterator(), IStringTreeNode::iterateParts); + final InOrderIterator> 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> { - private final Iterator base; - private final Function nested; - private @Nullable T current = null; - - IteratorOfIterators(Iterator base, Function 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> { + private final Deque todo = new ArrayDeque<>(depth); + private final Function getActualIterator; + private T activeIterator; + + InOrderIterator( Function 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 leftMostIterator() { - return new Iterator<>() { - final Deque 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 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 todo, IStringTreeNode start) { - IStringTreeNode cur = start; - - while (cur.depth() > 1) { - todo.push(cur.right()); - cur = cur.left(); + return cur; } - - return cur; } }