yeptris 0.6.21.1-arm-linux-eabihf → 0.6.23.1-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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0f28d08ec5958231b1fe465347ed53ea2f03dc51d3012f49501c2b0b0c425439
4
- data.tar.gz: afe0d37786ef93cbcfcae545b7095dc76668a9fae7ddd8f3099c3df6c9655178
3
+ metadata.gz: 627e70bedb0bd290674f8a94d08ad53c68e48cf60b5752783b6d8db3391921d3
4
+ data.tar.gz: 79403cdb0ce605fd4d79777291e02274afb041200f9f5b7d8972538442a29a31
5
5
  SHA512:
6
- metadata.gz: a6d8196d4017395748fef1170e4d7dd3ee6a0c2dd3e246d17d170ddd5b1dfb7b40b272fbf5d0f459c47e6eefd0599c752b038b3db9adbd89e310f54662db06f9
7
- data.tar.gz: 2e57246545fa63e30626aa16b2ea60b6da89b3fff8802de16e6d5dee38bd6df97297dff7e9f9c8cf6244bfb614e94bf40702316fc54664f3d9daaf2231d4b4c1
6
+ metadata.gz: 1512bd1736078082f3de2a1c07afc42c998ba53a5204fb2073a8c3f49510231c42deb96322cf92ac16764df6c24eeaa7b02fad5cfc0113bdefbd97beb039355a
7
+ data.tar.gz: 44c9e72d06b689ce1e18e4b2283421f99d20ee9b89a076a1e0439d91d0b0254cae04a819334c6b63a3ba49d686efe57eef39871dce52f36a36cfb5301c67fbf1
data/lib/yeptris.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module Yeptris
4
4
  # The gem's version lives in the parent namespace's file — the last
5
5
  # internal require (yeptris/version) retired with it.
6
- VERSION = "0.6.21.1".freeze
6
+ VERSION = "0.6.23.1".freeze
7
7
 
8
8
  # Informational notices are OPT-IN (yeptris-ruby#217): consumers
9
9
  # embed yeptris inside CLIs that assert clean stderr, and a
data/libyeptris.so CHANGED
Binary file
@@ -3,7 +3,7 @@
3
3
  cmake_minimum_required(VERSION 3.20)
4
4
 
5
5
  project(yeptris
6
- VERSION 0.6.21
6
+ VERSION 0.6.23
7
7
  DESCRIPTION "Ultra-fast YAML 1.2 parser, emitter and streamer in C"
8
8
  LANGUAGES C CXX
9
9
  )
