blob: 95ae54fbfe4dfbf87b807135f2e22de4b0ccb7b8 [file] [log] [blame]
Scott Bakere7144bc2019-10-01 14:16:47 -07001package 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
77 captureStartedAt int
78 captured []byte
79 Error error
80 Attachment interface{} // open for customized decoder
81}
82
83// NewIterator creates an empty Iterator instance
84func NewIterator(cfg API) *Iterator {
85 return &Iterator{
86 cfg: cfg.(*frozenConfig),
87 reader: nil,
88 buf: nil,
89 head: 0,
90 tail: 0,
91 }
92}
93
94// Parse creates an Iterator instance from io.Reader
95func Parse(cfg API, reader io.Reader, bufSize int) *Iterator {
96 return &Iterator{
97 cfg: cfg.(*frozenConfig),
98 reader: reader,
99 buf: make([]byte, bufSize),
100 head: 0,
101 tail: 0,
102 }
103}
104
105// ParseBytes creates an Iterator instance from byte array
106func ParseBytes(cfg API, input []byte) *Iterator {
107 return &Iterator{
108 cfg: cfg.(*frozenConfig),
109 reader: nil,
110 buf: input,
111 head: 0,
112 tail: len(input),
113 }
114}
115
116// ParseString creates an Iterator instance from string
117func ParseString(cfg API, input string) *Iterator {
118 return ParseBytes(cfg, []byte(input))
119}
120
121// Pool returns a pool can provide more iterator with same configuration
122func (iter *Iterator) Pool() IteratorPool {
123 return iter.cfg
124}
125
126// Reset reuse iterator instance by specifying another reader
127func (iter *Iterator) Reset(reader io.Reader) *Iterator {
128 iter.reader = reader
129 iter.head = 0
130 iter.tail = 0
131 return iter
132}
133
134// ResetBytes reuse iterator instance by specifying another byte array as input
135func (iter *Iterator) ResetBytes(input []byte) *Iterator {
136 iter.reader = nil
137 iter.buf = input
138 iter.head = 0
139 iter.tail = len(input)
140 return iter
141}
142
143// WhatIsNext gets ValueType of relatively next json element
144func (iter *Iterator) WhatIsNext() ValueType {
145 valueType := valueTypes[iter.nextToken()]
146 iter.unreadByte()
147 return valueType
148}
149
150func (iter *Iterator) skipWhitespacesWithoutLoadMore() bool {
151 for i := iter.head; i < iter.tail; i++ {
152 c := iter.buf[i]
153 switch c {
154 case ' ', '\n', '\t', '\r':
155 continue
156 }
157 iter.head = i
158 return false
159 }
160 return true
161}
162
163func (iter *Iterator) isObjectEnd() bool {
164 c := iter.nextToken()
165 if c == ',' {
166 return false
167 }
168 if c == '}' {
169 return true
170 }
171 iter.ReportError("isObjectEnd", "object ended prematurely, unexpected char "+string([]byte{c}))
172 return true
173}
174
175func (iter *Iterator) nextToken() byte {
176 // a variation of skip whitespaces, returning the next non-whitespace token
177 for {
178 for i := iter.head; i < iter.tail; i++ {
179 c := iter.buf[i]
180 switch c {
181 case ' ', '\n', '\t', '\r':
182 continue
183 }
184 iter.head = i + 1
185 return c
186 }
187 if !iter.loadMore() {
188 return 0
189 }
190 }
191}
192
193// ReportError record a error in iterator instance with current position.
194func (iter *Iterator) ReportError(operation string, msg string) {
195 if iter.Error != nil {
196 if iter.Error != io.EOF {
197 return
198 }
199 }
200 peekStart := iter.head - 10
201 if peekStart < 0 {
202 peekStart = 0
203 }
204 peekEnd := iter.head + 10
205 if peekEnd > iter.tail {
206 peekEnd = iter.tail
207 }
208 parsing := string(iter.buf[peekStart:peekEnd])
209 contextStart := iter.head - 50
210 if contextStart < 0 {
211 contextStart = 0
212 }
213 contextEnd := iter.head + 50
214 if contextEnd > iter.tail {
215 contextEnd = iter.tail
216 }
217 context := string(iter.buf[contextStart:contextEnd])
218 iter.Error = fmt.Errorf("%s: %s, error found in #%v byte of ...|%s|..., bigger context ...|%s|...",
219 operation, msg, iter.head-peekStart, parsing, context)
220}
221
222// CurrentBuffer gets current buffer as string for debugging purpose
223func (iter *Iterator) CurrentBuffer() string {
224 peekStart := iter.head - 10
225 if peekStart < 0 {
226 peekStart = 0
227 }
228 return fmt.Sprintf("parsing #%v byte, around ...|%s|..., whole buffer ...|%s|...", iter.head,
229 string(iter.buf[peekStart:iter.head]), string(iter.buf[0:iter.tail]))
230}
231
232func (iter *Iterator) readByte() (ret byte) {
233 if iter.head == iter.tail {
234 if iter.loadMore() {
235 ret = iter.buf[iter.head]
236 iter.head++
237 return ret
238 }
239 return 0
240 }
241 ret = iter.buf[iter.head]
242 iter.head++
243 return ret
244}
245
246func (iter *Iterator) loadMore() bool {
247 if iter.reader == nil {
248 if iter.Error == nil {
249 iter.head = iter.tail
250 iter.Error = io.EOF
251 }
252 return false
253 }
254 if iter.captured != nil {
255 iter.captured = append(iter.captured,
256 iter.buf[iter.captureStartedAt:iter.tail]...)
257 iter.captureStartedAt = 0
258 }
259 for {
260 n, err := iter.reader.Read(iter.buf)
261 if n == 0 {
262 if err != nil {
263 if iter.Error == nil {
264 iter.Error = err
265 }
266 return false
267 }
268 } else {
269 iter.head = 0
270 iter.tail = n
271 return true
272 }
273 }
274}
275
276func (iter *Iterator) unreadByte() {
277 if iter.Error != nil {
278 return
279 }
280 iter.head--
281 return
282}
283
284// Read read the next JSON element as generic interface{}.
285func (iter *Iterator) Read() interface{} {
286 valueType := iter.WhatIsNext()
287 switch valueType {
288 case StringValue:
289 return iter.ReadString()
290 case NumberValue:
291 if iter.cfg.configBeforeFrozen.UseNumber {
292 return json.Number(iter.readNumberAsString())
293 }
294 return iter.ReadFloat64()
295 case NilValue:
296 iter.skipFourBytes('n', 'u', 'l', 'l')
297 return nil
298 case BoolValue:
299 return iter.ReadBool()
300 case ArrayValue:
301 arr := []interface{}{}
302 iter.ReadArrayCB(func(iter *Iterator) bool {
303 var elem interface{}
304 iter.ReadVal(&elem)
305 arr = append(arr, elem)
306 return true
307 })
308 return arr
309 case ObjectValue:
310 obj := map[string]interface{}{}
311 iter.ReadMapCB(func(Iter *Iterator, field string) bool {
312 var elem interface{}
313 iter.ReadVal(&elem)
314 obj[field] = elem
315 return true
316 })
317 return obj
318 default:
319 iter.ReportError("Read", fmt.Sprintf("unexpected value type: %v", valueType))
320 return nil
321 }
322}