yeptris 0.6.35.2-aarch64-linux → 0.6.37.0-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/4.0/native.so +0 -0
- data/lib/yeptris/document.rb +11 -0
- data/lib/yeptris/ffi.rb +8 -0
- data/lib/yeptris/json.rb +12 -2
- data/lib/yeptris.rb +1 -1
- data/libyeptris.so +0 -0
- data/vendor/libyeptris/CMakeLists.txt +1 -1
- data/vendor/libyeptris/src/include/yeptris/json.h +10 -0
- data/vendor/libyeptris/src/yeptris/emit/emit.c +18 -0
- data/vendor/libyeptris/src/yeptris/emit/writer.c +16 -4
- data/vendor/libyeptris/src/yeptris/emit/writer.h +4 -0
- data/vendor/libyeptris/src/yeptris/marshal.c +11 -1
- data/vendor/libyeptris/src/yeptris/parse/engine.c +137 -43
- 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: 0b9695f8f9e37a623dbe567e66018e50f6afb6ae479d0a0f42218ed2ca011dc8
|
|
4
|
+
data.tar.gz: '08c35c1d8e5eb686e0f573272bc9bf20cf9b17ab060a502c0d1de8c83e4a6e4d'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4c3dc61e302319370012a822c4e813df1c6f8fcb90b5a07719db5a824c7f80dcba2e90567d451ca560e71c92c4eebbfa93f869ff452ef243722a24c8f05c3e04
|
|
7
|
+
data.tar.gz: b3f3771a5d06f58c2e404af154cca6257dab478a1ad19b8c59515b0573532c599d2e4bdc4e64dec4c4c6b801c4f7e9874b295a52e911b9e57d60aa3764c3b5d3
|
data/lib/yeptris/4.0/native.so
CHANGED
|
Binary file
|
data/lib/yeptris/document.rb
CHANGED
|
@@ -202,6 +202,17 @@ class Yeptris::Document
|
|
|
202
202
|
Yeptris::FFI::Owned.string(Yeptris::FFI.yeptris_serialize_json_ex(@c_ptr, len, 1), len)
|
|
203
203
|
end
|
|
204
204
|
|
|
205
|
+
# JSON.pretty_generate's shape; nil indent rides the engine default
|
|
206
|
+
# (two spaces), any other String's bytes ride verbatim per depth
|
|
207
|
+
def serialize_json_pretty(indent = nil)
|
|
208
|
+
ensure_alive!
|
|
209
|
+
len = ::FFI::MemoryPointer.new(:size_t)
|
|
210
|
+
data = indent&.b
|
|
211
|
+
Yeptris::FFI::Owned.string(
|
|
212
|
+
Yeptris::FFI.yeptris_serialize_json_pretty(@c_ptr, len, data, data ? data.bytesize : 0), len
|
|
213
|
+
)
|
|
214
|
+
end
|
|
215
|
+
|
|
205
216
|
def serialize_json
|
|
206
217
|
ensure_alive!
|
|
207
218
|
len = ::FFI::MemoryPointer.new(:size_t)
|
data/lib/yeptris/ffi.rb
CHANGED
|
@@ -276,6 +276,14 @@ module Yeptris
|
|
|
276
276
|
false
|
|
277
277
|
end
|
|
278
278
|
|
|
279
|
+
# pretty JSON generation (JSON.pretty_generate's shape); the JSON
|
|
280
|
+
# surface feature-detects via the @missing convention below (the
|
|
281
|
+
# deferred stub records the miss at attach, so a begin/rescue
|
|
282
|
+
# never fires)
|
|
283
|
+
attach_function :yeptris_serialize_json_pretty,
|
|
284
|
+
%i[yeptris_document pointer pointer size_t], :pointer
|
|
285
|
+
JSON_PRETTY = !(@missing ||= []).include?(:yeptris_serialize_json_pretty)
|
|
286
|
+
|
|
279
287
|
# CBOR (RFC 8949, TODO.cbor): absent on libraries before the
|
|
280
288
|
# codec's release — the CBOR module feature-detects
|
|
281
289
|
attach_function :yeptris_cbor_decode, %i[pointer size_t uint32 yeptris_status_out],
|
data/lib/yeptris/json.rb
CHANGED
|
@@ -367,7 +367,7 @@ module Yeptris
|
|
|
367
367
|
# and null stay plain), Symbols become their name.
|
|
368
368
|
class DumpError < Error; end
|
|
369
369
|
|
|
370
|
-
def dump(obj)
|
|
370
|
+
def dump(obj, pretty: false, indent: " ")
|
|
371
371
|
parts = String.new(encoding: Encoding::BINARY,
|
|
372
372
|
capacity: 12 * 16) # 12-byte entries, appended in place
|
|
373
373
|
blob = String.new(encoding: Encoding::BINARY)
|
|
@@ -377,7 +377,17 @@ module Yeptris
|
|
|
377
377
|
# FFI passes String args BY REFERENCE — no MemoryPointer copies
|
|
378
378
|
rc = doc.build_entries(parts, parts.bytesize / 12, blob, blob.bytesize)
|
|
379
379
|
raise DumpError, "document_build failed: #{rc}" unless rc == ::Yeptris::FFI::OK
|
|
380
|
-
out =
|
|
380
|
+
out =
|
|
381
|
+
if pretty
|
|
382
|
+
unless ::Yeptris::FFI::JSON_PRETTY
|
|
383
|
+
raise DumpError, "pretty JSON needs a libyeptris with yeptris_serialize_json_pretty"
|
|
384
|
+
end
|
|
385
|
+
doc.serialize_json_pretty(indent)
|
|
386
|
+
elsif ::Yeptris::FFI::JSON_EX
|
|
387
|
+
doc.serialize_json_compact
|
|
388
|
+
else
|
|
389
|
+
doc.serialize_json
|
|
390
|
+
end
|
|
381
391
|
# JSON.generate emits no trailing newline (the document writer does)
|
|
382
392
|
out.end_with?("\n") ? out[0, out.bytesize - 1] : out
|
|
383
393
|
ensure
|
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.37.0".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
|
|
@@ -38,6 +38,16 @@ YEPTRIS_API char* yeptris_serialize_json(YeptrisDocument doc, size_t* len);
|
|
|
38
38
|
* compact == 0 is byte-identical to yeptris_serialize_json. */
|
|
39
39
|
YEPTRIS_API char* yeptris_serialize_json_ex(YeptrisDocument doc, size_t* len, int compact);
|
|
40
40
|
|
|
41
|
+
/* The pretty variant: JSON.pretty_generate's shape — one entry per
|
|
42
|
+
* line, ": " after keys, ",\n" + indent between entries, empty
|
|
43
|
+
* collections inline. indent/indent_len select the indent unit
|
|
44
|
+
* (NULL/0 = two spaces; the bytes are written verbatim per depth).
|
|
45
|
+
* Memory: returns a malloc'd NUL-terminated buffer (caller frees)
|
|
46
|
+
* with *len (may be NULL) set, or NULL on a NULL document /
|
|
47
|
+
* allocation failure / zero documents. */
|
|
48
|
+
YEPTRIS_API char* yeptris_serialize_json_pretty(YeptrisDocument doc, size_t* len,
|
|
49
|
+
const char* indent, size_t indent_len);
|
|
50
|
+
|
|
41
51
|
#ifdef __cplusplus
|
|
42
52
|
}
|
|
43
53
|
#endif
|
|
@@ -308,6 +308,14 @@ YEPTRIS_API char* yeptris_serialize_json_ex(YeptrisDocument handle, size_t* len,
|
|
|
308
308
|
return out;
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
+
YEPTRIS_API char* yeptris_serialize_json_pretty(YeptrisDocument handle, size_t* len,
|
|
312
|
+
const char* indent, size_t indent_len) {
|
|
313
|
+
if (handle == NULL) {
|
|
314
|
+
return NULL;
|
|
315
|
+
}
|
|
316
|
+
return yep_serialize_json_pretty_ex((const yeptris_document*)handle, len, indent, indent_len);
|
|
317
|
+
}
|
|
318
|
+
|
|
311
319
|
char* yep_serialize_json_compact(const yeptris_document* doc, size_t* len) {
|
|
312
320
|
if (doc == NULL) {
|
|
313
321
|
return NULL;
|
|
@@ -364,9 +372,17 @@ char* yep_serialize_json_compact(const yeptris_document* doc, size_t* len) {
|
|
|
364
372
|
}
|
|
365
373
|
|
|
366
374
|
char* yep_serialize_json_pretty(const yeptris_document* doc, size_t* len) {
|
|
375
|
+
return yep_serialize_json_pretty_ex(doc, len, NULL, 2);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
char* yep_serialize_json_pretty_ex(const yeptris_document* doc, size_t* len, const char* indent,
|
|
379
|
+
size_t indent_len) {
|
|
367
380
|
if (doc == NULL) {
|
|
368
381
|
return NULL;
|
|
369
382
|
}
|
|
383
|
+
if (yep_doc_dom((yeptris_document*)doc) == NULL) { /* #342 lazy */
|
|
384
|
+
return NULL;
|
|
385
|
+
}
|
|
370
386
|
yep_emitter em;
|
|
371
387
|
em.w.sc_dec = NULL;
|
|
372
388
|
em.w.sc_i = 0;
|
|
@@ -386,6 +402,8 @@ char* yep_serialize_json_pretty(const yeptris_document* doc, size_t* len) {
|
|
|
386
402
|
em.w.json_compact = 0;
|
|
387
403
|
em.w.json_pretty = 1;
|
|
388
404
|
em.w.pretty_depth = 0;
|
|
405
|
+
em.w.json_indent = indent;
|
|
406
|
+
em.w.json_indent_len = indent == NULL ? 2 : (int)indent_len;
|
|
389
407
|
em.w.best_width = 0;
|
|
390
408
|
em.w.col = 0;
|
|
391
409
|
em.w.sv_input = doc->dom->input_base;
|
|
@@ -139,6 +139,18 @@ static void wr_indent(yep_writer* w, int depth) {
|
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
+
/* json_pretty's per-depth indent: the default two spaces per level,
|
|
143
|
+
* or depth copies of the caller's unit (json.h pretty entry). */
|
|
144
|
+
static void wr_pretty_indent(yep_writer* w, int depth) {
|
|
145
|
+
if (w->json_indent == NULL) {
|
|
146
|
+
wr_indent(w, depth * 2);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
for (int i = 0; i < depth; i++) {
|
|
150
|
+
wr_put(w, w->json_indent, (uint32_t)w->json_indent_len);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
142
154
|
static void emit_dq(yep_writer* w, const char* p, uint32_t n) {
|
|
143
155
|
wr_byte(w, '"');
|
|
144
156
|
uint32_t run = 0;
|
|
@@ -899,9 +911,9 @@ static void emit_flow(yep_emitter* em, uint32_t id) {
|
|
|
899
911
|
int flow_indent = w->col;
|
|
900
912
|
if (w->json_pretty && n->count > 0) {
|
|
901
913
|
w->pretty_depth++;
|
|
902
|
-
flow_indent = w->pretty_depth * 2; /* 2 spaces per level */
|
|
903
914
|
wr_byte(w, '\n');
|
|
904
|
-
|
|
915
|
+
wr_pretty_indent(w, w->pretty_depth);
|
|
916
|
+
flow_indent = w->col;
|
|
905
917
|
}
|
|
906
918
|
uint32_t child = n->first_child;
|
|
907
919
|
uint32_t idx = 0;
|
|
@@ -913,7 +925,7 @@ static void emit_flow(yep_emitter* em, uint32_t id) {
|
|
|
913
925
|
* re-indent to the opening bracket's column */
|
|
914
926
|
if (w->json_pretty) {
|
|
915
927
|
wr_put(w, ",\n", 2);
|
|
916
|
-
|
|
928
|
+
wr_pretty_indent(w, w->pretty_depth);
|
|
917
929
|
} else if (w->json_compact) {
|
|
918
930
|
wr_byte(w, ',');
|
|
919
931
|
} else if (w->best_width > 0 && w->col > w->best_width) {
|
|
@@ -964,7 +976,7 @@ static void emit_flow(yep_emitter* em, uint32_t id) {
|
|
|
964
976
|
}
|
|
965
977
|
if (w->json_pretty && idx > 0) {
|
|
966
978
|
wr_byte(w, '\n');
|
|
967
|
-
|
|
979
|
+
wr_pretty_indent(w, w->pretty_depth - 1);
|
|
968
980
|
w->pretty_depth--;
|
|
969
981
|
}
|
|
970
982
|
wr_byte(w, map ? '}' : ']');
|
|
@@ -35,6 +35,8 @@ typedef struct yep_writer {
|
|
|
35
35
|
int json_compact; /* json-c to_json_string: no padding spaces */
|
|
36
36
|
int json_pretty; /* json-c PRETTY: 2-space indent, per-entry lines */
|
|
37
37
|
int pretty_depth; /* json_pretty nesting level (indent = 2*depth) */
|
|
38
|
+
const char* json_indent; /* json_pretty indent unit; NULL = 2 spaces */
|
|
39
|
+
int json_indent_len; /* json_pretty unit byte length */
|
|
38
40
|
int best_width; /* 13B: 0 = default 80; flow lines wrap after a
|
|
39
41
|
* value past this width */
|
|
40
42
|
int col; /* current output column (wr_* maintains) */
|
|
@@ -79,5 +81,7 @@ size_t yep_emit_run(yep_emitter* em, int dry);
|
|
|
79
81
|
* nesting level, one entry per line. */
|
|
80
82
|
char* yep_serialize_json_compact(const yeptris_document* doc, size_t* len);
|
|
81
83
|
char* yep_serialize_json_pretty(const yeptris_document* doc, size_t* len);
|
|
84
|
+
char* yep_serialize_json_pretty_ex(const yeptris_document* doc, size_t* len, const char* indent,
|
|
85
|
+
size_t indent_len);
|
|
82
86
|
|
|
83
87
|
#endif /* YEP_EMIT_WRITER_H */
|
|
@@ -815,7 +815,17 @@ static int strict_dup_scan(const yep_value_ctx* c) {
|
|
|
815
815
|
}
|
|
816
816
|
continue;
|
|
817
817
|
}
|
|
818
|
-
|
|
818
|
+
/* name the key like the tape walk's message (json 3 names it
|
|
819
|
+
* too): the arena bytes are the text for the str-like kinds,
|
|
820
|
+
* which is every JSON key */
|
|
821
|
+
if (k.kind == YEP_V_STR || k.kind == YEP_V_TIMESTAMP || k.kind == YEP_V_ALIAS ||
|
|
822
|
+
k.kind == YEP_V_ANCHOR) {
|
|
823
|
+
yep_error_set(yep_error_tls(), YEP_ERR_UNEXPECTED, 0, 0, 0,
|
|
824
|
+
"duplicate key \"%.*s\" in JSON object", (int)k.len,
|
|
825
|
+
k.len ? c->arena + k.off : "");
|
|
826
|
+
} else {
|
|
827
|
+
yep_error_set(yep_error_tls(), YEP_ERR_UNEXPECTED, 0, 0, 0, "duplicate key in object");
|
|
828
|
+
}
|
|
819
829
|
rc = 1;
|
|
820
830
|
}
|
|
821
831
|
for (size_t j = 0; j < depth; j++) {
|
|
@@ -555,9 +555,15 @@ static int e_flush_q_value(yep_engine* e) {
|
|
|
555
555
|
* this pop the stack keeps a stale entry and the outer pair's null
|
|
556
556
|
* flushes inside the wrong map (the nightly's run 38387614146). */
|
|
557
557
|
static int e_pair_value_done(yep_engine* e, yep_ctx ctx, uint16_t key_col) {
|
|
558
|
+
/* the pair's own level, BEFORE its value parse: the value may open
|
|
559
|
+
* deeper frames ("? a:\n ? b<EOF>") and a post-parse depth read
|
|
560
|
+
* then matches the DEEPER pair's pending slot, popping the wrong
|
|
561
|
+
* entry and stranding the outer null (the nightly's round 24,
|
|
562
|
+
* crash-bcc0f52c) */
|
|
563
|
+
int pre_depth = e->depth;
|
|
558
564
|
int rc = e_parse_value(e, YEP_CTX_AFTER_COLON, key_col);
|
|
559
565
|
if (rc >= 0 && ctx == YEP_CTX_AFTER_Q && e->qmd_n > 0 &&
|
|
560
|
-
|
|
566
|
+
pre_depth == e->qmd_stack[e->qmd_n - 1]) {
|
|
561
567
|
e->qmd_n--; /* the inline value resolved the innermost '?' pending */
|
|
562
568
|
}
|
|
563
569
|
return rc;
|
|
@@ -1173,6 +1179,14 @@ static yep_view e_resolve_tag_raw(yep_engine* e, yep_view tag) {
|
|
|
1173
1179
|
yep_view v = {tag.p + 2, tag.len - 3};
|
|
1174
1180
|
return v;
|
|
1175
1181
|
}
|
|
1182
|
+
/* the BARE '!' is the non-specific tag and is exempt from %TAG
|
|
1183
|
+
* directives (spec 7.3.3): it stays '!' here, and the plain-scalar
|
|
1184
|
+
* drop happens at emit_now (the nightly's round 22, crash-d6be3347:
|
|
1185
|
+
* '%TAG ! ...' + '- ! tag:clarkevans.com,2002:' resolved the
|
|
1186
|
+
* non-specific tag through the directive where libyaml drops it) */
|
|
1187
|
+
if (tag.len == 1 && tag.p[0] == '!') {
|
|
1188
|
+
return tag;
|
|
1189
|
+
}
|
|
1176
1190
|
/* longest matching handle wins */
|
|
1177
1191
|
int best = -1;
|
|
1178
1192
|
uint32_t best_len = 0;
|
|
@@ -1261,6 +1275,27 @@ static void e_props(yep_engine* e, yep_view* anchor, yep_view* tag) {
|
|
|
1261
1275
|
e_fail(e, YEP_ERR_UNEXPECTED, e->pos);
|
|
1262
1276
|
return;
|
|
1263
1277
|
}
|
|
1278
|
+
/* The flow-follower colon law (the nightly's round 29,
|
|
1279
|
+
* crash-47eb4054): a name ending at a riding colon whose
|
|
1280
|
+
* follower is a FLOW collection un-consumes the colon.
|
|
1281
|
+
* libyaml ACCEPTS "&k2: [1,\n2]" — the anchor names the
|
|
1282
|
+
* implicit-null KEY and the flow is the value — so the
|
|
1283
|
+
* riding law (2SXE) must yield exactly where its result
|
|
1284
|
+
* is observable in the differential; the plain-led twins
|
|
1285
|
+
* keep it (libyaml rejects those: "&a: key: v", W5VH's
|
|
1286
|
+
* value position — suite-VALID, ledgered). The colon
|
|
1287
|
+
* re-lexes as the key indicator and the existing colon
|
|
1288
|
+
* arm builds the anchored null key. */
|
|
1289
|
+
if (e->p[e->pos - 1] == ':') {
|
|
1290
|
+
size_t t = e->pos;
|
|
1291
|
+
while (t < e->len && (e->p[t] == ' ' || e->p[t] == '\t')) {
|
|
1292
|
+
t++;
|
|
1293
|
+
}
|
|
1294
|
+
if (t < e->len && (e->p[t] == '[' || e->p[t] == '{')) {
|
|
1295
|
+
anchor->len -= 1;
|
|
1296
|
+
e->pos -= 1;
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1264
1299
|
if (e->pos < e->len && e->p[e->pos] == '#') {
|
|
1265
1300
|
/* the name ends at a blank or flow indicator; a glued
|
|
1266
1301
|
* '#' is junk on the name (libyaml: "did not find
|
|
@@ -3628,6 +3663,15 @@ static int e_node(yep_engine* e, yep_ctx ctx, uint16_t floor_col) {
|
|
|
3628
3663
|
while (e->pos < e->len && e->p[e->pos] != ':') {
|
|
3629
3664
|
e->pos++;
|
|
3630
3665
|
}
|
|
3666
|
+
if (e->pos >= e->len) {
|
|
3667
|
+
/* EOF without the ':': the explicit-key pair's value never
|
|
3668
|
+
* came ("? b<EOF>") — the pending stays armed and the
|
|
3669
|
+
* stream-end flush completes it at the deepest open map
|
|
3670
|
+
* (the nightly's round 24, crash-bcc0f52c); popping here
|
|
3671
|
+
* resolved a pair that has no value and stranded the OUTER
|
|
3672
|
+
* pending's null in the wrong map */
|
|
3673
|
+
return 0;
|
|
3674
|
+
}
|
|
3631
3675
|
e->pos++; /* past ':' */
|
|
3632
3676
|
return e_pair_value_done(e, ctx, key_col);
|
|
3633
3677
|
}
|
|
@@ -4106,55 +4150,82 @@ static yep_norm_tok norm_step(yep_norm_ctx* c, const char* p, size_t len, size_t
|
|
|
4106
4150
|
return t;
|
|
4107
4151
|
}
|
|
4108
4152
|
if (c->quote != 0) {
|
|
4109
|
-
/*
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
if (i + 1 >= len) {
|
|
4153
|
+
/* A col-0 --- / ... marker RESCUES the quote: the parser ends
|
|
4154
|
+
* the document at the marker (the post-cut reset says "the
|
|
4155
|
+
* tail began at a --- line in a clean state"), so bytes after
|
|
4156
|
+
* it are NOT quoted content. Whole-buffer runs must classify
|
|
4157
|
+
* them the same way or the routes diverge: round 25 of the
|
|
4158
|
+
* nightly (crash-27a77050) fed ">\n: '\n---\na<U+2029>" and
|
|
4159
|
+
* the whole route kept the PS raw inside the never-closed
|
|
4160
|
+
* quote while the chunked route (fresh probe after the cut)
|
|
4161
|
+
* folded it — a plain scalar "a " vs "a". */
|
|
4162
|
+
int rescue = (c->at_break && i + 2 < len && (ch == '-' || ch == '.') && p[i + 1] == ch &&
|
|
4163
|
+
p[i + 2] == ch &&
|
|
4164
|
+
(i + 3 >= len || p[i + 3] == ' ' || p[i + 3] == '\t' || p[i + 3] == '\n' ||
|
|
4165
|
+
p[i + 3] == '\r'));
|
|
4166
|
+
if (rescue) {
|
|
4167
|
+
c->quote = 0;
|
|
4168
|
+
} else {
|
|
4169
|
+
/* NEL folds inside quotes too; LS/PS stay raw content — but
|
|
4170
|
+
* every break still arms the line-start state, or a col-0
|
|
4171
|
+
* marker after a quoted newline is invisible (at_break was
|
|
4172
|
+
* last armed OUTSIDE the quote) */
|
|
4173
|
+
if (nel) {
|
|
4174
|
+
t.n = 2;
|
|
4175
|
+
t.fold_off = 0;
|
|
4176
|
+
t.fold_len = 2;
|
|
4177
|
+
c->at_break = 1;
|
|
4135
4178
|
return t;
|
|
4136
4179
|
}
|
|
4137
|
-
|
|
4138
|
-
if (nx == 0xC2 && i + 2 < len && (unsigned char)p[i + 2] == 0x85) {
|
|
4180
|
+
if (lps) {
|
|
4139
4181
|
t.n = 3;
|
|
4140
|
-
|
|
4141
|
-
t.fold_len = 2;
|
|
4182
|
+
c->at_break = 1;
|
|
4142
4183
|
return t;
|
|
4143
4184
|
}
|
|
4144
|
-
if (
|
|
4145
|
-
|
|
4146
|
-
t.n = 4;
|
|
4147
|
-
t.fold_off = 1;
|
|
4148
|
-
t.fold_len = 3;
|
|
4185
|
+
if (ch == '\n' || (ch == '\r' && (i + 1 >= len || p[i + 1] != '\n'))) {
|
|
4186
|
+
c->at_break = 1;
|
|
4149
4187
|
return t;
|
|
4150
4188
|
}
|
|
4151
|
-
|
|
4189
|
+
c->at_break = 0;
|
|
4190
|
+
if (c->quote == '\'') {
|
|
4191
|
+
if (ch == '\'') {
|
|
4192
|
+
if (i + 1 < len && p[i + 1] == '\'') {
|
|
4193
|
+
t.n = 2; /* '' escaped quote */
|
|
4194
|
+
return t;
|
|
4195
|
+
}
|
|
4196
|
+
c->quote = 0;
|
|
4197
|
+
}
|
|
4198
|
+
return t;
|
|
4199
|
+
}
|
|
4200
|
+
if (ch == '\\') {
|
|
4201
|
+
/* the escape consumes the next byte — but a multibyte
|
|
4202
|
+
* break under the escape still folds (an escaped break is
|
|
4203
|
+
* a fold continuation, and the blind pass folded it) */
|
|
4204
|
+
if (i + 1 >= len) {
|
|
4205
|
+
return t;
|
|
4206
|
+
}
|
|
4207
|
+
unsigned char nx = (unsigned char)p[i + 1];
|
|
4208
|
+
if (nx == 0xC2 && i + 2 < len && (unsigned char)p[i + 2] == 0x85) {
|
|
4209
|
+
t.n = 3;
|
|
4210
|
+
t.fold_off = 1;
|
|
4211
|
+
t.fold_len = 2;
|
|
4212
|
+
return t;
|
|
4213
|
+
}
|
|
4214
|
+
if (nx == 0xE2 && i + 3 < len && (unsigned char)p[i + 2] == 0x80 &&
|
|
4215
|
+
((unsigned char)p[i + 3] & 0xFE) == 0xA8) {
|
|
4216
|
+
t.n = 4;
|
|
4217
|
+
t.fold_off = 1;
|
|
4218
|
+
t.fold_len = 3;
|
|
4219
|
+
return t;
|
|
4220
|
+
}
|
|
4221
|
+
t.n = 2;
|
|
4222
|
+
return t;
|
|
4223
|
+
}
|
|
4224
|
+
if (ch == '"') {
|
|
4225
|
+
c->quote = 0;
|
|
4226
|
+
}
|
|
4152
4227
|
return t;
|
|
4153
4228
|
}
|
|
4154
|
-
if (ch == '"') {
|
|
4155
|
-
c->quote = 0;
|
|
4156
|
-
}
|
|
4157
|
-
return t;
|
|
4158
4229
|
}
|
|
4159
4230
|
if (c->in_verbatim) {
|
|
4160
4231
|
if (ch == '>') {
|
|
@@ -4892,7 +4963,26 @@ static size_t step_scan(yep_stepstate* st) {
|
|
|
4892
4963
|
st->bs_indent = (uint32_t)-1; /* root rule: markers only */
|
|
4893
4964
|
}
|
|
4894
4965
|
}
|
|
4895
|
-
|
|
4966
|
+
/* the line before a marker must not be a
|
|
4967
|
+
* directive-LOOKING line: the scan's quote
|
|
4968
|
+
* state can close a quote where the parser
|
|
4969
|
+
* reads content (or vice versa), so a %-led
|
|
4970
|
+
* line may ride an open quote the scan
|
|
4971
|
+
* believes in -- cutting then strands the
|
|
4972
|
+
* directive from its --- and the window
|
|
4973
|
+
* rejects it (the nightly's round 27,
|
|
4974
|
+
* crash-95bbd95f: "i\n\"\n...\n%TAG ! \"\n--- ").
|
|
4975
|
+
* The check is byte-level, independent of the
|
|
4976
|
+
* quote tracking's verdict. */
|
|
4977
|
+
int prev_pct = 0;
|
|
4978
|
+
if (i > 0) {
|
|
4979
|
+
size_t ls = i - 1; /* the break before the marker */
|
|
4980
|
+
while (ls > 0 && p[ls - 1] != '\n' && p[ls - 1] != '\r') {
|
|
4981
|
+
ls--;
|
|
4982
|
+
}
|
|
4983
|
+
prev_pct = p[ls] == '%';
|
|
4984
|
+
}
|
|
4985
|
+
if (st->saw_directive == 0 && i > 0 && !st->bs_open && !prev_pct) {
|
|
4896
4986
|
last_cut = i; /* interior document boundary */
|
|
4897
4987
|
}
|
|
4898
4988
|
st->saw_directive = 0; /* this --- owns the directives */
|
|
@@ -5450,10 +5540,14 @@ static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep
|
|
|
5450
5540
|
}
|
|
5451
5541
|
} else {
|
|
5452
5542
|
e->q_key_pending = 0;
|
|
5453
|
-
e->q_value_pending = 0;
|
|
5454
5543
|
if (e->qmd_n > 0) {
|
|
5455
5544
|
e->qmd_n--; /* the ':' line supplied the innermost value */
|
|
5456
5545
|
}
|
|
5546
|
+
/* the flag governs the WHOLE stack: deeper pendings
|
|
5547
|
+
* keep it up so their nulls still flush (the nightly's
|
|
5548
|
+
* round 24, crash-bcc0f52c — the hard clear stranded
|
|
5549
|
+
* the outer pair's null) */
|
|
5550
|
+
e->q_value_pending = e->qmd_n > 0;
|
|
5457
5551
|
}
|
|
5458
5552
|
e->pos++;
|
|
5459
5553
|
e->cv_line = e->line; /* the value parses on THIS line's colon */
|
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.37.0
|
|
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-
|
|
11
|
+
date: 2026-10-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ffi
|