diff options
| author | 2026-02-14 00:55:12 +0300 | |
|---|---|---|
| committer | 2026-02-14 01:07:49 +0300 | |
| commit | adaaa6bd68a4af7c2e9a7f4c2ed2036a369d707d (patch) | |
| tree | 0f8c85af9456f1edd3b96a75a36f9b96e4ebecc3 /container/smap.go | |
| download | std-adaaa6bd68a4af7c2e9a7f4c2ed2036a369d707d.tar.gz std-adaaa6bd68a4af7c2e9a7f4c2ed2036a369d707d.tar.bz2 std-adaaa6bd68a4af7c2e9a7f4c2ed2036a369d707d.tar.xz std-adaaa6bd68a4af7c2e9a7f4c2ed2036a369d707d.zip | |
Diffstat (limited to 'container/smap.go')
| -rw-r--r-- | container/smap.go | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/container/smap.go b/container/smap.go new file mode 100644 index 0000000..688ec40 --- /dev/null +++ b/container/smap.go @@ -0,0 +1,104 @@ +package container + +import ( + "slices" + "sync" +) + +// M is ordered and concurent safe map implementation. +type M[K comparable, V any] struct { + m map[K]V + k []K + mu sync.RWMutex +} + +// Make returns new instance with `capacity` initial capacity. +func Make[K comparable, V any](capacity int) M[K, V] { + return M[K, V]{ + m: make(map[K]V, capacity), + k: make([]K, 0, capacity), + } +} + +// Get value `V` by key `k K`. Returns zero value if the key is absent. +func (m *M[K, V]) Get(k K) V { + m.mu.RLock() + defer m.mu.RUnlock() + + return m.m[k] +} + +// Get2 value `v V` by key `k K` and a presence flag `ok bool`. Returns +// `(value, true)` if the key exists, and `(zero value, false)` if the key is +// absent. +func (m *M[K, V]) Get2(k K) (v V, ok bool) { + m.mu.RLock() + defer m.mu.RUnlock() + v, ok = m.m[k] + + return v, ok +} + +// Has returns true if key `k K` exists in map. +func (m *M[K, V]) Has(k K) bool { + m.mu.RLock() + defer m.mu.RUnlock() + + _, ok := m.m[k] + + return ok +} + +// Set value `v V` to key `k K`. +func (m *M[K, V]) Set(k K, v V) { + m.mu.Lock() + defer m.mu.Unlock() + + if _, exists := m.m[k]; !exists { + m.k = append(m.k, k) + } + + m.m[k] = v +} + +// Delete key `k K` from map. +func (m *M[K, V]) Delete(k K) { + m.mu.Lock() + defer m.mu.Unlock() + + if _, ok := m.m[k]; !ok { + return + } + + idx := slices.Index(m.k, k) + m.k = slices.Delete(m.k, idx, idx+1) + + delete(m.m, k) +} + +// Keys is iterator over keys. +func (m *M[K, V]) Keys(yield func(K) bool) { + for _, k := range m.k { + if !yield(k) { + break + } + } +} + +// Values is iterator over values. +func (m *M[K, V]) Values(yield func(V) bool) { + for _, k := range m.k { + if !yield(m.m[k]) { + break + } + } +} + +// Entries is iterator over key:value pairs. +func (m *M[K, V]) Entries(yield func(K, V) bool) { + for _, k := range m.k { + if !yield(k, m.m[k]) { + break + } + } +} |
