tasks a-s
This commit is contained in:
parent
47bf37c096
commit
b83f433714
12433 changed files with 156208 additions and 123 deletions
160
Task/Read-a-configuration-file/Go/read-a-configuration-file-1.go
Normal file
160
Task/Read-a-configuration-file/Go/read-a-configuration-file-1.go
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"fmt"
|
||||
"bytes"
|
||||
"strings"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
var (
|
||||
ENONE = errors.New("Requested value does not exist")
|
||||
EBADTYPE = errors.New("Requested type and actual type do not match")
|
||||
EBADVAL = errors.New("Value and type do not match")
|
||||
)
|
||||
|
||||
type varError struct {
|
||||
err error
|
||||
n string
|
||||
t VarType
|
||||
}
|
||||
|
||||
func (err *varError) Error() string {
|
||||
return fmt.Sprintf("%v: (%q, %v)", err.err, err.n, err.t)
|
||||
}
|
||||
|
||||
type VarType int
|
||||
|
||||
const (
|
||||
Bool VarType = 1 + iota
|
||||
Array
|
||||
String
|
||||
)
|
||||
|
||||
func (t VarType) String() string {
|
||||
switch t {
|
||||
case Bool:
|
||||
return "Bool"
|
||||
case Array:
|
||||
return "Array"
|
||||
case String:
|
||||
return "String"
|
||||
}
|
||||
|
||||
panic("Unknown VarType")
|
||||
}
|
||||
|
||||
type confvar struct {
|
||||
Type VarType
|
||||
Val interface{}
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
m map[string]confvar
|
||||
}
|
||||
|
||||
func Parse(r io.Reader) (c *Config, err error) {
|
||||
c = new(Config)
|
||||
c.m = make(map[string]confvar)
|
||||
|
||||
buf, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
lines := bytes.Split(buf, []byte{'\n'})
|
||||
|
||||
for _, line := range lines {
|
||||
line = bytes.TrimSpace(line)
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
switch line[0] {
|
||||
case '#', ';':
|
||||
continue
|
||||
}
|
||||
|
||||
parts := bytes.SplitN(line, []byte{' '}, 2)
|
||||
nam := string(bytes.ToLower(parts[0]))
|
||||
|
||||
if len(parts) == 1 {
|
||||
c.m[nam] = confvar{Bool, true}
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.Contains(string(parts[1]), ",") {
|
||||
tmpB := bytes.Split(parts[1], []byte{','})
|
||||
for i := range tmpB {
|
||||
tmpB[i] = bytes.TrimSpace(tmpB[i])
|
||||
}
|
||||
tmpS := make([]string, 0, len(tmpB))
|
||||
for i := range tmpB {
|
||||
tmpS = append(tmpS, string(tmpB[i]))
|
||||
}
|
||||
|
||||
c.m[nam] = confvar{Array, tmpS}
|
||||
continue
|
||||
}
|
||||
|
||||
c.m[nam] = confvar{String, string(bytes.TrimSpace(parts[1]))}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Config) Bool(name string) (bool, error) {
|
||||
name = strings.ToLower(name)
|
||||
|
||||
if _, ok := c.m[name]; !ok {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if c.m[name].Type != Bool {
|
||||
return false, &varError{EBADTYPE, name, Bool}
|
||||
}
|
||||
|
||||
v, ok := c.m[name].Val.(bool)
|
||||
if !ok {
|
||||
return false, &varError{EBADVAL, name, Bool}
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func (c *Config) Array(name string) ([]string, error) {
|
||||
name = strings.ToLower(name)
|
||||
|
||||
if _, ok := c.m[name]; !ok {
|
||||
return nil, &varError{ENONE, name, Array}
|
||||
}
|
||||
|
||||
if c.m[name].Type != Array {
|
||||
return nil, &varError{EBADTYPE, name, Array}
|
||||
}
|
||||
|
||||
v, ok := c.m[name].Val.([]string)
|
||||
if !ok {
|
||||
return nil, &varError{EBADVAL, name, Array}
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func (c *Config) String(name string) (string, error) {
|
||||
name = strings.ToLower(name)
|
||||
|
||||
if _, ok := c.m[name]; !ok {
|
||||
return "", &varError{ENONE, name, String}
|
||||
}
|
||||
|
||||
if c.m[name].Type != String {
|
||||
return "", &varError{EBADTYPE, name, String}
|
||||
}
|
||||
|
||||
v, ok := c.m[name].Val.(string)
|
||||
if !ok {
|
||||
return "", &varError{EBADVAL, name, String}
|
||||
}
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"fmt"
|
||||
"config"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Printf("Usage: %v <configfile>\n", os.Args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
file, err := os.Open(os.Args[1])
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
conf, err := config.Parse(file)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fullname, err := conf.String("fullname")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
favouritefruit, err := conf.String("favouritefruit")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
needspeeling, err := conf.Bool("needspeeling")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
seedsremoved, err := conf.Bool("seedsremoved")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
otherfamily, err := conf.Array("otherfamily")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("FULLNAME: %q\n", fullname)
|
||||
fmt.Printf("FAVOURITEFRUIT: %q\n", favouritefruit)
|
||||
fmt.Printf("NEEDSPEELING: %q\n", needspeeling)
|
||||
fmt.Printf("SEEDSREMOVED: %q\n", seedsremoved)
|
||||
fmt.Printf("OTHERFAMILY: %q\n", otherfamily)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue