yeptris 0.6.59.1-arm-linux-eabihf → 0.6.61.1-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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/ext/yeptris_native/version.h +2 -2
  3. data/lib/yeptris/3.4/native.so +0 -0
  4. data/lib/yeptris/ffi.rb +19 -0
  5. data/lib/yeptris/yaml.rb +71 -0
  6. data/lib/yeptris.rb +1 -1
  7. data/libyeptris.so +0 -0
  8. data/vendor/libyeptris/CMakeLists.txt +1 -1
  9. data/vendor/libyeptris/src/CMakeLists.txt +7 -0
  10. data/vendor/libyeptris/src/include/yeptris/emit.h +30 -2
  11. data/vendor/libyeptris/src/include/yeptris/parse.h +73 -0
  12. data/vendor/libyeptris/src/include/yeptris/resolve.h +8 -0
  13. data/vendor/libyeptris/src/include/yeptris/validate.h +222 -21
  14. data/vendor/libyeptris/src/include/yeptris/values.h +8 -2
  15. data/vendor/libyeptris/src/yeptris/cbor/cbor.h +10 -0
  16. data/vendor/libyeptris/src/yeptris/cbor/decode.c +5 -7
  17. data/vendor/libyeptris/src/yeptris/cbor/encode.c +9 -9
  18. data/vendor/libyeptris/src/yeptris/cbor/from_marshal.c +1 -1
  19. data/vendor/libyeptris/src/yeptris/common/error.h +2 -0
  20. data/vendor/libyeptris/src/yeptris/doc.h +20 -0
  21. data/vendor/libyeptris/src/yeptris/dom/dom.c +12 -1
  22. data/vendor/libyeptris/src/yeptris/dom/ytape.c +56 -7
  23. data/vendor/libyeptris/src/yeptris/emit/emit.c +93 -13
  24. data/vendor/libyeptris/src/yeptris/emit/writer.c +243 -652
  25. data/vendor/libyeptris/src/yeptris/emit/writer.h +25 -8
  26. data/vendor/libyeptris/src/yeptris/events/push.c +28 -3
  27. data/vendor/libyeptris/src/yeptris/events/values.c +46 -0
  28. data/vendor/libyeptris/src/yeptris/marshal/to_json.c +650 -0
  29. data/vendor/libyeptris/src/yeptris/parse/engine.c +611 -130
  30. data/vendor/libyeptris/src/yeptris/parse/engine.h +5 -0
  31. data/vendor/libyeptris/src/yeptris/parse/stream_iter.c +358 -0
  32. data/vendor/libyeptris/src/yeptris/parse.c +216 -44
  33. data/vendor/libyeptris/src/yeptris/resolve/compat11.c +3 -6
  34. data/vendor/libyeptris/src/yeptris/resolve/core12.c +11 -3
  35. data/vendor/libyeptris/src/yeptris/resolve/full12.c +201 -0
  36. data/vendor/libyeptris/src/yeptris/resolve/json12.c +12 -6
  37. data/vendor/libyeptris/src/yeptris/resolve/resolver.h +38 -0
  38. data/vendor/libyeptris/src/yeptris/resolve/tags.c +192 -0
  39. data/vendor/libyeptris/src/yeptris/scan/scan.c +22 -7
  40. data/vendor/libyeptris/src/yeptris/tape.c +24 -5
  41. data/vendor/libyeptris/src/yeptris/validate/compile.c +39 -3
  42. data/vendor/libyeptris/src/yeptris/validate/internal.h +223 -7
  43. data/vendor/libyeptris/src/yeptris/validate/jsonschema.c +645 -115
  44. data/vendor/libyeptris/src/yeptris/validate/output.c +246 -0
  45. data/vendor/libyeptris/src/yeptris/validate/regexp.c +623 -157
  46. data/vendor/libyeptris/src/yeptris/validate/registry.c +118 -0
  47. data/vendor/libyeptris/src/yeptris/validate/resources.c +601 -0
  48. data/vendor/libyeptris/src/yeptris/validate/stream.c +1155 -0
  49. data/vendor/libyeptris/src/yeptris/validate/validate.c +288 -145
  50. metadata +8 -1
@@ -53,6 +53,11 @@ int yep_engine_step(yep_engine* e, const char* chunk, size_t len, int final, con
53
53
  * allocates a fresh one if reused). Returns NULL when absent. */
