All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jhotdraw8.icollection.impl.champ.ChampSpliterator Maven / Gradle / Ivy

/*
 * @(#)KeySpliterator.java
 * Copyright © 2023 The authors and contributors of JHotDraw. MIT License.
 */

package org.jhotdraw8.icollection.impl.champ;

import org.jspecify.annotations.Nullable;

import java.util.Spliterators;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * Data iterator over a CHAMP trie.
 * 

* References: *

* This class has been derived from 'The Capsule Hash Trie Collections Library'. *

*
The Capsule Hash Trie Collections Library. *
Copyright (c) Michael Steindorfer. BSD-2-Clause License
*
github.com *
* * * @param the data type of the trie node * @param the element type of the iterator */ public class ChampSpliterator extends Spliterators.AbstractSpliterator { private final Function mappingFunction; private static final int MAX_DEPTH = 7; protected int currentValueCursor; protected int currentValueLength; protected Node currentValueNode; private int currentStackLevel = -1; /** * Even indexes: node index * Odd indexes: node length */ private final int[] indexAndArity = new int[MAX_DEPTH * 2]; @SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"}) final Node[] nodes = new Node[MAX_DEPTH]; private K current; @SuppressWarnings("unchecked") public ChampSpliterator(Node rootNode, @Nullable Function mappingFunction, long size, int characteristics) { super(size, characteristics); this.mappingFunction = mappingFunction == null ? k -> (E) k : mappingFunction; if (rootNode.hasNodes()) { currentStackLevel = 0; nodes[0] = rootNode; indexAndArity[0] = 0; indexAndArity[1] = rootNode.nodeArity(); } if (rootNode.hasData()) { currentValueNode = rootNode; currentValueCursor = 0; currentValueLength = rootNode.dataArity(); } } private boolean searchNextValueNode() { // For inlining, it is essential that this method has a very small amount of byte code! while (currentStackLevel >= 0) { var index = currentStackLevel << 1; if (indexAndArity[index] < indexAndArity[index + 1]) { var nextNode = nodes[currentStackLevel].getNode(indexAndArity[index]); indexAndArity[index]++; if (nextNode.hasNodes()) { ++currentStackLevel; index += 2; nodes[currentStackLevel] = nextNode; indexAndArity[index] = 0; indexAndArity[index + 1] = nextNode.nodeArity(); } if (nextNode.hasData()) { currentValueNode = nextNode; currentValueCursor = 0; currentValueLength = nextNode.dataArity(); return true; } } else { currentStackLevel--; } } return false; } @Override public boolean tryAdvance(Consumer action) { // For inlining, it is essential that this method has a very small amount of byte code! // Specifically, do not inline searchNextValueNode() into this method! if (currentValueCursor < currentValueLength || searchNextValueNode()) { action.accept(mappingFunction.apply(currentValueNode.getData(currentValueCursor++))); return true; } return false; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy