package ini import ( "github.com/spf13/cast" insensitiveopt "github.com/spf13/viper/internal/insensitiveOpt" ) // THIS CODE IS COPIED HERE: IT SHOULD NOT BE MODIFIED // AT SOME POINT IT WILL BE MOVED TO A COMMON PLACE // deepSearch scans deep maps, following the key indexes listed in the // sequence "path". // The last value is expected to be another map, and is returned. // // In case intermediate keys do not exist, or map to a non-map value, // a new map is created and inserted, and the search continues from there: // the initial map "m" may be modified! func deepSearch(m map[string]interface{}, path []string) map[string]interface{} { for _, k := range path { m2, ok := m[k] if !ok { // intermediate key does not exist // => create it and continue from there m3 := make(map[string]interface{}) m[k] = m3 m = m3 continue } m3, ok := m2.(map[string]interface{}) if !ok { // intermediate key is a value // => replace with a new map m3 = make(map[string]interface{}) m[k] = m3 } // continue search from here m = m3 } return m } // flattenAndMergeMap recursively flattens the given map into a new map // Code is based on the function with the same name in tha main package. // TODO: move it to a common place func flattenAndMergeMap(shadow map[string]interface{}, m map[string]interface{}, prefix string, delimiter string) map[string]interface{} { if shadow != nil && prefix != "" && shadow[prefix] != nil { // prefix is shadowed => nothing more to flatten return shadow } if shadow == nil { shadow = make(map[string]interface{}) } var m2 map[string]interface{} if prefix != "" { prefix += delimiter } for k, val := range m { fullKey := prefix + k switch val.(type) { case map[string]interface{}: m2 = val.(map[string]interface{}) case map[interface{}]interface{}: m2 = cast.ToStringMap(val) default: // immediate value shadow[insensitiveopt.ToLower(fullKey)] = val continue } // recursively merge to shadow map shadow = flattenAndMergeMap(shadow, m2, fullKey, delimiter) } return shadow }