123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- // 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"
- "io"
- "strings"
- "github.com/gogf/gf/v2/errors/gcode"
- "github.com/gogf/gf/v2/errors/gerror"
- "github.com/gogf/gf/v2/internal/json"
- )
- // Decode converts INI format to map.
- func Decode(data []byte) (res map[string]interface{}, err error) {
- res = make(map[string]interface{})
- var (
- fieldMap = make(map[string]interface{})
- bytesReader = bytes.NewReader(data)
- bufioReader = bufio.NewReader(bytesReader)
- section string
- lastSection string
- haveSection bool
- line string
- )
- for {
- line, err = bufioReader.ReadString('\n')
- if err != nil {
- if err == io.EOF {
- break
- }
- err = gerror.Wrapf(err, `bufioReader.ReadString failed`)
- return nil, err
- }
- if line = strings.TrimSpace(line); len(line) == 0 {
- continue
- }
- if line[0] == ';' || line[0] == '#' {
- continue
- }
- var (
- sectionBeginPos = strings.Index(line, "[")
- sectionEndPos = strings.Index(line, "]")
- )
- if sectionBeginPos >= 0 && sectionEndPos >= 2 {
- section = line[sectionBeginPos+1 : sectionEndPos]
- if lastSection == "" {
- lastSection = section
- } else if lastSection != section {
- lastSection = section
- fieldMap = make(map[string]interface{})
- }
- haveSection = true
- } else if !haveSection {
- continue
- }
- if strings.Contains(line, "=") && haveSection {
- values := strings.Split(line, "=")
- fieldMap[strings.TrimSpace(values[0])] = strings.TrimSpace(strings.Join(values[1:], "="))
- res[section] = fieldMap
- }
- }
- if !haveSection {
- 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) {
- var (
- n int
- w = new(bytes.Buffer)
- m map[string]interface{}
- ok bool
- )
- for section, item := range data {
- // Section key-value pairs.
- if m, ok = item.(map[string]interface{}); ok {
- n, err = w.WriteString(fmt.Sprintf("[%s]\n", section))
- if err != nil || n == 0 {
- return nil, gerror.Wrapf(err, "w.WriteString failed")
- }
- for k, v := range m {
- if n, err = w.WriteString(fmt.Sprintf("%s=%v\n", k, v)); err != nil || n == 0 {
- return nil, gerror.Wrapf(err, "w.WriteString failed")
- }
- }
- continue
- }
- // Simple key-value pairs.
- for k, v := range data {
- if n, err = w.WriteString(fmt.Sprintf("%s=%v\n", k, v)); err != nil || n == 0 {
- return nil, gerror.Wrapf(err, "w.WriteString failed")
- }
- }
- break
- }
- res = make([]byte, w.Len())
- if n, err = w.Read(res); err != nil || n == 0 {
- return nil, gerror.Wrapf(err, "w.Read failed")
- }
- 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)
- }
|