basic version

This commit is contained in:
dmfed
2021-03-20 21:10:53 +03:00
committed by Dmitry Fedotov
parent 6cc9cd65fb
commit a1f792f448
10 changed files with 697 additions and 69 deletions

View File

@@ -5,67 +5,62 @@ import (
"io"
"os"
"regexp"
"strconv"
"strings"
)
var (
configKeyValueRe = regexp.MustCompile(`(\w+) *= *(.+)\b[\t| |\n]*`)
configOptionRe = regexp.MustCompile(`(\w+)`)
configKeyValueRe = regexp.MustCompile(`(\w+) *= *(.+)\b[\t| |\n]*`)
configOptionRe = regexp.MustCompile(`(\w+)`)
configCommentedOut = "#"
)
type Config struct {
Values map[string]string
}
func (c *Config) Get(key string) (s string) {
if val, ok := c.Values[key]; ok {
s = val
}
return
}
func (c *Config) GetBool(key string) (b bool) {
_, b = c.Values[key]
return
}
func (c *Config) GetInt(key string) (n int) {
if val, ok := c.Values[key]; ok {
num, err := strconv.Atoi(val)
if err == nil {
n = num
}
}
return
}
func Parse(filename string) (*Config, error) {
// ParseFile reads values from file. It returns nil and error if os.Open(filename) fails.
// It would be wise to always check returned error.
// ParseFile captures two types of values: "key = value" and "option". Either key value pair or
// option must be put in its own line in the file.
// Key or option must be a single word. In example line:
// "option1 option2"
// only option1 will be captured. option2 needs to be in a separate line in the file to take effect.
// In line "key = value1,value2,value3" all of value1, value2, and value3 will be
// captured. They can be later accesed separately with Setting's Split() method.
func ParseFile(filename string) (*Config, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
c := parseReader(file)
return c, nil
return parseReader(file), nil
}
// ParseReader reads from r and returns Config. See also ParseFile.
func ParseReader(r io.Reader) *Config {
return parseReader(r)
}
// ParseReadCloser reads from r, returns Config and calls r.Close().
// See also ParseFile.
func ParseReadCloser(r io.ReadCloser) *Config {
defer r.Close()
return parseReader(r)
}
func parseReader(r io.Reader) *Config {
var c Config
c.Values = make(map[string]string)
c.Settings = make(map[string]string)
c.Options = make(map[string]struct{})
scanner := bufio.NewScanner(r)
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, "#") {
if strings.HasPrefix(line, configCommentedOut) {
continue
}
switch {
case configKeyValueRe.MatchString(line):
kvpair := configKeyValueRe.FindStringSubmatch(line)
c.Values[kvpair[1]] = kvpair[2]
c.Settings[kvpair[1]] = kvpair[2]
case configOptionRe.MatchString(line):
opt := configOptionRe.FindString(line)
c.Values[opt] = ""
c.Options[opt] = struct{}{}
}
}
return &c