mirror of
https://github.com/cwinfo/matterbridge.git
synced 2025-07-16 23:08:55 +00:00
Update vendor (#1265)
This commit is contained in:
167
vendor/github.com/wiggin77/cfg/ini/ini.go
generated
vendored
Normal file
167
vendor/github.com/wiggin77/cfg/ini/ini.go
generated
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
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
|
||||
}
|
142
vendor/github.com/wiggin77/cfg/ini/parser.go
generated
vendored
Normal file
142
vendor/github.com/wiggin77/cfg/ini/parser.go
generated
vendored
Normal file
@ -0,0 +1,142 @@
|
||||
package ini
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/wiggin77/merror"
|
||||
)
|
||||
|
||||
// LF is linefeed
|
||||
const LF byte = 0x0A
|
||||
|
||||
// CR is carriage return
|
||||
const CR byte = 0x0D
|
||||
|
||||
// getSections parses an INI formatted string, or string containing just name/value pairs,
|
||||
// returns map of `Section`'s.
|
||||
//
|
||||
// Any name/value pairs appearing before a section name are added to the section named
|
||||
// with an empty string (""). Also true for Linux-style config files where all props
|
||||
// are outside a named section.
|
||||
//
|
||||
// Any errors encountered are aggregated and returned, along with the partially parsed
|
||||
// sections.
|
||||
func getSections(str string) (map[string]*Section, error) {
|
||||
merr := merror.New()
|
||||
mapSections := make(map[string]*Section)
|
||||
lines := buildLineArray(str)
|
||||
section := newSection("")
|
||||
|
||||
for _, line := range lines {
|
||||
name, ok := parseSection(line)
|
||||
if ok {
|
||||
// A section name encountered. Stop processing the current one.
|
||||
// Don't add the current section to the map if the section name is blank
|
||||
// and the prop map is empty.
|
||||
nameCurr := section.GetName()
|
||||
if nameCurr != "" || section.hasKeys() {
|
||||
mapSections[nameCurr] = section
|
||||
}
|
||||
// Start processing a new section.
|
||||
section = newSection(name)
|
||||
} else {
|
||||
// Parse the property and add to the current section, or ignore if comment.
|
||||
if k, v, comment, err := parseProp(line); !comment && err == nil {
|
||||
section.setProp(k, v)
|
||||
} else if err != nil {
|
||||
merr.Append(err) // aggregate errors
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// If the current section is not empty, add it.
|
||||
if section.hasKeys() {
|
||||
mapSections[section.GetName()] = section
|
||||
}
|
||||
return mapSections, merr.ErrorOrNil()
|
||||
}
|
||||
|
||||
// buildLineArray parses the given string buffer and creates a list of strings,
|
||||
// one for each line in the string buffer.
|
||||
//
|
||||
// A line is considered to be terminated by any one of a line feed ('\n'),
|
||||
// a carriage return ('\r'), or a carriage return followed immediately by a
|
||||
// linefeed.
|
||||
//
|
||||
// Lines prefixed with ';' or '#' are considered comments and skipped.
|
||||
func buildLineArray(str string) []string {
|
||||
arr := make([]string, 0, 10)
|
||||
str = str + "\n"
|
||||
|
||||
iLen := len(str)
|
||||
iPos, iBegin := 0, 0
|
||||
var ch byte
|
||||
|
||||
for iPos < iLen {
|
||||
ch = str[iPos]
|
||||
if ch == LF || ch == CR {
|
||||
sub := str[iBegin:iPos]
|
||||
sub = strings.TrimSpace(sub)
|
||||
if sub != "" && !strings.HasPrefix(sub, ";") && !strings.HasPrefix(sub, "#") {
|
||||
arr = append(arr, sub)
|
||||
}
|
||||
iPos++
|
||||
if ch == CR && iPos < iLen && str[iPos] == LF {
|
||||
iPos++
|
||||
}
|
||||
iBegin = iPos
|
||||
} else {
|
||||
iPos++
|
||||
}
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// parseSection parses the specified string for a section name enclosed in square brackets.
|
||||
// Returns the section name found, or `ok=false` if `str` is not a section header.
|
||||
func parseSection(str string) (name string, ok bool) {
|
||||
str = strings.TrimSpace(str)
|
||||
if !strings.HasPrefix(str, "[") {
|
||||
return "", false
|
||||
}
|
||||
iCloser := strings.Index(str, "]")
|
||||
if iCloser == -1 {
|
||||
return "", false
|
||||
}
|
||||
return strings.TrimSpace(str[1:iCloser]), true
|
||||
}
|
||||
|
||||
// parseProp parses the specified string and extracts a key/value pair.
|
||||
//
|
||||
// If the string is a comment (prefixed with ';' or '#') then `comment=true`
|
||||
// and key will be empty.
|
||||
func parseProp(str string) (key string, val string, comment bool, err error) {
|
||||
iLen := len(str)
|
||||
iEqPos := strings.Index(str, "=")
|
||||
if iEqPos == -1 {
|
||||
return "", "", false, fmt.Errorf("not a key/value pair:'%s'", str)
|
||||
}
|
||||
|
||||
key = str[0:iEqPos]
|
||||
key = strings.TrimSpace(key)
|
||||
if iEqPos+1 < iLen {
|
||||
val = str[iEqPos+1:]
|
||||
val = strings.TrimSpace(val)
|
||||
}
|
||||
|
||||
// Check that the key has at least 1 char.
|
||||
if key == "" {
|
||||
return "", "", false, fmt.Errorf("key is empty for '%s'", str)
|
||||
}
|
||||
|
||||
// Check if this line is a comment that just happens
|
||||
// to have an equals sign in it. Not an error, but not a
|
||||
// useable line either.
|
||||
if strings.HasPrefix(key, ";") || strings.HasPrefix(key, "#") {
|
||||
key = ""
|
||||
val = ""
|
||||
comment = true
|
||||
}
|
||||
return key, val, comment, err
|
||||
}
|
109
vendor/github.com/wiggin77/cfg/ini/section.go
generated
vendored
Normal file
109
vendor/github.com/wiggin77/cfg/ini/section.go
generated
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
package ini
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Section represents a section in an INI file. The section has a name, which is
|
||||
// enclosed in square brackets in the file. The section also has an array of
|
||||
// key/value pairs.
|
||||
type Section struct {
|
||||
name string
|
||||
props map[string]string
|
||||
mtx sync.RWMutex
|
||||
}
|
||||
|
||||
func newSection(name string) *Section {
|
||||
sec := &Section{}
|
||||
sec.name = name
|
||||
sec.props = make(map[string]string)
|
||||
return sec
|
||||
}
|
||||
|
||||
// addLines addes an array of strings containing name/value pairs
|
||||
// of the format `key=value`.
|
||||
//func addLines(lines []string) {
|
||||
// TODO
|
||||
//}
|
||||
|
||||
// GetName returns the name of the section.
|
||||
func (sec *Section) GetName() (name string) {
|
||||
sec.mtx.RLock()
|
||||
name = sec.name
|
||||
sec.mtx.RUnlock()
|
||||
return
|
||||
}
|
||||
|
||||
// GetProp returns the value associated with the given key, or
|
||||
// `ok=false` if key does not exist.
|
||||
func (sec *Section) GetProp(key string) (val string, ok bool) {
|
||||
sec.mtx.RLock()
|
||||
val, ok = sec.props[key]
|
||||
sec.mtx.RUnlock()
|
||||
return
|
||||
}
|
||||
|
||||
// SetProp sets the value associated with the given key.
|
||||
func (sec *Section) setProp(key string, val string) {
|
||||
sec.mtx.Lock()
|
||||
sec.props[key] = val
|
||||
sec.mtx.Unlock()
|
||||
}
|
||||
|
||||
// hasKeys returns true if there are one or more properties in
|
||||
// this section.
|
||||
func (sec *Section) hasKeys() (b bool) {
|
||||
sec.mtx.RLock()
|
||||
b = len(sec.props) > 0
|
||||
sec.mtx.RUnlock()
|
||||
return
|
||||
}
|
||||
|
||||
// getKeys returns an array containing all keys in this section.
|
||||
func (sec *Section) getKeys() []string {
|
||||
sec.mtx.RLock()
|
||||
defer sec.mtx.RUnlock()
|
||||
|
||||
arr := make([]string, len(sec.props))
|
||||
idx := 0
|
||||
for k := range sec.props {
|
||||
arr[idx] = k
|
||||
idx++
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
// combine the given section with this one.
|
||||
func (sec *Section) combine(sec2 *Section) {
|
||||
sec.mtx.Lock()
|
||||
sec2.mtx.RLock()
|
||||
defer sec.mtx.Unlock()
|
||||
defer sec2.mtx.RUnlock()
|
||||
|
||||
for k, v := range sec2.props {
|
||||
sec.props[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
// String returns a string representation of this section.
|
||||
func (sec *Section) String() string {
|
||||
return fmt.Sprintf("[%s]\n%s", sec.GetName(), sec.StringPropsOnly())
|
||||
}
|
||||
|
||||
// StringPropsOnly returns a string representation of this section
|
||||
// without the section header.
|
||||
func (sec *Section) StringPropsOnly() string {
|
||||
sec.mtx.RLock()
|
||||
defer sec.mtx.RUnlock()
|
||||
sb := &strings.Builder{}
|
||||
|
||||
for k, v := range sec.props {
|
||||
sb.WriteString(k)
|
||||
sb.WriteString("=")
|
||||
sb.WriteString(v)
|
||||
sb.WriteString("\n")
|
||||
}
|
||||
return sb.String()
|
||||
}
|
Reference in New Issue
Block a user