matterbridge/vendor/github.com/wiggin77/cfg/ini/ini.go

168 lines
3.7 KiB
Go

package ini
import (
"fmt"
"io"
"io/ioutil"
"os"
"sync"
"time"
)
// Ini provides parsing and querying of INI format or simple name/value pairs
// such as a simple config file.
// A name/value pair format is just an INI with no sections, and properties can
// be queried using an empty section name.
type Ini struct {
mutex sync.RWMutex
m map[string]*Section
lm time.Time
}
// LoadFromFilespec loads an INI file from string containing path and filename.
func (ini *Ini) LoadFromFilespec(filespec string) error {
f, err := os.Open(filespec)
if err != nil {
return err
}
return ini.LoadFromFile(f)
}
// LoadFromFile loads an INI file from `os.File`.
func (ini *Ini) LoadFromFile(file *os.File) error {
fi, err := file.Stat()
if err != nil {
return err
}
lm := fi.ModTime()
if err := ini.LoadFromReader(file); err != nil {
return err
}
ini.lm = lm
return nil
}
// LoadFromReader loads an INI file from an `io.Reader`.
func (ini *Ini) LoadFromReader(reader io.Reader) error {
data, err := ioutil.ReadAll(reader)
if err != nil {
return err
}
return ini.LoadFromString(string(data))
}
// LoadFromString parses an INI from a string .
func (ini *Ini) LoadFromString(s string) error {
m, err := getSections(s)
if err != nil {
return err
}
ini.mutex.Lock()
ini.m = m
ini.lm = time.Now()
ini.mutex.Unlock()
return nil
}
// GetLastModified returns the last modified timestamp of the
// INI contents.
func (ini *Ini) GetLastModified() time.Time {
return ini.lm
}
// GetSectionNames returns the names of all sections in this INI.
// Note, the returned section names are a snapshot in time, meaning
// other goroutines may change the contents of this INI as soon as
// the method returns.
func (ini *Ini) GetSectionNames() []string {
ini.mutex.RLock()
defer ini.mutex.RUnlock()
arr := make([]string, 0, len(ini.m))
for key := range ini.m {
arr = append(arr, key)
}
return arr
}
// GetKeys returns the names of all keys in the specified section.
// Note, the returned key names are a snapshot in time, meaning other
// goroutines may change the contents of this INI as soon as the
// method returns.
func (ini *Ini) GetKeys(sectionName string) ([]string, error) {
sec, err := ini.getSection(sectionName)
if err != nil {
return nil, err
}
return sec.getKeys(), nil
}
// getSection returns the named section.
func (ini *Ini) getSection(sectionName string) (*Section, error) {
ini.mutex.RLock()
defer ini.mutex.RUnlock()
sec, ok := ini.m[sectionName]
if !ok {
return nil, fmt.Errorf("section '%s' not found", sectionName)
}
return sec, nil
}
// GetFlattenedKeys returns all section names plus keys as one
// flattened array.
func (ini *Ini) GetFlattenedKeys() []string {
ini.mutex.RLock()
defer ini.mutex.RUnlock()
arr := make([]string, 0, len(ini.m)*2)
for _, section := range ini.m {
keys := section.getKeys()
for _, key := range keys {
name := section.GetName()
if name != "" {
key = name + "." + key
}
arr = append(arr, key)
}
}
return arr
}
// GetProp returns the value of the specified key in the named section.
func (ini *Ini) GetProp(section string, key string) (val string, ok bool) {
sec, err := ini.getSection(section)
if err != nil {
return val, false
}
return sec.GetProp(key)
}
// ToMap returns a flattened map of the section name plus keys mapped
// to values.
func (ini *Ini) ToMap() map[string]string {
m := make(map[string]string)
ini.mutex.RLock()
defer ini.mutex.RUnlock()
for _, section := range ini.m {
for _, key := range section.getKeys() {
val, ok := section.GetProp(key)
if ok {
name := section.GetName()
var mapkey string
if name != "" {
mapkey = name + "." + key
} else {
mapkey = key
}
m[mapkey] = val
}
}
}
return m
}