yeptris 0.6.41.0-aarch64-linux → 0.6.43.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/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/emit/emit.c +26 -2
- data/vendor/libyeptris/src/yeptris/emit/writer.c +75 -23
- data/vendor/libyeptris/src/yeptris/emit/writer.h +7 -3
- data/vendor/libyeptris/src/yeptris/parse/engine.c +9 -1
- 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: eeb2fd78b1b84c1f3928048d05211a602911bfd96cec7075e388e6e83e73d070
|
|
4
|
+
data.tar.gz: e483f4e301279d107a25ceecfdfec2ea7075c7afea85e2c87cafbb232389d253
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1776543ab8be8fb925f079e930a8a3f2b40eac489f2f82c7d511aa633a96811c20664d16a8617473c74d86650c69cf6a56dd54f0c5541d34de8347482fdf3334
|
|
7
|
+
data.tar.gz: 2363b583dc263ddb4796a88532650fe0f06d89fbc50d792627800d8321ddc67610502752726caf88a68ea40b089bf7a94f26c9809be2cf47bc0c92fc1d2cadad
|
|
@@ -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 43
|
|
15
|
+
#define YEPTRIS_VERSION_STRING "0.6.43"
|
|
16
16
|
|
|
17
17
|
#ifdef __cplusplus
|
|
18
18
|
extern "C" {
|
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.43.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
|
|
@@ -293,8 +293,15 @@ YEPTRIS_API char* yeptris_serialize_json(YeptrisDocument handle, size_t* len) {
|
|
|
293
293
|
if (em.w.canonical && !yep_nametab_init(&em.canon_names, yep_system_allocator())) {
|
|
294
294
|
return NULL;
|
|
295
295
|
}
|
|
296
|
-
|
|
297
|
-
|
|
296
|
+
/* #739: ONE wet pass into a growable buffer — the dry exact-sizing
|
|
297
|
+
* pass priced ~2x on the json lane (the #352 slice-2 pattern);
|
|
298
|
+
* the estimate starts at the input size (+64) and doubles on
|
|
299
|
+
* demand, shrink-to-fit at the end. */
|
|
300
|
+
size_t est = em.doc->dom->input_len + 64;
|
|
301
|
+
if (est < 256) {
|
|
302
|
+
est = 256;
|
|
303
|
+
}
|
|
304
|
+
char* out = (char*)malloc(est);
|
|
298
305
|
if (out == NULL) {
|
|
299
306
|
if (em.canon_names.sys != NULL) {
|
|
300
307
|
yep_nametab_free(&em.canon_names);
|
|
@@ -302,7 +309,24 @@ YEPTRIS_API char* yeptris_serialize_json(YeptrisDocument handle, size_t* len) {
|
|
|
302
309
|
return NULL;
|
|
303
310
|
}
|
|
304
311
|
em.w.p = out;
|
|
312
|
+
em.w.cap = est;
|
|
313
|
+
em.w.grow = 1;
|
|
305
314
|
size_t wrote = yep_emit_run(&em, 0);
|
|
315
|
+
em.w.grow = 0;
|
|
316
|
+
out = em.w.p; /* wr_grow reallocs through w->p — the local is stale */
|
|
317
|
+
if (em.w.oom || em.w.unserializable) {
|
|
318
|
+
free(out);
|
|
319
|
+
if (em.canon_names.sys != NULL) {
|
|
320
|
+
yep_nametab_free(&em.canon_names);
|
|
321
|
+
}
|
|
322
|
+
return NULL;
|
|
323
|
+
}
|
|
324
|
+
if (em.w.cap - (wrote + 1) > em.w.cap / 8) {
|
|
325
|
+
char* tight = (char*)realloc(out, wrote + 1);
|
|
326
|
+
if (tight != NULL) {
|
|
327
|
+
out = tight;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
306
330
|
if (em.canon_names.sys != NULL) {
|
|
307
331
|
yep_nametab_free(&em.canon_names);
|
|
308
332
|
}
|
|
@@ -66,6 +66,8 @@ static void wr_col_update(yep_writer* w, const char* p, uint32_t n) {
|
|
|
66
66
|
w->col += (int)n;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
static void wr_reserve(yep_writer* w, size_t need);
|
|
70
|
+
|
|
69
71
|
static void wr_grow(yep_writer* w, size_t need) {
|
|
70
72
|
if (w->oom || w->p == NULL) {
|
|
71
73
|
w->oom = w->p == NULL;
|
|
@@ -98,20 +100,53 @@ static void wr_put(yep_writer* w, const char* p, uint32_t n) {
|
|
|
98
100
|
* (len + n == cap) put that NUL one byte past the buffer — the
|
|
99
101
|
* first byte of the next heap block's header (the #182 flake:
|
|
100
102
|
* corrupt deterministic, detected later, timing-varying) */
|
|
101
|
-
if (w->
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
if (w->reserve < (size_t)n) {
|
|
104
|
+
wr_reserve(w, n);
|
|
105
|
+
if (w->oom) {
|
|
106
|
+
w->len += n; /* keep counting: the caller fails on oom */
|
|
107
|
+
return;
|
|
106
108
|
}
|
|
107
109
|
}
|
|
108
|
-
if (w->
|
|
109
|
-
w->
|
|
110
|
-
|
|
110
|
+
if ((size_t)n <= w->reserve) {
|
|
111
|
+
w->reserve -= n;
|
|
112
|
+
} else {
|
|
113
|
+
w->reserve = 0; /* grow=0 trusts the count: the write rides past
|
|
114
|
+
* the bookkeeping exactly as before */
|
|
111
115
|
}
|
|
112
116
|
memcpy(w->p + w->len, p, n);
|
|
113
117
|
w->len += n;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/* #739 lane 1: refill the writable reservation. The grow and flush
|
|
121
|
+
* checks move from every byte to every refill; the watermark law is
|
|
122
|
+
* unchanged in spirit (append-only output — any crossing is a safe
|
|
123
|
+
* cut, a sink just sees chunks up to one reserve past the mark).
|
|
124
|
+
* ONLY the growing routes hold a reservation: the caller-buffer and
|
|
125
|
+
* trusted-count routes keep cap bookkeeping that is not the writer's
|
|
126
|
+
* to reason about (several set cap=0), so their writes stay exactly
|
|
127
|
+
* the old per-call trust. */
|
|
128
|
+
static void wr_reserve(yep_writer* w, size_t need) {
|
|
129
|
+
/* the FLUSH runs for every route: the fixed-window streaming route
|
|
130
|
+
* (grow=0) has no reservation, so this refill path is its ONLY
|
|
131
|
+
* flush point -- skipping it let len ride to cap and the next
|
|
132
|
+
* write landed past the window (ASan: heap-buffer-overflow WRITE
|
|
133
|
+
* of size 2 exactly 0 bytes after the 128K region; ubuntu's
|
|
134
|
+
* allocator freed-corrupted, macOS's slack absorbed it). */
|
|
114
135
|
wr_maybe_flush(w);
|
|
136
|
+
if (!w->grow || w->bounded) {
|
|
137
|
+
w->reserve = 0;
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (w->oom) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
if (w->len + need + 1 > w->cap) { /* +1: the terminator */
|
|
144
|
+
wr_grow(w, need);
|
|
145
|
+
if (w->oom) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
w->reserve = w->cap - w->len - 1;
|
|
115
150
|
}
|
|
116
151
|
|
|
117
152
|
static void wr_byte(yep_writer* w, char c) {
|
|
@@ -125,20 +160,17 @@ static void wr_byte(yep_writer* w, char c) {
|
|
|
125
160
|
w->len++;
|
|
126
161
|
return;
|
|
127
162
|
}
|
|
128
|
-
if (w->
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
163
|
+
if (w->reserve == 0) {
|
|
164
|
+
wr_reserve(w, 1);
|
|
165
|
+
if (w->oom) {
|
|
166
|
+
w->len++;
|
|
167
|
+
return;
|
|
133
168
|
}
|
|
134
169
|
}
|
|
135
|
-
if (w->
|
|
136
|
-
w->
|
|
137
|
-
return;
|
|
170
|
+
if (w->reserve > 0) {
|
|
171
|
+
w->reserve--; /* grow=0 routes keep it at 0: per-call trust */
|
|
138
172
|
}
|
|
139
|
-
w->p[w->len] = c;
|
|
140
|
-
w->len++;
|
|
141
|
-
wr_maybe_flush(w);
|
|
173
|
+
w->p[w->len++] = c;
|
|
142
174
|
}
|
|
143
175
|
|
|
144
176
|
static void wr_indent(yep_writer* w, int depth) {
|
|
@@ -299,21 +331,34 @@ static void emit_dq_json(yep_writer* w, const char* p, uint32_t n) {
|
|
|
299
331
|
NULL, "\\f", "\\r", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
300
332
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
301
333
|
};
|
|
334
|
+
static const char hd[] = "0123456789abcdef";
|
|
335
|
+
/* run-batched (the #352 emit_dq shape): clean spans ride one
|
|
336
|
+
* wr_put each — per-byte wr_byte calls were 14% of the json
|
|
337
|
+
* write lane's leaf samples (yeptris#739) */
|
|
338
|
+
uint32_t run = 0;
|
|
302
339
|
for (uint32_t i = 0; i < n; i++) {
|
|
303
340
|
unsigned char c = (unsigned char)p[i];
|
|
341
|
+
if (c >= 0x20 && c != '"' && c != '\\') {
|
|
342
|
+
run++;
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
345
|
+
if (run) {
|
|
346
|
+
wr_put(w, p + i - run, run);
|
|
347
|
+
run = 0;
|
|
348
|
+
}
|
|
304
349
|
if (c < 32 && named[c] != NULL) {
|
|
305
350
|
wr_put(w, named[c], 2);
|
|
306
351
|
} else if (c == '"' || c == '\\') {
|
|
307
352
|
wr_byte(w, '\\');
|
|
308
353
|
wr_byte(w, (char)c);
|
|
309
|
-
} else
|
|
310
|
-
static const char hd[] = "0123456789abcdef";
|
|
354
|
+
} else {
|
|
311
355
|
char hex[6] = {'\\', 'u', '0', '0', hd[(c >> 4) & 0xf], hd[c & 0xf]};
|
|
312
356
|
wr_put(w, hex, 6);
|
|
313
|
-
} else {
|
|
314
|
-
wr_byte(w, (char)c);
|
|
315
357
|
}
|
|
316
358
|
}
|
|
359
|
+
if (run) {
|
|
360
|
+
wr_put(w, p + n - run, run);
|
|
361
|
+
}
|
|
317
362
|
wr_byte(w, '"');
|
|
318
363
|
}
|
|
319
364
|
|
|
@@ -912,6 +957,9 @@ static void emit_node(yep_emitter* em, uint32_t id, int parent_col, int as_key);
|
|
|
912
957
|
* written). Conservative factor-4 estimate for every expandable
|
|
913
958
|
* byte — overestimating only takes the (always-legal) explicit form. */
|
|
914
959
|
static int key_written_over_limit(yep_writer* w, const yep_dnode* kn) {
|
|
960
|
+
if (w->json) {
|
|
961
|
+
return 0; /* JSON has no simple-key law: every key writes (#739) */
|
|
962
|
+
}
|
|
915
963
|
uint64_t est = 2; /* the quotes */
|
|
916
964
|
yep_view kv_ = wv(w, kn->value);
|
|
917
965
|
const unsigned char* q = (const unsigned char*)kv_.p;
|
|
@@ -1098,6 +1146,9 @@ static void emit_block_map(yep_emitter* em, uint32_t id, int content_col) {
|
|
|
1098
1146
|
if (w->oom) {
|
|
1099
1147
|
w->len += total; /* keep counting: the caller fails on oom */
|
|
1100
1148
|
} else {
|
|
1149
|
+
/* the fused write bypasses wr_put/wr_byte: keep
|
|
1150
|
+
* the reservation honest (the #739 lane-1 law) */
|
|
1151
|
+
w->reserve = (size_t)total <= w->reserve ? w->reserve - (size_t)total : 0;
|
|
1101
1152
|
char* q = w->p + w->len;
|
|
1102
1153
|
if (nl) {
|
|
1103
1154
|
*q++ = '\n';
|
|
@@ -1357,6 +1408,7 @@ size_t yep_emit_run(yep_emitter* em, int dry) {
|
|
|
1357
1408
|
const yep_dom* d = em->doc->dom;
|
|
1358
1409
|
w->dry = dry;
|
|
1359
1410
|
w->len = 0;
|
|
1411
|
+
w->reserve = 0;
|
|
1360
1412
|
w->last = 0;
|
|
1361
1413
|
w->force_flow = 0;
|
|
1362
1414
|
w->flushed = 0;
|
|
@@ -57,9 +57,13 @@ typedef struct yep_writer {
|
|
|
57
57
|
size_t cap;
|
|
58
58
|
int grow;
|
|
59
59
|
int oom;
|
|
60
|
-
int bounded;
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
int bounded; /* #352: caller-owned fixed buffer — an oversized write
|
|
61
|
+
sets oom and keeps counting (the needed size falls
|
|
62
|
+
out of the same pass); wr_grow is never called */
|
|
63
|
+
/* #739 lane 1: writable bytes guaranteed at w->p + w->len. The
|
|
64
|
+
* grow/flush checks run once per refill instead of once per byte;
|
|
65
|
+
* 0 at run entry and whenever the guarantee lapses. */
|
|
66
|
+
size_t reserve;
|
|
63
67
|
int in_flow; /* scalars inside flow collections: plain must drop
|
|
64
68
|
',', '[', ']', '{', '}' — flow terminators */
|
|
65
69
|
int flow_item; /* the NEXT scalar is a flow-SEQ item: a null must
|
|
@@ -1207,10 +1207,18 @@ static yep_view e_resolve_tag_raw(yep_engine* e, yep_view tag) {
|
|
|
1207
1207
|
if (tag.len == 1 && tag.p[0] == '!') {
|
|
1208
1208
|
return tag;
|
|
1209
1209
|
}
|
|
1210
|
-
/* longest matching handle wins
|
|
1210
|
+
/* longest matching handle wins; a redefined PRIMARY ('%TAG ! ...')
|
|
1211
|
+
* cannot capture a '!!'-led tag — the secondary handle resolves
|
|
1212
|
+
* through its own entry or the fixed tag:yaml.org,2002: default
|
|
1213
|
+
* (spec 6.8.2.2; libyaml: "%TAG ! !p/" + "!!i" is
|
|
1214
|
+
* tag:yaml.org,2002:i, the nightly's round 52, crash-763bb852) */
|
|
1215
|
+
int secondary = tag.len >= 2 && tag.p[0] == '!' && tag.p[1] == '!';
|
|
1211
1216
|
int best = -1;
|
|
1212
1217
|
uint32_t best_len = 0;
|
|
1213
1218
|
for (int i = 0; i < e->tagmap_n; i++) {
|
|
1219
|
+
if (secondary && e->tagmap[i].handle.len == 1) {
|
|
1220
|
+
continue;
|
|
1221
|
+
}
|
|
1214
1222
|
if (tag.len >= e->tagmap[i].handle.len && e->tagmap[i].handle.len > best_len &&
|
|
1215
1223
|
memcmp(tag.p, e->tagmap[i].handle.p, e->tagmap[i].handle.len) == 0) {
|
|
1216
1224
|
best = i;
|
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.43.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-25 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ffi
|