yeptris 0.6.19.1-arm-linux-eabihf → 0.6.20.2-arm-linux-eabihf
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/build_windows_native.rb +31 -12
- data/lib/yeptris/3.4/native.so +0 -0
- data/lib/yeptris/psych.rb +1 -1
- data/lib/yeptris.rb +30 -14
- data/libyeptris.so +0 -0
- data/vendor/libyeptris/CMakeLists.txt +1 -1
- data/vendor/libyeptris/src/CMakeLists.txt +1 -0
- data/vendor/libyeptris/src/yeptris/cbor/decode.c +1 -0
- data/vendor/libyeptris/src/yeptris/common/simd_text.h +47 -13
- data/vendor/libyeptris/src/yeptris/common/simd_text_avx2.c +86 -8
- data/vendor/libyeptris/src/yeptris/common/simd_text_neon.c +82 -8
- data/vendor/libyeptris/src/yeptris/common/simd_text_scalar.c +10 -6
- data/vendor/libyeptris/src/yeptris/doc.h +8 -4
- data/vendor/libyeptris/src/yeptris/dom/ytape.c +640 -0
- data/vendor/libyeptris/src/yeptris/dom/ytape.h +77 -0
- data/vendor/libyeptris/src/yeptris/emit/writer.c +7 -2
- data/vendor/libyeptris/src/yeptris/parse.c +144 -42
- data/vendor/libyeptris/src/yeptris/scan/json.c +43 -5
- data/vendor/libyeptris/src/yeptris/scan/json.h +9 -2
- data/vendor/libyeptris/src/yeptris/tape.c +539 -163
- data/vendor/libyeptris/src/yeptris/tape_in.h +12 -0
- metadata +4 -2
- data/lib/yeptris/native-3.4.so +0 -0
|
@@ -618,200 +618,335 @@ YeptrisStatus yep_tape_walk_lenient_fused(const char* p, size_t len, size_t open
|
|
|
618
618
|
uint8_t top_kind = p[open] == '[' ? 0 : 1;
|
|
619
619
|
recs[1] =
|
|
620
620
|
((uint64_t)0 << 32) | ((uint64_t)0 << 8) | (top_kind ? YEP_T_MAP_OPEN : YEP_T_SEQ_OPEN);
|
|
621
|
-
uint32_t top_open = 1;
|
|
622
621
|
size_t count = 2;
|
|
623
|
-
uint8_t top_expect = top_kind ? JW_KEY_OR_CLOSE : JW_VALUE_OR_CLOSE;
|
|
624
|
-
int key_slot = top_kind ? 1 : 0;
|
|
625
622
|
int depth = 1;
|
|
626
|
-
open_at[0] =
|
|
623
|
+
open_at[0] = 1;
|
|
627
624
|
kind[0] = top_kind;
|
|
628
625
|
|
|
629
626
|
size_t i = open + 1;
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
if (i >= len) {
|
|
635
|
-
goto lreject;
|
|
636
|
-
}
|
|
637
|
-
size_t at = i;
|
|
638
|
-
char c = p[i];
|
|
627
|
+
if (top_kind) {
|
|
628
|
+
goto lmap1;
|
|
629
|
+
}
|
|
630
|
+
goto lseq1;
|
|
639
631
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
|
|
632
|
+
/* The specialized member loops (the #342 dispatch-chain cut): once
|
|
633
|
+
* inside a container the grammar is a 2-state cycle — member or
|
|
634
|
+
* separator — so the general chain's expect/key_slot machine and
|
|
635
|
+
* its per-token re-dispatch are replaced by direct loops per kind.
|
|
636
|
+
* Acceptance is IDENTICAL to the chain (the pinning suites hold:
|
|
637
|
+
* Tape suite, LenientMatchesStrict, ErrorParity, the json corpora).
|
|
638
|
+
*
|
|
639
|
+
* lmap / lseq: positioned at a member (or the container's closer).
|
|
640
|
+
* lvalue: scans one value (string/number/literal/container).
|
|
641
|
+
* lafter: positioned after a complete value — ',' or the closer.
|
|
642
|
+
* A close pops the frame; depth 0 ends the walk. */
|
|
643
|
+
|
|
644
|
+
#define LWS() \
|
|
645
|
+
do { \
|
|
646
|
+
while (i < len && (p[i] == ' ' || p[i] == '\n' || p[i] == '\r' || p[i] == '\t')) { \
|
|
647
|
+
i++; \
|
|
648
|
+
} \
|
|
649
|
+
if (i >= len) { \
|
|
650
|
+
goto lreject; \
|
|
651
|
+
} \
|
|
652
|
+
} while (0)
|
|
653
|
+
|
|
654
|
+
#define LPUSH(k) \
|
|
655
|
+
do { \
|
|
656
|
+
if (depth >= YEP_JSON_WALK_DEPTH) { \
|
|
657
|
+
goto lreject; \
|
|
658
|
+
} \
|
|
659
|
+
recs[count] = ((uint64_t)0 << 32) | ((uint64_t)0 << 8) | \
|
|
660
|
+
(uint64_t)((k) ? YEP_T_MAP_OPEN : YEP_T_SEQ_OPEN); \
|
|
661
|
+
kind[depth] = (k); \
|
|
662
|
+
open_at[depth] = (uint32_t)count; \
|
|
663
|
+
count++; \
|
|
664
|
+
depth++; \
|
|
665
|
+
i++; \
|
|
666
|
+
} while (0)
|
|
667
|
+
|
|
668
|
+
#define LCLOSE() \
|
|
669
|
+
do { \
|
|
670
|
+
uint32_t lo_ = open_at[depth - 1]; \
|
|
671
|
+
recs[count] = ((uint64_t)lo_ << 32) | ((uint64_t)0 << 8) | YEP_T_CLOSE; \
|
|
672
|
+
recs[lo_] = \
|
|
673
|
+
(recs[lo_] & ~(uint64_t)0xFFFFFFFF00000000u) | ((uint64_t)(uint32_t)count << 32); \
|
|
674
|
+
count++; \
|
|
675
|
+
i++; \
|
|
676
|
+
depth--; \
|
|
677
|
+
if (depth == 0) { \
|
|
678
|
+
goto ldone; \
|
|
679
|
+
} \
|
|
680
|
+
if (kind[depth - 1]) { \
|
|
681
|
+
goto lmapafter; \
|
|
682
|
+
} \
|
|
683
|
+
goto lseqafter; \
|
|
684
|
+
} while (0)
|
|
685
|
+
|
|
686
|
+
/* LSTR_SCAN(after) — the fused string arm, positioned at p[i] == '"'.
|
|
687
|
+
* One SWAR round settles the common short span; quote_scan (the SIMD
|
|
688
|
+
* close scan) settles longer no-escape spans, with a c0 sweep over the
|
|
689
|
+
* content (quote_scan never tests control bytes); the kernel runs only
|
|
690
|
+
* when escapes appear — its grammar authority covers the escape rules
|
|
691
|
+
* quote_scan skips. `after` names the post-member label. */
|
|
692
|
+
#define LSTR_SCAN(after) \
|
|
693
|
+
do { \
|
|
694
|
+
size_t j_ = i + 1; \
|
|
695
|
+
int esc_ = 0; \
|
|
696
|
+
if (j_ + 8 <= len) { \
|
|
697
|
+
uint64_t w_; \
|
|
698
|
+
memcpy(&w_, p + j_, 8); \
|
|
699
|
+
uint64_t qm_ = (w_ ^ 0x2222222222222222ull); \
|
|
700
|
+
uint64_t bm_ = (w_ ^ 0x5C5C5C5C5C5C5C5Cull); \
|
|
701
|
+
qm_ = (qm_ - 0x0101010101010101ull) & ~qm_ & 0x8080808080808080ull; \
|
|
702
|
+
bm_ = (bm_ - 0x0101010101010101ull) & ~bm_ & 0x8080808080808080ull; \
|
|
703
|
+
uint64_t c0_ = (w_ - 0x2020202020202020ull) & ~w_ & 0x8080808080808080ull; \
|
|
704
|
+
if (qm_ != 0 && ((bm_ | c0_) & (qm_ - 1)) == 0) { \
|
|
705
|
+
size_t cl_ = j_ + (size_t)yep_ctz64(qm_) / 8; \
|
|
706
|
+
recs[count] = ((uint64_t)((uint32_t)j_) << 32) | \
|
|
707
|
+
((uint64_t)((uint32_t)(cl_ - j_)) << 8) | (uint64_t)(YEP_T_STR); \
|
|
708
|
+
count++; \
|
|
709
|
+
i = cl_ + 1; \
|
|
710
|
+
goto after; \
|
|
711
|
+
} \
|
|
712
|
+
} \
|
|
713
|
+
{ \
|
|
714
|
+
const yep_text_kernels* kk_ = yep_text_active(); \
|
|
715
|
+
ptrdiff_t r_ = kk_->quote_scan(p + j_, len - j_, '"', &esc_); \
|
|
716
|
+
if (r_ >= 0 && esc_ == 0) { \
|
|
717
|
+
size_t cl_ = j_ + (size_t)r_; \
|
|
718
|
+
for (size_t b_ = j_; b_ < cl_;) { \
|
|
719
|
+
size_t room_ = cl_ - b_; \
|
|
720
|
+
if (room_ >= 8) { \
|
|
721
|
+
uint64_t v_; \
|
|
722
|
+
memcpy(&v_, p + b_, 8); \
|
|
723
|
+
if ((v_ - 0x2020202020202020ull) & ~v_ & 0x8080808080808080ull) { \
|
|
724
|
+
goto lreject; \
|
|
725
|
+
} \
|
|
726
|
+
b_ += 8; \
|
|
727
|
+
} else { \
|
|
728
|
+
if ((unsigned char)p[b_] < 0x20) { \
|
|
729
|
+
goto lreject; \
|
|
730
|
+
} \
|
|
731
|
+
b_++; \
|
|
732
|
+
} \
|
|
733
|
+
} \
|
|
734
|
+
recs[count] = ((uint64_t)((uint32_t)j_) << 32) | \
|
|
735
|
+
((uint64_t)((uint32_t)(cl_ - j_)) << 8) | (uint64_t)(YEP_T_STR); \
|
|
736
|
+
count++; \
|
|
737
|
+
i = cl_ + 1; \
|
|
738
|
+
goto after; \
|
|
739
|
+
} \
|
|
740
|
+
} \
|
|
741
|
+
{ \
|
|
742
|
+
size_t at_ = i; \
|
|
743
|
+
size_t cl_ = 0; \
|
|
744
|
+
if (!yep_json_string(p, len, &i, &cl_, &esc_)) { \
|
|
745
|
+
goto lreject; \
|
|
746
|
+
} \
|
|
747
|
+
recs[count] = ((uint64_t)((uint32_t)(at_ + 1)) << 32) | \
|
|
748
|
+
((uint64_t)((uint32_t)(cl_ - at_ - 1)) << 8) | (uint64_t)(YEP_T_STR); \
|
|
749
|
+
count++; \
|
|
750
|
+
i = cl_ + 1; \
|
|
751
|
+
} \
|
|
752
|
+
goto after; \
|
|
753
|
+
} while (0)
|
|
754
|
+
|
|
755
|
+
/* The map member cycle — ONE contiguous region (the json-doc lesson:
|
|
756
|
+
* a goto web across value/key/after regions scattered the hot path and
|
|
757
|
+
* cost 2.7x on the flat-map shape). Values scan inline; only nested
|
|
758
|
+
* containers, literals, and the kernel string fallback leave the
|
|
759
|
+
* cycle. Acceptance is the chain's: no trailing commas, string keys
|
|
760
|
+
* only, `:` required, closers only in first-member position. */
|
|
761
|
+
lmap1: /* {} closes here */
|
|
762
|
+
LWS();
|
|
763
|
+
if (p[i] == '}') {
|
|
764
|
+
LCLOSE();
|
|
765
|
+
}
|
|
766
|
+
if (p[i] != '"') {
|
|
767
|
+
goto lreject;
|
|
768
|
+
}
|
|
769
|
+
goto lmapkey;
|
|
662
770
|
|
|
771
|
+
lmap: /* a member MUST follow (after ','): JW_KEY — a closer rejects */
|
|
772
|
+
LWS();
|
|
773
|
+
if (p[i] != '"') {
|
|
774
|
+
goto lreject;
|
|
775
|
+
}
|
|
776
|
+
lmapkey: { LSTR_SCAN(lmapcolon); }
|
|
777
|
+
lmapcolon:
|
|
778
|
+
LWS();
|
|
779
|
+
if (p[i] != ':') {
|
|
780
|
+
goto lreject;
|
|
781
|
+
}
|
|
782
|
+
i++;
|
|
783
|
+
LWS();
|
|
784
|
+
{
|
|
785
|
+
char c = p[i];
|
|
663
786
|
if (c == '"') {
|
|
664
|
-
|
|
665
|
-
size_t close = 0;
|
|
666
|
-
/* SWAR settle first (the lenient walk's own fast path); the
|
|
667
|
-
* kernel stays the authority on escapes/C0/long spans */
|
|
668
|
-
if (j + 8 <= len) {
|
|
669
|
-
uint64_t w;
|
|
670
|
-
memcpy(&w, p + j, 8);
|
|
671
|
-
uint64_t qm = (w ^ 0x2222222222222222ull);
|
|
672
|
-
uint64_t bm = (w ^ 0x5C5C5C5C5C5C5C5Cull);
|
|
673
|
-
qm = (qm - 0x0101010101010101ull) & ~qm & 0x8080808080808080ull;
|
|
674
|
-
bm = (bm - 0x0101010101010101ull) & ~bm & 0x8080808080808080ull;
|
|
675
|
-
uint64_t c0 = (w - 0x2020202020202020ull) & ~w & 0x8080808080808080ull;
|
|
676
|
-
if (qm != 0 && ((bm | c0) & (qm - 1)) == 0) {
|
|
677
|
-
close = j + (size_t)yep_ctz64(qm) / 8;
|
|
678
|
-
recs[count] = ((uint64_t)((uint32_t)j) << 32) |
|
|
679
|
-
((uint64_t)((uint32_t)(close - j)) << 8) | (uint64_t)(YEP_T_STR);
|
|
680
|
-
count++;
|
|
681
|
-
i = close + 1;
|
|
682
|
-
goto lstr_done;
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
int esc = 0;
|
|
686
|
-
if (!yep_json_string(p, len, &i, &close, &esc)) {
|
|
687
|
-
goto lreject;
|
|
688
|
-
}
|
|
689
|
-
recs[count] = ((uint64_t)((uint32_t)(at + 1)) << 32) |
|
|
690
|
-
((uint64_t)((uint32_t)(close - at - 1)) << 8) | (uint64_t)(YEP_T_STR);
|
|
691
|
-
count++;
|
|
692
|
-
lstr_done:
|
|
693
|
-
if (key_slot) {
|
|
694
|
-
if (i < len && p[i] == ':') {
|
|
695
|
-
i++;
|
|
696
|
-
top_expect = JW_VALUE;
|
|
697
|
-
key_slot = 0;
|
|
698
|
-
} else {
|
|
699
|
-
top_expect = JW_COLON;
|
|
700
|
-
}
|
|
701
|
-
} else {
|
|
702
|
-
goto lcomma;
|
|
703
|
-
}
|
|
704
|
-
continue;
|
|
787
|
+
LSTR_SCAN(lmapafter);
|
|
705
788
|
}
|
|
706
789
|
if ((unsigned)(c - '0') <= 9u || c == '-') {
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
char d = p[i];
|
|
790
|
+
size_t k = i + 1;
|
|
791
|
+
while (k < len) {
|
|
792
|
+
char d = p[k];
|
|
711
793
|
if ((d >= '0' && d <= '9') || d == '-' || d == '+' || d == '.' || d == 'e' ||
|
|
712
794
|
d == 'E') {
|
|
713
|
-
|
|
795
|
+
k++;
|
|
714
796
|
continue;
|
|
715
797
|
}
|
|
716
798
|
break;
|
|
717
799
|
}
|
|
718
|
-
recs[count] = ((uint64_t)((uint32_t)
|
|
800
|
+
recs[count] = ((uint64_t)((uint32_t)i) << 32) | ((uint64_t)((uint32_t)(k - i)) << 8) |
|
|
719
801
|
(uint64_t)(YEP_T_NUM);
|
|
720
802
|
count++;
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
i++;
|
|
724
|
-
top_expect = top_kind ? JW_KEY : JW_VALUE;
|
|
725
|
-
key_slot = top_kind ? 1 : 0;
|
|
726
|
-
} else {
|
|
727
|
-
top_expect = JW_COMMA_OR_CLOSE;
|
|
728
|
-
}
|
|
729
|
-
continue;
|
|
730
|
-
}
|
|
731
|
-
if (c == ']' || c == '}') {
|
|
732
|
-
int want = c == ']' ? 0 : 1;
|
|
733
|
-
if (top_kind != want ||
|
|
734
|
-
(top_expect != JW_VALUE_OR_CLOSE && top_expect != JW_KEY_OR_CLOSE &&
|
|
735
|
-
top_expect != JW_COMMA_OR_CLOSE)) {
|
|
736
|
-
goto lreject;
|
|
737
|
-
}
|
|
738
|
-
recs[count] = ((uint64_t)top_open << 32) | ((uint64_t)0 << 8) | YEP_T_CLOSE;
|
|
739
|
-
/* back-patch the opener's count link: keep the original
|
|
740
|
-
* off/len, set the link into the record's off word */
|
|
741
|
-
recs[top_open] = (recs[top_open] & ~(uint64_t)0xFFFFFFFF00000000u) |
|
|
742
|
-
((uint64_t)(uint32_t)count << 32);
|
|
743
|
-
count++;
|
|
744
|
-
i = at + 1;
|
|
745
|
-
depth--;
|
|
746
|
-
if (depth == 0) {
|
|
747
|
-
break;
|
|
748
|
-
}
|
|
749
|
-
top_kind = kind[depth - 1];
|
|
750
|
-
top_expect = JW_COMMA_OR_CLOSE;
|
|
751
|
-
top_open = open_at[depth - 1];
|
|
752
|
-
key_slot = 0;
|
|
753
|
-
continue;
|
|
754
|
-
}
|
|
755
|
-
if (c == '{' || c == '[') {
|
|
756
|
-
if (depth >= YEP_JSON_WALK_DEPTH) {
|
|
757
|
-
goto lreject;
|
|
758
|
-
}
|
|
759
|
-
if (key_slot) {
|
|
760
|
-
goto lreject;
|
|
761
|
-
}
|
|
762
|
-
kind[depth - 1] = top_kind;
|
|
763
|
-
open_at[depth - 1] = top_open;
|
|
764
|
-
top_kind = c == '[' ? 0 : 1;
|
|
765
|
-
recs[count] = ((uint64_t)0 << 32) | ((uint64_t)0 << 8) |
|
|
766
|
-
(uint64_t)(c == '[' ? YEP_T_SEQ_OPEN : YEP_T_MAP_OPEN);
|
|
767
|
-
top_open = (uint32_t)count;
|
|
768
|
-
count++;
|
|
769
|
-
top_expect = top_kind ? JW_KEY_OR_CLOSE : JW_VALUE_OR_CLOSE;
|
|
770
|
-
key_slot = top_kind ? 1 : 0;
|
|
771
|
-
kind[depth] = top_kind;
|
|
772
|
-
open_at[depth] = top_open;
|
|
773
|
-
depth++;
|
|
774
|
-
i = at + 1;
|
|
775
|
-
continue;
|
|
803
|
+
i = k;
|
|
804
|
+
goto lmapafter;
|
|
776
805
|
}
|
|
777
806
|
if (c == 't' || c == 'f' || c == 'n') {
|
|
778
807
|
size_t wl = c == 'f' ? 5 : 4;
|
|
779
|
-
if (
|
|
808
|
+
if (i + wl > len) {
|
|
780
809
|
goto lreject;
|
|
781
810
|
}
|
|
782
811
|
uint32_t got4;
|
|
783
|
-
memcpy(&got4, p +
|
|
812
|
+
memcpy(&got4, p + i, 4);
|
|
784
813
|
if (got4 != (c == 't' ? 0x65757274u /* "true" */
|
|
785
814
|
: c == 'n' ? 0x6C6C756Eu /* "null" */
|
|
786
815
|
: 0x736C6166u /* "fals" */) ||
|
|
787
|
-
(c == 'f' && p[
|
|
816
|
+
(c == 'f' && p[i + 4] != 'e')) {
|
|
788
817
|
goto lreject;
|
|
789
818
|
}
|
|
790
|
-
if (
|
|
791
|
-
char z = p[
|
|
819
|
+
if (i + wl < len) {
|
|
820
|
+
char z = p[i + wl];
|
|
792
821
|
if (z != ' ' && z != '\t' && z != '\n' && z != '\r' && z != ',' && z != ']' &&
|
|
793
822
|
z != '}' && z != ':') {
|
|
794
823
|
goto lreject;
|
|
795
824
|
}
|
|
796
825
|
}
|
|
797
|
-
recs[count] = ((uint64_t)((uint32_t)
|
|
826
|
+
recs[count] = ((uint64_t)((uint32_t)i) << 32) | ((uint64_t)((uint32_t)wl) << 8) |
|
|
798
827
|
(uint64_t)(c == 'n' ? YEP_T_NULL : (c == 't' ? YEP_T_TRUE : YEP_T_FALSE));
|
|
799
828
|
count++;
|
|
800
|
-
i
|
|
801
|
-
goto
|
|
829
|
+
i += wl;
|
|
830
|
+
goto lmapafter;
|
|
831
|
+
}
|
|
832
|
+
if (c == '{') {
|
|
833
|
+
LPUSH(1);
|
|
834
|
+
goto lmap1;
|
|
835
|
+
}
|
|
836
|
+
if (c == '[') {
|
|
837
|
+
LPUSH(0);
|
|
838
|
+
goto lseq1;
|
|
802
839
|
}
|
|
803
840
|
goto lreject;
|
|
804
841
|
}
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
842
|
+
|
|
843
|
+
lmapafter:
|
|
844
|
+
LWS();
|
|
845
|
+
if (p[i] == ',') {
|
|
846
|
+
i++;
|
|
847
|
+
goto lmap;
|
|
848
|
+
}
|
|
849
|
+
if (p[i] == '}') {
|
|
850
|
+
LCLOSE();
|
|
851
|
+
}
|
|
852
|
+
goto lreject;
|
|
853
|
+
|
|
854
|
+
/* The sequence member cycle — the same single-region shape. */
|
|
855
|
+
lseq1: /* [] closes here */
|
|
856
|
+
LWS();
|
|
857
|
+
if (p[i] == ']') {
|
|
858
|
+
LCLOSE();
|
|
859
|
+
}
|
|
860
|
+
goto lseqval;
|
|
861
|
+
|
|
862
|
+
lseq: /* a member MUST follow (after ','): JW_VALUE */
|
|
863
|
+
LWS();
|
|
864
|
+
lseqval: {
|
|
865
|
+
char c = p[i];
|
|
866
|
+
if (c == '"') {
|
|
867
|
+
LSTR_SCAN(lseqafter);
|
|
868
|
+
}
|
|
869
|
+
if ((unsigned)(c - '0') <= 9u || c == '-') {
|
|
870
|
+
size_t k = i + 1;
|
|
871
|
+
while (k < len) {
|
|
872
|
+
char d = p[k];
|
|
873
|
+
if ((d >= '0' && d <= '9') || d == '-' || d == '+' || d == '.' || d == 'e' ||
|
|
874
|
+
d == 'E') {
|
|
875
|
+
k++;
|
|
876
|
+
continue;
|
|
877
|
+
}
|
|
878
|
+
break;
|
|
810
879
|
}
|
|
811
|
-
|
|
880
|
+
recs[count] = ((uint64_t)((uint32_t)i) << 32) | ((uint64_t)((uint32_t)(k - i)) << 8) |
|
|
881
|
+
(uint64_t)(YEP_T_NUM);
|
|
882
|
+
count++;
|
|
883
|
+
i = k;
|
|
884
|
+
goto lseqafter;
|
|
885
|
+
}
|
|
886
|
+
if (c == 't' || c == 'f' || c == 'n') {
|
|
887
|
+
size_t wl = c == 'f' ? 5 : 4;
|
|
888
|
+
if (i + wl > len) {
|
|
889
|
+
goto lreject;
|
|
890
|
+
}
|
|
891
|
+
uint32_t got4;
|
|
892
|
+
memcpy(&got4, p + i, 4);
|
|
893
|
+
if (got4 != (c == 't' ? 0x65757274u /* "true" */
|
|
894
|
+
: c == 'n' ? 0x6C6C756Eu /* "null" */
|
|
895
|
+
: 0x736C6166u /* "fals" */) ||
|
|
896
|
+
(c == 'f' && p[i + 4] != 'e')) {
|
|
812
897
|
goto lreject;
|
|
813
898
|
}
|
|
899
|
+
if (i + wl < len) {
|
|
900
|
+
char z = p[i + wl];
|
|
901
|
+
if (z != ' ' && z != '\t' && z != '\n' && z != '\r' && z != ',' && z != ']' &&
|
|
902
|
+
z != '}' && z != ':') {
|
|
903
|
+
goto lreject;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
recs[count] = ((uint64_t)((uint32_t)i) << 32) | ((uint64_t)((uint32_t)wl) << 8) |
|
|
907
|
+
(uint64_t)(c == 'n' ? YEP_T_NULL : (c == 't' ? YEP_T_TRUE : YEP_T_FALSE));
|
|
908
|
+
count++;
|
|
909
|
+
i += wl;
|
|
910
|
+
goto lseqafter;
|
|
911
|
+
}
|
|
912
|
+
if (c == '{') {
|
|
913
|
+
LPUSH(1);
|
|
914
|
+
goto lmap1;
|
|
915
|
+
}
|
|
916
|
+
if (c == '[') {
|
|
917
|
+
LPUSH(0);
|
|
918
|
+
goto lseq1;
|
|
919
|
+
}
|
|
920
|
+
goto lreject;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
lseqafter:
|
|
924
|
+
LWS();
|
|
925
|
+
if (p[i] == ',') {
|
|
926
|
+
i++;
|
|
927
|
+
goto lseq;
|
|
814
928
|
}
|
|
929
|
+
if (p[i] == ']') {
|
|
930
|
+
LCLOSE();
|
|
931
|
+
}
|
|
932
|
+
goto lreject;
|
|
933
|
+
|
|
934
|
+
ldone:
|
|
935
|
+
#undef LWS
|
|
936
|
+
#undef LPUSH
|
|
937
|
+
#undef LCLOSE
|
|
938
|
+
#undef LSTR_SCAN
|
|
939
|
+
|
|
940
|
+
{
|
|
941
|
+
size_t tail = i;
|
|
942
|
+
while (tail < len &&
|
|
943
|
+
(p[tail] == ' ' || p[tail] == '\t' || p[tail] == '\n' || p[tail] == '\r')) {
|
|
944
|
+
tail++;
|
|
945
|
+
}
|
|
946
|
+
if (tail != len) {
|
|
947
|
+
goto lreject;
|
|
948
|
+
}
|
|
949
|
+
}
|
|
815
950
|
t->count = count;
|
|
816
951
|
t->_src = p;
|
|
817
952
|
t->_srclen = len;
|
|
@@ -1044,6 +1179,243 @@ reject:
|
|
|
1044
1179
|
return YEPTRIS_ERROR_PARSE;
|
|
1045
1180
|
}
|
|
1046
1181
|
|
|
1182
|
+
/* The span walk, single-pass edition: the classifier writes per-block
|
|
1183
|
+
* masks (no idx array, no emission loop), and this walk derives each
|
|
1184
|
+
* block's token mask in registers and dispatches straight off the set
|
|
1185
|
+
* bits. Numbers/keywords have no entry — a pending scalar occupies
|
|
1186
|
+
* [val_start, next token) and is recorded (with its charset
|
|
1187
|
+
* validation) when the next token arrives. String closes come from a
|
|
1188
|
+
* backward quote scan over a few bytes. Escape-carrying documents
|
|
1189
|
+
* never reach here (the route sends them to the validating fused
|
|
1190
|
+
* walk), so the fast path never scans string content. Same
|
|
1191
|
+
* accept/reject contract as the fused lenient walk (the differential
|
|
1192
|
+
* suite pins both). */
|
|
1193
|
+
static YEP_UNUSED_FN YeptrisStatus tape_walk_lnt_span(const char* p, size_t len, size_t open,
|
|
1194
|
+
const struct yep_s1_block* blocks,
|
|
1195
|
+
size_t nblocks, yeptris_json_tape* t) {
|
|
1196
|
+
if (tape_carve(t, len) != YEPTRIS_OK) {
|
|
1197
|
+
return YEPTRIS_ERROR_MEMORY;
|
|
1198
|
+
}
|
|
1199
|
+
t->_rec_primary = 1;
|
|
1200
|
+
yeptris_tape_rec* recs = t->recs;
|
|
1201
|
+
uint32_t open_at[YEP_JSON_WALK_DEPTH];
|
|
1202
|
+
uint8_t kind[YEP_JSON_WALK_DEPTH];
|
|
1203
|
+
|
|
1204
|
+
recs[0] = ((uint64_t)0 << 32) | ((uint64_t)0 << 8) | YEP_T_DOC;
|
|
1205
|
+
uint8_t top_kind = p[open] == '[' ? 0 : 1;
|
|
1206
|
+
recs[1] =
|
|
1207
|
+
((uint64_t)0 << 32) | ((uint64_t)0 << 8) | (top_kind ? YEP_T_MAP_OPEN : YEP_T_SEQ_OPEN);
|
|
1208
|
+
uint32_t top_open = 1;
|
|
1209
|
+
size_t count = 2;
|
|
1210
|
+
uint8_t top_expect = top_kind ? JW_KEY_OR_CLOSE : JW_VALUE_OR_CLOSE;
|
|
1211
|
+
int key_slot = top_kind ? 1 : 0;
|
|
1212
|
+
int depth = 1;
|
|
1213
|
+
open_at[0] = top_open;
|
|
1214
|
+
kind[0] = top_kind;
|
|
1215
|
+
|
|
1216
|
+
size_t bi = 0;
|
|
1217
|
+
uint64_t tokens = 0;
|
|
1218
|
+
size_t off = 0;
|
|
1219
|
+
size_t val_start = open + 1;
|
|
1220
|
+
size_t pos = 0;
|
|
1221
|
+
for (;;) {
|
|
1222
|
+
while (tokens == 0) {
|
|
1223
|
+
if (bi >= nblocks) {
|
|
1224
|
+
goto reject; /* EOF mid-structure (the root never closed) */
|
|
1225
|
+
}
|
|
1226
|
+
off = (size_t)bi * 64;
|
|
1227
|
+
tokens = blocks[bi].tokens;
|
|
1228
|
+
bi++;
|
|
1229
|
+
}
|
|
1230
|
+
pos = off + (size_t)yep_ctz64(tokens);
|
|
1231
|
+
tokens &= tokens - 1;
|
|
1232
|
+
if (pos == open) {
|
|
1233
|
+
continue; /* the root opener: recs[1] already carries it */
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
/* the pending scalar (numbers/keywords only — a quote would be
|
|
1237
|
+
* a token): [val_start, pos) with trailing ws trimmed. All-ws
|
|
1238
|
+
* residue is harmless; a required value/key is satisfied by a
|
|
1239
|
+
* quote entry (the string arm) or a container. */
|
|
1240
|
+
if (val_start < pos) {
|
|
1241
|
+
size_t end = pos;
|
|
1242
|
+
while (end > val_start && (p[end - 1] == ' ' || p[end - 1] == '\t' ||
|
|
1243
|
+
p[end - 1] == '\n' || p[end - 1] == '\r')) {
|
|
1244
|
+
end--;
|
|
1245
|
+
}
|
|
1246
|
+
size_t vs = val_start;
|
|
1247
|
+
while (vs < end && (p[vs] == ' ' || p[vs] == '\t' || p[vs] == '\n' || p[vs] == '\r')) {
|
|
1248
|
+
vs++;
|
|
1249
|
+
}
|
|
1250
|
+
if (vs < end) {
|
|
1251
|
+
char h = p[vs];
|
|
1252
|
+
if (top_expect != JW_VALUE && top_expect != JW_VALUE_OR_CLOSE) {
|
|
1253
|
+
goto reject; /* bytes where no value may start: {x} [1 2] */
|
|
1254
|
+
}
|
|
1255
|
+
if (h == 't' || h == 'f' || h == 'n') {
|
|
1256
|
+
size_t wl = h == 'f' ? 5 : 4;
|
|
1257
|
+
if (end - vs != wl || memcmp(p + vs,
|
|
1258
|
+
h == 't' ? "true"
|
|
1259
|
+
: h == 'n' ? "null"
|
|
1260
|
+
: "false",
|
|
1261
|
+
wl) != 0) {
|
|
1262
|
+
goto reject;
|
|
1263
|
+
}
|
|
1264
|
+
recs[count] =
|
|
1265
|
+
((uint64_t)((uint32_t)vs) << 32) | ((uint64_t)((uint32_t)wl) << 8) |
|
|
1266
|
+
(uint64_t)(h == 'n' ? YEP_T_NULL : (h == 't' ? YEP_T_TRUE : YEP_T_FALSE));
|
|
1267
|
+
count++;
|
|
1268
|
+
} else {
|
|
1269
|
+
if (!((unsigned)(h - '0') <= 9u || h == '-')) {
|
|
1270
|
+
goto reject;
|
|
1271
|
+
}
|
|
1272
|
+
for (size_t k = vs; k < end; k++) {
|
|
1273
|
+
char d = p[k];
|
|
1274
|
+
if ((d < '0' || d > '9') && d != '-' && d != '+' && d != '.' && d != 'e' &&
|
|
1275
|
+
d != 'E') {
|
|
1276
|
+
goto reject;
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
recs[count] = ((uint64_t)((uint32_t)vs) << 32) |
|
|
1280
|
+
((uint64_t)((uint32_t)(end - vs)) << 8) | (uint64_t)(YEP_T_NUM);
|
|
1281
|
+
count++;
|
|
1282
|
+
}
|
|
1283
|
+
top_expect = JW_COMMA_OR_CLOSE;
|
|
1284
|
+
key_slot = 0;
|
|
1285
|
+
} else if ((top_expect == JW_VALUE || top_expect == JW_KEY) &&
|
|
1286
|
+
(p[pos] != '"' && p[pos] != '{' && p[pos] != '[')) {
|
|
1287
|
+
goto reject; /* a value/key was required: [1,] {"a":} */
|
|
1288
|
+
}
|
|
1289
|
+
val_start = pos;
|
|
1290
|
+
} else if ((top_expect == JW_VALUE || top_expect == JW_KEY) &&
|
|
1291
|
+
(p[pos] != '"' && p[pos] != '{' && p[pos] != '[')) {
|
|
1292
|
+
goto reject; /* a value/key was required and none started */
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
{
|
|
1296
|
+
char c = p[pos];
|
|
1297
|
+
if (c == '"') {
|
|
1298
|
+
size_t close = 0;
|
|
1299
|
+
if (top_expect == JW_COMMA_OR_CLOSE || top_expect == JW_COLON) {
|
|
1300
|
+
goto reject; /* ["a" "b"] — no punct between values */
|
|
1301
|
+
}
|
|
1302
|
+
size_t end = (tokens != 0) ? off + (size_t)yep_ctz64(tokens) : 0;
|
|
1303
|
+
if (end == 0) {
|
|
1304
|
+
size_t b2 = bi;
|
|
1305
|
+
while (b2 < nblocks && blocks[b2].q == 0 && blocks[b2].op == 0) {
|
|
1306
|
+
b2++;
|
|
1307
|
+
}
|
|
1308
|
+
end = (b2 < nblocks) ? b2 * 64 : len;
|
|
1309
|
+
uint64_t m = blocks[b2].q | blocks[b2].op;
|
|
1310
|
+
if (b2 < nblocks && m != 0) {
|
|
1311
|
+
end = b2 * 64 + (size_t)yep_ctz64(m);
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
/* end may be the close quote itself (the raw q mask
|
|
1315
|
+
* feeds the forward position), so the scan includes it */
|
|
1316
|
+
for (size_t k = end + 1; k-- > pos + 1;) {
|
|
1317
|
+
if (p[k] == '"') {
|
|
1318
|
+
close = k;
|
|
1319
|
+
break;
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
if (close == 0) {
|
|
1323
|
+
goto reject;
|
|
1324
|
+
}
|
|
1325
|
+
recs[count] = ((uint64_t)((uint32_t)(pos + 1)) << 32) |
|
|
1326
|
+
((uint64_t)((uint32_t)(close - pos - 1)) << 8) |
|
|
1327
|
+
(uint64_t)(YEP_T_STR);
|
|
1328
|
+
count++;
|
|
1329
|
+
val_start = close + 1;
|
|
1330
|
+
if (key_slot) {
|
|
1331
|
+
top_expect = JW_COLON;
|
|
1332
|
+
} else {
|
|
1333
|
+
top_expect = JW_COMMA_OR_CLOSE;
|
|
1334
|
+
}
|
|
1335
|
+
continue;
|
|
1336
|
+
}
|
|
1337
|
+
if (c == ':') {
|
|
1338
|
+
if (top_expect != JW_COLON) {
|
|
1339
|
+
goto reject;
|
|
1340
|
+
}
|
|
1341
|
+
top_expect = JW_VALUE;
|
|
1342
|
+
key_slot = 0;
|
|
1343
|
+
val_start = pos + 1;
|
|
1344
|
+
continue;
|
|
1345
|
+
}
|
|
1346
|
+
if (c == ',') {
|
|
1347
|
+
if (top_expect != JW_COMMA_OR_CLOSE) {
|
|
1348
|
+
goto reject;
|
|
1349
|
+
}
|
|
1350
|
+
top_expect = top_kind ? JW_KEY : JW_VALUE;
|
|
1351
|
+
key_slot = top_kind ? 1 : 0;
|
|
1352
|
+
val_start = pos + 1;
|
|
1353
|
+
continue;
|
|
1354
|
+
}
|
|
1355
|
+
if (c == ']' || c == '}') {
|
|
1356
|
+
int want = c == ']' ? 0 : 1;
|
|
1357
|
+
if (top_kind != want ||
|
|
1358
|
+
(top_expect != JW_VALUE_OR_CLOSE && top_expect != JW_KEY_OR_CLOSE &&
|
|
1359
|
+
top_expect != JW_COMMA_OR_CLOSE)) {
|
|
1360
|
+
goto reject;
|
|
1361
|
+
}
|
|
1362
|
+
recs[count] = ((uint64_t)top_open << 32) | ((uint64_t)0 << 8) | YEP_T_CLOSE;
|
|
1363
|
+
recs[top_open] = (recs[top_open] & ~(uint64_t)0xFFFFFFFF00000000u) |
|
|
1364
|
+
((uint64_t)(uint32_t)count << 32);
|
|
1365
|
+
count++;
|
|
1366
|
+
depth--;
|
|
1367
|
+
if (depth == 0) {
|
|
1368
|
+
break;
|
|
1369
|
+
}
|
|
1370
|
+
top_kind = kind[depth - 1];
|
|
1371
|
+
top_expect = JW_COMMA_OR_CLOSE;
|
|
1372
|
+
top_open = open_at[depth - 1];
|
|
1373
|
+
key_slot = 0;
|
|
1374
|
+
val_start = pos + 1;
|
|
1375
|
+
continue;
|
|
1376
|
+
}
|
|
1377
|
+
if (c == '{' || c == '[') {
|
|
1378
|
+
if (depth >= YEP_JSON_WALK_DEPTH || key_slot || top_expect == JW_COMMA_OR_CLOSE ||
|
|
1379
|
+
top_expect == JW_COLON) {
|
|
1380
|
+
goto reject;
|
|
1381
|
+
}
|
|
1382
|
+
kind[depth - 1] = top_kind;
|
|
1383
|
+
open_at[depth - 1] = top_open;
|
|
1384
|
+
top_kind = c == '[' ? 0 : 1;
|
|
1385
|
+
recs[count] = ((uint64_t)0 << 32) | ((uint64_t)0 << 8) |
|
|
1386
|
+
(uint64_t)(c == '[' ? YEP_T_SEQ_OPEN : YEP_T_MAP_OPEN);
|
|
1387
|
+
top_open = (uint32_t)count;
|
|
1388
|
+
count++;
|
|
1389
|
+
top_expect = top_kind ? JW_KEY_OR_CLOSE : JW_VALUE_OR_CLOSE;
|
|
1390
|
+
key_slot = top_kind ? 1 : 0;
|
|
1391
|
+
kind[depth] = top_kind;
|
|
1392
|
+
open_at[depth] = top_open;
|
|
1393
|
+
depth++;
|
|
1394
|
+
val_start = pos + 1;
|
|
1395
|
+
continue;
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
goto reject;
|
|
1399
|
+
}
|
|
1400
|
+
/* trailing residue: after the root close, only ws may follow */
|
|
1401
|
+
size_t last = pos + 1;
|
|
1402
|
+
while (last < len &&
|
|
1403
|
+
(p[last] == ' ' || p[last] == '\t' || p[last] == '\n' || p[last] == '\r')) {
|
|
1404
|
+
last++;
|
|
1405
|
+
}
|
|
1406
|
+
if (last != len) {
|
|
1407
|
+
goto reject;
|
|
1408
|
+
}
|
|
1409
|
+
t->count = count;
|
|
1410
|
+
t->_src = p;
|
|
1411
|
+
t->_srclen = len;
|
|
1412
|
+
return YEPTRIS_OK;
|
|
1413
|
+
|
|
1414
|
+
reject:
|
|
1415
|
+
yeptris_tape_free(t);
|
|
1416
|
+
return YEPTRIS_ERROR_PARSE;
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1047
1419
|
YEPTRIS_API YeptrisStatus yeptris_parse_json_tape_lenient(const char* source, size_t len,
|
|
1048
1420
|
yeptris_json_tape* tape) {
|
|
1049
1421
|
if ((source == NULL && len != 0) || tape == NULL) {
|
|
@@ -1075,21 +1447,24 @@ YEPTRIS_API YeptrisStatus yeptris_parse_json_tape_lenient(const char* source, si
|
|
|
1075
1447
|
}
|
|
1076
1448
|
|
|
1077
1449
|
if (source[at] == '[' || source[at] == '{') {
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
*
|
|
1081
|
-
|
|
1082
|
-
|
|
1450
|
+
/* the span route: per-block classification + the register-token
|
|
1451
|
+
* walk — no idx array, no emission loop, content bytes never
|
|
1452
|
+
* forward-scanned. Escape-carrying documents (validation needs
|
|
1453
|
+
* the kernel) and C0-in-string ride the fused walk, which
|
|
1454
|
+
* delivers today's verdicts byte for byte. */
|
|
1455
|
+
struct yep_s1_block* blocks = malloc((len / 64 + 2) * sizeof(struct yep_s1_block));
|
|
1456
|
+
if (blocks == NULL) {
|
|
1083
1457
|
return YEPTRIS_ERROR_MEMORY;
|
|
1084
1458
|
}
|
|
1085
|
-
size_t
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1459
|
+
size_t nblocks = 0;
|
|
1460
|
+
unsigned flags = 0;
|
|
1461
|
+
if (yep_text_active()->json_stage1_masks(source, len, blocks, &nblocks, &flags) &&
|
|
1462
|
+
(flags & (YEP_S1_C0_IN_STRING | YEP_S1_HAS_ESCAPE)) == 0) {
|
|
1463
|
+
YeptrisStatus st = tape_walk_lnt_span(source, len, at, blocks, nblocks, tape);
|
|
1464
|
+
free(blocks);
|
|
1089
1465
|
return st;
|
|
1090
1466
|
}
|
|
1091
|
-
free(
|
|
1092
|
-
#endif
|
|
1467
|
+
free(blocks);
|
|
1093
1468
|
return yep_tape_walk_lenient_fused(source, len, at, tape);
|
|
1094
1469
|
}
|
|
1095
1470
|
|
|
@@ -1194,7 +1569,8 @@ YEPTRIS_API YeptrisStatus yeptris_parse_json_tape(const char* source, size_t len
|
|
|
1194
1569
|
return YEPTRIS_ERROR_MEMORY;
|
|
1195
1570
|
}
|
|
1196
1571
|
size_t nidx = 0;
|
|
1197
|
-
|
|
1572
|
+
unsigned sflags = 0;
|
|
1573
|
+
if (yep_text_active()->json_stage1(source, len, idx, &nidx, &sflags)) {
|
|
1198
1574
|
YeptrisStatus st = tape_walk_idx(source, len, off, idx, nidx, tape);
|
|
1199
1575
|
free(idx);
|
|
1200
1576
|
if (st != YEPTRIS_ERROR_PARSE) {
|