in utils/src/main/java/jetbrains/exodus/core/dataStructures/persistent/AbstractPersistent23Tree.java [310:383]
public Iterator<K> tailReverseIterator(@NotNull final K key) {
return new Iterator<K>() {
private Stack<TreePosRev<K>> stack;
private boolean hasNext;
private boolean hasNextValid;
private K bound;
@Override
public boolean hasNext() {
if (hasNextValid) {
return hasNext;
}
hasNextValid = true;
if (stack == null) {
Node<K> root = getRoot();
if (root == null) {
hasNext = false;
return false;
}
bound = getLess(root, key);
stack = new Stack<>();
stack.push(new TreePosRev<>(root));
}
TreePosRev<K> treePos = stack.peek();
if (treePos.node.isLeaf()) {
while (treePos.pos <= 1) {
stack.pop();
if (stack.isEmpty()) {
hasNext = false;
return false;
}
treePos = stack.peek();
}
} else {
if (treePos.pos == 1) {
treePos = new TreePosRev<>(treePos.node.getFirstChild());
} else if (treePos.pos == 2) {
treePos = new TreePosRev<>(treePos.node.getSecondChild());
} else {
treePos = new TreePosRev<>(treePos.node.getThirdChild());
}
stack.push(treePos);
while (!treePos.node.isLeaf()) {
treePos = new TreePosRev<>(treePos.node.isTernary() ? treePos.node.getThirdChild() : treePos.node.getSecondChild());
stack.push(treePos);
}
}
treePos.pos--;
hasNext = tryNext() != bound;
return hasNext;
}
@Override
public K next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
hasNextValid = false;
return tryNext();
}
private K tryNext() {
TreePosRev<K> treePos = stack.peek();
// treePos.pos must be 1 or 2 here
return treePos.pos == 1 ? treePos.node.getFirstKey() : treePos.node.getSecondKey();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}