package main import ( "log" "strconv" "strings" ) type Param struct { Index int Key string Value string } func (p *Param) String() *string { if p == nil { return nil } return &p.Value } func (p *Param) StringOr(fallback string) string { if p == nil { return fallback } return p.Value } func (p *Param) Int() *int { if p == nil { return nil } n, err := strconv.Atoi(p.Value) if err != nil { return nil } return &n } func (p *Param) Float() *float64 { if p == nil { return nil } n, err := strconv.ParseFloat(p.Value, 64) if err != nil { return nil } return &n } func (p *Param) Bool() *bool { if p == nil { return nil } v := strings.ToLower(p.Value) if v == "yes" || v == "true" || v == "on" { r := true return &r } else if v == "no" || v == "false" || v == "off" { r := false return &r } return nil } type Params []Param func (p Params) Get(key interface{}) *Param { switch key := key.(type) { case string: for _, p := range p { if p.Key == key { return &p } } case int: for _, p := range p { if p.Index == key { return &p } } default: log.Panicf("Incorrect key type %T", key) } return nil } func (p Params) Subset(prefix string) Params { if len(p) == 0 { return Params{} } if len(prefix) > 0 && !strings.HasSuffix(prefix, ".") { prefix += "." } res := make(Params, 0, len(p)) for _, param := range p { if param.Index == -1 && strings.HasPrefix(param.Key, prefix) { res = append(res, Param{Index: -1, Key: param.Key[len(prefix):], Value: param.Value}) } } return res } func (p Params) StringMap() map[string]string { res := make(map[string]string) for _, param := range p { if param.Index == -1 { res[param.Key] = param.Value } } return res } func (p Params) StringPtrMap() map[string]*string { res := make(map[string]*string) for _, param := range p { if param.Index == -1 { if param.Value == "NULL" { res[param.Key] = nil } else { res[param.Key] = ¶m.Value } } } return res } func (p Params) Strings(minIndex int) []string { res := make([]string, 0, len(p)) for _, param := range p { if param.Index >= minIndex { res = append(res, param.Value) } } return res } type Command struct { Name string Params Params } func parseCommand(args []string) Command { if len(args) == 0 { return Command{Name: "help"} } cmd := Command{ Name: args[0], Params: make(Params, 0, len(args)-1), } nextIndex := 0 for _, arg := range args[1:] { kv := strings.SplitN(arg, "=", 2) if len(kv) == 2 { cmd.Params = append(cmd.Params, Param{Index: -1, Key: kv[0], Value: kv[1]}) } else { cmd.Params = append(cmd.Params, Param{Index: nextIndex, Value: arg}) nextIndex += 1 } } return cmd }