You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

546 lines
11 KiB
Go

package starainrt
import (
"bufio"
"errors"
"io"
"io/ioutil"
"os"
"regexp"
"strconv"
"strings"
)
func ReWriteFileByKV(filepath, rem, conn, ret string, kv map[string]string) bool {
var outputstr string
var ataru bool = false
if (!Exists(filepath)) || (!IsFile(filepath)) {
return false
}
fso, err := os.Open(filepath)
if err != nil {
return false
}
rempar := regexp.MustCompile("^" + rem)
buf := bufio.NewReader(fso)
for {
bytxt, _, eof := buf.ReadLine()
if eof == io.EOF {
break
}
txt := strings.TrimSpace(string(bytxt))
if rempar.Match([]byte(txt)) {
outputstr += txt + ret
continue
}
for k, v := range kv {
keypar := regexp.MustCompile("^" + k)
if keypar.Match([]byte(txt)) {
ataru = true
outputstr += k + conn + v + ret
delete(kv, k)
}
}
if ataru {
ataru = false
continue
} else {
outputstr += txt + ret
}
}
fso.Close()
if len(kv) != 0 {
for k, v := range kv {
outputstr += k + conn + v + ret
delete(kv, k)
}
}
err = ioutil.WriteFile(filepath, []byte(outputstr), 0755)
if err != nil {
return false
}
return true
}
func GetINIValue(filepath, rem, conn string, kv []string) (bool, map[string]string) {
outputstr := make(map[string]string)
if (!Exists(filepath)) || (!IsFile(filepath)) {
return false, outputstr
}
fso, err := os.Open(filepath)
if err != nil {
return false, outputstr
}
rempar := regexp.MustCompile("^" + rem)
buf := bufio.NewReader(fso)
for {
bytxt, _, eof := buf.ReadLine()
if eof == io.EOF {
break
}
txt := strings.TrimSpace(string(bytxt))
if rempar.Match([]byte(txt)) {
continue
}
var i int = 0
var v2 string
for k, v := range kv {
if v == "" {
continue
}
v2 = ""
for _, b := range []byte(v) {
switch string(b) {
case ".":
v2 += "\\."
case "\\":
v2 += "\\"
case "-":
v2 += "\\-"
case "(":
v2 += "\\("
case ")":
v2 += "\\)"
case "{":
v2 += "\\{"
case "}":
v2 += "\\}"
case "[":
v2 += "\\["
case "]":
v2 += "\\]"
case "$":
v2 += "\\]$"
case "^":
v2 += "\\^"
default:
v2 += string(b)
}
}
keypar := regexp.MustCompile("^" + v2 + ".*?" + conn + "(.*?)" + "(" + rem + "|$)")
if keypar.Match([]byte(txt)) {
i++
kekka := keypar.FindSubmatch([]byte(txt))
outputstr[v] = string(kekka[1])
kv[k] = ""
}
}
if i != len(kv) {
for _, v := range kv {
if v != "" {
outputstr[v] = ""
}
}
}
}
return true, outputstr
}
func ReadINIConfig(filepath string) (map[string]map[string]string, error) {
var result map[string]map[string]string
result = make(map[string]map[string]string)
if !Exists(filepath) {
return result, errors.New("file not exists")
}
data, err := ioutil.ReadFile(filepath)
if err != nil {
return result, nil
}
strdata := string(data)
datas := strings.Split(strdata, "\n")
var inseg, nolabel bool = false, false
var segname string
jump:
if nolabel {
segname = "unnamed"
inseg = true
}
for _, v := range datas {
v = strings.TrimSpace(v)
if ok, _ := regexp.MatchString("^#", v); ok {
continue
}
segfind := regexp.MustCompile(`^\[(.*)\]`)
if !inseg {
if ok, _ := regexp.MatchString(`(.*?)=(.*)`, v); ok {
nolabel = true
goto jump
}
if !segfind.MatchString(v) {
continue
} else {
tmp := segfind.FindStringSubmatch(v)
segname = tmp[1]
inseg = true
}
} else {
if segfind.MatchString(v) {
tmp := segfind.FindStringSubmatch(v)
segname = tmp[1]
inseg = true
}
}
if fn := strings.Index(v, "#"); fn >= 0 {
v = v[0:fn]
}
if ok, _ := regexp.MatchString(`(.*?)=(.*)`, v); ok {
regtmp := regexp.MustCompile(`(.*?)=(.*)`)
tmp := regtmp.FindStringSubmatch(v)
if result[segname] == nil {
result[segname] = make(map[string]string)
}
result[segname][strings.TrimSpace(tmp[1])] = strings.TrimSpace(tmp[2])
} else {
continue
}
}
return result, nil
}
type StarCfg struct {
Data []*CfgSegment
segmap map[string]int
nodemap map[int]map[string]int
}
type CfgNode struct {
Key string
Value string
Comment string
}
type CfgSegment struct {
Name string
cmap map[string]int
Comment string
Node []*CfgNode
InsertNode []*CfgNode
}
func (this *StarCfg) ParseFromFile(filepath string) error {
if !Exists(filepath) {
return errors.New(filepath + " 不存在")
}
data, err := ioutil.ReadFile(filepath)
if err != nil {
return err
}
this.Parse(data)
return nil
}
func (this *StarCfg) WriteToFile(filepath string) error {
data := this.Build()
return ioutil.WriteFile(filepath, data, 0644)
}
func (this *StarCfg) Parse(data []byte) {
var newnode *CfgNode
segint := 0
nodeint := 0
this.segmap = make(map[string]int)
this.nodemap = make(map[int]map[string]int)
strdata := string(data)
list := strings.Split(strdata, "\n")
newseg := new(CfgSegment)
newseg.Name = "unnamed"
newseg.InsertNode = []*CfgNode{}
this.segmap["unnamed"] = 0
lastiseg := true
for _, v := range list {
istrans := false
isseg := false
isnote := false
isequal := false
tmp1 := []rune{}
tmp2 := []rune{}
note := []rune{}
v = strings.TrimSpace(v)
for k, v2 := range v {
if k == 0 {
if v2 == '[' {
isseg = true
continue
}
}
if v2 == '=' && (!istrans && !isnote) {
isequal = true
continue
}
if v2 == ']' && (!istrans && !isnote) {
continue
}
if v2 == '#' && (!istrans && !isnote) {
isnote = true
continue
}
if v2 == '\\' && (!istrans && !isnote) {
istrans = true
continue
}
if istrans {
istrans = false
}
if !isnote && (!isequal) {
tmp1 = append(tmp1, v2)
} else if !isnote && isequal {
tmp2 = append(tmp2, v2)
} else if isnote {
note = append(note, v2)
}
}
if isseg {
this.Data = append(this.Data, newseg)
newseg = new(CfgSegment)
newseg.InsertNode = []*CfgNode{}
newseg.Name = strings.TrimSpace(string(tmp1))
if isnote {
newseg.Comment = strings.TrimSpace(string(note))
}
segint++
this.segmap[newseg.Name] = segint
nodeint = 0
lastiseg = true
continue
}
if isequal {
newnode = new(CfgNode)
newnode.Key = strings.TrimSpace(string(tmp1))
newnode.Value = strings.TrimSpace(string(tmp2))
if isnote {
newnode.Comment = strings.TrimSpace(string(note))
}
newseg.Node = append(newseg.Node, newnode)
if this.nodemap[segint] == nil {
this.nodemap[segint] = make(map[string]int)
}
this.nodemap[segint][newnode.Key] = nodeint
nodeint++
lastiseg = false
continue
}
if isnote {
comment := strings.TrimSpace(string(note))
if lastiseg {
newseg.Comment += "\n" + comment
} else {
newnode.Comment += "\n" + comment
}
continue
}
}
this.Data = append(this.Data, newseg)
}
func (this *StarCfg) Seg(name string) *CfgSegment {
if _, ok := this.segmap[name]; !ok {
return nil
}
seg := this.Data[this.segmap[name]]
if seg.Name == name {
seg.cmap = this.nodemap[this.segmap[name]]
return seg
}
return nil
}
func (this *StarCfg) Build() []byte {
var res, comm string
for _, v := range this.Data {
comm = ""
if v.Name != "unnamed" {
res += `[ ` + this.repkv(v.Name) + ` ]`
}
if v.Comment != "" {
comm = strings.Replace(v.Comment, "\n", "\n#", -1)
if comm[0:1] != "\n" {
comm = " #" + comm
}
}
res += comm + "\n"
comm = ""
for _, v2 := range v.Node {
res += this.repkv(v2.Key) + " = " + this.repkv(v2.Value)
if v2.Comment != "" {
comm = strings.Replace(v2.Comment, "\n", "\n#", -1)
if comm[0:1] != "\n" {
comm = " #" + comm
}
}
res += comm + "\n"
}
comm = ""
for _, v2 := range v.InsertNode {
res += this.repkv(v2.Key) + " = " + this.repkv(v2.Value)
if v2.Comment != "" {
comm = strings.Replace(v2.Comment, "\n", "\n#", -1)
if comm[0:1] != "\n" {
comm = " #" + comm
}
}
res += comm + "\n"
}
}
return []byte(strings.TrimSpace(res))
}
func (this *StarCfg) repkv(value string) string {
value = strings.Replace(value, `\`, `\\`, -1)
value = strings.Replace(value, `#`, `\#`, -1)
value = strings.Replace(value, `=`, `\=`, -1)
value = strings.Replace(value, `[`, `\[`, -1)
value = strings.Replace(value, `]`, `\]`, -1)
return value
}
func (this *CfgSegment) GetComment(key string) string {
if v, ok := this.cmap[key]; !ok {
for _, v2 := range this.InsertNode {
if v2.Key == key {
return this.Node[v].Comment
}
}
return ""
} else {
return this.Node[v].Comment
}
}
func (this *CfgSegment) Exist(key string) bool {
if _, ok := this.cmap[key]; !ok {
for _, v2 := range this.InsertNode {
if v2.Key == key {
return true
}
}
return false
} else {
return true
}
}
func (this *CfgSegment) Get(key string) string {
if v, ok := this.cmap[key]; !ok {
for _, v2 := range this.InsertNode {
if v2.Key == key {
return this.Node[v].Value
}
}
return ""
} else {
return this.Node[v].Value
}
}
func (this *CfgSegment) Int(key string) int {
val := this.Get(key)
if val == "" {
return 0
}
res, _ := strconv.Atoi(val)
return res
}
func (this *CfgSegment) Int64(key string) int64 {
val := this.Get(key)
if val == "" {
return 0
}
res, _ := strconv.ParseInt(val, 10, 64)
return res
}
func (this *CfgSegment) Int32(key string) int32 {
val := this.Get(key)
if val == "" {
return 0
}
res, _ := strconv.ParseInt(val, 10, 32)
return int32(res)
}
func (this *CfgSegment) Float64(key string) float64 {
val := this.Get(key)
if val == "" {
return 0
}
res, _ := strconv.ParseFloat(val, 64)
return res
}
func (this *CfgSegment) Float32(key string) float32 {
val := this.Get(key)
if val == "" {
return 0
}
res, _ := strconv.ParseFloat(val, 32)
return float32(res)
}
func (this *CfgSegment) Bool(key string) bool {
val := this.Get(key)
if val == "" {
return false
}
res, _ := strconv.ParseBool(val)
return res
}
func (this *CfgSegment) SetBool(key string, value bool, comment string) error {
res := strconv.FormatBool(value)
return this.Set(key, res, comment)
}
func (this *CfgSegment) SetFloat64(key string, prec int, value float64, comment string) error {
res := strconv.FormatFloat(value, 'f', prec, 64)
return this.Set(key, res, comment)
}
func (this *CfgSegment) SetFloat32(key string, prec int, value float32, comment string) error {
res := strconv.FormatFloat(float64(value), 'f', prec, 32)
return this.Set(key, res, comment)
}
func (this *CfgSegment) SetInt64(key string, value int64, comment string) error {
res := strconv.FormatInt(value, 10)
return this.Set(key, res, comment)
}
func (this *CfgSegment) SetInt32(key string, value int32, comment string) error {
res := strconv.FormatInt(int64(value), 10)
return this.Set(key, res, comment)
}
func (this *CfgSegment) SetInt(key string, value int, comment string) error {
res := strconv.Itoa(value)
return this.Set(key, res, comment)
}
func (this *CfgSegment) Set(key, value, comment string) error {
if v, ok := this.cmap[key]; !ok {
for _, v2 := range this.InsertNode {
if v2.Key == key {
this.Node[v].Value = value
if comment != "" {
this.Node[v].Comment = comment
}
return nil
}
}
node := new(CfgNode)
node.Key = key
node.Value = value
node.Comment = comment
this.InsertNode = append(this.InsertNode, node)
return nil
} else {
this.Node[v].Value = value
if comment != "" {
this.Node[v].Comment = comment
}
}
return nil
}