yeptris 0.6.18.2-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 (142) hide show
  1. checksums.yaml +7 -0
  2. data/README.adoc +141 -0
  3. data/ext/build_windows_native.rb +41 -0
  4. data/ext/libyeptris/extconf.rb +57 -0
  5. data/ext/yeptris_native/cbor_ruby.c +193 -0
  6. data/ext/yeptris_native/extconf.rb +47 -0
  7. data/ext/yeptris_native/json_ruby.c +354 -0
  8. data/ext/yeptris_native/yeptris_native.c +497 -0
  9. data/lib/yeptris/cbor.rb +130 -0
  10. data/lib/yeptris/document.rb +255 -0
  11. data/lib/yeptris/ffi.rb +426 -0
  12. data/lib/yeptris/json/descriptor.rb +266 -0
  13. data/lib/yeptris/json.rb +394 -0
  14. data/lib/yeptris/materializer.rb +354 -0
  15. data/lib/yeptris/native-3.4.so +0 -0
  16. data/lib/yeptris/node.rb +453 -0
  17. data/lib/yeptris/psych/class_loader.rb +24 -0
  18. data/lib/yeptris/psych/coder_shim.rb +55 -0
  19. data/lib/yeptris/psych/drop_in.rb +63 -0
  20. data/lib/yeptris/psych/encodable.rb +14 -0
  21. data/lib/yeptris/psych/handler.rb +90 -0
  22. data/lib/yeptris/psych/parser.rb +105 -0
  23. data/lib/yeptris/psych/scalar_scanner.rb +149 -0
  24. data/lib/yeptris/psych/visitors.rb +545 -0
  25. data/lib/yeptris/psych.rb +622 -0
  26. data/lib/yeptris/schema.rb +253 -0
  27. data/lib/yeptris/valueml.rb +455 -0
  28. data/lib/yeptris/yaml/descriptor.rb +56 -0
  29. data/lib/yeptris/yaml.rb +422 -0
  30. data/lib/yeptris.rb +113 -0
  31. data/libyeptris.so +0 -0
  32. data/vendor/libyeptris/CMakeLists.txt +254 -0
  33. data/vendor/libyeptris/cmake/yeptris-config.cmake.in +5 -0
  34. data/vendor/libyeptris/cmake/yeptris.pc.in +11 -0
  35. data/vendor/libyeptris/src/CMakeLists.txt +167 -0
  36. data/vendor/libyeptris/src/include/yeptris/api.h +32 -0
  37. data/vendor/libyeptris/src/include/yeptris/cbor.h +101 -0
  38. data/vendor/libyeptris/src/include/yeptris/dom.h +190 -0
  39. data/vendor/libyeptris/src/include/yeptris/emit.h +81 -0
  40. data/vendor/libyeptris/src/include/yeptris/error.h +41 -0
  41. data/vendor/libyeptris/src/include/yeptris/events.h +157 -0
  42. data/vendor/libyeptris/src/include/yeptris/json.h +45 -0
  43. data/vendor/libyeptris/src/include/yeptris/json.hpp +258 -0
  44. data/vendor/libyeptris/src/include/yeptris/jsonc_compat.h +115 -0
  45. data/vendor/libyeptris/src/include/yeptris/marshal.h +52 -0
  46. data/vendor/libyeptris/src/include/yeptris/parse.h +48 -0
  47. data/vendor/libyeptris/src/include/yeptris/plan.h +100 -0
  48. data/vendor/libyeptris/src/include/yeptris/resolve.h +71 -0
  49. data/vendor/libyeptris/src/include/yeptris/schema.h +121 -0
  50. data/vendor/libyeptris/src/include/yeptris/tape.h +123 -0
  51. data/vendor/libyeptris/src/include/yeptris/types.h +38 -0
  52. data/vendor/libyeptris/src/include/yeptris/values.h +102 -0
  53. data/vendor/libyeptris/src/include/yeptris/version.h.in +29 -0
  54. data/vendor/libyeptris/src/include/yeptris/visit.h +77 -0
  55. data/vendor/libyeptris/src/include/yeptris/yajl_compat.h +135 -0
  56. data/vendor/libyeptris/src/include/yeptris.h +23 -0
  57. data/vendor/libyeptris/src/yeptris/build.c +376 -0
  58. data/vendor/libyeptris/src/yeptris/cbor/cbor.h +25 -0
  59. data/vendor/libyeptris/src/yeptris/cbor/decode.c +981 -0
  60. data/vendor/libyeptris/src/yeptris/cbor/encode.c +835 -0
  61. data/vendor/libyeptris/src/yeptris/cbor/sink.h +58 -0
  62. data/vendor/libyeptris/src/yeptris/common/chartype.c +41 -0
  63. data/vendor/libyeptris/src/yeptris/common/chartype.h +77 -0
  64. data/vendor/libyeptris/src/yeptris/common/cpu.c +81 -0
  65. data/vendor/libyeptris/src/yeptris/common/cpu.h +40 -0
  66. data/vendor/libyeptris/src/yeptris/common/error.c +65 -0
  67. data/vendor/libyeptris/src/yeptris/common/error.h +79 -0
  68. data/vendor/libyeptris/src/yeptris/common/mutex.h +45 -0
  69. data/vendor/libyeptris/src/yeptris/common/nametab.c +275 -0
  70. data/vendor/libyeptris/src/yeptris/common/nametab.h +68 -0
  71. data/vendor/libyeptris/src/yeptris/common/port.h +74 -0
  72. data/vendor/libyeptris/src/yeptris/common/simd_text.c +49 -0
  73. data/vendor/libyeptris/src/yeptris/common/simd_text.h +295 -0
  74. data/vendor/libyeptris/src/yeptris/common/simd_text_avx2.c +534 -0
  75. data/vendor/libyeptris/src/yeptris/common/simd_text_neon.c +662 -0
  76. data/vendor/libyeptris/src/yeptris/common/simd_text_scalar.c +298 -0
  77. data/vendor/libyeptris/src/yeptris/common/string_view.c +34 -0
  78. data/vendor/libyeptris/src/yeptris/common/string_view.h +93 -0
  79. data/vendor/libyeptris/src/yeptris/doc.h +56 -0
  80. data/vendor/libyeptris/src/yeptris/dom/dom.c +1192 -0
  81. data/vendor/libyeptris/src/yeptris/dom/dom.h +312 -0
  82. data/vendor/libyeptris/src/yeptris/dom/hpool.c +107 -0
  83. data/vendor/libyeptris/src/yeptris/dom/mapindex.c +173 -0
  84. data/vendor/libyeptris/src/yeptris/dom/mapindex.h +61 -0
  85. data/vendor/libyeptris/src/yeptris/dom/mutate.c +431 -0
  86. data/vendor/libyeptris/src/yeptris/emit/emit.c +434 -0
  87. data/vendor/libyeptris/src/yeptris/emit/float/api.h +38 -0
  88. data/vendor/libyeptris/src/yeptris/emit/float/dragon.c +405 -0
  89. data/vendor/libyeptris/src/yeptris/emit/float/floatint.h +231 -0
  90. data/vendor/libyeptris/src/yeptris/emit/float/print.c +396 -0
  91. data/vendor/libyeptris/src/yeptris/emit/style.c +81 -0
  92. data/vendor/libyeptris/src/yeptris/emit/style.h +24 -0
  93. data/vendor/libyeptris/src/yeptris/emit/writer.c +816 -0
  94. data/vendor/libyeptris/src/yeptris/emit/writer.h +76 -0
  95. data/vendor/libyeptris/src/yeptris/encoding/bom.c +31 -0
  96. data/vendor/libyeptris/src/yeptris/encoding/encoding.h +63 -0
  97. data/vendor/libyeptris/src/yeptris/encoding/transcode.c +148 -0
  98. data/vendor/libyeptris/src/yeptris/encoding/utf8_validate.c +178 -0
  99. data/vendor/libyeptris/src/yeptris/events/capture.c +150 -0
  100. data/vendor/libyeptris/src/yeptris/events/capture.h +39 -0
  101. data/vendor/libyeptris/src/yeptris/events/iterparse.c +208 -0
  102. data/vendor/libyeptris/src/yeptris/events/pull.c +97 -0
  103. data/vendor/libyeptris/src/yeptris/events/push.c +104 -0
  104. data/vendor/libyeptris/src/yeptris/events/recorder.c +107 -0
  105. data/vendor/libyeptris/src/yeptris/events/values.c +527 -0
  106. data/vendor/libyeptris/src/yeptris/events/values_priv.h +51 -0
  107. data/vendor/libyeptris/src/yeptris/events/yaml_compat.c +86 -0
  108. data/vendor/libyeptris/src/yeptris/events/yaml_compat.h +90 -0
  109. data/vendor/libyeptris/src/yeptris/jsonapi/jsonc_compat.c +687 -0
  110. data/vendor/libyeptris/src/yeptris/jsonapi/yajl_compat.c +728 -0
  111. data/vendor/libyeptris/src/yeptris/marshal.c +782 -0
  112. data/vendor/libyeptris/src/yeptris/memory/allocator.c +20 -0
  113. data/vendor/libyeptris/src/yeptris/memory/allocator.h +43 -0
  114. data/vendor/libyeptris/src/yeptris/memory/arena.c +134 -0
  115. data/vendor/libyeptris/src/yeptris/memory/arena.h +52 -0
  116. data/vendor/libyeptris/src/yeptris/memory/pool.c +122 -0
  117. data/vendor/libyeptris/src/yeptris/memory/pool.h +36 -0
  118. data/vendor/libyeptris/src/yeptris/parse/engine.c +3698 -0
  119. data/vendor/libyeptris/src/yeptris/parse/engine.h +65 -0
  120. data/vendor/libyeptris/src/yeptris/parse/events.h +124 -0
  121. data/vendor/libyeptris/src/yeptris/parse/numbers.c +349 -0
  122. data/vendor/libyeptris/src/yeptris/parse/numbers.h +33 -0
  123. data/vendor/libyeptris/src/yeptris/parse/scalars.c +416 -0
  124. data/vendor/libyeptris/src/yeptris/parse/scalars.h +75 -0
  125. data/vendor/libyeptris/src/yeptris/parse.c +737 -0
  126. data/vendor/libyeptris/src/yeptris/plan.c +824 -0
  127. data/vendor/libyeptris/src/yeptris/resolve/compat11.c +334 -0
  128. data/vendor/libyeptris/src/yeptris/resolve/core12.c +143 -0
  129. data/vendor/libyeptris/src/yeptris/resolve/resolver.h +56 -0
  130. data/vendor/libyeptris/src/yeptris/resolve/tags.c +58 -0
  131. data/vendor/libyeptris/src/yeptris/scan/json.c +792 -0
  132. data/vendor/libyeptris/src/yeptris/scan/json.h +109 -0
  133. data/vendor/libyeptris/src/yeptris/scan/scan.c +463 -0
  134. data/vendor/libyeptris/src/yeptris/scan/scan.h +150 -0
  135. data/vendor/libyeptris/src/yeptris/schema.c +308 -0
  136. data/vendor/libyeptris/src/yeptris/tape.c +1308 -0
  137. data/vendor/libyeptris/src/yeptris/tape_in.h +19 -0
  138. data/vendor/libyeptris/src/yeptris/version.c +7 -0
  139. data/vendor/libyeptris/src/yeptris/visit/dom_visit.c +115 -0
  140. data/vendor/libyeptris/src/yeptris/visit/json_visit.c +293 -0
  141. data/vendor/libyeptris/src/yeptris/visit/yaml_visit.c +127 -0
  142. metadata +199 -0
