yeptris 0.6.41.0-powerpc64le-linux → 0.6.43.0-powerpc64le-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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3aed54da7f15bc22c5f779f2529df1723c7c2b36e75cf167ce64d91509fd5bcb
4
- data.tar.gz: 30558d753e8daa9bc6abb53301d77c2d08a22f289d208dbe7ec51ecbdf3e0f2b
3
+ metadata.gz: f91368a63c01ce77d1dec0fabb6ea9dc175cae7c68bb21e34635aca468319724
4
+ data.tar.gz: 20fe41b400a6261b2f5d18d302994f0b1fb3450b00d06f6a6be40270504aecaf
5
5
  SHA512:
6
- metadata.gz: 5c533248db34c2f814cb1811725ff2d68664e8b9e2a7742f0653d840f16df4bcceb4adf6fa8b657bfce646092f0ca960ab056e096b78ee9e2c48ff931fc17251
7
- data.tar.gz: 447c30099bf87a3203f95c7c0258adb13a9fd37367a422703d8817faae440fdcd9bd5e50fdaddcfdf10f91dbee6102996a845ee8889aa5effa112ef5418c90a8
6
+ metadata.gz: 450f4911af194dadebc41a221ce52e65c4d0b1affce6fda8f7c03ecb90aed5b61408e8e9b7febf5965da873b07b99592fe9b9d8da90e252cffff2173a153e530
7
+ data.tar.gz: 55eb5c0515983584e4f22ed405afe0515251f3856a9b62ea17288a9ea260b906d062b23d76590be2b6e889a8c8d0c842e506c58b9e37132bc1bd298f476b38a9
@@ -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 41
15
- #define YEPTRIS_VERSION_STRING "0.6.41"
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.41.0".freeze
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
@@ -3,7 +3,7 @@
3
3
  cmake_minimum_required(VERSION 3.20)
4
4
 
5
5
  project(yeptris
6
- VERSION 0.6.41
6
+ VERSION 0.6.43
7
7
  DESCRIPTION "Ultra-fast YAML 1.2 parser, emitter and streamer in C"
8
8
  LANGUAGES C CXX
9
9
  )
@@ -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
- size_t need = yep_emit_run(&em, 1);
297
- char* out = malloc(need + 1);
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->grow && w->len + n + 1 > w->cap) {
102
- if (w->bounded) {
103
- w->oom = 1; /* keep counting: the trusted caller reads the size */
104
- } else {
105
- wr_grow(w, n);
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->oom) {
109
- w->len += n; /* keep counting: the caller fails on oom */
110
- return;
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->grow && w->len + 2 > w->cap) { /* +1 write, +1 terminator */
129
- if (w->bounded) {
130
- w->oom = 1; /* keep counting: the trusted caller reads the size */
131
- } else {
132
- wr_grow(w, 1);
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->oom) {
136
- w->len++;
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 if (c < 0x20) {
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; /* #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 */
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,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yeptris
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.41.0
4
+ version: 0.6.43.0
5
5
  platform: powerpc64le-linux
6
6
  authors:
7
7
  - Ribose Inc.