package util
import (
"fmt"
"strings"
)
// The input mapping is experessed on the command line as `key1:value1,key2:value2,...`
// We parse it here, but need to keep in mind that keys or values may contain
// commas and colons. We will allow escaping those using double quotes, so
// when passing in "key1":"value1", we will not look inside the quoted sections.
func ParseCommandlineMap(src string) (map[string]string, error) {
result := make(map[string]string)
tuples := splitString(src, ',')
for _, t := range tuples {
kv := splitString(t, ':')
if len(kv) != 2 {
return nil, fmt.Errorf("expected key:value, got :%s", t)
}
key := strings.TrimLeft(kv[0], `"`)
key = strings.TrimRight(key, `"`)
value := strings.TrimLeft(kv[1], `"`)
value = strings.TrimRight(value, `"`)
result[key] = value
}
return result, nil
}
// This function splits a string along the specifed separator, but it
// ignores anything between double quotes for splitting. We do simple
// inside/outside quote counting. Quotes are not stripped from output.
func splitString(s string, sep rune) ([]string) {
const escapeChar rune = '"'
var parts []string
var part string
inQuotes := false
for _, c := range s {
if c == escapeChar{
if inQuotes {
inQuotes = false
} else {
inQuotes = true
}
}
// If we've gotten the separator rune, consider the previous part
// complete, but only if we're outside of quoted sections
if c == sep && !inQuotes {
parts = append(parts, part)
part = ""
continue
}
part = part + string(c)
}
return append(parts, part)
}