diff options
Diffstat (limited to '')
| -rw-r--r-- | common/args/args.go | 79 | ||||
| -rw-r--r-- | common/args/args_test.go | 83 |
2 files changed, 162 insertions, 0 deletions
diff --git a/common/args/args.go b/common/args/args.go new file mode 100644 index 0000000..28c3b5f --- /dev/null +++ b/common/args/args.go @@ -0,0 +1,79 @@ +package args + +import ( + "strings" + + "github.com/osm/quake/common/buffer" +) + +type Arg struct { + Cmd string + Args []string +} + +func Parse(input string) []Arg { + var arg string + var args []string + var ret []Arg + var inQuotes bool + + for _, c := range input { + switch c { + case '\n', ';': + if inQuotes { + arg += string(c) + continue + } + + if arg != "" { + args = append(args, strings.TrimSpace(arg)) + } + + ret = append(ret, Arg{Cmd: strings.TrimSpace(args[0]), Args: args[1:]}) + arg = "" + args = []string{} + case ' ': + if inQuotes { + arg += string(c) + continue + } + + if arg != "" { + args = append(args, strings.TrimSpace(arg)) + arg = "" + } + case '"': + inQuotes = !inQuotes + arg += string(c) + default: + arg += string(c) + } + } + + if arg != "" { + args = append(args, strings.TrimSpace(arg)) + } + + if len(args) > 0 { + ret = append(ret, Arg{Cmd: strings.TrimSpace(args[0]), Args: args[1:]}) + } + + return ret +} + +func (s Arg) Bytes() []byte { + buf := buffer.New() + + buf.PutBytes([]byte(s.Cmd)) + + if len(s.Args) > 0 { + buf.PutByte(byte(' ')) + buf.PutBytes([]byte(strings.Join(s.Args, " "))) + } + + return buf.Bytes() +} + +func (s Arg) String() string { + return string(s.Bytes()) +} diff --git a/common/args/args_test.go b/common/args/args_test.go new file mode 100644 index 0000000..4f1967c --- /dev/null +++ b/common/args/args_test.go @@ -0,0 +1,83 @@ +package args + +import ( + "encoding/base64" + "reflect" + "testing" +) + +type argsTest struct { + name string + input string + expected []Arg +} + +var argsTests = []argsTest{ + { + name: "foo bar baz", + input: "Zm9vIGJhciBiYXo=", + expected: []Arg{ + { + Cmd: "foo", + Args: []string{"bar", "baz"}, + }, + }, + }, + { + name: "foo bar baz\n", + input: "Zm9vIGJhciBiYXoK", + expected: []Arg{ + { + Cmd: "foo", + Args: []string{"bar", "baz"}, + }, + }, + }, + { + name: "foo \"bar baz\"", + input: "Zm9vICJiYXIgYmF6Ig==", + expected: []Arg{ + { + Cmd: "foo", + Args: []string{"\"bar baz\""}, + }, + }, + }, + { + name: "foo \"bar baz\";foo bar baz\nfoo bar", + input: "Zm9vICJiYXIgYmF6Ijtmb28gYmFyIGJhegpmb28gYmFy", + expected: []Arg{ + { + Cmd: "foo", + Args: []string{"\"bar baz\""}, + }, + { + Cmd: "foo", + Args: []string{"bar", "baz"}, + }, + { + Cmd: "foo", + Args: []string{"bar"}, + }, + }, + }, +} + +func TestArgs(t *testing.T) { + for _, at := range argsTests { + t.Run(at.name, func(t *testing.T) { + input, err := base64.StdEncoding.DecodeString(at.input) + if err != nil { + t.Errorf("unable to decode input: %#v", err) + } + + args := Parse(string(input)) + + if !reflect.DeepEqual(at.expected, args) { + t.Errorf("parsed args output didn't match") + t.Logf("output: %#v", args) + t.Logf("expected: %#v", at.expected) + } + }) + } +} |
