package config import ( "gogs.qqck.cn/s/gotools/files" "gogs.qqck.cn/s/gotools/strconv" strings2 "gogs.qqck.cn/s/gotools/strings" "strings" ) const ( type_line = iota type_notes type_section type_value ) type Config struct { list []*item } type item struct { byte // type notes string section string key string value string } func Parse(file string) (t *Config) { t = new(Config) // -----------------------------------------------------------------------Parse if file == "" { return } j_ss := strings.Split(strings2.EmptyRight(files.GetString(file)), "\n") if len(j_ss) == 0 { return } var j_section string for j_i := 0; j_i < len(j_ss); j_i++ { switch j_ss[j_i] = strings2.Empty(j_ss[j_i]); { case j_ss[j_i] == "": t.list = append(t.list, &item{byte: type_line}) case j_ss[j_i][0] == ';' || j_ss[j_i][0] == '#': t.list = append(t.list, &item{byte: type_notes, notes: j_ss[j_i]}) case j_ss[j_i][0] == '[' && j_ss[j_i][len(j_ss[j_i])-1] == ']': j_section = j_ss[j_i][1 : len(j_ss[j_i])-1] t.addSection(j_section) case j_section == "": default: j_k, j_v := strings2.Empty(strings2.Left(j_ss[j_i], "=")), strings2.Empty(strings2.Right(j_ss[j_i], "=")) if j_k == "" || j_v == "" { continue } t.SetValue(j_section, j_k, j_v) } } return } func (t *Config) GetString(section, key string) string { for j_i, j_item := range t.list { if j_item.byte == type_section && j_item.section == section { if j_i+1 == len(t.list) { break } for _, j_item := range t.list[j_i+1:] { if j_item.byte == type_section { break } if j_item.byte == type_value && j_item.key == key { return j_item.value } } break } } return "" } func (t *Config) GetBool(section, key string) bool { switch t.GetString(section, key) { case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "y", "ON", "on", "On": return true } return false } func (t *Config) GetInt32(section, key string) int32 { return strconv.ParseInt32(t.GetString(section, key)) } func (t *Config) GetUint32(section, key string) uint32 { return strconv.ParseUint32(t.GetString(section, key)) } func (t *Config) GetInt64(section, key string) int64 { return strconv.ParseInt64(t.GetString(section, key)) } func (t *Config) GetUint64(section, key string) uint64 { return strconv.ParseUint64(t.GetString(section, key)) } func (t *Config) GetInt(section, key string) int { return strconv.ParseInt(t.GetString(section, key)) } func (t *Config) GetUint(section, key string) uint { return strconv.ParseUint(t.GetString(section, key)) } func (t *Config) GetUintptr(section, key string) uintptr { return strconv.ParseUintptr(t.GetString(section, key)) } func (t *Config) addSection(section string) { if section == "" { return } for _, j_item := range t.list { if j_item.byte == type_section && j_item.section == section { return } } t.list = append(t.list, &item{ byte: type_section, section: section, }) } func (t *Config) SetValue(section, key string, value any) { if section == "" { return } var j_i, j_i2 int var j_item *item for j_i, j_item = range t.list { if j_item.byte == type_section && j_item.section == section { for j_i2, j_item = range t.list[j_i+1:] { if j_item.byte == type_section { j_i2-- break } if j_item.byte == type_value && j_item.key == key { t.setValue(j_item, value) return } } j_i += j_i2 j_i += 2 var j_list []*item j_item = &item{byte: type_value, key: key} t.setValue(j_item, value) if j_i > len(t.list) { t.list = append(t.list, j_item) return } j_list, t.list = t.list, nil t.list = append(t.list, j_list[:j_i]...) t.list = append(t.list, j_item) t.list = append(t.list, j_list[j_i:]...) return } } t.list = append(t.list, &item{byte: type_section, section: section}) j_item = &item{byte: type_value, key: key} t.setValue(j_item, value) t.list = append(t.list, j_item) } func (t *Config) setValue(item *item, value any) bool { switch value.(type) { case string: item.value = value.(string) case byte: item.value = strconv.FormatByte(value.(byte)) case bool: if value.(bool) { item.value = "1" } else { item.value = "0" } case int32: item.value = strconv.FormatInt32(value.(int32)) case uint32: item.value = strconv.FormatUint32(value.(uint32)) case int64: item.value = strconv.FormatInt64(value.(int64)) case uint64: item.value = strconv.FormatUint64(value.(uint64)) case int: item.value = strconv.FormatInt(value.(int)) case uint: item.value = strconv.FormatUint(value.(uint)) case uintptr: item.value = strconv.FormatUintptr(value.(uintptr)) default: return false } return true } func (t *Config) Save(file string) { files.Set(file, nil) for j_i, j_item := range t.list { switch j_item.byte { case type_line: files.PutString(file, "\r\n") case type_notes: files.PutString(file, j_item.notes, "\r\n") case type_section: if j_i > 0 && t.list[j_i-1].byte != type_line { files.PutString(file, "\r\n", "[", j_item.section, "]", "\r\n") } else { files.PutString(file, "[", j_item.section, "]", "\r\n") } case type_value: files.PutString(file, j_item.key, "\t", "=", "\t", j_item.value, "\r\n") } } }