2735 lines
79 KiB
Go
2735 lines
79 KiB
Go
// Package immutable provides immutable collection types.
|
|
//
|
|
// Introduction
|
|
//
|
|
// Immutable collections provide an efficient, safe way to share collections
|
|
// of data while minimizing locks. The collections in this package provide
|
|
// List, Map, and SortedMap implementations. These act similarly to slices
|
|
// and maps, respectively, except that altering a collection returns a new
|
|
// copy of the collection with that change.
|
|
//
|
|
// Because collections are unable to change, they are safe for multiple
|
|
// goroutines to read from at the same time without a mutex. However, these
|
|
// types of collections come with increased CPU & memory usage as compared
|
|
// with Go's built-in collection types so please evaluate for your specific
|
|
// use.
|
|
//
|
|
// Collection Types
|
|
//
|
|
// The List type provides an API similar to Go slices. They allow appending,
|
|
// prepending, and updating of elements. Elements can also be fetched by index
|
|
// or iterated over using a ListIterator.
|
|
//
|
|
// The Map & SortedMap types provide an API similar to Go maps. They allow
|
|
// values to be assigned to unique keys and allow for the deletion of keys.
|
|
// Values can be fetched by key and key/value pairs can be iterated over using
|
|
// the appropriate iterator type. Both map types provide the same API. The
|
|
// SortedMap, however, provides iteration over sorted keys while the Map
|
|
// provides iteration over unsorted keys. Maps improved performance and memory
|
|
// usage as compared to SortedMaps.
|
|
//
|
|
// Hashing and Sorting
|
|
//
|
|
// Map types require the use of a Hasher implementation to calculate hashes for
|
|
// their keys and check for key equality. SortedMaps require the use of a
|
|
// Comparer implementation to sort keys in the map.
|
|
//
|
|
// These collection types automatically provide built-in hasher and comparers
|
|
// for int, string, and byte slice keys. If you are using one of these key types
|
|
// then simply pass a nil into the constructor. Otherwise you will need to
|
|
// implement a custom Hasher or Comparer type. Please see the provided
|
|
// implementations for reference.
|
|
package immutable
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"math/bits"
|
|
"reflect"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// List is a dense, ordered, indexed collections. They are analogous to slices
|
|
// in Go. They can be updated by appending to the end of the list, prepending
|
|
// values to the beginning of the list, or updating existing indexes in the
|
|
// list.
|
|
type List struct {
|
|
root listNode // root node
|
|
origin int // offset to zero index element
|
|
size int // total number of elements in use
|
|
}
|
|
|
|
// NewList returns a new empty instance of List.
|
|
func NewList() *List {
|
|
return &List{
|
|
root: &listLeafNode{},
|
|
}
|
|
}
|
|
|
|
// clone returns a copy of the list.
|
|
func (l *List) clone() *List {
|
|
other := *l
|
|
return &other
|
|
}
|
|
|
|
// Len returns the number of elements in the list.
|
|
func (l *List) Len() int {
|
|
return l.size
|
|
}
|
|
|
|
// cap returns the total number of possible elements for the current depth.
|
|
func (l *List) cap() int {
|
|
return 1 << (l.root.depth() * listNodeBits)
|
|
}
|
|
|
|
// Get returns the value at the given index. Similar to slices, this method will
|
|
// panic if index is below zero or is greater than or equal to the list size.
|
|
func (l *List) Get(index int) interface{} {
|
|
if index < 0 || index >= l.size {
|
|
panic(fmt.Sprintf("immutable.List.Get: index %d out of bounds", index))
|
|
}
|
|
return l.root.get(l.origin + index)
|
|
}
|
|
|
|
// Set returns a new list with value set at index. Similar to slices, this
|
|
// method will panic if index is below zero or if the index is greater than
|
|
// or equal to the list size.
|
|
func (l *List) Set(index int, value interface{}) *List {
|
|
return l.set(index, value, false)
|
|
}
|
|
|
|
func (l *List) set(index int, value interface{}, mutable bool) *List {
|
|
if index < 0 || index >= l.size {
|
|
panic(fmt.Sprintf("immutable.List.Set: index %d out of bounds", index))
|
|
}
|
|
other := l
|
|
if !mutable {
|
|
other = l.clone()
|
|
}
|
|
other.root = other.root.set(l.origin+index, value, mutable)
|
|
return other
|
|
}
|
|
|
|
// Append returns a new list with value added to the end of the list.
|
|
func (l *List) Append(value interface{}) *List {
|
|
return l.append(value, false)
|
|
}
|
|
|
|
func (l *List) append(value interface{}, mutable bool) *List {
|
|
other := l
|
|
if !mutable {
|
|
other = l.clone()
|
|
}
|
|
|
|
// Expand list to the right if no slots remain.
|
|
if other.size+other.origin >= l.cap() {
|
|
newRoot := &listBranchNode{d: other.root.depth() + 1}
|
|
newRoot.children[0] = other.root
|
|
other.root = newRoot
|
|
}
|
|
|
|
// Increase size and set the last element to the new value.
|
|
other.size++
|
|
other.root = other.root.set(other.origin+other.size-1, value, mutable)
|
|
return other
|
|
}
|
|
|
|
// Prepend returns a new list with value added to the beginning of the list.
|
|
func (l *List) Prepend(value interface{}) *List {
|
|
return l.prepend(value, false)
|
|
}
|
|
|
|
func (l *List) prepend(value interface{}, mutable bool) *List {
|
|
other := l
|
|
if !mutable {
|
|
other = l.clone()
|
|
}
|
|
|
|
// Expand list to the left if no slots remain.
|
|
if other.origin == 0 {
|
|
newRoot := &listBranchNode{d: other.root.depth() + 1}
|
|
newRoot.children[listNodeSize-1] = other.root
|
|
other.root = newRoot
|
|
other.origin += (listNodeSize - 1) << (other.root.depth() * listNodeBits)
|
|
}
|
|
|
|
// Increase size and move origin back. Update first element to value.
|
|
other.size++
|
|
other.origin--
|
|
other.root = other.root.set(other.origin, value, mutable)
|
|
return other
|
|
}
|
|
|
|
// Slice returns a new list of elements between start index and end index.
|
|
// Similar to slices, this method will panic if start or end are below zero or
|
|
// greater than the list size. A panic will also occur if start is greater than
|
|
// end.
|
|
//
|
|
// Unlike Go slices, references to inaccessible elements will be automatically
|
|
// removed so they can be garbage collected.
|
|
func (l *List) Slice(start, end int) *List {
|
|
return l.slice(start, end, false)
|
|
}
|
|
|
|
func (l *List) slice(start, end int, mutable bool) *List {
|
|
// Panics similar to Go slices.
|
|
if start < 0 || start > l.size {
|
|
panic(fmt.Sprintf("immutable.List.Slice: start index %d out of bounds", start))
|
|
} else if end < 0 || end > l.size {
|
|
panic(fmt.Sprintf("immutable.List.Slice: end index %d out of bounds", end))
|
|
} else if start > end {
|
|
panic(fmt.Sprintf("immutable.List.Slice: invalid slice index: [%d:%d]", start, end))
|
|
}
|
|
|
|
// Return the same list if the start and end are the entire range.
|
|
if start == 0 && end == l.size {
|
|
return l
|
|
}
|
|
|
|
// Create copy, if immutable.
|
|
other := l
|
|
if !mutable {
|
|
other = l.clone()
|
|
}
|
|
|
|
// Update origin/size.
|
|
other.origin = l.origin + start
|
|
other.size = end - start
|
|
|
|
// Contract tree while the start & end are in the same child node.
|
|
for other.root.depth() > 1 {
|
|
i := (other.origin >> (other.root.depth() * listNodeBits)) & listNodeMask
|
|
j := ((other.origin + other.size - 1) >> (other.root.depth() * listNodeBits)) & listNodeMask
|
|
if i != j {
|
|
break // branch contains at least two nodes, exit
|
|
}
|
|
|
|
// Replace the current root with the single child & update origin offset.
|
|
other.origin -= i << (other.root.depth() * listNodeBits)
|
|
other.root = other.root.(*listBranchNode).children[i]
|
|
}
|
|
|
|
// Ensure all references are removed before start & after end.
|
|
other.root = other.root.deleteBefore(other.origin, mutable)
|
|
other.root = other.root.deleteAfter(other.origin+other.size-1, mutable)
|
|
|
|
return other
|
|
}
|
|
|
|
// Iterator returns a new iterator for this list positioned at the first index.
|
|
func (l *List) Iterator() *ListIterator {
|
|
itr := &ListIterator{list: l}
|
|
itr.First()
|
|
return itr
|
|
}
|
|
|
|
// ListBuilder represents an efficient builder for creating new Lists.
|
|
type ListBuilder struct {
|
|
list *List // current state
|
|
}
|
|
|
|
// NewListBuilder returns a new instance of ListBuilder.
|
|
func NewListBuilder() *ListBuilder {
|
|
return &ListBuilder{list: NewList()}
|
|
}
|
|
|
|
// List returns the current copy of the list.
|
|
// The builder should not be used again after the list after this call.
|
|
func (b *ListBuilder) List() *List {
|
|
assert(b.list != nil, "immutable.ListBuilder.List(): duplicate call to fetch list")
|
|
list := b.list
|
|
b.list = nil
|
|
return list
|
|
}
|
|
|
|
// Len returns the number of elements in the underlying list.
|
|
func (b *ListBuilder) Len() int {
|
|
assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation")
|
|
return b.list.Len()
|
|
}
|
|
|
|
// Get returns the value at the given index. Similar to slices, this method will
|
|
// panic if index is below zero or is greater than or equal to the list size.
|
|
func (b *ListBuilder) Get(index int) interface{} {
|
|
assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation")
|
|
return b.list.Get(index)
|
|
}
|
|
|
|
// Set updates the value at the given index. Similar to slices, this method will
|
|
// panic if index is below zero or if the index is greater than or equal to the
|
|
// list size.
|
|
func (b *ListBuilder) Set(index int, value interface{}) {
|
|
assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation")
|
|
b.list = b.list.set(index, value, true)
|
|
}
|
|
|
|
// Append adds value to the end of the list.
|
|
func (b *ListBuilder) Append(value interface{}) {
|
|
assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation")
|
|
b.list = b.list.append(value, true)
|
|
}
|
|
|
|
// Prepend adds value to the beginning of the list.
|
|
func (b *ListBuilder) Prepend(value interface{}) {
|
|
assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation")
|
|
b.list = b.list.prepend(value, true)
|
|
}
|
|
|
|
// Slice updates the list with a sublist of elements between start and end index.
|
|
// See List.Slice() for more details.
|
|
func (b *ListBuilder) Slice(start, end int) {
|
|
assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation")
|
|
b.list = b.list.slice(start, end, true)
|
|
}
|
|
|
|
// Iterator returns a new iterator for the underlying list.
|
|
func (b *ListBuilder) Iterator() *ListIterator {
|
|
assert(b.list != nil, "immutable.ListBuilder: builder invalid after List() invocation")
|
|
return b.list.Iterator()
|
|
}
|
|
|
|
// Constants for bit shifts used for levels in the List trie.
|
|
const (
|
|
listNodeBits = 5
|
|
listNodeSize = 1 << listNodeBits
|
|
listNodeMask = listNodeSize - 1
|
|
)
|
|
|
|
// listNode represents either a branch or leaf node in a List.
|
|
type listNode interface {
|
|
depth() uint
|
|
get(index int) interface{}
|
|
set(index int, v interface{}, mutable bool) listNode
|
|
|
|
containsBefore(index int) bool
|
|
containsAfter(index int) bool
|
|
|
|
deleteBefore(index int, mutable bool) listNode
|
|
deleteAfter(index int, mutable bool) listNode
|
|
}
|
|
|
|
// newListNode returns a leaf node for depth zero, otherwise returns a branch node.
|
|
func newListNode(depth uint) listNode {
|
|
if depth == 0 {
|
|
return &listLeafNode{}
|
|
}
|
|
return &listBranchNode{d: depth}
|
|
}
|
|
|
|
// listBranchNode represents a branch of a List tree at a given depth.
|
|
type listBranchNode struct {
|
|
d uint // depth
|
|
children [listNodeSize]listNode
|
|
}
|
|
|
|
// depth returns the depth of this branch node from the leaf.
|
|
func (n *listBranchNode) depth() uint { return n.d }
|
|
|
|
// get returns the child node at the segment of the index for this depth.
|
|
func (n *listBranchNode) get(index int) interface{} {
|
|
idx := (index >> (n.d * listNodeBits)) & listNodeMask
|
|
return n.children[idx].get(index)
|
|
}
|
|
|
|
// set recursively updates the value at index for each lower depth from the node.
|
|
func (n *listBranchNode) set(index int, v interface{}, mutable bool) listNode {
|
|
idx := (index >> (n.d * listNodeBits)) & listNodeMask
|
|
|
|
// Find child for the given value in the branch. Create new if it doesn't exist.
|
|
child := n.children[idx]
|
|
if child == nil {
|
|
child = newListNode(n.depth() - 1)
|
|
}
|
|
|
|
// Return a copy of this branch with the new child.
|
|
var other *listBranchNode
|
|
if mutable {
|
|
other = n
|
|
} else {
|
|
tmp := *n
|
|
other = &tmp
|
|
}
|
|
other.children[idx] = child.set(index, v, mutable)
|
|
return other
|
|
}
|
|
|
|
// containsBefore returns true if non-nil values exists between [0,index).
|
|
func (n *listBranchNode) containsBefore(index int) bool {
|
|
idx := (index >> (n.d * listNodeBits)) & listNodeMask
|
|
|
|
// Quickly check if any direct children exist before this segment of the index.
|
|
for i := 0; i < idx; i++ {
|
|
if n.children[i] != nil {
|
|
return true
|
|
}
|
|
}
|
|
|
|
// Recursively check for children directly at the given index at this segment.
|
|
if n.children[idx] != nil && n.children[idx].containsBefore(index) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// containsAfter returns true if non-nil values exists between (index,listNodeSize).
|
|
func (n *listBranchNode) containsAfter(index int) bool {
|
|
idx := (index >> (n.d * listNodeBits)) & listNodeMask
|
|
|
|
// Quickly check if any direct children exist after this segment of the index.
|
|
for i := idx + 1; i < len(n.children); i++ {
|
|
if n.children[i] != nil {
|
|
return true
|
|
}
|
|
}
|
|
|
|
// Recursively check for children directly at the given index at this segment.
|
|
if n.children[idx] != nil && n.children[idx].containsAfter(index) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// deleteBefore returns a new node with all elements before index removed.
|
|
func (n *listBranchNode) deleteBefore(index int, mutable bool) listNode {
|
|
// Ignore if no nodes exist before the given index.
|
|
if !n.containsBefore(index) {
|
|
return n
|
|
}
|
|
|
|
// Return a copy with any nodes prior to the index removed.
|
|
idx := (index >> (n.d * listNodeBits)) & listNodeMask
|
|
|
|
var other *listBranchNode
|
|
if mutable {
|
|
other = n
|
|
for i := 0; i < idx; i++ {
|
|
n.children[i] = nil
|
|
}
|
|
} else {
|
|
other = &listBranchNode{d: n.d}
|
|
copy(other.children[idx:][:], n.children[idx:][:])
|
|
}
|
|
|
|
if other.children[idx] != nil {
|
|
other.children[idx] = other.children[idx].deleteBefore(index, mutable)
|
|
}
|
|
return other
|
|
}
|
|
|
|
// deleteBefore returns a new node with all elements before index removed.
|
|
func (n *listBranchNode) deleteAfter(index int, mutable bool) listNode {
|
|
// Ignore if no nodes exist after the given index.
|
|
if !n.containsAfter(index) {
|
|
return n
|
|
}
|
|
|
|
// Return a copy with any nodes after the index removed.
|
|
idx := (index >> (n.d * listNodeBits)) & listNodeMask
|
|
|
|
var other *listBranchNode
|
|
if mutable {
|
|
other = n
|
|
for i := idx + 1; i < len(n.children); i++ {
|
|
n.children[i] = nil
|
|
}
|
|
} else {
|
|
other = &listBranchNode{d: n.d}
|
|
copy(other.children[:idx+1], n.children[:idx+1])
|
|
}
|
|
|
|
if other.children[idx] != nil {
|
|
other.children[idx] = other.children[idx].deleteAfter(index, mutable)
|
|
}
|
|
return other
|
|
}
|
|
|
|
// listLeafNode represents a leaf node in a List.
|
|
type listLeafNode struct {
|
|
children [listNodeSize]interface{}
|
|
}
|
|
|
|
// depth always returns 0 for leaf nodes.
|
|
func (n *listLeafNode) depth() uint { return 0 }
|
|
|
|
// get returns the value at the given index.
|
|
func (n *listLeafNode) get(index int) interface{} {
|
|
return n.children[index&listNodeMask]
|
|
}
|
|
|
|
// set returns a copy of the node with the value at the index updated to v.
|
|
func (n *listLeafNode) set(index int, v interface{}, mutable bool) listNode {
|
|
idx := index & listNodeMask
|
|
var other *listLeafNode
|
|
if mutable {
|
|
other = n
|
|
} else {
|
|
tmp := *n
|
|
other = &tmp
|
|
}
|
|
other.children[idx] = v
|
|
return other
|
|
}
|
|
|
|
// containsBefore returns true if non-nil values exists between [0,index).
|
|
func (n *listLeafNode) containsBefore(index int) bool {
|
|
idx := index & listNodeMask
|
|
for i := 0; i < idx; i++ {
|
|
if n.children[i] != nil {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// containsAfter returns true if non-nil values exists between (index,listNodeSize).
|
|
func (n *listLeafNode) containsAfter(index int) bool {
|
|
idx := index & listNodeMask
|
|
for i := idx + 1; i < len(n.children); i++ {
|
|
if n.children[i] != nil {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// deleteBefore returns a new node with all elements before index removed.
|
|
func (n *listLeafNode) deleteBefore(index int, mutable bool) listNode {
|
|
if !n.containsBefore(index) {
|
|
return n
|
|
}
|
|
|
|
idx := index & listNodeMask
|
|
var other *listLeafNode
|
|
if mutable {
|
|
other = n
|
|
for i := 0; i < idx; i++ {
|
|
other.children[i] = nil
|
|
}
|
|
} else {
|
|
other = &listLeafNode{}
|
|
copy(other.children[idx:][:], n.children[idx:][:])
|
|
}
|
|
return other
|
|
}
|
|
|
|
// deleteBefore returns a new node with all elements before index removed.
|
|
func (n *listLeafNode) deleteAfter(index int, mutable bool) listNode {
|
|
if !n.containsAfter(index) {
|
|
return n
|
|
}
|
|
|
|
idx := index & listNodeMask
|
|
var other *listLeafNode
|
|
if mutable {
|
|
other = n
|
|
for i := idx + 1; i < len(n.children); i++ {
|
|
other.children[i] = nil
|
|
}
|
|
} else {
|
|
other = &listLeafNode{}
|
|
copy(other.children[:idx+1][:], n.children[:idx+1][:])
|
|
}
|
|
return other
|
|
}
|
|
|
|
// ListIterator represents an ordered iterator over a list.
|
|
type ListIterator struct {
|
|
list *List // source list
|
|
index int // current index position
|
|
|
|
stack [32]listIteratorElem // search stack
|
|
depth int // stack depth
|
|
}
|
|
|
|
// Done returns true if no more elements remain in the iterator.
|
|
func (itr *ListIterator) Done() bool {
|
|
return itr.index < 0 || itr.index >= itr.list.Len()
|
|
}
|
|
|
|
// First positions the iterator on the first index.
|
|
// If source list is empty then no change is made.
|
|
func (itr *ListIterator) First() {
|
|
if itr.list.Len() != 0 {
|
|
itr.Seek(0)
|
|
}
|
|
}
|
|
|
|
// Last positions the iterator on the last index.
|
|
// If source list is empty then no change is made.
|
|
func (itr *ListIterator) Last() {
|
|
if n := itr.list.Len(); n != 0 {
|
|
itr.Seek(n - 1)
|
|
}
|
|
}
|
|
|
|
// Seek moves the iterator position to the given index in the list.
|
|
// Similar to Go slices, this method will panic if index is below zero or if
|
|
// the index is greater than or equal to the list size.
|
|
func (itr *ListIterator) Seek(index int) {
|
|
// Panic similar to Go slices.
|
|
if index < 0 || index >= itr.list.Len() {
|
|
panic(fmt.Sprintf("immutable.ListIterator.Seek: index %d out of bounds", index))
|
|
}
|
|
itr.index = index
|
|
|
|
// Reset to the bottom of the stack at seek to the correct position.
|
|
itr.stack[0] = listIteratorElem{node: itr.list.root}
|
|
itr.depth = 0
|
|
itr.seek(index)
|
|
}
|
|
|
|
// Next returns the current index and its value & moves the iterator forward.
|
|
// Returns an index of -1 if the there are no more elements to return.
|
|
func (itr *ListIterator) Next() (index int, value interface{}) {
|
|
// Exit immediately if there are no elements remaining.
|
|
if itr.Done() {
|
|
return -1, nil
|
|
}
|
|
|
|
// Retrieve current index & value.
|
|
elem := &itr.stack[itr.depth]
|
|
index, value = itr.index, elem.node.(*listLeafNode).children[elem.index]
|
|
|
|
// Increase index. If index is at the end then return immediately.
|
|
itr.index++
|
|
if itr.Done() {
|
|
return index, value
|
|
}
|
|
|
|
// Move up stack until we find a node that has remaining position ahead.
|
|
for ; itr.depth > 0 && itr.stack[itr.depth].index >= listNodeSize-1; itr.depth-- {
|
|
}
|
|
|
|
// Seek to correct position from current depth.
|
|
itr.seek(itr.index)
|
|
|
|
return index, value
|
|
}
|
|
|
|
// Prev returns the current index and value and moves the iterator backward.
|
|
// Returns an index of -1 if the there are no more elements to return.
|
|
func (itr *ListIterator) Prev() (index int, value interface{}) {
|
|
// Exit immediately if there are no elements remaining.
|
|
if itr.Done() {
|
|
return -1, nil
|
|
}
|
|
|
|
// Retrieve current index & value.
|
|
elem := &itr.stack[itr.depth]
|
|
index, value = itr.index, elem.node.(*listLeafNode).children[elem.index]
|
|
|
|
// Decrease index. If index is past the beginning then return immediately.
|
|
itr.index--
|
|
if itr.Done() {
|
|
return index, value
|
|
}
|
|
|
|
// Move up stack until we find a node that has remaining position behind.
|
|
for ; itr.depth > 0 && itr.stack[itr.depth].index == 0; itr.depth-- {
|
|
}
|
|
|
|
// Seek to correct position from current depth.
|
|
itr.seek(itr.index)
|
|
|
|
return index, value
|
|
}
|
|
|
|
// seek positions the stack to the given index from the current depth.
|
|
// Elements and indexes below the current depth are assumed to be correct.
|
|
func (itr *ListIterator) seek(index int) {
|
|
// Iterate over each level until we reach a leaf node.
|
|
for {
|
|
elem := &itr.stack[itr.depth]
|
|
elem.index = ((itr.list.origin + index) >> (elem.node.depth() * listNodeBits)) & listNodeMask
|
|
|
|
switch node := elem.node.(type) {
|
|
case *listBranchNode:
|
|
child := node.children[elem.index]
|
|
itr.stack[itr.depth+1] = listIteratorElem{node: child}
|
|
itr.depth++
|
|
case *listLeafNode:
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// listIteratorElem represents the node and it's child index within the stack.
|
|
type listIteratorElem struct {
|
|
node listNode
|
|
index int
|
|
}
|
|
|
|
// Size thresholds for each type of branch node.
|
|
const (
|
|
maxArrayMapSize = 8
|
|
maxBitmapIndexedSize = 16
|
|
)
|
|
|
|
// Segment bit shifts within the map tree.
|
|
const (
|
|
mapNodeBits = 5
|
|
mapNodeSize = 1 << mapNodeBits
|
|
mapNodeMask = mapNodeSize - 1
|
|
)
|
|
|
|
// Map represents an immutable hash map implementation. The map uses a Hasher
|
|
// to generate hashes and check for equality of key values.
|
|
//
|
|
// It is implemented as an Hash Array Mapped Trie.
|
|
type Map struct {
|
|
size int // total number of key/value pairs
|
|
root mapNode // root node of trie
|
|
hasher Hasher // hasher implementation
|
|
}
|
|
|
|
// NewMap returns a new instance of Map. If hasher is nil, a default hasher
|
|
// implementation will automatically be chosen based on the first key added.
|
|
// Default hasher implementations only exist for int, string, and byte slice types.
|
|
func NewMap(hasher Hasher) *Map {
|
|
return &Map{
|
|
hasher: hasher,
|
|
}
|
|
}
|
|
|
|
// Len returns the number of elements in the map.
|
|
func (m *Map) Len() int {
|
|
return m.size
|
|
}
|
|
|
|
// clone returns a shallow copy of m.
|
|
func (m *Map) clone() *Map {
|
|
other := *m
|
|
return &other
|
|
}
|
|
|
|
// Get returns the value for a given key and a flag indicating whether the
|
|
// key exists. This flag distinguishes a nil value set on a key versus a
|
|
// non-existent key in the map.
|
|
func (m *Map) Get(key interface{}) (value interface{}, ok bool) {
|
|
if m.root == nil {
|
|
return nil, false
|
|
}
|
|
keyHash := m.hasher.Hash(key)
|
|
return m.root.get(key, 0, keyHash, m.hasher)
|
|
}
|
|
|
|
// Set returns a map with the key set to the new value. A nil value is allowed.
|
|
//
|
|
// This function will return a new map even if the updated value is the same as
|
|
// the existing value because Map does not track value equality.
|
|
func (m *Map) Set(key, value interface{}) *Map {
|
|
return m.set(key, value, false)
|
|
}
|
|
|
|
func (m *Map) set(key, value interface{}, mutable bool) *Map {
|
|
// Set a hasher on the first value if one does not already exist.
|
|
hasher := m.hasher
|
|
if hasher == nil {
|
|
hasher = NewHasher(key)
|
|
}
|
|
|
|
// Generate copy if necessary.
|
|
other := m
|
|
if !mutable {
|
|
other = m.clone()
|
|
}
|
|
other.hasher = hasher
|
|
|
|
// If the map is empty, initialize with a simple array node.
|
|
if m.root == nil {
|
|
other.size = 1
|
|
other.root = &mapArrayNode{entries: []mapEntry{{key: key, value: value}}}
|
|
return other
|
|
}
|
|
|
|
// Otherwise copy the map and delegate insertion to the root.
|
|
// Resized will return true if the key does not currently exist.
|
|
var resized bool
|
|
other.root = m.root.set(key, value, 0, hasher.Hash(key), hasher, mutable, &resized)
|
|
if resized {
|
|
other.size++
|
|
}
|
|
return other
|
|
}
|
|
|
|
// Delete returns a map with the given key removed.
|
|
// Removing a non-existent key will cause this method to return the same map.
|
|
func (m *Map) Delete(key interface{}) *Map {
|
|
return m.delete(key, false)
|
|
}
|
|
|
|
func (m *Map) delete(key interface{}, mutable bool) *Map {
|
|
// Return original map if no keys exist.
|
|
if m.root == nil {
|
|
return m
|
|
}
|
|
|
|
// If the delete did not change the node then return the original map.
|
|
var resized bool
|
|
newRoot := m.root.delete(key, 0, m.hasher.Hash(key), m.hasher, mutable, &resized)
|
|
if !resized {
|
|
return m
|
|
}
|
|
|
|
// Generate copy if necessary.
|
|
other := m
|
|
if !mutable {
|
|
other = m.clone()
|
|
}
|
|
|
|
// Return copy of map with new root and decreased size.
|
|
other.size = m.size - 1
|
|
other.root = newRoot
|
|
return other
|
|
}
|
|
|
|
// Iterator returns a new iterator for the map.
|
|
func (m *Map) Iterator() *MapIterator {
|
|
itr := &MapIterator{m: m}
|
|
itr.First()
|
|
return itr
|
|
}
|
|
|
|
// MapBuilder represents an efficient builder for creating Maps.
|
|
type MapBuilder struct {
|
|
m *Map // current state
|
|
}
|
|
|
|
// NewMapBuilder returns a new instance of MapBuilder.
|
|
func NewMapBuilder(hasher Hasher) *MapBuilder {
|
|
return &MapBuilder{m: NewMap(hasher)}
|
|
}
|
|
|
|
// Map returns the underlying map. Only call once.
|
|
// Builder is invalid after call. Will panic on second invocation.
|
|
func (b *MapBuilder) Map() *Map {
|
|
assert(b.m != nil, "immutable.SortedMapBuilder.Map(): duplicate call to fetch map")
|
|
m := b.m
|
|
b.m = nil
|
|
return m
|
|
}
|
|
|
|
// Len returns the number of elements in the underlying map.
|
|
func (b *MapBuilder) Len() int {
|
|
assert(b.m != nil, "immutable.MapBuilder: builder invalid after Map() invocation")
|
|
return b.m.Len()
|
|
}
|
|
|
|
// Get returns the value for the given key.
|
|
func (b *MapBuilder) Get(key interface{}) (value interface{}, ok bool) {
|
|
assert(b.m != nil, "immutable.MapBuilder: builder invalid after Map() invocation")
|
|
return b.m.Get(key)
|
|
}
|
|
|
|
// Set sets the value of the given key. See Map.Set() for additional details.
|
|
func (b *MapBuilder) Set(key, value interface{}) {
|
|
assert(b.m != nil, "immutable.MapBuilder: builder invalid after Map() invocation")
|
|
b.m = b.m.set(key, value, true)
|
|
}
|
|
|
|
// Delete removes the given key. See Map.Delete() for additional details.
|
|
func (b *MapBuilder) Delete(key interface{}) {
|
|
assert(b.m != nil, "immutable.MapBuilder: builder invalid after Map() invocation")
|
|
b.m = b.m.delete(key, true)
|
|
}
|
|
|
|
// Iterator returns a new iterator for the underlying map.
|
|
func (b *MapBuilder) Iterator() *MapIterator {
|
|
assert(b.m != nil, "immutable.MapBuilder: builder invalid after Map() invocation")
|
|
return b.m.Iterator()
|
|
}
|
|
|
|
// mapNode represents any node in the map tree.
|
|
type mapNode interface {
|
|
get(key interface{}, shift uint, keyHash uint32, h Hasher) (value interface{}, ok bool)
|
|
set(key, value interface{}, shift uint, keyHash uint32, h Hasher, mutable bool, resized *bool) mapNode
|
|
delete(key interface{}, shift uint, keyHash uint32, h Hasher, mutable bool, resized *bool) mapNode
|
|
}
|
|
|
|
var _ mapNode = (*mapArrayNode)(nil)
|
|
var _ mapNode = (*mapBitmapIndexedNode)(nil)
|
|
var _ mapNode = (*mapHashArrayNode)(nil)
|
|
var _ mapNode = (*mapValueNode)(nil)
|
|
var _ mapNode = (*mapHashCollisionNode)(nil)
|
|
|
|
// mapLeafNode represents a node that stores a single key hash at the leaf of the map tree.
|
|
type mapLeafNode interface {
|
|
mapNode
|
|
keyHashValue() uint32
|
|
}
|
|
|
|
var _ mapLeafNode = (*mapValueNode)(nil)
|
|
var _ mapLeafNode = (*mapHashCollisionNode)(nil)
|
|
|
|
// mapArrayNode is a map node that stores key/value pairs in a slice.
|
|
// Entries are stored in insertion order. An array node expands into a bitmap
|
|
// indexed node once a given threshold size is crossed.
|
|
type mapArrayNode struct {
|
|
entries []mapEntry
|
|
}
|
|
|
|
// indexOf returns the entry index of the given key. Returns -1 if key not found.
|
|
func (n *mapArrayNode) indexOf(key interface{}, h Hasher) int {
|
|
for i := range n.entries {
|
|
if h.Equal(n.entries[i].key, key) {
|
|
return i
|
|
}
|
|
}
|
|
return -1
|
|
}
|
|
|
|
// get returns the value for the given key.
|
|
func (n *mapArrayNode) get(key interface{}, shift uint, keyHash uint32, h Hasher) (value interface{}, ok bool) {
|
|
i := n.indexOf(key, h)
|
|
if i == -1 {
|
|
return nil, false
|
|
}
|
|
return n.entries[i].value, true
|
|
}
|
|
|
|
// set inserts or updates the value for a given key. If the key is inserted and
|
|
// the new size crosses the max size threshold, a bitmap indexed node is returned.
|
|
func (n *mapArrayNode) set(key, value interface{}, shift uint, keyHash uint32, h Hasher, mutable bool, resized *bool) mapNode {
|
|
idx := n.indexOf(key, h)
|
|
|
|
// Mark as resized if the key doesn't exist.
|
|
if idx == -1 {
|
|
*resized = true
|
|
}
|
|
|
|
// If we are adding and it crosses the max size threshold, expand the node.
|
|
// We do this by continually setting the entries to a value node and expanding.
|
|
if idx == -1 && len(n.entries) >= maxArrayMapSize {
|
|
var node mapNode = newMapValueNode(h.Hash(key), key, value)
|
|
for _, entry := range n.entries {
|
|
node = node.set(entry.key, entry.value, 0, h.Hash(entry.key), h, false, resized)
|
|
}
|
|
return node
|
|
}
|
|
|
|
// Update in-place if mutable.
|
|
if mutable {
|
|
if idx != -1 {
|
|
n.entries[idx] = mapEntry{key, value}
|
|
} else {
|
|
n.entries = append(n.entries, mapEntry{key, value})
|
|
}
|
|
return n
|
|
}
|
|
|
|
// Update existing entry if a match is found.
|
|
// Otherwise append to the end of the element list if it doesn't exist.
|
|
var other mapArrayNode
|
|
if idx != -1 {
|
|
other.entries = make([]mapEntry, len(n.entries))
|
|
copy(other.entries, n.entries)
|
|
other.entries[idx] = mapEntry{key, value}
|
|
} else {
|
|
other.entries = make([]mapEntry, len(n.entries)+1)
|
|
copy(other.entries, n.entries)
|
|
other.entries[len(other.entries)-1] = mapEntry{key, value}
|
|
}
|
|
return &other
|
|
}
|
|
|
|
// delete removes the given key from the node. Returns the same node if key does
|
|
// not exist. Returns a nil node when removing the last entry.
|
|
func (n *mapArrayNode) delete(key interface{}, shift uint, keyHash uint32, h Hasher, mutable bool, resized *bool) mapNode {
|
|
idx := n.indexOf(key, h)
|
|
|
|
// Return original node if key does not exist.
|
|
if idx == -1 {
|
|
return n
|
|
}
|
|
*resized = true
|
|
|
|
// Return nil if this node will contain no nodes.
|
|
if len(n.entries) == 1 {
|
|
return nil
|
|
}
|
|
|
|
// Update in-place, if mutable.
|
|
if mutable {
|
|
copy(n.entries[idx:], n.entries[idx+1:])
|
|
n.entries[len(n.entries)-1] = mapEntry{}
|
|
n.entries = n.entries[:len(n.entries)-1]
|
|
return n
|
|
}
|
|
|
|
// Otherwise create a copy with the given entry removed.
|
|
other := &mapArrayNode{entries: make([]mapEntry, len(n.entries)-1)}
|
|
copy(other.entries[:idx], n.entries[:idx])
|
|
copy(other.entries[idx:], n.entries[idx+1:])
|
|
return other
|
|
}
|
|
|
|
// mapBitmapIndexedNode represents a map branch node with a variable number of
|
|
// node slots and indexed using a bitmap. Indexes for the node slots are
|
|
// calculated by counting the number of set bits before the target bit using popcount.
|
|
type mapBitmapIndexedNode struct {
|
|
bitmap uint32
|
|
nodes []mapNode
|
|
}
|
|
|
|
// get returns the value for the given key.
|
|
func (n *mapBitmapIndexedNode) get(key interface{}, shift uint, keyHash uint32, h Hasher) (value interface{}, ok bool) {
|
|
bit := uint32(1) << ((keyHash >> shift) & mapNodeMask)
|
|
if (n.bitmap & bit) == 0 {
|
|
return nil, false
|
|
}
|
|
child := n.nodes[bits.OnesCount32(n.bitmap&(bit-1))]
|
|
return child.get(key, shift+mapNodeBits, keyHash, h)
|
|
}
|
|
|
|
// set inserts or updates the value for the given key. If a new key is inserted
|
|
// and the size crosses the max size threshold then a hash array node is returned.
|
|
func (n *mapBitmapIndexedNode) set(key, value interface{}, shift uint, keyHash uint32, h Hasher, mutable bool, resized *bool) mapNode {
|
|
// Extract the index for the bit segment of the key hash.
|
|
keyHashFrag := (keyHash >> shift) & mapNodeMask
|
|
|
|
// Determine the bit based on the hash index.
|
|
bit := uint32(1) << keyHashFrag
|
|
exists := (n.bitmap & bit) != 0
|
|
|
|
// Mark as resized if the key doesn't exist.
|
|
if !exists {
|
|
*resized = true
|
|
}
|
|
|
|
// Find index of node based on popcount of bits before it.
|
|
idx := bits.OnesCount32(n.bitmap & (bit - 1))
|
|
|
|
// If the node already exists, delegate set operation to it.
|
|
// If the node doesn't exist then create a simple value leaf node.
|
|
var newNode mapNode
|
|
if exists {
|
|
newNode = n.nodes[idx].set(key, value, shift+mapNodeBits, keyHash, h, mutable, resized)
|
|
} else {
|
|
newNode = newMapValueNode(keyHash, key, value)
|
|
}
|
|
|
|
// Convert to a hash-array node once we exceed the max bitmap size.
|
|
// Copy each node based on their bit position within the bitmap.
|
|
if !exists && len(n.nodes) > maxBitmapIndexedSize {
|
|
var other mapHashArrayNode
|
|
for i := uint(0); i < uint(len(other.nodes)); i++ {
|
|
if n.bitmap&(uint32(1)<<i) != 0 {
|
|
other.nodes[i] = n.nodes[other.count]
|
|
other.count++
|
|
}
|
|
}
|
|
other.nodes[keyHashFrag] = newNode
|
|
other.count++
|
|
return &other
|
|
}
|
|
|
|
// Update in-place if mutable.
|
|
if mutable {
|
|
if exists {
|
|
n.nodes[idx] = newNode
|
|
} else {
|
|
n.bitmap |= bit
|
|
n.nodes = append(n.nodes, nil)
|
|
copy(n.nodes[idx+1:], n.nodes[idx:])
|
|
n.nodes[idx] = newNode
|
|
}
|
|
return n
|
|
}
|
|
|
|
// If node exists at given slot then overwrite it with new node.
|
|
// Otherwise expand the node list and insert new node into appropriate position.
|
|
other := &mapBitmapIndexedNode{bitmap: n.bitmap | bit}
|
|
if exists {
|
|
other.nodes = make([]mapNode, len(n.nodes))
|
|
copy(other.nodes, n.nodes)
|
|
other.nodes[idx] = newNode
|
|
} else {
|
|
other.nodes = make([]mapNode, len(n.nodes)+1)
|
|
copy(other.nodes, n.nodes[:idx])
|
|
other.nodes[idx] = newNode
|
|
copy(other.nodes[idx+1:], n.nodes[idx:])
|
|
}
|
|
return other
|
|
}
|
|
|
|
// delete removes the key from the tree. If the key does not exist then the
|
|
// original node is returned. If removing the last child node then a nil is
|
|
// returned. Note that shrinking the node will not convert it to an array node.
|
|
func (n *mapBitmapIndexedNode) delete(key interface{}, shift uint, keyHash uint32, h Hasher, mutable bool, resized *bool) mapNode {
|
|
bit := uint32(1) << ((keyHash >> shift) & mapNodeMask)
|
|
|
|
// Return original node if key does not exist.
|
|
if (n.bitmap & bit) == 0 {
|
|
return n
|
|
}
|
|
|
|
// Find index of node based on popcount of bits before it.
|
|
idx := bits.OnesCount32(n.bitmap & (bit - 1))
|
|
|
|
// Delegate delete to child node.
|
|
child := n.nodes[idx]
|
|
newChild := child.delete(key, shift+mapNodeBits, keyHash, h, mutable, resized)
|
|
|
|
// Return original node if key doesn't exist in child.
|
|
if !*resized {
|
|
return n
|
|
}
|
|
|
|
// Remove if returned child has been deleted.
|
|
if newChild == nil {
|
|
// If we won't have any children then return nil.
|
|
if len(n.nodes) == 1 {
|
|
return nil
|
|
}
|
|
|
|
// Update in-place if mutable.
|
|
if mutable {
|
|
n.bitmap ^= bit
|
|
copy(n.nodes[idx:], n.nodes[idx+1:])
|
|
n.nodes[len(n.nodes)-1] = nil
|
|
n.nodes = n.nodes[:len(n.nodes)-1]
|
|
return n
|
|
}
|
|
|
|
// Return copy with bit removed from bitmap and node removed from node list.
|
|
other := &mapBitmapIndexedNode{bitmap: n.bitmap ^ bit, nodes: make([]mapNode, len(n.nodes)-1)}
|
|
copy(other.nodes[:idx], n.nodes[:idx])
|
|
copy(other.nodes[idx:], n.nodes[idx+1:])
|
|
return other
|
|
}
|
|
|
|
// Generate copy, if necessary.
|
|
other := n
|
|
if !mutable {
|
|
other = &mapBitmapIndexedNode{bitmap: n.bitmap, nodes: make([]mapNode, len(n.nodes))}
|
|
copy(other.nodes, n.nodes)
|
|
}
|
|
|
|
// Update child.
|
|
other.nodes[idx] = newChild
|
|
return other
|
|
}
|
|
|
|
// mapHashArrayNode is a map branch node that stores nodes in a fixed length
|
|
// array. Child nodes are indexed by their index bit segment for the current depth.
|
|
type mapHashArrayNode struct {
|
|
count uint // number of set nodes
|
|
nodes [mapNodeSize]mapNode // child node slots, may contain empties
|
|
}
|
|
|
|
// clone returns a shallow copy of n.
|
|
func (n *mapHashArrayNode) clone() *mapHashArrayNode {
|
|
other := *n
|
|
return &other
|
|
}
|
|
|
|
// get returns the value for the given key.
|
|
func (n *mapHashArrayNode) get(key interface{}, shift uint, keyHash uint32, h Hasher) (value interface{}, ok bool) {
|
|
node := n.nodes[(keyHash>>shift)&mapNodeMask]
|
|
if node == nil {
|
|
return nil, false
|
|
}
|
|
return node.get(key, shift+mapNodeBits, keyHash, h)
|
|
}
|
|
|
|
// set returns a node with the value set for the given key.
|
|
func (n *mapHashArrayNode) set(key, value interface{}, shift uint, keyHash uint32, h Hasher, mutable bool, resized *bool) mapNode {
|
|
idx := (keyHash >> shift) & mapNodeMask
|
|
node := n.nodes[idx]
|
|
|
|
// If node at index doesn't exist, create a simple value leaf node.
|
|
// Otherwise delegate set to child node.
|
|
var newNode mapNode
|
|
if node == nil {
|
|
*resized = true
|
|
newNode = newMapValueNode(keyHash, key, value)
|
|
} else {
|
|
newNode = node.set(key, value, shift+mapNodeBits, keyHash, h, mutable, resized)
|
|
}
|
|
|
|
// Generate copy, if necessary.
|
|
other := n
|
|
if !mutable {
|
|
other = n.clone()
|
|
}
|
|
|
|
// Update child node (and update size, if new).
|
|
if node == nil {
|
|
other.count++
|
|
}
|
|
other.nodes[idx] = newNode
|
|
return other
|
|
}
|
|
|
|
// delete returns a node with the given key removed. Returns the same node if
|
|
// the key does not exist. If node shrinks to within bitmap-indexed size then
|
|
// converts to a bitmap-indexed node.
|
|
func (n *mapHashArrayNode) delete(key interface{}, shift uint, keyHash uint32, h Hasher, mutable bool, resized *bool) mapNode {
|
|
idx := (keyHash >> shift) & mapNodeMask
|
|
node := n.nodes[idx]
|
|
|
|
// Return original node if child is not found.
|
|
if node == nil {
|
|
return n
|
|
}
|
|
|
|
// Return original node if child is unchanged.
|
|
newNode := node.delete(key, shift+mapNodeBits, keyHash, h, mutable, resized)
|
|
if !*resized {
|
|
return n
|
|
}
|
|
|
|
// If we remove a node and drop below a threshold, convert back to bitmap indexed node.
|
|
if newNode == nil && n.count <= maxBitmapIndexedSize {
|
|
other := &mapBitmapIndexedNode{nodes: make([]mapNode, 0, n.count-1)}
|
|
for i, child := range n.nodes {
|
|
if child != nil && uint32(i) != idx {
|
|
other.bitmap |= 1 << uint(i)
|
|
other.nodes = append(other.nodes, child)
|
|
}
|
|
}
|
|
return other
|
|
}
|
|
|
|
// Generate copy, if necessary.
|
|
other := n
|
|
if !mutable {
|
|
other = n.clone()
|
|
}
|
|
|
|
// Return copy of node with child updated.
|
|
other.nodes[idx] = newNode
|
|
if newNode == nil {
|
|
other.count--
|
|
}
|
|
return other
|
|
}
|
|
|
|
// mapValueNode represents a leaf node with a single key/value pair.
|
|
// A value node can be converted to a hash collision leaf node if a different
|
|
// key with the same keyHash is inserted.
|
|
type mapValueNode struct {
|
|
keyHash uint32
|
|
key interface{}
|
|
value interface{}
|
|
}
|
|
|
|
// newMapValueNode returns a new instance of mapValueNode.
|
|
func newMapValueNode(keyHash uint32, key, value interface{}) *mapValueNode {
|
|
return &mapValueNode{
|
|
keyHash: keyHash,
|
|
key: key,
|
|
value: value,
|
|
}
|
|
}
|
|
|
|
// keyHashValue returns the key hash for this node.
|
|
func (n *mapValueNode) keyHashValue() uint32 {
|
|
return n.keyHash
|
|
}
|
|
|
|
// get returns the value for the given key.
|
|
func (n *mapValueNode) get(key interface{}, shift uint, keyHash uint32, h Hasher) (value interface{}, ok bool) {
|
|
if !h.Equal(n.key, key) {
|
|
return nil, false
|
|
}
|
|
return n.value, true
|
|
}
|
|
|
|
// set returns a new node with the new value set for the key. If the key equals
|
|
// the node's key then a new value node is returned. If key is not equal to the
|
|
// node's key but has the same hash then a hash collision node is returned.
|
|
// Otherwise the nodes are merged into a branch node.
|
|
func (n *mapValueNode) set(key, value interface{}, shift uint, keyHash uint32, h Hasher, mutable bool, resized *bool) mapNode {
|
|
// If the keys match then return a new value node overwriting the value.
|
|
if h.Equal(n.key, key) {
|
|
// Update in-place if mutable.
|
|
if mutable {
|
|
n.value = value
|
|
return n
|
|
}
|
|
// Otherwise return a new copy.
|
|
return newMapValueNode(n.keyHash, key, value)
|
|
}
|
|
|
|
*resized = true
|
|
|
|
// Recursively merge nodes together if key hashes are different.
|
|
if n.keyHash != keyHash {
|
|
return mergeIntoNode(n, shift, keyHash, key, value)
|
|
}
|
|
|
|
// Merge into collision node if hash matches.
|
|
return &mapHashCollisionNode{keyHash: keyHash, entries: []mapEntry{
|
|
{key: n.key, value: n.value},
|
|
{key: key, value: value},
|
|
}}
|
|
}
|
|
|
|
// delete returns nil if the key matches the node's key. Otherwise returns the original node.
|
|
func (n *mapValueNode) delete(key interface{}, shift uint, keyHash uint32, h Hasher, mutable bool, resized *bool) mapNode {
|
|
// Return original node if the keys do not match.
|
|
if !h.Equal(n.key, key) {
|
|
return n
|
|
}
|
|
|
|
// Otherwise remove the node if keys do match.
|
|
*resized = true
|
|
return nil
|
|
}
|
|
|
|
// mapHashCollisionNode represents a leaf node that contains two or more key/value
|
|
// pairs with the same key hash. Single pairs for a hash are stored as value nodes.
|
|
type mapHashCollisionNode struct {
|
|
keyHash uint32 // key hash for all entries
|
|
entries []mapEntry
|
|
}
|
|
|
|
// keyHashValue returns the key hash for all entries on the node.
|
|
func (n *mapHashCollisionNode) keyHashValue() uint32 {
|
|
return n.keyHash
|
|
}
|
|
|
|
// indexOf returns the index of the entry for the given key.
|
|
// Returns -1 if the key does not exist in the node.
|
|
func (n *mapHashCollisionNode) indexOf(key interface{}, h Hasher) int {
|
|
for i := range n.entries {
|
|
if h.Equal(n.entries[i].key, key) {
|
|
return i
|
|
}
|
|
}
|
|
return -1
|
|
}
|
|
|
|
// get returns the value for the given key.
|
|
func (n *mapHashCollisionNode) get(key interface{}, shift uint, keyHash uint32, h Hasher) (value interface{}, ok bool) {
|
|
for i := range n.entries {
|
|
if h.Equal(n.entries[i].key, key) {
|
|
return n.entries[i].value, true
|
|
}
|
|
}
|
|
return nil, false
|
|
}
|
|
|
|
// set returns a copy of the node with key set to the given value.
|
|
func (n *mapHashCollisionNode) set(key, value interface{}, shift uint, keyHash uint32, h Hasher, mutable bool, resized *bool) mapNode {
|
|
// Merge node with key/value pair if this is not a hash collision.
|
|
if n.keyHash != keyHash {
|
|
*resized = true
|
|
return mergeIntoNode(n, shift, keyHash, key, value)
|
|
}
|
|
|
|
// Update in-place if mutable.
|
|
if mutable {
|
|
if idx := n.indexOf(key, h); idx == -1 {
|
|
*resized = true
|
|
n.entries = append(n.entries, mapEntry{key, value})
|
|
} else {
|
|
n.entries[idx] = mapEntry{key, value}
|
|
}
|
|
return n
|
|
}
|
|
|
|
// Append to end of node if key doesn't exist & mark resized.
|
|
// Otherwise copy nodes and overwrite at matching key index.
|
|
other := &mapHashCollisionNode{keyHash: n.keyHash}
|
|
if idx := n.indexOf(key, h); idx == -1 {
|
|
*resized = true
|
|
other.entries = make([]mapEntry, len(n.entries)+1)
|
|
copy(other.entries, n.entries)
|
|
other.entries[len(other.entries)-1] = mapEntry{key, value}
|
|
} else {
|
|
other.entries = make([]mapEntry, len(n.entries))
|
|
copy(other.entries, n.entries)
|
|
other.entries[idx] = mapEntry{key, value}
|
|
}
|
|
return other
|
|
}
|
|
|
|
// delete returns a node with the given key deleted. Returns the same node if
|
|
// the key does not exist. If removing the key would shrink the node to a single
|
|
// entry then a value node is returned.
|
|
func (n *mapHashCollisionNode) delete(key interface{}, shift uint, keyHash uint32, h Hasher, mutable bool, resized *bool) mapNode {
|
|
idx := n.indexOf(key, h)
|
|
|
|
// Return original node if key is not found.
|
|
if idx == -1 {
|
|
return n
|
|
}
|
|
|
|
// Mark as resized if key exists.
|
|
*resized = true
|
|
|
|
// Convert to value node if we move to one entry.
|
|
if len(n.entries) == 2 {
|
|
return &mapValueNode{
|
|
keyHash: n.keyHash,
|
|
key: n.entries[idx^1].key,
|
|
value: n.entries[idx^1].value,
|
|
}
|
|
}
|
|
|
|
// Remove entry in-place if mutable.
|
|
if mutable {
|
|
copy(n.entries[idx:], n.entries[idx+1:])
|
|
n.entries[len(n.entries)-1] = mapEntry{}
|
|
n.entries = n.entries[:len(n.entries)-1]
|
|
return n
|
|
}
|
|
|
|
// Return copy without entry if immutable.
|
|
other := &mapHashCollisionNode{keyHash: n.keyHash, entries: make([]mapEntry, len(n.entries)-1)}
|
|
copy(other.entries[:idx], n.entries[:idx])
|
|
copy(other.entries[idx:], n.entries[idx+1:])
|
|
return other
|
|
}
|
|
|
|
// mergeIntoNode merges a key/value pair into an existing node.
|
|
// Caller must verify that node's keyHash is not equal to keyHash.
|
|
func mergeIntoNode(node mapLeafNode, shift uint, keyHash uint32, key, value interface{}) mapNode {
|
|
idx1 := (node.keyHashValue() >> shift) & mapNodeMask
|
|
idx2 := (keyHash >> shift) & mapNodeMask
|
|
|
|
// Recursively build branch nodes to combine the node and its key.
|
|
other := &mapBitmapIndexedNode{bitmap: (1 << idx1) | (1 << idx2)}
|
|
if idx1 == idx2 {
|
|
other.nodes = []mapNode{mergeIntoNode(node, shift+mapNodeBits, keyHash, key, value)}
|
|
} else {
|
|
if newNode := newMapValueNode(keyHash, key, value); idx1 < idx2 {
|
|
other.nodes = []mapNode{node, newNode}
|
|
} else {
|
|
other.nodes = []mapNode{newNode, node}
|
|
}
|
|
}
|
|
return other
|
|
}
|
|
|
|
// mapEntry represents a single key/value pair.
|
|
type mapEntry struct {
|
|
key interface{}
|
|
value interface{}
|
|
}
|
|
|
|
// MapIterator represents an iterator over a map's key/value pairs. Although
|
|
// map keys are not sorted, the iterator's order is deterministic.
|
|
type MapIterator struct {
|
|
m *Map // source map
|
|
|
|
stack [32]mapIteratorElem // search stack
|
|
depth int // stack depth
|
|
}
|
|
|
|
// Done returns true if no more elements remain in the iterator.
|
|
func (itr *MapIterator) Done() bool {
|
|
return itr.depth == -1
|
|
}
|
|
|
|
// First resets the iterator to the first key/value pair.
|
|
func (itr *MapIterator) First() {
|
|
// Exit immediately if the map is empty.
|
|
if itr.m.root == nil {
|
|
itr.depth = -1
|
|
return
|
|
}
|
|
|
|
// Initialize the stack to the left most element.
|
|
itr.stack[0] = mapIteratorElem{node: itr.m.root}
|
|
itr.depth = 0
|
|
itr.first()
|
|
}
|
|
|
|
// Next returns the next key/value pair. Returns a nil key when no elements remain.
|
|
func (itr *MapIterator) Next() (key, value interface{}) {
|
|
// Return nil key if iteration is done.
|
|
if itr.Done() {
|
|
return nil, nil
|
|
}
|
|
|
|
// Retrieve current index & value. Current node is always a leaf.
|
|
elem := &itr.stack[itr.depth]
|
|
switch node := elem.node.(type) {
|
|
case *mapArrayNode:
|
|
entry := &node.entries[elem.index]
|
|
key, value = entry.key, entry.value
|
|
case *mapValueNode:
|
|
key, value = node.key, node.value
|
|
case *mapHashCollisionNode:
|
|
entry := &node.entries[elem.index]
|
|
key, value = entry.key, entry.value
|
|
}
|
|
|
|
// Move up stack until we find a node that has remaining position ahead
|
|
// and move that element forward by one.
|
|
itr.next()
|
|
return key, value
|
|
}
|
|
|
|
// next moves to the next available key.
|
|
func (itr *MapIterator) next() {
|
|
for ; itr.depth >= 0; itr.depth-- {
|
|
elem := &itr.stack[itr.depth]
|
|
|
|
switch node := elem.node.(type) {
|
|
case *mapArrayNode:
|
|
if elem.index < len(node.entries)-1 {
|
|
elem.index++
|
|
return
|
|
}
|
|
|
|
case *mapBitmapIndexedNode:
|
|
if elem.index < len(node.nodes)-1 {
|
|
elem.index++
|
|
itr.stack[itr.depth+1].node = node.nodes[elem.index]
|
|
itr.depth++
|
|
itr.first()
|
|
return
|
|
}
|
|
|
|
case *mapHashArrayNode:
|
|
for i := elem.index + 1; i < len(node.nodes); i++ {
|
|
if node.nodes[i] != nil {
|
|
elem.index = i
|
|
itr.stack[itr.depth+1].node = node.nodes[elem.index]
|
|
itr.depth++
|
|
itr.first()
|
|
return
|
|
}
|
|
}
|
|
|
|
case *mapValueNode:
|
|
continue // always the last value, traverse up
|
|
|
|
case *mapHashCollisionNode:
|
|
if elem.index < len(node.entries)-1 {
|
|
elem.index++
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// first positions the stack left most index.
|
|
// Elements and indexes at and below the current depth are assumed to be correct.
|
|
func (itr *MapIterator) first() {
|
|
for ; ; itr.depth++ {
|
|
elem := &itr.stack[itr.depth]
|
|
|
|
switch node := elem.node.(type) {
|
|
case *mapBitmapIndexedNode:
|
|
elem.index = 0
|
|
itr.stack[itr.depth+1].node = node.nodes[0]
|
|
|
|
case *mapHashArrayNode:
|
|
for i := 0; i < len(node.nodes); i++ {
|
|
if node.nodes[i] != nil { // find first node
|
|
elem.index = i
|
|
itr.stack[itr.depth+1].node = node.nodes[i]
|
|
break
|
|
}
|
|
}
|
|
|
|
default: // *mapArrayNode, mapLeafNode
|
|
elem.index = 0
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// mapIteratorElem represents a node/index pair in the MapIterator stack.
|
|
type mapIteratorElem struct {
|
|
node mapNode
|
|
index int
|
|
}
|
|
|
|
// Sorted map child node limit size.
|
|
const (
|
|
sortedMapNodeSize = 32
|
|
)
|
|
|
|
// SortedMap represents a map of key/value pairs sorted by key. The sort order
|
|
// is determined by the Comparer used by the map.
|
|
//
|
|
// This map is implemented as a B+tree.
|
|
type SortedMap struct {
|
|
size int // total number of key/value pairs
|
|
root sortedMapNode // root of b+tree
|
|
comparer Comparer
|
|
}
|
|
|
|
// NewSortedMap returns a new instance of SortedMap. If comparer is nil then
|
|
// a default comparer is set after the first key is inserted. Default comparers
|
|
// exist for int, string, and byte slice keys.
|
|
func NewSortedMap(comparer Comparer) *SortedMap {
|
|
return &SortedMap{
|
|
comparer: comparer,
|
|
}
|
|
}
|
|
|
|
// Len returns the number of elements in the sorted map.
|
|
func (m *SortedMap) Len() int {
|
|
return m.size
|
|
}
|
|
|
|
// Get returns the value for a given key and a flag indicating if the key is set.
|
|
// The flag can be used to distinguish between a nil-set key versus an unset key.
|
|
func (m *SortedMap) Get(key interface{}) (interface{}, bool) {
|
|
if m.root == nil {
|
|
return nil, false
|
|
}
|
|
return m.root.get(key, m.comparer)
|
|
}
|
|
|
|
// Set returns a copy of the map with the key set to the given value.
|
|
func (m *SortedMap) Set(key, value interface{}) *SortedMap {
|
|
return m.set(key, value, false)
|
|
}
|
|
|
|
func (m *SortedMap) set(key, value interface{}, mutable bool) *SortedMap {
|
|
// Set a comparer on the first value if one does not already exist.
|
|
comparer := m.comparer
|
|
if comparer == nil {
|
|
comparer = NewComparer(key)
|
|
}
|
|
|
|
// Create copy, if necessary.
|
|
other := m
|
|
if !mutable {
|
|
other = m.clone()
|
|
}
|
|
other.comparer = comparer
|
|
|
|
// If no values are set then initialize with a leaf node.
|
|
if m.root == nil {
|
|
other.size = 1
|
|
other.root = &sortedMapLeafNode{entries: []mapEntry{{key: key, value: value}}}
|
|
return other
|
|
}
|
|
|
|
// Otherwise delegate to root node.
|
|
// If a split occurs then grow the tree from the root.
|
|
var resized bool
|
|
newRoot, splitNode := m.root.set(key, value, comparer, mutable, &resized)
|
|
if splitNode != nil {
|
|
newRoot = newSortedMapBranchNode(newRoot, splitNode)
|
|
}
|
|
|
|
// Update root and size (if resized).
|
|
other.size = m.size
|
|
other.root = newRoot
|
|
if resized {
|
|
other.size++
|
|
}
|
|
return other
|
|
}
|
|
|
|
// Delete returns a copy of the map with the key removed.
|
|
// Returns the original map if key does not exist.
|
|
func (m *SortedMap) Delete(key interface{}) *SortedMap {
|
|
return m.delete(key, false)
|
|
}
|
|
|
|
func (m *SortedMap) delete(key interface{}, mutable bool) *SortedMap {
|
|
// Return original map if no keys exist.
|
|
if m.root == nil {
|
|
return m
|
|
}
|
|
|
|
// If the delete did not change the node then return the original map.
|
|
var resized bool
|
|
newRoot := m.root.delete(key, m.comparer, mutable, &resized)
|
|
if !resized {
|
|
return m
|
|
}
|
|
|
|
// Create copy, if necessary.
|
|
other := m
|
|
if !mutable {
|
|
other = m.clone()
|
|
}
|
|
|
|
// Update root and size.
|
|
other.size = m.size - 1
|
|
other.root = newRoot
|
|
return other
|
|
}
|
|
|
|
// clone returns a shallow copy of m.
|
|
func (m *SortedMap) clone() *SortedMap {
|
|
other := *m
|
|
return &other
|
|
}
|
|
|
|
// Iterator returns a new iterator for this map positioned at the first key.
|
|
func (m *SortedMap) Iterator() *SortedMapIterator {
|
|
itr := &SortedMapIterator{m: m}
|
|
itr.First()
|
|
return itr
|
|
}
|
|
|
|
// SortedMapBuilder represents an efficient builder for creating sorted maps.
|
|
type SortedMapBuilder struct {
|
|
m *SortedMap // current state
|
|
}
|
|
|
|
// NewSortedMapBuilder returns a new instance of SortedMapBuilder.
|
|
func NewSortedMapBuilder(comparer Comparer) *SortedMapBuilder {
|
|
return &SortedMapBuilder{m: NewSortedMap(comparer)}
|
|
}
|
|
|
|
// SortedMap returns the current copy of the map.
|
|
// The returned map is safe to use even if after the builder continues to be used.
|
|
func (b *SortedMapBuilder) Map() *SortedMap {
|
|
assert(b.m != nil, "immutable.SortedMapBuilder.Map(): duplicate call to fetch map")
|
|
m := b.m
|
|
b.m = nil
|
|
return m
|
|
}
|
|
|
|
// Len returns the number of elements in the underlying map.
|
|
func (b *SortedMapBuilder) Len() int {
|
|
assert(b.m != nil, "immutable.SortedMapBuilder: builder invalid after Map() invocation")
|
|
return b.m.Len()
|
|
}
|
|
|
|
// Get returns the value for the given key.
|
|
func (b *SortedMapBuilder) Get(key interface{}) (value interface{}, ok bool) {
|
|
assert(b.m != nil, "immutable.SortedMapBuilder: builder invalid after Map() invocation")
|
|
return b.m.Get(key)
|
|
}
|
|
|
|
// Set sets the value of the given key. See SortedMap.Set() for additional details.
|
|
func (b *SortedMapBuilder) Set(key, value interface{}) {
|
|
assert(b.m != nil, "immutable.SortedMapBuilder: builder invalid after Map() invocation")
|
|
b.m = b.m.set(key, value, true)
|
|
}
|
|
|
|
// Delete removes the given key. See SortedMap.Delete() for additional details.
|
|
func (b *SortedMapBuilder) Delete(key interface{}) {
|
|
assert(b.m != nil, "immutable.SortedMapBuilder: builder invalid after Map() invocation")
|
|
b.m = b.m.delete(key, true)
|
|
}
|
|
|
|
// Iterator returns a new iterator for the underlying map positioned at the first key.
|
|
func (b *SortedMapBuilder) Iterator() *SortedMapIterator {
|
|
assert(b.m != nil, "immutable.SortedMapBuilder: builder invalid after Map() invocation")
|
|
return b.m.Iterator()
|
|
}
|
|
|
|
// sortedMapNode represents a branch or leaf node in the sorted map.
|
|
type sortedMapNode interface {
|
|
minKey() interface{}
|
|
indexOf(key interface{}, c Comparer) int
|
|
get(key interface{}, c Comparer) (value interface{}, ok bool)
|
|
set(key, value interface{}, c Comparer, mutable bool, resized *bool) (sortedMapNode, sortedMapNode)
|
|
delete(key interface{}, c Comparer, mutable bool, resized *bool) sortedMapNode
|
|
}
|
|
|
|
var _ sortedMapNode = (*sortedMapBranchNode)(nil)
|
|
var _ sortedMapNode = (*sortedMapLeafNode)(nil)
|
|
|
|
// sortedMapBranchNode represents a branch in the sorted map.
|
|
type sortedMapBranchNode struct {
|
|
elems []sortedMapBranchElem
|
|
}
|
|
|
|
// newSortedMapBranchNode returns a new branch node with the given child nodes.
|
|
func newSortedMapBranchNode(children ...sortedMapNode) *sortedMapBranchNode {
|
|
// Fetch min keys for every child.
|
|
elems := make([]sortedMapBranchElem, len(children))
|
|
for i, child := range children {
|
|
elems[i] = sortedMapBranchElem{
|
|
key: child.minKey(),
|
|
node: child,
|
|
}
|
|
}
|
|
|
|
return &sortedMapBranchNode{elems: elems}
|
|
}
|
|
|
|
// minKey returns the lowest key stored in this node's tree.
|
|
func (n *sortedMapBranchNode) minKey() interface{} {
|
|
return n.elems[0].node.minKey()
|
|
}
|
|
|
|
// indexOf returns the index of the key within the child nodes.
|
|
func (n *sortedMapBranchNode) indexOf(key interface{}, c Comparer) int {
|
|
if idx := sort.Search(len(n.elems), func(i int) bool { return c.Compare(n.elems[i].key, key) == 1 }); idx > 0 {
|
|
return idx - 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// get returns the value for the given key.
|
|
func (n *sortedMapBranchNode) get(key interface{}, c Comparer) (value interface{}, ok bool) {
|
|
idx := n.indexOf(key, c)
|
|
return n.elems[idx].node.get(key, c)
|
|
}
|
|
|
|
// set returns a copy of the node with the key set to the given value.
|
|
func (n *sortedMapBranchNode) set(key, value interface{}, c Comparer, mutable bool, resized *bool) (sortedMapNode, sortedMapNode) {
|
|
idx := n.indexOf(key, c)
|
|
|
|
// Delegate insert to child node.
|
|
newNode, splitNode := n.elems[idx].node.set(key, value, c, mutable, resized)
|
|
|
|
// Update in-place, if mutable.
|
|
if mutable {
|
|
n.elems[idx] = sortedMapBranchElem{key: newNode.minKey(), node: newNode}
|
|
if splitNode != nil {
|
|
n.elems = append(n.elems, sortedMapBranchElem{})
|
|
copy(n.elems[idx+1:], n.elems[idx:])
|
|
n.elems[idx+1] = sortedMapBranchElem{key: splitNode.minKey(), node: splitNode}
|
|
}
|
|
|
|
// If the child splits and we have no more room then we split too.
|
|
if len(n.elems) > sortedMapNodeSize {
|
|
splitIdx := len(n.elems) / 2
|
|
newNode := &sortedMapBranchNode{elems: n.elems[:splitIdx:splitIdx]}
|
|
splitNode := &sortedMapBranchNode{elems: n.elems[splitIdx:]}
|
|
return newNode, splitNode
|
|
}
|
|
return n, nil
|
|
}
|
|
|
|
// If no split occurs, copy branch and update keys.
|
|
// If the child splits, insert new key/child into copy of branch.
|
|
var other sortedMapBranchNode
|
|
if splitNode == nil {
|
|
other.elems = make([]sortedMapBranchElem, len(n.elems))
|
|
copy(other.elems, n.elems)
|
|
other.elems[idx] = sortedMapBranchElem{
|
|
key: newNode.minKey(),
|
|
node: newNode,
|
|
}
|
|
} else {
|
|
other.elems = make([]sortedMapBranchElem, len(n.elems)+1)
|
|
copy(other.elems[:idx], n.elems[:idx])
|
|
copy(other.elems[idx+1:], n.elems[idx:])
|
|
other.elems[idx] = sortedMapBranchElem{
|
|
key: newNode.minKey(),
|
|
node: newNode,
|
|
}
|
|
other.elems[idx+1] = sortedMapBranchElem{
|
|
key: splitNode.minKey(),
|
|
node: splitNode,
|
|
}
|
|
}
|
|
|
|
// If the child splits and we have no more room then we split too.
|
|
if len(other.elems) > sortedMapNodeSize {
|
|
splitIdx := len(other.elems) / 2
|
|
newNode := &sortedMapBranchNode{elems: other.elems[:splitIdx:splitIdx]}
|
|
splitNode := &sortedMapBranchNode{elems: other.elems[splitIdx:]}
|
|
return newNode, splitNode
|
|
}
|
|
|
|
// Otherwise return the new branch node with the updated entry.
|
|
return &other, nil
|
|
}
|
|
|
|
// delete returns a node with the key removed. Returns the same node if the key
|
|
// does not exist. Returns nil if all child nodes are removed.
|
|
func (n *sortedMapBranchNode) delete(key interface{}, c Comparer, mutable bool, resized *bool) sortedMapNode {
|
|
idx := n.indexOf(key, c)
|
|
|
|
// Return original node if child has not changed.
|
|
newNode := n.elems[idx].node.delete(key, c, mutable, resized)
|
|
if !*resized {
|
|
return n
|
|
}
|
|
|
|
// Remove child if it is now nil.
|
|
if newNode == nil {
|
|
// If this node will become empty then simply return nil.
|
|
if len(n.elems) == 1 {
|
|
return nil
|
|
}
|
|
|
|
// If mutable, update in-place.
|
|
if mutable {
|
|
copy(n.elems[idx:], n.elems[idx+1:])
|
|
n.elems[len(n.elems)-1] = sortedMapBranchElem{}
|
|
n.elems = n.elems[:len(n.elems)-1]
|
|
return n
|
|
}
|
|
|
|
// Return a copy without the given node.
|
|
other := &sortedMapBranchNode{elems: make([]sortedMapBranchElem, len(n.elems)-1)}
|
|
copy(other.elems[:idx], n.elems[:idx])
|
|
copy(other.elems[idx:], n.elems[idx+1:])
|
|
return other
|
|
}
|
|
|
|
// If mutable, update in-place.
|
|
if mutable {
|
|
n.elems[idx] = sortedMapBranchElem{key: newNode.minKey(), node: newNode}
|
|
return n
|
|
}
|
|
|
|
// Return a copy with the updated node.
|
|
other := &sortedMapBranchNode{elems: make([]sortedMapBranchElem, len(n.elems))}
|
|
copy(other.elems, n.elems)
|
|
other.elems[idx] = sortedMapBranchElem{
|
|
key: newNode.minKey(),
|
|
node: newNode,
|
|
}
|
|
return other
|
|
}
|
|
|
|
type sortedMapBranchElem struct {
|
|
key interface{}
|
|
node sortedMapNode
|
|
}
|
|
|
|
// sortedMapLeafNode represents a leaf node in the sorted map.
|
|
type sortedMapLeafNode struct {
|
|
entries []mapEntry
|
|
}
|
|
|
|
// minKey returns the first key stored in this node.
|
|
func (n *sortedMapLeafNode) minKey() interface{} {
|
|
return n.entries[0].key
|
|
}
|
|
|
|
// indexOf returns the index of the given key.
|
|
func (n *sortedMapLeafNode) indexOf(key interface{}, c Comparer) int {
|
|
return sort.Search(len(n.entries), func(i int) bool {
|
|
return c.Compare(n.entries[i].key, key) != -1 // GTE
|
|
})
|
|
}
|
|
|
|
// get returns the value of the given key.
|
|
func (n *sortedMapLeafNode) get(key interface{}, c Comparer) (value interface{}, ok bool) {
|
|
idx := n.indexOf(key, c)
|
|
|
|
// If the index is beyond the entry count or the key is not equal then return 'not found'.
|
|
if idx == len(n.entries) || c.Compare(n.entries[idx].key, key) != 0 {
|
|
return nil, false
|
|
}
|
|
|
|
// If the key matches then return its value.
|
|
return n.entries[idx].value, true
|
|
}
|
|
|
|
// set returns a copy of node with the key set to the given value. If the update
|
|
// causes the node to grow beyond the maximum size then it is split in two.
|
|
func (n *sortedMapLeafNode) set(key, value interface{}, c Comparer, mutable bool, resized *bool) (sortedMapNode, sortedMapNode) {
|
|
// Find the insertion index for the key.
|
|
idx := n.indexOf(key, c)
|
|
exists := idx < len(n.entries) && c.Compare(n.entries[idx].key, key) == 0
|
|
|
|
// Update in-place, if mutable.
|
|
if mutable {
|
|
if !exists {
|
|
*resized = true
|
|
n.entries = append(n.entries, mapEntry{})
|
|
copy(n.entries[idx+1:], n.entries[idx:])
|
|
}
|
|
n.entries[idx] = mapEntry{key: key, value: value}
|
|
|
|
// If the key doesn't exist and we exceed our max allowed values then split.
|
|
if len(n.entries) > sortedMapNodeSize {
|
|
splitIdx := len(n.entries) / 2
|
|
newNode := &sortedMapLeafNode{entries: n.entries[:splitIdx:splitIdx]}
|
|
splitNode := &sortedMapLeafNode{entries: n.entries[splitIdx:]}
|
|
return newNode, splitNode
|
|
}
|
|
return n, nil
|
|
}
|
|
|
|
// If the key matches then simply return a copy with the entry overridden.
|
|
// If there is no match then insert new entry and mark as resized.
|
|
var newEntries []mapEntry
|
|
if exists {
|
|
newEntries = make([]mapEntry, len(n.entries))
|
|
copy(newEntries, n.entries)
|
|
newEntries[idx] = mapEntry{key: key, value: value}
|
|
} else {
|
|
*resized = true
|
|
newEntries = make([]mapEntry, len(n.entries)+1)
|
|
copy(newEntries[:idx], n.entries[:idx])
|
|
newEntries[idx] = mapEntry{key: key, value: value}
|
|
copy(newEntries[idx+1:], n.entries[idx:])
|
|
}
|
|
|
|
// If the key doesn't exist and we exceed our max allowed values then split.
|
|
if len(newEntries) > sortedMapNodeSize {
|
|
splitIdx := len(newEntries) / 2
|
|
newNode := &sortedMapLeafNode{entries: newEntries[:splitIdx:splitIdx]}
|
|
splitNode := &sortedMapLeafNode{entries: newEntries[splitIdx:]}
|
|
return newNode, splitNode
|
|
}
|
|
|
|
// Otherwise return the new leaf node with the updated entry.
|
|
return &sortedMapLeafNode{entries: newEntries}, nil
|
|
}
|
|
|
|
// delete returns a copy of node with key removed. Returns the original node if
|
|
// the key does not exist. Returns nil if the removed key is the last remaining key.
|
|
func (n *sortedMapLeafNode) delete(key interface{}, c Comparer, mutable bool, resized *bool) sortedMapNode {
|
|
idx := n.indexOf(key, c)
|
|
|
|
// Return original node if key is not found.
|
|
if idx >= len(n.entries) || c.Compare(n.entries[idx].key, key) != 0 {
|
|
return n
|
|
}
|
|
*resized = true
|
|
|
|
// If this is the last entry then return nil.
|
|
if len(n.entries) == 1 {
|
|
return nil
|
|
}
|
|
|
|
// Update in-place, if mutable.
|
|
if mutable {
|
|
copy(n.entries[idx:], n.entries[idx+1:])
|
|
n.entries[len(n.entries)-1] = mapEntry{}
|
|
n.entries = n.entries[:len(n.entries)-1]
|
|
return n
|
|
}
|
|
|
|
// Return copy of node with entry removed.
|
|
other := &sortedMapLeafNode{entries: make([]mapEntry, len(n.entries)-1)}
|
|
copy(other.entries[:idx], n.entries[:idx])
|
|
copy(other.entries[idx:], n.entries[idx+1:])
|
|
return other
|
|
}
|
|
|
|
// SortedMapIterator represents an iterator over a sorted map.
|
|
// Iteration can occur in natural or reverse order based on use of Next() or Prev().
|
|
type SortedMapIterator struct {
|
|
m *SortedMap // source map
|
|
|
|
stack [32]sortedMapIteratorElem // search stack
|
|
depth int // stack depth
|
|
}
|
|
|
|
// Done returns true if no more key/value pairs remain in the iterator.
|
|
func (itr *SortedMapIterator) Done() bool {
|
|
return itr.depth == -1
|
|
}
|
|
|
|
// First moves the iterator to the first key/value pair.
|
|
func (itr *SortedMapIterator) First() {
|
|
if itr.m.root == nil {
|
|
itr.depth = -1
|
|
return
|
|
}
|
|
itr.stack[0] = sortedMapIteratorElem{node: itr.m.root}
|
|
itr.depth = 0
|
|
itr.first()
|
|
}
|
|
|
|
// Last moves the iterator to the last key/value pair.
|
|
func (itr *SortedMapIterator) Last() {
|
|
if itr.m.root == nil {
|
|
itr.depth = -1
|
|
return
|
|
}
|
|
itr.stack[0] = sortedMapIteratorElem{node: itr.m.root}
|
|
itr.depth = 0
|
|
itr.last()
|
|
}
|
|
|
|
// Seek moves the iterator position to the given key in the map.
|
|
// If the key does not exist then the next key is used. If no more keys exist
|
|
// then the iteartor is marked as done.
|
|
func (itr *SortedMapIterator) Seek(key interface{}) {
|
|
if itr.m.root == nil {
|
|
itr.depth = -1
|
|
return
|
|
}
|
|
itr.stack[0] = sortedMapIteratorElem{node: itr.m.root}
|
|
itr.depth = 0
|
|
itr.seek(key)
|
|
}
|
|
|
|
// Next returns the current key/value pair and moves the iterator forward.
|
|
// Returns a nil key if the there are no more elements to return.
|
|
func (itr *SortedMapIterator) Next() (key, value interface{}) {
|
|
// Return nil key if iteration is complete.
|
|
if itr.Done() {
|
|
return nil, nil
|
|
}
|
|
|
|
// Retrieve current key/value pair.
|
|
leafElem := &itr.stack[itr.depth]
|
|
leafNode := leafElem.node.(*sortedMapLeafNode)
|
|
leafEntry := &leafNode.entries[leafElem.index]
|
|
key, value = leafEntry.key, leafEntry.value
|
|
|
|
// Move to the next available key/value pair.
|
|
itr.next()
|
|
|
|
// Only occurs when iterator is done.
|
|
return key, value
|
|
}
|
|
|
|
// next moves to the next key. If no keys are after then depth is set to -1.
|
|
func (itr *SortedMapIterator) next() {
|
|
for ; itr.depth >= 0; itr.depth-- {
|
|
elem := &itr.stack[itr.depth]
|
|
|
|
switch node := elem.node.(type) {
|
|
case *sortedMapLeafNode:
|
|
if elem.index < len(node.entries)-1 {
|
|
elem.index++
|
|
return
|
|
}
|
|
case *sortedMapBranchNode:
|
|
if elem.index < len(node.elems)-1 {
|
|
elem.index++
|
|
itr.stack[itr.depth+1].node = node.elems[elem.index].node
|
|
itr.depth++
|
|
itr.first()
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Prev returns the current key/value pair and moves the iterator backward.
|
|
// Returns a nil key if the there are no more elements to return.
|
|
func (itr *SortedMapIterator) Prev() (key, value interface{}) {
|
|
// Return nil key if iteration is complete.
|
|
if itr.Done() {
|
|
return nil, nil
|
|
}
|
|
|
|
// Retrieve current key/value pair.
|
|
leafElem := &itr.stack[itr.depth]
|
|
leafNode := leafElem.node.(*sortedMapLeafNode)
|
|
leafEntry := &leafNode.entries[leafElem.index]
|
|
key, value = leafEntry.key, leafEntry.value
|
|
|
|
itr.prev()
|
|
return key, value
|
|
}
|
|
|
|
// prev moves to the previous key. If no keys are before then depth is set to -1.
|
|
func (itr *SortedMapIterator) prev() {
|
|
for ; itr.depth >= 0; itr.depth-- {
|
|
elem := &itr.stack[itr.depth]
|
|
|
|
switch node := elem.node.(type) {
|
|
case *sortedMapLeafNode:
|
|
if elem.index > 0 {
|
|
elem.index--
|
|
return
|
|
}
|
|
case *sortedMapBranchNode:
|
|
if elem.index > 0 {
|
|
elem.index--
|
|
itr.stack[itr.depth+1].node = node.elems[elem.index].node
|
|
itr.depth++
|
|
itr.last()
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// first positions the stack to the leftmost key from the current depth.
|
|
// Elements and indexes below the current depth are assumed to be correct.
|
|
func (itr *SortedMapIterator) first() {
|
|
for {
|
|
elem := &itr.stack[itr.depth]
|
|
elem.index = 0
|
|
|
|
switch node := elem.node.(type) {
|
|
case *sortedMapBranchNode:
|
|
itr.stack[itr.depth+1] = sortedMapIteratorElem{node: node.elems[elem.index].node}
|
|
itr.depth++
|
|
case *sortedMapLeafNode:
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// last positions the stack to the rightmost key from the current depth.
|
|
// Elements and indexes below the current depth are assumed to be correct.
|
|
func (itr *SortedMapIterator) last() {
|
|
for {
|
|
elem := &itr.stack[itr.depth]
|
|
|
|
switch node := elem.node.(type) {
|
|
case *sortedMapBranchNode:
|
|
elem.index = len(node.elems) - 1
|
|
itr.stack[itr.depth+1] = sortedMapIteratorElem{node: node.elems[elem.index].node}
|
|
itr.depth++
|
|
case *sortedMapLeafNode:
|
|
elem.index = len(node.entries) - 1
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// seek positions the stack to the given key from the current depth.
|
|
// Elements and indexes below the current depth are assumed to be correct.
|
|
func (itr *SortedMapIterator) seek(key interface{}) {
|
|
for {
|
|
elem := &itr.stack[itr.depth]
|
|
elem.index = elem.node.indexOf(key, itr.m.comparer)
|
|
|
|
switch node := elem.node.(type) {
|
|
case *sortedMapBranchNode:
|
|
itr.stack[itr.depth+1] = sortedMapIteratorElem{node: node.elems[elem.index].node}
|
|
itr.depth++
|
|
case *sortedMapLeafNode:
|
|
if elem.index == len(node.entries) {
|
|
itr.next()
|
|
}
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// sortedMapIteratorElem represents node/index pair in the SortedMapIterator stack.
|
|
type sortedMapIteratorElem struct {
|
|
node sortedMapNode
|
|
index int
|
|
}
|
|
|
|
// Hasher hashes keys and checks them for equality.
|
|
type Hasher interface {
|
|
// Computes a 32-bit hash for key.
|
|
Hash(key interface{}) uint32
|
|
|
|
// Returns true if a and b are equal.
|
|
Equal(a, b interface{}) bool
|
|
}
|
|
|
|
// NewHasher returns the built-in hasher for a given key type.
|
|
func NewHasher(key interface{}) Hasher {
|
|
// Attempt to use non-reflection based hasher first.
|
|
switch key.(type) {
|
|
case int:
|
|
return &intHasher{}
|
|
case int8:
|
|
return &int8Hasher{}
|
|
case int16:
|
|
return &int16Hasher{}
|
|
case int32:
|
|
return &int32Hasher{}
|
|
case int64:
|
|
return &int64Hasher{}
|
|
case uint:
|
|
return &uintHasher{}
|
|
case uint8:
|
|
return &uint8Hasher{}
|
|
case uint16:
|
|
return &uint16Hasher{}
|
|
case uint32:
|
|
return &uint32Hasher{}
|
|
case uint64:
|
|
return &uint64Hasher{}
|
|
case string:
|
|
return &stringHasher{}
|
|
case []byte:
|
|
return &byteSliceHasher{}
|
|
}
|
|
|
|
// Fallback to reflection-based hasher otherwise.
|
|
// This is used when caller wraps a type around a primitive type.
|
|
switch reflect.TypeOf(key).Kind() {
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
return &reflectIntHasher{}
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
|
return &reflectUintHasher{}
|
|
case reflect.String:
|
|
return &reflectStringHasher{}
|
|
}
|
|
|
|
// If no hashers match then panic.
|
|
// This is a compile time issue so it should not return an error.
|
|
panic(fmt.Sprintf("immutable.NewHasher: must set hasher for %T type", key))
|
|
}
|
|
|
|
// intHasher implements Hasher for int keys.
|
|
type intHasher struct{}
|
|
|
|
// Hash returns a hash for key.
|
|
func (h *intHasher) Hash(key interface{}) uint32 {
|
|
return hashUint64(uint64(key.(int)))
|
|
}
|
|
|
|
// Equal returns true if a is equal to b. Otherwise returns false.
|
|
// Panics if a and b are not ints.
|
|
func (h *intHasher) Equal(a, b interface{}) bool {
|
|
return a.(int) == b.(int)
|
|
}
|
|
|
|
// int8Hasher implements Hasher for int8 keys.
|
|
type int8Hasher struct{}
|
|
|
|
// Hash returns a hash for key.
|
|
func (h *int8Hasher) Hash(key interface{}) uint32 {
|
|
return hashUint64(uint64(key.(int8)))
|
|
}
|
|
|
|
// Equal returns true if a is equal to b. Otherwise returns false.
|
|
// Panics if a and b are not int8s.
|
|
func (h *int8Hasher) Equal(a, b interface{}) bool {
|
|
return a.(int8) == b.(int8)
|
|
}
|
|
|
|
// int16Hasher implements Hasher for int16 keys.
|
|
type int16Hasher struct{}
|
|
|
|
// Hash returns a hash for key.
|
|
func (h *int16Hasher) Hash(key interface{}) uint32 {
|
|
return hashUint64(uint64(key.(int16)))
|
|
}
|
|
|
|
// Equal returns true if a is equal to b. Otherwise returns false.
|
|
// Panics if a and b are not int16s.
|
|
func (h *int16Hasher) Equal(a, b interface{}) bool {
|
|
return a.(int16) == b.(int16)
|
|
}
|
|
|
|
// int32Hasher implements Hasher for int32 keys.
|
|
type int32Hasher struct{}
|
|
|
|
// Hash returns a hash for key.
|
|
func (h *int32Hasher) Hash(key interface{}) uint32 {
|
|
return hashUint64(uint64(key.(int32)))
|
|
}
|
|
|
|
// Equal returns true if a is equal to b. Otherwise returns false.
|
|
// Panics if a and b are not int32s.
|
|
func (h *int32Hasher) Equal(a, b interface{}) bool {
|
|
return a.(int32) == b.(int32)
|
|
}
|
|
|
|
// int64Hasher implements Hasher for int64 keys.
|
|
type int64Hasher struct{}
|
|
|
|
// Hash returns a hash for key.
|
|
func (h *int64Hasher) Hash(key interface{}) uint32 {
|
|
return hashUint64(uint64(key.(int64)))
|
|
}
|
|
|
|
// Equal returns true if a is equal to b. Otherwise returns false.
|
|
// Panics if a and b are not int64s.
|
|
func (h *int64Hasher) Equal(a, b interface{}) bool {
|
|
return a.(int64) == b.(int64)
|
|
}
|
|
|
|
// uintHasher implements Hasher for uint keys.
|
|
type uintHasher struct{}
|
|
|
|
// Hash returns a hash for key.
|
|
func (h *uintHasher) Hash(key interface{}) uint32 {
|
|
return hashUint64(uint64(key.(uint)))
|
|
}
|
|
|
|
// Equal returns true if a is equal to b. Otherwise returns false.
|
|
// Panics if a and b are not uints.
|
|
func (h *uintHasher) Equal(a, b interface{}) bool {
|
|
return a.(uint) == b.(uint)
|
|
}
|
|
|
|
// uint8Hasher implements Hasher for uint8 keys.
|
|
type uint8Hasher struct{}
|
|
|
|
// Hash returns a hash for key.
|
|
func (h *uint8Hasher) Hash(key interface{}) uint32 {
|
|
return hashUint64(uint64(key.(uint8)))
|
|
}
|
|
|
|
// Equal returns true if a is equal to b. Otherwise returns false.
|
|
// Panics if a and b are not uint8s.
|
|
func (h *uint8Hasher) Equal(a, b interface{}) bool {
|
|
return a.(uint8) == b.(uint8)
|
|
}
|
|
|
|
// uint16Hasher implements Hasher for uint16 keys.
|
|
type uint16Hasher struct{}
|
|
|
|
// Hash returns a hash for key.
|
|
func (h *uint16Hasher) Hash(key interface{}) uint32 {
|
|
return hashUint64(uint64(key.(uint16)))
|
|
}
|
|
|
|
// Equal returns true if a is equal to b. Otherwise returns false.
|
|
// Panics if a and b are not uint16s.
|
|
func (h *uint16Hasher) Equal(a, b interface{}) bool {
|
|
return a.(uint16) == b.(uint16)
|
|
}
|
|
|
|
// uint32Hasher implements Hasher for uint32 keys.
|
|
type uint32Hasher struct{}
|
|
|
|
// Hash returns a hash for key.
|
|
func (h *uint32Hasher) Hash(key interface{}) uint32 {
|
|
return hashUint64(uint64(key.(uint32)))
|
|
}
|
|
|
|
// Equal returns true if a is equal to b. Otherwise returns false.
|
|
// Panics if a and b are not uint32s.
|
|
func (h *uint32Hasher) Equal(a, b interface{}) bool {
|
|
return a.(uint32) == b.(uint32)
|
|
}
|
|
|
|
// uint64Hasher implements Hasher for uint64 keys.
|
|
type uint64Hasher struct{}
|
|
|
|
// Hash returns a hash for key.
|
|
func (h *uint64Hasher) Hash(key interface{}) uint32 {
|
|
return hashUint64(key.(uint64))
|
|
}
|
|
|
|
// Equal returns true if a is equal to b. Otherwise returns false.
|
|
// Panics if a and b are not uint64s.
|
|
func (h *uint64Hasher) Equal(a, b interface{}) bool {
|
|
return a.(uint64) == b.(uint64)
|
|
}
|
|
|
|
// stringHasher implements Hasher for string keys.
|
|
type stringHasher struct{}
|
|
|
|
// Hash returns a hash for value.
|
|
func (h *stringHasher) Hash(value interface{}) uint32 {
|
|
var hash uint32
|
|
for i, value := 0, value.(string); i < len(value); i++ {
|
|
hash = 31*hash + uint32(value[i])
|
|
}
|
|
return hash
|
|
}
|
|
|
|
// Equal returns true if a is equal to b. Otherwise returns false.
|
|
// Panics if a and b are not strings.
|
|
func (h *stringHasher) Equal(a, b interface{}) bool {
|
|
return a.(string) == b.(string)
|
|
}
|
|
|
|
// byteSliceHasher implements Hasher for byte slice keys.
|
|
type byteSliceHasher struct{}
|
|
|
|
// Hash returns a hash for value.
|
|
func (h *byteSliceHasher) Hash(value interface{}) uint32 {
|
|
var hash uint32
|
|
for i, value := 0, value.([]byte); i < len(value); i++ {
|
|
hash = 31*hash + uint32(value[i])
|
|
}
|
|
return hash
|
|
}
|
|
|
|
// Equal returns true if a is equal to b. Otherwise returns false.
|
|
// Panics if a and b are not byte slices.
|
|
func (h *byteSliceHasher) Equal(a, b interface{}) bool {
|
|
return bytes.Equal(a.([]byte), b.([]byte))
|
|
}
|
|
|
|
// reflectIntHasher implements a reflection-based Hasher for int keys.
|
|
type reflectIntHasher struct{}
|
|
|
|
// Hash returns a hash for key.
|
|
func (h *reflectIntHasher) Hash(key interface{}) uint32 {
|
|
return hashUint64(uint64(reflect.ValueOf(key).Int()))
|
|
}
|
|
|
|
// Equal returns true if a is equal to b. Otherwise returns false.
|
|
// Panics if a and b are not ints.
|
|
func (h *reflectIntHasher) Equal(a, b interface{}) bool {
|
|
return reflect.ValueOf(a).Int() == reflect.ValueOf(b).Int()
|
|
}
|
|
|
|
// reflectUintHasher implements a reflection-based Hasher for uint keys.
|
|
type reflectUintHasher struct{}
|
|
|
|
// Hash returns a hash for key.
|
|
func (h *reflectUintHasher) Hash(key interface{}) uint32 {
|
|
return hashUint64(reflect.ValueOf(key).Uint())
|
|
}
|
|
|
|
// Equal returns true if a is equal to b. Otherwise returns false.
|
|
// Panics if a and b are not ints.
|
|
func (h *reflectUintHasher) Equal(a, b interface{}) bool {
|
|
return reflect.ValueOf(a).Uint() == reflect.ValueOf(b).Uint()
|
|
}
|
|
|
|
// reflectStringHasher implements a refletion-based Hasher for string keys.
|
|
type reflectStringHasher struct{}
|
|
|
|
// Hash returns a hash for value.
|
|
func (h *reflectStringHasher) Hash(value interface{}) uint32 {
|
|
var hash uint32
|
|
s := reflect.ValueOf(value).String()
|
|
for i := 0; i < len(s); i++ {
|
|
hash = 31*hash + uint32(s[i])
|
|
}
|
|
return hash
|
|
}
|
|
|
|
// Equal returns true if a is equal to b. Otherwise returns false.
|
|
// Panics if a and b are not strings.
|
|
func (h *reflectStringHasher) Equal(a, b interface{}) bool {
|
|
return reflect.ValueOf(a).String() == reflect.ValueOf(b).String()
|
|
}
|
|
|
|
// hashUint64 returns a 32-bit hash for a 64-bit value.
|
|
func hashUint64(value uint64) uint32 {
|
|
hash := value
|
|
for value > 0xffffffff {
|
|
value /= 0xffffffff
|
|
hash ^= value
|
|
}
|
|
return uint32(hash)
|
|
}
|
|
|
|
// Comparer allows the comparison of two keys for the purpose of sorting.
|
|
type Comparer interface {
|
|
// Returns -1 if a is less than b, returns 1 if a is greater than b,
|
|
// and returns 0 if a is equal to b.
|
|
Compare(a, b interface{}) int
|
|
}
|
|
|
|
// NewComparer returns the built-in comparer for a given key type.
|
|
func NewComparer(key interface{}) Comparer {
|
|
// Attempt to use non-reflection based comparer first.
|
|
switch key.(type) {
|
|
case int:
|
|
return &intComparer{}
|
|
case int8:
|
|
return &int8Comparer{}
|
|
case int16:
|
|
return &int16Comparer{}
|
|
case int32:
|
|
return &int32Comparer{}
|
|
case int64:
|
|
return &int64Comparer{}
|
|
case uint:
|
|
return &uintComparer{}
|
|
case uint8:
|
|
return &uint8Comparer{}
|
|
case uint16:
|
|
return &uint16Comparer{}
|
|
case uint32:
|
|
return &uint32Comparer{}
|
|
case uint64:
|
|
return &uint64Comparer{}
|
|
case string:
|
|
return &stringComparer{}
|
|
case []byte:
|
|
return &byteSliceComparer{}
|
|
}
|
|
|
|
// Fallback to reflection-based comparer otherwise.
|
|
// This is used when caller wraps a type around a primitive type.
|
|
switch reflect.TypeOf(key).Kind() {
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
return &reflectIntComparer{}
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
|
return &reflectUintComparer{}
|
|
case reflect.String:
|
|
return &reflectStringComparer{}
|
|
}
|
|
|
|
// If no comparers match then panic.
|
|
// This is a compile time issue so it should not return an error.
|
|
panic(fmt.Sprintf("immutable.NewComparer: must set comparer for %T type", key))
|
|
}
|
|
|
|
// intComparer compares two integers. Implements Comparer.
|
|
type intComparer struct{}
|
|
|
|
// Compare returns -1 if a is less than b, returns 1 if a is greater than b, and
|
|
// returns 0 if a is equal to b. Panic if a or b is not an int.
|
|
func (c *intComparer) Compare(a, b interface{}) int {
|
|
if i, j := a.(int), b.(int); i < j {
|
|
return -1
|
|
} else if i > j {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// int8Comparer compares two int8 values. Implements Comparer.
|
|
type int8Comparer struct{}
|
|
|
|
// Compare returns -1 if a is less than b, returns 1 if a is greater than b, and
|
|
// returns 0 if a is equal to b. Panic if a or b is not an int8.
|
|
func (c *int8Comparer) Compare(a, b interface{}) int {
|
|
if i, j := a.(int8), b.(int8); i < j {
|
|
return -1
|
|
} else if i > j {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// int16Comparer compares two int16 values. Implements Comparer.
|
|
type int16Comparer struct{}
|
|
|
|
// Compare returns -1 if a is less than b, returns 1 if a is greater than b, and
|
|
// returns 0 if a is equal to b. Panic if a or b is not an int16.
|
|
func (c *int16Comparer) Compare(a, b interface{}) int {
|
|
if i, j := a.(int16), b.(int16); i < j {
|
|
return -1
|
|
} else if i > j {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// int32Comparer compares two int32 values. Implements Comparer.
|
|
type int32Comparer struct{}
|
|
|
|
// Compare returns -1 if a is less than b, returns 1 if a is greater than b, and
|
|
// returns 0 if a is equal to b. Panic if a or b is not an int32.
|
|
func (c *int32Comparer) Compare(a, b interface{}) int {
|
|
if i, j := a.(int32), b.(int32); i < j {
|
|
return -1
|
|
} else if i > j {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// int64Comparer compares two int64 values. Implements Comparer.
|
|
type int64Comparer struct{}
|
|
|
|
// Compare returns -1 if a is less than b, returns 1 if a is greater than b, and
|
|
// returns 0 if a is equal to b. Panic if a or b is not an int64.
|
|
func (c *int64Comparer) Compare(a, b interface{}) int {
|
|
if i, j := a.(int64), b.(int64); i < j {
|
|
return -1
|
|
} else if i > j {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// uintComparer compares two uint values. Implements Comparer.
|
|
type uintComparer struct{}
|
|
|
|
// Compare returns -1 if a is less than b, returns 1 if a is greater than b, and
|
|
// returns 0 if a is equal to b. Panic if a or b is not an uint.
|
|
func (c *uintComparer) Compare(a, b interface{}) int {
|
|
if i, j := a.(uint), b.(uint); i < j {
|
|
return -1
|
|
} else if i > j {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// uint8Comparer compares two uint8 values. Implements Comparer.
|
|
type uint8Comparer struct{}
|
|
|
|
// Compare returns -1 if a is less than b, returns 1 if a is greater than b, and
|
|
// returns 0 if a is equal to b. Panic if a or b is not an uint8.
|
|
func (c *uint8Comparer) Compare(a, b interface{}) int {
|
|
if i, j := a.(uint8), b.(uint8); i < j {
|
|
return -1
|
|
} else if i > j {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// uint16Comparer compares two uint16 values. Implements Comparer.
|
|
type uint16Comparer struct{}
|
|
|
|
// Compare returns -1 if a is less than b, returns 1 if a is greater than b, and
|
|
// returns 0 if a is equal to b. Panic if a or b is not an uint16.
|
|
func (c *uint16Comparer) Compare(a, b interface{}) int {
|
|
if i, j := a.(uint16), b.(uint16); i < j {
|
|
return -1
|
|
} else if i > j {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// uint32Comparer compares two uint32 values. Implements Comparer.
|
|
type uint32Comparer struct{}
|
|
|
|
// Compare returns -1 if a is less than b, returns 1 if a is greater than b, and
|
|
// returns 0 if a is equal to b. Panic if a or b is not an uint32.
|
|
func (c *uint32Comparer) Compare(a, b interface{}) int {
|
|
if i, j := a.(uint32), b.(uint32); i < j {
|
|
return -1
|
|
} else if i > j {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// uint64Comparer compares two uint64 values. Implements Comparer.
|
|
type uint64Comparer struct{}
|
|
|
|
// Compare returns -1 if a is less than b, returns 1 if a is greater than b, and
|
|
// returns 0 if a is equal to b. Panic if a or b is not an uint64.
|
|
func (c *uint64Comparer) Compare(a, b interface{}) int {
|
|
if i, j := a.(uint64), b.(uint64); i < j {
|
|
return -1
|
|
} else if i > j {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// stringComparer compares two strings. Implements Comparer.
|
|
type stringComparer struct{}
|
|
|
|
// Compare returns -1 if a is less than b, returns 1 if a is greater than b, and
|
|
// returns 0 if a is equal to b. Panic if a or b is not a string.
|
|
func (c *stringComparer) Compare(a, b interface{}) int {
|
|
return strings.Compare(a.(string), b.(string))
|
|
}
|
|
|
|
// byteSliceComparer compares two byte slices. Implements Comparer.
|
|
type byteSliceComparer struct{}
|
|
|
|
// Compare returns -1 if a is less than b, returns 1 if a is greater than b, and
|
|
// returns 0 if a is equal to b. Panic if a or b is not a byte slice.
|
|
func (c *byteSliceComparer) Compare(a, b interface{}) int {
|
|
return bytes.Compare(a.([]byte), b.([]byte))
|
|
}
|
|
|
|
// reflectIntComparer compares two int values using reflection. Implements Comparer.
|
|
type reflectIntComparer struct{}
|
|
|
|
// Compare returns -1 if a is less than b, returns 1 if a is greater than b, and
|
|
// returns 0 if a is equal to b. Panic if a or b is not an int.
|
|
func (c *reflectIntComparer) Compare(a, b interface{}) int {
|
|
if i, j := reflect.ValueOf(a).Int(), reflect.ValueOf(b).Int(); i < j {
|
|
return -1
|
|
} else if i > j {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// reflectUintComparer compares two uint values using reflection. Implements Comparer.
|
|
type reflectUintComparer struct{}
|
|
|
|
// Compare returns -1 if a is less than b, returns 1 if a is greater than b, and
|
|
// returns 0 if a is equal to b. Panic if a or b is not an int.
|
|
func (c *reflectUintComparer) Compare(a, b interface{}) int {
|
|
if i, j := reflect.ValueOf(a).Uint(), reflect.ValueOf(b).Uint(); i < j {
|
|
return -1
|
|
} else if i > j {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// reflectStringComparer compares two string values using reflection. Implements Comparer.
|
|
type reflectStringComparer struct{}
|
|
|
|
// Compare returns -1 if a is less than b, returns 1 if a is greater than b, and
|
|
// returns 0 if a is equal to b. Panic if a or b is not an int.
|
|
func (c *reflectStringComparer) Compare(a, b interface{}) int {
|
|
return strings.Compare(reflect.ValueOf(a).String(), reflect.ValueOf(b).String())
|
|
}
|
|
|
|
func assert(condition bool, message string) {
|
|
if !condition {
|
|
panic(message)
|
|
}
|
|
}
|