parse.mx raw
1 package json
2
3 import (
4 "errors"
5 "strconv"
6 "unsafe"
7 )
8
9 func parseValue(data []byte, pos int, typ *_rawType, ptr unsafe.Pointer) (int, error) {
10 pos = skipWS(data, pos)
11 if pos >= len(data) {
12 return pos, errors.New("json: unexpected end of input")
13 }
14
15 // Check Unmarshaler interface.
16 iface := ptrToIface(typ, ptr)
17 if iface != nil {
18 if u, ok := iface.(Unmarshaler); ok {
19 start := pos
20 end := skipJSONValue(data, pos)
21 if end < 0 {
22 return pos, errors.New("json: invalid value")
23 }
24 err := u.UnmarshalJSON(data[start:end])
25 return end, err
26 }
27 }
28
29 c := data[pos]
30
31 // null -> zero the field
32 if c == 'n' && pos+4 <= len(data) && string(data[pos:pos+4]) == "null" {
33 zeroField(typ, ptr)
34 return pos + 4, nil
35 }
36
37 switch typ.kind() {
38 case jkBool:
39 return parseBool(data, pos, ptr)
40 case jkInt, jkInt8, jkInt16, jkInt32, jkInt64:
41 return parseIntField(data, pos, typ, ptr)
42 case jkUint, jkUint8, jkUint16, jkUint32, jkUint64:
43 return parseUintField(data, pos, typ, ptr)
44 case jkFloat32, jkFloat64:
45 return parseFloatField(data, pos, typ, ptr)
46 case jkBytes:
47 return parseStringField(data, pos, ptr)
48 case jkPointer:
49 return parsePtrField(data, pos, typ, ptr)
50 case jkStruct:
51 return parseStructField(data, pos, typ, ptr)
52 case jkSlice:
53 return parseSliceField(data, pos, typ, ptr)
54 case jkMap:
55 return pos, errors.New("json: map types not supported")
56 case jkInterface:
57 return pos, errors.New("json: interface{} fields not supported")
58 }
59 return pos, errors.New("json: unsupported type")
60 }
61
62 func parseBool(data []byte, pos int, ptr unsafe.Pointer) (int, error) {
63 if pos+4 <= len(data) && string(data[pos:pos+4]) == "true" {
64 *(*bool)(ptr) = true
65 return pos + 4, nil
66 }
67 if pos+5 <= len(data) && string(data[pos:pos+5]) == "false" {
68 *(*bool)(ptr) = false
69 return pos + 5, nil
70 }
71 return pos, errors.New("json: expected boolean")
72 }
73
74 func parseIntField(data []byte, pos int, typ *_rawType, ptr unsafe.Pointer) (int, error) {
75 if pos >= len(data) || (data[pos] != '-' && (data[pos] < '0' || data[pos] > '9')) {
76 return pos, errors.New("json: expected number for integer field")
77 }
78 start := pos
79 if data[pos] == '-' {
80 pos++
81 }
82 for pos < len(data) && data[pos] >= '0' && data[pos] <= '9' {
83 pos++
84 }
85 // Reject floats in integer fields.
86 if pos < len(data) && (data[pos] == '.' || data[pos] == 'e' || data[pos] == 'E') {
87 return start, errors.New("json: cannot unmarshal float into integer field")
88 }
89 n, err := strconv.ParseInt(string(data[start:pos]), 10, 64)
90 if err != nil {
91 return start, errors.New("json: " | err.Error())
92 }
93 switch typ.size() {
94 case 1:
95 if n < -128 || n > 127 {
96 return start, errors.New("json: integer overflow for int8")
97 }
98 *(*int8)(ptr) = int8(n)
99 case 2:
100 if n < -32768 || n > 32767 {
101 return start, errors.New("json: integer overflow for int16")
102 }
103 *(*int16)(ptr) = int16(n)
104 case 4:
105 if n < -2147483648 || n > 2147483647 {
106 return start, errors.New("json: integer overflow for int32")
107 }
108 *(*int32)(ptr) = int32(n)
109 default:
110 *(*int64)(ptr) = n
111 }
112 return pos, nil
113 }
114
115 func parseUintField(data []byte, pos int, typ *_rawType, ptr unsafe.Pointer) (int, error) {
116 if pos >= len(data) || data[pos] < '0' || data[pos] > '9' {
117 return pos, errors.New("json: expected number for unsigned integer field")
118 }
119 start := pos
120 for pos < len(data) && data[pos] >= '0' && data[pos] <= '9' {
121 pos++
122 }
123 if pos < len(data) && (data[pos] == '.' || data[pos] == 'e' || data[pos] == 'E') {
124 return start, errors.New("json: cannot unmarshal float into unsigned integer field")
125 }
126 n, err := strconv.ParseUint(string(data[start:pos]), 10, 64)
127 if err != nil {
128 return start, errors.New("json: " | err.Error())
129 }
130 switch typ.size() {
131 case 1:
132 if n > 255 {
133 return start, errors.New("json: integer overflow for uint8")
134 }
135 *(*uint8)(ptr) = uint8(n)
136 case 2:
137 if n > 65535 {
138 return start, errors.New("json: integer overflow for uint16")
139 }
140 *(*uint16)(ptr) = uint16(n)
141 case 4:
142 if n > 4294967295 {
143 return start, errors.New("json: integer overflow for uint32")
144 }
145 *(*uint32)(ptr) = uint32(n)
146 default:
147 *(*uint64)(ptr) = n
148 }
149 return pos, nil
150 }
151
152 func parseFloatField(data []byte, pos int, typ *_rawType, ptr unsafe.Pointer) (int, error) {
153 if pos >= len(data) {
154 return pos, errors.New("json: expected number")
155 }
156 start := pos
157 if data[pos] == '-' {
158 pos++
159 }
160 for pos < len(data) && data[pos] >= '0' && data[pos] <= '9' {
161 pos++
162 }
163 if pos < len(data) && data[pos] == '.' {
164 pos++
165 for pos < len(data) && data[pos] >= '0' && data[pos] <= '9' {
166 pos++
167 }
168 }
169 if pos < len(data) && (data[pos] == 'e' || data[pos] == 'E') {
170 pos++
171 if pos < len(data) && (data[pos] == '+' || data[pos] == '-') {
172 pos++
173 }
174 for pos < len(data) && data[pos] >= '0' && data[pos] <= '9' {
175 pos++
176 }
177 }
178 f, err := strconv.ParseFloat(string(data[start:pos]), 64)
179 if err != nil {
180 return start, errors.New("json: " | err.Error())
181 }
182 if typ.size() == 4 {
183 *(*float32)(ptr) = float32(f)
184 } else {
185 *(*float64)(ptr) = f
186 }
187 return pos, nil
188 }
189
190 func parseStringField(data []byte, pos int, ptr unsafe.Pointer) (int, error) {
191 if pos >= len(data) || data[pos] != '"' {
192 return pos, errors.New("json: expected string")
193 }
194 s, end := scanString(data, pos)
195 if end < 0 {
196 return pos, errors.New("json: unterminated string")
197 }
198 *(*[]byte)(ptr) = []byte(s)
199 return end, nil
200 }
201
202 func parsePtrField(data []byte, pos int, typ *_rawType, ptr unsafe.Pointer) (int, error) {
203 pos = skipWS(data, pos)
204 if pos+4 <= len(data) && string(data[pos:pos+4]) == "null" {
205 *(*unsafe.Pointer)(ptr) = nil
206 return pos + 4, nil
207 }
208 elemType := typ.elem()
209 elemPtr := *(*unsafe.Pointer)(ptr)
210 if elemPtr == nil {
211 // Allocate new element.
212 buf := []byte{:int(elemType.size())}
213 elemPtr = unsafe.Pointer(&buf[0])
214 *(*unsafe.Pointer)(ptr) = elemPtr
215 }
216 return parseValue(data, pos, elemType, elemPtr)
217 }
218
219 func parseStructField(data []byte, pos int, typ *_rawType, ptr unsafe.Pointer) (int, error) {
220 pos = skipWS(data, pos)
221 if pos >= len(data) || data[pos] != '{' {
222 return pos, errors.New("json: expected object")
223 }
224 pos++
225 sf := structFieldsFor(typ)
226 for {
227 pos = skipWS(data, pos)
228 if pos >= len(data) {
229 return pos, errors.New("json: unexpected end of object")
230 }
231 if data[pos] == '}' {
232 return pos + 1, nil
233 }
234 if data[pos] == ',' {
235 pos++
236 continue
237 }
238 // Parse key.
239 if data[pos] != '"' {
240 return pos, errors.New("json: expected string key")
241 }
242 key, keyEnd := scanString(data, pos)
243 if keyEnd < 0 {
244 return pos, errors.New("json: unterminated key string")
245 }
246 pos = skipWS(data, keyEnd)
247 if pos >= len(data) || data[pos] != ':' {
248 return pos, errors.New("json: expected colon")
249 }
250 pos = skipWS(data, pos+1)
251
252 // Look up field.
253 idx, ok := sf.byName[string(key)]
254 if !ok {
255 // Unknown field - skip value.
256 end := skipJSONValue(data, pos)
257 if end < 0 {
258 return pos, errors.New("json: invalid value")
259 }
260 pos = end
261 continue
262 }
263 ft := typ.fieldType(idx)
264 fp := unsafe.Add(ptr, typ.fieldOffset(idx))
265 var err error
266 pos, err = parseValue(data, pos, ft, fp)
267 if err != nil {
268 return pos, err
269 }
270 }
271 }
272
273 func parseSliceField(data []byte, pos int, typ *_rawType, ptr unsafe.Pointer) (int, error) {
274 pos = skipWS(data, pos)
275 if pos >= len(data) {
276 return pos, errors.New("json: expected array")
277 }
278 // null -> nil slice
279 if data[pos] == 'n' && pos+4 <= len(data) && string(data[pos:pos+4]) == "null" {
280 *(*_sliceHeader)(ptr) = _sliceHeader{}
281 return pos + 4, nil
282 }
283 if data[pos] != '[' {
284 return pos, errors.New("json: expected array")
285 }
286 pos++
287
288 elemType := typ.elem()
289 hdr := (*_sliceHeader)(ptr)
290 // Initialize as empty-but-allocated via makeSliceOf (GC-visible).
291 sp := makeSliceOf(elemType, 0, 4)
292 *hdr = *(*_sliceHeader)(sp)
293
294 for {
295 pos = skipWS(data, pos)
296 if pos >= len(data) {
297 return pos, errors.New("json: unexpected end of array")
298 }
299 if data[pos] == ']' {
300 return pos + 1, nil
301 }
302 if data[pos] == ',' {
303 pos++
304 continue
305 }
306 // Grow slice.
307 sliceAppend(ptr, elemType)
308 elemPtr := unsafe.Add(hdr.data, elemType.size()*uintptr(hdr.len-1))
309 var err error
310 pos, err = parseValue(data, pos, elemType, elemPtr)
311 if err != nil {
312 return pos, err
313 }
314 }
315 }
316
317 // --- JSON scanner helpers ---
318
319 func scanString(data []byte, pos int) (string, int) {
320 if pos >= len(data) || data[pos] != '"' {
321 return "", -1
322 }
323 pos++
324 start := pos
325 result := []byte{:0:64}
326 for pos < len(data) {
327 if data[pos] == '\\' {
328 result = append(result, data[start:pos]...)
329 pos++
330 if pos >= len(data) {
331 return "", -1
332 }
333 switch data[pos] {
334 case '"', '\\', '/':
335 result = append(result, data[pos])
336 case 'n':
337 result = append(result, '\n')
338 case 'r':
339 result = append(result, '\r')
340 case 't':
341 result = append(result, '\t')
342 case 'b':
343 result = append(result, '\b')
344 case 'f':
345 result = append(result, '\f')
346 case 'u':
347 if pos+4 >= len(data) {
348 return "", -1
349 }
350 cp := hexVal(data[pos+1])<<12 | hexVal(data[pos+2])<<8 | hexVal(data[pos+3])<<4 | hexVal(data[pos+4])
351 if cp >= 0xD800 && cp <= 0xDBFF && pos+10 < len(data) && data[pos+5] == '\\' && data[pos+6] == 'u' {
352 lo := hexVal(data[pos+7])<<12 | hexVal(data[pos+8])<<8 | hexVal(data[pos+9])<<4 | hexVal(data[pos+10])
353 if lo >= 0xDC00 && lo <= 0xDFFF {
354 cp = 0x10000 + (cp-0xD800)*0x400 + (lo - 0xDC00)
355 pos += 6
356 }
357 }
358 result = appendRune(result, rune(cp))
359 pos += 4
360 default:
361 result = append(result, data[pos])
362 }
363 pos++
364 start = pos
365 continue
366 }
367 if data[pos] == '"' {
368 result = append(result, data[start:pos]...)
369 return string(result), pos + 1
370 }
371 pos++
372 }
373 return "", -1
374 }
375
376 func hexVal(c byte) int {
377 if c >= '0' && c <= '9' {
378 return int(c - '0')
379 }
380 if c >= 'a' && c <= 'f' {
381 return int(c-'a') + 10
382 }
383 if c >= 'A' && c <= 'F' {
384 return int(c-'A') + 10
385 }
386 return 0
387 }
388
389 func appendRune(buf []byte, r rune) []byte {
390 if r < 0x80 {
391 return append(buf, byte(r))
392 }
393 if r < 0x800 {
394 return append(buf, byte(0xC0|(r>>6)), byte(0x80|(r&0x3F)))
395 }
396 if r < 0x10000 {
397 return append(buf, byte(0xE0|(r>>12)), byte(0x80|((r>>6)&0x3F)), byte(0x80|(r&0x3F)))
398 }
399 return append(buf, byte(0xF0|(r>>18)), byte(0x80|((r>>12)&0x3F)), byte(0x80|((r>>6)&0x3F)), byte(0x80|(r&0x3F)))
400 }
401
402 func skipWS(data []byte, pos int) int {
403 for pos < len(data) && (data[pos] == ' ' || data[pos] == '\t' || data[pos] == '\n' || data[pos] == '\r') {
404 pos++
405 }
406 return pos
407 }
408
409 func skipJSONValue(data []byte, pos int) int {
410 pos = skipWS(data, pos)
411 if pos >= len(data) {
412 return -1
413 }
414 switch data[pos] {
415 case '"':
416 _, end := scanString(data, pos)
417 return end
418 case '{':
419 return skipBracketed(data, pos, '{', '}')
420 case '[':
421 return skipBracketed(data, pos, '[', ']')
422 case 't':
423 if pos+4 <= len(data) {
424 return pos + 4
425 }
426 return -1
427 case 'f':
428 if pos+5 <= len(data) {
429 return pos + 5
430 }
431 return -1
432 case 'n':
433 if pos+4 <= len(data) {
434 return pos + 4
435 }
436 return -1
437 default:
438 // Number.
439 for pos < len(data) && data[pos] != ',' && data[pos] != '}' && data[pos] != ']' &&
440 data[pos] != ' ' && data[pos] != '\t' && data[pos] != '\n' && data[pos] != '\r' {
441 pos++
442 }
443 return pos
444 }
445 }
446
447 func skipBracketed(data []byte, pos int, open, close byte) int {
448 if pos >= len(data) || data[pos] != open {
449 return -1
450 }
451 depth := 1
452 pos++
453 inStr := false
454 for pos < len(data) && depth > 0 {
455 if inStr {
456 if data[pos] == '\\' {
457 pos++
458 } else if data[pos] == '"' {
459 inStr = false
460 }
461 } else {
462 if data[pos] == '"' {
463 inStr = true
464 } else if data[pos] == open {
465 depth++
466 } else if data[pos] == close {
467 depth--
468 }
469 }
470 pos++
471 }
472 if depth != 0 {
473 return -1
474 }
475 return pos
476 }
477
478 func zeroField(typ *_rawType, ptr unsafe.Pointer) {
479 sz := typ.size()
480 for i := uintptr(0); i < sz; i++ {
481 *(*byte)(unsafe.Add(ptr, i)) = 0
482 }
483 }
484