diff options
Diffstat (limited to 'vendor/codeberg.org/gruf/go-maps/common.go')
-rw-r--r-- | vendor/codeberg.org/gruf/go-maps/common.go | 293 |
1 files changed, 0 insertions, 293 deletions
diff --git a/vendor/codeberg.org/gruf/go-maps/common.go b/vendor/codeberg.org/gruf/go-maps/common.go deleted file mode 100644 index 0c92b41a2..000000000 --- a/vendor/codeberg.org/gruf/go-maps/common.go +++ /dev/null @@ -1,293 +0,0 @@ -package maps - -import ( - "fmt" - "reflect" - - "codeberg.org/gruf/go-byteutil" - "codeberg.org/gruf/go-kv" -) - -// ordered provides a common ordered hashmap base, storing order in a doubly-linked list. -type ordered[K comparable, V any] struct { - hmap map[K]*elem[K, V] - list list[K, V] - pool []*elem[K, V] - rnly bool -} - -// write_check panics if map is not in a safe-state to write to. -func (m *ordered[K, V]) write_check() { - if m.rnly { - panic("map write during read loop") - } -} - -// Has returns whether key exists in map. -func (m *ordered[K, V]) Has(key K) bool { - _, ok := m.hmap[key] - return ok -} - -// Delete will delete given key from map, returns false if not found. -func (m *ordered[K, V]) Delete(key K) bool { - // Ensure safe - m.write_check() - - // Look for existing elem - elem, ok := m.hmap[key] - if !ok { - return false - } - - // Drop from list - m.list.Unlink(elem) - - // Delete from map - delete(m.hmap, key) - - // Return to pool - m.free(elem) - - return true -} - -// Range passes given function over the requested range of the map. -func (m *ordered[K, V]) Range(start, length int, fn func(int, K, V)) { - // Nil check - if fn == nil { - panic("nil func") - } - - // Disallow writes - m.rnly = true - defer func() { - m.rnly = false - }() - - switch end := start + length; { - // No loop to iterate - case length == 0: - if start < 0 || (m.list.len > 0 && start >= m.list.len) { - panic("index out of bounds") - } - - // Step backwards - case length < 0: - // Check loop indices are within map bounds - if end < -1 || start >= m.list.len || m.list.len == 0 { - panic("index out of bounds") - } - - // Get starting index elem - elem := m.list.Index(start) - - for i := start; i > end; i-- { - fn(i, elem.K, elem.V) - elem = elem.prev - } - - // Step forwards - case length > 0: - // Check loop indices are within map bounds - if start < 0 || end > m.list.len || m.list.len == 0 { - panic("index out of bounds") - } - - // Get starting index elem - elem := m.list.Index(start) - - for i := start; i < end; i++ { - fn(i, elem.K, elem.V) - elem = elem.next - } - } -} - -// RangeIf passes given function over the requested range of the map. Returns early on 'fn' -> false. -func (m *ordered[K, V]) RangeIf(start, length int, fn func(int, K, V) bool) { - // Nil check - if fn == nil { - panic("nil func") - } - - // Disallow writes - m.rnly = true - defer func() { - m.rnly = false - }() - - switch end := start + length; { - // No loop to iterate - case length == 0: - if start < 0 || (m.list.len > 0 && start >= m.list.len) { - panic("index out of bounds") - } - - // Step backwards - case length < 0: - // Check loop indices are within map bounds - if end < -1 || start >= m.list.len || m.list.len == 0 { - panic("index out of bounds") - } - - // Get starting index elem - elem := m.list.Index(start) - - for i := start; i > end; i-- { - if !fn(i, elem.K, elem.V) { - return - } - elem = elem.prev - } - - // Step forwards - case length > 0: - // Check loop indices are within map bounds - if start < 0 || end > m.list.len || m.list.len == 0 { - panic("index out of bounds") - } - - // Get starting index elem - elem := m.list.Index(start) - - for i := start; i < end; i++ { - if !fn(i, elem.K, elem.V) { - return - } - elem = elem.next - } - } -} - -// Truncate will truncate the map from the back by given amount, passing dropped elements to given function. -func (m *ordered[K, V]) Truncate(sz int, fn func(K, V)) { - // Check size withing bounds - if sz > m.list.len { - panic("index out of bounds") - } - - // Nil check - if fn == nil { - fn = func(K, V) {} - } - - // Disallow writes - m.rnly = true - defer func() { - m.rnly = false - }() - - for i := 0; i < sz; i++ { - // Pop current tail - elem := m.list.tail - m.list.Unlink(elem) - - // Delete from map - delete(m.hmap, elem.K) - - // Pass dropped to func - fn(elem.K, elem.V) - - // Release to pool - m.free(elem) - } -} - -// Len returns the current length of the map. -func (m *ordered[K, V]) Len() int { - return m.list.len -} - -// format implements fmt.Formatter, allowing performant string formatting of map. -func (m *ordered[K, V]) format(rtype reflect.Type, state fmt.State, verb rune) { - var ( - kvbuf byteutil.Buffer - field kv.Field - vbose bool - ) - - switch { - // Only handle 'v' verb - case verb != 'v': - panic("invalid verb '" + string(verb) + "' for map") - - // Prefix with type when verbose - case state.Flag('#'): - state.Write([]byte(rtype.String())) - } - - // Disallow writes - m.rnly = true - defer func() { - m.rnly = false - }() - - // Write map opening brace - state.Write([]byte{'{'}) - - if m.list.len > 0 { - // Preallocate buffer - kvbuf.Guarantee(64) - - // Start at index 0 - elem := m.list.head - - for i := 0; i < m.list.len-1; i++ { - // Append formatted key-val pair to state - field.K = fmt.Sprint(elem.K) - field.V = elem.V - field.AppendFormat(&kvbuf, vbose) - _, _ = state.Write(kvbuf.B) - kvbuf.Reset() - - // Prepare buffer with comma separator - kvbuf.B = append(kvbuf.B, `, `...) - - // Jump to next in list - elem = elem.next - } - - // Append formatted key-val pair to state - field.K = fmt.Sprint(elem.K) - field.V = elem.V - field.AppendFormat(&kvbuf, vbose) - _, _ = state.Write(kvbuf.B) - } - - // Write map closing brace - state.Write([]byte{'}'}) -} - -// Std returns a clone of map's data in the standard library equivalent map type. -func (m *ordered[K, V]) Std() map[K]V { - std := make(map[K]V, m.list.len) - for _, elem := range m.hmap { - std[elem.K] = elem.V - } - return std -} - -// alloc will acquire list element from pool, or allocate new. -func (m *ordered[K, V]) alloc() *elem[K, V] { - if len(m.pool) == 0 { - return &elem[K, V]{} - } - idx := len(m.pool) - 1 - elem := m.pool[idx] - m.pool = m.pool[:idx] - return elem -} - -// free will reset elem fields and place back in pool. -func (m *ordered[K, V]) free(elem *elem[K, V]) { - var ( - zk K - zv V - ) - elem.K = zk - elem.V = zv - elem.next = nil - elem.prev = nil - m.pool = append(m.pool, elem) -} |