HashCollisionNode
(HashCollisionNode. edit collision-hash cnt arr)
(deftype HashCollisionNode [edit
^:mutable collision-hash
^:mutable cnt
^:mutable arr]
Object
(inode-assoc [inode shift hash key val added-leaf?]
(if (== hash collision-hash)
(let [idx (hash-collision-node-find-index arr cnt key)]
(if (== idx -1)
(let [len (* 2 cnt)
new-arr (make-array (+ len 2))]
(array-copy arr 0 new-arr 0 len)
(aset new-arr len key)
(aset new-arr (inc len) val)
(set! (.-val added-leaf?) true)
(HashCollisionNode. nil collision-hash (inc cnt) new-arr))
(if (= (aget arr (inc idx)) val)
inode
(HashCollisionNode. nil collision-hash cnt (clone-and-set arr (inc idx) val)))))
(.inode-assoc (BitmapIndexedNode. nil (bitpos collision-hash shift) (array nil inode))
shift hash key val added-leaf?)))
(inode-without [inode shift hash key]
(let [idx (hash-collision-node-find-index arr cnt key)]
(cond (== idx -1) inode
(== cnt 1) nil
:else (HashCollisionNode. nil collision-hash (dec cnt) (remove-pair arr (quot idx 2))))))
(inode-lookup [inode shift hash key not-found]
(let [idx (hash-collision-node-find-index arr cnt key)]
(cond (< idx 0) not-found
(key-test key (aget arr idx)) (aget arr (inc idx))
:else not-found)))
(inode-find [inode shift hash key not-found]
(let [idx (hash-collision-node-find-index arr cnt key)]
(cond (< idx 0) not-found
(key-test key (aget arr idx)) (MapEntry. (aget arr idx) (aget arr (inc idx)) nil)
:else not-found)))
(inode-seq [inode]
(create-inode-seq arr))
(ensure-editable [inode e]
(if (identical? e edit)
inode
(let [new-arr (make-array (* 2 (inc cnt)))]
(array-copy arr 0 new-arr 0 (* 2 cnt))
(HashCollisionNode. e collision-hash cnt new-arr))))
(ensure-editable-array [inode e count array]
(if (identical? e edit)
(do (set! arr array)
(set! cnt count)
inode)
(HashCollisionNode. edit collision-hash count array)))
(inode-assoc! [inode edit shift hash key val added-leaf?]
(if (== hash collision-hash)
(let [idx (hash-collision-node-find-index arr cnt key)]
(if (== idx -1)
(if (> (alength arr) (* 2 cnt))
(let [editable (edit-and-set inode edit (* 2 cnt) key (inc (* 2 cnt)) val)]
(set! (.-val added-leaf?) true)
(set! (.-cnt editable) (inc (.-cnt editable)))
editable)
(let [len (alength arr)
new-arr (make-array (+ len 2))]
(array-copy arr 0 new-arr 0 len)
(aset new-arr len key)
(aset new-arr (inc len) val)
(set! (.-val added-leaf?) true)
(.ensure-editable-array inode edit (inc cnt) new-arr)))
(if (identical? (aget arr (inc idx)) val)
inode
(edit-and-set inode edit (inc idx) val))))
(.inode-assoc! (BitmapIndexedNode. edit (bitpos collision-hash shift) (array nil inode nil nil))
edit shift hash key val added-leaf?)))
(inode-without! [inode edit shift hash key removed-leaf?]
(let [idx (hash-collision-node-find-index arr cnt key)]
(if (== idx -1)
inode
(do (set! (.-val removed-leaf?) true)
(if (== cnt 1)
nil
(let [editable (.ensure-editable inode edit)
earr (.-arr editable)]
(aset earr idx (aget earr (- (* 2 cnt) 2)))
(aset earr (inc idx) (aget earr (dec (* 2 cnt))))
(aset earr (dec (* 2 cnt)) nil)
(aset earr (- (* 2 cnt) 2) nil)
(set! (.-cnt editable) (dec (.-cnt editable)))
editable))))))
(kv-reduce [inode f init]
(inode-kv-reduce arr f init))
IIterable
(-iterator [coll]
(NodeIterator. arr 0 nil nil)))