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  }