github.com/urso/go-structform@v0.0.2/gotype/symbols.go (about) 1 package gotype 2 3 type symbolCache struct { 4 m map[string]*symbol 5 lst symbolList 6 max int 7 } 8 9 type symbol struct { 10 value string 11 prev *symbol 12 next *symbol 13 } 14 15 type symbolList symbol 16 17 func (c *symbolCache) init(max int) { 18 c.max = max 19 c.m = make(map[string]*symbol, max) 20 c.lst = symbolList{} 21 c.lst.prev = (*symbol)(&c.lst) 22 c.lst.next = (*symbol)(&c.lst) 23 } 24 25 func (c *symbolCache) enabled() bool { 26 return c.m != nil 27 } 28 29 func (c *symbolCache) get(in []byte) string { 30 if !c.enabled() { 31 return string(in) 32 } 33 34 if sym := c.lookup(bytes2Str(in)); sym != nil { 35 return sym.value 36 } 37 38 str := string(in) 39 c.add(str) 40 return str 41 } 42 43 func (c *symbolCache) lookup(value string) *symbol { 44 sym := c.m[value] 45 if sym != nil { 46 removeLst(sym) 47 c.lst.append(sym) 48 } 49 return sym 50 } 51 52 func (c *symbolCache) add(value string) { 53 if len(c.m) == c.max { 54 old := c.lst.pop() 55 delete(c.m, old.value) 56 } 57 58 sym := &symbol{value: value} 59 c.m[value] = sym 60 c.lst.append(sym) 61 } 62 63 func (l *symbolList) empty() bool { 64 s := (*symbol)(l) 65 return s.next == s && s.prev == s 66 } 67 68 func (l *symbolList) append(sym *symbol) { 69 head := (*symbol)(l) 70 71 sym.prev = head.prev 72 sym.next = head 73 head.prev.next = sym 74 head.prev = sym 75 } 76 77 func (l *symbolList) pop() (sym *symbol) { 78 if !l.empty() { 79 sym = l.next 80 removeLst(sym) 81 } 82 return 83 } 84 85 func removeLst(s *symbol) { 86 s.prev.next = s.next 87 s.next.prev = s.prev 88 }