mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2024-12-08 14:36:32 +01:00
adf345f1ec
* update go-structr library -> v0.6.0, add necessary wrapping types + code changes to support these changes
* update readme with go-structr package changes
* improved wrapping of the SliceCache type
* add code comments for the cache wrapper types
* remove test.out 😇
---------
Co-authored-by: tobi <31960611+tsmethurst@users.noreply.github.com>
170 lines
2.7 KiB
Go
170 lines
2.7 KiB
Go
package structr
|
|
|
|
import (
|
|
"sync"
|
|
"unsafe"
|
|
)
|
|
|
|
// elem represents an elem
|
|
// in a doubly-linked list.
|
|
type list_elem struct {
|
|
next *list_elem
|
|
prev *list_elem
|
|
|
|
// data is a ptr to the
|
|
// value this linked list
|
|
// element is embedded-in.
|
|
data unsafe.Pointer
|
|
}
|
|
|
|
// list implements a doubly-linked list, where:
|
|
// - head = index 0 (i.e. the front)
|
|
// - tail = index n-1 (i.e. the back)
|
|
type list struct {
|
|
head *list_elem
|
|
tail *list_elem
|
|
len int
|
|
}
|
|
|
|
var list_pool sync.Pool
|
|
|
|
// new_list returns a new prepared list.
|
|
func new_list() *list {
|
|
v := list_pool.Get()
|
|
if v == nil {
|
|
v = new(list)
|
|
}
|
|
list := v.(*list)
|
|
return list
|
|
}
|
|
|
|
// free_list releases the list.
|
|
func free_list(list *list) {
|
|
list.head = nil
|
|
list.tail = nil
|
|
list.len = 0
|
|
list_pool.Put(list)
|
|
}
|
|
|
|
// push_front will push the given elem to front (head) of list.
|
|
func (l *list) push_front(elem *list_elem) {
|
|
if l.len == 0 {
|
|
// Set new tail + head
|
|
l.head = elem
|
|
l.tail = elem
|
|
|
|
// Link elem to itself
|
|
elem.next = elem
|
|
elem.prev = elem
|
|
} else {
|
|
oldHead := l.head
|
|
|
|
// Link to old head
|
|
elem.next = oldHead
|
|
oldHead.prev = elem
|
|
|
|
// Link up to tail
|
|
elem.prev = l.tail
|
|
l.tail.next = elem
|
|
|
|
// Set new head
|
|
l.head = elem
|
|
}
|
|
|
|
// Incr count
|
|
l.len++
|
|
}
|
|
|
|
// push_back will push the given elem to back (tail) of list.
|
|
func (l *list) push_back(elem *list_elem) {
|
|
if l.len == 0 {
|
|
// Set new tail + head
|
|
l.head = elem
|
|
l.tail = elem
|
|
|
|
// Link elem to itself
|
|
elem.next = elem
|
|
elem.prev = elem
|
|
} else {
|
|
oldTail := l.tail
|
|
|
|
// Link to old tail
|
|
elem.prev = oldTail
|
|
oldTail.next = elem
|
|
|
|
// Link up to head
|
|
elem.next = l.head
|
|
l.head.prev = elem
|
|
|
|
// Set new tail
|
|
l.tail = elem
|
|
}
|
|
|
|
// Incr count
|
|
l.len++
|
|
}
|
|
|
|
// move_front will move given elem to front (head) of list.
|
|
func (l *list) move_front(elem *list_elem) {
|
|
l.remove(elem)
|
|
l.push_front(elem)
|
|
}
|
|
|
|
// move_back will move given elem to back (tail) of list.
|
|
func (l *list) move_back(elem *list_elem) {
|
|
l.remove(elem)
|
|
l.push_back(elem)
|
|
}
|
|
|
|
// remove will remove given elem from list.
|
|
func (l *list) remove(elem *list_elem) {
|
|
if l.len <= 1 {
|
|
// Drop elem's links
|
|
elem.next = nil
|
|
elem.prev = nil
|
|
|
|
// Only elem in list
|
|
l.head = nil
|
|
l.tail = nil
|
|
l.len = 0
|
|
return
|
|
}
|
|
|
|
// Get surrounding elems
|
|
next := elem.next
|
|
prev := elem.prev
|
|
|
|
// Relink chain
|
|
next.prev = prev
|
|
prev.next = next
|
|
|
|
switch elem {
|
|
// Set new head
|
|
case l.head:
|
|
l.head = next
|
|
|
|
// Set new tail
|
|
case l.tail:
|
|
l.tail = prev
|
|
}
|
|
|
|
// Drop elem's links
|
|
elem.next = nil
|
|
elem.prev = nil
|
|
|
|
// Decr count
|
|
l.len--
|
|
}
|
|
|
|
// rangefn will range all elems in list, passing each to fn.
|
|
func (l *list) rangefn(fn func(*list_elem)) {
|
|
if fn == nil {
|
|
panic("nil fn")
|
|
}
|
|
elem := l.head
|
|
for i := 0; i < l.len; i++ {
|
|
fn(elem)
|
|
elem = elem.next
|
|
}
|
|
}
|