yeptris 0.6.5.4 → 0.6.7.2

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 (115) hide show
  1. checksums.yaml +4 -4
  2. data/ext/libyeptris/extconf.rb +57 -0
  3. data/lib/yeptris/ffi.rb +12 -15
  4. data/lib/yeptris/json.rb +5 -2
  5. data/lib/yeptris/psych.rb +76 -3
  6. data/lib/yeptris.rb +36 -14
  7. data/vendor/libyeptris/CMakeLists.txt +254 -0
  8. data/vendor/libyeptris/cmake/yeptris-config.cmake.in +5 -0
  9. data/vendor/libyeptris/cmake/yeptris.pc.in +11 -0
  10. data/vendor/libyeptris/src/CMakeLists.txt +167 -0
  11. data/vendor/libyeptris/src/include/yeptris/api.h +32 -0
  12. data/vendor/libyeptris/src/include/yeptris/cbor.h +101 -0
  13. data/vendor/libyeptris/src/include/yeptris/dom.h +181 -0
  14. data/vendor/libyeptris/src/include/yeptris/emit.h +81 -0
  15. data/vendor/libyeptris/src/include/yeptris/error.h +41 -0
  16. data/vendor/libyeptris/src/include/yeptris/events.h +157 -0
  17. data/vendor/libyeptris/src/include/yeptris/json.h +45 -0
  18. data/vendor/libyeptris/src/include/yeptris/json.hpp +258 -0
  19. data/vendor/libyeptris/src/include/yeptris/jsonc_compat.h +115 -0
  20. data/vendor/libyeptris/src/include/yeptris/marshal.h +52 -0
  21. data/vendor/libyeptris/src/include/yeptris/parse.h +48 -0
  22. data/vendor/libyeptris/src/include/yeptris/plan.h +100 -0
  23. data/vendor/libyeptris/src/include/yeptris/resolve.h +71 -0
  24. data/vendor/libyeptris/src/include/yeptris/schema.h +119 -0
  25. data/vendor/libyeptris/src/include/yeptris/tape.h +99 -0
  26. data/vendor/libyeptris/src/include/yeptris/types.h +38 -0
  27. data/vendor/libyeptris/src/include/yeptris/values.h +102 -0
  28. data/vendor/libyeptris/src/include/yeptris/version.h.in +29 -0
  29. data/vendor/libyeptris/src/include/yeptris/visit.h +77 -0
  30. data/vendor/libyeptris/src/include/yeptris/yajl_compat.h +135 -0
  31. data/vendor/libyeptris/src/include/yeptris.h +23 -0
  32. data/vendor/libyeptris/src/yeptris/build.c +371 -0
  33. data/vendor/libyeptris/src/yeptris/cbor/cbor.h +25 -0
  34. data/vendor/libyeptris/src/yeptris/cbor/decode.c +846 -0
  35. data/vendor/libyeptris/src/yeptris/cbor/encode.c +824 -0
  36. data/vendor/libyeptris/src/yeptris/common/chartype.c +41 -0
  37. data/vendor/libyeptris/src/yeptris/common/chartype.h +77 -0
  38. data/vendor/libyeptris/src/yeptris/common/cpu.c +81 -0
  39. data/vendor/libyeptris/src/yeptris/common/cpu.h +40 -0
  40. data/vendor/libyeptris/src/yeptris/common/error.c +65 -0
  41. data/vendor/libyeptris/src/yeptris/common/error.h +79 -0
  42. data/vendor/libyeptris/src/yeptris/common/mutex.h +45 -0
  43. data/vendor/libyeptris/src/yeptris/common/nametab.c +275 -0
  44. data/vendor/libyeptris/src/yeptris/common/nametab.h +68 -0
  45. data/vendor/libyeptris/src/yeptris/common/port.h +74 -0
  46. data/vendor/libyeptris/src/yeptris/common/simd_text.c +49 -0
  47. data/vendor/libyeptris/src/yeptris/common/simd_text.h +295 -0
  48. data/vendor/libyeptris/src/yeptris/common/simd_text_avx2.c +534 -0
  49. data/vendor/libyeptris/src/yeptris/common/simd_text_neon.c +662 -0
  50. data/vendor/libyeptris/src/yeptris/common/simd_text_scalar.c +298 -0
  51. data/vendor/libyeptris/src/yeptris/common/string_view.c +34 -0
  52. data/vendor/libyeptris/src/yeptris/common/string_view.h +93 -0
  53. data/vendor/libyeptris/src/yeptris/doc.h +37 -0
  54. data/vendor/libyeptris/src/yeptris/dom/dom.c +973 -0
  55. data/vendor/libyeptris/src/yeptris/dom/dom.h +290 -0
  56. data/vendor/libyeptris/src/yeptris/dom/hpool.c +107 -0
  57. data/vendor/libyeptris/src/yeptris/dom/mapindex.c +173 -0
  58. data/vendor/libyeptris/src/yeptris/dom/mapindex.h +61 -0
  59. data/vendor/libyeptris/src/yeptris/dom/mutate.c +429 -0
  60. data/vendor/libyeptris/src/yeptris/emit/emit.c +349 -0
  61. data/vendor/libyeptris/src/yeptris/emit/float/api.h +38 -0
  62. data/vendor/libyeptris/src/yeptris/emit/float/dragon.c +405 -0
  63. data/vendor/libyeptris/src/yeptris/emit/float/floatint.h +203 -0
  64. data/vendor/libyeptris/src/yeptris/emit/float/print.c +396 -0
  65. data/vendor/libyeptris/src/yeptris/emit/style.c +81 -0
  66. data/vendor/libyeptris/src/yeptris/emit/style.h +24 -0
  67. data/vendor/libyeptris/src/yeptris/emit/writer.c +746 -0
  68. data/vendor/libyeptris/src/yeptris/emit/writer.h +61 -0
  69. data/vendor/libyeptris/src/yeptris/encoding/bom.c +31 -0
  70. data/vendor/libyeptris/src/yeptris/encoding/encoding.h +63 -0
  71. data/vendor/libyeptris/src/yeptris/encoding/transcode.c +148 -0
  72. data/vendor/libyeptris/src/yeptris/encoding/utf8_validate.c +178 -0
  73. data/vendor/libyeptris/src/yeptris/events/capture.c +150 -0
  74. data/vendor/libyeptris/src/yeptris/events/capture.h +39 -0
  75. data/vendor/libyeptris/src/yeptris/events/iterparse.c +208 -0
  76. data/vendor/libyeptris/src/yeptris/events/pull.c +97 -0
  77. data/vendor/libyeptris/src/yeptris/events/push.c +104 -0
  78. data/vendor/libyeptris/src/yeptris/events/recorder.c +107 -0
  79. data/vendor/libyeptris/src/yeptris/events/values.c +527 -0
  80. data/vendor/libyeptris/src/yeptris/events/values_priv.h +51 -0
  81. data/vendor/libyeptris/src/yeptris/events/yaml_compat.c +86 -0
  82. data/vendor/libyeptris/src/yeptris/events/yaml_compat.h +90 -0
  83. data/vendor/libyeptris/src/yeptris/jsonapi/jsonc_compat.c +687 -0
  84. data/vendor/libyeptris/src/yeptris/jsonapi/yajl_compat.c +728 -0
  85. data/vendor/libyeptris/src/yeptris/marshal.c +744 -0
  86. data/vendor/libyeptris/src/yeptris/memory/allocator.c +20 -0
  87. data/vendor/libyeptris/src/yeptris/memory/allocator.h +43 -0
  88. data/vendor/libyeptris/src/yeptris/memory/arena.c +134 -0
  89. data/vendor/libyeptris/src/yeptris/memory/arena.h +52 -0
  90. data/vendor/libyeptris/src/yeptris/memory/pool.c +115 -0
  91. data/vendor/libyeptris/src/yeptris/memory/pool.h +36 -0
  92. data/vendor/libyeptris/src/yeptris/parse/engine.c +3689 -0
  93. data/vendor/libyeptris/src/yeptris/parse/engine.h +65 -0
  94. data/vendor/libyeptris/src/yeptris/parse/events.h +124 -0
  95. data/vendor/libyeptris/src/yeptris/parse/numbers.c +349 -0
  96. data/vendor/libyeptris/src/yeptris/parse/numbers.h +33 -0
  97. data/vendor/libyeptris/src/yeptris/parse/scalars.c +416 -0
  98. data/vendor/libyeptris/src/yeptris/parse/scalars.h +75 -0
  99. data/vendor/libyeptris/src/yeptris/parse.c +650 -0
  100. data/vendor/libyeptris/src/yeptris/plan.c +817 -0
  101. data/vendor/libyeptris/src/yeptris/resolve/compat11.c +334 -0
  102. data/vendor/libyeptris/src/yeptris/resolve/core12.c +143 -0
  103. data/vendor/libyeptris/src/yeptris/resolve/resolver.h +56 -0
  104. data/vendor/libyeptris/src/yeptris/resolve/tags.c +58 -0
  105. data/vendor/libyeptris/src/yeptris/scan/json.c +792 -0
  106. data/vendor/libyeptris/src/yeptris/scan/json.h +109 -0
  107. data/vendor/libyeptris/src/yeptris/scan/scan.c +463 -0
  108. data/vendor/libyeptris/src/yeptris/scan/scan.h +150 -0
  109. data/vendor/libyeptris/src/yeptris/schema.c +238 -0
  110. data/vendor/libyeptris/src/yeptris/tape.c +1292 -0
  111. data/vendor/libyeptris/src/yeptris/version.c +7 -0
  112. data/vendor/libyeptris/src/yeptris/visit/dom_visit.c +115 -0
  113. data/vendor/libyeptris/src/yeptris/visit/json_visit.c +293 -0
  114. data/vendor/libyeptris/src/yeptris/visit/yaml_visit.c +127 -0
  115. metadata +112 -2
