github.com/Finschia/finschia-sdk@v0.48.1/types/kv/list.go (about) 1 package kv 2 3 // This code was copied from golang.org/pkg/container/list, but specially adapted 4 // for use with kv.Pair to avoid the type assertion CPU expense of using Value with 5 // an interface, per https://github.com/cosmos/cosmos-sdk/issues/8810 6 // 7 // Copyright 2009 The Go Authors. All rights reserved. 8 // Use of this source code is governed by a BSD-style 9 // license that can be found in the LICENSE file. 10 11 // Element is an element of a linked list. 12 type Element struct { 13 // Next and previous pointers in the doubly-linked list of elements. 14 // To simplify the implementation, internally a list l is implemented 15 // as a ring, such that &l.root is both the next element of the last 16 // list element (l.Back()) and the previous element of the first list 17 // element (l.Front()). 18 next, prev *Element 19 20 // The list to which this element belongs. 21 list *List 22 23 // The value stored with this element. 24 Value *Pair 25 } 26 27 // Next returns the next list element or nil. 28 func (e *Element) Next() *Element { 29 if p := e.next; e.list != nil && p != &e.list.root { 30 return p 31 } 32 return nil 33 } 34 35 // Prev returns the previous list element or nil. 36 func (e *Element) Prev() *Element { 37 if p := e.prev; e.list != nil && p != &e.list.root { 38 return p 39 } 40 return nil 41 } 42 43 // List represents a doubly linked list. 44 // The zero value for List is an empty list ready to use. 45 type List struct { 46 root Element // sentinel list element, only &root, root.prev, and root.next are used 47 len int // current list length excluding (this) sentinel element 48 } 49 50 // Init initializes or clears list l. 51 func (l *List) Init() *List { 52 l.root.next = &l.root 53 l.root.prev = &l.root 54 l.len = 0 55 return l 56 } 57 58 // NewList returns an initialized list. 59 func NewList() *List { return new(List).Init() } 60 61 // Len returns the number of elements of list l. 62 // The complexity is O(1). 63 func (l *List) Len() int { return l.len } 64 65 // Front returns the first element of list l or nil if the list is empty. 66 func (l *List) Front() *Element { 67 if l.len == 0 { 68 return nil 69 } 70 return l.root.next 71 } 72 73 // Back returns the last element of list l or nil if the list is empty. 74 func (l *List) Back() *Element { 75 if l.len == 0 { 76 return nil 77 } 78 return l.root.prev 79 } 80 81 // lazyInit lazily initializes a zero List value. 82 func (l *List) lazyInit() { 83 if l.root.next == nil { 84 l.Init() 85 } 86 } 87 88 // insert inserts e after at, increments l.len, and returns e. 89 func (l *List) insert(e, at *Element) *Element { 90 e.prev = at 91 e.next = at.next 92 e.prev.next = e 93 e.next.prev = e 94 e.list = l 95 l.len++ 96 return e 97 } 98 99 // insertValue is a convenience wrapper for insert(&Element{Value: v}, at). 100 func (l *List) insertValue(v *Pair, at *Element) *Element { 101 return l.insert(&Element{Value: v}, at) 102 } 103 104 // remove removes e from its list, decrements l.len, and returns e. 105 func (l *List) remove(e *Element) *Element { 106 e.prev.next = e.next 107 e.next.prev = e.prev 108 e.next = nil // avoid memory leaks 109 e.prev = nil // avoid memory leaks 110 e.list = nil 111 l.len-- 112 return e 113 } 114 115 // move moves e to next to at and returns e. 116 // nolint: unparam 117 func (l *List) move(e, at *Element) *Element { 118 if e == at { 119 return e 120 } 121 e.prev.next = e.next 122 e.next.prev = e.prev 123 124 e.prev = at 125 e.next = at.next 126 e.prev.next = e 127 e.next.prev = e 128 129 return e 130 } 131 132 // Remove removes e from l if e is an element of list l. 133 // It returns the element value e.Value. 134 // The element must not be nil. 135 func (l *List) Remove(e *Element) *Pair { 136 if e.list == l { 137 // if e.list == l, l must have been initialized when e was inserted 138 // in l or l == nil (e is a zero Element) and l.remove will crash 139 l.remove(e) 140 } 141 return e.Value 142 } 143 144 // PushFront inserts a new element e with value v at the front of list l and returns e. 145 func (l *List) PushFront(v *Pair) *Element { 146 l.lazyInit() 147 return l.insertValue(v, &l.root) 148 } 149 150 // PushBack inserts a new element e with value v at the back of list l and returns e. 151 func (l *List) PushBack(v *Pair) *Element { 152 l.lazyInit() 153 return l.insertValue(v, l.root.prev) 154 } 155 156 // InsertBefore inserts a new element e with value v immediately before mark and returns e. 157 // If mark is not an element of l, the list is not modified. 158 // The mark must not be nil. 159 func (l *List) InsertBefore(v *Pair, mark *Element) *Element { 160 if mark.list != l { 161 return nil 162 } 163 // see comment in List.Remove about initialization of l 164 return l.insertValue(v, mark.prev) 165 } 166 167 // InsertAfter inserts a new element e with value v immediately after mark and returns e. 168 // If mark is not an element of l, the list is not modified. 169 // The mark must not be nil. 170 func (l *List) InsertAfter(v *Pair, mark *Element) *Element { 171 if mark.list != l { 172 return nil 173 } 174 // see comment in List.Remove about initialization of l 175 return l.insertValue(v, mark) 176 } 177 178 // MoveToFront moves element e to the front of list l. 179 // If e is not an element of l, the list is not modified. 180 // The element must not be nil. 181 func (l *List) MoveToFront(e *Element) { 182 if e.list != l || l.root.next == e { 183 return 184 } 185 // see comment in List.Remove about initialization of l 186 l.move(e, &l.root) 187 } 188 189 // MoveToBack moves element e to the back of list l. 190 // If e is not an element of l, the list is not modified. 191 // The element must not be nil. 192 func (l *List) MoveToBack(e *Element) { 193 if e.list != l || l.root.prev == e { 194 return 195 } 196 // see comment in List.Remove about initialization of l 197 l.move(e, l.root.prev) 198 } 199 200 // MoveBefore moves element e to its new position before mark. 201 // If e or mark is not an element of l, or e == mark, the list is not modified. 202 // The element and mark must not be nil. 203 func (l *List) MoveBefore(e, mark *Element) { 204 if e.list != l || e == mark || mark.list != l { 205 return 206 } 207 l.move(e, mark.prev) 208 } 209 210 // MoveAfter moves element e to its new position after mark. 211 // If e or mark is not an element of l, or e == mark, the list is not modified. 212 // The element and mark must not be nil. 213 func (l *List) MoveAfter(e, mark *Element) { 214 if e.list != l || e == mark || mark.list != l { 215 return 216 } 217 l.move(e, mark) 218 } 219 220 // PushBackList inserts a copy of another list at the back of list l. 221 // The lists l and other may be the same. They must not be nil. 222 func (l *List) PushBackList(other *List) { 223 l.lazyInit() 224 for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() { 225 l.insertValue(e.Value, l.root.prev) 226 } 227 } 228 229 // PushFrontList inserts a copy of another list at the front of list l. 230 // The lists l and other may be the same. They must not be nil. 231 func (l *List) PushFrontList(other *List) { 232 l.lazyInit() 233 for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() { 234 l.insertValue(e.Value, &l.root) 235 } 236 }