@@ -28,8 +28,13 @@ int yep_style_plain_safe(const char* p, uint32_t len) {
28
28
  case '-':
29
29
  case '?':
30
30
  /* indicators only before a blank or EOL: "-5" and "?x" are
31
- * plain (libyaml emits negative numbers plain; Psych, too) */
32
- return !(len == 1 || is_blank(p[1]));
31
+ * plain (libyaml emits negative numbers plain; Psych, too) —
32
+ * but fall through: the document-marker check below owns
33
+ * the bare "---"/"..." (libyaml quotes those) */
34
+ if (len == 1 || is_blank(p[1])) {
35
+ return 0;
36
+ }
37
+ break;
33
38
  case ',':
34
39
  case '[':
35
40
  case ']':
@@ -50,20 +55,67 @@ int yep_style_plain_safe(const char* p, uint32_t len) {
50
55
  default:
51
56
  break;
52
57
  }
53
- for (uint32_t i = 0; i < len; i++) {
54
- char c = p[i];
55
- if (is_break(c) || c == '\t') {
56
- return 0;
57
- }
58
- if (c == ':') {
59
- if (i + 1 >= len || is_blank(p[i + 1])) {
58
+ /* The interior scan in SWAR words: every reject condition is a
59
+ * byte-class adjacency, so one masked word test is exact —
60
+ * break/tab bytes reject directly; ':' rejects with a blank at its
61
+ * NEXT lane (or the span's EOL); '#' with a blank at its PREVIOUS
62
+ * lane (the span's first byte is exempt — the head switch already
63
+ * handled a leading '#'). Cross-word adjacency rides one carried
64
+ * byte per boundary; the tail runs the byte loop, whose rules read
65
+ * real neighbors and need no carries. */
66
+ {
67
+ const uint64_t ONES = 0x0101010101010101ull;
68
+ const uint64_t HIGH = 0x8080808080808080ull;
69
+ #define YST_ZDET(w, ch) \
70
+ ((((w) ^ (uint64_t)(ch) * ONES) - ONES) & ~((w) ^ (uint64_t)(ch) * ONES) & HIGH)
71
+ uint32_t i = 0;
72
+ int prev_blank7 = 0;
73
+ while (i + 8 <= len) {
74
+ uint64_t w;
75
+ memcpy(&w, p + i, 8);
76
+ uint64_t space = YST_ZDET(w, ' ');
77
+ uint64_t tab = YST_ZDET(w, '\t');
78
+ uint64_t blank = space | tab;
79
+ uint64_t colon = YST_ZDET(w, ':');
80
+ uint64_t hash = YST_ZDET(w, '#');
81
+ /* tab and the breaks reject outright */
82
+ if (tab | YST_ZDET(w, '\n') | YST_ZDET(w, '\r')) {
60
83
  return 0;
61
84
  }
85
+ /* ':' + blank next: (blank >> 8) pulls lane i+1's flag down
86
+ * into lane i; the word's last lane takes the peeked byte
87
+ * (EOL at the span end counts as blank — the rule rejects
88
+ * there) */
89
+ if (colon) {
90
+ int next_blank = i + 8 < len ? is_blank(p[i + 8]) : 1;
91
+ if (colon & ((blank >> 8) | (next_blank ? (uint64_t)0x80 << 56 : 0))) {
92
+ return 0;
93
+ }
94
+ }
95
+ /* '#' + blank prev: (blank << 8) lifts lane i-1's flag up
96
+ * into lane i; lane 0 takes the carried last-lane flag */
97
+ if (hash && (hash & ((blank << 8) | (prev_blank7 ? 0x80 : 0)))) {
98
+ return 0;
99
+ }
100
+ prev_blank7 = (int)((blank >> 63) & 1); /* lane 7's flag is its top bit */
101
+ i += 8;
62
102
  }
63
- if (c == '#') {
64
- if (i > 0 && is_blank(p[i - 1])) {
103
+ #undef YST_ZDET
104
+ for (; i < len; i++) {
105
+ char c = p[i];
106
+ if (is_break(c) || c == '\t') {
65
107
  return 0;
66
108
  }
109
+ if (c == ':') {
110
+ if (i + 1 >= len || is_blank(p[i + 1])) {
111
+ return 0;
112
+ }
113
+ }
114
+ if (c == '#') {
115
+ if (i > 0 && is_blank(p[i - 1])) {
116
+ return 0;
117
+ }
118
+ }
67
119
  }
68
120
  }
69
121
  /* document markers */
@@ -10,6 +10,10 @@
10
10
 
11
11
  #include <stdint.h>
12
12
 
13
+ #ifdef __cplusplus
14
+ extern "C" {
15
+ #endif
16
+
13
17
  /* A plain scalar may be re-emitted plain only when every byte is safe
14
18
  * in ANY position of a block context: no leading/trailing space, no
15
19
  * indicator first byte, no ": " / " #" inside, no tab, no break, and
@@ -21,4 +25,8 @@ int yep_style_plain_safe(const char* p, uint32_t len);
21
25
  * (plain_safe plus: no ':' at all unless followed by a non-blank). */
22
26
  int yep_style_plain_key_safe(const char* p, uint32_t len);
23
27
 
28
+ #ifdef __cplusplus
29
+ }
30
+ #endif
31
+
24
32
  #endif /* YEP_EMIT_STYLE_H */
@@ -2457,13 +2457,12 @@ static int e_classified(yep_engine* e, uint16_t floor_col) {
2457
2457
  }
2458
2458
  /* Whole-line fast path (TODO.restructure/54): the sink may build
2459
2459
  * the key and its classified value as one unit — no events. The
2460
- * value EVENT is prepared first (folded content, resolved alias,
2461
- * defined anchor: exactly what the chain below would emit), so a
2462
- * rejection emits key + prepared value unchanged. */
2463
- yep_event vv;
2464
- e_event_init(&vv, YEP_EV_SCALAR);
2465
- vv.line = e->line;
2466
- vv.col = e_col(e, sh->val_start) + 1;
2460
+ * value EVENT is assembled ONLY on the fallback path (the sinks
2461
+ * that take the pair read the yep_block_value and ignore it): the
2462
+ * semantic helpers run unchanged (alias resolution, anchor
2463
+ * definition, the fold), the fallback reuses the pair facts
2464
+ * captured before the fold — e_plain_multiline advances
2465
+ * line/pos across continuations, so post-fold e_col would lie. */
2467
2466
  /* the pair facts are captured BEFORE the fold: e_plain_multiline
2468
2467
  * advances line/pos across continuations */
2469
2468
  uint32_t pair_line = e->line;
@@ -2471,6 +2470,18 @@ static int e_classified(yep_engine* e, uint16_t floor_col) {
2471
2470
  yep_block_value v;
2472
2471
  memset(&v, 0, sizeof(v));
2473
2472
  v.cls = (uint8_t)sh->val;
2473
+ yep_event vv; /* the fields the fallback reads are assigned HERE and
2474
+ * overwritten by the arms/helpers — MSVC C4701 cannot
2475
+ * see through the helpers' bypointer writes, so the
2476
+ * zero-init lives in this function, not a memset */
2477
+ vv.value.p = NULL;
2478
+ vv.value.len = 0;
2479
+ vv.borrowed = 0;
2480
+ vv.anchor.p = NULL;
2481
+ vv.anchor.len = 0;
2482
+ vv.anchor_id = 0;
2483
+ vv.end_line = 0;
2484
+ vv.end_col = 0;
2474
2485
  int prepared = 0;
2475
2486
  if (sh->val == YEP_LVAL_ALIAS) {
2476
2487
  e->pos = sh->val_start;
@@ -2497,8 +2508,6 @@ static int e_classified(yep_engine* e, uint16_t floor_col) {
2497
2508
  vv.value.p = e->p + sh->val_span.start;
2498
2509
  vv.value.len = sh->val_span.end - sh->val_span.start;
2499
2510
  vv.borrowed = 1;
2500
- vv.style = YEP_STYLE_PLAIN;
2501
- vv.implicit = 1;
2502
2511
  e->pos = sh->val_span.end;
2503
2512
  if (e_plain_multiline(e, sh->val_span, key_col, &vv, 0) != 0) {
2504
2513
  return -1;
@@ -2523,9 +2532,30 @@ static int e_classified(yep_engine* e, uint16_t floor_col) {
2523
2532
  return 1;
2524
2533
  }
2525
2534
  }
2535
+ /* Fallback: assemble the value event with the helper-filled
2536
+ * fields preserved — e_alias stamps type=ALIAS + the end marks,
2537
+ * e_plain_multiline stamps the fold end marks; the pair facts
2538
+ * taken pre-fold (post-fold e_col would read the advanced
2539
+ * line/pos). Field-for-field what the pre-fill built. */
2540
+ yep_event ve;
2541
+ e_event_init(&ve, YEP_EV_SCALAR);
2542
+ ve.line = pair_line;
2543
+ ve.col = (uint32_t)pair_val_col + 1;
2544
+ ve.value = vv.value;
2545
+ ve.borrowed = vv.borrowed;
2546
+ ve.anchor = vv.anchor;
2547
+ ve.anchor_id = vv.anchor_id;
2548
+ ve.end_line = vv.end_line;
2549
+ ve.end_col = vv.end_col;
2550
+ if (sh->val == YEP_LVAL_ALIAS) {
2551
+ ve.type = YEP_EV_ALIAS;
2552
+ } else {
2553
+ ve.style = YEP_STYLE_PLAIN;
2554
+ ve.implicit = 1;
2555
+ }
2526
2556
  yep_event kv;
2527
2557
  e_key_event(e, sh, key_col, pair_line, &kv);
2528
- if (emit_now(e, &kv) != 0 || emit_now(e, &vv) != 0) {
2558
+ if (emit_now(e, &kv) != 0 || emit_now(e, &ve) != 0) {
2529
2559
  return -2;
2530
2560
  }
2531
2561
  return 1;
@@ -601,12 +601,49 @@ reject:
601
601
  * (the classify scan carries no accept/reject structure) and
602
602
  * yeptris_tape_convert owns validation. Everything else matches
603
603
  * tape_walk state for state. */
604
+ /* LNUM_RUN — the initial digit run of a number span: SWAR words, eight
605
+ * bytes per pass, with the byte loop below as tail and classifier.
606
+ * digit iff 0x30-0x39: a lane flags when (c+0x46) carries into bit7
607
+ * (c > '9'), when ((c|0x80)-0xB0) goes negative (c < '0'), or when the
608
+ * byte is non-ASCII — and since the all-digit prefix never borrows
609
+ * across lanes, the flags are exact up to the first non-digit, where
610
+ * the scan stops and the byte loop classifies what follows (the
611
+ * consumed-only digits_only law is untouched: the run sets saw_digit,
612
+ * nothing else). */
613
+ #define LNUM_RUN \
614
+ do { \
615
+ size_t ks_ = k; \
616
+ while (k + 8 <= len) { \
617
+ uint64_t w_; \
618
+ memcpy(&w_, p + k, 8); \
619
+ uint64_t nd_ = \
620
+ ((w_ + 0x4646464646464646ull) & 0x8080808080808080ull) | \
621
+ (((w_ | 0x8080808080808080ull) - 0xB0B0B0B0B0B0B0B0ull) & 0x8080808080808080ull) | \
622
+ (w_ & 0x8080808080808080ull); \
623
+ if (nd_ != 0) { \
624
+ k += (size_t)yep_ctz64(nd_) >> 3; \
625
+ break; \
626
+ } \
627
+ k += 8; \
628
+ } \
629
+ if (k > ks_) { \
630
+ saw_digit = 1; \
631
+ } \
632
+ } while (0)
633
+
604
634
  /* The strict RFC 8259 number check over one number-ish run — the
605
635
  * in-walk float/exp validator (the out-of-line number_shape call +
606
636
  * rescan was 13% of json-doc; the digits-only case never gets here).
607
637
  * One pass, no state machine words: sign, digits (leading-zero rule),
608
- * optional .digits, optional e[+-]digits, consume exactly len. */
609
- static int tape_num_ok(const char* p, size_t len) {
638
+ * optional .digits, optional e[+-]digits, consume exactly len.
639
+ * always_inline: the spans are 3-8 bytes and the out-of-line call was
640
+ * the cost (the rescan itself is nothing). */
641
+ #if defined(__GNUC__)
642
+ #define TAPE_NUM_OK_INLINE __attribute__((always_inline)) inline
643
+ #else
644
+ #define TAPE_NUM_OK_INLINE
645
+ #endif
646
+ static TAPE_NUM_OK_INLINE int tape_num_ok(const char* p, size_t len) {
610
647
  size_t k = 0;
611
648
  if (k < len && p[k] == '-') {
612
649
  k++;
@@ -770,6 +807,38 @@ YeptrisStatus yep_tape_walk_lenient_fused(const char* p, size_t len, size_t open
770
807
  i = cl_ + 1; \
771
808
  goto after; \
772
809
  } \
810
+ /* rounds 2-4 (up to 32 bytes inline): the email-class strings \
811
+ * close here without the quote_scan call and its redundant \
812
+ * content re-sweep; reached only when round 1 had no close, \
813
+ * so the short-string case pays nothing */ \
814
+ if ((qm_ | bm_ | c0_ | hi_) == 0) { \
815
+ size_t nr_ = (len - j_) >> 3; \
816
+ if (nr_ > 4) { \
817
+ nr_ = 4; \
818
+ } \
819
+ for (size_t r_ = 1; r_ < nr_; r_++) { \
820
+ size_t b2_ = j_ + (r_ << 3); \
821
+ memcpy(&w_, p + b2_, 8); \
822
+ qm_ = (w_ ^ 0x2222222222222222ull); \
823
+ bm_ = (w_ ^ 0x5C5C5C5C5C5C5C5Cull); \
824
+ qm_ = (qm_ - 0x0101010101010101ull) & ~qm_ & 0x8080808080808080ull; \
825
+ bm_ = (bm_ - 0x0101010101010101ull) & ~bm_ & 0x8080808080808080ull; \
826
+ c0_ = (w_ - 0x2020202020202020ull) & ~w_ & 0x8080808080808080ull; \
827
+ hi_ = cl ? (w_ & 0x8080808080808080ull) : 0; \
828
+ if (qm_ != 0 && ((bm_ | c0_ | hi_) & (qm_ - 1)) == 0) { \
829
+ size_t cl_ = b2_ + (size_t)yep_ctz64(qm_) / 8; \
830
+ recs[count] = ((uint64_t)((uint32_t)j_) << 32) | \
831
+ ((uint64_t)((uint32_t)(cl_ - j_)) << 8) | \
832
+ (uint64_t)(YEP_T_STR); \
833
+ count++; \
834
+ i = cl_ + 1; \
835
+ goto after; \
836
+ } \
837
+ if ((qm_ | bm_ | c0_ | hi_) != 0) { \
838
+ break; /* escape, c0 or hi: kernel authority */ \
839
+ } \
840
+ } \
841
+ } \
773
842
  } \
774
843
  { \
775
844
  const yep_text_kernels* kk_ = yep_text_active(); \
@@ -845,99 +914,132 @@ lmap1: /* {} closes here */
845
914
  goto lmapkey;
846
915
 
847
916
  lmap: /* a member MUST follow (after ','): JW_KEY — a closer rejects */
917
+ /* compact fast path: the byte is the key's quote already — LWS's
918
+ * loop would examine it once and exit */
919
+ if (i < len && p[i] == '"') {
920
+ goto lmapkey;
921
+ }
848
922
  LWS();
849
923
  if (p[i] != '"') {
850
924
  goto lreject;
851
925
  }
852
926
  lmapkey: { LSTR_SCAN(lmapcolon); }
853
927
  lmapcolon:
928
+ if (i < len && p[i] == ':') {
929
+ i++;
930
+ /* compact fast path: the value byte follows the colon with no
931
+ * whitespace — one load dispatches it (the ws test below is
932
+ * what LWS would run anyway) */
933
+ if (i < len) {
934
+ char v = p[i];
935
+ if (v != ' ' && v != '\n' && v != '\r' && (cl || v != '\t')) {
936
+ goto lmapval;
937
+ }
938
+ }
939
+ LWS();
940
+ goto lmapval;
941
+ }
854
942
  LWS();
855
943
  if (p[i] != ':') {
856
944
  goto lreject;
857
945
  }
858
946
  i++;
859
947
  LWS();
860
- {
861
- char c = p[i];
862
- if (c == '"') {
863
- LSTR_SCAN(lmapafter);
864
- }
865
- if ((unsigned)(c - '0') <= 9u || c == '-') {
866
- size_t k = i + 1;
867
- /* the digits-only tracking makes the pure-integer case a
868
- * 3-cycle leading-zero check — number_shape (a call + a
869
- * rescan, 13% of json-doc) runs only for dot/exp spans */
870
- int digits_only = 1, saw_digit = (c != '-');
871
- while (k < len) {
872
- char d = p[k];
873
- if ((unsigned)(d - '0') <= 9u) {
874
- k++;
875
- saw_digit = 1;
876
- continue;
877
- }
878
- digits_only = 0;
879
- if (d == '-' || d == '+' || d == '.' || d == 'e' || d == 'E') {
880
- k++;
881
- continue;
882
- }
883
- break;
948
+ lmapval: {
949
+ char c = p[i];
950
+ if (c == '"') {
951
+ LSTR_SCAN(lmapafter);
952
+ }
953
+ if ((unsigned)(c - '0') <= 9u || c == '-') {
954
+ size_t k = i + 1;
955
+ /* the digits-only tracking makes the pure-integer case a
956
+ * 3-cycle leading-zero check — number_shape (a call + a
957
+ * rescan, 13% of json-doc) runs only for dot/exp spans */
958
+ int digits_only = 1, saw_digit = (c != '-');
959
+ LNUM_RUN;
960
+ while (k < len) {
961
+ char d = p[k];
962
+ if ((unsigned)(d - '0') <= 9u) {
963
+ k++;
964
+ saw_digit = 1;
965
+ continue;
884
966
  }
885
- if (strict_nums) {
886
- int ok;
887
- if (digits_only && saw_digit) {
888
- size_t d0 = (c == '-') ? i + 1 : i;
889
- ok = (k - d0 == 1) || p[d0] != '0';
890
- } else {
891
- ok = tape_num_ok(p + i, (size_t)(k - i));
892
- }
893
- if (!ok) {
894
- goto lreject;
895
- }
967
+ /* the flag clears only on a CONSUMED byte: the run's
968
+ * terminator (',', '}', ']', whitespace) must leave
969
+ * digits_only intact, or every plain integer followed
970
+ * by a delimiter falls into the full validator */
971
+ if (d == '-' || d == '+' || d == '.' || d == 'e' || d == 'E') {
972
+ digits_only = 0;
973
+ k++;
974
+ continue;
896
975
  }
897
- recs[count] = ((uint64_t)((uint32_t)i) << 32) | ((uint64_t)((uint32_t)(k - i)) << 8) |
898
- (uint64_t)(YEP_T_NUM);
899
- count++;
900
- i = k;
901
- goto lmapafter;
976
+ break;
902
977
  }
903
- if (c == 't' || c == 'f' || c == 'n') {
904
- size_t wl = c == 'f' ? 5 : 4;
905
- if (i + wl > len) {
906
- goto lreject;
978
+ if (strict_nums) {
979
+ int ok;
980
+ if (digits_only && saw_digit) {
981
+ size_t d0 = (c == '-') ? i + 1 : i;
982
+ ok = (k - d0 == 1) || p[d0] != '0';
983
+ } else {
984
+ ok = tape_num_ok(p + i, (size_t)(k - i));
907
985
  }
908
- uint32_t got4;
909
- memcpy(&got4, p + i, 4);
910
- if (got4 != (c == 't' ? 0x65757274u /* "true" */
911
- : c == 'n' ? 0x6C6C756Eu /* "null" */
912
- : 0x736C6166u /* "fals" */) ||
913
- (c == 'f' && p[i + 4] != 'e')) {
986
+ if (!ok) {
914
987
  goto lreject;
915
988
  }
916
- if (i + wl < len) {
917
- char z = p[i + wl];
918
- if (z != ' ' && z != '\t' && z != '\n' && z != '\r' && z != ',' && z != ']' &&
919
- z != '}' && z != ':') {
920
- goto lreject;
921
- }
922
- }
923
- recs[count] = ((uint64_t)((uint32_t)i) << 32) | ((uint64_t)((uint32_t)wl) << 8) |
924
- (uint64_t)(c == 'n' ? YEP_T_NULL : (c == 't' ? YEP_T_TRUE : YEP_T_FALSE));
925
- count++;
926
- i += wl;
927
- goto lmapafter;
928
989
  }
929
- if (c == '{') {
930
- LPUSH(1);
931
- goto lmap1;
990
+ recs[count] = ((uint64_t)((uint32_t)i) << 32) | ((uint64_t)((uint32_t)(k - i)) << 8) |
991
+ (uint64_t)(YEP_T_NUM);
992
+ count++;
993
+ i = k;
994
+ goto lmapafter;
995
+ }
996
+ if (c == 't' || c == 'f' || c == 'n') {
997
+ size_t wl = c == 'f' ? 5 : 4;
998
+ if (i + wl > len) {
999
+ goto lreject;
932
1000
  }
933
- if (c == '[') {
934
- LPUSH(0);
935
- goto lseq1;
1001
+ uint32_t got4;
1002
+ memcpy(&got4, p + i, 4);
1003
+ if (got4 != (c == 't' ? 0x65757274u /* "true" */
1004
+ : c == 'n' ? 0x6C6C756Eu /* "null" */
1005
+ : 0x736C6166u /* "fals" */) ||
1006
+ (c == 'f' && p[i + 4] != 'e')) {
1007
+ goto lreject;
936
1008
  }
937
- goto lreject;
1009
+ if (i + wl < len) {
1010
+ char z = p[i + wl];
1011
+ if (z != ' ' && z != '\t' && z != '\n' && z != '\r' && z != ',' && z != ']' &&
1012
+ z != '}' && z != ':') {
1013
+ goto lreject;
1014
+ }
1015
+ }
1016
+ recs[count] = ((uint64_t)((uint32_t)i) << 32) | ((uint64_t)((uint32_t)wl) << 8) |
1017
+ (uint64_t)(c == 'n' ? YEP_T_NULL : (c == 't' ? YEP_T_TRUE : YEP_T_FALSE));
1018
+ count++;
1019
+ i += wl;
1020
+ goto lmapafter;
938
1021
  }
1022
+ if (c == '{') {
1023
+ LPUSH(1);
1024
+ goto lmap1;
1025
+ }
1026
+ if (c == '[') {
1027
+ LPUSH(0);
1028
+ goto lseq1;
1029
+ }
1030
+ goto lreject;
1031
+ }
939
1032
 
940
1033
  lmapafter:
1034
+ /* compact fast path: value ',' key directly — the two LWS hops the
1035
+ * general form runs both exit on byte one here */
1036
+ if (i < len && p[i] == ',') {
1037
+ i++;
1038
+ if (i < len && p[i] == '"') {
1039
+ goto lmapkey;
1040
+ }
1041
+ goto lmap;
1042
+ }
941
1043
  LWS();
942
1044
  if (p[i] == ',') {
943
1045
  i++;
@@ -966,6 +1068,7 @@ lseqval: {
966
1068
  if ((unsigned)(c - '0') <= 9u || c == '-') {
967
1069
  size_t k = i + 1;
968
1070
  int digits_only = 1, saw_digit = (c != '-');
1071
+ LNUM_RUN;
969
1072
  while (k < len) {
970
1073
  char d = p[k];
971
1074
  if ((unsigned)(d - '0') <= 9u) {
@@ -973,8 +1076,9 @@ lseqval: {
973
1076
  saw_digit = 1;
974
1077
  continue;
975
1078
  }
976
- digits_only = 0;
1079
+ /* consumed-only clearing: see the map arm's comment */
977
1080
  if (d == '-' || d == '+' || d == '.' || d == 'e' || d == 'E') {
1081
+ digits_only = 0;
978
1082
  k++;
979
1083
  continue;
980
1084
  }
@@ -1036,6 +1140,18 @@ lseqval: {
1036
1140
  }
1037
1141
 
1038
1142
  lseqafter:
1143
+ /* compact fast path: value ',' value directly — both LWS hops exit
1144
+ * on byte one here */
1145
+ if (i < len && p[i] == ',') {
1146
+ i++;
1147
+ if (i < len) {
1148
+ char v = p[i];
1149
+ if (v != ' ' && v != '\n' && v != '\r' && (cl || v != '\t')) {
1150
+ goto lseqval;
1151
+ }
1152
+ }
1153
+ goto lseq;
1154
+ }
1039
1155
  LWS();
1040
1156
  if (p[i] == ',') {
1041
1157
  i++;
@@ -1048,6 +1164,7 @@ lseqafter:
1048
1164
 
1049
1165
  ldone:
1050
1166
  #undef LWS
1167
+ #undef LNUM_RUN
1051
1168
  #undef LPUSH
1052
1169
  #undef LCLOSE
1053
1170
  #undef LSTR_SCAN
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yeptris
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.21.1
4
+ version: 0.6.23.1
5
5
  platform: arm-linux-eabihf
6
6
  authors:
7
7
  - Ribose Inc.