@@ -0,0 +1,100 @@
1
+ /* plan.h — the compiled plan walk (TODO.restructure/87 slice one,
2
+ * yeptris#293): a Descriptor-shaped plan compiled from a JSON spec,
3
+ * applied to a parsed JSON tape in ONE C pass producing typed
4
+ * COLUMNAR output — no Ruby/Python tree, no per-node host dispatch.
5
+ *
6
+ * Slice one covers the lutaml-model shape: a root collection (seq or
7
+ * map-of-rows) whose rows are mappings of scalar leaves (int, float,
8
+ * str, bool). Nested paths, the YAML leg, and partial descriptors
9
+ * compose later per the board item.
10
+ *
11
+ * The plan borrows nothing; the result borrows the tape's source
12
+ * buffer for string spans (free the result before the tape/source).
13
+ */
14
+ #ifndef YEPTRIS_PLAN_H
15
+ #define YEPTRIS_PLAN_H
16
+
17
+ #include <stddef.h>
18
+ #include <stdint.h>
19
+
20
+ #include <yeptris/api.h>
21
+ #include <yeptris/error.h>
22
+ #include <yeptris/tape.h>
23
+
24
+ #ifdef __cplusplus
25
+ extern "C" {
26
+ #endif
27
+
28
+ /* Column kinds (mirrors the spec's leaf "kind"). */
29
+ enum {
30
+ YEP_PLAN_INT = 0,
31
+ YEP_PLAN_FLOAT,
32
+ YEP_PLAN_STR,
33
+ YEP_PLAN_BOOL,
34
+ };
35
+
36
+ typedef struct yeptris_plan yeptris_plan;
37
+ typedef struct yeptris_plan_result yeptris_plan_result;
38
+
39
+ /* Compiles a plan from a strict-JSON spec document:
40
+ *
41
+ * {"kind":"seq","path":"items","children":[
42
+ * {"name":"id","kind":"int"}, {"name":"ok","kind":"bool"}, ...]}
43
+ *
44
+ * kind: "seq" or "map" — the ROWS container's shape at the root.
45
+ * path: the root mapping's key holding the rows — a string, or an
46
+ * ARRAY of strings for a segmented (nested) path walked
47
+ * mapping by mapping. Empty/absent: the seq root itself.
48
+ * Leaf kinds: int, float, str, bool. Returns NULL with *st on
49
+ * a malformed spec (ARG/PARSE) or allocation failure. */
50
+ YEPTRIS_API yeptris_plan* yeptris_plan_compile(const char* spec, size_t len, YeptrisStatus* st);
51
+
52
+ YEPTRIS_API void yeptris_plan_free(yeptris_plan* plan);
53
+
54
+ YEPTRIS_API size_t yeptris_plan_column_count(const yeptris_plan* plan);
55
+
56
+ /* Applies the plan to a tape (from yeptris_parse_json_tape; the
57
+ * LENIENT tape also works — NUM records convert at extraction).
58
+ * Every row of the collection fills one slot per column; missing or
59
+ * null leaves mark the slot null. Returns NULL with *st on
60
+ * PARSE (document shape disagreement) or MEMORY. */
61
+ YEPTRIS_API yeptris_plan_result*
62
+ yeptris_tape_plan_walk(const yeptris_json_tape* tape, const yeptris_plan* plan, YeptrisStatus* st);
63
+
64
+ /* The YAML/DOM leg: the same compiled plan applied to a parsed
65
+ * yeptris document (yeptris_parse — any schema). Typed extraction
66
+ * rides the parse-time tag ids; string columns expose (ptr,len)
67
+ * views into the document's regions (input or string arena), so the
68
+ * RESULT BORROWS the document — free the result first. Same status
69
+ * contract as the tape walk. */
70
+ YEPTRIS_API yeptris_plan_result*
71
+ yeptris_document_plan_walk(YeptrisDocument doc, const yeptris_plan* plan, YeptrisStatus* st);
72
+
73
+ YEPTRIS_API void yeptris_plan_result_free(yeptris_plan_result* r);
74
+
75
+ /* Result accessors: rows, and per-column kind + typed arrays. The
76
+ * arrays hold `rows` entries; NULL markers are the per-column u8
77
+ * bitmap (1 = null/missing). String columns expose spans into the
78
+ * tape's source. */
79
+ YEPTRIS_API size_t yeptris_plan_result_rows(const yeptris_plan_result* r);
80
+ YEPTRIS_API int yeptris_plan_result_kind(const yeptris_plan_result* r, size_t col);
81
+ YEPTRIS_API const int64_t* yeptris_plan_result_ints(const yeptris_plan_result* r, size_t col);
82
+ YEPTRIS_API const double* yeptris_plan_result_floats(const yeptris_plan_result* r, size_t col);
83
+ YEPTRIS_API const uint32_t* yeptris_plan_result_str_offs(const yeptris_plan_result* r, size_t col);
84
+ YEPTRIS_API const uint32_t* yeptris_plan_result_str_lens(const yeptris_plan_result* r, size_t col);
85
+ /* The DOM leg's string column: rows (ptr,len) views into the
86
+ * document (NULL on the tape leg — use the offs/lens pair there). */
87
+ typedef struct yeptris_plan_str {
88
+ const char* p;
89
+ size_t len;
90
+ } yeptris_plan_str;
91
+
92
+ YEPTRIS_API const yeptris_plan_str* yeptris_plan_result_strs(const yeptris_plan_result* r,
93
+ size_t col);
94
+ YEPTRIS_API const uint8_t* yeptris_plan_result_nulls(const yeptris_plan_result* r, size_t col);
95
+
96
+ #ifdef __cplusplus
97
+ }
98
+ #endif
99
+
100
+ #endif /* YEPTRIS_PLAN_H */
@@ -0,0 +1,71 @@
1
+ /* resolve.h — schema resolvers and typed scalar access (TODO.impl/10).
2
+ *
3
+ * Typing is pluggable and outside the grammar: a resolver decides,
4
+ * per plain scalar, which implicit tag it carries. YAML 1.2 core
5
+ * correctness and Psych/libyaml 1.1 parity are two resolvers over one
6
+ * interface; the parse options select one per document.
7
+ *
8
+ * Resolution assigns a dense tag id at parse time (stored on DOM
9
+ * nodes); typed VALUE conversion happens on accessor demand — parse
10
+ * speed never pays for typing the caller never reads.
11
+ */
12
+ #ifndef YEPTRIS_RESOLVE_H
13
+ #define YEPTRIS_RESOLVE_H
14
+
15
+ #include <stddef.h>
16
+ #include <stdint.h>
17
+
18
+ #include <yeptris/api.h>
19
+ #include <yeptris/error.h>
20
+ #include <yeptris/types.h>
21
+
22
+ #ifdef __cplusplus
23
+ extern "C" {
24
+ #endif
25
+
26
+ /* Tag ids. The core set is preallocated and stable (ABI-pinned);
27
+ * custom tags resolve to YEPTRIS_TAG_CUSTOM and keep their string. */
28
+ typedef enum {
29
+ YEPTRIS_TAG_STR = 0,
30
+ YEPTRIS_TAG_INT = 1,
31
+ YEPTRIS_TAG_FLOAT = 2,
32
+ YEPTRIS_TAG_BOOL = 3,
33
+ YEPTRIS_TAG_NULL = 4,
34
+ YEPTRIS_TAG_TIMESTAMP = 5,
35
+ YEPTRIS_TAG_SEQ = 6,
36
+ YEPTRIS_TAG_MAP = 7,
37
+ YEPTRIS_TAG_BINARY = 8,
38
+ YEPTRIS_TAG_MERGE = 9,
39
+ YEPTRIS_TAG_VALUE = 10,
40
+ YEPTRIS_TAG_CUSTOM = 11,
41
+ } YeptrisTagId;
42
+
43
+ /* Schemas. */
44
+ typedef enum {
45
+ YEPTRIS_SCHEMA_12_CORE = 0, /* default: the yaml-test-suite target */
46
+ YEPTRIS_SCHEMA_11_COMPAT, /* libyaml/Psych implicit typing */
47
+ } YeptrisSchema;
48
+
49
+ /* Canonical tag URI for a core id ("tag:yaml.org,2002:str"); NULL for
50
+ * YEPTRIS_TAG_CUSTOM. */
51
+ YEPTRIS_API const char* yeptris_tag_uri(YeptrisTagId id);
52
+
53
+ /* The tag a scalar resolved to (PLAIN scalars carry their implicit
54
+ * tag; quoted/other styles are always STR; explicit tags map to their
55
+ * core id when they match one, else CUSTOM). Non-scalars: SEQ/MAP.
56
+ * YEPTRIS_ERROR_ARG on a bad handle. */
57
+ YEPTRIS_API YeptrisTagId yeptris_node_tag_id(YeptrisNode node);
58
+
59
+ /* Typed access (lazy conversion from the raw view; resolution's tag
60
+ * id decides eligibility, the conversion revalidates the bytes):
61
+ * YEPTRIS_ERROR_PARSE when the scalar's tag does not match the
62
+ * accessor (e.g. an INT accessor on a STR). */
63
+ YEPTRIS_API YeptrisStatus yeptris_node_int(YeptrisNode node, int64_t* out);
64
+ YEPTRIS_API YeptrisStatus yeptris_node_float(YeptrisNode node, double* out);
65
+ YEPTRIS_API YeptrisStatus yeptris_node_bool(YeptrisNode node, int* out);
66
+
67
+ #ifdef __cplusplus
68
+ }
69
+ #endif
70
+
71
+ #endif /* YEPTRIS_RESOLVE_H */
@@ -0,0 +1,119 @@
1
+ /* schema.h — the fused schema-descriptor materialization API
2
+ * (issue #238, TODO.restructure/83).
3
+ *
4
+ * The descriptor is the ABI, NOT a schema language: XSD/JSON-Schema
5
+ * cannot express consumer semantics (two-names-one-slot merges, value
6
+ * maps, key renames, raw capture) — the CONSUMER compiles those into
7
+ * this flat positional plan, the same way lutaml-model compiles its
8
+ * rule plans. The engine materializes against it in ONE native pass;
9
+ * the intermediate generic document (the Hash/Array the bindings used
10
+ * to build) never exists.
11
+ *
12
+ * Design contract (from the committed consumer, co-designed):
13
+ * - kind CALLBACK is the escape hatch: the raw value span plus the
14
+ * node's byte position come back as records; the host finishes
15
+ * just those fields (custom procs, polymorphism, delegates).
16
+ * - Results are WHOLE DOCUMENTS: this call never crosses the FFI
17
+ * boundary per value — the caller passes output buffers sized by
18
+ * expectation and receives per-node counts.
19
+ * - The descriptor ABI is versioned in lockstep with the bindings
20
+ * ({c-semver}.{binding-patch}); desc_abi changes only with a C
21
+ * minor bump.
22
+ * - Sequences of a plan run the SAME node plan for every element
23
+ * (flags ELEMENT); nested mappings run their child plan slice.
24
+ */
25
+ #ifndef YEPTRIS_SCHEMA_H
26
+ #define YEPTRIS_SCHEMA_H
27
+
28
+ #include <stddef.h>
29
+ #include <stdint.h>
30
+
31
+ #include <yeptris/api.h>
32
+ #include <yeptris/error.h>
33
+ #include <yeptris/parse.h>
34
+
35
+ #ifdef __cplusplus
36
+ extern "C" {
37
+ #endif
38
+
39
+ /* The descriptor ABI version of this header. */
40
+ #define YEPTRIS_DESC_ABI 1u
41
+
42
+ /* node kinds */
43
+ enum {
44
+ YEP_SK_SCALAR = 0, /* typed leaf: type_tag decides the column */
45
+ YEP_SK_SEQUENCE, /* sequence: children[0] is the ELEMENT plan */
46
+ YEP_SK_MAPPING, /* mapping: children are the key plans */
47
+ YEP_SK_CALLBACK, /* escape hatch: raw span + position records */
48
+ };
49
+
50
+ /* scalar type tags (the columns' element types) */
51
+ enum {
52
+ YEP_ST_STR = 0, /* off/len into the input */
53
+ YEP_ST_INT, /* int64_t */
54
+ YEP_ST_FLOAT, /* double */
55
+ YEP_ST_BOOL, /* uint8_t */
56
+ YEP_ST_NULL, /* no payload (count only) */
57
+ YEP_ST_ANY, /* SCALAR: keep the resolver's verdict — the
58
+ column is a YeptrisValue-like record */
59
+ };
60
+
61
+ /* node flags */
62
+ enum {
63
+ YEP_SF_REQUIRED = 1u << 0, /* missing at its mapping -> error */
64
+ YEP_SF_FIRST_WINS = 1u << 1, /* duplicates: first match kept
65
+ (default: last, as at parse) */
66
+ };
67
+
68
+ /* One plan node. 32 bytes, ABI-pinned. */
69
+ typedef struct yeptris_desc_node {
70
+ const char* wire_name; /* mapping key to match (NULL: the root) */
71
+ uint8_t kind; /* YEP_SK_* */
72
+ uint8_t type_tag; /* YEP_ST_* (SCALAR) */
73
+ uint16_t flags; /* YEP_SF_* */
74
+ uint32_t child_index; /* SEQUENCE: the element plan; MAPPING: the
75
+ first child. Unused otherwise (0). */
76
+ uint32_t child_count; /* MAPPING: children from child_index. */
77
+ uint32_t reserved; /* must be 0 (ABI headroom) */
78
+ } yeptris_desc_node;
79
+
80
+ YEPTRIS_CT_ASSERT(sizeof(yeptris_desc_node) == 24);
81
+
82
+ /* One column's output. Caller allocates the payload array (sized by
83
+ * expectation); the call fills it and sets count. No per-value FFI:
84
+ * hosts drain whole columns after the call. */
85
+ typedef struct yeptris_schema_column {
86
+ void* data; /* element type from the plan's type_tag */
87
+ uint32_t capacity; /* elements the buffer holds */
88
+ uint32_t count; /* elements materialized (out) */
89
+ } yeptris_schema_column;
90
+
91
+ /* STR/CALLBACK payload: off/len into the INPUT buffer (zero-copy to
92
+ * the host). CALLBACK also carries the node's byte position. */
93
+ typedef struct yeptris_span2 {
94
+ uint32_t off;
95
+ uint32_t len;
96
+ uint32_t node_off; /* the node's first byte (callbacks) */
97
+ uint32_t pad;
98
+ } yeptris_span2;
99
+
100
+ YEPTRIS_CT_ASSERT(sizeof(yeptris_span2) == 16);
101
+
102
+ /* Parses `source` (YAML or strict JSON — the same front door as
103
+ * yeptris_parse_ex) and materializes against the descriptor in one
104
+ * pass: node i's matches land in cols[i]. The input buffer must
105
+ * outlive the string/callback spans (they borrow it).
106
+ *
107
+ * Status: YEPTRIS_OK; YEPTRIS_ERROR_PARSE (yeptris_last_error);
108
+ * YEPTRIS_ERROR_SCHEMA (a REQUIRED node missing — the error carries
109
+ * the node index; detail via yeptris_last_error); YEPTRIS_ERROR_MEMORY
110
+ * / ARG (NULL descriptor, desc_len 0, desc_abi mismatch). */
111
+ YEPTRIS_API YeptrisStatus yeptris_schema_load(const char* source, size_t len, YeptrisSchema schema,
112
+ const yeptris_desc_node* desc, uint32_t desc_len,
113
+ uint32_t desc_abi, yeptris_schema_column* cols);
114
+
115
+ #ifdef __cplusplus
116
+ }
117
+ #endif
118
+
119
+ #endif /* YEPTRIS_SCHEMA_H */
@@ -0,0 +1,99 @@
1
+ /* tape.h — the compact JSON tape (issue #238's consumer shape,
2
+ * TODO.restructure/85: the simdjson-class materialization).
3
+ *
4
+ * One fused strict walk appends ONE record per token — no DOM nodes,
5
+ * no links, no views. Records are THREE parallel columns (kind byte,
6
+ * off, len) carved from one block: bools encode in the kind, container
7
+ * links ride the off column, and NUMBERS RECORD SPANS ONLY — parse
8
+ * validates the grammar (the lean shape scan) and materialize converts
9
+ * (yeptris_tape_convert; the C-API materializer converts inline).
10
+ * Strings stay zero-copy spans into the caller's buffer.
11
+ *
12
+ * The tape is a document-level result (never per value across FFI);
13
+ * the buffer the spans borrow must outlive it.
14
+ */
15
+ #ifndef YEPTRIS_TAPE_H
16
+ #define YEPTRIS_TAPE_H
17
+
18
+ #include <stddef.h>
19
+ #include <stdint.h>
20
+
21
+ #include <yeptris/api.h>
22
+ #include <yeptris/error.h>
23
+
24
+ #ifdef __cplusplus
25
+ extern "C" {
26
+ #endif
27
+
28
+ /* Record kinds (the kinds column). */
29
+ enum {
30
+ YEP_T_DOC = 0, /* document boundary (records start after it) */
31
+ YEP_T_NULL,
32
+ YEP_T_TRUE, /* the kind IS the value */
33
+ YEP_T_FALSE, /* the kind IS the value */
34
+ YEP_T_INT, /* off/len: signed digit span; convert at materialize */
35
+ YEP_T_FLOAT, /* off/len: float text span; convert at materialize */
36
+ YEP_T_STR, /* off/len: raw span (escapes untouched; the
37
+ qbc kernel found them) */
38
+ YEP_T_SEQ_OPEN, /* off: index of the matching CLOSE */
39
+ YEP_T_MAP_OPEN, /* off: index of the matching CLOSE; keys are
40
+ the STR records at even positions inside */
41
+ YEP_T_CLOSE, /* off: index of the matching OPEN */
42
+ YEP_T_NUM, /* lenient route only: off/len number span with
43
+ the grammar UNVALIDATED at parse —
44
+ yeptris_tape_convert is the authority (it
45
+ classifies int/float and rejects malformed
46
+ spans; simdjson's deferred contract) */
47
+ };
48
+
49
+ typedef struct yeptris_json_tape {
50
+ size_t count;
51
+ uint8_t* kinds; /* yeptris tape kind per record */
52
+ uint32_t* offs; /* span starts (STR/INT/FLOAT); container links */
53
+ uint32_t* lens; /* span lengths (STR/INT/FLOAT) */
54
+ int64_t int_min; /* set by yeptris_tape_convert when an INT span
55
+ exceeds int64 (materialize-time discovery) */
56
+ const void* _src; /* the parsed buffer (spans borrow it; it must
57
+ outlive the tape — same contract as the spans) */
58
+ size_t _srclen;
59
+ void* _block; /* the carved allocation base */
60
+ } yeptris_json_tape;
61
+
62
+ /* Parses strict JSON into the tape. Accepts scalar roots (a single
63
+ * record). Returns YEPTRIS_OK, YEPTRIS_ERROR_PARSE (details via
64
+ * yeptris_last_error), YEPTRIS_ERROR_MEMORY, YEPTRIS_ERROR_ARG. */
65
+ YEPTRIS_API YeptrisStatus yeptris_parse_json_tape(const char* source, size_t len,
66
+ yeptris_json_tape* tape);
67
+
68
+ /* The lenient route (simdjson's deferred contract, opt-in): every
69
+ * STRUCTURAL check stays at parse (bracket matching, alternation,
70
+ * comma/colon placement, literals, string closes/escapes) while
71
+ * NUMBER grammar defers to yeptris_tape_convert — a number records
72
+ * as a YEP_T_NUM charset run (so "1.2.3" is accepted here and
73
+ * rejected at convert, exactly where simdjson's number parse would
74
+ * fail; a run with non-number bytes like "12ab" still rejects
75
+ * structurally at parse). Accepts a superset of the strict route's
76
+ * inputs (tab whitespace becomes legal, RFC 8259); on everything
77
+ * the strict route accepts, the tapes are structurally identical
78
+ * (spans and containers equal; NUM records carry the same bytes the
79
+ * strict INT/FLOAT records carry). Non-ASCII inputs take the strict
80
+ * route unchanged. */
81
+ YEPTRIS_API YeptrisStatus yeptris_parse_json_tape_lenient(const char* source, size_t len,
82
+ yeptris_json_tape* tape);
83
+
84
+ YEPTRIS_API void yeptris_tape_free(yeptris_json_tape* tape);
85
+
86
+ /* Converts the INT/FLOAT records in [from, to): ivals/dvals are
87
+ * parallel to the RECORD indices (slots for other kinds are left
88
+ * untouched; either pointer may be NULL). Returns the number of
89
+ * number records converted, or SIZE_MAX if a span does not re-scan
90
+ * as a number (impossible for a tape this library produced).
91
+ * Sets t->int_min when an INT span exceeds int64. */
92
+ YEPTRIS_API size_t yeptris_tape_convert(yeptris_json_tape* t, size_t from, size_t to,
93
+ int64_t* ivals, double* dvals);
94
+
95
+ #ifdef __cplusplus
96
+ }
97
+ #endif
98
+
99
+ #endif /* YEPTRIS_TAPE_H */
@@ -0,0 +1,38 @@
1
+ /* types.h — opaque public handles.
2
+ *
3
+ * The single canonical source of public types (TODO.impl/02 extends this
4
+ * file; internal types never appear here). Callers never see struct
5
+ * definitions: every handle is opaque and pointer-sized, asserted by the
6
+ * ABI pinning test (test/unit/test_abi.cpp).
7
+ */
8
+ #ifndef YEPTRIS_TYPES_H
9
+ #define YEPTRIS_TYPES_H
10
+
11
+ #include <stddef.h>
12
+
13
+ #ifdef __cplusplus
14
+ extern "C" {
15
+ #endif
16
+
17
+ /* A parsed document; the sole owner of all memory reachable from it.
18
+ * Memory: freed exactly once with yeptris_document_free (TODO.impl/11). */
19
+ typedef struct yeptris_document* YeptrisDocument;
20
+
21
+ /* A node (document, mapping, sequence, scalar, alias) inside a document.
22
+ * Memory: borrowed from its document — valid until the document is freed. */
23
+ typedef struct yeptris_node* YeptrisNode;
24
+
25
+ /* Streaming/streaming-adjacent handles, introduced with their items:
26
+ * parser engine (TODO.impl/07), pull/recorder/iterparse (TODO.impl/12),
27
+ * emitter (TODO.impl/13). Declared now so the handle vocabulary is stable. */
28
+ typedef struct yeptris_parser* YeptrisParser;
29
+ typedef struct yeptris_pull* YeptrisPullParser;
30
+ typedef struct yeptris_recorder* YeptrisRecorder;
31
+ typedef struct yeptris_iterparse* YeptrisIterparse;
32
+ typedef struct yeptris_emitter* YeptrisEmitter;
33
+
34
+ #ifdef __cplusplus
35
+ }
36
+ #endif
37
+
38
+ #endif /* YEPTRIS_TYPES_H */
@@ -0,0 +1,102 @@
1
+ /* values.h — the typed value stream (TODO.impl/15 phase F).
2
+ *
3
+ * The materialization fast path for FFI bindings: one parse, one
4
+ * drain of PRE-CONVERTED typed values. The C side runs the same
5
+ * engine the recorder drives, then converts every scalar by its
6
+ * resolver tag — the host walks a flat array and builds containers,
7
+ * never re-parsing text.
8
+ *
9
+ * The `is_key` bit carries the key/value alternation, so hosts need
10
+ * no pending-key bookkeeping; `tag_id` rides along so hosts with
11
+ * schema quirks (Psych's single-char y/n, PyYAML's dot-required
12
+ * floats) can re-decide a scalar's type from its raw bytes without
13
+ * re-running a conversion grammar.
14
+ */
15
+ #ifndef YEPTRIS_VALUES_H
16
+ #define YEPTRIS_VALUES_H
17
+
18
+ #include <stddef.h>
19
+ #include <stdint.h>
20
+
21
+ #include <yeptris/api.h>
22
+ #include <yeptris/error.h>
23
+ #include <yeptris/resolve.h>
24
+
25
+ #ifdef __cplusplus
26
+ extern "C" {
27
+ #endif
28
+
29
+ typedef enum {
30
+ YEP_V_DOC = 0, /* document boundary */
31
+ YEP_V_NULL,
32
+ YEP_V_BOOL, /* b carries 0/1 */
33
+ YEP_V_INT, /* i */
34
+ YEP_V_FLOAT, /* d */
35
+ YEP_V_STR, /* off/len bytes */
36
+ YEP_V_TIMESTAMP, /* off/len bytes (host constructs the date) */
37
+ YEP_V_SEQ_OPEN,
38
+ YEP_V_MAP_OPEN,
39
+ YEP_V_CLOSE, /* closes the innermost open container */
40
+ YEP_V_ALIAS, /* off/len: the alias name */
41
+ /* decorates the entry that FOLLOWS it: the anchor name binds to
42
+ * that value (identity for aliases). Emitted only when anchored. */
43
+ YEP_V_ANCHOR, /* off/len: the name */
44
+ } YeptrisValueKind;
45
+
46
+ /* 24 bytes, ABI-pinned. Every scalar carries its raw bytes (off/len)
47
+ * next to a typed payload; `p` holds the INT bits or the FLOAT bits
48
+ * (reinterpreted by kind — hosts unpack it as ONE 64-bit field, so
49
+ * the record costs 7 values, not 8). */
50
+ typedef struct {
51
+ uint8_t kind; /* YeptrisValueKind */
52
+ uint8_t tag_id; /* the resolver's verdict for this scalar */
53
+ uint8_t is_key; /* the entry lands in the inner map's key slot */
54
+ uint8_t b; /* BOOL payload; implicit-plain flag otherwise */
55
+ uint32_t off; /* STR/TIMESTAMP/ALIAS/anchor bytes */
56
+ uint32_t len;
57
+ uint64_t p; /* INT or FLOAT payload, by kind */
58
+ } YeptrisValue;
59
+ YEPTRIS_CT_ASSERT(sizeof(YeptrisValue) == 24);
60
+
61
+ /* Parses `yaml` and drains the typed value stream. On success sets
62
+ * *vals / *count / *arena / *arena_len (both malloc'd; free with
63
+ * yeptris_value_free exactly once). Returns YEPTRIS_OK,
64
+ * YEPTRIS_ERROR_PARSE (details via yeptris_last_error), or
65
+ * YEPTRIS_ERROR_MEMORY / YEPTRIS_ERROR_ARG. */
66
+ YEPTRIS_API YeptrisStatus yeptris_value_drain(const char* yaml, size_t len, YeptrisSchema schema,
67
+ YeptrisValue** vals, size_t* count, char** arena,
68
+ size_t* arena_len);
69
+
70
+ YEPTRIS_API void yeptris_value_free(YeptrisValue* vals, char* arena);
71
+
72
+ /* Columnar projection of the same stream (task #42: the materializer
73
+ * wall is per-record struct decoding in FFI hosts — parallel typed
74
+ * buffers let bindings iterate C-speed arrays and unpack whole
75
+ * columns in one call). Same walk, same semantics, same arena; one
76
+ * carved allocation holds payloads/offs/lens/kinds/tags/is_keys/bools
77
+ * (payloads is the block base — yeptris_value_free_columns frees it
78
+ * and the arena; both are safe on a zero-entry drain). */
79
+ typedef struct {
80
+ size_t count;
81
+ size_t arena_len;
82
+ int64_t* payloads; /* INT or FLOAT bits, by kind */
83
+ uint32_t* offs; /* STR/TIMESTAMP/ALIAS/ANCHOR bytes */
84
+ uint32_t* lens;
85
+ uint8_t* kinds; /* YeptrisValueKind */
86
+ uint8_t* tags; /* resolver verdict per scalar */
87
+ uint8_t* is_keys;
88
+ uint8_t* bools; /* BOOL payload; implicit-plain flag otherwise */
89
+ char* arena;
90
+ } YeptrisValueColumns;
91
+
92
+ YEPTRIS_API YeptrisStatus yeptris_value_drain_columns(const char* yaml, size_t len,
93
+ YeptrisSchema schema,
94
+ YeptrisValueColumns* cols);
95
+
96
+ YEPTRIS_API void yeptris_value_free_columns(YeptrisValueColumns* cols);
97
+
98
+ #ifdef __cplusplus
99
+ }
100
+ #endif
101
+
102
+ #endif /* YEPTRIS_VALUES_H */
@@ -0,0 +1,29 @@
1
+ /* version.h — generated from the CMake project VERSION.
2
+ *
3
+ * CMakeLists.txt project(yeptris VERSION ...) is the single source of truth;
4
+ * scripts/bump-version.sh syncs vcpkg.json and CHANGELOG.md from it. Never
5
+ * hand-edit the generated file (it lives in the build tree).
6
+ */
7
+ #ifndef YEPTRIS_VERSION_H
8
+ #define YEPTRIS_VERSION_H
9
+
10
+ #include <yeptris/api.h>
11
+
12
+ #define YEPTRIS_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
13
+ #define YEPTRIS_VERSION_MINOR @PROJECT_VERSION_MINOR@
14
+ #define YEPTRIS_VERSION_PATCH @PROJECT_VERSION_PATCH@
15
+ #define YEPTRIS_VERSION_STRING "@PROJECT_VERSION@"
16
+
17
+ #ifdef __cplusplus
18
+ extern "C" {
19
+ #endif
20
+
21
+ /* Returns the library version string ("major.minor.patch").
22
+ * Memory: static storage; valid for the lifetime of the process. */
23
+ YEPTRIS_API const char* yeptris_version(void);
24
+
25
+ #ifdef __cplusplus
26
+ }
27
+ #endif
28
+
29
+ #endif /* YEPTRIS_VERSION_H */
@@ -0,0 +1,77 @@
1
+ /* visit.h — language-agnostic value visitor (TODO.restructure/22/24).
2
+ *
3
+ * A push-style sink over the parsed value stream. Hosts that build
4
+ * native objects (Ruby C-API, CPython, etc.) implement the vtable and
5
+ * receive one callback per scalar/container — no intermediate records,
6
+ * no DOM, no host-side walk. The JSON entry is a fused RFC 8259 scan
7
+ * that never allocates a tree; the YAML entry rides the engine; the
8
+ * node entry walks an existing DOM subtree.
9
+ *
10
+ * OCP: a new host is a new vtable, never a core edit. MECE: scanning
11
+ * stays in scan/; this header is only the sink contract. */
12
+ #ifndef YEPTRIS_VISIT_H
13
+ #define YEPTRIS_VISIT_H
14
+
15
+ #include <stddef.h>
16
+ #include <stdint.h>
17
+
18
+ #include <yeptris/api.h>
19
+ #include <yeptris/dom.h>
20
+ #include <yeptris/error.h>
21
+ #include <yeptris/resolve.h>
22
+
23
+ #ifdef __cplusplus
24
+ extern "C" {
25
+ #endif
26
+
27
+ /* Return 0 to continue, nonzero to abort (propagated as the status
28
+ * detail when non-zero; YEPTRIS_ERROR_INTERNAL is the library-side
29
+ * stand-in when the visitor doesn't set a more specific code). */
30
+ typedef struct YeptrisVisitVTable {
31
+ int (*on_null)(void* ctx);
32
+ int (*on_bool)(void* ctx, int truthy);
33
+ int (*on_int)(void* ctx, int64_t v);
34
+ int (*on_float)(void* ctx, double v);
35
+ /* bytes are borrowed from the input (or a short-lived decode
36
+ * scratch for escaped JSON strings — valid only for the duration
37
+ * of the callback). */
38
+ int (*on_string)(void* ctx, const char* p, size_t len);
39
+ int (*on_seq_start)(void* ctx);
40
+ int (*on_seq_end)(void* ctx);
41
+ int (*on_map_start)(void* ctx);
42
+ /* A map key is always a string callback immediately followed by
43
+ * the value; hosts that need the key/value pairing push the key
44
+ * on on_string when is_key is set. */
45
+ int (*on_map_end)(void* ctx);
46
+ /* Optional: 1 when the next scalar/container is a map key. NULL
47
+ * means the visitor does not distinguish (JSON keys are always
48
+ * strings fired via on_string before their value). */
49
+ int (*on_key)(void* ctx, const char* p, size_t len);
50
+ /* Optional document boundary (YAML multi-doc). NULL = ignore. */
51
+ int (*on_doc)(void* ctx);
52
+ /* Optional anchor/alias. NULL = materializer does not support
53
+ * identity (JSON never fires these). */
54
+ int (*on_anchor)(void* ctx, const char* name, size_t len);
55
+ int (*on_alias)(void* ctx, const char* name, size_t len);
56
+ } YeptrisVisitVTable;
57
+
58
+ /* Fused strict-JSON scan → visit. No DOM, no records. On success the
59
+ * visitor saw exactly one value (plus optional ws). */
60
+ YEPTRIS_API YeptrisStatus yeptris_visit_json(const char* data, size_t len,
61
+ const YeptrisVisitVTable* vt, void* ctx);
62
+
63
+ /* YAML parse → visit through the engine (schema selects the resolver).
64
+ * Multi-doc streams fire on_doc before each document's root value. */
65
+ YEPTRIS_API YeptrisStatus yeptris_visit(const char* data, size_t len, YeptrisSchema schema,
66
+ const YeptrisVisitVTable* vt, void* ctx);
67
+
68
+ /* Existing DOM subtree → visit (Node#to_ruby bulk path without
69
+ * records/Marshal). */
70
+ YEPTRIS_API YeptrisStatus yeptris_visit_node(YeptrisNode node, const YeptrisVisitVTable* vt,
71
+ void* ctx);
72
+
73
+ #ifdef __cplusplus
74
+ }
75
+ #endif
76
+
77
+ #endif /* YEPTRIS_VISIT_H */