goini/goini.go
2019-10-25 10:32:13 +08:00

196 lines
4.8 KiB
Go

package goini
import (
"bytes"
"io/ioutil"
"regexp"
"strconv"
"strings"
)
type GoINI struct {
data []byte
dataMap map[string]map[string]string
nameList []string
dataKeyList map[string][]string
commonField string
}
func NewGoINI() *GoINI {
return &GoINI{
commonField: "BuiltCommon",
}
}
func (ini *GoINI) parse() {
currentName := ini.commonField
iniData := make(map[string]map[string]string)
iniData[currentName] = make(map[string]string)
ini.nameList = append(ini.nameList, currentName)
ini.dataKeyList = make(map[string][]string)
for _, v := range bytes.Split(ini.data, []byte("\n")) {
line := bytes.TrimSpace(v)
lineLen := len(line)
if line == nil || lineLen < 3 ||
line[0] == 35 || line[0] == 59 {
continue
}
if line[0] == 91 && line[lineLen-1] == 93 {
name := bytes.TrimSpace(line[1 : lineLen-1])
if name != nil {
currentName = string(name)
if _, ok := iniData[currentName]; !ok {
iniData[currentName] = make(map[string]string)
ini.nameList = append(ini.nameList, currentName)
}
}
continue
}
split := bytes.IndexByte(line, 61)
if split == -1 {
split = bytes.IndexByte(line, 32)
if split == -1 {
continue
}
}
key := bytes.TrimSpace(line[0:split])
value := bytes.TrimSpace(line[split+1:])
valueLen := len(value)
keyStr, valueStr := string(key), string(value)
if keyStr == "" {
continue
}
if _, ok := iniData[currentName][keyStr]; ok {
continue
}
ini.dataKeyList[currentName] = append(ini.dataKeyList[currentName], keyStr)
if value == nil {
iniData[currentName][keyStr] = ""
continue
}
if valueLen >= 2 &&
((value[0] == 34 && value[valueLen-1] == 34) ||
(value[0] == 39 && value[valueLen-1] == 39) ||
(value[0] == 96 && value[valueLen-1] == 96)) {
iniData[currentName][keyStr] = string(value[1 : valueLen-1])
continue
}
iniData[currentName][keyStr] = valueStr
}
ini.dataMap = iniData
}
func (ini *GoINI) String() string {
var iniLines []string
for _, name := range ini.GetNames("") {
if name != ini.commonField {
if len(iniLines) < 1 {
iniLines = append(iniLines, "["+name+"]")
} else {
iniLines = append(iniLines, "\n["+name+"]")
}
}
for _, key := range ini.GetNameKeys(name, "") {
nameValue := ini.GetString(name, key, "")
if ok, _ := regexp.MatchString("^\\s|\\s$", nameValue); ok {
iniLines = append(iniLines, key+" = \""+nameValue+"\"")
continue
}
nameValueLen := len(nameValue)
if nameValueLen >= 2 &&
((nameValue[0] == 34 && nameValue[nameValueLen-1] == 34) ||
(nameValue[0] == 39 && nameValue[nameValueLen-1] == 39) ||
(nameValue[0] == 96 && nameValue[nameValueLen-1] == 96)) {
tag := `"`
if nameValue[0] == 34 {
tag = "`"
}
iniLines = append(iniLines, key+" = "+tag+nameValue+tag)
} else {
iniLines = append(iniLines, key+" = "+nameValue)
}
}
}
return strings.Join(iniLines, "\n")
}
func (ini *GoINI) SetData(fileData []byte) {
ini.data = bytes.TrimSpace(fileData)
ini.parse()
}
func (ini *GoINI) LoadFile(fileName string) error {
b, err := ioutil.ReadFile(fileName)
if err != nil {
return err
}
ini.data = bytes.TrimSpace(b)
ini.parse()
return nil
}
func (ini *GoINI) GetNames(match string) []string {
if match == "" {
return ini.nameList
}
var matchNameList []string
for _, name := range ini.nameList {
if b, e := regexp.MatchString(match, name); e == nil && b {
matchNameList = append(matchNameList, name)
}
}
return matchNameList
}
func (ini *GoINI) GetNameKeys(name string, match string) []string {
var keyList []string
if name == "" {
name = ini.commonField
}
if keyList, ok := ini.dataKeyList[name]; ok {
if match == "" {
return keyList
}
var matchKeyList []string
for _, key := range keyList {
if b, e := regexp.MatchString(match, key); e == nil && b {
matchKeyList = append(matchKeyList, key)
}
}
return matchKeyList
}
return keyList
}
func (ini *GoINI) GetBool(name string, key string, value bool) bool {
boolStr := ini.GetString(name, key, "")
switch strings.ToLower(boolStr) {
case "y", "yes", "on":
return true
case "n", "no", "off":
return false
}
if b, e := strconv.ParseBool(boolStr); e == nil {
return b
}
return value
}
func (ini *GoINI) GetInt64(name string, key string, value int64) int64 {
int64Str := ini.GetString(name, key, "")
if i, e := strconv.ParseInt(int64Str, 10, 64); e == nil {
return i
}
return value
}
func (ini *GoINI) GetString(name string, key string, value string) string {
if 0 == len(name) {
name = ini.commonField
}
if v, ok := ini.dataMap[name]; ok {
if vv, ok := v[key]; ok {
return vv
}
}
return value
}
func (ini *GoINI) GetFloat64(name string, key string, value float64) float64 {
float64Str := ini.GetString(name, key, "")
if f, e := strconv.ParseFloat(float64Str, 64); e == nil {
return f
}
return value
}