@@ -0,0 +1,687 @@
1
+ /* jsonc_compat.c — json-c symbols over the yeptris core (TODO.impl/21).
2
+ *
3
+ * Read path: parse via strict JSON mode, query via the DOM API, output
4
+ * via the JSON writer. The root object owns the YeptrisDocument;
5
+ * children borrow it.
6
+ *
7
+ * Building path (v2, over DOM mutation 11/3): new_* objects are
8
+ * PENDING — no document exists until the object is attached or first
9
+ * queried. Attaching materializes the node directly in the parent's
10
+ * document (O(1), no copies); a standalone object materializes its own
11
+ * document on first query. json-c ownership rules hold: add transfers
12
+ * ownership, the caller's pointer stays valid until the root is put.
13
+ */
14
+
15
+ #include <math.h>
16
+ #include <stdio.h>
17
+ #include <stdlib.h>
18
+ #include <string.h>
19
+
20
+ #include "../../include/yeptris/dom.h"
21
+ #include "../../include/yeptris/json.h"
22
+ #include "../../include/yeptris/jsonc_compat.h"
23
+
24
+ #include "../emit/float/api.h"
25
+ #include "../emit/writer.h"
26
+
27
+ struct json_object {
28
+ YeptrisDocument doc; /* set when materialized; owned only when owns_doc */
29
+ YeptrisNode node; /* NULL for the root placeholder */
30
+ int owns_doc;
31
+ int pending; /* constructed, no document yet */
32
+ json_type jtype; /* pending payload kind */
33
+ char* sval; /* pending json_type_string (malloc'd) */
34
+ size_t slen;
35
+ int64_t ival; /* pending json_type_int */
36
+ double dval; /* pending json_type_double */
37
+ int bval; /* pending json_type_boolean */
38
+ char* json_out; /* cached to_json_string result */
39
+ struct json_object* root; /* the owning root (self for roots) */
40
+ /* the root registers every wrapper it hands out; wrappers live
41
+ * until the root is put (json-c lifetime: borrowed refs die with
42
+ * the root) */
43
+ struct json_object** children;
44
+ size_t nchild;
45
+ size_t capchild;
46
+ };
47
+
48
+ /* --- root registry (wrappers die with their root) --- */
49
+
50
+ static json_object* reg_grow(json_object* root) {
51
+ if (root->nchild == root->capchild) {
52
+ size_t cap = root->capchild ? root->capchild * 2 : 8;
53
+ struct json_object** grown = realloc(root->children, cap * sizeof(*grown));
54
+ if (grown == NULL) {
55
+ return NULL;
56
+ }
57
+ root->children = grown;
58
+ root->capchild = cap;
59
+ }
60
+ return root;
61
+ }
62
+
63
+ static void register_child(json_object* root, json_object* child) {
64
+ if (reg_grow(root) == NULL) {
65
+ return; /* registry full = the wrapper leaks at put only */
66
+ }
67
+ root->children[root->nchild++] = child;
68
+ }
69
+
70
+ static json_object* child_of(json_object* from, YeptrisNode node) {
71
+ if (from == NULL || node == NULL) {
72
+ return NULL;
73
+ }
74
+ json_object* root = from->root;
75
+ if (reg_grow(root) == NULL) {
76
+ return NULL;
77
+ }
78
+ json_object* child = calloc(1, sizeof(*child));
79
+ if (child == NULL) {
80
+ return NULL;
81
+ }
82
+ child->doc = root->doc;
83
+ child->node = node;
84
+ child->root = root;
85
+ register_child(root, child);
86
+ return child;
87
+ }
88
+
89
+ /* --- pending payload -> DOM node --- */
90
+
91
+ /* The scalar text a pending double materializes as: shortest
92
+ * round-trip (finite) or the resolver's non-finite word. */
93
+ static int double_text(double d, char* buf) {
94
+ if (isfinite(d)) {
95
+ return yep_d2s_shortest(d, buf);
96
+ }
97
+ return yep_d2s_nonfinite(d, buf);
98
+ }
99
+
100
+ static YeptrisNode pending_node(YeptrisDocument doc, json_object* o) {
101
+ char buf[32];
102
+ switch (o->jtype) {
103
+ case json_type_object:
104
+ return yeptris_node_new_mapping(doc);
105
+ case json_type_array:
106
+ return yeptris_node_new_sequence(doc);
107
+ case json_type_string:
108
+ return yeptris_node_new_scalar(doc, o->sval ? o->sval : "", o->slen,
109
+ YEPTRIS_STYLE_DOUBLE_QUOTED);
110
+ case json_type_int:
111
+ snprintf(buf, sizeof(buf), "%lld", (long long)o->ival);
112
+ return yeptris_node_new_scalar(doc, buf, strlen(buf), YEPTRIS_STYLE_PLAIN);
113
+ case json_type_double:
114
+ return yeptris_node_new_scalar(doc, buf, (size_t)double_text(o->dval, buf),
115
+ YEPTRIS_STYLE_PLAIN);
116
+ case json_type_boolean:
117
+ return yeptris_node_new_scalar(doc, o->bval ? "true" : "false", o->bval ? 4 : 5,
118
+ YEPTRIS_STYLE_PLAIN);
119
+ default:
120
+ return yeptris_node_new_scalar(doc, "null", 4, YEPTRIS_STYLE_PLAIN);
121
+ }
122
+ }
123
+
124
+ /* A pending object becomes its own document's root. */
125
+ static int materialize_root(json_object* o) {
126
+ if (!o->pending) {
127
+ return 0;
128
+ }
129
+ YeptrisDocument doc = yeptris_document_new();
130
+ if (doc == NULL) {
131
+ return -1;
132
+ }
133
+ YeptrisNode node = pending_node(doc, o);
134
+ if (node == NULL || yeptris_document_set_root(doc, node) != YEPTRIS_OK) {
135
+ yeptris_document_free(doc);
136
+ return -1;
137
+ }
138
+ free(o->sval);
139
+ o->sval = NULL;
140
+ o->pending = 0;
141
+ o->doc = doc;
142
+ o->node = node;
143
+ o->owns_doc = 1;
144
+ return 0;
145
+ }
146
+
147
+ /* Every read on a standalone pending object materializes it first. */
148
+ static int ensure_materialized(json_object* o) {
149
+ if (o == NULL) {
150
+ return -1;
151
+ }
152
+ return o->pending ? materialize_root(o) : 0;
153
+ }
154
+
155
+ /* Duplicates an attached subtree into `doc` via the public builders —
156
+ * the rare path where a standalone object was materialized by a query
157
+ * before being added to a parent. Styles ride along, so a quoted "12"
158
+ * stays a string and a bare 12 stays an int. */
159
+ static YeptrisNode dup_into(YeptrisDocument doc, YeptrisNode src) {
160
+ switch (yeptris_node_kind(src)) {
161
+ case YEPTRIS_NODE_SEQUENCE: {
162
+ YeptrisNode s = yeptris_node_new_sequence(doc);
163
+ if (s == NULL) {
164
+ return NULL;
165
+ }
166
+ for (size_t i = 0; i < yeptris_node_seq_count(src); i++) {
167
+ YeptrisNode e = dup_into(doc, yeptris_node_seq_at(src, i));
168
+ if (e == NULL || yeptris_node_seq_add(s, e) != YEPTRIS_OK) {
169
+ return NULL;
170
+ }
171
+ }
172
+ return s;
173
+ }
174
+ case YEPTRIS_NODE_MAPPING: {
175
+ YeptrisNode m = yeptris_node_new_mapping(doc);
176
+ if (m == NULL) {
177
+ return NULL;
178
+ }
179
+ for (size_t i = 0; i < yeptris_node_map_count(src); i++) {
180
+ YeptrisNode k, v;
181
+ size_t klen = 0;
182
+ if (yeptris_node_map_at(src, i, &k, &v) != 0) {
183
+ return NULL;
184
+ }
185
+ const char* kt = yeptris_node_value(k, &klen);
186
+ YeptrisNode dv = dup_into(doc, v);
187
+ if (dv == NULL || yeptris_node_map_set(m, kt ? kt : "", klen, dv) != YEPTRIS_OK) {
188
+ return NULL;
189
+ }
190
+ }
191
+ return m;
192
+ }
193
+ default: {
194
+ size_t len = 0;
195
+ const char* v = yeptris_node_value(src, &len);
196
+ return yeptris_node_new_scalar(doc, v ? v : "", len, yeptris_node_style(src));
197
+ }
198
+ }
199
+ }
200
+
201
+ /* Attaches val under parent: materializes pending payloads in the
202
+ * parent's document (O(1)); standalone materialized vals are
203
+ * duplicated in and their private document released. Retargets the
204
+ * wrapper so the caller's pointer stays valid (json-c contract). */
205
+ static int attach(json_object* parent, json_object* val, const char* key) {
206
+ if (ensure_materialized(parent) != 0) {
207
+ return -1;
208
+ }
209
+ json_object* root = parent->root;
210
+ YeptrisNode vnode;
211
+ if (val->pending) {
212
+ vnode = pending_node(root->doc, val);
213
+ if (vnode == NULL) {
214
+ return -1;
215
+ }
216
+ free(val->sval);
217
+ val->sval = NULL;
218
+ val->pending = 0;
219
+ } else if (val->owns_doc) {
220
+ vnode = dup_into(root->doc, val->node);
221
+ if (vnode == NULL) {
222
+ return -1;
223
+ }
224
+ yeptris_document_free(val->doc);
225
+ /* the standalone root died with its document: its old registry
226
+ * and cached output die too (borrowed refs die with the root —
227
+ * the caller's val pointer is the one that stays valid) */
228
+ for (size_t i = 0; i < val->nchild; i++) {
229
+ free(val->children[i]->json_out);
230
+ free(val->children[i]);
231
+ }
232
+ free(val->children);
233
+ val->children = NULL;
234
+ val->nchild = 0;
235
+ val->capchild = 0;
236
+ free(val->json_out);
237
+ val->json_out = NULL;
238
+ } else {
239
+ return -1; /* already attached to a parent: two parents is a bug */
240
+ }
241
+ int rc;
242
+ if (key != NULL) {
243
+ /* added vs replaced: json-c's return contract */
244
+ rc = yeptris_node_map_get(parent->node, key, strlen(key)) != NULL;
245
+ if (yeptris_node_map_set(parent->node, key, strlen(key), vnode) != YEPTRIS_OK) {
246
+ return -1;
247
+ }
248
+ } else {
249
+ rc = yeptris_node_seq_add(parent->node, vnode) == YEPTRIS_OK ? 0 : -1;
250
+ if (rc != 0) {
251
+ return -1;
252
+ }
253
+ }
254
+ val->doc = root->doc;
255
+ val->node = vnode;
256
+ val->root = root;
257
+ val->owns_doc = 0;
258
+ register_child(root, val);
259
+ return key != NULL ? rc : 0;
260
+ }
261
+
262
+ /* --- parse / lifetime --- */
263
+
264
+ json_object* json_tokener_parse(const char* str) {
265
+ if (str == NULL) {
266
+ return NULL;
267
+ }
268
+ return json_tokener_parse_ex(str, (int)strlen(str));
269
+ }
270
+
271
+ json_object* json_tokener_parse_ex(const char* buf, int len) {
272
+ if (buf == NULL || len < 0) {
273
+ return NULL;
274
+ }
275
+ /* json-c tolerates trailing NUL: honor the explicit length only */
276
+ YeptrisStatus st = YEPTRIS_OK;
277
+ YeptrisDocument doc = yeptris_parse_json(buf, (size_t)len, &st);
278
+ if (doc == NULL) {
279
+ return NULL;
280
+ }
281
+ if (yeptris_document_count(doc) == 0) {
282
+ yeptris_document_free(doc);
283
+ return NULL;
284
+ }
285
+ json_object* obj = calloc(1, sizeof(*obj));
286
+ if (obj == NULL) {
287
+ yeptris_document_free(doc);
288
+ return NULL;
289
+ }
290
+ obj->doc = doc;
291
+ obj->node = yeptris_document_root(doc, 0);
292
+ obj->owns_doc = 1;
293
+ obj->root = obj;
294
+ return obj;
295
+ }
296
+
297
+ void json_tokener_free(json_object* obj) {
298
+ json_object_put(obj);
299
+ }
300
+
301
+ int json_object_put(json_object* obj) {
302
+ if (obj == NULL) {
303
+ return 0;
304
+ }
305
+ if (obj->pending) {
306
+ free(obj->sval);
307
+ free(obj->json_out);
308
+ free(obj);
309
+ return 1;
310
+ }
311
+ if (obj->owns_doc) {
312
+ free(obj->json_out);
313
+ for (size_t i = 0; i < obj->nchild; i++) {
314
+ free(obj->children[i]->json_out);
315
+ free(obj->children[i]);
316
+ }
317
+ free(obj->children);
318
+ yeptris_document_free(obj->doc);
319
+ free(obj);
320
+ }
321
+ /* children are owned by their root */
322
+ return 1;
323
+ }
324
+
325
+ json_object* json_object_get(json_object* obj) {
326
+ return obj;
327
+ }
328
+
329
+ /* --- building (json_object_new_*) --- */
330
+
331
+ static json_object* new_pending(json_type t) {
332
+ json_object* o = calloc(1, sizeof(*o));
333
+ if (o != NULL) {
334
+ o->pending = 1;
335
+ o->jtype = t;
336
+ o->root = o;
337
+ }
338
+ return o;
339
+ }
340
+
341
+ json_object* json_object_new_object(void) {
342
+ return new_pending(json_type_object);
343
+ }
344
+
345
+ json_object* json_object_new_array(void) {
346
+ return new_pending(json_type_array);
347
+ }
348
+
349
+ json_object* json_object_new_string(const char* s) {
350
+ return json_object_new_string_len(s, s ? (int)strlen(s) : 0);
351
+ }
352
+
353
+ json_object* json_object_new_string_len(const char* s, int len) {
354
+ if (s == NULL || len < 0) {
355
+ return NULL;
356
+ }
357
+ json_object* o = new_pending(json_type_string);
358
+ if (o == NULL) {
359
+ return NULL;
360
+ }
361
+ o->sval = malloc((size_t)len + 1);
362
+ if (o->sval == NULL) {
363
+ free(o);
364
+ return NULL;
365
+ }
366
+ memcpy(o->sval, s, (size_t)len);
367
+ o->sval[len] = '\0';
368
+ o->slen = (size_t)len;
369
+ return o;
370
+ }
371
+
372
+ json_object* json_object_new_int(int32_t i) {
373
+ return json_object_new_int64(i);
374
+ }
375
+
376
+ json_object* json_object_new_int64(int64_t i) {
377
+ json_object* o = new_pending(json_type_int);
378
+ if (o != NULL) {
379
+ o->ival = i;
380
+ }
381
+ return o;
382
+ }
383
+
384
+ json_object* json_object_new_double(double d) {
385
+ json_object* o = new_pending(json_type_double);
386
+ if (o != NULL) {
387
+ o->dval = d;
388
+ }
389
+ return o;
390
+ }
391
+
392
+ json_object* json_object_new_boolean(int b) {
393
+ json_object* o = new_pending(json_type_boolean);
394
+ if (o != NULL) {
395
+ o->bval = b != 0;
396
+ }
397
+ return o;
398
+ }
399
+
400
+ int json_object_object_add(json_object* obj, const char* key, json_object* val) {
401
+ if (obj == NULL || key == NULL) {
402
+ return -1;
403
+ }
404
+ if (val == NULL) {
405
+ /* legacy json-c: NULL val deletes the key */
406
+ return json_object_object_del(obj, key) == 0 ? 0 : -1;
407
+ }
408
+ if (ensure_materialized(obj) != 0 || yeptris_node_kind(obj->node) != YEPTRIS_NODE_MAPPING) {
409
+ return -1;
410
+ }
411
+ return attach(obj, val, key);
412
+ }
413
+
414
+ int json_object_object_del(json_object* obj, const char* key) {
415
+ if (obj == NULL || key == NULL || ensure_materialized(obj) != 0 ||
416
+ yeptris_node_kind(obj->node) != YEPTRIS_NODE_MAPPING) {
417
+ return -1;
418
+ }
419
+ return yeptris_node_map_del(obj->node, key, strlen(key)) == YEPTRIS_OK ? 0 : -1;
420
+ }
421
+
422
+ int json_object_array_add(json_object* obj, json_object* val) {
423
+ if (obj == NULL || val == NULL || ensure_materialized(obj) != 0 ||
424
+ yeptris_node_kind(obj->node) != YEPTRIS_NODE_SEQUENCE) {
425
+ return -1;
426
+ }
427
+ return attach(obj, val, NULL);
428
+ }
429
+
430
+ /* json-c: index < len replaces in place; index == len appends;
431
+ * beyond that errors. */
432
+ int json_object_array_put_idx(json_object* obj, size_t idx, json_object* val) {
433
+ if (obj == NULL || val == NULL || ensure_materialized(obj) != 0 ||
434
+ yeptris_node_kind(obj->node) != YEPTRIS_NODE_SEQUENCE) {
435
+ return -1;
436
+ }
437
+ size_t len = yeptris_node_seq_count(obj->node);
438
+ if (idx > len) {
439
+ return -1;
440
+ }
441
+ if (idx == len) {
442
+ return attach(obj, val, NULL);
443
+ }
444
+ /* replace in place: duplicate-then-splice for pending/standalone
445
+ * values, mirroring attach's retarget contract */
446
+ if (ensure_materialized(val) != 0) {
447
+ return -1;
448
+ }
449
+ json_object* root = obj->root;
450
+ YeptrisNode vnode;
451
+ if (val->pending) {
452
+ vnode = pending_node(root->doc, val);
453
+ if (vnode == NULL) {
454
+ return -1;
455
+ }
456
+ free(val->sval);
457
+ val->sval = NULL;
458
+ val->pending = 0;
459
+ } else if (val->owns_doc) {
460
+ vnode = dup_into(root->doc, val->node);
461
+ if (vnode == NULL) {
462
+ return -1;
463
+ }
464
+ yeptris_document_free(val->doc);
465
+ for (size_t i = 0; i < val->nchild; i++) {
466
+ free(val->children[i]->json_out);
467
+ free(val->children[i]);
468
+ }
469
+ free(val->children);
470
+ val->children = NULL;
471
+ val->nchild = 0;
472
+ val->capchild = 0;
473
+ free(val->json_out);
474
+ val->json_out = NULL;
475
+ } else {
476
+ return -1;
477
+ }
478
+ if (yeptris_node_seq_set(obj->node, idx, vnode) != YEPTRIS_OK) {
479
+ return -1;
480
+ }
481
+ val->doc = root->doc;
482
+ val->node = vnode;
483
+ val->root = root;
484
+ val->owns_doc = 0;
485
+ register_child(root, val);
486
+ return 0;
487
+ }
488
+
489
+ int json_object_array_del_idx(json_object* obj, size_t idx, size_t count) {
490
+ if (obj == NULL || ensure_materialized(obj) != 0 ||
491
+ yeptris_node_kind(obj->node) != YEPTRIS_NODE_SEQUENCE) {
492
+ return -1;
493
+ }
494
+ if (idx + count > yeptris_node_seq_count(obj->node)) {
495
+ return -1;
496
+ }
497
+ for (size_t i = 0; i < count; i++) {
498
+ if (yeptris_node_seq_del(obj->node, idx) != YEPTRIS_OK) {
499
+ return -1;
500
+ }
501
+ }
502
+ return 0;
503
+ }
504
+
505
+ /* --- queries --- */
506
+
507
+ static int kind_of(const json_object* obj) {
508
+ if (obj == NULL || obj->node == NULL) {
509
+ return -1;
510
+ }
511
+ return (int)yeptris_node_kind(obj->node);
512
+ }
513
+
514
+ json_type json_object_get_type(const json_object* obj) {
515
+ if (obj == NULL || ensure_materialized((json_object*)obj) != 0) {
516
+ return json_type_null;
517
+ }
518
+ if (obj->node == NULL) {
519
+ return json_type_null;
520
+ }
521
+ switch (kind_of(obj)) {
522
+ case YEPTRIS_NODE_MAPPING:
523
+ return json_type_object;
524
+ case YEPTRIS_NODE_SEQUENCE:
525
+ return json_type_array;
526
+ case YEPTRIS_NODE_ALIAS:
527
+ return json_type_null;
528
+ default:
529
+ break;
530
+ }
531
+ /* Typed accessors respect implicitness: a QUOTED "12" in strict
532
+ * JSON is a string (the accessors reject it), a bare 12 is int —
533
+ * the discrimination comes free from the resolver */
534
+ int64_t i;
535
+ double d;
536
+ int b;
537
+ if (yeptris_node_int(obj->node, &i) == YEPTRIS_OK) {
538
+ return json_type_int;
539
+ }
540
+ if (yeptris_node_float(obj->node, &d) == YEPTRIS_OK) {
541
+ return json_type_double;
542
+ }
543
+ if (yeptris_node_bool(obj->node, &b) == YEPTRIS_OK) {
544
+ return json_type_boolean;
545
+ }
546
+ size_t len = 0;
547
+ const char* v = yeptris_node_value(obj->node, &len);
548
+ if (len == 4 && v != NULL && memcmp(v, "null", 4) == 0) {
549
+ return json_type_null;
550
+ }
551
+ return json_type_string;
552
+ }
553
+
554
+ int json_object_is_type(const json_object* obj, json_type type) {
555
+ return json_object_get_type(obj) == type;
556
+ }
557
+
558
+ const char* json_object_get_string(json_object* obj) {
559
+ if (obj == NULL || ensure_materialized(obj) != 0) {
560
+ return NULL;
561
+ }
562
+ size_t len = 0;
563
+ const char* v = yeptris_node_value(obj->node, &len);
564
+ if (v == NULL) {
565
+ return NULL;
566
+ }
567
+ char* out = malloc(len + 1);
568
+ if (out == NULL) {
569
+ return NULL;
570
+ }
571
+ memcpy(out, v, len);
572
+ out[len] = '\0';
573
+ /* attach to the object's slot: freed on the NEXT call or at put —
574
+ * json-c returns owned storage; we approximate with a per-object
575
+ * cache (the last getString result) */
576
+ free(obj->json_out);
577
+ obj->json_out = out;
578
+ return out;
579
+ }
580
+
581
+ int32_t json_object_get_int(const json_object* obj) {
582
+ return (int32_t)json_object_get_int64(obj);
583
+ }
584
+
585
+ int64_t json_object_get_int64(const json_object* obj) {
586
+ int64_t v = 0;
587
+ if (obj != NULL && ensure_materialized((json_object*)obj) == 0 && obj->node != NULL) {
588
+ if (yeptris_node_int(obj->node, &v) != YEPTRIS_OK) {
589
+ double d = 0; /* json-c truncates doubles in getInt */
590
+ if (yeptris_node_float(obj->node, &d) == YEPTRIS_OK) {
591
+ v = (int64_t)d;
592
+ }
593
+ }
594
+ }
595
+ return v;
596
+ }
597
+
598
+ double json_object_get_double(const json_object* obj) {
599
+ double v = 0.0;
600
+ if (obj != NULL && ensure_materialized((json_object*)obj) == 0 && obj->node != NULL) {
601
+ yeptris_node_float(obj->node, &v);
602
+ }
603
+ return v;
604
+ }
605
+
606
+ int json_object_get_boolean(const json_object* obj) {
607
+ int v = 0;
608
+ if (obj != NULL && ensure_materialized((json_object*)obj) == 0 && obj->node != NULL) {
609
+ yeptris_node_bool(obj->node, &v);
610
+ }
611
+ return v;
612
+ }
613
+
614
+ int json_object_object_get_ex(const json_object* obj, const char* key, json_object** value) {
615
+ if (obj == NULL || key == NULL || kind_of(obj) != YEPTRIS_NODE_MAPPING) {
616
+ if (value != NULL) {
617
+ *value = NULL;
618
+ }
619
+ return 0;
620
+ }
621
+ YeptrisNode n = yeptris_node_map_get(obj->node, key, strlen(key));
622
+ if (n == NULL) {
623
+ if (value != NULL) {
624
+ *value = NULL;
625
+ }
626
+ return 0;
627
+ }
628
+ if (value != NULL) {
629
+ json_object* child = child_of((json_object*)obj, n);
630
+ *value = child;
631
+ return child != NULL;
632
+ }
633
+ return 1;
634
+ }
635
+
636
+ size_t json_object_object_length(const json_object* obj) {
637
+ if (obj == NULL || kind_of(obj) != YEPTRIS_NODE_MAPPING) {
638
+ return 0;
639
+ }
640
+ return yeptris_node_map_count(obj->node);
641
+ }
642
+
643
+ size_t json_object_array_length(const json_object* obj) {
644
+ if (obj == NULL || kind_of(obj) != YEPTRIS_NODE_SEQUENCE) {
645
+ return 0;
646
+ }
647
+ return yeptris_node_seq_count(obj->node);
648
+ }
649
+
650
+ json_object* json_object_array_get_idx(const json_object* obj, size_t idx) {
651
+ if (obj == NULL || kind_of(obj) != YEPTRIS_NODE_SEQUENCE) {
652
+ return NULL;
653
+ }
654
+ if (idx >= yeptris_node_seq_count(obj->node)) {
655
+ return NULL;
656
+ }
657
+ return child_of((json_object*)obj, yeptris_node_seq_at(obj->node, idx));
658
+ }
659
+
660
+ const char* json_object_to_json_string_ext(json_object* obj, int flags) {
661
+ if (obj == NULL) {
662
+ return NULL;
663
+ }
664
+ if (obj->pending && materialize_root(obj) != 0) {
665
+ return NULL;
666
+ }
667
+ if (obj->json_out != NULL && obj->owns_doc) {
668
+ free(obj->json_out);
669
+ }
670
+ /* children serialize their SUBTREE: emit from the node's document
671
+ * requires a whole-document writer; v1 supports roots only */
672
+ if (obj->node == NULL || !obj->owns_doc) {
673
+ return NULL;
674
+ }
675
+ size_t len = 0;
676
+ int pretty = (flags & JSON_C_TO_STRING_PRETTY) != 0 && !(flags & JSON_C_TO_STRING_PLAIN);
677
+ obj->json_out = pretty ? yep_serialize_json_pretty((const yeptris_document*)obj->doc, &len)
678
+ : yep_serialize_json_compact((const yeptris_document*)obj->doc, &len);
679
+ if (obj->json_out != NULL && len > 0 && obj->json_out[len - 1] == '\n') {
680
+ obj->json_out[len - 1] = '\0'; /* json-c output carries no newline */
681
+ }
682
+ return obj->json_out;
683
+ }
684
+
685
+ const char* json_object_to_json_string(json_object* obj) {
686
+ return json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN);
687
+ }