blob: 29b31cf78950654b3478784fda9d024212db75ff [file] [log] [blame]
khenaidoo59ce9dd2019-11-11 13:05:32 -05001package jsoniter
2
3import (
4 "encoding/json"
5 "fmt"
6 "io"
7)
8
9// ValueType the type for JSON element
10type ValueType int
11
12const (
13 // InvalidValue invalid JSON element
14 InvalidValue ValueType = iota
15 // StringValue JSON element "string"
16 StringValue
17 // NumberValue JSON element 100 or 0.10
18 NumberValue
19 // NilValue JSON element null
20 NilValue
21 // BoolValue JSON element true or false
22 BoolValue
23 // ArrayValue JSON element []
24 ArrayValue
25 // ObjectValue JSON element {}
26 ObjectValue
27)
28
29var hexDigits []byte
30var valueTypes []ValueType
31
32func init() {
33 hexDigits = make([]byte, 256)
34 for i := 0; i < len(hexDigits); i++ {
35 hexDigits[i] = 255
36 }
37 for i := '0'; i <= '9'; i++ {
38 hexDigits[i] = byte(i - '0')
39 }
40 for i := 'a'; i <= 'f'; i++ {
41 hexDigits[i] = byte((i - 'a') + 10)
42 }
43 for i := 'A'; i <= 'F'; i++ {
44 hexDigits[i] = byte((i - 'A') + 10)
45 }
46 valueTypes = make([]ValueType, 256)
47 for i := 0; i < len(valueTypes); i++ {
48 valueTypes[i] = InvalidValue
49 }
50 valueTypes['"'] = StringValue
51 valueTypes['-'] = NumberValue
52 valueTypes['0'] = NumberValue
53 valueTypes['1'] = NumberValue
54 valueTypes['2'] = NumberValue
55 valueTypes['3'] = NumberValue
56 valueTypes['4'] = NumberValue
57 valueTypes['5'] = NumberValue
58 valueTypes['6'] = NumberValue
59 valueTypes['7'] = NumberValue
60 valueTypes['8'] = NumberValue
61 valueTypes['9'] = NumberValue
62 valueTypes['t'] = BoolValue
63 valueTypes['f'] = BoolValue
64 valueTypes['n'] = NilValue
65 valueTypes['['] = ArrayValue
66 valueTypes['{'] = ObjectValue
67}
68
69// Iterator is a io.Reader like object, with JSON specific read functions.
70// Error is not returned as return value, but stored as Error member on this iterator instance.
71type Iterator struct {
72 cfg *frozenConfig
73 reader io.Reader
74 buf []byte
75 head int
76 tail int
khenaidoo26721882021-08-11 17:42:52 -040077 depth int
khenaidoo59ce9dd2019-11-11 13:05:32 -050078 captureStartedAt int
79 captured []byte
80 Error error
81 Attachment interface{} // open for customized decoder
82}
83
84// NewIterator creates an empty Iterator instance
85func NewIterator(cfg API) *Iterator {
86 return &Iterator{
87 cfg: cfg.(*frozenConfig),
88 reader: nil,
89 buf: nil,
90 head: 0,
91 tail: 0,
khenaidoo26721882021-08-11 17:42:52 -040092 depth: 0,
khenaidoo59ce9dd2019-11-11 13:05:32 -050093 }
94}
95
96// Parse creates an Iterator instance from io.Reader
97func Parse(cfg API, reader io.Reader, bufSize int) *Iterator {
98 return &Iterator{
99 cfg: cfg.(*frozenConfig),
100 reader: reader,
101 buf: make([]byte, bufSize),
102 head: 0,
103 tail: 0,
khenaidoo26721882021-08-11 17:42:52 -0400104 depth: 0,
khenaidoo59ce9dd2019-11-11 13:05:32 -0500105 }
106}
107
108// ParseBytes creates an Iterator instance from byte array
109func ParseBytes(cfg API, input []byte) *Iterator {
110 return &Iterator{
111 cfg: cfg.(*frozenConfig),
112 reader: nil,
113 buf: input,
114 head: 0,
115 tail: len(input),
khenaidoo26721882021-08-11 17:42:52 -0400116 depth: 0,
khenaidoo59ce9dd2019-11-11 13:05:32 -0500117 }
118}
119
120// ParseString creates an Iterator instance from string
121func ParseString(cfg API, input string) *Iterator {
122 return ParseBytes(cfg, []byte(input))
123}
124
125// Pool returns a pool can provide more iterator with same configuration
126func (iter *Iterator) Pool() IteratorPool {
127 return iter.cfg
128}
129
130// Reset reuse iterator instance by specifying another reader
131func (iter *Iterator) Reset(reader io.Reader) *Iterator {
132 iter.reader = reader
133 iter.head = 0
134 iter.tail = 0
khenaidoo26721882021-08-11 17:42:52 -0400135 iter.depth = 0
khenaidoo59ce9dd2019-11-11 13:05:32 -0500136 return iter
137}
138
139// ResetBytes reuse iterator instance by specifying another byte array as input
140func (iter *Iterator) ResetBytes(input []byte) *Iterator {
141 iter.reader = nil
142 iter.buf = input
143 iter.head = 0
144 iter.tail = len(input)
khenaidoo26721882021-08-11 17:42:52 -0400145 iter.depth = 0
khenaidoo59ce9dd2019-11-11 13:05:32 -0500146 return iter
147}
148
149// WhatIsNext gets ValueType of relatively next json element
150func (iter *Iterator) WhatIsNext() ValueType {
151 valueType := valueTypes[iter.nextToken()]
152 iter.unreadByte()
153 return valueType
154}
155
156func (iter *Iterator) skipWhitespacesWithoutLoadMore() bool {
157 for i := iter.head; i < iter.tail; i++ {
158 c := iter.buf[i]
159 switch c {
160 case ' ', '\n', '\t', '\r':
161 continue
162 }
163 iter.head = i
164 return false
165 }
166 return true
167}
168
169func (iter *Iterator) isObjectEnd() bool {
170 c := iter.nextToken()
171 if c == ',' {
172 return false
173 }
174 if c == '}' {
175 return true
176 }
177 iter.ReportError("isObjectEnd", "object ended prematurely, unexpected char "+string([]byte{c}))
178 return true
179}
180
181func (iter *Iterator) nextToken() byte {
182 // a variation of skip whitespaces, returning the next non-whitespace token
183 for {
184 for i := iter.head; i < iter.tail; i++ {
185 c := iter.buf[i]
186 switch c {
187 case ' ', '\n', '\t', '\r':
188 continue
189 }
190 iter.head = i + 1
191 return c
192 }
193 if !iter.loadMore() {
194 return 0
195 }
196 }
197}
198
199// ReportError record a error in iterator instance with current position.
200func (iter *Iterator) ReportError(operation string, msg string) {
201 if iter.Error != nil {
202 if iter.Error != io.EOF {
203 return
204 }
205 }
206 peekStart := iter.head - 10
207 if peekStart < 0 {
208 peekStart = 0
209 }
210 peekEnd := iter.head + 10
211 if peekEnd > iter.tail {
212 peekEnd = iter.tail
213 }
214 parsing := string(iter.buf[peekStart:peekEnd])
215 contextStart := iter.head - 50
216 if contextStart < 0 {
217 contextStart = 0
218 }
219 contextEnd := iter.head + 50
220 if contextEnd > iter.tail {
221 contextEnd = iter.tail
222 }
223 context := string(iter.buf[contextStart:contextEnd])
224 iter.Error = fmt.Errorf("%s: %s, error found in #%v byte of ...|%s|..., bigger context ...|%s|...",
225 operation, msg, iter.head-peekStart, parsing, context)
226}
227
228// CurrentBuffer gets current buffer as string for debugging purpose
229func (iter *Iterator) CurrentBuffer() string {
230 peekStart := iter.head - 10
231 if peekStart < 0 {
232 peekStart = 0
233 }
234 return fmt.Sprintf("parsing #%v byte, around ...|%s|..., whole buffer ...|%s|...", iter.head,
235 string(iter.buf[peekStart:iter.head]), string(iter.buf[0:iter.tail]))
236}
237
238func (iter *Iterator) readByte() (ret byte) {
239 if iter.head == iter.tail {
240 if iter.loadMore() {
241 ret = iter.buf[iter.head]
242 iter.head++
243 return ret
244 }
245 return 0
246 }
247 ret = iter.buf[iter.head]
248 iter.head++
249 return ret
250}
251
252func (iter *Iterator) loadMore() bool {
253 if iter.reader == nil {
254 if iter.Error == nil {
255 iter.head = iter.tail
256 iter.Error = io.EOF
257 }
258 return false
259 }
260 if iter.captured != nil {
261 iter.captured = append(iter.captured,
262 iter.buf[iter.captureStartedAt:iter.tail]...)
263 iter.captureStartedAt = 0
264 }
265 for {
266 n, err := iter.reader.Read(iter.buf)
267 if n == 0 {
268 if err != nil {
269 if iter.Error == nil {
270 iter.Error = err
271 }
272 return false
273 }
274 } else {
275 iter.head = 0
276 iter.tail = n
277 return true
278 }
279 }
280}
281
282func (iter *Iterator) unreadByte() {
283 if iter.Error != nil {
284 return
285 }
286 iter.head--
287 return
288}
289
290// Read read the next JSON element as generic interface{}.
291func (iter *Iterator) Read() interface{} {
292 valueType := iter.WhatIsNext()
293 switch valueType {
294 case StringValue:
295 return iter.ReadString()
296 case NumberValue:
297 if iter.cfg.configBeforeFrozen.UseNumber {
298 return json.Number(iter.readNumberAsString())
299 }
300 return iter.ReadFloat64()
301 case NilValue:
302 iter.skipFourBytes('n', 'u', 'l', 'l')
303 return nil
304 case BoolValue:
305 return iter.ReadBool()
306 case ArrayValue:
307 arr := []interface{}{}
308 iter.ReadArrayCB(func(iter *Iterator) bool {
309 var elem interface{}
310 iter.ReadVal(&elem)
311 arr = append(arr, elem)
312 return true
313 })
314 return arr
315 case ObjectValue:
316 obj := map[string]interface{}{}
317 iter.ReadMapCB(func(Iter *Iterator, field string) bool {
318 var elem interface{}
319 iter.ReadVal(&elem)
320 obj[field] = elem
321 return true
322 })
323 return obj
324 default:
325 iter.ReportError("Read", fmt.Sprintf("unexpected value type: %v", valueType))
326 return nil
327 }
328}
khenaidoo26721882021-08-11 17:42:52 -0400329
330// limit maximum depth of nesting, as allowed by https://tools.ietf.org/html/rfc7159#section-9
331const maxDepth = 10000
332
333func (iter *Iterator) incrementDepth() (success bool) {
334 iter.depth++
335 if iter.depth <= maxDepth {
336 return true
337 }
338 iter.ReportError("incrementDepth", "exceeded max depth")
339 return false
340}
341
342func (iter *Iterator) decrementDepth() (success bool) {
343 iter.depth--
344 if iter.depth >= 0 {
345 return true
346 }
347 iter.ReportError("decrementDepth", "unexpected negative nesting")
348 return false
349}