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,728 @@
1
+ /* yajl_compat.c — the yajl generator over the yeptris core (TODO.impl/21).
2
+ *
3
+ * A state machine over the DOM builder: yajl's call-order rules
4
+ * (maps alternate string-key/value; a closed root accepts no more)
5
+ * enforced here, values build a document, get_buf serializes JSON.
6
+ */
7
+
8
+ #include <math.h>
9
+ #include <stdarg.h>
10
+ #include <stdio.h>
11
+ #include <stdlib.h>
12
+ #include <string.h>
13
+
14
+ #include "../../include/yeptris/dom.h"
15
+ #include "../../include/yeptris/error.h"
16
+ #include "../../include/yeptris/json.h"
17
+ #include "../../include/yeptris/yajl_compat.h"
18
+
19
+ #include "../doc.h"
20
+ #include "../emit/writer.h"
21
+
22
+ #define YAJL_MAX_STACK 512
23
+
24
+ typedef struct yajl_gen_t {
25
+ yeptris_document* doc;
26
+ YeptrisNode stack[YAJL_MAX_STACK];
27
+ int depth;
28
+ int key_pending[YAJL_MAX_STACK]; /* per open map: string key next */
29
+ int root_closed;
30
+ YeptrisNode pending_key; /* map: key placed, awaiting its value */
31
+ unsigned char* buf; /* get_buf cache: freed on next gen call */
32
+ size_t buf_len;
33
+ int beautify;
34
+ char numbuf[48];
35
+ } yajl_gen_t;
36
+
37
+ yajl_gen yajl_gen_alloc(const yajl_alloc_funcs* afs) {
38
+ (void)afs; /* the system allocator (yajl's NULL default) */
39
+ yajl_gen g = calloc(1, sizeof(*g));
40
+ if (g == NULL) {
41
+ return NULL;
42
+ }
43
+ g->doc = yeptris_document_new();
44
+ if (g->doc == NULL) {
45
+ free(g);
46
+ return NULL;
47
+ }
48
+ return g;
49
+ }
50
+
51
+ void yajl_gen_free(yajl_gen g) {
52
+ if (g == NULL) {
53
+ return;
54
+ }
55
+ free(g->buf);
56
+ yeptris_document_free(g->doc);
57
+ free(g);
58
+ }
59
+
60
+ void yajl_gen_reset(yajl_gen g, const char* sep) {
61
+ if (g == NULL) {
62
+ return;
63
+ }
64
+ (void)sep; /* yajl emits the separator between streams; the buf
65
+ * clears on the next generation anyway */
66
+ free(g->buf);
67
+ g->buf = NULL;
68
+ g->buf_len = 0;
69
+ yeptris_document_free(g->doc);
70
+ g->doc = yeptris_document_new();
71
+ g->depth = 0;
72
+ g->root_closed = 0;
73
+ g->pending_key = NULL;
74
+ memset(g->key_pending, 0, sizeof(g->key_pending));
75
+ }
76
+
77
+ int yajl_gen_config(yajl_gen g, yajl_gen_option opt, ...) {
78
+ if (g == NULL) {
79
+ return 0;
80
+ }
81
+ va_list ap;
82
+ va_start(ap, opt);
83
+ int rc = 0;
84
+ switch (opt) {
85
+ case yajl_gen_beautify:
86
+ g->beautify = va_arg(ap, int) != 0;
87
+ rc = 1;
88
+ break;
89
+ case yajl_gen_indent_string:
90
+ case yajl_gen_validate_utf8:
91
+ rc = 1; /* accepted: fixed 2-space indent; UTF-8 always on */
92
+ break;
93
+ }
94
+ va_end(ap);
95
+ return rc;
96
+ }
97
+
98
+ /* Places a completed value under the innermost open container (or
99
+ * closes the root). yajl rule: inside a map, the value slot must be
100
+ * preceded by its string key (key_pending). */
101
+ static yajl_gen_status place(yajl_gen g, YeptrisNode value) {
102
+ if (g->root_closed) {
103
+ return yajl_gen_generation_complete;
104
+ }
105
+ if (g->depth > 0 && yeptris_node_kind(g->stack[g->depth - 1]) == YEPTRIS_NODE_MAPPING &&
106
+ g->key_pending[g->depth - 1] && yeptris_node_style(value) != YEPTRIS_STYLE_DOUBLE_QUOTED) {
107
+ return yajl_gen_keys_must_be_strings; /* yajl's map-key rule */
108
+ }
109
+ if (g->depth == 0) {
110
+ if (g->root_closed) {
111
+ return yajl_gen_generation_complete;
112
+ }
113
+ if (yeptris_document_set_root(g->doc, value) != YEPTRIS_OK) {
114
+ return yajl_gen_in_error_state;
115
+ }
116
+ /* a root SCALAR completes generation; an open container
117
+ * continues (it closes later at depth 0) */
118
+ g->root_closed = 1;
119
+ return yajl_gen_status_ok;
120
+ }
121
+ YeptrisNode top = g->stack[g->depth - 1];
122
+ if (yeptris_node_kind(top) == YEPTRIS_NODE_MAPPING) {
123
+ if (g->key_pending[g->depth - 1]) {
124
+ /* this placement IS the key: remember it for the value
125
+ * call (keys are strings per yajl's rule) */
126
+ g->pending_key = value;
127
+ g->key_pending[g->depth - 1] = 0;
128
+ } else {
129
+ if (g->pending_key == NULL) {
130
+ return yajl_gen_in_error_state;
131
+ }
132
+ if (yeptris_node_map_add_node(top, g->pending_key, value) != YEPTRIS_OK) {
133
+ return yajl_gen_in_error_state;
134
+ }
135
+ g->pending_key = NULL;
136
+ g->key_pending[g->depth - 1] = 1;
137
+ }
138
+ return yajl_gen_status_ok;
139
+ }
140
+ if (yeptris_node_seq_add(top, value) != YEPTRIS_OK) {
141
+ return yajl_gen_in_error_state;
142
+ }
143
+ return yajl_gen_status_ok;
144
+ }
145
+
146
+ yajl_gen_status yajl_gen_map_open(yajl_gen g) {
147
+ if (g == NULL) {
148
+ return yajl_gen_in_error_state;
149
+ }
150
+ if (g->root_closed) {
151
+ return yajl_gen_generation_complete;
152
+ }
153
+ if (g->depth >= YAJL_MAX_STACK) {
154
+ return yajl_max_depth_exceeded;
155
+ }
156
+ YeptrisNode m = yeptris_node_new_mapping(g->doc);
157
+ if (m == NULL) {
158
+ return yajl_gen_in_error_state;
159
+ }
160
+ yajl_gen_status st = place(g, m);
161
+ if (st != yajl_gen_status_ok) {
162
+ return st;
163
+ }
164
+ g->root_closed = 0; /* an open root container keeps generating */
165
+ g->stack[g->depth] = m;
166
+ g->key_pending[g->depth] = 1;
167
+ g->depth++;
168
+ return yajl_gen_status_ok;
169
+ }
170
+
171
+ yajl_gen_status yajl_gen_map_close(yajl_gen g) {
172
+ if (g == NULL || g->depth == 0 ||
173
+ yeptris_node_kind(g->stack[g->depth - 1]) != YEPTRIS_NODE_MAPPING) {
174
+ return yajl_gen_in_error_state;
175
+ }
176
+ if (!g->key_pending[g->depth - 1] && g->pending_key != NULL) {
177
+ return yajl_gen_keys_must_be_strings; /* an incomplete pair */
178
+ }
179
+ g->depth--;
180
+ if (g->depth == 0) {
181
+ g->root_closed = 1; /* the root container finished */
182
+ }
183
+ return yajl_gen_status_ok;
184
+ }
185
+
186
+ yajl_gen_status yajl_gen_array_open(yajl_gen g) {
187
+ if (g == NULL) {
188
+ return yajl_gen_in_error_state;
189
+ }
190
+ if (g->root_closed) {
191
+ return yajl_gen_generation_complete;
192
+ }
193
+ if (g->depth >= YAJL_MAX_STACK) {
194
+ return yajl_max_depth_exceeded;
195
+ }
196
+ YeptrisNode sq = yeptris_node_new_sequence(g->doc);
197
+ if (sq == NULL) {
198
+ return yajl_gen_in_error_state;
199
+ }
200
+ yajl_gen_status st = place(g, sq);
201
+ if (st != yajl_gen_status_ok) {
202
+ return st;
203
+ }
204
+ g->root_closed = 0;
205
+ g->stack[g->depth] = sq;
206
+ g->key_pending[g->depth] = 0;
207
+ g->depth++;
208
+ return yajl_gen_status_ok;
209
+ }
210
+
211
+ yajl_gen_status yajl_gen_array_close(yajl_gen g) {
212
+ if (g == NULL || g->depth == 0 ||
213
+ yeptris_node_kind(g->stack[g->depth - 1]) != YEPTRIS_NODE_SEQUENCE) {
214
+ return yajl_gen_in_error_state;
215
+ }
216
+ g->depth--;
217
+ if (g->depth == 0) {
218
+ g->root_closed = 1;
219
+ }
220
+ return yajl_gen_status_ok;
221
+ }
222
+
223
+ yajl_gen_status yajl_gen_string(yajl_gen g, const unsigned char* str, size_t len) {
224
+ if (g == NULL) {
225
+ return yajl_gen_in_error_state;
226
+ }
227
+ if (g->root_closed) {
228
+ return yajl_gen_generation_complete;
229
+ }
230
+ if (g->depth > 0 && yeptris_node_kind(g->stack[g->depth - 1]) == YEPTRIS_NODE_MAPPING &&
231
+ !g->key_pending[g->depth - 1]) {
232
+ /* value slot: a JSON string */
233
+ YeptrisNode n =
234
+ yeptris_node_new_scalar(g->doc, (const char*)str, len, YEPTRIS_STYLE_DOUBLE_QUOTED);
235
+ if (n == NULL) {
236
+ return yajl_gen_in_error_state;
237
+ }
238
+ return place(g, n);
239
+ }
240
+ /* key slot (or root/seq): keys build as plain scalar nodes whose
241
+ * JSON serialization quotes them; yajl requires map keys to be
242
+ * strings, and gen_string is the only legal key call */
243
+ YeptrisNode n =
244
+ yeptris_node_new_scalar(g->doc, (const char*)str, len, YEPTRIS_STYLE_DOUBLE_QUOTED);
245
+ if (n == NULL) {
246
+ return yajl_gen_in_error_state;
247
+ }
248
+ return place(g, n);
249
+ }
250
+
251
+ yajl_gen_status yajl_gen_integer(yajl_gen g, long long n) {
252
+ if (g == NULL) {
253
+ return yajl_gen_in_error_state;
254
+ }
255
+ snprintf(g->numbuf, sizeof(g->numbuf), "%lld", n);
256
+ YeptrisNode v =
257
+ yeptris_node_new_scalar(g->doc, g->numbuf, strlen(g->numbuf), YEPTRIS_STYLE_PLAIN);
258
+ if (v == NULL) {
259
+ return yajl_gen_in_error_state;
260
+ }
261
+ return place(g, v);
262
+ }
263
+
264
+ yajl_gen_status yajl_gen_double(yajl_gen g, double d) {
265
+ if (g == NULL) {
266
+ return yajl_gen_in_error_state;
267
+ }
268
+ snprintf(g->numbuf, sizeof(g->numbuf), "%.17g", d);
269
+ YeptrisNode v =
270
+ yeptris_node_new_scalar(g->doc, g->numbuf, strlen(g->numbuf), YEPTRIS_STYLE_PLAIN);
271
+ if (v == NULL) {
272
+ return yajl_gen_in_error_state;
273
+ }
274
+ return place(g, v);
275
+ }
276
+
277
+ yajl_gen_status yajl_gen_number(yajl_gen g, const char* s, size_t len) {
278
+ if (g == NULL || s == NULL) {
279
+ return yajl_gen_in_error_state;
280
+ }
281
+ YeptrisNode v = yeptris_node_new_scalar(g->doc, s, len, YEPTRIS_STYLE_PLAIN);
282
+ if (v == NULL) {
283
+ return yajl_gen_in_error_state;
284
+ }
285
+ return place(g, v);
286
+ }
287
+
288
+ yajl_gen_status yajl_gen_null(yajl_gen g) {
289
+ if (g == NULL) {
290
+ return yajl_gen_in_error_state;
291
+ }
292
+ YeptrisNode v = yeptris_node_new_scalar(g->doc, "null", 4, YEPTRIS_STYLE_PLAIN);
293
+ if (v == NULL) {
294
+ return yajl_gen_in_error_state;
295
+ }
296
+ return place(g, v);
297
+ }
298
+
299
+ yajl_gen_status yajl_gen_bool(yajl_gen g, int b) {
300
+ if (g == NULL) {
301
+ return yajl_gen_in_error_state;
302
+ }
303
+ YeptrisNode v =
304
+ yeptris_node_new_scalar(g->doc, b ? "true" : "false", b ? 4 : 5, YEPTRIS_STYLE_PLAIN);
305
+ if (v == NULL) {
306
+ return yajl_gen_in_error_state;
307
+ }
308
+ return place(g, v);
309
+ }
310
+
311
+ const unsigned char* yajl_gen_get_buf(yajl_gen g, size_t* len) {
312
+ if (g == NULL || !g->root_closed) {
313
+ if (len != NULL) {
314
+ *len = 0;
315
+ }
316
+ return NULL;
317
+ }
318
+ if (g->buf == NULL) {
319
+ size_t n = 0;
320
+ char* out = g->beautify ? yep_serialize_json_pretty((const yeptris_document*)g->doc, &n)
321
+ : yep_serialize_json_compact((const yeptris_document*)g->doc, &n);
322
+ if (out == NULL) {
323
+ if (len != NULL) {
324
+ *len = 0;
325
+ }
326
+ return NULL;
327
+ }
328
+ if (n > 0 && out[n - 1] == '\n') {
329
+ out[n - 1] = '\0'; /* yajl output carries no newline */
330
+ n--;
331
+ }
332
+ g->buf = (unsigned char*)out;
333
+ g->buf_len = n;
334
+ }
335
+ if (len != NULL) {
336
+ *len = g->buf_len;
337
+ }
338
+ return g->buf;
339
+ }
340
+
341
+ void yajl_gen_clear(yajl_gen g) {
342
+ if (g == NULL) {
343
+ return;
344
+ }
345
+ yajl_gen_reset(g, NULL);
346
+ }
347
+
348
+ /* ---- SAX parser (TODO.impl/21 v4) --------------------------------------
349
+ *
350
+ * yajl_parse feeds accumulate; yajl_complete_parse runs the parse
351
+ * (strict RFC 8259 by default, the YAML front end with
352
+ * yajl_allow_comments) and walks the DOM to the callbacks. Events
353
+ * arrive at completion — batched in time, identical in order and
354
+ * content to yajl's incremental delivery. */
355
+
356
+ typedef struct yajl_handle_t {
357
+ yajl_callbacks cbs;
358
+ void* ctx;
359
+ char* buf;
360
+ size_t len, cap;
361
+ int allow_comments;
362
+ int state; /* 0 feeding, 1 complete-ok, 2 error, 3 canceled */
363
+ int num_overflow; /* a number unrepresentable as double (yajl errors) */
364
+ char err[192];
365
+ size_t err_off; /* byte offset of the violation */
366
+ int have_err_off;
367
+ } yajl_handle_t;
368
+
369
+ const char* yajl_status_to_string(yajl_status code) {
370
+ switch (code) {
371
+ case yajl_status_ok:
372
+ return "ok, no error";
373
+ case yajl_status_client_canceled:
374
+ return "client canceled parse";
375
+ case yajl_status_error:
376
+ return "unknown error?";
377
+ }
378
+ return "unknown error?";
379
+ }
380
+
381
+ yajl_handle yajl_alloc(const yajl_callbacks* callbacks, yajl_alloc_funcs* afs, void* ctx) {
382
+ (void)afs; /* the system allocator (yajl's NULL default) */
383
+ yajl_handle_t* h = calloc(1, sizeof(*h));
384
+ if (h == NULL) {
385
+ return NULL;
386
+ }
387
+ if (callbacks != NULL) {
388
+ h->cbs = *callbacks;
389
+ }
390
+ h->ctx = ctx;
391
+ return h;
392
+ }
393
+
394
+ void yajl_free(yajl_handle handle) {
395
+ if (handle != NULL) {
396
+ free(handle->buf);
397
+ free(handle);
398
+ }
399
+ }
400
+
401
+ int yajl_config(yajl_handle h, yajl_option opt, ...) {
402
+ if (h == NULL) {
403
+ return 0;
404
+ }
405
+ va_list ap;
406
+ va_start(ap, opt);
407
+ int on = va_arg(ap, int);
408
+ va_end(ap);
409
+ switch (opt) {
410
+ case yajl_allow_comments:
411
+ h->allow_comments = on != 0;
412
+ return 1;
413
+ case yajl_dont_validate_strings:
414
+ return 1; /* no-op: UTF-8 validation is always on */
415
+ case yajl_allow_trailing_garbage:
416
+ case yajl_allow_multiple_values:
417
+ case yajl_allow_partial_values:
418
+ default:
419
+ return 0; /* unsupported: honest error, not silent misparse */
420
+ }
421
+ }
422
+
423
+ yajl_status yajl_parse(yajl_handle hand, const unsigned char* jsonText, size_t jsonTextLength) {
424
+ if (hand == NULL || (jsonText == NULL && jsonTextLength != 0)) {
425
+ return yajl_status_error;
426
+ }
427
+ if (hand->state != 0) {
428
+ /* yajl parks a completed handle; an error/cancel sticks */
429
+ return hand->state == 1 ? yajl_status_ok : yajl_status_error;
430
+ }
431
+ if (jsonTextLength > 0) {
432
+ if (hand->len + jsonTextLength > hand->cap) {
433
+ size_t cap = hand->cap ? hand->cap : 4096;
434
+ while (cap < hand->len + jsonTextLength) {
435
+ cap *= 2;
436
+ }
437
+ char* nb = realloc(hand->buf, cap);
438
+ if (nb == NULL) {
439
+ return yajl_status_error;
440
+ }
441
+ hand->buf = nb;
442
+ hand->cap = cap;
443
+ }
444
+ memcpy(hand->buf + hand->len, jsonText, jsonTextLength);
445
+ hand->len += jsonTextLength;
446
+ }
447
+ return yajl_status_ok;
448
+ }
449
+
450
+ /* Replaces JavaScript comments (yajl's allow_comments: block
451
+ * star-slash and line double-slash) outside strings with spaces —
452
+ * every byte offset and line number is preserved, so the strict
453
+ * parse sees the exact text yajl would. String boundaries (with
454
+ * escapes) are tracked so a double slash inside \"http://x\" stays
455
+ * content. */
456
+ static void mask_js_comments(char* p, size_t len) {
457
+ enum { NORM, STR } st = NORM;
458
+ size_t i = 0;
459
+ while (i < len) {
460
+ char c = p[i];
461
+ if (st == STR) {
462
+ if (c == '\\') {
463
+ i += 2; /* the escaped byte is content */
464
+ continue;
465
+ }
466
+ if (c == '"') {
467
+ st = NORM;
468
+ }
469
+ i++;
470
+ continue;
471
+ }
472
+ if (c == '"') {
473
+ st = STR;
474
+ i++;
475
+ continue;
476
+ }
477
+ if (c == '/' && i + 1 < len && p[i + 1] == '*') {
478
+ size_t j = i + 2;
479
+ while (j + 1 < len && !(p[j] == '*' && p[j + 1] == '/')) {
480
+ j++;
481
+ }
482
+ size_t end = (j + 1 < len && p[j] == '*' && p[j + 1] == '/') ? j + 2 : len;
483
+ for (size_t k = i; k < end; k++) {
484
+ if (p[k] != '\n') { /* line numbers stay true */
485
+ p[k] = ' ';
486
+ }
487
+ }
488
+ i = end;
489
+ continue;
490
+ }
491
+ if (c == '/' && i + 1 < len && p[i + 1] == '/') {
492
+ while (i < len && p[i] != '\n') {
493
+ p[i++] = ' ';
494
+ }
495
+ continue;
496
+ }
497
+ i++;
498
+ }
499
+ }
500
+
501
+ /* line:col (1-based) back to a byte offset in the accumulated input */
502
+ static size_t err_offset_of(const yajl_handle_t* h, uint32_t line, uint32_t col) {
503
+ size_t off = 0;
504
+ uint32_t ln = 1;
505
+ while (off < h->len && ln < line) {
506
+ if (h->buf[off] == '\n') {
507
+ ln++;
508
+ }
509
+ off++;
510
+ }
511
+ return off + (col > 0 ? col - 1 : 0);
512
+ }
513
+
514
+ static void fail_parse(yajl_handle_t* h, const char* what, uint32_t line, uint32_t col) {
515
+ h->state = 2;
516
+ h->err_off = line != 0 ? err_offset_of(h, line, col) : h->len;
517
+ h->have_err_off = 1;
518
+ snprintf(h->err, sizeof(h->err), "parse error: %s", what);
519
+ }
520
+
521
+ /* Walks one node; 0 = a callback canceled */
522
+ static int walk_node(yajl_handle_t* h, YeptrisNode n) {
523
+ switch (yeptris_node_kind(n)) {
524
+ case YEPTRIS_NODE_SEQUENCE:
525
+ if (h->cbs.yajl_start_array != NULL && !h->cbs.yajl_start_array(h->ctx)) {
526
+ return 0;
527
+ }
528
+ for (size_t i = 0; i < yeptris_node_seq_count(n); i++) {
529
+ if (!walk_node(h, yeptris_node_seq_at(n, i))) {
530
+ return 0;
531
+ }
532
+ }
533
+ if (h->cbs.yajl_end_array != NULL && !h->cbs.yajl_end_array(h->ctx)) {
534
+ return 0;
535
+ }
536
+ return 1;
537
+ case YEPTRIS_NODE_MAPPING:
538
+ if (h->cbs.yajl_start_map != NULL && !h->cbs.yajl_start_map(h->ctx)) {
539
+ return 0;
540
+ }
541
+ size_t pairs = yeptris_node_map_count(n);
542
+ for (size_t i = 0; i < pairs; i++) {
543
+ YeptrisNode k = NULL;
544
+ YeptrisNode v = NULL;
545
+ if (yeptris_node_map_at(n, i, &k, &v) != YEPTRIS_OK) {
546
+ return 1; /* unreachable on a parsed document */
547
+ }
548
+ size_t klen = 0;
549
+ const char* key = yeptris_node_value(k, &klen);
550
+ if (h->cbs.yajl_map_key != NULL &&
551
+ !h->cbs.yajl_map_key(h->ctx, (const unsigned char*)(key ? key : ""), klen)) {
552
+ return 0;
553
+ }
554
+ if (v != NULL && !walk_node(h, v)) {
555
+ return 0;
556
+ }
557
+ }
558
+ if (h->cbs.yajl_end_map != NULL && !h->cbs.yajl_end_map(h->ctx)) {
559
+ return 0;
560
+ }
561
+ return 1;
562
+ default:
563
+ break;
564
+ }
565
+ /* scalar: the resolver's typing decides the callback (a quoted
566
+ * "12" is a string — same discrimination jsonc_compat relies on) */
567
+ size_t vlen = 0;
568
+ const char* v = yeptris_node_value(n, &vlen);
569
+ if (h->cbs.yajl_number != NULL) {
570
+ int64_t i = 0;
571
+ double d = 0;
572
+ if (yeptris_node_int(n, &i) == YEPTRIS_OK || yeptris_node_float(n, &d) == YEPTRIS_OK) {
573
+ return h->cbs.yajl_number(h->ctx, v ? v : "", vlen);
574
+ }
575
+ } else {
576
+ int64_t i = 0;
577
+ double d = 0;
578
+ int b = 0;
579
+ if (yeptris_node_int(n, &i) == YEPTRIS_OK) {
580
+ return h->cbs.yajl_integer == NULL || h->cbs.yajl_integer(h->ctx, (long long)i);
581
+ }
582
+ if (yeptris_node_float(n, &d) == YEPTRIS_OK) {
583
+ if (!(d > -HUGE_VAL && d < HUGE_VAL)) {
584
+ /* yajl: unrepresentable numbers are parse errors when
585
+ * the number callback is absent */
586
+ h->num_overflow = 1;
587
+ return 0;
588
+ }
589
+ return h->cbs.yajl_double == NULL || h->cbs.yajl_double(h->ctx, d);
590
+ }
591
+ if (yeptris_node_bool(n, &b) == YEPTRIS_OK) {
592
+ return h->cbs.yajl_boolean == NULL || h->cbs.yajl_boolean(h->ctx, b);
593
+ }
594
+ }
595
+ size_t wlen = 0;
596
+ const char* w = yeptris_node_value(n, &wlen);
597
+ if (wlen == 4 && w != NULL && memcmp(w, "null", 4) == 0) {
598
+ return h->cbs.yajl_null == NULL || h->cbs.yajl_null(h->ctx);
599
+ }
600
+ return h->cbs.yajl_string == NULL ||
601
+ h->cbs.yajl_string(h->ctx, (const unsigned char*)(v ? v : ""), vlen);
602
+ }
603
+
604
+ yajl_status yajl_complete_parse(yajl_handle hand) {
605
+ if (hand == NULL) {
606
+ return yajl_status_error;
607
+ }
608
+ if (hand->state == 3) {
609
+ return yajl_status_client_canceled;
610
+ }
611
+ if (hand->state == 2) {
612
+ return yajl_status_error;
613
+ }
614
+ if (hand->state == 1) {
615
+ return yajl_status_ok; /* yajl parks completed handles */
616
+ }
617
+ if (hand->len == 0) {
618
+ fail_parse(hand, "premature EOF", 1, 1);
619
+ return yajl_status_error;
620
+ }
621
+ YeptrisStatus st = YEPTRIS_OK;
622
+ const char* parse_buf = hand->buf;
623
+ char* masked = NULL;
624
+ if (hand->allow_comments && hand->buf != NULL) {
625
+ masked = malloc(hand->len);
626
+ if (masked == NULL) {
627
+ return yajl_status_error;
628
+ }
629
+ memcpy(masked, hand->buf, hand->len);
630
+ mask_js_comments(masked, hand->len);
631
+ parse_buf = masked;
632
+ }
633
+ YeptrisDocument doc = yeptris_parse_json(parse_buf, hand->len, &st);
634
+ if (doc == NULL) {
635
+ uint32_t line = 0;
636
+ uint32_t col = 0;
637
+ const char* msg = yeptris_last_error(&line, &col);
638
+ fail_parse(hand, msg != NULL ? msg : "invalid JSON", line, col);
639
+ return yajl_status_error;
640
+ }
641
+ if (yeptris_document_count(doc) != 1) {
642
+ yeptris_document_free(doc);
643
+ fail_parse(hand, "trailing garbage", 1, 1);
644
+ return yajl_status_error;
645
+ }
646
+ int ok = walk_node(hand, yeptris_document_root(doc, 0));
647
+ int overflow = hand->num_overflow;
648
+ yeptris_document_free(doc);
649
+ free(masked);
650
+ if (!ok && overflow) {
651
+ fail_parse(hand, "number unrepresentable as double or integer", 1, 1);
652
+ return yajl_status_error;
653
+ }
654
+ if (!ok) {
655
+ hand->state = 3;
656
+ snprintf(hand->err, sizeof(hand->err), "client canceled parse");
657
+ return yajl_status_client_canceled;
658
+ }
659
+ hand->state = 1;
660
+ hand->err_off = hand->len;
661
+ hand->have_err_off = 1;
662
+ return yajl_status_ok;
663
+ }
664
+
665
+ unsigned char* yajl_get_error(yajl_handle hand, int verbose, const unsigned char* jsonText,
666
+ size_t jsonTextLength) {
667
+ (void)jsonText;
668
+ (void)jsonTextLength;
669
+ if (hand == NULL || hand->state < 2) {
670
+ return NULL;
671
+ }
672
+ if (!verbose) {
673
+ size_t need = strlen(hand->err) + 1;
674
+ unsigned char* out = malloc(need);
675
+ if (out != NULL) {
676
+ memcpy(out, hand->err, need);
677
+ }
678
+ return out;
679
+ }
680
+ /* verbose: the offending line plus a caret at the column */
681
+ size_t line_start = 0;
682
+ size_t line_end = hand->len;
683
+ if (hand->have_err_off) {
684
+ line_start = hand->err_off;
685
+ while (line_start > 0 && hand->buf[line_start - 1] != '\n') {
686
+ line_start--;
687
+ }
688
+ line_end = hand->err_off;
689
+ while (line_end < hand->len && hand->buf[line_end] != '\n') {
690
+ line_end++;
691
+ }
692
+ }
693
+ size_t lineno = 1;
694
+ for (size_t i = 0; i < line_start; i++) {
695
+ if (hand->buf[i] == '\n') {
696
+ lineno++;
697
+ }
698
+ }
699
+ size_t caret = hand->err_off > line_start ? hand->err_off - line_start : 0;
700
+ char* out = malloc(strlen(hand->err) + (line_end - line_start) + caret + 64);
701
+ if (out == NULL) {
702
+ return NULL;
703
+ }
704
+ int n = snprintf(out, strlen(hand->err) + 64, "%s at line %zu:\n", hand->err, lineno);
705
+ memcpy(out + n, hand->buf + line_start, line_end - line_start);
706
+ n += (int)(line_end - line_start);
707
+ out[n++] = '\n';
708
+ memset(out + n, ' ', caret);
709
+ n += (int)caret;
710
+ out[n++] = '^';
711
+ out[n] = '\0';
712
+ return (unsigned char*)out;
713
+ }
714
+
715
+ void yajl_free_error(yajl_handle hand, unsigned char* str) {
716
+ (void)hand;
717
+ free(str);
718
+ }
719
+
720
+ size_t yajl_get_bytes_consumed(yajl_handle hand) {
721
+ if (hand == NULL) {
722
+ return 0;
723
+ }
724
+ if (hand->have_err_off) {
725
+ return hand->err_off;
726
+ }
727
+ return hand->len;
728
+ }