yeptris 0.6.42.0 → 0.6.43.0
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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5fe6c4145817f5a8c4dd753ea92f523a41ebcef08ae6fc17cf12a4be8d5fcc7e
|
|
4
|
+
data.tar.gz: 46989aada81d5d8cb75ea73d51af0be671326041fec93ca03ba2184fb98fc0f0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a896a1a0a23c9ab475f1dd642e44cc0dd30288416da97f67b2b6d037957c70cee08e3c37b6e76d09b21ba71884f87759cf460536d5033e988ea1b4cdd299b7d4
|
|
7
|
+
data.tar.gz: 8838bb5ee6f826da3ecb17316c328cf53ecd690e89f927a7c579b04ac62d17e31ca23e7bf0fcfe7d3ecd17e020223021d9638fa095c1aff4967db128ec552746
|
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
|
|
@@ -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
|
|
|
@@ -1101,6 +1146,9 @@ static void emit_block_map(yep_emitter* em, uint32_t id, int content_col) {
|
|
|
1101
1146
|
if (w->oom) {
|
|
1102
1147
|
w->len += total; /* keep counting: the caller fails on oom */
|
|
1103
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;
|
|
1104
1152
|
char* q = w->p + w->len;
|
|
1105
1153
|
if (nl) {
|
|
1106
1154
|
*q++ = '\n';
|
|
@@ -1360,6 +1408,7 @@ size_t yep_emit_run(yep_emitter* em, int dry) {
|
|
|
1360
1408
|
const yep_dom* d = em->doc->dom;
|
|
1361
1409
|
w->dry = dry;
|
|
1362
1410
|
w->len = 0;
|
|
1411
|
+
w->reserve = 0;
|
|
1363
1412
|
w->last = 0;
|
|
1364
1413
|
w->force_flow = 0;
|
|
1365
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
|
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: ruby
|
|
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
|