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

commonMain.implementations.immutableMap.PersistentHashMapBuilderContentIterators.kt Maven / Gradle / Ivy

There is a newer version: 0.3.8
Show 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


internal class TrieNodeMutableEntriesIterator(
        private val parentIterator: PersistentHashMapBuilderEntriesIterator
) : TrieNodeBaseIterator>() {

    override fun next(): MutableMap.MutableEntry {
        assert(hasNextKey())
        index += 2
        @Suppress("UNCHECKED_CAST")
        return MutableMapEntry(parentIterator, buffer[index - 2] as K, buffer[index - 1] as V)
    }
}

private class MutableMapEntry(
        private val parentIterator: PersistentHashMapBuilderEntriesIterator,
        key: K,
        override var value: V
) : MapEntry(key, value), MutableMap.MutableEntry {

    override fun setValue(newValue: V): V {
        val result = value
        value = newValue
        parentIterator.setValue(key, newValue)
        return result
    }
}


internal open class PersistentHashMapBuilderBaseIterator(
        private val builder: PersistentHashMapBuilder,
        path: Array>
) : MutableIterator, PersistentHashMapBaseIterator(builder.node, path) {

    private var lastIteratedKey: K? = null
    private var nextWasInvoked = false
    private var expectedModCount = builder.modCount

    override fun next(): T {
        checkForComodification()
        lastIteratedKey = currentKey()
        nextWasInvoked = true
        return super.next()
    }

    override fun remove() {
        checkNextWasInvoked()
        if (hasNext()) {
            val currentKey = currentKey()

            builder.remove(lastIteratedKey)
            resetPath(currentKey.hashCode(), builder.node, currentKey, 0)
        } else {
            builder.remove(lastIteratedKey)
        }

        lastIteratedKey = null
        nextWasInvoked = false
        expectedModCount = builder.modCount
    }

    fun setValue(key: K, newValue: V) {
        if (!builder.containsKey(key)) return

        if (hasNext()) {
            val currentKey = currentKey()

            builder[key] = newValue
            resetPath(currentKey.hashCode(), builder.node, currentKey, 0)
        } else {
            builder[key] = newValue
        }

        expectedModCount = builder.modCount
    }

    private fun resetPath(keyHash: Int, node: TrieNode<*, *>, key: K, pathIndex: Int) {
        val shift = pathIndex * LOG_MAX_BRANCHING_FACTOR

        if (shift > MAX_SHIFT) {    // collision
            path[pathIndex].reset(node.buffer, node.buffer.size, 0)
            while (path[pathIndex].currentKey() != key) {
                path[pathIndex].moveToNextKey()
            }
            pathLastIndex = pathIndex
            return
        }

        val keyPositionMask = 1 shl indexSegment(keyHash, shift)

        if (node.hasEntryAt(keyPositionMask)) { // key is directly in buffer
            val keyIndex = node.entryKeyIndex(keyPositionMask)

//            assert(node.keyAtIndex(keyIndex) == key)

            path[pathIndex].reset(node.buffer, ENTRY_SIZE * node.entryCount(), keyIndex)
            pathLastIndex = pathIndex
            return
        }

//        assert(node.hasNodeAt(keyPositionMask)) // key is in node

        val nodeIndex = node.nodeIndex(keyPositionMask)
        val targetNode = node.nodeAtIndex(nodeIndex)
        path[pathIndex].reset(node.buffer, ENTRY_SIZE * node.entryCount(), nodeIndex)
        resetPath(keyHash, targetNode, key, pathIndex + 1)
    }

    private fun checkNextWasInvoked() {
        if (!nextWasInvoked)
            throw IllegalStateException()
    }

    private fun checkForComodification() {
        if (builder.modCount != expectedModCount)
            throw ConcurrentModificationException()
    }
}

internal class PersistentHashMapBuilderEntriesIterator(
        builder: PersistentHashMapBuilder
) : MutableIterator> {
    private val base = PersistentHashMapBuilderBaseIterator>(
            builder,
            Array(TRIE_MAX_HEIGHT + 1) { TrieNodeMutableEntriesIterator(this) }
    )

    override fun hasNext(): Boolean = base.hasNext()
    override fun next(): MutableMap.MutableEntry = base.next()
    override fun remove(): Unit = base.remove()

    fun setValue(key: K, newValue: V): Unit = base.setValue(key, newValue)
}

internal class PersistentHashMapBuilderKeysIterator(builder: PersistentHashMapBuilder)
    : PersistentHashMapBuilderBaseIterator(builder, Array(TRIE_MAX_HEIGHT + 1) { TrieNodeKeysIterator() })

internal class PersistentHashMapBuilderValuesIterator(builder: PersistentHashMapBuilder)
    : PersistentHashMapBuilderBaseIterator(builder, Array(TRIE_MAX_HEIGHT + 1) { TrieNodeValuesIterator() })




© 2015 - 2024 Weber Informatics LLC | Privacy Policy