blob: 6e7c370abecb79fc71d895814cc954987f1452a0 [file] [log] [blame]
Matthias Andreas Benkard832a54e2019-01-29 09:27:38 +01001package jsoniter
2
3import (
4 "fmt"
5 "unicode"
6)
7
8// ReadObject read one field from object.
9// If object ended, returns empty string.
10// Otherwise, returns the field name.
11func (iter *Iterator) ReadObject() (ret string) {
12 c := iter.nextToken()
13 switch c {
14 case 'n':
15 iter.skipThreeBytes('u', 'l', 'l')
16 return "" // null
17 case '{':
18 c = iter.nextToken()
19 if c == '"' {
20 iter.unreadByte()
21 field := iter.ReadString()
22 c = iter.nextToken()
23 if c != ':' {
24 iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
25 }
26 return field
27 }
28 if c == '}' {
29 return "" // end of object
30 }
31 iter.ReportError("ReadObject", `expect " after {, but found `+string([]byte{c}))
32 return
33 case ',':
34 field := iter.ReadString()
35 c = iter.nextToken()
36 if c != ':' {
37 iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
38 }
39 return field
40 case '}':
41 return "" // end of object
42 default:
43 iter.ReportError("ReadObject", fmt.Sprintf(`expect { or , or } or n, but found %s`, string([]byte{c})))
44 return
45 }
46}
47
48// CaseInsensitive
49func (iter *Iterator) readFieldHash() int64 {
50 hash := int64(0x811c9dc5)
51 c := iter.nextToken()
52 if c != '"' {
53 iter.ReportError("readFieldHash", `expect ", but found `+string([]byte{c}))
54 return 0
55 }
56 for {
57 for i := iter.head; i < iter.tail; i++ {
58 // require ascii string and no escape
59 b := iter.buf[i]
60 if b == '\\' {
61 iter.head = i
62 for _, b := range iter.readStringSlowPath() {
63 if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive {
64 b += 'a' - 'A'
65 }
66 hash ^= int64(b)
67 hash *= 0x1000193
68 }
69 c = iter.nextToken()
70 if c != ':' {
71 iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c}))
72 return 0
73 }
74 return hash
75 }
76 if b == '"' {
77 iter.head = i + 1
78 c = iter.nextToken()
79 if c != ':' {
80 iter.ReportError("readFieldHash", `expect :, but found `+string([]byte{c}))
81 return 0
82 }
83 return hash
84 }
85 if 'A' <= b && b <= 'Z' && !iter.cfg.caseSensitive {
86 b += 'a' - 'A'
87 }
88 hash ^= int64(b)
89 hash *= 0x1000193
90 }
91 if !iter.loadMore() {
92 iter.ReportError("readFieldHash", `incomplete field name`)
93 return 0
94 }
95 }
96}
97
98func calcHash(str string, caseSensitive bool) int64 {
99 hash := int64(0x811c9dc5)
100 for _, b := range str {
101 if caseSensitive {
102 hash ^= int64(b)
103 } else {
104 hash ^= int64(unicode.ToLower(b))
105 }
106 hash *= 0x1000193
107 }
108 return int64(hash)
109}
110
111// ReadObjectCB read object with callback, the key is ascii only and field name not copied
112func (iter *Iterator) ReadObjectCB(callback func(*Iterator, string) bool) bool {
113 c := iter.nextToken()
114 var field string
115 if c == '{' {
116 c = iter.nextToken()
117 if c == '"' {
118 iter.unreadByte()
119 field = iter.ReadString()
120 c = iter.nextToken()
121 if c != ':' {
122 iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
123 }
124 if !callback(iter, field) {
125 return false
126 }
127 c = iter.nextToken()
128 for c == ',' {
129 field = iter.ReadString()
130 c = iter.nextToken()
131 if c != ':' {
132 iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
133 }
134 if !callback(iter, field) {
135 return false
136 }
137 c = iter.nextToken()
138 }
139 if c != '}' {
140 iter.ReportError("ReadObjectCB", `object not ended with }`)
141 return false
142 }
143 return true
144 }
145 if c == '}' {
146 return true
147 }
148 iter.ReportError("ReadObjectCB", `expect " after }, but found `+string([]byte{c}))
149 return false
150 }
151 if c == 'n' {
152 iter.skipThreeBytes('u', 'l', 'l')
153 return true // null
154 }
155 iter.ReportError("ReadObjectCB", `expect { or n, but found `+string([]byte{c}))
156 return false
157}
158
159// ReadMapCB read map with callback, the key can be any string
160func (iter *Iterator) ReadMapCB(callback func(*Iterator, string) bool) bool {
161 c := iter.nextToken()
162 if c == '{' {
163 c = iter.nextToken()
164 if c == '"' {
165 iter.unreadByte()
166 field := iter.ReadString()
167 if iter.nextToken() != ':' {
168 iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
169 return false
170 }
171 if !callback(iter, field) {
172 return false
173 }
174 c = iter.nextToken()
175 for c == ',' {
176 field = iter.ReadString()
177 if iter.nextToken() != ':' {
178 iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
179 return false
180 }
181 if !callback(iter, field) {
182 return false
183 }
184 c = iter.nextToken()
185 }
186 if c != '}' {
187 iter.ReportError("ReadMapCB", `object not ended with }`)
188 return false
189 }
190 return true
191 }
192 if c == '}' {
193 return true
194 }
195 iter.ReportError("ReadMapCB", `expect " after }, but found `+string([]byte{c}))
196 return false
197 }
198 if c == 'n' {
199 iter.skipThreeBytes('u', 'l', 'l')
200 return true // null
201 }
202 iter.ReportError("ReadMapCB", `expect { or n, but found `+string([]byte{c}))
203 return false
204}
205
206func (iter *Iterator) readObjectStart() bool {
207 c := iter.nextToken()
208 if c == '{' {
209 c = iter.nextToken()
210 if c == '}' {
211 return false
212 }
213 iter.unreadByte()
214 return true
215 } else if c == 'n' {
216 iter.skipThreeBytes('u', 'l', 'l')
217 return false
218 }
219 iter.ReportError("readObjectStart", "expect { or n, but found "+string([]byte{c}))
220 return false
221}
222
223func (iter *Iterator) readObjectFieldAsBytes() (ret []byte) {
224 str := iter.ReadStringAsSlice()
225 if iter.skipWhitespacesWithoutLoadMore() {
226 if ret == nil {
227 ret = make([]byte, len(str))
228 copy(ret, str)
229 }
230 if !iter.loadMore() {
231 return
232 }
233 }
234 if iter.buf[iter.head] != ':' {
235 iter.ReportError("readObjectFieldAsBytes", "expect : after object field, but found "+string([]byte{iter.buf[iter.head]}))
236 return
237 }
238 iter.head++
239 if iter.skipWhitespacesWithoutLoadMore() {
240 if ret == nil {
241 ret = make([]byte, len(str))
242 copy(ret, str)
243 }
244 if !iter.loadMore() {
245 return
246 }
247 }
248 if ret == nil {
249 return str
250 }
251 return ret
252}