// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. // // This Source Code Form is subject to the terms of the MIT License. // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. // Package gini provides accessing and converting for INI content. package gini import ( "bufio" "bytes" "fmt" "github.com/gogf/gf/errors/gcode" "github.com/gogf/gf/errors/gerror" "github.com/gogf/gf/internal/json" "io" "strings" ) // Decode converts INI format to map. func Decode(data []byte) (res map[string]interface{}, err error) { res = make(map[string]interface{}) fieldMap := make(map[string]interface{}) a := bytes.NewReader(data) r := bufio.NewReader(a) var section string var lastSection string var haveSection bool for { line, err := r.ReadString('\n') if err != nil { if err == io.EOF { break } return nil, err } lineStr := strings.TrimSpace(string(line)) if len(lineStr) == 0 { continue } if lineStr[0] == ';' || lineStr[0] == '#' { continue } sectionBeginPos := strings.Index(lineStr, "[") sectionEndPos := strings.Index(lineStr, "]") if sectionBeginPos >= 0 && sectionEndPos >= 2 { section = lineStr[sectionBeginPos+1 : sectionEndPos] if lastSection == "" { lastSection = section } else if lastSection != section { lastSection = section fieldMap = make(map[string]interface{}) } haveSection = true } else if haveSection == false { continue } if strings.Contains(lineStr, "=") && haveSection { values := strings.Split(lineStr, "=") fieldMap[strings.TrimSpace(values[0])] = strings.TrimSpace(strings.Join(values[1:], "")) res[section] = fieldMap } } if haveSection == false { return nil, gerror.NewCode(gcode.CodeInvalidParameter, "failed to parse INI file, section not found") } return res, nil } // Encode converts map to INI format. func Encode(data map[string]interface{}) (res []byte, err error) { w := new(bytes.Buffer) w.WriteString("; this ini file is produced by package gini\n") for k, v := range data { n, err := w.WriteString(fmt.Sprintf("[%s]\n", k)) if err != nil || n == 0 { return nil, fmt.Errorf("write data failed. %v", err) } for kk, vv := range v.(map[string]interface{}) { n, err := w.WriteString(fmt.Sprintf("%s=%s\n", kk, vv.(string))) if err != nil || n == 0 { return nil, fmt.Errorf("write data failed. %v", err) } } } res = make([]byte, w.Len()) n, err := w.Read(res) if err != nil || n == 0 { return nil, fmt.Errorf("write data failed. %v", err) } return res, nil } // ToJson convert INI format to JSON. func ToJson(data []byte) (res []byte, err error) { iniMap, err := Decode(data) if err != nil { return nil, err } return json.Marshal(iniMap) }