54
54
  yep_pool* yep_engine_detach_pool(yep_engine* e);
55
55
 
56
+ /* Detaches the run's break-normalizer copy (ownership moves to the
57
+ * caller; the caller owns the returned buffer once detached). Returns
58
+ * NULL when the run kept the input zero-copy. */
59
+ char* yep_engine_detach_norm_buf(yep_engine* e, size_t* len_out);
60
+
56
61
  /* Implicit-typing schema for the next run (NULL: 1.2 core), and the
57
62
  * runtime nesting limit. */
58
63
  struct yep_resolver;
@@ -0,0 +1,358 @@
1
+ /* stream_iter.c — tolerant per-document stream iteration (#921).
2
+ *
3
+ * The load_stream contract parses the whole stream and returns nothing
4
+ * when any document fails; consumers that must keep the valid
5
+ * documents of a stream cannot use the engine for recovery. This
6
+ * iterator frames documents ENGINE-SIDE (the abort-at-DOCUMENT_END
7
+ * run iterparse uses — scanner-accurate: a quoted scalar spanning a
8
+ * line that looks like a marker never splits) and reports failures
9
+ * per document: on a parse-class error the iterator records that
10
+ * document's verdict (the engine's line/col, which ARE the failed
11
+ * document's own — each run starts at the frame) and resyncs to the
12
+ * next line-start marker, so the host keeps the valid documents.
13
+ *
14
+ * The resync after a FAILURE is a raw marker scan: the failed
15
+ * document's tail is ill-formed by definition, so the scanner-grade
16
+ * framing above no longer has a well-defined subject; the raw scan is
17
+ * the libyaml-familiar best effort and only ever runs on the recovery
18
+ * path (valid documents never hit it).
19
+ *
20
+ * Cost note: each document parses twice (the boundary run + the slice
21
+ * parse). The tolerance contract is the point; a single-pass upgrade
22
+ * rides on the same sink seam when a workload demands it. */
23
+
24
+ #include <stdlib.h>
25
+ #include <string.h>
26
+
27
+ #include "../../include/yeptris/dom.h"
28
+ #include "../../include/yeptris/parse.h"
29
+ #include "../common/error.h"
30
+ #include "../common/simd_text.h"
31
+ #include "../encoding/encoding.h"
32
+ #include "../memory/allocator.h"
33
+ #include "../resolve/resolver.h"
34
+ #include "doc.h"
35
+ #include "engine.h"
36
+
37
+ /* The boundary finder: a sink that aborts the run at the first
38
+ * DOCUMENT_END (iterparse's law — the marker line stays unconsumed
39
+ * and doubles as the next document's start). Events are discarded;
40
+ * the run's pos IS the document's end offset. */
41
+ typedef struct {
42
+ int doc_ends;
43
+ } frame_sink;
44
+
45
+ static int frame_on_event(void* ctx, const yep_event* ev) {
46
+ frame_sink* s = (frame_sink*)ctx;
47
+ if (ev->type == YEP_EV_DOCUMENT_END) {
48
+ s->doc_ends++;
49
+ return 1; /* abort: the document is complete */
50
+ }
51
+ return 0;
52
+ }
53
+
54
+ struct yeptris_stream_iter {
55
+ const char* buf;
56
+ size_t len;
57
+ size_t cursor;
58
+ int done;
59
+ int gated; /* the encoding front-end ran once (iterparse's
60
+ * law: after it, cursor and engine pos live in
61
+ * the same buffer space) */
62
+ unsigned char* owned; /* UTF-16/32 transcode output */
63
+ char* norm; /* NEL/LS/PS-normalized copy */
64
+ const YeptrisParseOptions* opts; /* borrowed */
65
+ size_t index; /* 0-based stream document index (errors consume
66
+ * one too — the host's yield order is the stream's) */
67
+ YeptrisStatus last_status; /* the LAST next()'s per-document verdict */
68
+ uint32_t last_line;
69
+ uint32_t last_col;
70
+ size_t last_off; /* the last SUCCESSFUL document's slice
71
+ * in the (post-gate) buffer space */
72
+ size_t last_len;
73
+ };
74
+
75
+ yeptris_stream_iter* yeptris_stream_iter_new(const char* buf, size_t len,
76
+ const YeptrisParseOptions* opts) {
77
+ if (buf == NULL && len != 0) {
78
+ return NULL;
79
+ }
80
+ struct yeptris_stream_iter* it = calloc(1, sizeof(*it));
81
+ if (it == NULL) {
82
+ return NULL;
83
+ }
84
+ it->buf = buf;
85
+ it->len = len;
86
+ it->opts = opts;
87
+ return it;
88
+ }
89
+
90
+ /* The resync: the next line-start marker (--- / ...) followed by
91
+ * space, break, or EOF — the c-forbidden lookahead. Raw bytes: the
92
+ * recovery path's best effort (see the file comment). The scan starts
93
+ * AFTER the failed frame's first line: the frame opened at `from`'s
94
+ * line, and the engine's failure pos can sit at EOF (the run scans to
95
+ * the end before reporting), so anchoring on `from` itself is the only
96
+ * stable reference. */
97
+ static size_t next_marker(const char* p, size_t len, size_t from) {
98
+ size_t i = from;
99
+ while (i < len && p[i] != '\n' && p[i] != '\r') {
100
+ i++;
101
+ }
102
+ if (i < len) {
103
+ i++;
104
+ }
105
+ int line_start = 1;
106
+ while (i < len) {
107
+ char ch = p[i];
108
+ if (ch == '\n' || ch == '\r') {
109
+ line_start = 1;
110
+ i++;
111
+ continue;
112
+ }
113
+ if (line_start && ch == '-' && i + 2 < len && p[i + 1] == '-' && p[i + 2] == '-' &&
114
+ (i + 3 == len || p[i + 3] == ' ' || p[i + 3] == '\n' || p[i + 3] == '\r' ||
115
+ p[i + 3] == '\t')) {
116
+ return i;
117
+ }
118
+ if (line_start && ch == '.' && i + 2 < len && p[i + 1] == '.' && p[i + 2] == '.' &&
119
+ (i + 3 == len || p[i + 3] == ' ' || p[i + 3] == '\n' || p[i + 3] == '\r' ||
120
+ p[i + 3] == '\t')) {
121
+ return i;
122
+ }
123
+ line_start = 0;
124
+ i++;
125
+ }
126
+ return len; /* no marker: the tail is unrecoverable */
127
+ }
128
+
129
+ static void it_fail(struct yeptris_stream_iter* it, YeptrisStatus st, uint32_t line, uint32_t col) {
130
+ it->last_status = st;
131
+ it->last_line = line;
132
+ it->last_col = col;
133
+ it->last_len = 0; /* the slice accessor must not serve a stale frame
134
+ * (the success path sets off/len right after) */
135
+ }
136
+
137
+ static int engine_opts(yep_engine* eng, const YeptrisParseOptions* opts) {
138
+ /* the typing SSOT: one switch (parse.c owns it) */
139
+ YeptrisSchema schema = opts != NULL ? opts->schema : YEPTRIS_SCHEMA_12_CORE;
140
+ yep_engine_set_resolver(eng, resolver_for_schema(schema));
141
+ if (opts != NULL && opts->schema == YEPTRIS_SCHEMA_11_COMPAT) {
142
+ /* the compat grammar is the psych/libyaml surface (parse_impl's
143
+ * law) */
144
+ yep_engine_set_compat_grammar(eng, 1);
145
+ }
146
+ if (opts != NULL && opts->max_depth > 0) {
147
+ yep_engine_set_max_depth(eng, opts->max_depth);
148
+ }
149
+ return 0;
150
+ }
151
+
152
+ YeptrisStatus yeptris_stream_iter_next(struct yeptris_stream_iter* it, YeptrisDocument* out,
153
+ size_t* index) {
154
+ if (it == NULL || out == NULL) {
155
+ return YEPTRIS_ERROR_ARG;
156
+ }
157
+ *out = NULL;
158
+ if (index != NULL) {
159
+ *index = it->index;
160
+ }
161
+ for (;;) {
162
+ /* the encoding front-end, ONCE (iterparse's gate law: BOM
163
+ * strip, UTF-16/32 transcode, NEL/LS/PS normalization — cursor
164
+ * and engine pos must live in one buffer space or the resume
165
+ * arithmetic corrupts slices) */
166
+ if (!it->gated) {
167
+ it->gated = 1;
168
+ const yep_allocator* sys = yep_system_allocator();
169
+ yep_encoding enc = YEP_ENC_UNKNOWN;
170
+ size_t bom = yep_bom_sniff((const unsigned char*)it->buf, it->len, &enc);
171
+ if (enc == YEP_ENC_UTF16LE || enc == YEP_ENC_UTF16BE || enc == YEP_ENC_UTF32LE ||
172
+ enc == YEP_ENC_UTF32BE) {
173
+ size_t tlen = 0;
174
+ size_t terr = 0;
175
+ unsigned char* owned = NULL;
176
+ int rc = yep_transcode_to_utf8(sys, enc, (const unsigned char*)it->buf + bom,
177
+ it->len - bom, &owned, &tlen, &terr);
178
+ if (rc != 0) {
179
+ it->done = 1;
180
+ it_fail(it, YEPTRIS_ERROR_ENCODING, 1, 1);
181
+ return YEPTRIS_ERROR_ENCODING;
182
+ }
183
+ it->owned = owned;
184
+ it->buf = (const char*)owned;
185
+ it->len = tlen;
186
+ it->cursor = 0;
187
+ } else {
188
+ it->cursor = bom;
189
+ }
190
+ size_t nlen = 0;
191
+ int kept_raw = 0;
192
+ char* norm = yep_engine_normalize_breaks(sys, it->buf + it->cursor,
193
+ it->len - it->cursor, &nlen, &kept_raw);
194
+ if (norm != NULL) {
195
+ it->norm = norm;
196
+ it->buf = norm;
197
+ it->len = nlen;
198
+ it->cursor = 0;
199
+ }
200
+ }
201
+ if (it->done) {
202
+ it_fail(it, YEPTRIS_OK, 0, 0);
203
+ return YEPTRIS_OK; /* *out stays NULL: the stream is over */
204
+ }
205
+
206
+ /* one boundary run: abort at DOCUMENT_END, learn the extent */
207
+ frame_sink fs = {0};
208
+ yep_engine* eng = yep_engine_create(yep_system_allocator());
209
+ if (eng == NULL) {
210
+ it->done = 1;
211
+ it_fail(it, YEPTRIS_ERROR_MEMORY, 0, 0);
212
+ return YEPTRIS_ERROR_MEMORY;
213
+ }
214
+ engine_opts(eng, it->opts);
215
+ yep_sink sink = {.on_event = frame_on_event,
216
+ .ctx = &fs,
217
+ .on_flow_build = NULL,
218
+ .on_flow_commit = NULL,
219
+ .on_flow_rollback = NULL,
220
+ .on_block_pair = NULL,
221
+ .on_block_open = NULL,
222
+ .on_block_item = NULL};
223
+ yep_text_stats pst;
224
+ yep_text_active()->scan_stats(it->buf + it->cursor, it->len - it->cursor, &pst);
225
+ yep_engine_prepare(eng, &pst);
226
+ int rc = yep_engine_run(eng, it->buf + it->cursor, it->len - it->cursor, &sink);
227
+ size_t pos = yep_engine_pos(eng);
228
+ yep_err_code err_code = YEP_ERR_NONE;
229
+ uint32_t err_line = 0, err_col = 0;
230
+ {
231
+ const yep_error* err = yep_engine_error(eng);
232
+ if (err != NULL) {
233
+ err_code = err->code;
234
+ err_line = err->line;
235
+ err_col = err->col;
236
+ }
237
+ }
238
+ yep_engine_destroy(eng);
239
+
240
+ if (rc == -1 && (err_code == YEP_ERR_MEMORY || err_code == YEP_ERR_ENCODING)) {
241
+ /* the stream-fatal classes: the arena state is unknown
242
+ * (memory) or the front-end's space is broken (encoding —
243
+ * it gated once, so this cannot be a per-document miss) */
244
+ it->done = 1;
245
+ it_fail(it, err_code == YEP_ERR_MEMORY ? YEPTRIS_ERROR_MEMORY : YEPTRIS_ERROR_ENCODING,
246
+ err_line, err_col);
247
+ return it->last_status;
248
+ }
249
+ if (rc == -1 || (rc != 0 && fs.doc_ends == 0)) {
250
+ /* THIS document failed (parse-class or the run died before
251
+ * any document completed): report the per-document verdict
252
+ * — the run started at the frame, so the engine's line/col
253
+ * ARE the failed document's own — then resync to the next
254
+ * marker and keep going */
255
+ it_fail(it, err_code == YEP_ERR_DEPTH ? YEPTRIS_ERROR_DEPTH : YEPTRIS_ERROR_PARSE,
256
+ err_line, err_col);
257
+ size_t at = next_marker(it->buf, it->len, it->cursor);
258
+ if (at >= it->len) {
259
+ it->done = 1; /* the tail is unrecoverable */
260
+ } else {
261
+ it->cursor = at;
262
+ }
263
+ it->index++;
264
+ if (index != NULL) {
265
+ *index = it->index - 1;
266
+ }
267
+ return it->last_status; /* *out stays NULL: the failed slot */
268
+ }
269
+ if (fs.doc_ends == 0) {
270
+ /* natural end or a blank tail: the stream is over */
271
+ it->done = 1;
272
+ it_fail(it, YEPTRIS_OK, 0, 0);
273
+ return YEPTRIS_OK;
274
+ }
275
+
276
+ /* the frame is [cursor, cursor+pos): parse it as ONE document
277
+ * (the slice's own marker or bare content rides parse_ex's
278
+ * contract; the default tape route is what load uses) */
279
+ YeptrisStatus st = YEPTRIS_OK;
280
+ YeptrisDocument doc = yeptris_parse_ex(it->buf + it->cursor, pos, it->opts, &st);
281
+ if (doc == NULL || st != YEPTRIS_OK) {
282
+ /* the boundary run accepted what the slice parse refused:
283
+ * report as a failed document and resync the same way */
284
+ it_fail(it, st == YEPTRIS_OK ? YEPTRIS_ERROR_PARSE : st, 0, 0);
285
+ yeptris_document_free(doc);
286
+ size_t at = next_marker(it->buf, it->len, it->cursor);
287
+ if (at >= it->len) {
288
+ it->done = 1;
289
+ } else {
290
+ it->cursor = at;
291
+ }
292
+ it->index++;
293
+ if (index != NULL) {
294
+ *index = it->index - 1;
295
+ }
296
+ return it->last_status;
297
+ }
298
+ it_fail(it, YEPTRIS_OK, 0, 0);
299
+ it->last_off = it->cursor;
300
+ it->last_len = pos;
301
+ it->cursor += pos;
302
+ it->index++;
303
+ if (index != NULL) {
304
+ *index = it->index - 1;
305
+ }
306
+ *out = doc;
307
+ return YEPTRIS_OK;
308
+ }
309
+ }
310
+
311
+ YeptrisStatus yeptris_stream_iter_status(const struct yeptris_stream_iter* it, uint32_t* line,
312
+ uint32_t* col) {
313
+ if (it == NULL) {
314
+ return YEPTRIS_ERROR_ARG;
315
+ }
316
+ if (line != NULL) {
317
+ *line = it->last_line;
318
+ }
319
+ if (col != NULL) {
320
+ *col = it->last_col;
321
+ }
322
+ return it->last_status;
323
+ }
324
+
325
+ /* The last successful document's slice (parse.h): the host's value
326
+ * route re-parses exactly these bytes — one typing SSOT. */
327
+ YeptrisStatus yeptris_stream_iter_slice(const struct yeptris_stream_iter* it, size_t* off,
328
+ size_t* len) {
329
+ if (it == NULL || off == NULL || len == NULL) {
330
+ return YEPTRIS_ERROR_ARG;
331
+ }
332
+ if (it->last_status != YEPTRIS_OK || it->last_len == 0) {
333
+ return YEPTRIS_ERROR_ARG; /* a failure or the stream end was the last step */
334
+ }
335
+ *off = it->last_off;
336
+ *len = it->last_len;
337
+ return YEPTRIS_OK;
338
+ }
339
+
340
+ YeptrisStatus yeptris_stream_iter_buffer(const struct yeptris_stream_iter* it, const char** buf,
341
+ size_t* len) {
342
+ if (it == NULL || buf == NULL || len == NULL) {
343
+ return YEPTRIS_ERROR_ARG;
344
+ }
345
+ *buf = it->buf;
346
+ *len = it->len;
347
+ return YEPTRIS_OK;
348
+ }
349
+
350
+ void yeptris_stream_iter_free(struct yeptris_stream_iter* it) {
351
+ if (it == NULL) {
352
+ return;
353
+ }
354
+ const yep_allocator* sys = yep_system_allocator();
355
+ yep_free(sys, it->owned);
356
+ yep_free(sys, it->norm);
357
+ free(it);
358
+ }