yeptris 0.6.52.0-arm-linux-eabihf → 0.6.53.0-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/yeptris_native/version.h +2 -2
- data/lib/yeptris.rb +1 -1
- data/libyeptris.so +0 -0
- data/vendor/libyeptris/CMakeLists.txt +1 -1
- data/vendor/libyeptris/src/yeptris/cbor/from_marshal.c +7 -0
- data/vendor/libyeptris/src/yeptris/dom/dom.c +15 -8
- data/vendor/libyeptris/src/yeptris/dom/dom.h +8 -2
- data/vendor/libyeptris/src/yeptris/dom/ytape.c +2 -2
- data/vendor/libyeptris/src/yeptris/emit/emit.c +4 -0
- data/vendor/libyeptris/src/yeptris/emit/style.c +9 -191
- data/vendor/libyeptris/src/yeptris/emit/writer.c +149 -35
- data/vendor/libyeptris/src/yeptris/marshal.c +10 -5
- data/vendor/libyeptris/src/yeptris/parse/engine.c +185 -67
- data/vendor/libyeptris/src/yeptris/parse/events.h +2 -2
- data/vendor/libyeptris/src/yeptris/resolve/compat11.c +2 -1
- data/vendor/libyeptris/src/yeptris/resolve/core12.c +3 -1
- data/vendor/libyeptris/src/yeptris/scan/json.c +6 -0
- data/vendor/libyeptris/src/yeptris/scan/scan.c +202 -1
- data/vendor/libyeptris/src/yeptris/scan/scan.h +12 -1
- metadata +1 -1
|
@@ -97,7 +97,7 @@ void yep_scan_line_f(const char* p, size_t len, size_t pos, const yep_line_facts
|
|
|
97
97
|
li.first = 0;
|
|
98
98
|
li.end = f->end;
|
|
99
99
|
size_t j = f->indent;
|
|
100
|
-
li.indent = (
|
|
100
|
+
li.indent = (uint32_t)(j - pos);
|
|
101
101
|
if (j < li.end && p[j] == '\t') {
|
|
102
102
|
size_t k = j;
|
|
103
103
|
while (k < li.end && (p[k] == ' ' || p[k] == '\t')) {
|
|
@@ -162,6 +162,12 @@ static int yep_colon_terminates(const char* p, size_t len, size_t colon, int flo
|
|
|
162
162
|
if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
|
|
163
163
|
return 1;
|
|
164
164
|
}
|
|
165
|
+
/* a raw NEL/LS/PS is a break like LF (libyaml's IS_BLANKZ): the
|
|
166
|
+
* value-position separator arm the #833 dig pinned — the LF twin
|
|
167
|
+
* terminated while the PS spelling kept the colon in the plain */
|
|
168
|
+
if (yep_scan_mb_break_len(p, len, next) > 0) {
|
|
169
|
+
return 1;
|
|
170
|
+
}
|
|
165
171
|
if (flow && yep_ct_is(c, YEP_CT_FLOW_IND)) {
|
|
166
172
|
return 1;
|
|
167
173
|
}
|
|
@@ -198,6 +204,201 @@ int yep_scan_dq_forced(const char* p, uint32_t len) {
|
|
|
198
204
|
return 0;
|
|
199
205
|
}
|
|
200
206
|
|
|
207
|
+
/* ---- the plain-safety truth table (moved from emit/style.c,
|
|
208
|
+
* #352 lane 3: scan owns bytes→facts; the emitter and the DOM's
|
|
209
|
+
* parse-time fact bit both read THIS walk so they cannot drift) ---- */
|
|
210
|
+
|
|
211
|
+
static int is_blank(char c) {
|
|
212
|
+
return c == ' ' || c == '\t';
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
static int is_break(char c) {
|
|
216
|
+
return c == '\n' || c == '\r';
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
int yep_scan_plain_safe(const char* p, uint32_t len) {
|
|
220
|
+
if (len == 0) {
|
|
221
|
+
return 0; /* empty needs quotes or an empty-value slot */
|
|
222
|
+
}
|
|
223
|
+
if (is_blank(p[0]) || is_blank(p[len - 1])) {
|
|
224
|
+
return 0;
|
|
225
|
+
}
|
|
226
|
+
if (len >= 3 && (unsigned char)p[0] == 0xef && (unsigned char)p[1] == 0xbb &&
|
|
227
|
+
(unsigned char)p[2] == 0xbf) {
|
|
228
|
+
/* a LEADING U+FEFF re-parses as a document BOM and vanishes —
|
|
229
|
+
* the emitted form must carry its escape ("\uFEFF", the
|
|
230
|
+
* nightly's run 38258674337); mid-token BOMs ride plain */
|
|
231
|
+
return 0;
|
|
232
|
+
}
|
|
233
|
+
switch (p[0]) {
|
|
234
|
+
case ':':
|
|
235
|
+
/* libyaml (Psych symbol dumps ":name"): a leading colon only
|
|
236
|
+
* indicates when followed by a blank/EOL — the interior rule
|
|
237
|
+
* below covers it; ":name" stays plain */
|
|
238
|
+
break;
|
|
239
|
+
case '-':
|
|
240
|
+
case '?':
|
|
241
|
+
/* indicators only before a blank or EOL: "-5" and "?x" are
|
|
242
|
+
* plain (libyaml emits negative numbers plain; Psych, too) —
|
|
243
|
+
* but fall through: the document-marker check below owns
|
|
244
|
+
* the bare "---"/"..." (libyaml quotes those) */
|
|
245
|
+
if (len == 1 || is_blank(p[1])) {
|
|
246
|
+
return 0;
|
|
247
|
+
}
|
|
248
|
+
break;
|
|
249
|
+
case ',':
|
|
250
|
+
case '[':
|
|
251
|
+
case ']':
|
|
252
|
+
case '{':
|
|
253
|
+
case '}':
|
|
254
|
+
case '#':
|
|
255
|
+
case '&':
|
|
256
|
+
case '*':
|
|
257
|
+
case '!':
|
|
258
|
+
case '|':
|
|
259
|
+
case '>':
|
|
260
|
+
case '\'':
|
|
261
|
+
case '"':
|
|
262
|
+
case '%':
|
|
263
|
+
case '@':
|
|
264
|
+
case '`':
|
|
265
|
+
return 0;
|
|
266
|
+
default:
|
|
267
|
+
break;
|
|
268
|
+
}
|
|
269
|
+
/* The interior scan in SWAR words: every reject condition is a
|
|
270
|
+
* byte-class adjacency, so one masked word test is exact —
|
|
271
|
+
* break/tab bytes reject directly; ':' rejects with a blank at its
|
|
272
|
+
* NEXT lane (or the span's EOL); '#' with a blank at its PREVIOUS
|
|
273
|
+
* lane (the span's first byte is exempt — the head switch already
|
|
274
|
+
* handled a leading '#'). Cross-word adjacency rides one carried
|
|
275
|
+
* byte per boundary; the tail runs the byte loop, whose rules read
|
|
276
|
+
* real neighbors and need no carries. */
|
|
277
|
+
{
|
|
278
|
+
const uint64_t ONES = 0x0101010101010101ull;
|
|
279
|
+
const uint64_t HIGH = 0x8080808080808080ull;
|
|
280
|
+
#define YST_ZDET(w, ch) \
|
|
281
|
+
((((w) ^ (uint64_t)(ch) * ONES) - ONES) & ~((w) ^ (uint64_t)(ch) * ONES) & HIGH)
|
|
282
|
+
/* the all-boring accept (#742): a span of pure [0-9A-Za-z_]
|
|
283
|
+
* makes EVERY rule in this function vacuous — no indicators
|
|
284
|
+
* (the head switch), no blanks at the ends, no BOM, no
|
|
285
|
+
* ': '/' #' adjacency, no breaks, and no ---/... marker — so
|
|
286
|
+
* one range test per word accepts without the six-mask walk.
|
|
287
|
+
* Anything else falls through to the exact scan below. */
|
|
288
|
+
{
|
|
289
|
+
uint32_t bi = 0;
|
|
290
|
+
int boring = 1;
|
|
291
|
+
while (bi + 8 <= len) {
|
|
292
|
+
uint64_t bw;
|
|
293
|
+
memcpy(&bw, p + bi, 8);
|
|
294
|
+
if (bw & HIGH) {
|
|
295
|
+
boring = 0;
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
/* per-lane unsigned range checks via borrow bits: alpha
|
|
299
|
+
* is (t - 'a') and ('z' - t) both borrow-free with
|
|
300
|
+
* t = w|0x20 (A-Z fold); digits bound 0x30..0x39 */
|
|
301
|
+
uint64_t t = bw | (ONES * 0x20);
|
|
302
|
+
uint64_t bad = ((t - ONES * 0x61) | (ONES * 0x7A - t)) & HIGH; /* alpha */
|
|
303
|
+
bad |= ((bw - ONES * 0x30) | (ONES * 0x39 - bw)) & HIGH; /* digit */
|
|
304
|
+
bad &= ~YST_ZDET(bw, '_'); /* the one extra boring byte */
|
|
305
|
+
if (bad != 0) {
|
|
306
|
+
boring = 0;
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
bi += 8;
|
|
310
|
+
}
|
|
311
|
+
if (boring) {
|
|
312
|
+
for (; bi < len; bi++) {
|
|
313
|
+
char c = p[bi];
|
|
314
|
+
int a = (c | 0x20);
|
|
315
|
+
if (!((c >= '0' && c <= '9') || (a >= 'a' && a <= 'z') || c == '_')) {
|
|
316
|
+
boring = 0;
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
if (boring) {
|
|
321
|
+
return 1;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
uint32_t i = 0;
|
|
326
|
+
int prev_blank7 = 0;
|
|
327
|
+
while (i + 8 <= len) {
|
|
328
|
+
uint64_t w;
|
|
329
|
+
memcpy(&w, p + i, 8);
|
|
330
|
+
if (w & HIGH) {
|
|
331
|
+
/* multibyte content: the byte loop owns the rest — a raw
|
|
332
|
+
* LS/PS/NEL rides in a scalar value since the quote-aware
|
|
333
|
+
* normalizer (#638) and is a line break on re-parse, so
|
|
334
|
+
* the value must be quoted, not plain (the nightly's
|
|
335
|
+
* round 18, crash-1e79b2e3) */
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
338
|
+
uint64_t space = YST_ZDET(w, ' ');
|
|
339
|
+
uint64_t tab = YST_ZDET(w, '\t');
|
|
340
|
+
uint64_t blank = space | tab;
|
|
341
|
+
uint64_t colon = YST_ZDET(w, ':');
|
|
342
|
+
uint64_t hash = YST_ZDET(w, '#');
|
|
343
|
+
/* tab and the breaks reject outright */
|
|
344
|
+
if (tab | YST_ZDET(w, '\n') | YST_ZDET(w, '\r')) {
|
|
345
|
+
return 0;
|
|
346
|
+
}
|
|
347
|
+
/* ':' + blank next: (blank >> 8) pulls lane i+1's flag down
|
|
348
|
+
* into lane i; the word's last lane takes the peeked byte
|
|
349
|
+
* (EOL at the span end counts as blank — the rule rejects
|
|
350
|
+
* there) */
|
|
351
|
+
if (colon) {
|
|
352
|
+
int next_blank = i + 8 < len ? is_blank(p[i + 8]) : 1;
|
|
353
|
+
if (colon & ((blank >> 8) | (next_blank ? (uint64_t)0x80 << 56 : 0))) {
|
|
354
|
+
return 0;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
/* '#' + blank prev: (blank << 8) lifts lane i-1's flag up
|
|
358
|
+
* into lane i; lane 0 takes the carried last-lane flag */
|
|
359
|
+
if (hash && (hash & ((blank << 8) | (prev_blank7 ? 0x80 : 0)))) {
|
|
360
|
+
return 0;
|
|
361
|
+
}
|
|
362
|
+
prev_blank7 = (int)((blank >> 63) & 1); /* lane 7's flag is its top bit */
|
|
363
|
+
i += 8;
|
|
364
|
+
}
|
|
365
|
+
#undef YST_ZDET
|
|
366
|
+
for (; i < len; i++) {
|
|
367
|
+
char c = p[i];
|
|
368
|
+
if (is_break(c) || c == '\t') {
|
|
369
|
+
return 0;
|
|
370
|
+
}
|
|
371
|
+
if ((unsigned char)c == 0xE2 && i + 2 < len && (unsigned char)p[i + 1] == 0x80 &&
|
|
372
|
+
((unsigned char)p[i + 2] & 0xFE) == 0xA8) {
|
|
373
|
+
return 0; /* a raw LS/PS re-parses as a line break */
|
|
374
|
+
}
|
|
375
|
+
if ((unsigned char)c == 0xC2 && i + 1 < len && (unsigned char)p[i + 1] == 0x85) {
|
|
376
|
+
return 0; /* a raw NEL ditto */
|
|
377
|
+
}
|
|
378
|
+
if (c == ':') {
|
|
379
|
+
if (i + 1 >= len || is_blank(p[i + 1])) {
|
|
380
|
+
return 0;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
if (c == '#') {
|
|
384
|
+
if (i > 0 && is_blank(p[i - 1])) {
|
|
385
|
+
return 0;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
/* document markers */
|
|
391
|
+
if (len >= 3 && (memcmp(p, "---", 3) == 0 || memcmp(p, "...", 3) == 0) &&
|
|
392
|
+
(len == 3 || p[3] == ' ' || p[3] == '\t' || p[3] == '\n' || p[3] == '\r')) {
|
|
393
|
+
/* a PREFIX marker is worse than the bare one: emitted plain at
|
|
394
|
+
* line start, "--- ..." re-reads as a document marker (the
|
|
395
|
+
* nightly's "--- --- >" folded-plain crasher) — libyaml quotes
|
|
396
|
+
* both */
|
|
397
|
+
return 0;
|
|
398
|
+
}
|
|
399
|
+
return 1;
|
|
400
|
+
}
|
|
401
|
+
|
|
201
402
|
size_t yep_scan_prop_end(const char* p, size_t len, size_t pos) {
|
|
202
403
|
while (pos < len) {
|
|
203
404
|
unsigned char c = (unsigned char)p[pos];
|
|
@@ -20,7 +20,9 @@ extern "C" {
|
|
|
20
20
|
typedef struct yep_line_info {
|
|
21
21
|
uint32_t offset; /* byte offset of the line start */
|
|
22
22
|
uint32_t end; /* byte offset of the line break (exclusive content end) */
|
|
23
|
-
|
|
23
|
+
uint32_t indent; /* column of the first non-space (== end - offset when blank);
|
|
24
|
+
* 32-bit: a 65536-space line wrapped to 0 and read as a
|
|
25
|
+
* dedent (the 2026-10-31 audit) */
|
|
24
26
|
uint16_t flags;
|
|
25
27
|
unsigned char first; /* first content byte ('\0' for blank lines) */
|
|
26
28
|
} yep_line_info;
|
|
@@ -104,6 +106,15 @@ size_t yep_scan_prop_end(const char* p, size_t len, size_t pos);
|
|
|
104
106
|
* AND the DOM's parse-time fact bit, so the two cannot drift. */
|
|
105
107
|
int yep_scan_dq_forced(const char* p, uint32_t len);
|
|
106
108
|
|
|
109
|
+
/* The plain-safety truth table (issue #352 lane 3): 1 when the span
|
|
110
|
+
* re-parses as a plain scalar in BLOCK context (value or key — the
|
|
111
|
+
* key wrapper is the same predicate; the colon rule covers keys).
|
|
112
|
+
* The bytes→facts home: the emitter's style chooser AND the DOM's
|
|
113
|
+
* parse-time fact bit read this one walk, so the verdicts cannot
|
|
114
|
+
* drift. Multibyte-aware (raw NEL/LS/PS reject; a leading U+FEFF
|
|
115
|
+
* rejects; mid-token BOMs ride). */
|
|
116
|
+
int yep_scan_plain_safe(const char* p, uint32_t len);
|
|
117
|
+
|
|
107
118
|
/* Tag-shorthand suffix byte: libyaml's URI set (";/?:@&=+$,_.!~*'()%"
|
|
108
119
|
* plus alphanumerics; flow indicators and ',' terminate instead).
|
|
109
120
|
* Stray non-set bytes stay visible as the props follower, which
|