yeptris 0.6.22.1-aarch64-linux → 0.6.24.1-aarch64-linux
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/lib/yeptris/document.rb +10 -0
- data/lib/yeptris.rb +1 -1
- data/libyeptris.so +0 -0
- data/vendor/libyeptris/CMakeLists.txt +1 -1
- data/vendor/libyeptris/src/yeptris/emit/style.c +63 -11
- data/vendor/libyeptris/src/yeptris/emit/style.h +8 -0
- data/vendor/libyeptris/src/yeptris/events/values.c +5 -0
- data/vendor/libyeptris/src/yeptris/parse/engine.c +56 -13
- data/vendor/libyeptris/src/yeptris/parse/engine.h +7 -0
- data/vendor/libyeptris/src/yeptris/parse.c +6 -0
- data/vendor/libyeptris/src/yeptris/tape.c +146 -73
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 70a01a3cece0f9c86c27be214251080e6364e252faebbe66508713091663902e
|
|
4
|
+
data.tar.gz: 7152ae15236d42c54992c90f56ab473ace6594b97b3deb7c2c98b0bf83ff8a57
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a387cf0bf3570a28c1688391bf28b54205a532b7f4d39a30f1c9836afc2d30ce256b5b8087e8b4c92f6e70ceb352af7a01aadf8f914d65c7c5658d0ce9f3b7e9
|
|
7
|
+
data.tar.gz: 398160b717efdacf5682b0e4fe924ce220ba32b29ff4922b461382cbc07de8020232a7c9b6f83e8e5793e474c364bb5c779dc675035b906e32013abedb443b1e
|
data/lib/yeptris/document.rb
CHANGED
|
@@ -17,6 +17,16 @@ class Yeptris::Document
|
|
|
17
17
|
attr_reader :parse_schema
|
|
18
18
|
|
|
19
19
|
def initialize(c_ptr = nil, freed = Freed.new(:alive), parse_schema = :core_12)
|
|
20
|
+
# The pointer is produced by the FFI parse/create calls; a nil (or
|
|
21
|
+
# non-pointer) argument is an API misuse — Document.parse and
|
|
22
|
+
# Document.create are the entry points. Fail with that guidance
|
|
23
|
+
# instead of a NoMethodError from the finalizer guard below (the
|
|
24
|
+
# FFI::Pointer#null? probe does not exist on nil).
|
|
25
|
+
unless c_ptr.is_a?(::FFI::Pointer)
|
|
26
|
+
raise ArgumentError,
|
|
27
|
+
"a document FFI pointer is required — build documents with " \
|
|
28
|
+
"Yeptris::Document.parse or Yeptris::Document.create"
|
|
29
|
+
end
|
|
20
30
|
@c_ptr = c_ptr
|
|
21
31
|
@freed = freed
|
|
22
32
|
@parse_schema = parse_schema
|
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.
|
|
6
|
+
VERSION = "0.6.24.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
|
|
@@ -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
|
-
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
64
|
-
|
|
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 */
|
|
@@ -389,6 +389,11 @@ int yep_values_from_input(const char* yaml, size_t len, int schema_compat, yep_v
|
|
|
389
389
|
return -1;
|
|
390
390
|
}
|
|
391
391
|
yep_engine_set_resolver(eng, schema_compat ? yep_resolver_compat11() : yep_resolver_core12());
|
|
392
|
+
if (schema_compat) {
|
|
393
|
+
yep_engine_set_compat_grammar(eng, 1); /* libyaml grammar parity
|
|
394
|
+
* (the value drains ride the
|
|
395
|
+
* same compat contract) */
|
|
396
|
+
}
|
|
392
397
|
|
|
393
398
|
yep_value_ctx* c = ctx_create();
|
|
394
399
|
if (c == NULL) {
|
|
@@ -124,6 +124,13 @@ struct yep_engine {
|
|
|
124
124
|
int doc_inline; /* content node opened on the --- line */
|
|
125
125
|
uint16_t flow_floor; /* parent column of the current block-level flow */
|
|
126
126
|
int flow_enforce; /* flow continuation lines must out-indent it */
|
|
127
|
+
int compat_grammar; /* 11-COMPAT: libyaml/psych grammar parity —
|
|
128
|
+
* the flow indent floor (9C9N/VJP3) is a
|
|
129
|
+
* yaml-test-suite rule libyaml never
|
|
130
|
+
* enforced, and real-world locale files
|
|
131
|
+
* close multi-line flows at the parent's
|
|
132
|
+
* column; the floor stays on for the
|
|
133
|
+
* strict 1.2 engine the suite runs */
|
|
127
134
|
};
|
|
128
135
|
|
|
129
136
|
/* ------------------------------------------------------------ forwards */
|
|
@@ -2308,7 +2315,7 @@ static int e_shape_flow_value(yep_engine* e, const yep_line_shape* sh, uint16_t
|
|
|
2308
2315
|
yep_view none = {NULL, 0};
|
|
2309
2316
|
e->pos = sh->val_start;
|
|
2310
2317
|
e->flow_floor = floor;
|
|
2311
|
-
e->flow_enforce = (e->depth > 0);
|
|
2318
|
+
e->flow_enforce = (e->depth > 0) && !e->compat_grammar;
|
|
2312
2319
|
int fast = e_flow_json(e, none, none, 0);
|
|
2313
2320
|
e->flow_enforce = 0;
|
|
2314
2321
|
if (fast == -2) {
|
|
@@ -2457,13 +2464,12 @@ static int e_classified(yep_engine* e, uint16_t floor_col) {
|
|
|
2457
2464
|
}
|
|
2458
2465
|
/* Whole-line fast path (TODO.restructure/54): the sink may build
|
|
2459
2466
|
* the key and its classified value as one unit — no events. The
|
|
2460
|
-
* value EVENT is
|
|
2461
|
-
*
|
|
2462
|
-
*
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
vv.col = e_col(e, sh->val_start) + 1;
|
|
2467
|
+
* value EVENT is assembled ONLY on the fallback path (the sinks
|
|
2468
|
+
* that take the pair read the yep_block_value and ignore it): the
|
|
2469
|
+
* semantic helpers run unchanged (alias resolution, anchor
|
|
2470
|
+
* definition, the fold), the fallback reuses the pair facts
|
|
2471
|
+
* captured before the fold — e_plain_multiline advances
|
|
2472
|
+
* line/pos across continuations, so post-fold e_col would lie. */
|
|
2467
2473
|
/* the pair facts are captured BEFORE the fold: e_plain_multiline
|
|
2468
2474
|
* advances line/pos across continuations */
|
|
2469
2475
|
uint32_t pair_line = e->line;
|
|
@@ -2471,6 +2477,18 @@ static int e_classified(yep_engine* e, uint16_t floor_col) {
|
|
|
2471
2477
|
yep_block_value v;
|
|
2472
2478
|
memset(&v, 0, sizeof(v));
|
|
2473
2479
|
v.cls = (uint8_t)sh->val;
|
|
2480
|
+
yep_event vv; /* the fields the fallback reads are assigned HERE and
|
|
2481
|
+
* overwritten by the arms/helpers — MSVC C4701 cannot
|
|
2482
|
+
* see through the helpers' bypointer writes, so the
|
|
2483
|
+
* zero-init lives in this function, not a memset */
|
|
2484
|
+
vv.value.p = NULL;
|
|
2485
|
+
vv.value.len = 0;
|
|
2486
|
+
vv.borrowed = 0;
|
|
2487
|
+
vv.anchor.p = NULL;
|
|
2488
|
+
vv.anchor.len = 0;
|
|
2489
|
+
vv.anchor_id = 0;
|
|
2490
|
+
vv.end_line = 0;
|
|
2491
|
+
vv.end_col = 0;
|
|
2474
2492
|
int prepared = 0;
|
|
2475
2493
|
if (sh->val == YEP_LVAL_ALIAS) {
|
|
2476
2494
|
e->pos = sh->val_start;
|
|
@@ -2497,8 +2515,6 @@ static int e_classified(yep_engine* e, uint16_t floor_col) {
|
|
|
2497
2515
|
vv.value.p = e->p + sh->val_span.start;
|
|
2498
2516
|
vv.value.len = sh->val_span.end - sh->val_span.start;
|
|
2499
2517
|
vv.borrowed = 1;
|
|
2500
|
-
vv.style = YEP_STYLE_PLAIN;
|
|
2501
|
-
vv.implicit = 1;
|
|
2502
2518
|
e->pos = sh->val_span.end;
|
|
2503
2519
|
if (e_plain_multiline(e, sh->val_span, key_col, &vv, 0) != 0) {
|
|
2504
2520
|
return -1;
|
|
@@ -2523,9 +2539,30 @@ static int e_classified(yep_engine* e, uint16_t floor_col) {
|
|
|
2523
2539
|
return 1;
|
|
2524
2540
|
}
|
|
2525
2541
|
}
|
|
2542
|
+
/* Fallback: assemble the value event with the helper-filled
|
|
2543
|
+
* fields preserved — e_alias stamps type=ALIAS + the end marks,
|
|
2544
|
+
* e_plain_multiline stamps the fold end marks; the pair facts
|
|
2545
|
+
* taken pre-fold (post-fold e_col would read the advanced
|
|
2546
|
+
* line/pos). Field-for-field what the pre-fill built. */
|
|
2547
|
+
yep_event ve;
|
|
2548
|
+
e_event_init(&ve, YEP_EV_SCALAR);
|
|
2549
|
+
ve.line = pair_line;
|
|
2550
|
+
ve.col = (uint32_t)pair_val_col + 1;
|
|
2551
|
+
ve.value = vv.value;
|
|
2552
|
+
ve.borrowed = vv.borrowed;
|
|
2553
|
+
ve.anchor = vv.anchor;
|
|
2554
|
+
ve.anchor_id = vv.anchor_id;
|
|
2555
|
+
ve.end_line = vv.end_line;
|
|
2556
|
+
ve.end_col = vv.end_col;
|
|
2557
|
+
if (sh->val == YEP_LVAL_ALIAS) {
|
|
2558
|
+
ve.type = YEP_EV_ALIAS;
|
|
2559
|
+
} else {
|
|
2560
|
+
ve.style = YEP_STYLE_PLAIN;
|
|
2561
|
+
ve.implicit = 1;
|
|
2562
|
+
}
|
|
2526
2563
|
yep_event kv;
|
|
2527
2564
|
e_key_event(e, sh, key_col, pair_line, &kv);
|
|
2528
|
-
if (emit_now(e, &kv) != 0 || emit_now(e, &
|
|
2565
|
+
if (emit_now(e, &kv) != 0 || emit_now(e, &ve) != 0) {
|
|
2529
2566
|
return -2;
|
|
2530
2567
|
}
|
|
2531
2568
|
return 1;
|
|
@@ -2705,7 +2742,7 @@ static int e_node(yep_engine* e, yep_ctx ctx, uint16_t floor_col) {
|
|
|
2705
2742
|
/* JSON fast path first: its validating scan already finds the
|
|
2706
2743
|
* close, replacing e_skip_flow's pre-scan when it applies. */
|
|
2707
2744
|
e->flow_floor = floor_col;
|
|
2708
|
-
e->flow_enforce = (e->depth > 0);
|
|
2745
|
+
e->flow_enforce = (e->depth > 0) && !e->compat_grammar;
|
|
2709
2746
|
int fast = e_flow_json(e, node_a, node_t, anchor_ordinal);
|
|
2710
2747
|
e->flow_enforce = 0;
|
|
2711
2748
|
if (fast == 1) {
|
|
@@ -2750,7 +2787,7 @@ static int e_node(yep_engine* e, yep_ctx ctx, uint16_t floor_col) {
|
|
|
2750
2787
|
}
|
|
2751
2788
|
{
|
|
2752
2789
|
e->flow_floor = floor_col;
|
|
2753
|
-
e->flow_enforce = (e->depth > 0);
|
|
2790
|
+
e->flow_enforce = (e->depth > 0) && !e->compat_grammar;
|
|
2754
2791
|
int rc = e_flow(e, node_a, node_t, node_aid);
|
|
2755
2792
|
e->flow_enforce = 0;
|
|
2756
2793
|
if (rc != 0) {
|
|
@@ -3082,6 +3119,12 @@ void yep_engine_set_resolver(yep_engine* e, const yep_resolver* r) {
|
|
|
3082
3119
|
}
|
|
3083
3120
|
}
|
|
3084
3121
|
|
|
3122
|
+
void yep_engine_set_compat_grammar(yep_engine* e, int on) {
|
|
3123
|
+
if (e != NULL) {
|
|
3124
|
+
e->compat_grammar = on != 0;
|
|
3125
|
+
}
|
|
3126
|
+
}
|
|
3127
|
+
|
|
3085
3128
|
void yep_engine_set_max_depth(yep_engine* e, int depth) {
|
|
3086
3129
|
if (e != NULL && depth > 0) {
|
|
3087
3130
|
e->max_depth = depth > YEP_MAX_DEPTH ? YEP_MAX_DEPTH : depth;
|
|
@@ -52,6 +52,13 @@ struct yep_resolver;
|
|
|
52
52
|
void yep_engine_set_resolver(yep_engine* e, const struct yep_resolver* r);
|
|
53
53
|
void yep_engine_set_max_depth(yep_engine* e, int depth);
|
|
54
54
|
|
|
55
|
+
/* The 1.1-compat grammar (libyaml/psych parity): the block-level flow
|
|
56
|
+
* indent floor (9C9N, VJP3) is a yaml-test-suite rule libyaml never
|
|
57
|
+
* enforced — real-world locale files close multi-line flow collections
|
|
58
|
+
* at their parent's column ("k: {\n a: b\n}"). Off by default (the
|
|
59
|
+
* strict 1.2 engine the conformance suite runs keeps the floor). */
|
|
60
|
+
void yep_engine_set_compat_grammar(yep_engine* e, int on);
|
|
61
|
+
|
|
55
62
|
/* Byte offset the last run reached (into that run's buffer); used by
|
|
56
63
|
* consumers that stop the engine at a boundary and resume. */
|
|
57
64
|
size_t yep_engine_pos(const yep_engine* e);
|
|
@@ -301,6 +301,12 @@ engine_enter:
|
|
|
301
301
|
yep_engine_set_resolver(eng, opts->schema == YEPTRIS_SCHEMA_11_COMPAT
|
|
302
302
|
? yep_resolver_compat11()
|
|
303
303
|
: yep_resolver_core12());
|
|
304
|
+
if (opts->schema == YEPTRIS_SCHEMA_11_COMPAT) {
|
|
305
|
+
/* the compat schema is the psych/libyaml surface: its grammar
|
|
306
|
+
* must accept what libyaml accepts (the flow floor is suite-
|
|
307
|
+
* strict, not libyaml — see yep_engine_set_compat_grammar) */
|
|
308
|
+
yep_engine_set_compat_grammar(eng, 1);
|
|
309
|
+
}
|
|
304
310
|
if (opts->max_depth > 0) {
|
|
305
311
|
yep_engine_set_max_depth(eng, opts->max_depth);
|
|
306
312
|
}
|
|
@@ -601,6 +601,36 @@ 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).
|
|
@@ -884,103 +914,132 @@ lmap1: /* {} closes here */
|
|
|
884
914
|
goto lmapkey;
|
|
885
915
|
|
|
886
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
|
+
}
|
|
887
922
|
LWS();
|
|
888
923
|
if (p[i] != '"') {
|
|
889
924
|
goto lreject;
|
|
890
925
|
}
|
|
891
926
|
lmapkey: { LSTR_SCAN(lmapcolon); }
|
|
892
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
|
+
}
|
|
893
942
|
LWS();
|
|
894
943
|
if (p[i] != ':') {
|
|
895
944
|
goto lreject;
|
|
896
945
|
}
|
|
897
946
|
i++;
|
|
898
947
|
LWS();
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
/* the flag clears only on a CONSUMED byte: the run's
|
|
918
|
-
* terminator (',', '}', ']', whitespace) must leave
|
|
919
|
-
* digits_only intact, or every plain integer followed
|
|
920
|
-
* by a delimiter falls into the full validator */
|
|
921
|
-
if (d == '-' || d == '+' || d == '.' || d == 'e' || d == 'E') {
|
|
922
|
-
digits_only = 0;
|
|
923
|
-
k++;
|
|
924
|
-
continue;
|
|
925
|
-
}
|
|
926
|
-
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;
|
|
927
966
|
}
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
if (!ok) {
|
|
937
|
-
goto lreject;
|
|
938
|
-
}
|
|
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;
|
|
939
975
|
}
|
|
940
|
-
|
|
941
|
-
(uint64_t)(YEP_T_NUM);
|
|
942
|
-
count++;
|
|
943
|
-
i = k;
|
|
944
|
-
goto lmapafter;
|
|
976
|
+
break;
|
|
945
977
|
}
|
|
946
|
-
if (
|
|
947
|
-
|
|
948
|
-
if (
|
|
949
|
-
|
|
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));
|
|
950
985
|
}
|
|
951
|
-
|
|
952
|
-
memcpy(&got4, p + i, 4);
|
|
953
|
-
if (got4 != (c == 't' ? 0x65757274u /* "true" */
|
|
954
|
-
: c == 'n' ? 0x6C6C756Eu /* "null" */
|
|
955
|
-
: 0x736C6166u /* "fals" */) ||
|
|
956
|
-
(c == 'f' && p[i + 4] != 'e')) {
|
|
986
|
+
if (!ok) {
|
|
957
987
|
goto lreject;
|
|
958
988
|
}
|
|
959
|
-
if (i + wl < len) {
|
|
960
|
-
char z = p[i + wl];
|
|
961
|
-
if (z != ' ' && z != '\t' && z != '\n' && z != '\r' && z != ',' && z != ']' &&
|
|
962
|
-
z != '}' && z != ':') {
|
|
963
|
-
goto lreject;
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
recs[count] = ((uint64_t)((uint32_t)i) << 32) | ((uint64_t)((uint32_t)wl) << 8) |
|
|
967
|
-
(uint64_t)(c == 'n' ? YEP_T_NULL : (c == 't' ? YEP_T_TRUE : YEP_T_FALSE));
|
|
968
|
-
count++;
|
|
969
|
-
i += wl;
|
|
970
|
-
goto lmapafter;
|
|
971
989
|
}
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
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;
|
|
975
1000
|
}
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
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;
|
|
979
1008
|
}
|
|
980
|
-
|
|
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;
|
|
981
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
|
+
}
|
|
982
1032
|
|
|
983
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
|
+
}
|
|
984
1043
|
LWS();
|
|
985
1044
|
if (p[i] == ',') {
|
|
986
1045
|
i++;
|
|
@@ -1009,6 +1068,7 @@ lseqval: {
|
|
|
1009
1068
|
if ((unsigned)(c - '0') <= 9u || c == '-') {
|
|
1010
1069
|
size_t k = i + 1;
|
|
1011
1070
|
int digits_only = 1, saw_digit = (c != '-');
|
|
1071
|
+
LNUM_RUN;
|
|
1012
1072
|
while (k < len) {
|
|
1013
1073
|
char d = p[k];
|
|
1014
1074
|
if ((unsigned)(d - '0') <= 9u) {
|
|
@@ -1080,6 +1140,18 @@ lseqval: {
|
|
|
1080
1140
|
}
|
|
1081
1141
|
|
|
1082
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
|
+
}
|
|
1083
1155
|
LWS();
|
|
1084
1156
|
if (p[i] == ',') {
|
|
1085
1157
|
i++;
|
|
@@ -1092,6 +1164,7 @@ lseqafter:
|
|
|
1092
1164
|
|
|
1093
1165
|
ldone:
|
|
1094
1166
|
#undef LWS
|
|
1167
|
+
#undef LNUM_RUN
|
|
1095
1168
|
#undef LPUSH
|
|
1096
1169
|
#undef LCLOSE
|
|
1097
1170
|
#undef LSTR_SCAN
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: yeptris
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.24.1
|
|
5
5
|
platform: aarch64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-09-
|
|
11
|
+
date: 2026-09-26 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ffi
|