-
Notifications
You must be signed in to change notification settings - Fork 4
/
dec_obj.go
93 lines (88 loc) · 2.07 KB
/
dec_obj.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
package jx
import (
"github.com/go-faster/errors"
)
// ObjBytes calls f for every key in object, using byte slice as key.
//
// The key value is valid only until f is not returned.
func (d *Decoder) ObjBytes(f func(d *Decoder, key []byte) error) error {
if err := d.consume('{'); err != nil {
return errors.Wrap(err, `"{" expected`)
}
if f == nil {
return d.skipObj()
}
if err := d.incDepth(); err != nil {
return err
}
c, err := d.more()
if err != nil {
return errors.Wrap(err, `'"' or "}" expected`)
}
if c == '}' {
return d.decDepth()
}
d.unread()
// Do not reference internal buffer for key if decoder is not buffered.
//
// Otherwise, subsequent reads may overwrite the key.
//
// See https://github.com/go-faster/jx/pull/62.
isBuffer := d.reader == nil
k, err := d.str(value{raw: isBuffer})
if err != nil {
return errors.Wrap(err, "field name")
}
if err := d.consume(':'); err != nil {
return errors.Wrap(err, `":" expected`)
}
// Skip whitespace.
if _, err = d.more(); err != nil {
return err
}
d.unread()
if err := f(d, k.buf); err != nil {
return errors.Wrap(err, "callback")
}
c, err = d.more()
if err != nil {
return errors.Wrap(err, `"," or "}" expected`)
}
for c == ',' {
k, err := d.str(value{raw: isBuffer})
if err != nil {
return errors.Wrap(err, "field name")
}
if err := d.consume(':'); err != nil {
return errors.Wrap(err, `":" expected`)
}
// Check that value exists.
if _, err = d.more(); err != nil {
return err
}
d.unread()
if err := f(d, k.buf); err != nil {
return errors.Wrap(err, "callback")
}
if c, err = d.more(); err != nil {
return err
}
}
if c != '}' {
err := badToken(c, d.offset()-1)
return errors.Wrap(err, `"}" expected`)
}
return d.decDepth()
}
// Obj reads json object, calling f on each field.
//
// Use ObjBytes to reduce heap allocations for keys.
func (d *Decoder) Obj(f func(d *Decoder, key string) error) error {
if f == nil {
// Skipping object.
return d.ObjBytes(nil)
}
return d.ObjBytes(func(d *Decoder, key []byte) error {
return f(d, string(key))
})
}