mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-17 21:01:26 +02:00
133
common/maps/ordered.go
Normal file
133
common/maps/ordered.go
Normal file
@@ -0,0 +1,133 @@
|
||||
// Copyright 2024 The Hugo Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package maps
|
||||
|
||||
import (
|
||||
"github.com/gohugoio/hugo/common/hashing"
|
||||
)
|
||||
|
||||
// Ordered is a map that can be iterated in the order of insertion.
|
||||
// Note that insertion order is not affected if a key is re-inserted into the map.
|
||||
// In a nil map, all operations are no-ops.
|
||||
// This is not thread safe.
|
||||
type Ordered[K comparable, T any] struct {
|
||||
// The keys in the order they were added.
|
||||
keys []K
|
||||
// The values.
|
||||
values map[K]T
|
||||
}
|
||||
|
||||
// NewOrdered creates a new Ordered map.
|
||||
func NewOrdered[K comparable, T any]() *Ordered[K, T] {
|
||||
return &Ordered[K, T]{values: make(map[K]T)}
|
||||
}
|
||||
|
||||
// Set sets the value for the given key.
|
||||
// Note that insertion order is not affected if a key is re-inserted into the map.
|
||||
func (m *Ordered[K, T]) Set(key K, value T) {
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
// Check if key already exists.
|
||||
if _, found := m.values[key]; !found {
|
||||
m.keys = append(m.keys, key)
|
||||
}
|
||||
m.values[key] = value
|
||||
}
|
||||
|
||||
// Get gets the value for the given key.
|
||||
func (m *Ordered[K, T]) Get(key K) (T, bool) {
|
||||
if m == nil {
|
||||
var v T
|
||||
return v, false
|
||||
}
|
||||
value, found := m.values[key]
|
||||
return value, found
|
||||
}
|
||||
|
||||
// Delete deletes the value for the given key.
|
||||
func (m *Ordered[K, T]) Delete(key K) {
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
delete(m.values, key)
|
||||
for i, k := range m.keys {
|
||||
if k == key {
|
||||
m.keys = append(m.keys[:i], m.keys[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clone creates a shallow copy of the map.
|
||||
func (m *Ordered[K, T]) Clone() *Ordered[K, T] {
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
clone := NewOrdered[K, T]()
|
||||
for _, k := range m.keys {
|
||||
clone.Set(k, m.values[k])
|
||||
}
|
||||
return clone
|
||||
}
|
||||
|
||||
// Keys returns the keys in the order they were added.
|
||||
func (m *Ordered[K, T]) Keys() []K {
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
return m.keys
|
||||
}
|
||||
|
||||
// Values returns the values in the order they were added.
|
||||
func (m *Ordered[K, T]) Values() []T {
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
var values []T
|
||||
for _, k := range m.keys {
|
||||
values = append(values, m.values[k])
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
// Len returns the number of items in the map.
|
||||
func (m *Ordered[K, T]) Len() int {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
return len(m.keys)
|
||||
}
|
||||
|
||||
// Range calls f sequentially for each key and value present in the map.
|
||||
// If f returns false, range stops the iteration.
|
||||
// TODO(bep) replace with iter.Seq2 when we bump go Go 1.24.
|
||||
func (m *Ordered[K, T]) Range(f func(key K, value T) bool) {
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
for _, k := range m.keys {
|
||||
if !f(k, m.values[k]) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hash calculates a hash from the values.
|
||||
func (m *Ordered[K, T]) Hash() (uint64, error) {
|
||||
if m == nil {
|
||||
return 0, nil
|
||||
}
|
||||
return hashing.Hash(m.values)
|
||||
}
|
Reference in New Issue
Block a user