1/*
2 * Copyright 2021 ByteDance Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "native.h"
18#include "utf8.h"
19#include "utils.h"
20
21static const uint64_t ODD_MASK = 0xaaaaaaaaaaaaaaaa;
22static const uint64_t EVEN_MASK = 0x5555555555555555;
23
24// NOTE: mask referenced from decoder/decoder.go
25static const uint64_t MASK_VALIDATE_STRING = 1ull << 5;
26static const uint64_t MASK_ALLOW_CONTROL = 1ull << 31;
27
28static const double P10_TAB[23] = {
29 /* <= the connvertion to double is not exact when less than 1 => */ 1e-000,
30 1e+001, 1e+002, 1e+003, 1e+004, 1e+005, 1e+006, 1e+007, 1e+008, 1e+009, 1e+010,
31 1e+011, 1e+012, 1e+013, 1e+014, 1e+015, 1e+016, 1e+017, 1e+018, 1e+019, 1e+020,
32 1e+021, 1e+022 /* <= the connvertion to double is not exact when larger, => */
33};
34
35static inline uint64_t add32(uint64_t v1, uint64_t v2, uint64_t *vo) {
36 uint32_t v;
37 uint32_t c = __builtin_uadd_overflow((uint32_t)v1, (uint32_t)v2, &v);
38
39 /* set the carry */
40 *vo = c;
41 return v;
42}
43
44static inline uint64_t add64(uint64_t v1, uint64_t v2, uint64_t *vo) {
45 unsigned long long v;
46 uint64_t c = __builtin_uaddll_overflow(v1, v2, &v);
47
48 /* set the carry */
49 *vo = c;
50 return v;
51}
52
53static inline char isspace(char ch) {
54 return ch == ' ' || ch == '\r' || ch == '\n' | ch == '\t';
55}
56
57const int MASK_USE_NUMBER = 1<<1;
58
59static inline void vdigits(const GoString *src, long *p, JsonState *ret, uint64_t flag) {
60 --*p;
61 if (flag & MASK_USE_NUMBER) {
62 long i = skip_number(src, p);
63 if (i < 0) {
64 ret->vt = i;
65 return;
66 }
67 ret->vt = V_DOUBLE;
68 ret->ep = i;
69 return;
70 }
71 vnumber(src, p, ret);
72}
73
74static inline char advance_ns(const GoString *src, long *p) {
75 size_t vi = *p;
76 size_t nb = src->len;
77 const char * sp = src->buf;
78
79 /* it's likely to run into non-spaces within a few
80 * characters, so test up to 4 characters manually */
81 if (vi < nb && !isspace(sp[vi])) goto nospace; else vi++;
82 if (vi < nb && !isspace(sp[vi])) goto nospace; else vi++;
83 if (vi < nb && !isspace(sp[vi])) goto nospace; else vi++;
84 if (vi < nb && !isspace(sp[vi])) goto nospace; else vi++;
85
86 /* check EOF */
87 if (vi >= nb) {
88 *p = vi;
89 return 0;
90 }
91
92 /* too many spaces, use SIMD to search for characters */
93 if ((vi = lspace(sp, nb, vi)) >= nb) {
94 return 0;
95 }
96
97nospace:
98 *p = vi + 1;
99 return src->buf[vi];
100}
101
102static inline int64_t advance_dword(const GoString *src, long *p, long dec, int64_t ret, uint32_t val) {
103 if (*p > src->len + dec - 4) {
104 *p = src->len;
105 return -ERR_EOF;
106 } else if (*(uint32_t *)(src->buf + *p - dec) == val) {
107 *p += 4 - dec;
108 return ret;
109 } else {
110 *p -= dec;
111 for (int i = 0; src->buf[*p] == (val & 0xff) && i < 4; i++, ++*p) { val >>= 8; }
112 return -ERR_INVAL;
113 }
114}
115
116static inline ssize_t advance_string_default(const GoString *src, long p, int64_t *ep) {
117 char ch;
118 uint64_t es;
119 uint64_t fe;
120 uint64_t os;
121 uint64_t m0;
122 uint64_t m1;
123 uint64_t cr = 0;
124
125 /* prevent out-of-bounds accessing */
126 if (unlikely(src->len == p)) {
127 return -ERR_EOF;
128 }
129
130 /* buffer pointers */
131 size_t nb = src->len;
132 const char * sp = src->buf;
133 const char * ss = src->buf;
134
135#define ep_init() *ep = -1;
136#define ep_setc() ep_setx(sp - ss - 1)
137#define ep_setx(x) if (*ep == -1) { *ep = (x); }
138
139 /* seek to `p` */
140 nb -= p;
141 sp += p;
142 ep_init()
143
144#if USE_AVX2
145 /* initialize vectors */
146 __m256i v0;
147 __m256i v1;
148 __m256i q0;
149 __m256i q1;
150 __m256i x0;
151 __m256i x1;
152 __m256i cq = _mm256_set1_epi8('"');
153 __m256i cx = _mm256_set1_epi8('\\');
154
155 /* partial masks */
156 uint32_t s0;
157 uint32_t s1;
158 uint32_t t0;
159 uint32_t t1;
160#else
161 /* initialize vectors */
162 __m128i v0;
163 __m128i v1;
164 __m128i v2;
165 __m128i v3;
166 __m128i q0;
167 __m128i q1;
168 __m128i q2;
169 __m128i q3;
170 __m128i x0;
171 __m128i x1;
172 __m128i x2;
173 __m128i x3;
174 __m128i cq = _mm_set1_epi8('"');
175 __m128i cx = _mm_set1_epi8('\\');
176
177 /* partial masks */
178 uint32_t s0;
179 uint32_t s1;
180 uint32_t s2;
181 uint32_t s3;
182 uint32_t t0;
183 uint32_t t1;
184 uint32_t t2;
185 uint32_t t3;
186#endif
187
188#define m0_mask(add) \
189 m1 &= ~cr; \
190 fe = (m1 << 1) | cr; \
191 os = (m1 & ~fe) & ODD_MASK; \
192 es = add(os, m1, &cr) << 1; \
193 m0 &= ~(fe & (es ^ EVEN_MASK));
194
195 /* 64-byte SIMD loop */
196 while (likely(nb >= 64)) {
197#if USE_AVX2
198 v0 = _mm256_loadu_si256 ((const void *)(sp + 0));
199 v1 = _mm256_loadu_si256 ((const void *)(sp + 32));
200 q0 = _mm256_cmpeq_epi8 (v0, cq);
201 q1 = _mm256_cmpeq_epi8 (v1, cq);
202 x0 = _mm256_cmpeq_epi8 (v0, cx);
203 x1 = _mm256_cmpeq_epi8 (v1, cx);
204 s0 = _mm256_movemask_epi8 (q0);
205 s1 = _mm256_movemask_epi8 (q1);
206 t0 = _mm256_movemask_epi8 (x0);
207 t1 = _mm256_movemask_epi8 (x1);
208 m0 = ((uint64_t)s1 << 32) | (uint64_t)s0;
209 m1 = ((uint64_t)t1 << 32) | (uint64_t)t0;
210#else
211 v0 = _mm_loadu_si128 ((const void *)(sp + 0));
212 v1 = _mm_loadu_si128 ((const void *)(sp + 16));
213 v2 = _mm_loadu_si128 ((const void *)(sp + 32));
214 v3 = _mm_loadu_si128 ((const void *)(sp + 48));
215 q0 = _mm_cmpeq_epi8 (v0, cq);
216 q1 = _mm_cmpeq_epi8 (v1, cq);
217 q2 = _mm_cmpeq_epi8 (v2, cq);
218 q3 = _mm_cmpeq_epi8 (v3, cq);
219 x0 = _mm_cmpeq_epi8 (v0, cx);
220 x1 = _mm_cmpeq_epi8 (v1, cx);
221 x2 = _mm_cmpeq_epi8 (v2, cx);
222 x3 = _mm_cmpeq_epi8 (v3, cx);
223 s0 = _mm_movemask_epi8 (q0);
224 s1 = _mm_movemask_epi8 (q1);
225 s2 = _mm_movemask_epi8 (q2);
226 s3 = _mm_movemask_epi8 (q3);
227 t0 = _mm_movemask_epi8 (x0);
228 t1 = _mm_movemask_epi8 (x1);
229 t2 = _mm_movemask_epi8 (x2);
230 t3 = _mm_movemask_epi8 (x3);
231 m0 = ((uint64_t)s3 << 48) | ((uint64_t)s2 << 32) | ((uint64_t)s1 << 16) | (uint64_t)s0;
232 m1 = ((uint64_t)t3 << 48) | ((uint64_t)t2 << 32) | ((uint64_t)t1 << 16) | (uint64_t)t0;
233#endif
234 /** update first quote position */
235 if (unlikely(m1 != 0)) {
236 ep_setx(sp - ss + __builtin_ctzll(m1))
237 }
238
239 /** mask all the escaped quotes */
240 if (unlikely(m1 != 0 || cr != 0)) {
241 m0_mask(add64)
242 }
243
244 /* check for end quote */
245 if (m0 != 0) {
246 return sp - ss + __builtin_ctzll(m0) + 1;
247 }
248
249 /* move to the next block */
250 sp += 64;
251 nb -= 64;
252 }
253
254 /* 32-byte SIMD round */
255 if (likely(nb >= 32)) {
256#if USE_AVX2
257 v0 = _mm256_loadu_si256 ((const void *)sp);
258 q0 = _mm256_cmpeq_epi8 (v0, cq);
259 x0 = _mm256_cmpeq_epi8 (v0, cx);
260 s0 = _mm256_movemask_epi8 (q0);
261 t0 = _mm256_movemask_epi8 (x0);
262 m0 = (uint64_t)s0;
263 m1 = (uint64_t)t0;
264#else
265 v0 = _mm_loadu_si128 ((const void *)(sp + 0));
266 v1 = _mm_loadu_si128 ((const void *)(sp + 16));
267 q0 = _mm_cmpeq_epi8 (v0, cq);
268 q1 = _mm_cmpeq_epi8 (v1, cq);
269 x0 = _mm_cmpeq_epi8 (v0, cx);
270 x1 = _mm_cmpeq_epi8 (v1, cx);
271 s0 = _mm_movemask_epi8 (q0);
272 s1 = _mm_movemask_epi8 (q1);
273 t0 = _mm_movemask_epi8 (x0);
274 t1 = _mm_movemask_epi8 (x1);
275 m0 = ((uint64_t)s1 << 16) | (uint64_t)s0;
276 m1 = ((uint64_t)t1 << 16) | (uint64_t)t0;
277#endif
278
279 /** update first quote position */
280 if (unlikely(m1 != 0)) {
281 ep_setx(sp - ss + __builtin_ctzll(m1))
282 }
283
284 /** mask all the escaped quotes */
285 if (unlikely(m1 != 0 || cr != 0)) {
286 m0_mask(add32)
287 }
288
289 /* check for end quote */
290 if (m0 != 0) {
291 return sp - ss + __builtin_ctzll(m0) + 1;
292 }
293
294 /* move to the next block */
295 sp += 32;
296 nb -= 32;
297 }
298
299 /* check for carry */
300 if (unlikely(cr != 0)) {
301 if (nb == 0) {
302 return -ERR_EOF;
303 } else {
304 ep_setc()
305 sp++, nb--;
306 }
307 }
308
309 /* handle the remaining bytes with scalar code */
310 while (nb-- > 0 && (ch = *sp++) != '"') {
311 if (unlikely(ch == '\\')) {
312 if (nb == 0) {
313 return -ERR_EOF;
314 } else {
315 ep_setc()
316 sp++, nb--;
317 }
318 }
319 }
320
321#undef ep_init
322#undef ep_setc
323#undef ep_setx
324#undef m0_mask
325
326 /* check for quotes */
327 if (ch == '"') {
328 return sp - ss;
329 } else {
330 return -ERR_EOF;
331 }
332}
333
334#if USE_AVX2
335
336static inline int _mm256_get_mask(__m256i v, __m256i t) {
337 return _mm256_movemask_epi8(_mm256_cmpeq_epi8(v, t));
338}
339
340// contrl char: 0x00 ~ 0x1F
341static inline int _mm256_cchars_mask(__m256i v) {
342 __m256i e1 = _mm256_cmpgt_epi8 (v, _mm256_set1_epi8(-1));
343 __m256i e2 = _mm256_cmpgt_epi8 (v, _mm256_set1_epi8(31));
344 return _mm256_movemask_epi8 (_mm256_andnot_si256 (e2, e1));
345}
346
347// ascii: 0x00 ~ 0x7F
348static inline int _mm256_nonascii_mask(__m256i v) {
349 return _mm256_movemask_epi8(v);
350}
351
352#endif
353
354static inline int _mm_get_mask(__m128i v, __m128i t) {
355 return _mm_movemask_epi8(_mm_cmpeq_epi8(v, t));
356}
357
358// contrl char: 0x00 ~ 0x1F
359static inline int _mm_cchars_mask(__m128i v) {
360 __m128i e1 = _mm_cmpgt_epi8 (v, _mm_set1_epi8(-1));
361 __m128i e2 = _mm_cmpgt_epi8 (v, _mm_set1_epi8(31));
362 return _mm_movemask_epi8 (_mm_andnot_si128 (e2, e1));
363}
364
365// ascii: 0x00 ~ 0x7F
366static inline int _mm_nonascii_mask(__m128i v) {
367 return _mm_movemask_epi8(v);
368}
369
370static inline ssize_t advance_string_validate(const GoString *src, long p, int64_t *ep) {
371 char ch;
372 uint64_t m0, m1, m2;
373 uint64_t es, fe, os;
374 uint64_t cr = 0;
375 long qp = 0;
376 long np = 0;
377
378 /* buffer pointers */
379 size_t nb = src->len;
380 const char * sp = src->buf;
381 const char * ss = src->buf;
382
383 /* prevent out-of-bounds accessing */
384 if (unlikely(nb == p)) {
385 return -ERR_EOF;
386 }
387
388#define ep_init() *ep = -1;
389#define ep_setc() ep_setx(sp - ss - 1)
390#define ep_setx(x) if (*ep == -1) { *ep = (x); }
391#define ep_seterr(x) *ep = (x);
392
393 /* seek to `p` */
394 nb -= p;
395 sp += p;
396 ep_init()
397
398#if USE_AVX2
399 /* initialize vectors */
400 __m256i v0;
401 __m256i v1;
402 __m256i cq = _mm256_set1_epi8('"');
403 __m256i cx = _mm256_set1_epi8('\\');
404
405 /* partial masks */
406 uint32_t s0, s1;
407 uint32_t t0, t1;
408 uint32_t c0, c1;
409#else
410 /* initialize vectors */
411 __m128i v0;
412 __m128i v1;
413 __m128i v2;
414 __m128i v3;
415 __m128i cq = _mm_set1_epi8('"');
416 __m128i cx = _mm_set1_epi8('\\');
417
418 /* partial masks */
419 uint32_t s0, s1, s2, s3;
420 uint32_t t0, t1, t2, t3;
421 uint32_t c0, c1, c2, c3;
422#endif
423
424#define m0_mask(add) \
425 m1 &= ~cr; \
426 fe = (m1 << 1) | cr; \
427 os = (m1 & ~fe) & ODD_MASK; \
428 es = add(os, m1, &cr) << 1; \
429 m0 &= ~(fe & (es ^ EVEN_MASK));
430
431 /* 64-byte SIMD loop */
432 while (likely(nb >= 64)) {
433#if USE_AVX2
434 v0 = _mm256_loadu_si256 ((const void *)(sp + 0));
435 v1 = _mm256_loadu_si256 ((const void *)(sp + 32));
436 s0 = _mm256_get_mask(v0, cq);
437 s1 = _mm256_get_mask(v1, cq);
438 t0 = _mm256_get_mask(v0, cx);
439 t1 = _mm256_get_mask(v1, cx);
440 c0 = _mm256_cchars_mask(v0);
441 c1 = _mm256_cchars_mask(v1);
442 m0 = ((uint64_t)s1 << 32) | (uint64_t)s0;
443 m1 = ((uint64_t)t1 << 32) | (uint64_t)t0;
444 m2 = ((uint64_t)c1 << 32) | (uint64_t)c0;
445#else
446 v0 = _mm_loadu_si128 ((const void *)(sp + 0));
447 v1 = _mm_loadu_si128 ((const void *)(sp + 16));
448 v2 = _mm_loadu_si128 ((const void *)(sp + 32));
449 v3 = _mm_loadu_si128 ((const void *)(sp + 48));
450 s0 = _mm_get_mask(v0, cq);
451 s1 = _mm_get_mask(v1, cq);
452 s2 = _mm_get_mask(v2, cq);
453 s3 = _mm_get_mask(v3, cq);
454 t0 = _mm_get_mask(v0, cx);
455 t1 = _mm_get_mask(v1, cx);
456 t2 = _mm_get_mask(v2, cx);
457 t3 = _mm_get_mask(v3, cx);
458 c0 = _mm_cchars_mask(v0);
459 c1 = _mm_cchars_mask(v1);
460 c2 = _mm_cchars_mask(v2);
461 c3 = _mm_cchars_mask(v3);
462 m0 = ((uint64_t)s3 << 48) | ((uint64_t)s2 << 32) | ((uint64_t)s1 << 16) | (uint64_t)s0;
463 m1 = ((uint64_t)t3 << 48) | ((uint64_t)t2 << 32) | ((uint64_t)t1 << 16) | (uint64_t)t0;
464 m2 = ((uint64_t)c3 << 48) | ((uint64_t)c2 << 32) | ((uint64_t)c1 << 16) | (uint64_t)c0;
465
466#endif
467
468 /** update first quote position */
469 if (unlikely(m1 != 0)) {
470 ep_setx(sp - ss + __builtin_ctzll(m1))
471 }
472
473 /** mask all the escaped quotes */
474 if (unlikely(m1 != 0 || cr != 0)) {
475 m0_mask(add64)
476 }
477
478 qp = m0 ? __builtin_ctzll(m0) : 64;
479 np = m2 ? __builtin_ctzll(m2) : 64;
480
481 /* get the position of end quote */
482 if (m0 != 0) {
483 /* check control chars in JSON string */
484 if (unlikely(np < qp)) {
485 ep_seterr(sp - ss + np)
486
487 return -ERR_INVAL;
488 }
489 return sp - ss + qp + 1;
490 }
491
492 /* check control chars in JSON string */
493 if (unlikely(m2 != 0)) {
494 ep_setx(sp - ss + np)
495
496 return -ERR_INVAL;
497 }
498
499 /* move to the next block */
500 sp += 64;
501 nb -= 64;
502 }
503
504 /* 32-byte SIMD round */
505 if (likely(nb >= 32)) {
506#if USE_AVX2
507 v0 = _mm256_loadu_si256 ((const void *)sp);
508 s0 = _mm256_get_mask (v0, cq);
509 t0 = _mm256_get_mask (v0, cx);
510 c0 = _mm256_cchars_mask(v0);
511 m0 = (uint64_t)s0;
512 m1 = (uint64_t)t0;
513 m2 = (uint64_t)c0;
514#else
515 v0 = _mm_loadu_si128 ((const void *)(sp + 0));
516 v1 = _mm_loadu_si128 ((const void *)(sp + 16));
517 s0 = _mm_get_mask(v0, cq);
518 s1 = _mm_get_mask(v1, cq);
519 t0 = _mm_get_mask(v0, cx);
520 t1 = _mm_get_mask(v1, cx);
521 c0 = _mm_cchars_mask(v0);
522 c1 = _mm_cchars_mask(v1);
523 m0 = ((uint64_t)s1 << 16) | (uint64_t)s0;
524 m1 = ((uint64_t)t1 << 16) | (uint64_t)t0;
525 m2 = ((uint64_t)c1 << 16) | (uint64_t)c0;
526#endif
527
528 /** update first quote position */
529 if (unlikely(m1 != 0)) {
530 ep_setx(sp - ss + __builtin_ctzll(m1))
531 }
532
533 /** mask all the escaped quotes */
534 if (unlikely(m1 != 0 || cr != 0)) {
535 m0_mask(add32)
536 }
537
538 qp = m0 ? __builtin_ctzll(m0) : 64;
539 np = m2 ? __builtin_ctzll(m2) : 64;
540
541 /* get the position of end quote */
542 if (m0 != 0) {
543 if (unlikely(np < qp)) {
544 ep_seterr(sp - ss + np)
545 return -ERR_INVAL;
546 }
547 return sp - ss + qp + 1;
548 }
549
550 /* check control chars in JSON string */
551 if (unlikely(m2 != 0)) {
552 ep_seterr(sp - ss + __builtin_ctzll(m2))
553 return -ERR_INVAL;
554 }
555
556 /* move to the next block */
557 sp += 32;
558 nb -= 32;
559 }
560
561 /* check for carry */
562 if (unlikely(cr != 0)) {
563 if (nb == 0) {
564 return -ERR_EOF;
565 } else {
566 ep_setc()
567 sp++, nb--;
568 }
569 }
570
571 /* handle the remaining bytes with scalar code */
572 while (nb > 0) {
573 ch = *sp;
574 if (ch == '"') {
575
576 return sp - ss + 1;
577 }
578
579 /* valid the escaped chars */
580 if (unlikely(ch == '\\')) {
581 if (nb == 1) {
582 return -ERR_EOF;
583 }
584 ep_setx(sp - ss)
585 sp += 2, nb -= 2;
586 continue;
587 }
588
589 /* valid unescaped chars */
590 if (unlikely( ch >= 0 && ch <= 0x1f)) { // control chars
591 ep_seterr(sp - ss)
592 return -ERR_INVAL;
593 }
594
595 sp++, nb--;
596 }
597 return -ERR_EOF;
598#undef ep_init
599#undef ep_setc
600#undef ep_setx
601#undef ep_seterr
602#undef m0_mask
603}
604
605static inline ssize_t advance_string(const GoString *src, long p, int64_t *ep, uint64_t flags) {
606 if ((flags & MASK_VALIDATE_STRING) != 0) {
607 return advance_string_validate(src, p, ep);
608 } else {
609 return advance_string_default(src, p, ep);
610 }
611}
612
613/** Value Scanning Routines **/
614
615long value(const char *s, size_t n, long p, JsonState *ret, uint64_t flags) {
616 long q = p;
617 GoString m = {.buf = s, .len = n};
618 bool allow_control = (flags & MASK_ALLOW_CONTROL) != 0;
619 /* parse the next identifier, q is UNSAFE, may cause out-of-bounds accessing */
620 switch (advance_ns(&m, &q)) {
621 case '-' : /* fallthrough */
622 case '0' : /* fallthrough */
623 case '1' : /* fallthrough */
624 case '2' : /* fallthrough */
625 case '3' : /* fallthrough */
626 case '4' : /* fallthrough */
627 case '5' : /* fallthrough */
628 case '6' : /* fallthrough */
629 case '7' : /* fallthrough */
630 case '8' : /* fallthrough */
631 case '9' : vdigits(&m, &q, ret, flags) ; return q;
632 case '"' : vstring(&m, &q, ret, flags) ; return q;
633 case 'n' : ret->vt = advance_dword(&m, &q, 1, V_NULL, VS_NULL) ; return q;
634 case 't' : ret->vt = advance_dword(&m, &q, 1, V_TRUE, VS_TRUE) ; return q;
635 case 'f' : ret->vt = advance_dword(&m, &q, 0, V_FALSE, VS_ALSE) ; return q;
636 case '[' : ret->vt = V_ARRAY ; return q;
637 case '{' : ret->vt = V_OBJECT ; return q;
638 case ':' : ret->vt = allow_control ? V_KEY_SEP : -ERR_INVAL ; return allow_control ? q : q - 1;
639 case ',' : ret->vt = allow_control ? V_ELEM_SEP : -ERR_INVAL ; return allow_control ? q : q - 1;
640 case ']' : ret->vt = allow_control ? V_ARRAY_END : -ERR_INVAL ; return allow_control ? q : q - 1;
641 case '}' : ret->vt = allow_control ? V_OBJECT_END : -ERR_INVAL ; return allow_control ? q : q - 1;
642 case 0 : ret->vt = V_EOF ; return q;
643 default : ret->vt = -ERR_INVAL ; return q - 1;
644 }
645}
646
647void vstring(const GoString *src, long *p, JsonState *ret, uint64_t flags) {
648 int64_t v = -1;
649 int64_t i = *p;
650 ssize_t e = advance_string(src, i, &v, flags);
651
652 /* check for errors */
653 if (e < 0) {
654 *p = src->len;
655 ret->vt = e;
656 return;
657 }
658
659 /* update the result, and fix the escape position (escaping past the end of string) */
660 *p = e;
661 ret->iv = i;
662 ret->vt = V_STRING;
663 ret->ep = v >= e ? -1 : v;
664}
665
666#define set_vt(t) \
667 ret->vt = t;
668
669#define init_ret(t) \
670 ret->vt = t; \
671 ret->dv = 0.0; \
672 ret->iv = 0; \
673 ret->ep = *p;
674
675#define check_eof() \
676 if (i >= n) { \
677 *p = n; \
678 ret->vt = -ERR_EOF; \
679 return; \
680 }
681
682#define check_sign(on_neg) \
683 if (s[i] == '-') { \
684 i++; \
685 on_neg; \
686 check_eof() \
687 }
688
689#define check_digit() \
690 if (s[i] < '0' || s[i] > '9') { \
691 *p = i; \
692 ret->vt = -ERR_INVAL; \
693 return; \
694 }
695
696#define check_leading_zero() \
697 if (s[i] == '0' && (i >= n || (s[i + 1] != '.' && s[i + 1] != 'e' && s[i + 1] != 'E'))) { \
698 *p = ++i; \
699 return; \
700 }
701
702#define parse_sign(sgn) \
703 if (s[i] == '+' || s[i] == '-') { \
704 sgn = s[i++] == '+' ? 1 : -1; \
705 check_eof() \
706 }
707
708#define is_digit(val) \
709 '0' <= val && val <= '9'
710
711#define add_integer_to_mantissa(man, man_nd, exp10, dig) \
712 if (man_nd < 19) { \
713 man = man * 10 + dig; \
714 man_nd++; \
715 } else { \
716 exp10++; \
717 }
718
719#define add_float_to_mantissa(man, man_nd, exp10, dig) \
720 man = man * 10 + dig; \
721 man_nd++; \
722 exp10--;
723
724#define parse_float_digits(val, sgn, ...) \
725 while (i < n && s[i] >= '0' && s[i] <= '9' __VA_ARGS__) { \
726 val *= 10; \
727 val += sgn * (s[i++] - '0'); \
728 }
729
730#define parse_integer_digits(val, sgn, ovf) \
731 while (i < n && s[i] >= '0' && s[i] <= '9') { \
732 if (add_digit_overflow(val, sgn * (s[i++] - '0'))) { \
733 ovf = 1; \
734 break; \
735 } \
736 }
737
738#define add_digit_overflow(val, chr) ( \
739 __builtin_mul_overflow(val, 10, &val) || \
740 __builtin_add_overflow(val, chr, &val) \
741)
742
743#define vinteger(type, sgn, on_neg) \
744 int ovf = 0; \
745 type val = 0; \
746 \
747 /* initial buffer pointers */ \
748 long i = *p; \
749 size_t n = src->len; \
750 const char * s = src->buf; \
751 \
752 /* initialize the result, and check for '-' */ \
753 init_ret(V_INTEGER) \
754 check_eof() \
755 check_sign(on_neg) \
756 \
757 /* check for leading zero or any digits */ \
758 check_digit() \
759 check_leading_zero() \
760 parse_integer_digits(val, sgn, ovf) \
761 \
762 /* check for overflow */ \
763 if (ovf) { \
764 *p = i - 1; \
765 ret->vt = -ERR_OVERFLOW; \
766 return; \
767 } \
768 \
769 /* check for the decimal part */ \
770 if (i < n && s[i] == '.') { \
771 *p = i; \
772 ret->vt = -ERR_NUMBER_FMT; \
773 return; \
774 } \
775 \
776 /* check for the exponent part */ \
777 if (i < n && (s[i] == 'e' || s[i] == 'E')) { \
778 *p = i; \
779 ret->vt = -ERR_NUMBER_FMT; \
780 return; \
781 } \
782 \
783 /* update the result */ \
784 *p = i; \
785 ret->iv = val;
786
787/** check whether float can represent the val exactly **/
788static inline bool is_atof_exact(uint64_t man, int exp, int sgn, double *val) {
789 *val = (double)man;
790
791 if (man >> 52 != 0) {
792 return false;
793 }
794
795 /* equal to if (sgn == -1) { *val *= -1; } */
796 *(uint64_t *)val |= ((uint64_t)(sgn) >> 63 << 63);
797
798 if (exp == 0 || man == 0) {
799 return true;
800 } else if (exp > 0 && exp <= 15+22) {
801 /* uint64 integers: accurate range <= 10^15 *
802 * Powers of 10: accurate range <= 10^22, as P10_TAB *
803 * Example: man 1, exp 36, is ok */
804 if (exp > 22) {
805 *val *= P10_TAB[exp-22];
806 exp = 22;
807 }
808
809 /* f is not accurate when too larger */
810 if (*val > 1e15 || *val < -1e15) {
811 return false;
812 }
813
814 *val *= P10_TAB[exp];
815 return true;
816 } else if (exp < 0 && exp >= -22) {
817 *val /= P10_TAB[-exp];
818 return true;
819 }
820
821 return false;
822}
823
824static inline double atof_fast(uint64_t man, int exp, int sgn, int trunc, double *val) {
825 double val_up = 0.0;
826
827 /* look-up for fast atof if the conversion can be exactly */
828 if (is_atof_exact(man, exp, sgn, val)) {
829 return true;
830 }
831
832 /* A fast atof algorithm for high percison */
833 if (atof_eisel_lemire64(man, exp, sgn, val)) {
834 if (!trunc || (atof_eisel_lemire64(man+1, exp, sgn, &val_up) && val_up == *val)) {
835 return true;
836 }
837 }
838
839 return false;
840}
841
842static bool inline is_overflow(uint64_t man, int sgn, int exp10) {
843 /* the former exp10 != 0 means man has overflowed
844 * the later euqals to man*sgn < INT64_MIN or > INT64_MAX */
845 return exp10 != 0 ||
846 ((man >> 63) == 1 && ((uint64_t)sgn & man) != (1ull << 63));
847}
848
849void vnumber(const GoString *src, long *p, JsonState *ret) {
850 int sgn = 1;
851 uint64_t man = 0; // mantissa for double (float64)
852 int man_nd = 0; // # digits of mantissa, 10 ^ 19 fits uint64_t
853 int exp10 = 0; // val = sgn * man * 10 ^ exp10
854 int trunc = 0;
855 double val = 0;
856
857 /* initial buffer pointers */
858 long i = *p;
859 size_t n = src->len;
860 const char * s = src->buf;
861 char *dbuf = ret->dbuf;
862 ssize_t dcap = ret->dcap;
863
864 /* initialize the result, and check for EOF */
865 init_ret(V_INTEGER)
866 check_eof()
867 check_sign(sgn = -1)
868
869 /* check for leading zero */
870 check_digit()
871 check_leading_zero()
872
873 /* parse the integer part */
874 while (i < n && is_digit(s[i])) {
875 add_integer_to_mantissa(man, man_nd, exp10, (s[i] - '0'))
876 i++;
877 }
878
879 if (exp10 > 0) {
880 trunc = 1;
881 }
882
883 /* check for decimal points */
884 if (i < n && s[i] == '.') {
885 i++;
886 set_vt(V_DOUBLE)
887 check_eof()
888 check_digit()
889 }
890
891 /* skip the leading zeros of 0.000xxxx */
892 if (man == 0 && exp10 == 0) {
893 while (i < n && s[i] == '0') {
894 i++;
895 exp10--;
896 }
897 man = 0;
898 man_nd = 0;
899 }
900
901 /* the fractional part (uint64_t mantissa can represent at most 19 digits) */
902 while (i < n && man_nd < 19 && is_digit(s[i])) {
903 add_float_to_mantissa(man, man_nd, exp10, (s[i] - '0'))
904 i++;
905 }
906
907 /* skip the remaining digits */
908 while (i < n && is_digit(s[i])) {
909 trunc = 1;
910 i++;
911 }
912
913 /* check for exponent */
914 if (i < n && (s[i] == 'e' || s[i] == 'E')) {
915 int esm = 1;
916 int exp = 0;
917
918 /* check for the '+' or '-' sign, and parse the power */
919 i++;
920 set_vt(V_DOUBLE)
921 check_eof()
922 parse_sign(esm)
923 check_digit()
924 while (i < n && is_digit(s[i])) {
925 if (exp < 10000) {
926 exp = exp * 10 + (s[i] - '0');
927 }
928 i++;
929 }
930 exp10 += exp * esm;
931 goto parse_float;
932 }
933
934 if (ret->vt == V_INTEGER) {
935 if (!is_overflow(man, sgn, exp10)) {
936 ret->iv = (int64_t)man * sgn;
937
938 /* following lines equal to ret->dv = (double)(man) * sgn */
939 ret->dv = (double)(man);
940 *(uint64_t *)&ret->dv |= ((uint64_t)(sgn) >> 63 << 63);
941
942 *p = i;
943 return;
944 }
945 set_vt(V_DOUBLE)
946 }
947
948parse_float:
949 /* when fast algorithms failed, use slow fallback.*/
950 if(!atof_fast(man, exp10, sgn, trunc, &val)) {
951 val = atof_native(s + *p, i - *p, dbuf, dcap);
952 }
953
954 /* check parsed double val */
955 if (is_infinity(val)) {
956 ret->vt = -ERR_FLOAT_INF;
957 }
958
959 /* update the result */
960 ret->dv = val;
961 *p = i;
962}
963
964void vsigned(const GoString *src, long *p, JsonState *ret) {
965 int64_t sgn = 1;
966 vinteger(int64_t, sgn, sgn = -1)
967}
968
969void vunsigned(const GoString *src, long *p, JsonState *ret) {
970 vinteger(uint64_t, 1, {
971 *p = i - 1;
972 ret->vt = -ERR_NUMBER_FMT;
973 return;
974 })
975}
976
977#undef init_ret
978#undef check_eof
979#undef check_digit
980#undef check_leading_zero
981#undef parse_sign
982#undef is_digit
983#undef add_integer_to_mantissa
984#undef add_float_to_mantissa
985#undef parse_float_digits
986#undef parse_integer_digits
987#undef add_digit_overflow
988#undef vinteger
989
990/** Value Skipping FSM **/
991
992#define FSM_VAL 0
993#define FSM_ARR 1
994#define FSM_OBJ 2
995#define FSM_KEY 3
996#define FSM_ELEM 4
997#define FSM_ARR_0 5
998#define FSM_OBJ_0 6
999
1000#define FSM_DROP(v) (v)->sp--
1001#define FSM_REPL(v, t) (v)->vt[(v)->sp - 1] = (t)
1002
1003#define FSM_CHAR(c) do { if (ch != (c)) return -ERR_INVAL; } while (0)
1004#define FSM_XERR(v) do { long r = (v); if (r < 0) return r; } while (0)
1005
1006static inline void fsm_init(StateMachine *self, int vt) {
1007 self->sp = 1;
1008 self->vt[0] = vt;
1009}
1010
1011static inline long fsm_push(StateMachine *self, int vt) {
1012 if (self->sp >= MAX_RECURSE) {
1013 return -ERR_RECURSE_MAX;
1014 } else {
1015 self->vt[self->sp++] = vt;
1016 return 0;
1017 }
1018}
1019
1020static inline long fsm_exec(StateMachine *self, const GoString *src, long *p, uint64_t flags) {
1021 int vt;
1022 char ch;
1023 long vi = -1;
1024
1025 /* run until no more nested values */
1026 while (self->sp) {
1027 ch = advance_ns(src, p);
1028 if (ch == 0) {
1029 return -ERR_EOF;
1030 }
1031 vt = self->vt[self->sp - 1];
1032
1033 /* set the start address if any */
1034 if (vi == -1) {
1035 vi = *p - 1;
1036 }
1037
1038 /* check for special types */
1039 switch (vt) {
1040 default: {
1041 FSM_DROP(self);
1042 break;
1043 }
1044
1045 /* arrays */
1046 case FSM_ARR: {
1047 switch (ch) {
1048 case ']' : FSM_DROP(self); continue;
1049 case ',' : FSM_XERR(fsm_push(self, FSM_VAL)); continue;
1050 default : return -ERR_INVAL;
1051 }
1052 }
1053
1054 /* objects */
1055 case FSM_OBJ: {
1056 switch (ch) {
1057 case '}' : FSM_DROP(self); continue;
1058 case ',' : FSM_XERR(fsm_push(self, FSM_KEY)); continue;
1059 default : return -ERR_INVAL;
1060 }
1061 }
1062
1063 /* object keys */
1064 case FSM_KEY: {
1065 FSM_CHAR('"');
1066 FSM_REPL(self, FSM_ELEM);
1067 FSM_XERR(skip_string(src, p, flags));
1068 continue;
1069 }
1070
1071 /* object element */
1072 case FSM_ELEM: {
1073 FSM_CHAR(':');
1074 FSM_REPL(self, FSM_VAL);
1075 continue;
1076 }
1077
1078 /* arrays, first element */
1079 case FSM_ARR_0: {
1080 if (ch == ']') {
1081 FSM_DROP(self);
1082 continue;
1083 } else {
1084 FSM_REPL(self, FSM_ARR);
1085 break;
1086 }
1087 }
1088
1089 /* objects, first pair */
1090 case FSM_OBJ_0: {
1091 switch (ch) {
1092 default: {
1093 return -ERR_INVAL;
1094 }
1095
1096 /* empty object */
1097 case '}': {
1098 FSM_DROP(self);
1099 continue;
1100 }
1101
1102 /* the quote of the first key */
1103 case '"': {
1104 FSM_REPL(self, FSM_OBJ);
1105 FSM_XERR(skip_string(src, p, flags));
1106 FSM_XERR(fsm_push(self, FSM_ELEM));
1107 continue;
1108 }
1109 }
1110 }
1111 }
1112
1113 /* simple values */
1114 switch (ch) {
1115 case '0' : /* fallthrough */
1116 case '1' : /* fallthrough */
1117 case '2' : /* fallthrough */
1118 case '3' : /* fallthrough */
1119 case '4' : /* fallthrough */
1120 case '5' : /* fallthrough */
1121 case '6' : /* fallthrough */
1122 case '7' : /* fallthrough */
1123 case '8' : /* fallthrough */
1124 case '9' : FSM_XERR(skip_positive(src, p)); break;
1125 case '-' : FSM_XERR(skip_negative(src, p)); break;
1126 case 'n' : FSM_XERR(advance_dword(src, p, 1, *p - 1, VS_NULL)); break;
1127 case 't' : FSM_XERR(advance_dword(src, p, 1, *p - 1, VS_TRUE)); break;
1128 case 'f' : FSM_XERR(advance_dword(src, p, 0, *p - 1, VS_ALSE)); break;
1129 case '[' : FSM_XERR(fsm_push(self, FSM_ARR_0)); break;
1130 case '{' : FSM_XERR(fsm_push(self, FSM_OBJ_0)); break;
1131 case '"' : FSM_XERR(skip_string(src, p, flags)); break;
1132 case 0 : return -ERR_EOF;
1133 default : return -ERR_INVAL;
1134 }
1135 }
1136
1137 /* all done */
1138 return vi;
1139}
1140
1141#undef FSM_DROP
1142#undef FSM_REPL
1143#undef FSM_CHAR
1144#undef FSM_XERR
1145
1146#define check_bits(mv) \
1147 if (unlikely((v = mv & (mv - 1)) != 0)) { \
1148 return -(sp - ss + __builtin_ctz(v) + 1); \
1149 }
1150
1151#define check_sidx(iv) \
1152 if (likely(iv == -1)) { \
1153 iv = sp - ss - 1; \
1154 } else { \
1155 return -(sp - ss); \
1156 }
1157
1158#define check_vidx(iv, mv) \
1159 if (mv != 0) { \
1160 if (likely(iv == -1)) { \
1161 iv = sp - ss + __builtin_ctz(mv); \
1162 } else { \
1163 return -(sp - ss + __builtin_ctz(mv) + 1); \
1164 } \
1165 }
1166
1167static inline long do_skip_number(const char *sp, size_t nb) {
1168 long di = -1;
1169 long ei = -1;
1170 long si = -1;
1171 const char * ss = sp;
1172
1173 /* check for EOF */
1174 if (nb == 0) {
1175 return -1;
1176 }
1177
1178 /* special case of '0' */
1179 if (*sp == '0' && (nb == 1 || (sp[1] != '.' && sp[1] != 'e' && sp[1] != 'E'))) {
1180 return 1;
1181 }
1182
1183#if USE_AVX2
1184 /* can do with AVX-2 */
1185 if (likely(nb >= 32)) {
1186 __m256i d9 = _mm256_set1_epi8('9');
1187 __m256i ds = _mm256_set1_epi8('/');
1188 __m256i dp = _mm256_set1_epi8('.');
1189 __m256i el = _mm256_set1_epi8('e');
1190 __m256i eu = _mm256_set1_epi8('E');
1191 __m256i xp = _mm256_set1_epi8('+');
1192 __m256i xm = _mm256_set1_epi8('-');
1193
1194 /* 32-byte loop */
1195 do {
1196 __m256i sb = _mm256_loadu_si256 ((const void *)sp);
1197 __m256i i0 = _mm256_cmpgt_epi8 (sb, ds);
1198 __m256i i9 = _mm256_cmpgt_epi8 (sb, d9);
1199 __m256i id = _mm256_cmpeq_epi8 (sb, dp);
1200 __m256i il = _mm256_cmpeq_epi8 (sb, el);
1201 __m256i iu = _mm256_cmpeq_epi8 (sb, eu);
1202 __m256i ip = _mm256_cmpeq_epi8 (sb, xp);
1203 __m256i im = _mm256_cmpeq_epi8 (sb, xm);
1204 __m256i iv = _mm256_andnot_si256 (i9, i0);
1205 __m256i ie = _mm256_or_si256 (il, iu);
1206 __m256i is = _mm256_or_si256 (ip, im);
1207 __m256i rt = _mm256_or_si256 (iv, id);
1208 __m256i ru = _mm256_or_si256 (ie, is);
1209 __m256i rv = _mm256_or_si256 (rt, ru);
1210
1211 /* exponent and sign position */
1212 uint32_t md = _mm256_movemask_epi8(id);
1213 uint32_t me = _mm256_movemask_epi8(ie);
1214 uint32_t ms = _mm256_movemask_epi8(is);
1215 uint32_t mr = _mm256_movemask_epi8(rv);
1216
1217 /* mismatch position */
1218 uint32_t v;
1219 uint32_t i = __builtin_ctzll(~(uint64_t)mr | 0x0100000000);
1220
1221 /* mask out excess characters */
1222 if (i != 32) {
1223 md &= (1 << i) - 1;
1224 me &= (1 << i) - 1;
1225 ms &= (1 << i) - 1;
1226 }
1227
1228 /* check & update decimal point, exponent and sign index */
1229 check_bits(md)
1230 check_bits(me)
1231 check_bits(ms)
1232 check_vidx(di, md)
1233 check_vidx(ei, me)
1234 check_vidx(si, ms)
1235
1236 /* check for valid number */
1237 if (i != 32) {
1238 sp += i;
1239 _mm256_zeroupper();
1240 goto check_index;
1241 }
1242
1243 /* move to next block */
1244 sp += 32;
1245 nb -= 32;
1246 } while (nb >= 32);
1247
1248 /* clear the upper half to prevent AVX-SSE transition penalty */
1249 _mm256_zeroupper();
1250 }
1251#endif
1252
1253 /* can do with SSE */
1254 if (likely(nb >= 16)) {
1255 __m128i dc = _mm_set1_epi8(':');
1256 __m128i ds = _mm_set1_epi8('/');
1257 __m128i dp = _mm_set1_epi8('.');
1258 __m128i el = _mm_set1_epi8('e');
1259 __m128i eu = _mm_set1_epi8('E');
1260 __m128i xp = _mm_set1_epi8('+');
1261 __m128i xm = _mm_set1_epi8('-');
1262
1263 /* 16-byte loop */
1264 do {
1265 __m128i sb = _mm_loadu_si128 ((const void *)sp);
1266 __m128i i0 = _mm_cmpgt_epi8 (sb, ds);
1267 __m128i i9 = _mm_cmplt_epi8 (sb, dc);
1268 __m128i id = _mm_cmpeq_epi8 (sb, dp);
1269 __m128i il = _mm_cmpeq_epi8 (sb, el);
1270 __m128i iu = _mm_cmpeq_epi8 (sb, eu);
1271 __m128i ip = _mm_cmpeq_epi8 (sb, xp);
1272 __m128i im = _mm_cmpeq_epi8 (sb, xm);
1273 __m128i iv = _mm_and_si128 (i9, i0);
1274 __m128i ie = _mm_or_si128 (il, iu);
1275 __m128i is = _mm_or_si128 (ip, im);
1276 __m128i rt = _mm_or_si128 (iv, id);
1277 __m128i ru = _mm_or_si128 (ie, is);
1278 __m128i rv = _mm_or_si128 (rt, ru);
1279
1280 /* exponent and sign position */
1281 uint32_t md = _mm_movemask_epi8(id);
1282 uint32_t me = _mm_movemask_epi8(ie);
1283 uint32_t ms = _mm_movemask_epi8(is);
1284 uint32_t mr = _mm_movemask_epi8(rv);
1285
1286 /* mismatch position */
1287 uint32_t v;
1288 uint32_t i = __builtin_ctzll(~mr | 0x00010000);
1289
1290 /* mask out excess characters */
1291 if (i != 16) {
1292 md &= (1 << i) - 1;
1293 me &= (1 << i) - 1;
1294 ms &= (1 << i) - 1;
1295 }
1296
1297 /* check & update exponent and sign index */
1298 check_bits(md)
1299 check_bits(me)
1300 check_bits(ms)
1301 check_vidx(di, md)
1302 check_vidx(ei, me)
1303 check_vidx(si, ms)
1304
1305 /* check for valid number */
1306 if (i != 16) {
1307 sp += i;
1308 goto check_index;
1309 }
1310
1311 /* move to next block */
1312 sp += 16;
1313 nb -= 16;
1314 } while (nb >= 16);
1315 }
1316
1317 /* remaining bytes, do with scalar code */
1318 while (likely(nb-- > 0)) {
1319 switch (*sp++) {
1320 case '0' : /* fallthrough */
1321 case '1' : /* fallthrough */
1322 case '2' : /* fallthrough */
1323 case '3' : /* fallthrough */
1324 case '4' : /* fallthrough */
1325 case '5' : /* fallthrough */
1326 case '6' : /* fallthrough */
1327 case '7' : /* fallthrough */
1328 case '8' : /* fallthrough */
1329 case '9' : break;
1330 case '.' : check_sidx(di); break;
1331 case 'e' : /* fallthrough */
1332 case 'E' : check_sidx(ei); break;
1333 case '+' : /* fallthrough */
1334 case '-' : check_sidx(si); break;
1335 default : sp--; goto check_index;
1336 }
1337 }
1338check_index:
1339 if (di == 0 || si == 0 || ei == 0) {
1340 return -1;
1341 } else if (di == sp - ss - 1|| si == sp - ss - 1 || ei == sp - ss - 1) {
1342 return -(sp - ss);
1343 } else if (si > 0 && ei != si - 1) {
1344 return -si - 1;
1345 } else if (di >= 0 && ei >= 0 && di > ei - 1) {
1346 return -di - 1;
1347 } else if (di >= 0 && ei >= 0 && di == ei - 1) {
1348 return -ei - 1;
1349 } else {
1350 return sp - ss;
1351 }
1352}
1353
1354#undef check_bits
1355#undef check_sidx
1356#undef check_vidx
1357
1358long skip_array(const GoString *src, long *p, StateMachine *m, uint64_t flags) {
1359 fsm_init(m, FSM_ARR_0);
1360 return fsm_exec(m, src, p, flags);
1361}
1362
1363long skip_object(const GoString *src, long *p, StateMachine *m, uint64_t flags) {
1364 fsm_init(m, FSM_OBJ_0);
1365 return fsm_exec(m, src, p, flags);
1366}
1367
1368long skip_string(const GoString *src, long *p, uint64_t flags) {
1369 int64_t v = -1;
1370 ssize_t q = *p - 1; // start position
1371 ssize_t e = advance_string(src, *p, &v, flags);
1372
1373 /* check for errors */
1374 if (e < 0) {
1375 *p = e == -ERR_EOF ? src->len : v;
1376 return e;
1377 }
1378
1379 /* update the position */
1380 *p = e;
1381 return q;
1382}
1383
1384long skip_negative(const GoString *src, long *p) {
1385 long i = *p;
1386 long r = do_skip_number(src->buf + i, src->len - i);
1387
1388 /* check for errors */
1389 if (r < 0) {
1390 *p -= r + 1;
1391 return -ERR_INVAL;
1392 }
1393
1394 /* update value pointer */
1395 *p += r;
1396 return i - 1;
1397}
1398
1399long skip_positive(const GoString *src, long *p) {
1400 long i = *p - 1;
1401 long r = do_skip_number(src->buf + i, src->len - i);
1402
1403 /* check for errors */
1404 if (r < 0) {
1405 *p -= r + 2;
1406 return -ERR_INVAL;
1407 }
1408
1409 /* update value pointer */
1410 *p += r - 1;
1411 return i;
1412}
1413
1414long skip_number(const GoString *src, long *p) {
1415 const char* ss = src->buf;
1416 const char* sp = src->buf + *p;
1417 size_t nb = src->len - *p;
1418 long i = *p;
1419 long r;
1420 bool neg = *sp == '-';
1421
1422 sp += neg;
1423 nb -= neg;
1424 if (unlikely(nb <= 0)) {
1425 *p = sp - ss;
1426 return -ERR_EOF;
1427 }
1428
1429 if (unlikely(nb > 0 && (*sp > '9' || *sp < '0'))) {
1430 *p = sp - ss;
1431 return -ERR_INVAL;
1432 }
1433
1434 r = do_skip_number(sp, nb);
1435 if (unlikely(r < 0)) {
1436 *p = sp - (r + 1) - ss;
1437 return -ERR_INVAL;
1438 }
1439 *p = sp + r - ss;
1440 return i;
1441}
1442
1443long skip_one(const GoString *src, long *p, StateMachine *m, uint64_t flags) {
1444 fsm_init(m, FSM_VAL);
1445 return fsm_exec(m, src, p, flags);
1446}
1447
1448long validate_one(const GoString *src, long *p, StateMachine *m) {
1449 fsm_init(m, FSM_VAL);
1450 return fsm_exec(m, src, p, MASK_VALIDATE_STRING);
1451}
1452
1453/* Faster skip api for sonic.ast */
1454
1455static always_inline uint64_t get_maskx64(const char *s, char c) {
1456#if USE_AVX2
1457 __m256i v0 = _mm256_loadu_si256((__m256i const *)s);
1458 __m256i v1 = _mm256_loadu_si256((__m256i const *)(s + 32));
1459 uint32_t m0 = _mm256_movemask_epi8(_mm256_cmpeq_epi8(v0, _mm256_set1_epi8(c)));
1460 uint32_t m1 = _mm256_movemask_epi8(_mm256_cmpeq_epi8(v1, _mm256_set1_epi8(c)));
1461 return ((uint64_t)(m1) << 32) | (uint64_t)(m0);
1462#else
1463 __m128i v0 = _mm_loadu_si128((__m128i const*)s);
1464 __m128i v1 = _mm_loadu_si128((__m128i const*)(s + 16));
1465 __m128i v2 = _mm_loadu_si128((__m128i const*)(s + 32));
1466 __m128i v3 = _mm_loadu_si128((__m128i const*)(s + 48));
1467 uint32_t m0 = _mm_movemask_epi8(_mm_cmpeq_epi8(v0, _mm_set1_epi8(c)));
1468 uint32_t m1 = _mm_movemask_epi8(_mm_cmpeq_epi8(v1, _mm_set1_epi8(c)));
1469 uint32_t m2 = _mm_movemask_epi8(_mm_cmpeq_epi8(v2, _mm_set1_epi8(c)));
1470 uint32_t m3 = _mm_movemask_epi8(_mm_cmpeq_epi8(v3, _mm_set1_epi8(c)));
1471 return ((uint64_t)(m3) << 48) | ((uint64_t)(m2) << 32) | ((uint64_t)(m1) << 16) | (uint64_t)(m0);
1472#endif
1473}
1474
1475static always_inline uint64_t get_maskx32(const char *s, char c) {
1476#if USE_AVX2
1477 __m256i v0 = _mm256_loadu_si256((__m256i const *)s);
1478 uint64_t m0 = (unsigned)_mm256_movemask_epi8(_mm256_cmpeq_epi8(v0, _mm256_set1_epi8(c)));
1479 return m0;
1480#else
1481 __m128i v0 = _mm_loadu_si128((__m128i const*)s);
1482 __m128i v1 = _mm_loadu_si128((__m128i const*)(s + 16));
1483 uint64_t m0 = (unsigned)_mm_movemask_epi8(_mm_cmpeq_epi8(v0, _mm_set1_epi8(c)));
1484 uint64_t m1 = (unsigned)_mm_movemask_epi8(_mm_cmpeq_epi8(v1, _mm_set1_epi8(c)));
1485 return m0 | (m1 << 16);
1486#endif
1487}
1488
1489// get the string (besides in quote) mask
1490static always_inline uint64_t get_string_maskx64(const char *s, uint64_t *prev_inquote, uint64_t *prev_bs) {
1491 uint64_t escaped = *prev_bs;
1492 uint64_t quote_mask = 0, bs_mask = 0;
1493
1494 /* read and get the quote or backslash bitmask */
1495 quote_mask = get_maskx64(s, '"');
1496 bs_mask = get_maskx64(s, '\\');
1497
1498 /* get the escaped bitmask */
1499 if (bs_mask || *prev_bs) {
1500 bs_mask &= ~(*prev_bs);
1501 uint64_t follow_bs = (bs_mask << 1) | *prev_bs;
1502 uint64_t bs_start = bs_mask & ~follow_bs;
1503 uint64_t odd_start = bs_start & ODD_MASK;
1504 uint64_t even_or_oc = add64(odd_start, bs_mask, prev_bs);
1505 uint64_t even_or_escaped = (even_or_oc << 1) ^ EVEN_MASK;
1506 escaped = follow_bs & even_or_escaped;
1507 } else {
1508 *prev_bs = 0;
1509 }
1510 quote_mask &= ~escaped;
1511
1512 /* get the inquote bitmask */
1513 uint64_t inquote = _mm_cvtsi128_si64(_mm_clmulepi64_si128(_mm_set_epi64x(0, quote_mask), _mm_set1_epi8('\xFF'), 0));
1514 inquote ^= *prev_inquote;
1515 *prev_inquote = (uint64_t)(((int64_t)(inquote)) >> 63);
1516 return inquote;
1517}
1518
1519// get the next json structural, '}', ']' or ','。
1520#if USE_AVX2
1521static always_inline int get_structural_maskx32(const char *s) {
1522 __m256i v = _mm256_loadu_si256((const void *)s);
1523 __m256i e1 = _mm256_cmpeq_epi8(v, _mm256_set1_epi8('}'));
1524 __m256i e2 = _mm256_cmpeq_epi8(v, _mm256_set1_epi8(']'));
1525 __m256i e3 = _mm256_cmpeq_epi8(v, _mm256_set1_epi8(','));
1526 __m256i sv = _mm256_or_si256(_mm256_or_si256(e1, e2), e3);
1527 return _mm256_movemask_epi8(sv);
1528}
1529#endif
1530
1531static always_inline int get_structural_maskx16(const char *s) {
1532 __m128i v = _mm_loadu_si128((const void *)s);
1533 __m128i e1 = _mm_cmpeq_epi8(v, _mm_set1_epi8('}'));
1534 __m128i e2 = _mm_cmpeq_epi8(v, _mm_set1_epi8(']'));
1535 __m128i e3 = _mm_cmpeq_epi8(v, _mm_set1_epi8(','));
1536 __m128i sv = _mm_or_si128(_mm_or_si128(e1, e2), e3);
1537 return _mm_movemask_epi8(sv);
1538}
1539
1540// skip the number at the next '}', ']' or ',' or the ending of json.
1541static always_inline long skip_number_fast(const GoString *src, long *p) {
1542 size_t nb = src->len - *p;
1543 const char *s = src->buf + *p;
1544 long vi = *p - 1;
1545 int m = 0;
1546
1547#if USE_AVX2
1548 while (likely(nb >= 32)) {
1549 if ((m = get_structural_maskx32(s))) {
1550 *p = s - src->buf + __builtin_ctzll(m);
1551 return vi;
1552 }
1553 s += 32, nb -= 32;
1554 }
1555#endif
1556
1557 while (likely(nb >= 16)) {
1558 if ((m = get_structural_maskx16(s))) {
1559 *p = s - src->buf + __builtin_ctzll(m);
1560 return vi;
1561 }
1562 s += 16, nb -= 16;
1563 }
1564
1565 while (likely(nb > 0)) {
1566 if (*s == '}' || *s == ']' || *s == ',') {
1567 *p = s - src->buf;
1568 return vi;
1569 }
1570 s++, nb--;
1571 }
1572 *p = s - src->buf;
1573 return vi;
1574}
1575
1576static always_inline long skip_container_fast(const GoString *src, long *p, char lc, char rc) {
1577 long nb = src->len - *p;
1578 const char *s = src->buf + *p;
1579 long vi = *p - 1;
1580
1581 uint64_t prev_inquote = 0, prev_bs = 0;
1582 uint64_t lbrace = 0, rbrace = 0;
1583 size_t lnum = 0, rnum = 0, last_lnum = 0;
1584 uint64_t inquote = 0;
1585
1586 while (likely(nb >= 64)) {
1587skip:
1588 inquote = get_string_maskx64(s, &prev_inquote, &prev_bs);
1589 lbrace = get_maskx64(s, lc) & ~inquote;
1590 rbrace = get_maskx64(s, rc) & ~inquote;
1591
1592 /* traverse each right brace */
1593 last_lnum = lnum;
1594 while (rbrace > 0) {
1595 uint64_t lbrace_first = (rbrace - 1) & lbrace;
1596 lnum = last_lnum + __builtin_popcountll((int64_t)lbrace_first);
1597 bool is_closed = lnum <= rnum;
1598 if (is_closed) {
1599 *p = src->len - nb + __builtin_ctzll(rbrace) + 1;
1600 // *p is out-of-bound access here
1601 if (*p > src->len) {
1602 *p = src->len;
1603 return -ERR_EOF;
1604 }
1605 return vi;
1606 }
1607 rbrace &= (rbrace - 1); // clear the lowest right brace
1608 rnum ++;
1609 }
1610 lnum = last_lnum + __builtin_popcountll((int64_t)lbrace);
1611 s += 64, nb -= 64;
1612 }
1613
1614 if (nb <= 0) {
1615 *p = src->len;
1616 return -ERR_EOF;
1617 }
1618
1619 char tbuf[64] = {0};
1620 bool cross_page = vec_cross_page(s, 64);
1621 if (cross_page) {
1622 memcpy_p64(tbuf, s, nb);
1623 s = tbuf;
1624 }
1625 goto skip;
1626}
1627
1628static always_inline long skip_object_fast(const GoString *src, long *p) {
1629 return skip_container_fast(src, p, '{', '}');
1630}
1631
1632static always_inline long skip_array_fast(const GoString *src, long *p) {
1633 return skip_container_fast(src, p, '[', ']');
1634}
1635
1636static always_inline long skip_string_fast(const GoString *src, long *p) {
1637 const char* s = src->buf + *p;
1638 long nb = src->len - *p;
1639 long vi = *p - 1;
1640 uint64_t prev_bs = 0, escaped;
1641
1642 while (likely(nb >= 32)) {
1643 uint32_t quote = get_maskx32(s, '"');
1644 uint32_t bs_mask = get_maskx32(s, '\\');
1645 if (bs_mask || prev_bs) {
1646 bs_mask &= ~prev_bs;
1647 uint64_t follow_bs = (bs_mask << 1) | prev_bs;
1648 uint64_t bs_start = bs_mask & ~follow_bs;
1649 uint64_t odd_start = bs_start & ODD_MASK;
1650 uint64_t even_or_oc = add32(odd_start, bs_mask, &prev_bs);
1651 uint64_t even_or_escaped = (even_or_oc << 1) ^ EVEN_MASK;
1652 escaped = follow_bs & even_or_escaped;
1653 quote &= ~escaped;
1654 }
1655 if (quote) {
1656 *p = s + __builtin_ctzll(quote) + 1 - src->buf;
1657 return vi;
1658 }
1659 s += 32;
1660 nb -= 32;
1661 }
1662
1663 if (unlikely(prev_bs != 0)) {
1664 if (nb == 0) return -ERR_EOF;
1665 s++, nb--;
1666 }
1667
1668 while (likely(nb > 0)) {
1669 if (*s == '\\') {
1670 s += 2, nb -= 2;
1671 continue;
1672 }
1673 if (*s == '"') {
1674 *p = s - src->buf + 1;
1675 return vi;
1676 }
1677 s++, nb--;
1678 }
1679 return -ERR_EOF;
1680}
1681
1682long skip_one_fast(const GoString *src, long *p) {
1683 char c = advance_ns(src, p);
1684 /* set the start address */
1685 long vi = *p - 1;
1686 switch (c) {
1687 case '[': return skip_array_fast(src, p);
1688 case '{': return skip_object_fast(src, p);
1689 case '"': return skip_string_fast(src, p);
1690 case '-': case '0' ... '9': return skip_number_fast(src, p);
1691 case 't': case 'n': { if (*p + 3 <= src->len) { *p += 3; } else { return -ERR_EOF; } }; break;
1692 case 'f': { if (*p + 4 <= src->len) { *p += 4; } else { return -ERR_EOF; } }; break;
1693 case 0 : return -ERR_EOF;
1694 default : *p -= 1; return -ERR_INVAL; // backward error position
1695 }
1696 return vi;
1697}
1698
1699
1700static always_inline GoKind kind(const GoIface* iface) {
1701 return (iface->type->kind_flags) & GO_KIND_MASK;
1702}
1703
1704static always_inline bool is_int(const GoIface* iface) {
1705 return iface->type != NULL && kind(iface) == Int;
1706}
1707
1708static always_inline bool is_str(const GoIface* iface) {
1709 return iface->type != NULL && kind(iface) == String;
1710}
1711
1712static always_inline GoString get_str(const GoIface* iface) {
1713 return *(GoString*)(iface->value);
1714}
1715
1716static always_inline int64_t get_int(const GoIface* iface) {
1717 return *(int64_t*)(iface->value);
1718}
1719
1720// xmemcmpeq return true if s1 and s2 is equal for the n bytes, otherwise, return false.
1721static always_inline bool xmemcmpeq(const char * s1, const char * s2, size_t n) {
1722 bool c1, c2;
1723#if USE_AVX2
1724 while (n >= 32) {
1725 __m256i v1 = _mm256_loadu_si256((const void *)s1);
1726 __m256i v2 = _mm256_loadu_si256((const void *)s2);
1727 uint32_t mask = ~((uint32_t)_mm256_movemask_epi8(_mm256_cmpeq_epi8(v1, v2)));
1728 if (mask) return false;
1729 s1 += 32;
1730 s2 += 32;
1731 n -= 32;
1732 };
1733 c1 = vec_cross_page(s1, 32);
1734 c2 = vec_cross_page(s2, 32);
1735 // not cross page
1736 if (!c1 && !c2) {
1737 __m256i v1 = _mm256_loadu_si256((const void *)s1);
1738 __m256i v2 = _mm256_loadu_si256((const void *)s2);
1739 uint32_t mask = ~((uint32_t)_mm256_movemask_epi8(_mm256_cmpeq_epi8(v1, v2)));
1740 bool eq = (mask == 0) || (__builtin_ctzll(mask) >= n);
1741 return eq;
1742 }
1743#endif
1744 while (n >= 16) {
1745 __m128i v1 = _mm_loadu_si128((const void *)s1);
1746 __m128i v2 = _mm_loadu_si128((const void *)s2);
1747 uint16_t mask = ~((uint16_t)_mm_movemask_epi8(_mm_cmpeq_epi8(v1, v2)));
1748 if (mask != 0) return false;
1749 s1 += 16;
1750 s2 += 16;
1751 n -= 16;
1752 };
1753 c1 = vec_cross_page(s1, 16);
1754 c2 = vec_cross_page(s2, 16);
1755 // not cross page
1756 if (!c1 && !c2) {
1757 __m128i v1 = _mm_loadu_si128((const void *)s1);
1758 __m128i v2 = _mm_loadu_si128((const void *)s2);
1759 uint16_t mask = ~((uint16_t)_mm_movemask_epi8(_mm_cmpeq_epi8(v1, v2)));
1760 bool eq = (mask == 0) || (__builtin_ctzll(mask) >= n);
1761 return eq;
1762 }
1763 // cross page
1764 while (n > 0 && *s1++ == *s2++) n--;
1765 return n == 0;
1766}
1767
1768// match_key return negative if errors, zero if not matched, one if matched.
1769static always_inline long match_key(const GoString *src, long *p, const GoString key) {
1770 static const long not_match = 0;
1771 int64_t v = -1;
1772 long si = *p;
1773 long se = advance_string_default(src, *p, &v);
1774 if (unlikely(se < 0)) {
1775 *p = src->len;
1776 return -ERR_EOF;
1777 }
1778
1779 /* update position */
1780 *p = se;
1781
1782 /* compare non-escaped strings */
1783 if (likely(v == -1 || v > se)) {
1784 long sn = se - si - 1;
1785
1786 // check empty keys
1787 if (!sn && !key.len) {
1788 return true;
1789 }
1790
1791 return sn == key.len && xmemcmpeq(src->buf + si, key.buf, key.len);
1792 }
1793
1794 /* deal with escaped strings */
1795 char buf[8] = {0}; // escaped buffer
1796 const char* sp = src->buf + si;
1797 const char* end = src->buf + se - 1;
1798 const char* kp = key.buf;
1799 const char* ke = key.buf + key.len;
1800 while (sp < end && kp < ke) {
1801 if (*sp == '\\') {
1802 long en = unescape(&sp, end, buf);
1803 if (en < 0) {
1804 *p = sp - src->buf;
1805 return en;
1806 }
1807 const char* ee = buf + en;
1808 const char* ep = buf;
1809 while (kp < ke && ep < ee && *kp == *ep) kp++, ep++;
1810 if (ep != ee) {
1811 return not_match;
1812 }
1813 } else if (*sp == *kp) {
1814 sp++, kp++;
1815 } else {
1816 return not_match;
1817 }
1818 };
1819 return sp == end && kp == ke;
1820}
1821
1822long get_by_path(const GoString *src, long *p, const GoSlice *path, StateMachine* sm) {
1823 GoIface *ps = (GoIface*)(path->buf);
1824 GoIface *pe = (GoIface*)(path->buf) + path->len;
1825 char c = 0;
1826 int64_t index;
1827 long found;
1828
1829query:
1830 /* to be safer for invalid json, use slower skip for the demanded fields */
1831 if (ps == pe) {
1832 return skip_one(src, p, sm, 0);
1833 }
1834
1835 /* match type: should query key in object, query index in array */
1836 c = advance_ns(src, p);
1837 if (is_str(ps)) {
1838 if (c != '{') {
1839 goto err_inval;
1840 }
1841 goto skip_in_obj;
1842 } else if (is_int(ps)) {
1843 if (c != '[') {
1844 goto err_inval;
1845 }
1846
1847 index = get_int(ps);
1848 if (index < 0) {
1849 goto err_path;
1850 }
1851
1852 goto skip_in_arr;
1853 } else {
1854 goto err_path;
1855 }
1856
1857skip_in_obj:
1858 c = advance_ns(src, p);
1859 if (c == '}') {
1860 goto not_found;
1861 }
1862 if (c != '"') {
1863 goto err_inval;
1864 }
1865
1866 /* parse the object key */
1867 found = match_key(src, p, get_str(ps));
1868 if (found < 0) {
1869 return found; // parse string errors
1870 }
1871
1872 /* value should after : */
1873 c = advance_ns(src, p);
1874 if (c != ':') {
1875 goto err_inval;
1876 }
1877 if (found) {
1878 ps++;
1879 goto query;
1880 }
1881
1882 /* skip the unknown fields */
1883 skip_one_fast(src, p);
1884 c = advance_ns(src, p);
1885 if (c == '}') {
1886 goto not_found;
1887 }
1888 if (c != ',') {
1889 goto err_inval;
1890 }
1891 goto skip_in_obj;
1892
1893skip_in_arr:
1894 /* check empty array */
1895 c = advance_ns(src, p);
1896 if (c == ']') {
1897 goto not_found;
1898 }
1899 *p -= 1;
1900
1901 /* skip array elem one by one */
1902 while (index-- > 0) {
1903 skip_one_fast(src, p);
1904 c = advance_ns(src, p);
1905 if (c == ']') {
1906 goto not_found;
1907 }
1908 if (c != ',') {
1909 goto err_inval;
1910 }
1911 }
1912 ps++;
1913 goto query;
1914
1915not_found:
1916 *p -= 1; // backward error position
1917 return -ERR_NOT_FOUND;
1918err_inval:
1919 *p -= 1;
1920 return -ERR_INVAL;
1921err_path:
1922 *p -= 1;
1923 return -ERR_UNSUPPORT_TYPE;
1924}
1925
1926//
1927long validate_utf8(const GoString *src, long *p, StateMachine *m) {
1928 xassert(*p >= 0 && src->len > *p);
1929 return validate_utf8_with_errors(src->buf, src->len, p, m);
1930}
1931
1932// validate_utf8_fast returns zero if valid, otherwise, the error position.
1933long validate_utf8_fast(const GoString *s) {
1934#if USE_AVX2
1935 /* fast path for valid utf8 */
1936 if (validate_utf8_avx2(s) == 0) {
1937 return 0;
1938 }
1939#endif
1940 return validate_utf8_errors(s);
1941}
View as plain text