tlstunnel/config.go

103 lines
1.9 KiB
Go
Raw Normal View History

2020-09-08 10:11:32 +00:00
package main
import (
"bufio"
"fmt"
2020-09-08 15:13:39 +00:00
"io"
"os"
2020-09-08 10:11:32 +00:00
"github.com/google/shlex"
)
type Directive struct {
2020-09-08 15:13:39 +00:00
Name string
Params []string
2020-09-08 10:11:32 +00:00
Children []*Directive
}
2020-09-08 15:13:39 +00:00
func (d *Directive) ParseParams(params ...*string) error {
if len(d.Params) < len(params) {
return fmt.Errorf("directive %q: want %v params, got %v", d.Name, len(params), len(d.Params))
}
for i, ptr := range params {
if ptr == nil {
continue
}
*ptr = d.Params[i]
}
return nil
}
func (d *Directive) ChildrenByName(name string) []*Directive {
l := make([]*Directive, 0, len(d.Children))
for _, child := range d.Children {
if child.Name == name {
l = append(l, child)
}
}
return l
}
func (d *Directive) ChildByName(name string) *Directive {
for _, child := range d.Children {
if child.Name == name {
return child
}
}
return nil
}
2020-09-08 10:11:32 +00:00
func Load(path string) ([]*Directive, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
return Parse(f)
}
func Parse(r io.Reader) ([]*Directive, error) {
scanner := bufio.NewScanner(r)
var directives []*Directive
var cur *Directive
for scanner.Scan() {
l := scanner.Text()
words, err := shlex.Split(l)
if err != nil {
return directives, fmt.Errorf("failed to parse config file: %v", err)
} else if len(words) == 0 {
continue
}
2020-09-08 15:13:39 +00:00
if len(words) == 1 && l[len(l)-1] == '}' {
2020-09-08 10:11:32 +00:00
if cur == nil {
return nil, fmt.Errorf("unexpected '}'")
}
cur = nil
continue
}
var d *Directive
2020-09-08 15:13:39 +00:00
if words[len(words)-1] == "{" && l[len(l)-1] == '{' {
words = words[:len(words)-1]
d = &Directive{Params: words}
2020-09-08 10:11:32 +00:00
cur = d
directives = append(directives, d)
} else {
2020-09-08 15:13:39 +00:00
d = &Directive{Name: words[0], Params: words[1:]}
2020-09-08 10:11:32 +00:00
if cur != nil {
cur.Children = append(cur.Children, d)
} else {
directives = append(directives, d)
}
}
}
if err := scanner.Err(); err != nil {
return nil, fmt.Errorf("failed to read config file: %v", err)
}
return directives, nil
}