-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathparse.go
125 lines (119 loc) · 2.35 KB
/
parse.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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package gojo
import (
"encoding/base64"
"encoding/json"
"os"
"strconv"
"strings"
"github.com/iancoleman/orderedmap"
)
func parseKeyValue(s string) (setter, error) {
i := strings.IndexByte(s, '=')
if i < 0 {
return nil, errParse(s)
}
key := s[:i]
value, err := parseValue(s[i+1:])
if err != nil {
return nil, err
}
return buildSetter(key, value, false), nil
}
func parseValue(s string) (any, error) {
if s == "" {
return "", nil
}
switch s[0] {
case '@':
cnt, err := os.ReadFile(s[1:])
if err != nil {
return nil, err
}
for _, c := range []byte{'\n', '\r'} {
if l := len(cnt); l > 0 && cnt[l-1] == c {
cnt = cnt[:l-1]
}
}
return string(cnt), nil
case ':':
cnt, err := os.ReadFile(s[1:])
if err != nil {
return nil, err
}
return decodeJSON(cnt)
case '%':
cnt, err := os.ReadFile(s[1:])
if err != nil {
return nil, err
}
return base64.StdEncoding.EncodeToString(cnt), nil
default:
if v, err := decodeJSON([]byte(s)); err == nil {
return v, nil
}
if i, err := strconv.ParseInt(s, 10, 64); err == nil {
return i, nil
}
if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") {
if i, err := strconv.ParseInt(s[2:], 16, 64); err == nil {
return i, nil
}
}
return s, nil
}
}
func decodeJSON(bs []byte) (any, error) {
var m orderedmap.OrderedMap
if err := json.Unmarshal(bs, &m); err == nil {
return m, nil
}
var vs []orderedmap.OrderedMap
if err := json.Unmarshal(bs, &vs); err == nil {
if vs == nil {
return nil, nil
}
ws := make([]any, len(vs))
for i, v := range vs {
ws[i] = v
}
return ws, nil
}
var v any
if err := json.Unmarshal(bs, &v); err != nil {
return nil, err
}
return v, nil
}
func buildSetter(key string, value any, inner bool) setter {
i, j := strings.IndexByte(key, '['), strings.IndexByte(key, ']')
if i < 0 || j < 0 || j < i {
if inner {
return nil
}
return &objectSetter{key, value}
}
if i > 0 || !inner {
s := buildSetter(key[i:], value, true)
if s == nil {
if inner {
return nil
}
return &objectSetter{key, value}
}
return &objectSetter{key[:i], s}
}
if j < len(key)-1 {
s := buildSetter(key[j+1:], value, true)
if s == nil {
if inner {
return nil
}
return &objectSetter{key, value}
}
value = s
}
if i+1 == j {
return &arraySetter{value}
}
return &objectSetter{key[i+1 : j], value}
}