yeptris 0.6.31.2-aarch64-linux → 0.6.32.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 183da7797c7f5b350cd690df5ce9d68192e876b67d9d894d86e699fd525f893a
4
- data.tar.gz: b650b33d6927a1ebb0659925eac2fadf73bd7a55bf87a7c3b5acf140a1463209
3
+ metadata.gz: 27054940f25d07b0af5eebd56ff85e79de42305a7ab59e34f714b48ab523458c
4
+ data.tar.gz: aef30cec9183a9caf10864e3d112d109bf3c81f93000c11c87d5e4547b22ba50
5
5
  SHA512:
6
- metadata.gz: c215e725c05e52335ac398ce44bf5a28f33456e7941da00bc4349f6a0715629fe14f87cfe7e558e00ca6c0406253677d9a1fff5bc03dab95ae2591dc88b3d72d
7
- data.tar.gz: 30307baad810806be2ba5007d544d1f1de11151d38f21a93dd040289bb6dbb392b242fd6897c30c9b8cd37b67fa43343c698513c4fc22e4d3790151d85dc311c
6
+ metadata.gz: 5567d722a33e0f30f60ce64345be3c2ee57657bdd884b82f159f6ec9d5ec415ce6c83cd70ae317d3449e13824fd5a018b1e3be7c62440e02832c6c2b9bf479cf
7
+ data.tar.gz: 1e178a8fe0eda68348d962919ed6523c0347cc851de265804307a1d09aa2c5c80cc2859452d19b4c0fe1c14463184974d017d0000220db234d135905b5ada08c
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.31.2".freeze
6
+ VERSION = "0.6.32.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.31
6
+ VERSION 0.6.32
7
7
  DESCRIPTION "Ultra-fast YAML 1.2 parser, emitter and streamer in C"
8
8
  LANGUAGES C CXX
9
9
  )
