-
Notifications
You must be signed in to change notification settings - Fork 82
/
strparse.go
91 lines (88 loc) · 1.61 KB
/
strparse.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// Package strparse is used to parse strings
package strparse
import (
"fmt"
"github.com/regclient/regclient/types"
)
// SplitCSKV splits a comma separated key=value list into a map
func SplitCSKV(s string) (map[string]string, error) {
state := "key"
key := ""
val := ""
result := map[string]string{}
procKV := func() {
if key != "" {
result[key] = val
}
state = "key"
key = ""
val = ""
}
for _, c := range s {
switch state {
case "key":
switch c {
case '"':
state = "keyQuote"
case '\\':
state = "keyEscape"
case '=':
state = "val"
case ',':
procKV()
default:
key = key + string(c)
}
case "keyQuote":
switch c {
case '"':
state = "key"
case '\\':
state = "keyEscapeQuote"
default:
key = key + string(c)
}
case "keyEscape":
key = key + string(c)
state = "key"
case "keyEscapeQuote":
key = key + string(c)
state = "keyQuote"
case "val":
switch c {
case '"':
state = "valQuote"
case ',':
procKV()
case '\\':
state = "valEscape"
default:
val = val + string(c)
}
case "valQuote":
switch c {
case '"':
state = "val"
case '\\':
state = "valEscapeQuote"
default:
val = val + string(c)
}
case "valEscape":
val = val + string(c)
state = "val"
case "valEscapeQuote":
val = val + string(c)
state = "valQuote"
default:
return nil, fmt.Errorf("unhandled state: %s", state)
}
}
switch state {
case "val", "key":
procKV()
default:
return nil, fmt.Errorf("string parsing failed, end state: %s%.0w", state, types.ErrParsingFailed)
}
return result, nil
}