You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
260 lines
4.8 KiB
Go
260 lines
4.8 KiB
Go
1 year ago
|
package nmap
|
||
|
|
||
|
import (
|
||
|
"git.noahlan.cn/noahlan/ntool/narr"
|
||
|
"git.noahlan.cn/noahlan/ntool/nmath"
|
||
|
"git.noahlan.cn/noahlan/ntool/nstr"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
// Data an map data type
|
||
|
type Data map[string]any
|
||
|
|
||
|
// Map alias of Data
|
||
|
type Map = Data
|
||
|
|
||
|
// Has value on the data map
|
||
|
func (d Data) Has(key string) bool {
|
||
|
_, ok := d.GetByPath(key)
|
||
|
return ok
|
||
|
}
|
||
|
|
||
|
// IsEmtpy if the data map
|
||
|
func (d Data) IsEmtpy() bool {
|
||
|
return len(d) == 0
|
||
|
}
|
||
|
|
||
|
// 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
|
||
|
}
|
||
|
|
||
|
// 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 key path.
|
||
|
if strings.ContainsRune(path, '.') {
|
||
|
val, ok := GetByPath(path, d)
|
||
|
if ok {
|
||
|
return val, true
|
||
|
}
|
||
|
}
|
||
|
return nil, false
|
||
|
}
|
||
|
|
||
|
// 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.
|
||
|
//
|
||
|
// For 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.
|
||
|
//
|
||
|
// For 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)
|
||
|
}
|
||
|
|
||
|
// 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
|
||
|
func (d Data) Int(key string) int {
|
||
|
if val, ok := d.GetByPath(key); ok {
|
||
|
return nmath.QuietInt(val)
|
||
|
}
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
// Int64 value get
|
||
|
func (d Data) Int64(key string) int64 {
|
||
|
if val, ok := d.GetByPath(key); ok {
|
||
|
return nmath.QuietInt64(val)
|
||
|
}
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
// Uint value get
|
||
|
func (d Data) Uint(key string) uint64 {
|
||
|
if val, ok := d.GetByPath(key); ok {
|
||
|
return nmath.QuietUint(val)
|
||
|
}
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
// Str value get by key
|
||
|
func (d Data) Str(key string) string {
|
||
|
if val, ok := d.GetByPath(key); ok {
|
||
|
return nstr.SafeString(val)
|
||
|
}
|
||
|
return ""
|
||
|
}
|
||
|
|
||
|
// Bool value get
|
||
|
func (d Data) Bool(key string) bool {
|
||
|
val, ok := d.GetByPath(key)
|
||
|
if !ok {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
switch tv := val.(type) {
|
||
|
case string:
|
||
|
return nstr.QuietBool(tv)
|
||
|
case bool:
|
||
|
return tv
|
||
|
default:
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Strings get []string value
|
||
|
func (d Data) Strings(key string) []string {
|
||
|
val, ok := d.GetByPath(key)
|
||
|
if !ok {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
switch typVal := val.(type) {
|
||
|
case string:
|
||
|
return []string{typVal}
|
||
|
case []string:
|
||
|
return typVal
|
||
|
case []any:
|
||
|
return narr.SliceToStrings(typVal)
|
||
|
default:
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// StrSplit get strings by split key value
|
||
|
func (d Data) StrSplit(key, sep string) []string {
|
||
|
if val, ok := d.GetByPath(key); ok {
|
||
|
return strings.Split(nstr.SafeString(val), sep)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// StringsByStr value get by key
|
||
|
func (d Data) StringsByStr(key string) []string {
|
||
|
if val, ok := d.GetByPath(key); ok {
|
||
|
return strings.Split(nstr.SafeString(val), ",")
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// 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 as new Data
|
||
|
func (d Data) Sub(key string) Data {
|
||
|
if val, ok := d.GetByPath(key); ok {
|
||
|
if sub, ok := val.(map[string]any); ok {
|
||
|
return sub
|
||
|
}
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// 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
|
||
|
}
|
||
|
}
|