123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- // 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)
- }
|