@@ -1118,6 +1118,14 @@ static size_t yt_flat_run(yep_ytape* t, const char* p, size_t pos, size_t len, u
1118
1118
  if (col + 1 != run_cc) {
1119
1119
  return pos; /* off-column: the pop/nest logic owns it */
1120
1120
  }
1121
+ /* document markers are the engine's alone — the "..."+content
1122
+ * error law lives there (the nightly's marshal crasher) */
1123
+ if (le - li >= 3 && (memcmp(p + li, "...", 3) == 0 || memcmp(p + li, "---", 3) == 0)) {
1124
+ size_t mk2 = li + 3;
1125
+ if (mk2 >= le || p[mk2] == ' ' || p[mk2] == '\t') {
1126
+ return pos;
1127
+ }
1128
+ }
1121
1129
  unsigned char c = (unsigned char)p[li];
1122
1130
  if (c == '\t' || c == '-' || c == '&' || c == '!' || c == '*' || c == '\'' || c == '"' ||
1123
1131
  c == '[' || c == '{' || c == '|' || c == '>' || c == '%' || c == '?') {
@@ -1293,6 +1301,8 @@ static int yt_f_run(yt_fused* F) {
1293
1301
  if (n1 == ' ' || n1 == '\t') {
1294
1302
  dash = 1;
1295
1303
  }
1304
+ } else if (c == '-' && line_indent + 1 >= line_end) {
1305
+ dash = 1; /* a line-end dash is an indicator, not the scalar "-" */
1296
1306
  }
1297
1307
  size_t next = line_end < len ? (size_t)line_end + 1 : len;
1298
1308
  if (!blank && !comment) {
@@ -1301,6 +1311,18 @@ static int yt_f_run(yt_fused* F) {
1301
1311
  if (c == '\t') {
1302
1312
  return 1; /* tab-led content: the engine's error */
1303
1313
  }
1314
+ /* document markers are the engine's alone: only it carries
1315
+ * the "..."+content error law (the nightly's marshal
1316
+ * crasher, "a: b\n... vi an : }" — the runner swallowed
1317
+ * the post-'...' content as a pair) */
1318
+ if (col == 0 && line_end - line_indent >= 3 &&
1319
+ (memcmp(p + line_indent, "...", 3) == 0 ||
1320
+ memcmp(p + line_indent, "---", 3) == 0)) {
1321
+ size_t mk = line_indent + 3;
1322
+ if (mk >= line_end || p[mk] == ' ' || p[mk] == '\t') {
1323
+ return 1;
1324
+ }
1325
+ }
1304
1326
  if (dash && depth > 0 && st[depth].pending && col >= st[depth].indent) {
1305
1327
  /* the pending key resolves into a sequence: its own
1306
1328
  * frame (the key's map survives below it) */
@@ -1391,8 +1413,19 @@ static int yt_f_run(yt_fused* F) {
1391
1413
  vc == '?') {
1392
1414
  return 1;
1393
1415
  }
1394
- if (vc == '-' && vt + 1 < line_end && (p[vt + 1] == ' ' || p[vt + 1] == '\t')) {
1395
- return 1; /* nested dash: the engine's nested seq */
1416
+ if (!yep_plain_first_ok(vc)) {
1417
+ return 1; /* ']'/','/'}'/'@'/'`' first: no plain
1418
+ item can start there (the nightly's
1419
+ marshal crasher, "x:\n- ]\"#") — the
1420
+ engine errors cleanly */
1421
+ }
1422
+ if (vc == '-' && (vt + 1 >= line_end || p[vt + 1] == ' ' || p[vt + 1] == '\t' ||
1423
+ p[vt + 1] == '#')) {
1424
+ return 1; /* nested dash (incl. line-end — the
1425
+ nightly's "n:\n- -\t" crasher: a
1426
+ trailing bare '-' is an indicator,
1427
+ never the plain scalar "-"): the
1428
+ engine's nested seq */
1396
1429
  }
1397
1430
  /* compact map item "- k: v"? */
1398
1431
  for (size_t ic = vt; ic < vend; ic++) {
@@ -168,6 +168,20 @@ static void emit_dq(yep_writer* w, const char* p, uint32_t n) {
168
168
  i += 2;
169
169
  continue;
170
170
  }
171
+ /* U+FFFE/U+FFFF are noncharacters: the printable validator
172
+ * rejects them raw, so emitting them raw makes the document
173
+ * un-re-parseable (the nightly's "["\\uFFFE"]" catch). Their
174
+ * escapes re-enter the doc the same way they left. */
175
+ if (c == 0xef && i + 2 < n && (unsigned char)p[i + 1] == 0xbf &&
176
+ ((unsigned char)p[i + 2] == 0xbe || (unsigned char)p[i + 2] == 0xbf)) {
177
+ if (run) {
178
+ wr_put(w, p + i - run, run);
179
+ run = 0;
180
+ }
181
+ wr_put(w, (unsigned char)p[i + 2] == 0xbe ? "\\uFFFE" : "\\uFFFF", 6);
182
+ i += 2;
183
+ continue;
184
+ }
171
185
  /* U+FEFF must never ride raw: at the buffer head it IS the
172
186
  * BOM and re-parse would strip it (the nightly's UTF-32LE
173
187
  * catch); Psych escapes it everywhere ("") */
@@ -393,6 +407,11 @@ static uint8_t sc_route(yep_writer* w, const char* p, uint32_t len, int as_key,
393
407
  has_bom = 1;
394
408
  break;
395
409
  }
410
+ if ((unsigned char)p[k] == 0xef && k + 2 < len && (unsigned char)p[k + 1] == 0xbf &&
411
+ ((unsigned char)p[k + 2] == 0xbe || (unsigned char)p[k + 2] == 0xbf)) {
412
+ has_nel = 1; /* noncharacter: only its escape re-parses */
413
+ break;
414
+ }
396
415
  }
397
416
  if (has_nel || has_bom) {
398
417
  return YEP_SC_DQ;
@@ -556,6 +575,27 @@ static void emit_alias_ex(yep_emitter* em, const yep_dnode* n) {
556
575
  }
557
576
  }
558
577
 
578
+ /* Tag bytes outside ns-tag-char ride %XX (the parse side decodes them
579
+ * per the URI rule — a decoded newline emitted raw was the nightly's
580
+ * byte-instability crasher "!%0a"). Uppercase hex, libyaml's form. */
581
+ static void wr_tag_uri(yep_writer* w, const yep_view* v) {
582
+ static const char hd[] = "0123456789ABCDEF";
583
+ const unsigned char* p = (const unsigned char*)v->p;
584
+ for (uint32_t i = 0; i < v->len; i++) {
585
+ unsigned char c = p[i];
586
+ if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
587
+ c == '-' || c == ';' || c == '/' || c == '?' || c == ':' || c == '@' || c == '&' ||
588
+ c == '=' || c == '+' || c == '$' || c == ',' || c == '.' || c == '!' || c == '~' ||
589
+ c == '*' || c == '\'' || c == '(' || c == ')') {
590
+ wr_byte(w, (char)c);
591
+ } else {
592
+ wr_byte(w, '%');
593
+ wr_byte(w, hd[c >> 4]);
594
+ wr_byte(w, hd[c & 0xf]);
595
+ }
596
+ }
597
+ }
598
+
559
599
  /* Explicit tag, verbatim URI form ("!<tag:…> "). Never skipped: a
560
600
  * recorded tag always re-emits (implied-by-style skipping made the
561
601
  * roundtrip byte-unstable: plain+!!str and ""+!!str collided). */
@@ -567,13 +607,15 @@ static void emit_tag(yep_writer* w, const yep_dnode* n) {
567
607
  if (tdec.len > 0 && tdec.p[0] == '!') {
568
608
  /* already a shorthand ("!ruby/object:K", "!foo"): verbatim —
569
609
  * the !<...> wrapper is for verbatim URIs only */
570
- wr_put(w, (const char*)tdec.p, tdec.len);
610
+ yep_view rest = {tdec.p + 1, tdec.len - 1};
611
+ wr_byte(w, '!');
612
+ wr_tag_uri(w, &rest);
571
613
  wr_byte(w, ' ');
572
614
  return;
573
615
  }
574
616
  wr_byte(w, '!');
575
617
  wr_byte(w, '<');
576
- wr_put(w, (const char*)tdec.p, tdec.len);
618
+ wr_tag_uri(w, &tdec);
577
619
  wr_byte(w, '>');
578
620
  wr_byte(w, ' ');
579
621
  }
@@ -587,7 +629,7 @@ static void emit_props_tail(yep_writer* w, const yep_dnode* n) {
587
629
  yep_view tdec2 = wv(w, n->tag);
588
630
  wr_byte(w, '!');
589
631
  wr_byte(w, '<');
590
- wr_put(w, (const char*)tdec2.p, tdec2.len);
632
+ wr_tag_uri(w, &tdec2);
591
633
  wr_byte(w, '>');
592
634
  }
593
635
  if (n->anchor.len > 0) {
@@ -19,6 +19,7 @@
19
19
  #include "../../include/yeptris/values.h"
20
20
  #include "../common/simd_text.h"
21
21
  #include "../dom/dom.h"
22
+ #include "../encoding/encoding.h"
22
23
  #include "../memory/allocator.h"
23
24
  #include "../parse/engine.h"
24
25
  #include "../parse/numbers.h"
@@ -377,54 +378,91 @@ static int drain_json_route(const char* yaml, size_t len, yep_value_ctx** out) {
377
378
  * record array + arena, ownership moves to the caller. */
378
379
  int yep_values_from_input(const char* yaml, size_t len, int schema_compat, yep_value_ctx** out) {
379
380
  *out = NULL;
380
- if (looks_strict_json(yaml, len)) {
381
- int jrc = drain_json_route(yaml, len, out);
382
- if (jrc <= 0) {
383
- return jrc == 0 ? 0 : -1;
381
+ /* The encoding gate the parse entry owns (parse.c): the marshal/
382
+ * visit / value drains must not feed raw UTF-16/32 bytes to the
383
+ * engine while yeptris_parse accepts them — the nightly's marshal
384
+ * crasher (a UTF-16BE doc whose raw bytes contain "-s"). */
385
+ yep_encoding enc = YEP_ENC_UNKNOWN;
386
+ size_t bom = yep_bom_sniff((const unsigned char*)yaml, len, &enc);
387
+ const char* data = yaml + bom;
388
+ size_t data_len = len - bom;
389
+ unsigned char* transcoded = NULL;
390
+ const yep_allocator* sys = yep_system_allocator();
391
+ if (enc == YEP_ENC_UTF16LE || enc == YEP_ENC_UTF16BE || enc == YEP_ENC_UTF32LE ||
392
+ enc == YEP_ENC_UTF32BE) {
393
+ size_t tlen = 0;
394
+ size_t terr = 0;
395
+ int rc = yep_transcode_to_utf8(sys, enc, (const unsigned char*)data, data_len, &transcoded,
396
+ &tlen, &terr);
397
+ if (rc != 0) {
398
+ return -2;
399
+ }
400
+ size_t pverr = 0;
401
+ if (!yep_printable_validate(transcoded, tlen, &pverr)) {
402
+ yep_free(sys, transcoded);
403
+ return -2;
404
+ }
405
+ data = (const char*)transcoded;
406
+ data_len = tlen;
407
+ }
408
+ int prc_final = -2;
409
+ do {
410
+ if (looks_strict_json(data, data_len)) {
411
+ int jrc = drain_json_route(data, data_len, out);
412
+ if (jrc <= 0) {
413
+ prc_final = (jrc == 0) ? 0 : -1;
414
+ break;
415
+ }
416
+ /* fall through: engine */
417
+ }
418
+ yep_engine* eng = yep_engine_create(yep_system_allocator());
419
+ if (eng == NULL) {
420
+ return -1;
421
+ }
422
+ yep_engine_set_resolver(eng,
423
+ schema_compat ? yep_resolver_compat11() : yep_resolver_core12());
424
+ if (schema_compat) {
425
+ yep_engine_set_compat_grammar(eng, 1); /* libyaml grammar parity
426
+ * (the value drains ride the
427
+ * same compat contract) */
384
428
  }
385
- /* fall through: engine */
386
- }
387
- yep_engine* eng = yep_engine_create(yep_system_allocator());
388
- if (eng == NULL) {
389
- return -1;
390
- }
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
- }
397
429
 
398
- yep_value_ctx* c = ctx_create();
399
- if (c == NULL) {
400
- yep_engine_destroy(eng);
401
- return -1;
402
- }
403
- yep_rec_store store;
404
- yep_rec_init(&store);
430
+ yep_value_ctx* c = ctx_create();
431
+ if (c == NULL) {
432
+ yep_engine_destroy(eng);
433
+ return -1;
434
+ }
435
+ yep_rec_store store;
436
+ yep_rec_init(&store);
405
437
 
406
- int prc = -2;
407
- yep_sink sink = {.on_event = yep_rec_on_event,
408
- .ctx = &store,
409
- .on_flow_build = NULL,
410
- .on_flow_commit = NULL,
411
- .on_flow_rollback = NULL,
412
- .on_block_pair = NULL,
413
- .on_block_open = NULL,
414
- .on_block_item = NULL};
415
- /* strict JSON carries no anchors: no nametab reserve needed */
416
- if (yep_engine_run(eng, yaml, len, &sink) == 0 && transform(c, &store) == 0) {
417
- prc = 0;
418
- } else if (c->oom) {
419
- prc = -1;
420
- }
421
- yep_engine_destroy(eng);
422
- yep_rec_free(&store);
423
- if (prc != 0) {
424
- yep_value_ctx_free(c);
425
- return prc == -1 ? -1 : -2;
438
+ int prc = -2;
439
+ yep_sink sink = {.on_event = yep_rec_on_event,
440
+ .ctx = &store,
441
+ .on_flow_build = NULL,
442
+ .on_flow_commit = NULL,
443
+ .on_flow_rollback = NULL,
444
+ .on_block_pair = NULL,
445
+ .on_block_open = NULL,
446
+ .on_block_item = NULL};
447
+ /* strict JSON carries no anchors: no nametab reserve needed */
448
+ if (yep_engine_run(eng, data, data_len, &sink) == 0 && transform(c, &store) == 0) {
449
+ prc = 0;
450
+ } else if (c->oom) {
451
+ prc = -1;
452
+ }
453
+ yep_engine_destroy(eng);
454
+ yep_rec_free(&store);
455
+ if (prc != 0) {
456
+ yep_value_ctx_free(c);
457
+ break;
458
+ }
459
+ prc_final = ctx_finalize(c, out) == 0 ? 0 : -1;
460
+ } while (0);
461
+ yep_free(sys, transcoded);
462
+ if (prc_final != 0 && prc_final != -1) {
463
+ return -2;
426
464
  }
427
- return ctx_finalize(c, out) == 0 ? 0 : -1;
465
+ return prc_final;
428
466
  }
429
467
 
430
468
  static YeptrisStatus map_status(int rc) {
@@ -3112,6 +3112,17 @@ static int e_parse_value(yep_engine* e, yep_ctx ctx, uint16_t floor_col) {
3112
3112
  * fixture shape) */
3113
3113
  (vctx == YEP_CTX_VALUE_LINE && (li.first == '|' || li.first == '>') &&
3114
3114
  li.indent == floor_col)) {
3115
+ /* an empty-key ':' line cannot be a pending value's
3116
+ * content — libyaml errors ("did not find expected key";
3117
+ * the nightly's "- &a\n :" byte-instability crasher).
3118
+ * The same-line empty-key law lives in the shape arms. */
3119
+ if (li.first == ':') {
3120
+ size_t at2 = e->pos + li.indent + 1;
3121
+ if (at2 >= e->len || e->p[at2] == ' ' || e->p[at2] == '\t' || e->p[at2] == '\n' ||
3122
+ e->p[at2] == '\r') {
3123
+ return e_fail(e, YEP_ERR_UNEXPECTED, e->pos + li.indent);
3124
+ }
3125
+ }
3115
3126
  e->pos += li.indent;
3116
3127
  if (++e->rec >= e->max_depth) {
3117
3128
  e->rec--;
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.31.2
4
+ version: 0.6.32.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-10-09 00:00:00.000000000 Z
11
+ date: 2026-10-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi