Common code for implementing Twitch bots.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
2.3 KiB

package lru
import (
"container/list"
"strings"
)
type slruEntry struct {
key string
val interface{}
}
// SLRU is an LRU for strings
type SLRU struct {
capacity int
list *list.List
lut map[string]*list.Element
}
// NewStringLRU creates a new string LRU with a maximum capacity.
func NewStringLRU(capacity int) *SLRU {
return &SLRU{
capacity: capacity,
list: list.New(),
lut: make(map[string]*list.Element),
}
}
// Size returns the elements in the LRU.
func (s *SLRU) Size() int {
return len(s.lut)
}
// Set adds the given value and returns true if the value was already in the
// cache.
func (s *SLRU) Set(key string, v interface{}) bool {
e := s.lut[key]
if e != nil {
e.Value = slruEntry{key: key, val: v}
s.list.MoveToFront(e)
return true
}
if s.capacity == 0 {
// Evict once
if last := s.list.Back(); last != nil {
s.list.Remove(last)
delete(s.lut, last.Value.(slruEntry).key)
}
} else {
s.capacity--
}
e = s.list.PushFront(slruEntry{key: key, val: v})
s.lut[key] = e
return false
}
// Get returns the value associated with the key, if it is in the cache.
func (s *SLRU) Get(key string) (interface{}, bool) {
e, ok := s.lut[key]
if !ok {
return nil, ok
}
return e.Value.(slruEntry).val, true
}
// Delete removes a key from the LRU and returns if the key was in the cache.
func (s *SLRU) Delete(key string) (interface{}, bool) {
e, ok := s.lut[key]
if !ok {
return nil, false
}
ret := e.Value.(slruEntry).val
s.list.Remove(e)
delete(s.lut, key)
s.capacity++
return ret, true
}
// Iter iterates over the list values in most-recent-to-last order,
func (s *SLRU) Iter(f func(key string, v interface{}) bool) {
for e := s.list.Front(); e != nil; e = e.Next() {
entry := e.Value.(slruEntry)
if !f(entry.key, entry.val) {
break
}
}
}
func (s *SLRU) TailRemove(f func(key string, v interface{}) bool) {
e := s.list.Back()
for e != nil {
c := e
e = e.Prev()
entry := c.Value.(slruEntry)
if !f(entry.key, entry.val) {
break
}
s.list.Remove(c)
}
}
// String returns a string representation of the LRU entries for debugging.
func (s *SLRU) String() string {
var repr []string
for e := s.list.Front(); e != nil; e = e.Next() {
repr = append(repr, e.Value.(slruEntry).key)
}
return strings.Join(repr, ",")
}