github.com/gop9/olt@v0.0.0-20200202132135-d956aad50b08/gio/text/lru.go (about) 1 // SPDX-License-Identifier: Unlicense OR MIT 2 3 package text 4 5 import ( 6 "github.com/gop9/olt/gio/op" 7 "golang.org/x/image/math/fixed" 8 ) 9 10 type layoutCache struct { 11 m map[layoutKey]*layoutElem 12 head, tail *layoutElem 13 } 14 15 type pathCache struct { 16 m map[pathKey]*path 17 head, tail *path 18 } 19 20 type layoutElem struct { 21 next, prev *layoutElem 22 key layoutKey 23 layout *Layout 24 } 25 26 type path struct { 27 next, prev *path 28 key pathKey 29 val op.CallOp 30 } 31 32 type layoutKey struct { 33 ppem fixed.Int26_6 34 str string 35 opts LayoutOptions 36 } 37 38 type pathKey struct { 39 ppem fixed.Int26_6 40 str string 41 } 42 43 const maxSize = 1000 44 45 func (l *layoutCache) Get(k layoutKey) (*Layout, bool) { 46 if lt, ok := l.m[k]; ok { 47 l.remove(lt) 48 l.insert(lt) 49 return lt.layout, true 50 } 51 return nil, false 52 } 53 54 func (l *layoutCache) Put(k layoutKey, lt *Layout) { 55 if l.m == nil { 56 l.m = make(map[layoutKey]*layoutElem) 57 l.head = new(layoutElem) 58 l.tail = new(layoutElem) 59 l.head.prev = l.tail 60 l.tail.next = l.head 61 } 62 val := &layoutElem{key: k, layout: lt} 63 l.m[k] = val 64 l.insert(val) 65 if len(l.m) > maxSize { 66 oldest := l.tail.next 67 l.remove(oldest) 68 delete(l.m, oldest.key) 69 } 70 } 71 72 func (l *layoutCache) remove(lt *layoutElem) { 73 lt.next.prev = lt.prev 74 lt.prev.next = lt.next 75 } 76 77 func (l *layoutCache) insert(lt *layoutElem) { 78 lt.next = l.head 79 lt.prev = l.head.prev 80 lt.prev.next = lt 81 lt.next.prev = lt 82 } 83 84 func (c *pathCache) Get(k pathKey) (op.CallOp, bool) { 85 if v, ok := c.m[k]; ok { 86 c.remove(v) 87 c.insert(v) 88 return v.val, true 89 } 90 return op.CallOp{}, false 91 } 92 93 func (c *pathCache) Put(k pathKey, v op.CallOp) { 94 if c.m == nil { 95 c.m = make(map[pathKey]*path) 96 c.head = new(path) 97 c.tail = new(path) 98 c.head.prev = c.tail 99 c.tail.next = c.head 100 } 101 val := &path{key: k, val: v} 102 c.m[k] = val 103 c.insert(val) 104 if len(c.m) > maxSize { 105 oldest := c.tail.next 106 c.remove(oldest) 107 delete(c.m, oldest.key) 108 } 109 } 110 111 func (c *pathCache) remove(v *path) { 112 v.next.prev = v.prev 113 v.prev.next = v.next 114 } 115 116 func (c *pathCache) insert(v *path) { 117 v.next = c.head 118 v.prev = c.head.prev 119 v.prev.next = v 120 v.next.prev = v 121 }