Initial QSfera import
This commit is contained in:
+359
@@ -0,0 +1,359 @@
|
||||
package maputil
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/gookit/goutil/arrutil"
|
||||
"github.com/gookit/goutil/internal/comfunc"
|
||||
"github.com/gookit/goutil/mathutil"
|
||||
"github.com/gookit/goutil/strutil"
|
||||
)
|
||||
|
||||
// Map alias of Data
|
||||
type Map = Data
|
||||
|
||||
// Data alias of map[string]any
|
||||
type Data map[string]any
|
||||
|
||||
// Has value on the data map
|
||||
func (d Data) Has(key string) bool {
|
||||
_, ok := d.GetByPath(key)
|
||||
return ok
|
||||
}
|
||||
|
||||
// IsEmpty if the data map
|
||||
func (d Data) IsEmpty() bool {
|
||||
return len(d) == 0
|
||||
}
|
||||
|
||||
//
|
||||
// endregion
|
||||
// region T: set value(s)
|
||||
//
|
||||
|
||||
// Set value to the data map
|
||||
func (d Data) Set(key string, val any) {
|
||||
d[key] = val
|
||||
}
|
||||
|
||||
// SetByPath sets a value in the map.
|
||||
// Supports dot syntax to set deep values.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// d.SetByPath("name.first", "Mat")
|
||||
func (d Data) SetByPath(path string, value any) error {
|
||||
if path == "" {
|
||||
return nil
|
||||
}
|
||||
return d.SetByKeys(strings.Split(path, KeySepStr), value)
|
||||
}
|
||||
|
||||
// SetByKeys sets a value in the map by path keys.
|
||||
// Supports dot syntax to set deep values.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// d.SetByKeys([]string{"name", "first"}, "Mat")
|
||||
func (d Data) SetByKeys(keys []string, value any) error {
|
||||
kln := len(keys)
|
||||
if kln == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// special handle d is empty.
|
||||
if len(d) == 0 {
|
||||
if kln == 1 {
|
||||
d.Set(keys[0], value)
|
||||
} else {
|
||||
d.Set(keys[0], MakeByKeys(keys[1:], value))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return SetByKeys((*map[string]any)(&d), keys, value)
|
||||
// It's ok, but use `func (d *Data)`
|
||||
// return SetByKeys((*map[string]any)(d), keys, value)
|
||||
}
|
||||
|
||||
//
|
||||
// endregion
|
||||
// region T: read value(s)
|
||||
//
|
||||
|
||||
// Value get from the data map
|
||||
func (d Data) Value(key string) (any, bool) {
|
||||
val, ok := d.GetByPath(key)
|
||||
return val, ok
|
||||
}
|
||||
|
||||
// Get value from the data map.
|
||||
// Supports dot syntax to get deep values. eg: top.sub
|
||||
func (d Data) Get(key string) any {
|
||||
if val, ok := d.GetByPath(key); ok {
|
||||
return val
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// One get value from the data by multi paths. will return first founded value
|
||||
func (d Data) One(keys ...string) any {
|
||||
if val, ok := d.TryOne(keys...); ok {
|
||||
return val
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TryOne get value from the data by multi paths. will return first founded value
|
||||
func (d Data) TryOne(keys ...string) (any, bool) {
|
||||
for _, path := range keys {
|
||||
if val, ok := d.GetByPath(path); ok {
|
||||
return val, true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// GetByPath get value from the data map by path. eg: top.sub
|
||||
// Supports dot syntax to get deep values.
|
||||
func (d Data) GetByPath(path string) (any, bool) {
|
||||
if val, ok := d[path]; ok {
|
||||
return val, true
|
||||
}
|
||||
|
||||
// is a key path.
|
||||
if strings.ContainsRune(path, '.') {
|
||||
val, ok := GetByPath(path, d)
|
||||
if ok {
|
||||
return val, true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Default get value from the data map with default value
|
||||
func (d Data) Default(key string, def any) any {
|
||||
if val, ok := d.GetByPath(key); ok {
|
||||
return val
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
// Int value get, or default value
|
||||
func (d Data) Int(key string, defVal ...int) int {
|
||||
if val, ok := d.GetByPath(key); ok {
|
||||
return mathutil.SafeInt(val)
|
||||
}
|
||||
if len(defVal) > 0 {
|
||||
return defVal[0]
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Int64 value get, or default value
|
||||
func (d Data) Int64(key string, defVal ...int64) int64 {
|
||||
if val, ok := d.GetByPath(key); ok {
|
||||
return mathutil.SafeInt64(val)
|
||||
}
|
||||
if len(defVal) > 0 {
|
||||
return defVal[0]
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Uint value get, or default value
|
||||
func (d Data) Uint(key string, defVal ...uint) uint {
|
||||
if val, ok := d.GetByPath(key); ok {
|
||||
return mathutil.QuietUint(val)
|
||||
}
|
||||
if len(defVal) > 0 {
|
||||
return defVal[0]
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Uint16 value get, or default value
|
||||
func (d Data) Uint16(key string, defVal ...uint16) uint16 {
|
||||
if val, ok := d.GetByPath(key); ok {
|
||||
return uint16(mathutil.SafeUint(val))
|
||||
}
|
||||
|
||||
if len(defVal) > 0 {
|
||||
return defVal[0]
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Uint64 value get, or default value
|
||||
func (d Data) Uint64(key string, defVal ...uint64) uint64 {
|
||||
if val, ok := d.GetByPath(key); ok {
|
||||
return mathutil.QuietUint64(val)
|
||||
}
|
||||
if len(defVal) > 0 {
|
||||
return defVal[0]
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Str value gets by key, or default value
|
||||
func (d Data) Str(key string, defVal ...string) string {
|
||||
if val, ok := d.GetByPath(key); ok {
|
||||
return strutil.SafeString(val)
|
||||
}
|
||||
if len(defVal) > 0 {
|
||||
return defVal[0]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// StrOne value gets by multi keys, will return first value
|
||||
func (d Data) StrOne(keys ...string) string {
|
||||
for _, key := range keys {
|
||||
if val, ok := d.GetByPath(key); ok {
|
||||
return strutil.SafeString(val)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Bool value get
|
||||
func (d Data) Bool(key string) bool {
|
||||
val, ok := d.GetByPath(key)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return comfunc.Bool(val)
|
||||
}
|
||||
|
||||
// BoolOne value gets from multi keys, return first value
|
||||
func (d Data) BoolOne(keys ...string) bool {
|
||||
for _, key := range keys {
|
||||
if val, ok := d.GetByPath(key); ok {
|
||||
return comfunc.Bool(val)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// StringsOne get []string value by multi keys, return first founded value
|
||||
func (d Data) StringsOne(keys ...string) []string {
|
||||
for _, key := range keys {
|
||||
if val, ok := d.GetByPath(key); ok {
|
||||
return arrutil.AnyToStrings(val)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Strings get []string value by key
|
||||
func (d Data) Strings(key string) []string {
|
||||
if val, ok := d.GetByPath(key); ok {
|
||||
return arrutil.AnyToStrings(val)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// StrSplit get strings by split string value
|
||||
func (d Data) StrSplit(key, sep string) []string {
|
||||
if val, ok := d.GetByPath(key); ok {
|
||||
return strings.Split(strutil.SafeString(val), sep)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// StringsByStr value gets by key, will split string value by ","
|
||||
func (d Data) StringsByStr(key string) []string {
|
||||
return d.StrSplit(key, ",")
|
||||
}
|
||||
|
||||
// StrMap get map[string]string value
|
||||
func (d Data) StrMap(key string) map[string]string {
|
||||
return d.StringMap(key)
|
||||
}
|
||||
|
||||
// StringMap get map[string]string value
|
||||
func (d Data) StringMap(key string) map[string]string {
|
||||
val, ok := d.GetByPath(key)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch tv := val.(type) {
|
||||
case map[string]string:
|
||||
return tv
|
||||
case map[string]any:
|
||||
return ToStringMap(tv)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Sub get sub value(map[string]any) as new Data
|
||||
func (d Data) Sub(key string) Data {
|
||||
if val, ok := d.GetByPath(key); ok {
|
||||
return d.toAnyMap(val)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AnyMap get sub value as map[string]any
|
||||
func (d Data) AnyMap(key string) map[string]any {
|
||||
if val, ok := d.GetByPath(key); ok {
|
||||
return d.toAnyMap(val)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AnyMap get sub value as map[string]any
|
||||
func (d Data) toAnyMap(val any) map[string]any {
|
||||
switch tv := val.(type) {
|
||||
case map[string]string:
|
||||
return ToAnyMap(tv)
|
||||
case map[string]any:
|
||||
return tv
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Slice get []any value from data map
|
||||
func (d Data) Slice(key string) ([]any, error) {
|
||||
val, ok := d.GetByPath(key)
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
return arrutil.AnyToSlice(val)
|
||||
}
|
||||
|
||||
// Keys of the data map
|
||||
func (d Data) Keys() []string {
|
||||
keys := make([]string, 0, len(d))
|
||||
for k := range d {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
// ToStringMap convert to map[string]string
|
||||
func (d Data) ToStringMap() map[string]string {
|
||||
return ToStringMap(d)
|
||||
}
|
||||
|
||||
// String data to string
|
||||
func (d Data) String() string {
|
||||
return ToString(d)
|
||||
}
|
||||
|
||||
// Load other data to current data map
|
||||
func (d Data) Load(sub map[string]any) {
|
||||
for name, val := range sub {
|
||||
d[name] = val
|
||||
}
|
||||
}
|
||||
|
||||
// LoadSMap to data
|
||||
func (d Data) LoadSMap(smp map[string]string) {
|
||||
for name, val := range smp {
|
||||
d[name] = val
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user