1package 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}
323