mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-03 21:42:25 -06:00 
			
		
		
		
	
		
			
	
	
		
			160 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			160 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 
								 | 
							
								package maps
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import (
							 | 
						||
| 
								 | 
							
									"fmt"
							 | 
						||
| 
								 | 
							
									"reflect"
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// OrderedMap provides a hashmap implementation that tracks the order in which keys are added.
							 | 
						||
| 
								 | 
							
								type OrderedMap[K comparable, V any] struct {
							 | 
						||
| 
								 | 
							
									ordered[K, V]
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// NewOrdered returns a new instance of LRUMap with given initializing length and maximum capacity.
							 | 
						||
| 
								 | 
							
								func NewOrdered[K comparable, V any](len int) *OrderedMap[K, V] {
							 | 
						||
| 
								 | 
							
									m := new(OrderedMap[K, V])
							 | 
						||
| 
								 | 
							
									m.Init(len)
							 | 
						||
| 
								 | 
							
									return m
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Init will initialize this map with initial length.
							 | 
						||
| 
								 | 
							
								func (m *OrderedMap[K, V]) Init(len int) {
							 | 
						||
| 
								 | 
							
									if m.pool != nil {
							 | 
						||
| 
								 | 
							
										panic("ordered map already initialized")
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									m.ordered.hmap = make(map[K]*elem[K, V], len)
							 | 
						||
| 
								 | 
							
									m.ordered.pool = allocElems[K, V](len)
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Get will fetch value for given key from map. Returns false if not found.
							 | 
						||
| 
								 | 
							
								func (m *OrderedMap[K, V]) Get(key K) (V, bool) {
							 | 
						||
| 
								 | 
							
									if elem, ok := m.hmap[key]; ok {
							 | 
						||
| 
								 | 
							
										return elem.V, true
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									var z V // zero value
							 | 
						||
| 
								 | 
							
									return z, false
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Add will add the given key-value pair to the map, returns false if already exists.
							 | 
						||
| 
								 | 
							
								func (m *OrderedMap[K, V]) Add(key K, value V) bool {
							 | 
						||
| 
								 | 
							
									// Ensure safe
							 | 
						||
| 
								 | 
							
									m.write_check()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Look for existing elem
							 | 
						||
| 
								 | 
							
									elem, ok := m.hmap[key]
							 | 
						||
| 
								 | 
							
									if ok {
							 | 
						||
| 
								 | 
							
										return false
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Allocate elem
							 | 
						||
| 
								 | 
							
									elem = m.alloc()
							 | 
						||
| 
								 | 
							
									elem.K = key
							 | 
						||
| 
								 | 
							
									elem.V = value
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Add element map entry
							 | 
						||
| 
								 | 
							
									m.hmap[key] = elem
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Push to back of list
							 | 
						||
| 
								 | 
							
									m.list.PushBack(elem)
							 | 
						||
| 
								 | 
							
									return true
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Set will ensure that given key-value pair exists in the map, by either adding new or updating existing.
							 | 
						||
| 
								 | 
							
								func (m *OrderedMap[K, V]) Set(key K, value V) {
							 | 
						||
| 
								 | 
							
									// Ensure safe
							 | 
						||
| 
								 | 
							
									m.write_check()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Look for existing elem
							 | 
						||
| 
								 | 
							
									elem, ok := m.hmap[key]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ok {
							 | 
						||
| 
								 | 
							
										// Update existing
							 | 
						||
| 
								 | 
							
										elem.V = value
							 | 
						||
| 
								 | 
							
									} else {
							 | 
						||
| 
								 | 
							
										// Allocate elem
							 | 
						||
| 
								 | 
							
										elem = m.alloc()
							 | 
						||
| 
								 | 
							
										elem.K = key
							 | 
						||
| 
								 | 
							
										elem.V = value
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Add element map entry
							 | 
						||
| 
								 | 
							
										m.hmap[key] = elem
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Push to back of list
							 | 
						||
| 
								 | 
							
										m.list.PushBack(elem)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Index returns the key-value pair at index from map. Returns false if index out of range.
							 | 
						||
| 
								 | 
							
								func (m *OrderedMap[K, V]) Index(idx int) (K, V, bool) {
							 | 
						||
| 
								 | 
							
									if idx < 0 || idx >= m.list.len {
							 | 
						||
| 
								 | 
							
										var (
							 | 
						||
| 
								 | 
							
											zk K
							 | 
						||
| 
								 | 
							
											zv V
							 | 
						||
| 
								 | 
							
										) // zero values
							 | 
						||
| 
								 | 
							
										return zk, zv, false
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									elem := m.list.Index(idx)
							 | 
						||
| 
								 | 
							
									return elem.K, elem.V, true
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Push will insert the given key-value pair at index in the map. Panics if index out of range.
							 | 
						||
| 
								 | 
							
								func (m *OrderedMap[K, V]) Push(idx int, key K, value V) {
							 | 
						||
| 
								 | 
							
									// Check index within bounds of map
							 | 
						||
| 
								 | 
							
									if idx < 0 || idx >= m.list.len {
							 | 
						||
| 
								 | 
							
										panic("index out of bounds")
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Ensure safe
							 | 
						||
| 
								 | 
							
									m.write_check()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Get element at index
							 | 
						||
| 
								 | 
							
									next := m.list.Index(idx)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Allocate new elem
							 | 
						||
| 
								 | 
							
									elem := m.alloc()
							 | 
						||
| 
								 | 
							
									elem.K = key
							 | 
						||
| 
								 | 
							
									elem.V = value
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Add element map entry
							 | 
						||
| 
								 | 
							
									m.hmap[key] = elem
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Move next forward
							 | 
						||
| 
								 | 
							
									elem.next = next
							 | 
						||
| 
								 | 
							
									elem.prev = next.prev
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Link up elem in chain
							 | 
						||
| 
								 | 
							
									next.prev.next = elem
							 | 
						||
| 
								 | 
							
									next.prev = elem
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Pop will remove and return the key-value pair at index in the map. Panics if index out of range.
							 | 
						||
| 
								 | 
							
								func (m *OrderedMap[K, V]) Pop(idx int) (K, V) {
							 | 
						||
| 
								 | 
							
									// Check index within bounds of map
							 | 
						||
| 
								 | 
							
									if idx < 0 || idx >= m.list.len {
							 | 
						||
| 
								 | 
							
										panic("index out of bounds")
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Ensure safe
							 | 
						||
| 
								 | 
							
									m.write_check()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Get element at index
							 | 
						||
| 
								 | 
							
									elem := m.list.Index(idx)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Unlink elem from list
							 | 
						||
| 
								 | 
							
									m.list.Unlink(elem)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Get elem values
							 | 
						||
| 
								 | 
							
									k := elem.K
							 | 
						||
| 
								 | 
							
									v := elem.V
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Release to pool
							 | 
						||
| 
								 | 
							
									m.free(elem)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return k, v
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Format implements fmt.Formatter, allowing performant string formatting of map.
							 | 
						||
| 
								 | 
							
								func (m *OrderedMap[K, V]) Format(state fmt.State, verb rune) {
							 | 
						||
| 
								 | 
							
									m.format(reflect.TypeOf(m), state, verb)
							 | 
						||
| 
								 | 
							
								}
							 |