231 lines
6.4 KiB
Go
231 lines
6.4 KiB
Go
/*
|
|
* Copyright 2020 The Dragonfly Authors
|
|
*
|
|
* 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 syncmap
|
|
|
|
import (
|
|
"container/list"
|
|
"strconv"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
"go.uber.org/atomic"
|
|
|
|
"d7y.io/dragonfly/v2/internal/dferrors"
|
|
"d7y.io/dragonfly/v2/pkg/util/stringutils"
|
|
)
|
|
|
|
// SyncMap is a thread-safe map providing generic support
|
|
type SyncMap struct {
|
|
*sync.Map
|
|
}
|
|
|
|
// NewSyncMap returns a new SyncMap.
|
|
func NewSyncMap() *SyncMap {
|
|
return &SyncMap{&sync.Map{}}
|
|
}
|
|
|
|
// Add adds a key-value pair into the *sync.Map.
|
|
// The ErrEmptyValue error will be returned if the key is empty.
|
|
func (mmap *SyncMap) Add(key string, value interface{}) error {
|
|
if stringutils.IsBlank(key) {
|
|
return errors.Wrap(dferrors.ErrEmptyValue, "key")
|
|
}
|
|
mmap.Store(key, value)
|
|
return nil
|
|
}
|
|
|
|
// Get returns result as interface{} according to the key.
|
|
// The ErrEmptyValue error will be returned if the key is empty.
|
|
// And the ErrDataNotFound error will be returned if the key cannot be found.
|
|
func (mmap *SyncMap) Get(key string) (interface{}, error) {
|
|
if stringutils.IsBlank(key) {
|
|
return nil, errors.Wrap(dferrors.ErrEmptyValue, "key")
|
|
}
|
|
|
|
if v, ok := mmap.Load(key); ok {
|
|
return v, nil
|
|
}
|
|
|
|
return nil, errors.Wrapf(dferrors.ErrDataNotFound, "get key %s from map", key)
|
|
}
|
|
|
|
// GetAsMap returns result as SyncMap.
|
|
// The ErrConvertFailed error will be returned if the assertion fails.
|
|
func (mmap *SyncMap) GetAsMap(key string) (*SyncMap, error) {
|
|
v, err := mmap.Get(key)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "get key %s from map", key)
|
|
}
|
|
|
|
if value, ok := v.(*SyncMap); ok {
|
|
return value, nil
|
|
}
|
|
return nil, errors.Wrapf(dferrors.ErrConvertFailed, "get key %s from map with value %s", key, v)
|
|
}
|
|
|
|
// GetAsList returns result as list
|
|
// The ErrConvertFailed error will be returned if the assertion fails.
|
|
func (mmap *SyncMap) GetAsList(key string) (*list.List, error) {
|
|
v, err := mmap.Get(key)
|
|
if err != nil {
|
|
return list.New(), errors.Wrapf(err, "get key %s from map", key)
|
|
}
|
|
if value, ok := v.(*list.List); ok {
|
|
return value, nil
|
|
}
|
|
return nil, errors.Wrapf(dferrors.ErrConvertFailed, "get key %s from map with value %s", key, v)
|
|
}
|
|
|
|
// GetAsInt returns result as int.
|
|
// The ErrConvertFailed error will be returned if the assertion fails.
|
|
func (mmap *SyncMap) GetAsInt(key string) (int, error) {
|
|
v, err := mmap.Get(key)
|
|
if err != nil {
|
|
return 0, errors.Wrapf(err, "get key %s from map", key)
|
|
}
|
|
|
|
if value, ok := v.(int); ok {
|
|
return value, nil
|
|
}
|
|
return 0, errors.Wrapf(dferrors.ErrConvertFailed, "get key %s from map with value %s", key, v)
|
|
}
|
|
|
|
// GetAsInt64 returns result as int64.
|
|
// The ErrConvertFailed error will be returned if the assertion fails.
|
|
func (mmap *SyncMap) GetAsInt64(key string) (int64, error) {
|
|
v, err := mmap.Get(key)
|
|
if err != nil {
|
|
return 0, errors.Wrapf(err, "get key %s from map", key)
|
|
}
|
|
|
|
if value, ok := v.(int64); ok {
|
|
return value, nil
|
|
}
|
|
return 0, errors.Wrapf(dferrors.ErrConvertFailed, "get key %s from map with value %s", key, v)
|
|
}
|
|
|
|
// GetAsString returns result as string.
|
|
// The ErrConvertFailed error will be returned if the assertion fails.
|
|
func (mmap *SyncMap) GetAsString(key string) (string, error) {
|
|
v, err := mmap.Get(key)
|
|
if err != nil {
|
|
return "", errors.Wrapf(err, "get key %s from map", key)
|
|
}
|
|
|
|
if value, ok := v.(string); ok {
|
|
return value, nil
|
|
}
|
|
return "", errors.Wrapf(dferrors.ErrConvertFailed, "get key %s from map with value %s", key, v)
|
|
}
|
|
|
|
// GetAsBool returns result as bool.
|
|
// The ErrConvertFailed error will be returned if the assertion fails.
|
|
func (mmap *SyncMap) GetAsBool(key string) (bool, error) {
|
|
v, err := mmap.Get(key)
|
|
if err != nil {
|
|
return false, errors.Wrapf(err, "get key %s from map", key)
|
|
}
|
|
|
|
if value, ok := v.(bool); ok {
|
|
return value, nil
|
|
}
|
|
return false, errors.Wrapf(dferrors.ErrConvertFailed, "get key %s from map with value %s", key, v)
|
|
}
|
|
|
|
// GetAsAtomicInt returns result as *AtomicInt.
|
|
// The ErrConvertFailed error will be returned if the assertion fails.
|
|
func (mmap *SyncMap) GetAsAtomicInt(key string) (*atomic.Int32, error) {
|
|
v, err := mmap.Get(key)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "get key %s from map", key)
|
|
}
|
|
|
|
if value, ok := v.(*atomic.Int32); ok {
|
|
return value, nil
|
|
}
|
|
return nil, errors.Wrapf(dferrors.ErrConvertFailed, "get key %s from map with value %s", key, v)
|
|
}
|
|
|
|
// GetAsTime returns result as Time.
|
|
// The ErrConvertFailed error will be returned if the assertion fails.
|
|
func (mmap *SyncMap) GetAsTime(key string) (time.Time, error) {
|
|
v, err := mmap.Get(key)
|
|
if err != nil {
|
|
return time.Now(), errors.Wrapf(err, "get key %s from map", key)
|
|
}
|
|
|
|
if value, ok := v.(time.Time); ok {
|
|
return value, nil
|
|
}
|
|
return time.Now(), errors.Wrapf(dferrors.ErrConvertFailed, "get key %s from map with value %s", key, v)
|
|
}
|
|
|
|
// Remove deletes the key-value pair from the mmap.
|
|
// The ErrEmptyValue error will be returned if the key is empty.
|
|
// And the ErrDataNotFound error will be returned if the key cannot be found.
|
|
func (mmap *SyncMap) Remove(key string) error {
|
|
if stringutils.IsBlank(key) {
|
|
return errors.Wrap(dferrors.ErrEmptyValue, "key")
|
|
}
|
|
|
|
if _, ok := mmap.Load(key); !ok {
|
|
return errors.Wrapf(dferrors.ErrDataNotFound, "get key %s from map", key)
|
|
}
|
|
|
|
mmap.Delete(key)
|
|
return nil
|
|
}
|
|
|
|
// ListKeyAsStringSlice returns the list of keys as a string slice.
|
|
func (mmap *SyncMap) ListKeyAsStringSlice() (result []string) {
|
|
if mmap == nil {
|
|
return []string{}
|
|
}
|
|
|
|
rangeFunc := func(key, value interface{}) bool {
|
|
if v, ok := key.(string); ok {
|
|
result = append(result, v)
|
|
return true
|
|
}
|
|
return true
|
|
}
|
|
|
|
mmap.Range(rangeFunc)
|
|
return
|
|
}
|
|
|
|
// ListKeyAsIntSlice returns the list of keys as an int slice.
|
|
func (mmap *SyncMap) ListKeyAsIntSlice() (result []int) {
|
|
if mmap == nil {
|
|
return []int{}
|
|
}
|
|
|
|
rangeFunc := func(key, value interface{}) bool {
|
|
if v, ok := key.(string); ok {
|
|
if value, err := strconv.Atoi(v); err == nil {
|
|
result = append(result, value)
|
|
return true
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
mmap.Range(rangeFunc)
|
|
return
|
|
}
|