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.
129 lines
2.4 KiB
Go
129 lines
2.4 KiB
Go
1 year ago
|
package nmap
|
||
|
|
||
|
import (
|
||
|
"git.noahlan.cn/noahlan/ntool/narr"
|
||
|
"reflect"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
// Key, value sep char const
|
||
|
const (
|
||
|
ValSepStr = ","
|
||
|
ValSepChar = ','
|
||
|
KeySepStr = "."
|
||
|
KeySepChar = '.'
|
||
|
)
|
||
|
|
||
|
// SimpleMerge simple merge two data map by string key.
|
||
|
// will merge the src to dst map
|
||
|
func SimpleMerge(src, dst map[string]any) map[string]any {
|
||
|
if len(src) == 0 {
|
||
|
return dst
|
||
|
}
|
||
|
|
||
|
if len(dst) == 0 {
|
||
|
return src
|
||
|
}
|
||
|
|
||
|
for key, val := range src {
|
||
|
dst[key] = val
|
||
|
}
|
||
|
return dst
|
||
|
}
|
||
|
|
||
|
// func DeepMerge(src, dst map[string]any, deep int) map[string]any { TODO
|
||
|
// }
|
||
|
|
||
|
// MergeSMap simple merge two string map. merge src to dst map
|
||
|
func MergeSMap(src, dst map[string]string, ignoreCase bool) map[string]string {
|
||
|
return MergeStringMap(src, dst, ignoreCase)
|
||
|
}
|
||
|
|
||
|
// MergeStringMap simple merge two string map. merge src to dst map
|
||
|
func MergeStringMap(src, dst map[string]string, ignoreCase bool) map[string]string {
|
||
|
if len(src) == 0 {
|
||
|
return dst
|
||
|
}
|
||
|
if len(dst) == 0 {
|
||
|
return src
|
||
|
}
|
||
|
|
||
|
for k, v := range src {
|
||
|
if ignoreCase {
|
||
|
k = strings.ToLower(k)
|
||
|
}
|
||
|
|
||
|
dst[k] = v
|
||
|
}
|
||
|
return dst
|
||
|
}
|
||
|
|
||
|
// MakeByPath build new value by key names
|
||
|
//
|
||
|
// Example:
|
||
|
//
|
||
|
// "site.info"
|
||
|
// ->
|
||
|
// map[string]any {
|
||
|
// site: {info: val}
|
||
|
// }
|
||
|
//
|
||
|
// // case 2, last key is slice:
|
||
|
// "site.tags[1]"
|
||
|
// ->
|
||
|
// map[string]any {
|
||
|
// site: {tags: [val]}
|
||
|
// }
|
||
|
func MakeByPath(path string, val any) (mp map[string]any) {
|
||
|
return MakeByKeys(strings.Split(path, KeySepStr), val)
|
||
|
}
|
||
|
|
||
|
// MakeByKeys build new value by key names
|
||
|
//
|
||
|
// Example:
|
||
|
//
|
||
|
// // case 1:
|
||
|
// []string{"site", "info"}
|
||
|
// ->
|
||
|
// map[string]any {
|
||
|
// site: {info: val}
|
||
|
// }
|
||
|
//
|
||
|
// // case 2, last key is slice:
|
||
|
// []string{"site", "tags[1]"}
|
||
|
// ->
|
||
|
// map[string]any {
|
||
|
// site: {tags: [val]}
|
||
|
// }
|
||
|
func MakeByKeys(keys []string, val any) (mp map[string]any) {
|
||
|
size := len(keys)
|
||
|
|
||
|
// if last key contains slice index, make slice wrap the val
|
||
|
lastKey := keys[size-1]
|
||
|
if newK, idx, ok := parseArrKeyIndex(lastKey); ok {
|
||
|
// valTyp := reflect.TypeOf(val)
|
||
|
sliTyp := reflect.SliceOf(reflect.TypeOf(val))
|
||
|
sliVal := reflect.MakeSlice(sliTyp, idx+1, idx+1)
|
||
|
sliVal.Index(idx).Set(reflect.ValueOf(val))
|
||
|
|
||
|
// update val and last key
|
||
|
val = sliVal.Interface()
|
||
|
keys[size-1] = newK
|
||
|
}
|
||
|
|
||
|
if size == 1 {
|
||
|
return map[string]any{keys[0]: val}
|
||
|
}
|
||
|
|
||
|
// multi nodes
|
||
|
narr.Reverse(keys)
|
||
|
for _, p := range keys {
|
||
|
if mp == nil {
|
||
|
mp = map[string]any{p: val}
|
||
|
} else {
|
||
|
mp = map[string]any{p: mp}
|
||
|
}
|
||
|
}
|
||
|
return
|
||
|
}
|