// Package hashmap implements persistent hashmap.
package hashmap import ( ) const ( chunkBits = 5 nodeCap = 1 << chunkBits chunkMask = nodeCap - 1 ) // Equal is the type of a function that reports whether two keys are equal. type Equal func(k1, k2 interface{}) bool // Hash is the type of a function that returns the hash code of a key. type Hash func(k interface{}) uint32 // New takes an equality function and a hash function, and returns an empty // Map. func ( Equal, Hash) Map { return &hashMap{0, emptyBitmapNode, nil, , } } type hashMap struct { count int root node nilV *interface{} equal Equal hash Hash } func ( *hashMap) () int { return .count } func ( *hashMap) ( interface{}) (interface{}, bool) { if == nil { if .nilV == nil { return nil, false } return *.nilV, true } return .root.find(0, .hash(), , .equal) } func ( *hashMap) (, interface{}) Map { if == nil { := .count if .nilV == nil { ++ } return &hashMap{, .root, &, .equal, .hash} } , := .root.assoc(0, .hash(), , , .hash, .equal) := .count if { ++ } return &hashMap{, , .nilV, .equal, .hash} } func ( *hashMap) ( interface{}) Map { if == nil { := .count if .nilV != nil { -- } return &hashMap{, .root, nil, .equal, .hash} } , := .root.without(0, .hash(), , .equal) := .count if { -- } return &hashMap{, , .nilV, .equal, .hash} } func ( *hashMap) () Iterator { if .nilV != nil { return &nilVIterator{true, *.nilV, .root.iterator()} } return .root.iterator() } type nilVIterator struct { atNil bool nilV interface{} tail Iterator } func ( *nilVIterator) () (interface{}, interface{}) { if .atNil { return nil, .nilV } return .tail.Elem() } func ( *nilVIterator) () bool { return .atNil || .tail.HasElem() } func ( *nilVIterator) () { if .atNil { .atNil = false } else { .tail.Next() } } func ( *hashMap) () ([]byte, error) { var bytes.Buffer .WriteByte('{') := true for := .Iterator(); .HasElem(); .Next() { if { = false } else { .WriteByte(',') } , := .Elem() , := convertKey() if != nil { return nil, } , := json.Marshal() if != nil { return nil, } , := json.Marshal() if != nil { return nil, } .Write() .WriteByte(':') .Write() } .WriteByte('}') return .Bytes(), nil } // convertKey converts a map key to a string. The implementation matches the // behavior of how json.Marshal encodes keys of the builtin map type. func ( interface{}) (string, error) { := reflect.ValueOf() if .Kind() == reflect.String { return .String(), nil } if , := .(encoding.TextMarshaler); { , := .MarshalText() if != nil { return "", } return string(), nil } switch .Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return strconv.FormatInt(.Int(), 10), nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return strconv.FormatUint(.Uint(), 10), nil } return "", fmt.Errorf("unsupported key type %T", ) } // node is an interface for all nodes in the hash map tree. type node interface { // assoc adds a new pair of key and value. It returns the new node, and // whether the key did not exist before (i.e. a new pair has been added, // instead of replaced). assoc(shift, hash uint32, k, v interface{}, h Hash, eq Equal) (node, bool) // without removes a key. It returns the new node and whether the key did // not exist before (i.e. a key was indeed removed). without(shift, hash uint32, k interface{}, eq Equal) (node, bool) // find finds the value for a key. It returns the found value (if any) and // whether such a pair exists. find(shift, hash uint32, k interface{}, eq Equal) (interface{}, bool) // iterator returns an iterator. iterator() Iterator } // arrayNode stores all of its children in an array. The array is always at // least 1/4 full, otherwise it will be packed into a bitmapNode. type arrayNode struct { nChildren int children [nodeCap]node } func ( *arrayNode) ( uint32, node, int) *arrayNode { := .children [] = return &arrayNode{.nChildren + , } } func ( *arrayNode) (, uint32, , interface{}, Hash, Equal) (node, bool) { := chunk(, ) := .children[] if == nil { , := emptyBitmapNode.assoc(+chunkBits, , , , , ) return .withNewChild(, , 1), true } , := .assoc(+chunkBits, , , , , ) return .withNewChild(, , 0), } func ( *arrayNode) (, uint32, interface{}, Equal) (node, bool) { := chunk(, ) := .children[] if == nil { return , false } , := .without(+chunkBits, , , ) if == { return , false } if == emptyBitmapNode { if .nChildren <= nodeCap/4 { // less than 1/4 full; shrink return .pack(int()), true } return .withNewChild(, nil, -1), true } return .withNewChild(, , 0), true } func ( *arrayNode) ( int) *bitmapNode { := bitmapNode{0, make([]mapEntry, .nChildren-1)} := 0 for , := range .children { // TODO(xiaq): Benchmark performance difference after unrolling this // into two loops without the if if != && != nil { .bitmap |= 1 << uint() .entries[].value = ++ } } return & } func ( *arrayNode) (, uint32, interface{}, Equal) (interface{}, bool) { := chunk(, ) := .children[] if == nil { return nil, false } return .find(+chunkBits, , , ) } func ( *arrayNode) () Iterator { := &arrayNodeIterator{, 0, nil} .fixCurrent() return } type arrayNodeIterator struct { n *arrayNode index int current Iterator } func ( *arrayNodeIterator) () { for ; .index < nodeCap && .n.children[.index] == nil; .index++ { } if .index < nodeCap { .current = .n.children[.index].iterator() } else { .current = nil } } func ( *arrayNodeIterator) () (interface{}, interface{}) { return .current.Elem() } func ( *arrayNodeIterator) () bool { return .current != nil } func ( *arrayNodeIterator) () { .current.Next() if !.current.HasElem() { .index++ .fixCurrent() } } var emptyBitmapNode = &bitmapNode{} type bitmapNode struct { bitmap uint32 entries []mapEntry } // mapEntry is a map entry. When used in a collisionNode, it is also an entry // with non-nil key. When used in a bitmapNode, it is also abused to represent // children when the key is nil. type mapEntry struct { key interface{} value interface{} } func (, uint32) uint32 { return ( >> ) & chunkMask } func (, uint32) uint32 { return 1 << chunk(, ) } func (, uint32) uint32 { return popCount( & ( - 1)) } const ( m1 uint32 = 0x55555555 m2 = 0x33333333 m4 = 0x0f0f0f0f m8 = 0x00ff00ff m16 = 0x0000ffff ) // TODO(xiaq): Use an optimized implementation. func ( uint32) uint32 { = ( & m1) + (( >> 1) & m1) = ( & m2) + (( >> 2) & m2) = ( & m4) + (( >> 4) & m4) = ( & m8) + (( >> 8) & m8) = ( & m16) + (( >> 16) & m16) return } func ( uint32, interface{}, interface{}, uint32, interface{}, interface{}, Hash, Equal) node { := () if == { return &collisionNode{, []mapEntry{{, }, {, }}} } , := emptyBitmapNode.assoc(, , , , , ) , _ = .assoc(, , , , , ) return } func ( *bitmapNode) (, uint32, node, Hash, Equal) *arrayNode { var arrayNode .nChildren = len(.entries) + 1 .children[] = := 0 for := uint(0); < nodeCap; ++ { if (.bitmap>>)&1 != 0 { := .entries[] ++ if .key == nil { .children[] = .value.(node) } else { .children[], _ = emptyBitmapNode.assoc( +chunkBits, (.key), .key, .value, , ) } } } return & } func ( *bitmapNode) (, uint32) *bitmapNode { if .bitmap == { return emptyBitmapNode } return &bitmapNode{.bitmap ^ , withoutEntry(.entries, )} } func ( []mapEntry, uint32) []mapEntry { := make([]mapEntry, len()-1) copy([:], [:]) copy([:], [+1:]) return } func ( *bitmapNode) ( uint32, mapEntry) *bitmapNode { return &bitmapNode{.bitmap, replaceEntry(.entries, , .key, .value)} } func ( []mapEntry, uint32, , interface{}) []mapEntry { := append([]mapEntry(nil), ...) [] = mapEntry{, } return } func ( *bitmapNode) (, uint32, , interface{}, Hash, Equal) (node, bool) { := bitpos(, ) := index(.bitmap, ) if .bitmap& == 0 { // Entry does not exist yet := len(.entries) if >= nodeCap/2 { // Unpack into an arrayNode , := emptyBitmapNode.(+chunkBits, , , , , ) return .unpack(, chunk(, ), , , ), true } // Add a new entry := make([]mapEntry, len(.entries)+1) copy([:], .entries[:]) [] = mapEntry{, } copy([+1:], .entries[:]) return &bitmapNode{.bitmap | , }, true } // Entry exists := .entries[] if .key == nil { // Non-leaf child := .value.(node) , := .assoc(+chunkBits, , , , , ) return .withReplacedEntry(, mapEntry{nil, }), } // Leaf if (, .key) { // Identical key, replace return .withReplacedEntry(, mapEntry{, }), false } // Create and insert new inner node := createNode(+chunkBits, .key, .value, , , , , ) return .withReplacedEntry(, mapEntry{nil, }), true } func ( *bitmapNode) (, uint32, interface{}, Equal) (node, bool) { := bitpos(, ) if .bitmap& == 0 { return , false } := index(.bitmap, ) := .entries[] if .key == nil { // Non-leaf child := .value.(node) , := .without(+chunkBits, , , ) if == { return , false } if == emptyBitmapNode { return .withoutEntry(, ), true } return .withReplacedEntry(, mapEntry{nil, }), } else if (.key, ) { // Leaf, and this is the entry to delete. return .withoutEntry(, ), true } // Nothing to delete. return , false } func ( *bitmapNode) (, uint32, interface{}, Equal) (interface{}, bool) { := bitpos(, ) if .bitmap& == 0 { return nil, false } := index(.bitmap, ) := .entries[] if .key == nil { := .value.(node) return .find(+chunkBits, , , ) } else if (.key, ) { return .value, true } return nil, false } func ( *bitmapNode) () Iterator { := &bitmapNodeIterator{, 0, nil} .fixCurrent() return } type bitmapNodeIterator struct { n *bitmapNode index int current Iterator } func ( *bitmapNodeIterator) () { if .index < len(.n.entries) { := .n.entries[.index] if .key == nil { .current = .value.(node).iterator() } else { .current = nil } } else { .current = nil } } func ( *bitmapNodeIterator) () (interface{}, interface{}) { if .current != nil { return .current.Elem() } := .n.entries[.index] return .key, .value } func ( *bitmapNodeIterator) () bool { return .index < len(.n.entries) } func ( *bitmapNodeIterator) () { if .current != nil { .current.Next() } if .current == nil || !.current.HasElem() { .index++ .fixCurrent() } } type collisionNode struct { hash uint32 entries []mapEntry } func ( *collisionNode) (, uint32, , interface{}, Hash, Equal) (node, bool) { if == .hash { := .findIndex(, ) if != -1 { return &collisionNode{ .hash, replaceEntry(.entries, uint32(), , )}, false } := make([]mapEntry, len(.entries)+1) copy([:len(.entries)], .entries[:]) [len(.entries)] = mapEntry{, } return &collisionNode{.hash, }, true } // Wrap in a bitmapNode and add the entry := bitmapNode{bitpos(, .hash), []mapEntry{{nil, }}} return .assoc(, , , , , ) } func ( *collisionNode) (, uint32, interface{}, Equal) (node, bool) { := .findIndex(, ) if == -1 { return , false } if len(.entries) == 1 { return emptyBitmapNode, true } return &collisionNode{.hash, withoutEntry(.entries, uint32())}, true } func ( *collisionNode) (, uint32, interface{}, Equal) (interface{}, bool) { := .findIndex(, ) if == -1 { return nil, false } return .entries[].value, true } func ( *collisionNode) ( interface{}, Equal) int { for , := range .entries { if (, .key) { return } } return -1 } func ( *collisionNode) () Iterator { return &collisionNodeIterator{, 0} } type collisionNodeIterator struct { n *collisionNode index int } func ( *collisionNodeIterator) () (interface{}, interface{}) { := .n.entries[.index] return .key, .value } func ( *collisionNodeIterator) () bool { return .index < len(.n.entries) } func ( *collisionNodeIterator) () { .index++ }