yeptris 0.6.35.1-arm-linux-eabihf → 0.6.36.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/lib/yeptris/cbor.rb +3 -0
- data/lib/yeptris/document.rb +11 -0
- data/lib/yeptris/ffi.rb +8 -0
- data/lib/yeptris/json.rb +14 -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 +96 -42
- 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: f66c1643edcda6eba3086c332c967a59ce9b04175d2fb7f98f468cf4326319f4
|
|
4
|
+
data.tar.gz: 5ecef3fe6e04298e507ffdee8762ab02cc95752f366ca25adea27f3d56246086
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e03bca368d020c5358c7f870b792b584982bfde46f20cf1efa37327c8e8c0f19cbbd2047b6fe0aa9f06aca6bfa5984065ab049c21d38438ef09848a35d16a361
|
|
7
|
+
data.tar.gz: b61301d36a1743bd89c0210468994e4e280b9a1d2b25031f4db96d0c0caa6d10c72694528ef64a596e3b2686538695bf514e5632a778bd2938c51171e671b645
|
data/lib/yeptris/cbor.rb
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "yeptris"
|
|
4
|
+
require "yeptris/psych" # the encode path builds through the psych YAMLTree
|
|
5
|
+
|
|
3
6
|
module Yeptris
|
|
4
7
|
# CBOR (RFC 8949) over the same FFI document the rest of the
|
|
5
8
|
# binding rides (TODO.cbor/04). Decode materializes through the
|
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
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "yeptris"
|
|
4
|
+
|
|
3
5
|
module Yeptris
|
|
4
6
|
# The STRICT JSON surface (TODO.restructure/31).
|
|
5
7
|
#
|
|
@@ -365,7 +367,7 @@ module Yeptris
|
|
|
365
367
|
# and null stay plain), Symbols become their name.
|
|
366
368
|
class DumpError < Error; end
|
|
367
369
|
|
|
368
|
-
def dump(obj)
|
|
370
|
+
def dump(obj, pretty: false, indent: " ")
|
|
369
371
|
parts = String.new(encoding: Encoding::BINARY,
|
|
370
372
|
capacity: 12 * 16) # 12-byte entries, appended in place
|
|
371
373
|
blob = String.new(encoding: Encoding::BINARY)
|
|
@@ -375,7 +377,17 @@ module Yeptris
|
|
|
375
377
|
# FFI passes String args BY REFERENCE — no MemoryPointer copies
|
|
376
378
|
rc = doc.build_entries(parts, parts.bytesize / 12, blob, blob.bytesize)
|
|
377
379
|
raise DumpError, "document_build failed: #{rc}" unless rc == ::Yeptris::FFI::OK
|
|
378
|
-
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
|
|
379
391
|
# JSON.generate emits no trailing newline (the document writer does)
|
|
380
392
|
out.end_with?("\n") ? out[0, out.bytesize - 1] : out
|
|
381
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.36.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;
|
|
@@ -3628,6 +3642,15 @@ static int e_node(yep_engine* e, yep_ctx ctx, uint16_t floor_col) {
|
|
|
3628
3642
|
while (e->pos < e->len && e->p[e->pos] != ':') {
|
|
3629
3643
|
e->pos++;
|
|
3630
3644
|
}
|
|
3645
|
+
if (e->pos >= e->len) {
|
|
3646
|
+
/* EOF without the ':': the explicit-key pair's value never
|
|
3647
|
+
* came ("? b<EOF>") — the pending stays armed and the
|
|
3648
|
+
* stream-end flush completes it at the deepest open map
|
|
3649
|
+
* (the nightly's round 24, crash-bcc0f52c); popping here
|
|
3650
|
+
* resolved a pair that has no value and stranded the OUTER
|
|
3651
|
+
* pending's null in the wrong map */
|
|
3652
|
+
return 0;
|
|
3653
|
+
}
|
|
3631
3654
|
e->pos++; /* past ':' */
|
|
3632
3655
|
return e_pair_value_done(e, ctx, key_col);
|
|
3633
3656
|
}
|
|
@@ -4106,55 +4129,82 @@ static yep_norm_tok norm_step(yep_norm_ctx* c, const char* p, size_t len, size_t
|
|
|
4106
4129
|
return t;
|
|
4107
4130
|
}
|
|
4108
4131
|
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) {
|
|
4132
|
+
/* A col-0 --- / ... marker RESCUES the quote: the parser ends
|
|
4133
|
+
* the document at the marker (the post-cut reset says "the
|
|
4134
|
+
* tail began at a --- line in a clean state"), so bytes after
|
|
4135
|
+
* it are NOT quoted content. Whole-buffer runs must classify
|
|
4136
|
+
* them the same way or the routes diverge: round 25 of the
|
|
4137
|
+
* nightly (crash-27a77050) fed ">\n: '\n---\na<U+2029>" and
|
|
4138
|
+
* the whole route kept the PS raw inside the never-closed
|
|
4139
|
+
* quote while the chunked route (fresh probe after the cut)
|
|
4140
|
+
* folded it — a plain scalar "a " vs "a". */
|
|
4141
|
+
int rescue = (c->at_break && i + 2 < len && (ch == '-' || ch == '.') && p[i + 1] == ch &&
|
|
4142
|
+
p[i + 2] == ch &&
|
|
4143
|
+
(i + 3 >= len || p[i + 3] == ' ' || p[i + 3] == '\t' || p[i + 3] == '\n' ||
|
|
4144
|
+
p[i + 3] == '\r'));
|
|
4145
|
+
if (rescue) {
|
|
4146
|
+
c->quote = 0;
|
|
4147
|
+
} else {
|
|
4148
|
+
/* NEL folds inside quotes too; LS/PS stay raw content — but
|
|
4149
|
+
* every break still arms the line-start state, or a col-0
|
|
4150
|
+
* marker after a quoted newline is invisible (at_break was
|
|
4151
|
+
* last armed OUTSIDE the quote) */
|
|
4152
|
+
if (nel) {
|
|
4153
|
+
t.n = 2;
|
|
4154
|
+
t.fold_off = 0;
|
|
4155
|
+
t.fold_len = 2;
|
|
4156
|
+
c->at_break = 1;
|
|
4135
4157
|
return t;
|
|
4136
4158
|
}
|
|
4137
|
-
|
|
4138
|
-
if (nx == 0xC2 && i + 2 < len && (unsigned char)p[i + 2] == 0x85) {
|
|
4159
|
+
if (lps) {
|
|
4139
4160
|
t.n = 3;
|
|
4140
|
-
|
|
4141
|
-
t.fold_len = 2;
|
|
4161
|
+
c->at_break = 1;
|
|
4142
4162
|
return t;
|
|
4143
4163
|
}
|
|
4144
|
-
if (
|
|
4145
|
-
|
|
4146
|
-
t.n = 4;
|
|
4147
|
-
t.fold_off = 1;
|
|
4148
|
-
t.fold_len = 3;
|
|
4164
|
+
if (ch == '\n' || (ch == '\r' && (i + 1 >= len || p[i + 1] != '\n'))) {
|
|
4165
|
+
c->at_break = 1;
|
|
4149
4166
|
return t;
|
|
4150
4167
|
}
|
|
4151
|
-
|
|
4168
|
+
c->at_break = 0;
|
|
4169
|
+
if (c->quote == '\'') {
|
|
4170
|
+
if (ch == '\'') {
|
|
4171
|
+
if (i + 1 < len && p[i + 1] == '\'') {
|
|
4172
|
+
t.n = 2; /* '' escaped quote */
|
|
4173
|
+
return t;
|
|
4174
|
+
}
|
|
4175
|
+
c->quote = 0;
|
|
4176
|
+
}
|
|
4177
|
+
return t;
|
|
4178
|
+
}
|
|
4179
|
+
if (ch == '\\') {
|
|
4180
|
+
/* the escape consumes the next byte — but a multibyte
|
|
4181
|
+
* break under the escape still folds (an escaped break is
|
|
4182
|
+
* a fold continuation, and the blind pass folded it) */
|
|
4183
|
+
if (i + 1 >= len) {
|
|
4184
|
+
return t;
|
|
4185
|
+
}
|
|
4186
|
+
unsigned char nx = (unsigned char)p[i + 1];
|
|
4187
|
+
if (nx == 0xC2 && i + 2 < len && (unsigned char)p[i + 2] == 0x85) {
|
|
4188
|
+
t.n = 3;
|
|
4189
|
+
t.fold_off = 1;
|
|
4190
|
+
t.fold_len = 2;
|
|
4191
|
+
return t;
|
|
4192
|
+
}
|
|
4193
|
+
if (nx == 0xE2 && i + 3 < len && (unsigned char)p[i + 2] == 0x80 &&
|
|
4194
|
+
((unsigned char)p[i + 3] & 0xFE) == 0xA8) {
|
|
4195
|
+
t.n = 4;
|
|
4196
|
+
t.fold_off = 1;
|
|
4197
|
+
t.fold_len = 3;
|
|
4198
|
+
return t;
|
|
4199
|
+
}
|
|
4200
|
+
t.n = 2;
|
|
4201
|
+
return t;
|
|
4202
|
+
}
|
|
4203
|
+
if (ch == '"') {
|
|
4204
|
+
c->quote = 0;
|
|
4205
|
+
}
|
|
4152
4206
|
return t;
|
|
4153
4207
|
}
|
|
4154
|
-
if (ch == '"') {
|
|
4155
|
-
c->quote = 0;
|
|
4156
|
-
}
|
|
4157
|
-
return t;
|
|
4158
4208
|
}
|
|
4159
4209
|
if (c->in_verbatim) {
|
|
4160
4210
|
if (ch == '>') {
|
|
@@ -5450,10 +5500,14 @@ static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep
|
|
|
5450
5500
|
}
|
|
5451
5501
|
} else {
|
|
5452
5502
|
e->q_key_pending = 0;
|
|
5453
|
-
e->q_value_pending = 0;
|
|
5454
5503
|
if (e->qmd_n > 0) {
|
|
5455
5504
|
e->qmd_n--; /* the ':' line supplied the innermost value */
|
|
5456
5505
|
}
|
|
5506
|
+
/* the flag governs the WHOLE stack: deeper pendings
|
|
5507
|
+
* keep it up so their nulls still flush (the nightly's
|
|
5508
|
+
* round 24, crash-bcc0f52c — the hard clear stranded
|
|
5509
|
+
* the outer pair's null) */
|
|
5510
|
+
e->q_value_pending = e->qmd_n > 0;
|
|
5457
5511
|
}
|
|
5458
5512
|
e->pos++;
|
|
5459
5513
|
e->cv_line = e->line; /* the value parses on THIS line's colon */
|