diff --git a/.gitignore b/.gitignore index 3cf11717..c3c377d2 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,7 @@ captrace/captrace captrace/log/ tools/loadmconf/loadmconf +tools/loadpconf/loadpconf vendor diff --git a/tools/loadpconf/load.go b/tools/loadpconf/load.go index 5febe82c..80d0e1f1 100644 --- a/tools/loadpconf/load.go +++ b/tools/loadpconf/load.go @@ -3,8 +3,9 @@ package main import ( "flag" "fmt" - "io/ioutil" "os" + "reflect" + "strconv" "gopkg.in/yaml.v3" ) @@ -35,7 +36,7 @@ type YamlConfig struct { var yamlConfig YamlConfig func ReadConfig(configFile string) { - yamlFile, err := ioutil.ReadFile(configFile) + yamlFile, err := os.ReadFile(configFile) if err != nil { fmt.Printf("ioutil.ReadFile %s err %v", configFile, err) } @@ -54,16 +55,27 @@ func GetYamlConfig() *YamlConfig { var mapYaml map[string]interface{} func ReadParamConfig(fileName string) *map[string]interface{} { - file, err := ioutil.ReadFile(fileName) + file, err := os.ReadFile(fileName) if err != nil { fmt.Println("yamlFile.Get err", err) } mapYaml = make(map[string]interface{}) + // var node yaml.Node + // err = yaml.Unmarshal(file, &node) + // if err != nil { + // fmt.Printf("yaml.Unmarshal: %v when to struct", err) + // } + + // err = unmarshalNode(&node, reflect.ValueOf(&mapYaml)) + // if err != nil { + // fmt.Println("Failed to unmarshalNode:", err) + // } + err = yaml.Unmarshal(file, &mapYaml) if err != nil { - fmt.Println("yaml.Unmarshal: %v when to struct", err) + fmt.Printf("yaml.Unmarshal: %v when to struct", err) } // fmt.Println("mapYaml:", mapYaml) @@ -71,7 +83,7 @@ func ReadParamConfig(fileName string) *map[string]interface{} { } func GetAllFile(dir string, s []string) ([]string, error) { - rd, err := ioutil.ReadDir(dir) + rd, err := os.ReadDir(dir) if err != nil { fmt.Println("read dir fail:", err) return s, err @@ -122,3 +134,221 @@ func init() { } fmt.Println("pfiles:", pfiles) } + +// func unmarshalNode(node *yaml.Node, out interface{}) error { +// switch node.Kind { +// case yaml.DocumentNode: +// return unmarshalNode(node.Content[0], out) +// case yaml.MappingNode: +// m := nodeToMap(node) +// return unmarshalMap(m, out) +// case yaml.SequenceNode: +// s := nodeToSlice(node) +// return unmarshalSlice(s, out) +// case yaml.ScalarNode: +// return unmarshalScalar(node, out) +// default: +// return fmt.Errorf("unknown node kind: %v", node.Kind) +// } +// } + +// func nodeToMap(node *yaml.Node) map[string]*yaml.Node { +// m := make(map[string]*yaml.Node) +// for i := 0; i < len(node.Content); i += 2 { +// key := node.Content[i].Value +// value := node.Content[i+1] +// m[key] = value +// } +// return m +// } + +// func unmarshalMap(m map[string]*yaml.Node, out interface{}) error { +// data, ok := out.(*map[string]interface{}) +// if !ok { +// return fmt.Errorf("out must be a map[string]interface{}") +// } + +// *data = make(map[string]interface{}) +// for key, value := range m { +// var v interface{} +// err := unmarshalNode(value, &v) +// if err != nil { +// return err +// } +// (*data)[key] = v +// } +// return nil +// } + +// func nodeToSlice(node *yaml.Node) []*yaml.Node { +// return node.Content +// } + +// func unmarshalSlice(s []*yaml.Node, out interface{}) error { +// data, ok := out.(*[]interface{}) +// if !ok { +// return fmt.Errorf("out must be a []interface{}") +// } + +// *data = make([]interface{}, len(s)) +// for i, value := range s { +// var v interface{} +// err := unmarshalNode(value, &v) +// if err != nil { +// return err +// } +// (*data)[i] = v +// } +// return nil +// } + +// func unmarshalScalar(node *yaml.Node, out interface{}) error { +// switch node.Tag { +// case "!!str": +// *out = node.Value +// case "!!int": +// *out = node.Value +// case "!!float": +// *out = node.Value +// case "!!bool": +// *out = node.Value == "true" +// case "!!null": +// *out = nil +// default: +// return fmt.Errorf("unknown scalar tag: %v", node.Tag) +// } +// return nil +// } + +func unmarshalNode(node *yaml.Node, out reflect.Value) error { + switch node.Kind { + case yaml.DocumentNode: + return unmarshalNode(node.Content[0], out) + case yaml.MappingNode: + m := nodeToMap(node) + return unmarshalMap(m, out) + case yaml.SequenceNode: + s := nodeToSlice(node) + return unmarshalSlice(s, out) + case yaml.ScalarNode: + return unmarshalScalar(node, out) + default: + return fmt.Errorf("unknown node kind: %v", node.Kind) + } +} + +func nodeToMap(node *yaml.Node) map[string]*yaml.Node { + m := make(map[string]*yaml.Node) + for i := 0; i < len(node.Content); i += 2 { + key := node.Content[i].Value + value := node.Content[i+1] + m[key] = value + } + return m +} + +func unmarshalMap(m map[string]*yaml.Node, out reflect.Value) error { + if out.Kind() != reflect.Ptr || out.IsNil() { + return fmt.Errorf("out must be a non-nil pointer") + } + + outType := out.Type().Elem() + if outType.Kind() != reflect.Map { + return fmt.Errorf("out must be a pointer to a map") + } + + mapType := outType.Elem() + if mapType.Kind() != reflect.Interface && mapType.Kind() != reflect.Map { + return fmt.Errorf("out must be a pointer to a map of interface{}") + } + + out.Set(reflect.MakeMap(outType)) + + for key, value := range m { + var v reflect.Value + if mapType.Kind() == reflect.Interface { + v = reflect.New(reflect.TypeOf((*interface{})(nil)).Elem()) + } else { + v = reflect.New(mapType) + } + + err := unmarshalNode(value, v.Elem()) + if err != nil { + return err + } + + out.Elem().SetMapIndex(reflect.ValueOf(key), v.Elem()) + } + + return nil +} + +func nodeToSlice(node *yaml.Node) []*yaml.Node { + return node.Content +} + +func unmarshalSlice(s []*yaml.Node, out reflect.Value) error { + if out.Kind() != reflect.Ptr || out.IsNil() { + return fmt.Errorf("out must be a non-nil pointer") + } + + outType := out.Type().Elem() + if outType.Kind() != reflect.Slice { + return fmt.Errorf("out must be a pointer to a slice") + } + + sliceType := outType.Elem() + if sliceType.Kind() != reflect.Interface && sliceType.Kind() != reflect.Slice { + return fmt.Errorf("out must be a pointer to a slice of interface{}") + } + + out.Set(reflect.MakeSlice(outType, len(s), len(s))) + + for i, value := range s { + var v reflect.Value + if sliceType.Kind() == reflect.Interface { + v = reflect.New(reflect.TypeOf((*interface{})(nil)).Elem()) + } else { + v = reflect.New(sliceType) + } + + err := unmarshalNode(value, v.Elem()) + if err != nil { + return err + } + + out.Elem().Index(i).Set(v.Elem()) + } + + return nil +} + +func unmarshalScalar(node *yaml.Node, out reflect.Value) error { + switch node.Tag { + case "!!str": + out.SetString(node.Value) + case "!!int": + i, err := strconv.ParseInt(node.Value, 10, 64) + if err != nil { + return err + } + out.SetInt(i) + case "!!float": + f, err := strconv.ParseFloat(node.Value, 64) + if err != nil { + return err + } + out.SetFloat(f) + case "!!bool": + b, err := strconv.ParseBool(node.Value) + if err != nil { + return err + } + out.SetBool(b) + case "!!null": + out.Set(reflect.Zero(out.Type())) + default: + return fmt.Errorf("unknown scalar tag: %v", node.Tag) + } + return nil +}