71 lines
1.6 KiB
Go
71 lines
1.6 KiB
Go
// Package utils contains utility functions for the parser package.
|
|
package utils
|
|
|
|
import (
|
|
"maps"
|
|
"strings"
|
|
)
|
|
|
|
// SetPathValue sets value at a dot-separated path in obj, creating maps as needed.
|
|
// If the path is only dots (e.g., "." or ".."):
|
|
// - when obj == nil -> returns value directly (e.g., "flour")
|
|
// - when obj is a map -> if value is a map[string]any, merge into obj; otherwise obj is unchanged.
|
|
// - otherwise -> returns obj unchanged.
|
|
func SetPathValue(path string, value any, obj any) any {
|
|
// check if value is empty string and if so continue
|
|
if value == "" || value == nil {
|
|
return obj
|
|
}
|
|
|
|
// Split and drop empty segments (so ".", "..", "" become no keys)
|
|
raw := strings.Split(path, ".")
|
|
keys := raw[:0]
|
|
for _, k := range raw {
|
|
if k != "" {
|
|
keys = append(keys, k)
|
|
}
|
|
}
|
|
|
|
// Root case: no keys after trimming dots
|
|
if len(keys) == 0 {
|
|
if obj == nil {
|
|
return value
|
|
}
|
|
if m, ok := obj.(map[string]any); ok {
|
|
if mv, ok := value.(map[string]any); ok {
|
|
maps.Copy(m, mv)
|
|
}
|
|
return m
|
|
}
|
|
return obj
|
|
}
|
|
|
|
// Ensure root is a map
|
|
var root map[string]any
|
|
if obj == nil {
|
|
root = map[string]any{}
|
|
} else if m, ok := obj.(map[string]any); ok {
|
|
root = m
|
|
} else {
|
|
// if obj is not a map, just overwrite it with a new map
|
|
root = map[string]any{}
|
|
}
|
|
|
|
// Descend/construct maps
|
|
curr := root
|
|
for i, k := range keys {
|
|
if i == len(keys)-1 {
|
|
curr[k] = value
|
|
break
|
|
}
|
|
if next, ok := curr[k].(map[string]any); ok {
|
|
curr = next
|
|
continue
|
|
}
|
|
n := map[string]any{}
|
|
curr[k] = n
|
|
curr = n
|
|
}
|
|
return root
|
|
}
|