yeptris 0.6.60.1-arm-linux-eabihf → 0.6.61.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 +4 -4
- data/ext/yeptris_native/version.h +2 -2
- data/lib/yeptris/yaml.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/include/yeptris/parse.h +21 -0
- data/vendor/libyeptris/src/yeptris/dom/dom.c +12 -1
- data/vendor/libyeptris/src/yeptris/dom/ytape.c +56 -7
- data/vendor/libyeptris/src/yeptris/emit/emit.c +8 -0
- data/vendor/libyeptris/src/yeptris/emit/writer.c +85 -10
- data/vendor/libyeptris/src/yeptris/emit/writer.h +10 -7
- data/vendor/libyeptris/src/yeptris/events/values.c +22 -0
- data/vendor/libyeptris/src/yeptris/parse/engine.c +490 -90
- data/vendor/libyeptris/src/yeptris/parse/engine.h +5 -0
- data/vendor/libyeptris/src/yeptris/parse/stream_iter.c +33 -1
- data/vendor/libyeptris/src/yeptris/parse.c +43 -1
- data/vendor/libyeptris/src/yeptris/resolve/compat11.c +2 -5
- data/vendor/libyeptris/src/yeptris/resolve/resolver.h +18 -0
- data/vendor/libyeptris/src/yeptris/resolve/tags.c +192 -0
- data/vendor/libyeptris/src/yeptris/scan/scan.c +22 -7
- data/vendor/libyeptris/src/yeptris/tape.c +24 -5
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 62af06f8d7d9384dde77c3cca415da00be7d70f65505119fd43a82fa9e0c9e1f
|
|
4
|
+
data.tar.gz: afc2489139cdc52bb5d7f2a96382150c9cb78eca767741a806cbdd2c231b66bd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f7d3ecc7415faae434ffb16d3bf6578d5aa9130c98dc6057a5dca4ceecf2a5d6737a213f70c8fd2538a9a8e5a4015b80b526e557d8382ca0800ca61b1a235f2b
|
|
7
|
+
data.tar.gz: 114d8c80fb7ada38b45b9bba05b44c6b7087c3b6dde852bcdc0004fabaaa13211742122f557adc6f21a1c2b61e0e7e0eda135bb5f1beafebdacf7f07f7585823
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
|
|
12
12
|
#define YEPTRIS_VERSION_MAJOR 0
|
|
13
13
|
#define YEPTRIS_VERSION_MINOR 6
|
|
14
|
-
#define YEPTRIS_VERSION_PATCH
|
|
15
|
-
#define YEPTRIS_VERSION_STRING "0.6.
|
|
14
|
+
#define YEPTRIS_VERSION_PATCH 61
|
|
15
|
+
#define YEPTRIS_VERSION_STRING "0.6.61"
|
|
16
16
|
|
|
17
17
|
#ifdef __cplusplus
|
|
18
18
|
extern "C" {
|
data/lib/yeptris/yaml.rb
CHANGED
|
@@ -350,6 +350,16 @@ module Yeptris
|
|
|
350
350
|
Yeptris::FFI::BUILD_END => END_ENTRY }.freeze
|
|
351
351
|
|
|
352
352
|
def dump(obj, canonical: false, header: false, width: nil)
|
|
353
|
+
# The nil root rides the bare form (psych's dump(nil) == "\n",
|
|
354
|
+
# #290): the engine's r201 quoted-form law ("a document-root
|
|
355
|
+
# empty scalar rides the quoted form" -- the plain form does not
|
|
356
|
+
# re-parse, the roundtrip invariant) renders the built empty
|
|
357
|
+
# scalar as "" -- correct for the engine's generic serializer,
|
|
358
|
+
# wrong for the psych surface. The binding maps an empty stream
|
|
359
|
+
# back to nil on load (load\#docs.empty?\#nil), so the bare form
|
|
360
|
+
# round-trips THROUGH THE BINDING while keeping the engine's
|
|
361
|
+
# invariant untouched.
|
|
362
|
+
return header ? "--- \n" : "\n" if obj.nil? && !canonical
|
|
353
363
|
parts = []
|
|
354
364
|
blob = String.new(encoding: Encoding::BINARY)
|
|
355
365
|
off = [0]
|
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.61.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
|
|
@@ -91,6 +91,27 @@ YEPTRIS_API YeptrisStatus yeptris_stream_iter_next(yeptris_stream_iter* it, Yept
|
|
|
91
91
|
YEPTRIS_API YeptrisStatus yeptris_stream_iter_status(const yeptris_stream_iter* it, uint32_t* line,
|
|
92
92
|
uint32_t* col);
|
|
93
93
|
|
|
94
|
+
/* The last successful step's document SLICE inside the iterator's
|
|
95
|
+
* buffer space (post-gate: BOM/transcode/normalization may have moved
|
|
96
|
+
* the buffer — the offsets are relative to the CURRENT buf the
|
|
97
|
+
* iterator holds, which is the space `yeptris_stream_iter_next`'s
|
|
98
|
+
* documents live in). Hosts that materialize through their own value
|
|
99
|
+
* route (the Python/Rust/TS drains) re-parse exactly these bytes and
|
|
100
|
+
* inherit the engine's framing without a DOM walk: one typing SSOT —
|
|
101
|
+
* the drain — and scanner-accurate frames. ARG on NULL; ARG when the
|
|
102
|
+
* last step was not a successful document. */
|
|
103
|
+
YEPTRIS_API YeptrisStatus yeptris_stream_iter_slice(const yeptris_stream_iter* it, size_t* off,
|
|
104
|
+
size_t* len);
|
|
105
|
+
|
|
106
|
+
/* The iterator's ACTIVE buffer (the caller's bytes, or the post-gate
|
|
107
|
+
* owned copy after a BOM strip / UTF-16-32 transcode / NEL-LS-PS
|
|
108
|
+
* normalization) and its length. `yeptris_stream_iter_slice`'s offsets
|
|
109
|
+
* index THIS buffer — hosts copy their frame bytes out of here
|
|
110
|
+
* (ctypes.string_at / Rust slice / TS Buffer) and re-parse them through
|
|
111
|
+
* their own drain. Borrowed: valid until yeptris_stream_iter_free. */
|
|
112
|
+
YEPTRIS_API YeptrisStatus yeptris_stream_iter_buffer(const yeptris_stream_iter* it,
|
|
113
|
+
const char** buf, size_t* len);
|
|
114
|
+
|
|
94
115
|
YEPTRIS_API void yeptris_stream_iter_free(yeptris_stream_iter* it);
|
|
95
116
|
|
|
96
117
|
#ifdef __cplusplus
|
|
@@ -158,7 +158,18 @@ static yep_sview dom_str_in(yep_dom* d, const yep_view* v, int borrowed) {
|
|
|
158
158
|
yep_sview sv = {0, 0};
|
|
159
159
|
return sv;
|
|
160
160
|
}
|
|
161
|
-
|
|
161
|
+
/* The zero-copy law: borrow ONLY a view demonstrably inside the
|
|
162
|
+
* recorded input window. The old heap-order probe (v->p >=
|
|
163
|
+
* input_base) misfiled every engine-owned buffer that happened to
|
|
164
|
+
* sit above the caller's input — the r171 normalizer copy path
|
|
165
|
+
* (norm_buf) hands exactly such views to the pair/event builders —
|
|
166
|
+
* and the resulting input-relative offset was then layout luck per
|
|
167
|
+
* platform/build (the ubuntu-gcc / MSVC-arm / TSan / UBSan CI
|
|
168
|
+
* divergences of PR #1042). The upper bound makes the decision a
|
|
169
|
+
* pure function of the view's location class: both engines of a
|
|
170
|
+
* differential run now store identically on every platform. */
|
|
171
|
+
if (borrowed && v->p != NULL && d->input_base != NULL &&
|
|
172
|
+
(size_t)((const char*)v->p - d->input_base) + v->len <= d->input_len) {
|
|
162
173
|
return yep_sv_input(d, *v);
|
|
163
174
|
}
|
|
164
175
|
return yep_dom_str_put(d, (const char*)v->p, v->len);
|
|
@@ -1640,15 +1640,64 @@ static int yt_f_run(yt_fused* F) {
|
|
|
1640
1640
|
col + 1 != st[depth].content_col && st[depth].phantom) {
|
|
1641
1641
|
yt_f_close(F, st[depth].kind);
|
|
1642
1642
|
st[depth].phantom = 0;
|
|
1643
|
+
st[depth].content_col =
|
|
1644
|
+
0; /* the content map is gone:
|
|
1645
|
+
* its column must not greet later pairs (the
|
|
1646
|
+
* stale-frame law, run 38179552341) — after the
|
|
1647
|
+
* chained-pending arm resumes here, a stale
|
|
1648
|
+
* column rode yt_f_open_form's sibling test and
|
|
1649
|
+
* misfiled the next pending's container as a
|
|
1650
|
+
* key-SCALAR ("b:\n c: d\nq:\n b:\n c: d\n"
|
|
1651
|
+
* lost q's map; the nightly's run 42488986434) */
|
|
1643
1652
|
}
|
|
1644
1653
|
if (depth > 0 && st[depth].pending) {
|
|
1645
|
-
/* chained
|
|
1646
|
-
*
|
|
1647
|
-
*
|
|
1648
|
-
*
|
|
1649
|
-
*
|
|
1650
|
-
*
|
|
1651
|
-
|
|
1654
|
+
/* a chained pending ("a:\na:", the deep-nesting
|
|
1655
|
+
* "k:\n k:\n k:" ladder): resolve the outer
|
|
1656
|
+
* one before the sibling's frame takes the slot.
|
|
1657
|
+
* A same-column sibling key (col == the pending's
|
|
1658
|
+
* own column) gives the pending a NULL value —
|
|
1659
|
+
* the null pair MUST land now, or the OPEN'd
|
|
1660
|
+
* container swallows the sibling key as its
|
|
1661
|
+
* first pair's value (the nightly's run
|
|
1662
|
+
* 38110714729 tree corruption: {a: a, ?{b: c}:
|
|
1663
|
+
* h} instead of {a: null, a: {b: c}, h: v}).
|
|
1664
|
+
* When the OPEN form fired, the null pairs
|
|
1665
|
+
* INSIDE the opened container (parent → {k:
|
|
1666
|
+
* null}); under the key-SCALAR form it completes
|
|
1667
|
+
* the key's pair in the parent's map. A deeper
|
|
1668
|
+
* line (col > indent) opens the pending's
|
|
1669
|
+
* container and the chain nests. Anchored
|
|
1670
|
+
* pendings keep the engine: their anchor rides
|
|
1671
|
+
* the event path (yt_f_open drops the name) */
|
|
1672
|
+
if (st[depth].aid != 0) {
|
|
1673
|
+
return 1;
|
|
1674
|
+
}
|
|
1675
|
+
uint8_t of = yt_f_open_form(&st[depth - 1], depth == 1, st[depth].indent);
|
|
1676
|
+
if (aid != 0 && of == 0) {
|
|
1677
|
+
/* the outer pending resolved as a SIBLING
|
|
1678
|
+
* key-SCALAR: its value container is "the pair's",
|
|
1679
|
+
* materialized by the next OPEN-class record — but
|
|
1680
|
+
* the anchored pending resolves through the event
|
|
1681
|
+
* path, which emits its KEY SCALAR *before* the
|
|
1682
|
+
* anchored MAP_START. That key pairs with the
|
|
1683
|
+
* stranded outer key (the pair's value slot) and
|
|
1684
|
+
* the anchored map strands as a sibling key of the
|
|
1685
|
+
* parent: "2: e\n4:\n 5: &5\n 5: e\n7: s"
|
|
1686
|
+
* built {2:e, 4:"5", {5:e}&5:"7", s:null} instead
|
|
1687
|
+
* of {2:e, 4:{5:{5:e}&5}, 7:s} (the nightly's
|
|
1688
|
+
* crash-d8e3b3f392c37a62257576ce20d5a19b351f66ad,
|
|
1689
|
+
* round 213 — the first shape where a completed
|
|
1690
|
+
* pair arms root_pair_col BEFORE the chain). The
|
|
1691
|
+
* engine resolves the composition. */
|
|
1692
|
+
return 1;
|
|
1693
|
+
}
|
|
1694
|
+
yt_f_open(F, &st[depth], of);
|
|
1695
|
+
root_open = 1;
|
|
1696
|
+
if (col == st[depth].indent) {
|
|
1697
|
+
(void)yt_put(t, yt_props(YTP_SCALAR, 0, 0x0904u));
|
|
1698
|
+
yt_f_empty_span(F);
|
|
1699
|
+
}
|
|
1700
|
+
st[depth].pending = 0;
|
|
1652
1701
|
}
|
|
1653
1702
|
/* a spent key-SCALAR frame (resolved, phantom closed,
|
|
1654
1703
|
* no map of its own) gives its slot to the sibling —
|
|
@@ -112,6 +112,7 @@ YEPTRIS_API size_t yeptris_serialize_into_ex(YeptrisDocument handle,
|
|
|
112
112
|
em.w.col = 0;
|
|
113
113
|
em.w.sv_input = handle ? ((const yeptris_document*)handle)->dom->input_base : NULL;
|
|
114
114
|
em.w.sv_arena = handle ? ((const yeptris_document*)handle)->dom->str : NULL;
|
|
115
|
+
em.w.resolver = handle ? ((const yeptris_document*)handle)->dom->resolver : NULL;
|
|
115
116
|
em.w.sink = NULL;
|
|
116
117
|
em.w.watermark = 0;
|
|
117
118
|
em.w.sink_aborted = 0;
|
|
@@ -181,6 +182,7 @@ YEPTRIS_API size_t yeptris_serialize_into_trusted(YeptrisDocument handle,
|
|
|
181
182
|
em.w.col = 0;
|
|
182
183
|
em.w.sv_input = ((const yeptris_document*)handle)->dom->input_base;
|
|
183
184
|
em.w.sv_arena = ((const yeptris_document*)handle)->dom->str;
|
|
185
|
+
em.w.resolver = ((const yeptris_document*)handle)->dom->resolver;
|
|
184
186
|
em.w.sink = NULL;
|
|
185
187
|
em.w.watermark = 0;
|
|
186
188
|
em.w.sink_aborted = 0;
|
|
@@ -249,6 +251,7 @@ YEPTRIS_API char* yeptris_serialize_ex(YeptrisDocument handle, const yeptris_emi
|
|
|
249
251
|
em.w.col = 0;
|
|
250
252
|
em.w.sv_input = handle ? ((const yeptris_document*)handle)->dom->input_base : NULL;
|
|
251
253
|
em.w.sv_arena = handle ? ((const yeptris_document*)handle)->dom->str : NULL;
|
|
254
|
+
em.w.resolver = handle ? ((const yeptris_document*)handle)->dom->resolver : NULL;
|
|
252
255
|
em.w.sink = NULL;
|
|
253
256
|
em.w.watermark = 0;
|
|
254
257
|
em.w.sink_aborted = 0;
|
|
@@ -390,6 +393,7 @@ YEPTRIS_API char* yeptris_serialize_json(YeptrisDocument handle, size_t* len) {
|
|
|
390
393
|
em.w.col = 0;
|
|
391
394
|
em.w.sv_input = handle ? ((const yeptris_document*)handle)->dom->input_base : NULL;
|
|
392
395
|
em.w.sv_arena = handle ? ((const yeptris_document*)handle)->dom->str : NULL;
|
|
396
|
+
em.w.resolver = handle ? ((const yeptris_document*)handle)->dom->resolver : NULL;
|
|
393
397
|
em.w.sink = NULL;
|
|
394
398
|
em.w.watermark = 0;
|
|
395
399
|
em.w.sink_aborted = 0;
|
|
@@ -434,6 +438,7 @@ YEPTRIS_API char* yeptris_serialize_json_ex(YeptrisDocument handle, size_t* len,
|
|
|
434
438
|
em.w.col = 0;
|
|
435
439
|
em.w.sv_input = handle ? ((const yeptris_document*)handle)->dom->input_base : NULL;
|
|
436
440
|
em.w.sv_arena = handle ? ((const yeptris_document*)handle)->dom->str : NULL;
|
|
441
|
+
em.w.resolver = handle ? ((const yeptris_document*)handle)->dom->resolver : NULL;
|
|
437
442
|
em.w.sink = NULL;
|
|
438
443
|
em.w.watermark = 0;
|
|
439
444
|
em.w.sink_aborted = 0;
|
|
@@ -480,6 +485,7 @@ char* yep_serialize_json_compact(const yeptris_document* doc, size_t* len) {
|
|
|
480
485
|
em.w.col = 0;
|
|
481
486
|
em.w.sv_input = doc->dom->input_base;
|
|
482
487
|
em.w.sv_arena = doc->dom->str;
|
|
488
|
+
em.w.resolver = doc->dom->resolver;
|
|
483
489
|
em.w.sink = NULL;
|
|
484
490
|
em.w.watermark = 0;
|
|
485
491
|
em.w.sink_aborted = 0;
|
|
@@ -528,6 +534,7 @@ char* yep_serialize_json_pretty_ex(const yeptris_document* doc, size_t* len, con
|
|
|
528
534
|
em.w.col = 0;
|
|
529
535
|
em.w.sv_input = doc->dom->input_base;
|
|
530
536
|
em.w.sv_arena = doc->dom->str;
|
|
537
|
+
em.w.resolver = doc->dom->resolver;
|
|
531
538
|
em.w.sink = NULL;
|
|
532
539
|
em.w.watermark = 0;
|
|
533
540
|
em.w.sink_aborted = 0;
|
|
@@ -604,6 +611,7 @@ YEPTRIS_API size_t yeptris_serialize_stream(YeptrisDocument handle,
|
|
|
604
611
|
em.w.col = 0;
|
|
605
612
|
em.w.sv_input = handle ? ((const yeptris_document*)handle)->dom->input_base : NULL;
|
|
606
613
|
em.w.sv_arena = handle ? ((const yeptris_document*)handle)->dom->str : NULL;
|
|
614
|
+
em.w.resolver = handle ? ((const yeptris_document*)handle)->dom->resolver : NULL;
|
|
607
615
|
em.w.sink = sink;
|
|
608
616
|
em.w.sink_ctx = ctx;
|
|
609
617
|
em.w.watermark = YEP_EMIT_WATERMARK;
|
|
@@ -539,7 +539,33 @@ static void emit_literal(yep_writer* w, const yep_dnode* n, int parent_col) {
|
|
|
539
539
|
/* Canonical scalar (13B): typed words and numbers plain, everything
|
|
540
540
|
* else double-quoted; floats re-print through the shortest printer so
|
|
541
541
|
* canonical output is a fixed point (parse of canonical re-prints
|
|
542
|
-
* identically — the byte-stability gate).
|
|
542
|
+
* identically — the byte-stability gate). The DOM stores only the tag
|
|
543
|
+
* + source text, so the typed arms re-derive the VALUE from the
|
|
544
|
+
* resolver's own tables (#937): the bool table decides true/false
|
|
545
|
+
* (the old length guess spelled every non-4-char true-word false), the
|
|
546
|
+
* int decode spells JSON-unspellable forms (0x1F/0o7) in decimal, and
|
|
547
|
+
* the inf/nan words ride quoted in JSON mode (no JSON infinity). */
|
|
548
|
+
static int json_int_token(const char* p, uint32_t n) {
|
|
549
|
+
/* the strict JSON int token: -?(0|[1-9][0-9]*) — leading zeros
|
|
550
|
+
* and a '+' are YAML-spellable but not JSON (those decode) */
|
|
551
|
+
uint32_t i = 0;
|
|
552
|
+
if (i < n && p[0] == '-') {
|
|
553
|
+
i = 1;
|
|
554
|
+
}
|
|
555
|
+
if (i >= n) {
|
|
556
|
+
return 0;
|
|
557
|
+
}
|
|
558
|
+
if (p[i] == '0') {
|
|
559
|
+
return i + 1 == n;
|
|
560
|
+
}
|
|
561
|
+
for (uint32_t k = i; k < n; k++) {
|
|
562
|
+
if (p[k] < '0' || p[k] > '9') {
|
|
563
|
+
return 0;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
return 1;
|
|
567
|
+
}
|
|
568
|
+
|
|
543
569
|
static void emit_canonical_scalar(yep_writer* w, const yep_dnode* n) {
|
|
544
570
|
yep_view vdec = wv(w, n->value);
|
|
545
571
|
const char* p = (const char*)vdec.p;
|
|
@@ -553,17 +579,24 @@ static void emit_canonical_scalar(yep_writer* w, const yep_dnode* n) {
|
|
|
553
579
|
wr_put(w, "~", 1);
|
|
554
580
|
}
|
|
555
581
|
return;
|
|
556
|
-
case YEPTRIS_TAG_BOOL:
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
582
|
+
case YEPTRIS_TAG_BOOL: {
|
|
583
|
+
int bv = yep_tag_bool_value(p, len);
|
|
584
|
+
if (bv < 0) {
|
|
585
|
+
break; /* not a bool word: quoted (the resolver only
|
|
586
|
+
tags the table's words; defense) */
|
|
561
587
|
}
|
|
588
|
+
wr_put(w, bv ? "true" : "false", bv ? 4u : 5u);
|
|
562
589
|
return;
|
|
590
|
+
}
|
|
563
591
|
case YEPTRIS_TAG_FLOAT: {
|
|
564
592
|
const char* word = yep_tag_float_word(p, len);
|
|
565
593
|
if (word != NULL) {
|
|
566
|
-
|
|
594
|
+
uint32_t wl = (uint32_t)strlen(word);
|
|
595
|
+
if (w->json) {
|
|
596
|
+
emit_dq_json(w, word, wl);
|
|
597
|
+
} else {
|
|
598
|
+
wr_put(w, word, wl);
|
|
599
|
+
}
|
|
567
600
|
return;
|
|
568
601
|
}
|
|
569
602
|
char buf[40];
|
|
@@ -584,8 +617,23 @@ static void emit_canonical_scalar(yep_writer* w, const yep_dnode* n) {
|
|
|
584
617
|
break; /* unparseable view: fall through to quoting */
|
|
585
618
|
}
|
|
586
619
|
case YEPTRIS_TAG_INT:
|
|
587
|
-
|
|
588
|
-
|
|
620
|
+
if (!w->json || json_int_token(p, len)) {
|
|
621
|
+
/* YAML keeps the source text (stable, lossless); JSON
|
|
622
|
+
* keeps JSON-number-shaped text (big ints stay exact) */
|
|
623
|
+
wr_put(w, p, len);
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
{
|
|
627
|
+
int compat = w->resolver == yep_resolver_compat11();
|
|
628
|
+
int64_t v;
|
|
629
|
+
if (yep_tag_int64(p, len, compat, &v) == 0) {
|
|
630
|
+
char buf[24];
|
|
631
|
+
int nl = snprintf(buf, sizeof buf, "%lld", (long long)v);
|
|
632
|
+
wr_put(w, buf, (uint32_t)nl);
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
break; /* undecodable int text: quoted keeps JSON valid */
|
|
589
637
|
default:
|
|
590
638
|
break;
|
|
591
639
|
}
|
|
@@ -1602,6 +1650,24 @@ static void emit_node(yep_emitter* em, uint32_t id, int parent_col, int as_key)
|
|
|
1602
1650
|
}
|
|
1603
1651
|
emit_tag(w, n);
|
|
1604
1652
|
emit_anchor_ex(em, n);
|
|
1653
|
+
if (parent_col < 0 && !w->canonical && !w->json && n->kind == 0 && n->style <= 1) {
|
|
1654
|
+
/* A DOCUMENT-ROOT empty scalar rides the quoted form: libyaml
|
|
1655
|
+
* renders "--- ''" and never a bare marker with nothing after
|
|
1656
|
+
* it. A plain-empty root emitted as NOTHING (the value law of
|
|
1657
|
+
* issue #290, "k:" — kept below for non-root contexts) sheds
|
|
1658
|
+
* the root node entirely; the re-parse of that stream produced
|
|
1659
|
+
* an ANY-styled empty root whose render is "" — and the bytes
|
|
1660
|
+
* diverged on round two (the nightly's r201 fuzz_roundtrip
|
|
1661
|
+
* byte-instability catch, ">\n! \n !<aaa: bbb\n...\n<NEL><NEL>",
|
|
1662
|
+
* whose second document's break-only content parses to a
|
|
1663
|
+
* plain-empty root). Quoting the root's emptiness makes every
|
|
1664
|
+
* empty-root spelling converge on the same fixpoint bytes. */
|
|
1665
|
+
yep_view vdec = wv(w, n->value);
|
|
1666
|
+
if (vdec.len == 0) {
|
|
1667
|
+
emit_dq(w, (const char*)vdec.p, vdec.len);
|
|
1668
|
+
return;
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1605
1671
|
if (parent_col < 0) {
|
|
1606
1672
|
parent_col = 0; /* root scalar: block body at column 2 */
|
|
1607
1673
|
}
|
|
@@ -1755,7 +1821,16 @@ size_t yep_emit_run(yep_emitter* em, int dry) {
|
|
|
1755
1821
|
yep_view tdec3 = wv(w, root->tag);
|
|
1756
1822
|
wr_tag_token(w, &tdec3);
|
|
1757
1823
|
}
|
|
1758
|
-
if (root->anchor.len > 0) {
|
|
1824
|
+
if (root->anchor.len > 0 && !anchor_name_unspellable(w, root)) {
|
|
1825
|
+
/* the r235 law: the lead line writes the name UNQUOTED
|
|
1826
|
+
* and anchor names have no quoting -- a name the spell
|
|
1827
|
+
* law rejects has no safe lead-line spelling. The r235
|
|
1828
|
+
* nightly's riding-colon names ("&:" and the artifact's
|
|
1829
|
+
* "&k:\"" — run 42739927952, crash-5de6f9ff) re-parsed
|
|
1830
|
+
* as an anchored empty KEY of the follow-on collection
|
|
1831
|
+
* (the anchor lost, s1 != s2, byte growth); the
|
|
1832
|
+
* colon-tail law fails the serialize like every other
|
|
1833
|
+
* anchor write path (the r228 "&: |" law) */
|
|
1759
1834
|
if (root->tag.len > 0) {
|
|
1760
1835
|
wr_byte(w, ' '); /* props need the separator */
|
|
1761
1836
|
}
|
|
@@ -69,13 +69,16 @@ typedef struct yep_writer {
|
|
|
69
69
|
* grow/flush checks run once per refill instead of once per byte;
|
|
70
70
|
* 0 at run entry and whenever the guarantee lapses. */
|
|
71
71
|
size_t reserve;
|
|
72
|
-
int in_flow;
|
|
73
|
-
|
|
74
|
-
int flow_item;
|
|
75
|
-
|
|
76
|
-
int unserializable;
|
|
77
|
-
|
|
78
|
-
|
|
72
|
+
int in_flow; /* scalars inside flow collections: plain must drop
|
|
73
|
+
',', '[', ']', '{', '}' — flow terminators */
|
|
74
|
+
int flow_item; /* the NEXT scalar is a flow-SEQ item: a null must
|
|
75
|
+
emit '~' (a bare nothing reads as "[, x]") */
|
|
76
|
+
int unserializable; /* an anchor name that cannot ride raw in flow
|
|
77
|
+
context: the document has no safe spelling —
|
|
78
|
+
serialize fails rather than corrupt */
|
|
79
|
+
const struct yep_resolver* resolver; /* the document's implicit-typing
|
|
80
|
+
family (NULL = core12): the INT arm's decode needs the family's
|
|
81
|
+
own forms (leading-0 is octal in compat, decimal in core) */
|
|
79
82
|
} yep_writer;
|
|
80
83
|
|
|
81
84
|
typedef struct yep_emitter {
|
|
@@ -452,6 +452,28 @@ int yep_values_from_input(const char* yaml, size_t len, int schema_compat, yep_v
|
|
|
452
452
|
}
|
|
453
453
|
/* fall through: engine */
|
|
454
454
|
}
|
|
455
|
+
/* Unicode breaks (NEL/LS/PS) normalize to '\n' BEFORE the
|
|
456
|
+
* engine, exactly as the parse entry's front-end does
|
|
457
|
+
* (parse_frontend): this drain feeds the SAME compat-grammar
|
|
458
|
+
* engine, and a raw NEL it never normalized errors where
|
|
459
|
+
* parse accepts -- the nightly's round 239 roundtrip catch
|
|
460
|
+
* ("<NEL>...<NEL> >\n <NEL>...<NEL>\nt": marshal returned
|
|
461
|
+
* ERROR_PARSE on a document yeptris_parse_ex accepted and
|
|
462
|
+
* serialized cleanly). JSON stays above this: the JSON reader
|
|
463
|
+
* keeps U+0085 raw inside strings, only the YAML reader
|
|
464
|
+
* normalizes (the parse_frontend law). Ownership rides the
|
|
465
|
+
* same `transcoded` plumbing the transcode above installed. */
|
|
466
|
+
{
|
|
467
|
+
size_t nlen = 0;
|
|
468
|
+
int kept_raw = 0;
|
|
469
|
+
char* norm = yep_engine_normalize_breaks(sys, data, data_len, &nlen, &kept_raw);
|
|
470
|
+
if (norm != NULL) {
|
|
471
|
+
yep_free(sys, transcoded);
|
|
472
|
+
transcoded = (unsigned char*)norm;
|
|
473
|
+
data = (const char*)norm;
|
|
474
|
+
data_len = nlen;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
455
477
|
yep_engine* eng = yep_engine_create(yep_system_allocator());
|
|
456
478
|
if (eng == NULL) {
|
|
457
479
|
return -1;
|