108 lines
2.0 KiB
Go
108 lines
2.0 KiB
Go
package cuckoo
|
|
|
|
// An Entry is a key-value pair.
|
|
type Entry[K, V any] struct {
|
|
Key K
|
|
Value V
|
|
}
|
|
|
|
type slot[K, V any] struct {
|
|
Entry[K, V]
|
|
occupied bool
|
|
}
|
|
|
|
type subtable[K, V any] struct {
|
|
hash Hash[K]
|
|
slots []slot[K, V]
|
|
capacity, size uint64
|
|
compare EqualFunc[K]
|
|
}
|
|
|
|
// location determines where in the subtable a certain key would be placed. If
|
|
// the capacity is 0, this will panic.
|
|
func (t *subtable[K, V]) location(key K) uint64 {
|
|
return t.hash(key) % t.capacity
|
|
}
|
|
|
|
func (t *subtable[K, V]) get(key K) (value V, found bool) {
|
|
if t.capacity == 0 {
|
|
return
|
|
}
|
|
|
|
slot := t.slots[t.location(key)]
|
|
return slot.Value, slot.occupied && t.compare(slot.Key, key)
|
|
}
|
|
|
|
func (t *subtable[K, V]) drop(key K) (occupied bool) {
|
|
if t.capacity == 0 {
|
|
return
|
|
}
|
|
|
|
slot := &t.slots[t.location(key)]
|
|
|
|
if slot.occupied && t.compare(slot.Key, key) {
|
|
slot.occupied = false
|
|
t.size--
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (t *subtable[K, V]) resized(capacity uint64) *subtable[K, V] {
|
|
return &subtable[K, V]{
|
|
slots: make([]slot[K, V], capacity),
|
|
capacity: capacity,
|
|
hash: t.hash,
|
|
compare: t.compare,
|
|
}
|
|
}
|
|
|
|
func (t *subtable[K, V]) update(key K, value V) (updated bool) {
|
|
if t.capacity == 0 {
|
|
return
|
|
}
|
|
|
|
slot := &t.slots[t.location(key)]
|
|
|
|
if slot.occupied && t.compare(slot.Key, key) {
|
|
slot.Value = value
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (t *subtable[K, V]) insert(insertion Entry[K, V]) (evicted Entry[K, V], eviction bool) {
|
|
if t.capacity == 0 {
|
|
return insertion, true
|
|
}
|
|
|
|
slot := &t.slots[t.location(insertion.Key)]
|
|
|
|
if !slot.occupied {
|
|
slot.Entry = insertion
|
|
slot.occupied = true
|
|
t.size++
|
|
return
|
|
}
|
|
|
|
if t.compare(slot.Key, insertion.Key) {
|
|
slot.Value = insertion.Value
|
|
return
|
|
}
|
|
|
|
insertion, slot.Entry = slot.Entry, insertion
|
|
return insertion, true
|
|
}
|
|
|
|
func newSubtable[K, V any](capacity uint64, hash Hash[K], compare EqualFunc[K]) *subtable[K, V] {
|
|
return &subtable[K, V]{
|
|
hash: hash,
|
|
capacity: capacity,
|
|
compare: compare,
|
|
size: 0,
|
|
slots: make([]slot[K, V], capacity),
|
|
}
|
|
}
|