@@ -8,32 +8,37 @@ package kotlinx.collections.immutable.implementations.immutableMap
8
8
import kotlinx.collections.immutable.internal.assert
9
9
10
10
11
- internal class TrieNodeMutableEntriesIterator <K , V >(private val builder : PersistentHashMapBuilder <K , V >)
12
- : TrieNodeBaseIterator <K , V , MutableMap .MutableEntry <K , V >>() {
11
+ internal class TrieNodeMutableEntriesIterator <K , V >(
12
+ private val parentIterator : PersistentHashMapBuilderEntriesIterator <K , V >
13
+ ) : TrieNodeBaseIterator<K, V, MutableMap.MutableEntry<K, V>>() {
13
14
14
15
override fun next (): MutableMap .MutableEntry <K , V > {
15
16
assert (hasNextKey())
16
17
index + = 2
17
18
@Suppress(" UNCHECKED_CAST" )
18
- return MutableMapEntry (builder , buffer[index - 2 ] as K , buffer[index - 1 ] as V )
19
+ return MutableMapEntry (parentIterator , buffer[index - 2 ] as K , buffer[index - 1 ] as V )
19
20
}
20
21
}
21
22
22
- private class MutableMapEntry <K , V >(private val builder : PersistentHashMapBuilder <K , V >,
23
- key : K ,
24
- override var value : V ) : MapEntry<K, V>(key, value), MutableMap.MutableEntry<K, V> {
23
+ private class MutableMapEntry <K , V >(
24
+ private val parentIterator : PersistentHashMapBuilderEntriesIterator <K , V >,
25
+ key : K ,
26
+ override var value : V
27
+ ) : MapEntry<K, V>(key, value), MutableMap.MutableEntry<K, V> {
28
+
25
29
override fun setValue (newValue : V ): V {
26
30
val result = value
27
31
value = newValue
28
- builder[ key] = newValue
32
+ parentIterator.setValue( key, newValue)
29
33
return result
30
34
}
31
35
}
32
36
33
37
34
- internal abstract class PersistentHashMapBuilderBaseIterator <K , V , T >(private val builder : PersistentHashMapBuilder <K , V >,
35
- path : Array <TrieNodeBaseIterator <K , V , T >>)
36
- : MutableIterator <T >, PersistentHashMapBaseIterator <K , V , T >(builder.node, path) {
38
+ internal open class PersistentHashMapBuilderBaseIterator <K , V , T >(
39
+ private val builder : PersistentHashMapBuilder <K , V >,
40
+ path : Array <TrieNodeBaseIterator <K , V , T >>
41
+ ) : MutableIterator<T>, PersistentHashMapBaseIterator<K, V, T>(builder.node, path) {
37
42
38
43
private var lastIteratedKey: K ? = null
39
44
private var nextWasInvoked = false
@@ -62,8 +67,33 @@ internal abstract class PersistentHashMapBuilderBaseIterator<K, V, T>(private va
62
67
expectedModCount = builder.modCount
63
68
}
64
69
70
+ fun setValue (key : K , newValue : V ) {
71
+ if (! builder.containsKey(key)) return
72
+
73
+ if (hasNext()) {
74
+ val currentKey = currentKey()
75
+
76
+ builder[key] = newValue
77
+ resetPath(currentKey.hashCode(), builder.node, currentKey, 0 )
78
+ } else {
79
+ builder[key] = newValue
80
+ }
81
+
82
+ expectedModCount = builder.modCount
83
+ }
84
+
65
85
private fun resetPath (keyHash : Int , node : TrieNode <* , * >, key : K , pathIndex : Int ) {
66
86
val shift = pathIndex * LOG_MAX_BRANCHING_FACTOR
87
+
88
+ if (shift > MAX_SHIFT ) { // collision
89
+ path[pathIndex].reset(node.buffer, node.buffer.size, 0 )
90
+ while (path[pathIndex].currentKey() != key) {
91
+ path[pathIndex].moveToNextKey()
92
+ }
93
+ pathLastIndex = pathIndex
94
+ return
95
+ }
96
+
67
97
val keyPositionMask = 1 shl indexSegment(keyHash, shift)
68
98
69
99
if (node.hasEntryAt(keyPositionMask)) { // key is directly in buffer
@@ -72,22 +102,16 @@ internal abstract class PersistentHashMapBuilderBaseIterator<K, V, T>(private va
72
102
// assert(node.keyAtIndex(keyIndex) == key)
73
103
74
104
path[pathIndex].reset(node.buffer, ENTRY_SIZE * node.entryCount(), keyIndex)
105
+ pathLastIndex = pathIndex
75
106
return
76
107
}
77
108
78
- // assert(node.hasNodeAt(keyPosition )) // key is in node
109
+ // assert(node.hasNodeAt(keyPositionMask )) // key is in node
79
110
80
111
val nodeIndex = node.nodeIndex(keyPositionMask)
81
112
val targetNode = node.nodeAtIndex(nodeIndex)
82
- if (shift == MAX_SHIFT ) { // collision
83
- path[pathIndex].reset(node.buffer, node.buffer.size, 0 )
84
- while (path[pathIndex].currentKey() != key) {
85
- path[pathIndex].moveToNextKey()
86
- }
87
- } else {
88
- path[pathIndex].reset(node.buffer, ENTRY_SIZE * node.entryCount(), nodeIndex)
89
- resetPath(keyHash, targetNode, key, pathIndex + 1 )
90
- }
113
+ path[pathIndex].reset(node.buffer, ENTRY_SIZE * node.entryCount(), nodeIndex)
114
+ resetPath(keyHash, targetNode, key, pathIndex + 1 )
91
115
}
92
116
93
117
private fun checkNextWasInvoked () {
@@ -101,8 +125,20 @@ internal abstract class PersistentHashMapBuilderBaseIterator<K, V, T>(private va
101
125
}
102
126
}
103
127
104
- internal class PersistentHashMapBuilderEntriesIterator <K , V >(builder : PersistentHashMapBuilder <K , V >)
105
- : PersistentHashMapBuilderBaseIterator <K , V , MutableMap .MutableEntry <K , V >>(builder, Array (TRIE_MAX_HEIGHT + 1 ) { TrieNodeMutableEntriesIterator <K , V >(builder) })
128
+ internal class PersistentHashMapBuilderEntriesIterator <K , V >(
129
+ builder : PersistentHashMapBuilder <K , V >
130
+ ) : MutableIterator<MutableMap.MutableEntry<K, V>> {
131
+ private val base = PersistentHashMapBuilderBaseIterator <K , V , MutableMap .MutableEntry <K , V >>(
132
+ builder,
133
+ Array (TRIE_MAX_HEIGHT + 1 ) { TrieNodeMutableEntriesIterator (this ) }
134
+ )
135
+
136
+ override fun hasNext (): Boolean = base.hasNext()
137
+ override fun next (): MutableMap .MutableEntry <K , V > = base.next()
138
+ override fun remove (): Unit = base.remove()
139
+
140
+ fun setValue (key : K , newValue : V ): Unit = base.setValue(key, newValue)
141
+ }
106
142
107
143
internal class PersistentHashMapBuilderKeysIterator <K , V >(builder : PersistentHashMapBuilder <K , V >)
108
144
: PersistentHashMapBuilderBaseIterator <K , V , K >(builder, Array (TRIE_MAX_HEIGHT + 1 ) { TrieNodeKeysIterator <K , V >() })
0 commit comments