1
15
16 package strvals
17
18 import (
19 "bytes"
20 "encoding/json"
21 "fmt"
22 "io"
23 "strconv"
24 "strings"
25 "unicode"
26
27 "github.com/pkg/errors"
28 "sigs.k8s.io/yaml"
29 )
30
31
32 var ErrNotList = errors.New("not a list")
33
34
35
36 var MaxIndex = 65536
37
38
39
40 var MaxNestedNameLevel = 30
41
42
43 func ToYAML(s string) (string, error) {
44 m, err := Parse(s)
45 if err != nil {
46 return "", err
47 }
48 d, err := yaml.Marshal(m)
49 return strings.TrimSuffix(string(d), "\n"), err
50 }
51
52
53
54
55 func Parse(s string) (map[string]interface{}, error) {
56 vals := map[string]interface{}{}
57 scanner := bytes.NewBufferString(s)
58 t := newParser(scanner, vals, false)
59 err := t.parse()
60 return vals, err
61 }
62
63
64
65
66 func ParseString(s string) (map[string]interface{}, error) {
67 vals := map[string]interface{}{}
68 scanner := bytes.NewBufferString(s)
69 t := newParser(scanner, vals, true)
70 err := t.parse()
71 return vals, err
72 }
73
74
75
76
77
78 func ParseInto(s string, dest map[string]interface{}) error {
79 scanner := bytes.NewBufferString(s)
80 t := newParser(scanner, dest, false)
81 return t.parse()
82 }
83
84
85
86
87
88
89
90 func ParseFile(s string, reader RunesValueReader) (map[string]interface{}, error) {
91 vals := map[string]interface{}{}
92 scanner := bytes.NewBufferString(s)
93 t := newFileParser(scanner, vals, reader)
94 err := t.parse()
95 return vals, err
96 }
97
98
99
100
101 func ParseIntoString(s string, dest map[string]interface{}) error {
102 scanner := bytes.NewBufferString(s)
103 t := newParser(scanner, dest, true)
104 return t.parse()
105 }
106
107
108
109
110
111
112 func ParseJSON(s string, dest map[string]interface{}) error {
113 scanner := bytes.NewBufferString(s)
114 t := newJSONParser(scanner, dest)
115 return t.parse()
116 }
117
118
119
120
121 func ParseIntoFile(s string, dest map[string]interface{}, reader RunesValueReader) error {
122 scanner := bytes.NewBufferString(s)
123 t := newFileParser(scanner, dest, reader)
124 return t.parse()
125 }
126
127
128
129 type RunesValueReader func([]rune) (interface{}, error)
130
131
132
133
134
135
136 type parser struct {
137 sc *bytes.Buffer
138 data map[string]interface{}
139 reader RunesValueReader
140 isjsonval bool
141 }
142
143 func newParser(sc *bytes.Buffer, data map[string]interface{}, stringBool bool) *parser {
144 stringConverter := func(rs []rune) (interface{}, error) {
145 return typedVal(rs, stringBool), nil
146 }
147 return &parser{sc: sc, data: data, reader: stringConverter}
148 }
149
150 func newJSONParser(sc *bytes.Buffer, data map[string]interface{}) *parser {
151 return &parser{sc: sc, data: data, reader: nil, isjsonval: true}
152 }
153
154 func newFileParser(sc *bytes.Buffer, data map[string]interface{}, reader RunesValueReader) *parser {
155 return &parser{sc: sc, data: data, reader: reader}
156 }
157
158 func (t *parser) parse() error {
159 for {
160 err := t.key(t.data, 0)
161 if err == nil {
162 continue
163 }
164 if err == io.EOF {
165 return nil
166 }
167 return err
168 }
169 }
170
171 func runeSet(r []rune) map[rune]bool {
172 s := make(map[rune]bool, len(r))
173 for _, rr := range r {
174 s[rr] = true
175 }
176 return s
177 }
178
179 func (t *parser) key(data map[string]interface{}, nestedNameLevel int) (reterr error) {
180 defer func() {
181 if r := recover(); r != nil {
182 reterr = fmt.Errorf("unable to parse key: %s", r)
183 }
184 }()
185 stop := runeSet([]rune{'=', '[', ',', '.'})
186 for {
187 switch k, last, err := runesUntil(t.sc, stop); {
188 case err != nil:
189 if len(k) == 0 {
190 return err
191 }
192 return errors.Errorf("key %q has no value", string(k))
193
194
195 case last == '[':
196
197 i, err := t.keyIndex()
198 if err != nil {
199 return errors.Wrap(err, "error parsing index")
200 }
201 kk := string(k)
202
203 list := []interface{}{}
204 if _, ok := data[kk]; ok {
205 list = data[kk].([]interface{})
206 }
207
208
209 list, err = t.listItem(list, i, nestedNameLevel)
210 set(data, kk, list)
211 return err
212 case last == '=':
213 if t.isjsonval {
214 empval, err := t.emptyVal()
215 if err != nil {
216 return err
217 }
218 if empval {
219 set(data, string(k), nil)
220 return nil
221 }
222
223
224
225
226
227 var jsonval interface{}
228 dec := json.NewDecoder(strings.NewReader(t.sc.String()))
229 if err = dec.Decode(&jsonval); err != nil {
230 return err
231 }
232 set(data, string(k), jsonval)
233 if _, err = io.CopyN(io.Discard, t.sc, dec.InputOffset()); err != nil {
234 return err
235 }
236
237 _, err = t.emptyVal()
238 return err
239 }
240
241
242 vl, e := t.valList()
243 switch e {
244 case nil:
245 set(data, string(k), vl)
246 return nil
247 case io.EOF:
248 set(data, string(k), "")
249 return e
250 case ErrNotList:
251 rs, e := t.val()
252 if e != nil && e != io.EOF {
253 return e
254 }
255 v, e := t.reader(rs)
256 set(data, string(k), v)
257 return e
258 default:
259 return e
260 }
261 case last == ',':
262
263 set(data, string(k), "")
264 return errors.Errorf("key %q has no value (cannot end with ,)", string(k))
265 case last == '.':
266
267 nestedNameLevel++
268 if nestedNameLevel > MaxNestedNameLevel {
269 return fmt.Errorf("value name nested level is greater than maximum supported nested level of %d", MaxNestedNameLevel)
270 }
271
272
273 inner := map[string]interface{}{}
274 if _, ok := data[string(k)]; ok {
275 inner = data[string(k)].(map[string]interface{})
276 }
277
278
279 e := t.key(inner, nestedNameLevel)
280 if e == nil && len(inner) == 0 {
281 return errors.Errorf("key map %q has no value", string(k))
282 }
283 if len(inner) != 0 {
284 set(data, string(k), inner)
285 }
286 return e
287 }
288 }
289 }
290
291 func set(data map[string]interface{}, key string, val interface{}) {
292
293 if len(key) == 0 {
294 return
295 }
296 data[key] = val
297 }
298
299 func setIndex(list []interface{}, index int, val interface{}) (l2 []interface{}, err error) {
300
301
302
303 defer func() {
304 if r := recover(); r != nil {
305 err = fmt.Errorf("error processing index %d: %s", index, r)
306 }
307 }()
308
309 if index < 0 {
310 return list, fmt.Errorf("negative %d index not allowed", index)
311 }
312 if index > MaxIndex {
313 return list, fmt.Errorf("index of %d is greater than maximum supported index of %d", index, MaxIndex)
314 }
315 if len(list) <= index {
316 newlist := make([]interface{}, index+1)
317 copy(newlist, list)
318 list = newlist
319 }
320 list[index] = val
321 return list, nil
322 }
323
324 func (t *parser) keyIndex() (int, error) {
325
326 stop := runeSet([]rune{']'})
327 v, _, err := runesUntil(t.sc, stop)
328 if err != nil {
329 return 0, err
330 }
331
332 return strconv.Atoi(string(v))
333
334 }
335 func (t *parser) listItem(list []interface{}, i, nestedNameLevel int) ([]interface{}, error) {
336 if i < 0 {
337 return list, fmt.Errorf("negative %d index not allowed", i)
338 }
339 stop := runeSet([]rune{'[', '.', '='})
340 switch k, last, err := runesUntil(t.sc, stop); {
341 case len(k) > 0:
342 return list, errors.Errorf("unexpected data at end of array index: %q", k)
343 case err != nil:
344 return list, err
345 case last == '=':
346 if t.isjsonval {
347 empval, err := t.emptyVal()
348 if err != nil {
349 return list, err
350 }
351 if empval {
352 return setIndex(list, i, nil)
353 }
354
355
356
357
358
359 var jsonval interface{}
360 dec := json.NewDecoder(strings.NewReader(t.sc.String()))
361 if err = dec.Decode(&jsonval); err != nil {
362 return list, err
363 }
364 if list, err = setIndex(list, i, jsonval); err != nil {
365 return list, err
366 }
367 if _, err = io.CopyN(io.Discard, t.sc, dec.InputOffset()); err != nil {
368 return list, err
369 }
370
371 _, err = t.emptyVal()
372 return list, err
373 }
374 vl, e := t.valList()
375 switch e {
376 case nil:
377 return setIndex(list, i, vl)
378 case io.EOF:
379 return setIndex(list, i, "")
380 case ErrNotList:
381 rs, e := t.val()
382 if e != nil && e != io.EOF {
383 return list, e
384 }
385 v, e := t.reader(rs)
386 if e != nil {
387 return list, e
388 }
389 return setIndex(list, i, v)
390 default:
391 return list, e
392 }
393 case last == '[':
394
395 nextI, err := t.keyIndex()
396 if err != nil {
397 return list, errors.Wrap(err, "error parsing index")
398 }
399 var crtList []interface{}
400 if len(list) > i {
401
402 existed := list[i]
403 if existed != nil {
404 crtList = list[i].([]interface{})
405 }
406 }
407
408 list2, err := t.listItem(crtList, nextI, nestedNameLevel)
409 if err != nil {
410 return list, err
411 }
412 return setIndex(list, i, list2)
413 case last == '.':
414
415 inner := map[string]interface{}{}
416 if len(list) > i {
417 var ok bool
418 inner, ok = list[i].(map[string]interface{})
419 if !ok {
420
421 list[i] = map[string]interface{}{}
422 inner = list[i].(map[string]interface{})
423 }
424 }
425
426
427 e := t.key(inner, nestedNameLevel)
428 if e != nil {
429 return list, e
430 }
431 return setIndex(list, i, inner)
432 default:
433 return nil, errors.Errorf("parse error: unexpected token %v", last)
434 }
435 }
436
437
438
439
440 func (t *parser) emptyVal() (bool, error) {
441 for {
442 r, _, e := t.sc.ReadRune()
443 if e == io.EOF {
444 return true, nil
445 }
446 if e != nil {
447 return false, e
448 }
449 if r == ',' {
450 return true, nil
451 }
452 if !unicode.IsSpace(r) {
453 t.sc.UnreadRune()
454 return false, nil
455 }
456 }
457 }
458
459 func (t *parser) val() ([]rune, error) {
460 stop := runeSet([]rune{','})
461 v, _, err := runesUntil(t.sc, stop)
462 return v, err
463 }
464
465 func (t *parser) valList() ([]interface{}, error) {
466 r, _, e := t.sc.ReadRune()
467 if e != nil {
468 return []interface{}{}, e
469 }
470
471 if r != '{' {
472 t.sc.UnreadRune()
473 return []interface{}{}, ErrNotList
474 }
475
476 list := []interface{}{}
477 stop := runeSet([]rune{',', '}'})
478 for {
479 switch rs, last, err := runesUntil(t.sc, stop); {
480 case err != nil:
481 if err == io.EOF {
482 err = errors.New("list must terminate with '}'")
483 }
484 return list, err
485 case last == '}':
486
487 if r, _, e := t.sc.ReadRune(); e == nil && r != ',' {
488 t.sc.UnreadRune()
489 }
490 v, e := t.reader(rs)
491 list = append(list, v)
492 return list, e
493 case last == ',':
494 v, e := t.reader(rs)
495 if e != nil {
496 return list, e
497 }
498 list = append(list, v)
499 }
500 }
501 }
502
503 func runesUntil(in io.RuneReader, stop map[rune]bool) ([]rune, rune, error) {
504 v := []rune{}
505 for {
506 switch r, _, e := in.ReadRune(); {
507 case e != nil:
508 return v, r, e
509 case inMap(r, stop):
510 return v, r, nil
511 case r == '\\':
512 next, _, e := in.ReadRune()
513 if e != nil {
514 return v, next, e
515 }
516 v = append(v, next)
517 default:
518 v = append(v, r)
519 }
520 }
521 }
522
523 func inMap(k rune, m map[rune]bool) bool {
524 _, ok := m[k]
525 return ok
526 }
527
528 func typedVal(v []rune, st bool) interface{} {
529 val := string(v)
530
531 if st {
532 return val
533 }
534
535 if strings.EqualFold(val, "true") {
536 return true
537 }
538
539 if strings.EqualFold(val, "false") {
540 return false
541 }
542
543 if strings.EqualFold(val, "null") {
544 return nil
545 }
546
547 if strings.EqualFold(val, "0") {
548 return int64(0)
549 }
550
551
552 if len(val) != 0 && val[0] != '0' {
553 if iv, err := strconv.ParseInt(val, 10, 64); err == nil {
554 return iv
555 }
556 }
557
558 return val
559 }
560
View as plain text