commonMain.implementations.immutableMap.PersistentHashMapContentIterators.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlinx-collections-immutable-metadata Show documentation
Show all versions of kotlinx-collections-immutable-metadata Show documentation
Kotlin Immutable Collections multiplatform library
The newest version!
/*
* Copyright 2016-2019 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
*/
package kotlinx.collections.immutable.implementations.immutableMap
import kotlinx.collections.immutable.internal.assert
import kotlin.js.JsName
internal const val TRIE_MAX_HEIGHT = 7
internal abstract class TrieNodeBaseIterator : Iterator {
protected var buffer = TrieNode.EMPTY.buffer
private set
private var dataSize = 0
protected var index = 0
fun reset(buffer: Array, dataSize: Int, index: Int) {
this.buffer = buffer
this.dataSize = dataSize
this.index = index
}
fun reset(buffer: Array, dataSize: Int) {
reset(buffer, dataSize, 0)
}
fun hasNextKey(): Boolean {
return index < dataSize
}
fun currentKey(): K {
assert(hasNextKey())
@Suppress("UNCHECKED_CAST")
return buffer[index] as K
}
fun moveToNextKey() {
assert(hasNextKey())
index += 2
}
fun hasNextNode(): Boolean {
assert(index >= dataSize)
return index < buffer.size
}
fun currentNode(): TrieNode {
assert(hasNextNode())
@Suppress("UNCHECKED_CAST")
return buffer[index] as TrieNode
}
fun moveToNextNode() {
assert(hasNextNode())
index++
}
override fun hasNext(): Boolean {
return hasNextKey()
}
}
internal class TrieNodeKeysIterator : TrieNodeBaseIterator() {
override fun next(): K {
assert(hasNextKey())
index += 2
@Suppress("UNCHECKED_CAST")
return buffer[index - 2] as K
}
}
internal class TrieNodeValuesIterator : TrieNodeBaseIterator() {
override fun next(): V {
assert(hasNextKey())
index += 2
@Suppress("UNCHECKED_CAST")
return buffer[index - 1] as V
}
}
internal class TrieNodeEntriesIterator : TrieNodeBaseIterator>() {
override fun next(): Map.Entry {
assert(hasNextKey())
index += 2
@Suppress("UNCHECKED_CAST")
return MapEntry(buffer[index - 2] as K, buffer[index - 1] as V)
}
}
internal open class MapEntry(override val key: K, override val value: V) : Map.Entry {
override fun hashCode(): Int = key.hashCode() xor value.hashCode()
override fun equals(other: Any?): Boolean =
(other as? Map.Entry<*, *>)?.let { it.key == key && it.value == value } ?: false
override fun toString(): String = key.toString() + "=" + value.toString()
}
internal abstract class PersistentHashMapBaseIterator(
node: TrieNode,
protected val path: Array>
) : Iterator {
protected var pathLastIndex = 0
@JsName("_hasNext")
private var hasNext = true
init {
path[0].reset(node.buffer, ENTRY_SIZE * node.entryCount())
pathLastIndex = 0
ensureNextEntryIsReady()
}
private fun moveToNextNodeWithData(pathIndex: Int): Int {
if (path[pathIndex].hasNextKey()) {
return pathIndex
}
if (path[pathIndex].hasNextNode()) {
val node = path[pathIndex].currentNode()
if (pathIndex == TRIE_MAX_HEIGHT - 1) { // collision
path[pathIndex + 1].reset(node.buffer, node.buffer.size)
} else {
path[pathIndex + 1].reset(node.buffer, ENTRY_SIZE * node.entryCount())
}
return moveToNextNodeWithData(pathIndex + 1)
}
return -1
}
private fun ensureNextEntryIsReady() {
if (path[pathLastIndex].hasNextKey()) {
return
}
for(i in pathLastIndex downTo 0) {
var result = moveToNextNodeWithData(i)
if (result == -1 && path[i].hasNextNode()) {
path[i].moveToNextNode()
result = moveToNextNodeWithData(i)
}
if (result != -1) {
pathLastIndex = result
return
}
if (i > 0) {
path[i - 1].moveToNextNode()
}
path[i].reset(TrieNode.EMPTY.buffer, 0)
}
hasNext = false
}
protected fun currentKey(): K {
checkHasNext()
return path[pathLastIndex].currentKey()
}
override fun hasNext(): Boolean {
return hasNext
}
override fun next(): T {
checkHasNext()
val result = path[pathLastIndex].next()
ensureNextEntryIsReady()
return result
}
private fun checkHasNext() {
if (!hasNext())
throw NoSuchElementException()
}
}
internal class PersistentHashMapEntriesIterator(node: TrieNode)
: PersistentHashMapBaseIterator>(node, Array(TRIE_MAX_HEIGHT + 1) { TrieNodeEntriesIterator() })
internal class PersistentHashMapKeysIterator(node: TrieNode)
: PersistentHashMapBaseIterator(node, Array(TRIE_MAX_HEIGHT + 1) { TrieNodeKeysIterator() })
internal class PersistentHashMapValuesIterator(node: TrieNode)
: PersistentHashMapBaseIterator(node, Array(TRIE_MAX_HEIGHT + 1) { TrieNodeValuesIterator() })