package cnf import ( lib "github.com/go-ini/ini" "io" "io/ioutil" "strings" ) type ini struct { sections []string data *lib.File parsed bool } // ReadFrom implements io.ReaderFrom func (d *ini) ReadFrom(_reader io.Reader) (int64, error) { // disallow "key: value" // when trying to find out the format from content // and avoids conflicts with YAML opts := lib.LoadOptions{ KeyValueDelimiters: "=", } file, err := lib.LoadSources(opts, ioutil.NopCloser(_reader)) // 1. get json decoder if err != nil { return 0, err } d.data = file d.sections = file.SectionStrings() d.parsed = true return 0, nil } // WriteTo implements io.WriterTo func (d *ini) WriteTo(_writer io.Writer) (int64, error) { return d.data.WriteTo(_writer) } // Get returns the value of a dot-separated path, and if it exists // the maximum depth is 2 : Section.Field func (d *ini) Get(_path string) (string, bool) { // 1. split path path := strings.Split(_path, ".") // 2. fail if too long if len(path) > 2 { return "", false } // 3. direct field (no section) if len(path) == 1 { // unknown field if !d.data.Section("").Haskey(path[0]) { return "", false } // found return d.data.Section("").Key(path[0]).String(), true } // 4. fail on missing section found := false for _, sec := range d.sections { if sec == path[0] { found = true break } } if !found { return "", false } // 5. Fail on unknown field if !d.data.Section(path[0]).HasKey(path[1]) { return "", false } // 6. return value return d.data.Section(path[0]).Key(path[1]).String(), true } // Set the value of a dot-separated path, and creates it if not found func (d *ini) Set(_path, _value string) bool { // 1. split path path := strings.Split(_path, ".") // 2. fail if too long if len(path) > 2 { return false } // 3. direct field (no section) section, field := "", path[0] if len(path) > 1 { section, field = path[0], path[1] } // 4. Set field value d.data.Section(section).Key(field).SetValue(_value) return true }