alice-lg/pkg/pools/lists.go
2024-01-16 17:07:55 +01:00

75 lines
1.4 KiB
Go

package pools
import (
"sync"
)
// A IntListPool can be used to deduplicate
// lists of integers. Like an AS path or BGP communities.
//
// A Tree datastructure is used.
type IntListPool struct {
root *Node[int, []int]
counter uint64
sync.Mutex
}
// NewIntListPool creates a new int list pool
func NewIntListPool() *IntListPool {
return &IntListPool{
root: NewNode[int, []int]([]int{}),
}
}
// Acquire int list from pool
func (p *IntListPool) Acquire(list []int) []int {
p.Lock()
defer p.Unlock()
if len(list) == 0 {
return p.root.value // root
}
return p.root.traverse(list, list)
}
// A StringListPool can be used for deduplicating lists
// of strings. (This is a variant of an int list, as string
// values are converted to int.
type StringListPool struct {
root *Node[int, []string]
values map[string]int
head int
sync.Mutex
}
// NewStringListPool creates a new string list.
func NewStringListPool() *StringListPool {
return &StringListPool{
head: 1,
values: map[string]int{},
root: NewNode[int, []string]([]string{}),
}
}
// Acquire the string list pointer from the pool.
func (p *StringListPool) Acquire(list []string) []string {
if len(list) == 0 {
return p.root.value
}
// Make idenfier list
id := make([]int, len(list))
for i, s := range list {
// Resolve string value into int
v, ok := p.values[s]
if !ok {
p.head++
p.values[s] = p.head
v = p.head
}
id[i] = v
}
return p.root.traverse(list, id)
}