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.
- checksums.yaml +7 -0
- data/README.adoc +141 -0
- data/ext/build_windows_native.rb +41 -0
- data/ext/libyeptris/extconf.rb +57 -0
- data/ext/yeptris_native/cbor_ruby.c +193 -0
- data/ext/yeptris_native/extconf.rb +47 -0
- data/ext/yeptris_native/json_ruby.c +354 -0
- data/ext/yeptris_native/yeptris_native.c +497 -0
- data/lib/yeptris/cbor.rb +130 -0
- data/lib/yeptris/document.rb +255 -0
- data/lib/yeptris/ffi.rb +426 -0
- data/lib/yeptris/json/descriptor.rb +266 -0
- data/lib/yeptris/json.rb +394 -0
- data/lib/yeptris/materializer.rb +354 -0
- data/lib/yeptris/native-3.4.so +0 -0
- data/lib/yeptris/node.rb +453 -0
- data/lib/yeptris/psych/class_loader.rb +24 -0
- data/lib/yeptris/psych/coder_shim.rb +55 -0
- data/lib/yeptris/psych/drop_in.rb +63 -0
- data/lib/yeptris/psych/encodable.rb +14 -0
- data/lib/yeptris/psych/handler.rb +90 -0
- data/lib/yeptris/psych/parser.rb +105 -0
- data/lib/yeptris/psych/scalar_scanner.rb +149 -0
- data/lib/yeptris/psych/visitors.rb +545 -0
- data/lib/yeptris/psych.rb +622 -0
- data/lib/yeptris/schema.rb +253 -0
- data/lib/yeptris/valueml.rb +455 -0
- data/lib/yeptris/yaml/descriptor.rb +56 -0
- data/lib/yeptris/yaml.rb +422 -0
- data/lib/yeptris.rb +113 -0
- data/libyeptris.so +0 -0
- data/vendor/libyeptris/CMakeLists.txt +254 -0
- data/vendor/libyeptris/cmake/yeptris-config.cmake.in +5 -0
- data/vendor/libyeptris/cmake/yeptris.pc.in +11 -0
- data/vendor/libyeptris/src/CMakeLists.txt +167 -0
- data/vendor/libyeptris/src/include/yeptris/api.h +32 -0
- data/vendor/libyeptris/src/include/yeptris/cbor.h +101 -0
- data/vendor/libyeptris/src/include/yeptris/dom.h +190 -0
- data/vendor/libyeptris/src/include/yeptris/emit.h +81 -0
- data/vendor/libyeptris/src/include/yeptris/error.h +41 -0
- data/vendor/libyeptris/src/include/yeptris/events.h +157 -0
- data/vendor/libyeptris/src/include/yeptris/json.h +45 -0
- data/vendor/libyeptris/src/include/yeptris/json.hpp +258 -0
- data/vendor/libyeptris/src/include/yeptris/jsonc_compat.h +115 -0
- data/vendor/libyeptris/src/include/yeptris/marshal.h +52 -0
- data/vendor/libyeptris/src/include/yeptris/parse.h +48 -0
- data/vendor/libyeptris/src/include/yeptris/plan.h +100 -0
- data/vendor/libyeptris/src/include/yeptris/resolve.h +71 -0
- data/vendor/libyeptris/src/include/yeptris/schema.h +121 -0
- data/vendor/libyeptris/src/include/yeptris/tape.h +123 -0
- data/vendor/libyeptris/src/include/yeptris/types.h +38 -0
- data/vendor/libyeptris/src/include/yeptris/values.h +102 -0
- data/vendor/libyeptris/src/include/yeptris/version.h.in +29 -0
- data/vendor/libyeptris/src/include/yeptris/visit.h +77 -0
- data/vendor/libyeptris/src/include/yeptris/yajl_compat.h +135 -0
- data/vendor/libyeptris/src/include/yeptris.h +23 -0
- data/vendor/libyeptris/src/yeptris/build.c +376 -0
- data/vendor/libyeptris/src/yeptris/cbor/cbor.h +25 -0
- data/vendor/libyeptris/src/yeptris/cbor/decode.c +981 -0
- data/vendor/libyeptris/src/yeptris/cbor/encode.c +835 -0
- data/vendor/libyeptris/src/yeptris/cbor/sink.h +58 -0
- data/vendor/libyeptris/src/yeptris/common/chartype.c +41 -0
- data/vendor/libyeptris/src/yeptris/common/chartype.h +77 -0
- data/vendor/libyeptris/src/yeptris/common/cpu.c +81 -0
- data/vendor/libyeptris/src/yeptris/common/cpu.h +40 -0
- data/vendor/libyeptris/src/yeptris/common/error.c +65 -0
- data/vendor/libyeptris/src/yeptris/common/error.h +79 -0
- data/vendor/libyeptris/src/yeptris/common/mutex.h +45 -0
- data/vendor/libyeptris/src/yeptris/common/nametab.c +275 -0
- data/vendor/libyeptris/src/yeptris/common/nametab.h +68 -0
- data/vendor/libyeptris/src/yeptris/common/port.h +74 -0
- data/vendor/libyeptris/src/yeptris/common/simd_text.c +49 -0
- data/vendor/libyeptris/src/yeptris/common/simd_text.h +295 -0
- data/vendor/libyeptris/src/yeptris/common/simd_text_avx2.c +534 -0
- data/vendor/libyeptris/src/yeptris/common/simd_text_neon.c +662 -0
- data/vendor/libyeptris/src/yeptris/common/simd_text_scalar.c +298 -0
- data/vendor/libyeptris/src/yeptris/common/string_view.c +34 -0
- data/vendor/libyeptris/src/yeptris/common/string_view.h +93 -0
- data/vendor/libyeptris/src/yeptris/doc.h +56 -0
- data/vendor/libyeptris/src/yeptris/dom/dom.c +1192 -0
- data/vendor/libyeptris/src/yeptris/dom/dom.h +312 -0
- data/vendor/libyeptris/src/yeptris/dom/hpool.c +107 -0
- data/vendor/libyeptris/src/yeptris/dom/mapindex.c +173 -0
- data/vendor/libyeptris/src/yeptris/dom/mapindex.h +61 -0
- data/vendor/libyeptris/src/yeptris/dom/mutate.c +431 -0
- data/vendor/libyeptris/src/yeptris/emit/emit.c +434 -0
- data/vendor/libyeptris/src/yeptris/emit/float/api.h +38 -0
- data/vendor/libyeptris/src/yeptris/emit/float/dragon.c +405 -0
- data/vendor/libyeptris/src/yeptris/emit/float/floatint.h +231 -0
- data/vendor/libyeptris/src/yeptris/emit/float/print.c +396 -0
- data/vendor/libyeptris/src/yeptris/emit/style.c +81 -0
- data/vendor/libyeptris/src/yeptris/emit/style.h +24 -0
- data/vendor/libyeptris/src/yeptris/emit/writer.c +816 -0
- data/vendor/libyeptris/src/yeptris/emit/writer.h +76 -0
- data/vendor/libyeptris/src/yeptris/encoding/bom.c +31 -0
- data/vendor/libyeptris/src/yeptris/encoding/encoding.h +63 -0
- data/vendor/libyeptris/src/yeptris/encoding/transcode.c +148 -0
- data/vendor/libyeptris/src/yeptris/encoding/utf8_validate.c +178 -0
- data/vendor/libyeptris/src/yeptris/events/capture.c +150 -0
- data/vendor/libyeptris/src/yeptris/events/capture.h +39 -0
- data/vendor/libyeptris/src/yeptris/events/iterparse.c +208 -0
- data/vendor/libyeptris/src/yeptris/events/pull.c +97 -0
- data/vendor/libyeptris/src/yeptris/events/push.c +104 -0
- data/vendor/libyeptris/src/yeptris/events/recorder.c +107 -0
- data/vendor/libyeptris/src/yeptris/events/values.c +527 -0
- data/vendor/libyeptris/src/yeptris/events/values_priv.h +51 -0
- data/vendor/libyeptris/src/yeptris/events/yaml_compat.c +86 -0
- data/vendor/libyeptris/src/yeptris/events/yaml_compat.h +90 -0
- data/vendor/libyeptris/src/yeptris/jsonapi/jsonc_compat.c +687 -0
- data/vendor/libyeptris/src/yeptris/jsonapi/yajl_compat.c +728 -0
- data/vendor/libyeptris/src/yeptris/marshal.c +782 -0
- data/vendor/libyeptris/src/yeptris/memory/allocator.c +20 -0
- data/vendor/libyeptris/src/yeptris/memory/allocator.h +43 -0
- data/vendor/libyeptris/src/yeptris/memory/arena.c +134 -0
- data/vendor/libyeptris/src/yeptris/memory/arena.h +52 -0
- data/vendor/libyeptris/src/yeptris/memory/pool.c +122 -0
- data/vendor/libyeptris/src/yeptris/memory/pool.h +36 -0
- data/vendor/libyeptris/src/yeptris/parse/engine.c +3698 -0
- data/vendor/libyeptris/src/yeptris/parse/engine.h +65 -0
- data/vendor/libyeptris/src/yeptris/parse/events.h +124 -0
- data/vendor/libyeptris/src/yeptris/parse/numbers.c +349 -0
- data/vendor/libyeptris/src/yeptris/parse/numbers.h +33 -0
- data/vendor/libyeptris/src/yeptris/parse/scalars.c +416 -0
- data/vendor/libyeptris/src/yeptris/parse/scalars.h +75 -0
- data/vendor/libyeptris/src/yeptris/parse.c +737 -0
- data/vendor/libyeptris/src/yeptris/plan.c +824 -0
- data/vendor/libyeptris/src/yeptris/resolve/compat11.c +334 -0
- data/vendor/libyeptris/src/yeptris/resolve/core12.c +143 -0
- data/vendor/libyeptris/src/yeptris/resolve/resolver.h +56 -0
- data/vendor/libyeptris/src/yeptris/resolve/tags.c +58 -0
- data/vendor/libyeptris/src/yeptris/scan/json.c +792 -0
- data/vendor/libyeptris/src/yeptris/scan/json.h +109 -0
- data/vendor/libyeptris/src/yeptris/scan/scan.c +463 -0
- data/vendor/libyeptris/src/yeptris/scan/scan.h +150 -0
- data/vendor/libyeptris/src/yeptris/schema.c +308 -0
- data/vendor/libyeptris/src/yeptris/tape.c +1308 -0
- data/vendor/libyeptris/src/yeptris/tape_in.h +19 -0
- data/vendor/libyeptris/src/yeptris/version.c +7 -0
- data/vendor/libyeptris/src/yeptris/visit/dom_visit.c +115 -0
- data/vendor/libyeptris/src/yeptris/visit/json_visit.c +293 -0
- data/vendor/libyeptris/src/yeptris/visit/yaml_visit.c +127 -0
- metadata +199 -0
|
@@ -0,0 +1,824 @@
|
|
|
1
|
+
/* plan.c — the compiled plan walk (TODO.restructure/87 slice one,
|
|
2
|
+
* yeptris#293). Compile: the spec parses through the strict JSON DOM,
|
|
3
|
+
* then lands as a flat column array + the collection path. Walk: one
|
|
4
|
+
* linear pass over the tape's records — find the rows container,
|
|
5
|
+
* count rows, then fill the typed columns per row by comparing key
|
|
6
|
+
* spans against the planned leaf names (no host dispatch, no tree). */
|
|
7
|
+
|
|
8
|
+
#include <stdlib.h>
|
|
9
|
+
#include <string.h>
|
|
10
|
+
|
|
11
|
+
#include <yeptris.h>
|
|
12
|
+
#include <yeptris/json.h>
|
|
13
|
+
#include <yeptris/plan.h>
|
|
14
|
+
|
|
15
|
+
#include "doc.h"
|
|
16
|
+
#include "dom/dom.h"
|
|
17
|
+
#include "parse/numbers.h"
|
|
18
|
+
#include "scan/json.h"
|
|
19
|
+
|
|
20
|
+
/* sview decode (the writer's wv, over the document's two regions) */
|
|
21
|
+
static yep_view sv_view(const yep_dom* d, yep_sview sv) {
|
|
22
|
+
yep_view v = {NULL, 0};
|
|
23
|
+
if (sv.len == 0) {
|
|
24
|
+
return v;
|
|
25
|
+
}
|
|
26
|
+
v.len = sv.len;
|
|
27
|
+
v.p = ((sv.off & YEP_SV_INPUT) ? d->str : d->input_base) + (sv.off & YEP_SV_OFF);
|
|
28
|
+
return v;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
typedef struct {
|
|
32
|
+
char* name;
|
|
33
|
+
uint32_t name_len;
|
|
34
|
+
int kind;
|
|
35
|
+
} yep_plan_col;
|
|
36
|
+
|
|
37
|
+
struct yeptris_plan {
|
|
38
|
+
yep_plan_col* cols;
|
|
39
|
+
size_t ncols;
|
|
40
|
+
char* path; /* the path segments' bytes, concatenated */
|
|
41
|
+
size_t path_len;
|
|
42
|
+
uint32_t* seg_off; /* nsegs entries: segment start inside path */
|
|
43
|
+
uint32_t* seg_len;
|
|
44
|
+
size_t nsegs; /* 0 = the root itself is the rows container */
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
typedef struct {
|
|
48
|
+
int kind;
|
|
49
|
+
int64_t* ints;
|
|
50
|
+
double* floats;
|
|
51
|
+
uint32_t* offs;
|
|
52
|
+
uint32_t* lens;
|
|
53
|
+
yeptris_plan_str* views; /* the DOM leg's str lane: (ptr,len) into the doc */
|
|
54
|
+
uint8_t* nulls;
|
|
55
|
+
} yep_result_col;
|
|
56
|
+
|
|
57
|
+
struct yeptris_plan_result {
|
|
58
|
+
size_t rows;
|
|
59
|
+
size_t ncols;
|
|
60
|
+
yep_result_col* cols;
|
|
61
|
+
void* block; /* one carved allocation backs every array */
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
YEPTRIS_API yeptris_plan* yeptris_plan_compile(const char* spec, size_t len, YeptrisStatus* st) {
|
|
65
|
+
if (st != NULL) {
|
|
66
|
+
*st = YEPTRIS_OK;
|
|
67
|
+
}
|
|
68
|
+
if (spec == NULL && len != 0) {
|
|
69
|
+
if (st != NULL) {
|
|
70
|
+
*st = YEPTRIS_ERROR_ARG;
|
|
71
|
+
}
|
|
72
|
+
return NULL;
|
|
73
|
+
}
|
|
74
|
+
YeptrisStatus pst = YEPTRIS_OK;
|
|
75
|
+
YeptrisDocument doc = yeptris_parse_json(spec, len, &pst);
|
|
76
|
+
if (doc == NULL) {
|
|
77
|
+
if (st != NULL) {
|
|
78
|
+
*st = pst;
|
|
79
|
+
}
|
|
80
|
+
return NULL;
|
|
81
|
+
}
|
|
82
|
+
yeptris_document* d = (yeptris_document*)doc;
|
|
83
|
+
yeptris_plan* plan = calloc(1, sizeof(*plan)); /* before any goto: out frees it */
|
|
84
|
+
if (plan == NULL) {
|
|
85
|
+
goto mem;
|
|
86
|
+
}
|
|
87
|
+
yep_dom* dd = yep_doc_dom(d); /* #342 lazy: the spec parse may defer */
|
|
88
|
+
if (dd == NULL) {
|
|
89
|
+
goto mem;
|
|
90
|
+
}
|
|
91
|
+
const yep_dnode* root = yep_dom_node(dd, dd->docs[0]);
|
|
92
|
+
if (root == NULL || root->kind != 2) { /* the spec root is a mapping */
|
|
93
|
+
goto bad;
|
|
94
|
+
}
|
|
95
|
+
/* kind: "seq" (rows under the path key or the root itself) or
|
|
96
|
+
* "map" (rows under the path key); children: the leaf columns */
|
|
97
|
+
const yep_dnode* path_node = NULL;
|
|
98
|
+
const yep_dnode* children = NULL;
|
|
99
|
+
int saw_kind = 0;
|
|
100
|
+
uint32_t pair = root->first_child;
|
|
101
|
+
while (pair != UINT32_MAX) {
|
|
102
|
+
const yep_dnode* kn = yep_dom_node(dd, pair);
|
|
103
|
+
const yep_dnode* vn = yep_dom_node(dd, kn->next_sibling);
|
|
104
|
+
yep_view kv = sv_view(dd, kn->value);
|
|
105
|
+
yep_view vv = sv_view(dd, vn->value);
|
|
106
|
+
if (kv.len == 4 && memcmp(kv.p, "kind", 4) == 0) {
|
|
107
|
+
saw_kind = 1;
|
|
108
|
+
if (!(vv.len == 3 && (memcmp(vv.p, "seq", 3) == 0 || memcmp(vv.p, "map", 3) == 0))) {
|
|
109
|
+
goto bad;
|
|
110
|
+
}
|
|
111
|
+
} else if (kv.len == 4 && memcmp(kv.p, "path", 4) == 0) {
|
|
112
|
+
if (vn->kind != 0 && vn->kind != 1) { /* a string or a string seq */
|
|
113
|
+
goto bad;
|
|
114
|
+
}
|
|
115
|
+
path_node = vn;
|
|
116
|
+
} else if (kv.len == 8 && memcmp(kv.p, "children", 8) == 0) {
|
|
117
|
+
if (vn->kind != 1) { /* children is a sequence */
|
|
118
|
+
goto bad;
|
|
119
|
+
}
|
|
120
|
+
children = vn;
|
|
121
|
+
} else {
|
|
122
|
+
goto bad; /* unknown spec key */
|
|
123
|
+
}
|
|
124
|
+
pair = vn->next_sibling;
|
|
125
|
+
}
|
|
126
|
+
if (!saw_kind || children == NULL) {
|
|
127
|
+
goto bad;
|
|
128
|
+
}
|
|
129
|
+
plan->path = calloc(1, 1);
|
|
130
|
+
if (plan->path == NULL) {
|
|
131
|
+
goto mem;
|
|
132
|
+
}
|
|
133
|
+
if (path_node != NULL && path_node->kind == 0) {
|
|
134
|
+
if (path_node->tag_id != YEPTRIS_TAG_STR) {
|
|
135
|
+
goto bad; /* the path is a string, not a number */
|
|
136
|
+
}
|
|
137
|
+
yep_view vv = sv_view(dd, path_node->value);
|
|
138
|
+
if (vv.len != 0) { /* "" rides the seq root like no path */
|
|
139
|
+
plan->seg_off = malloc(sizeof(uint32_t));
|
|
140
|
+
plan->seg_len = malloc(sizeof(uint32_t));
|
|
141
|
+
if (plan->seg_off == NULL || plan->seg_len == NULL) {
|
|
142
|
+
goto mem;
|
|
143
|
+
}
|
|
144
|
+
free(plan->path);
|
|
145
|
+
plan->path = malloc(vv.len + 1);
|
|
146
|
+
if (plan->path == NULL) {
|
|
147
|
+
goto mem;
|
|
148
|
+
}
|
|
149
|
+
memcpy(plan->path, vv.p, vv.len);
|
|
150
|
+
plan->path[vv.len] = 0;
|
|
151
|
+
plan->path_len = vv.len;
|
|
152
|
+
plan->seg_off[0] = 0;
|
|
153
|
+
plan->seg_len[0] = vv.len;
|
|
154
|
+
plan->nsegs = 1;
|
|
155
|
+
}
|
|
156
|
+
} else if (path_node != NULL) {
|
|
157
|
+
size_t n = path_node->count;
|
|
158
|
+
plan->seg_off = calloc(n, sizeof(uint32_t));
|
|
159
|
+
plan->seg_len = calloc(n, sizeof(uint32_t));
|
|
160
|
+
if (n != 0 && (plan->seg_off == NULL || plan->seg_len == NULL)) {
|
|
161
|
+
goto mem;
|
|
162
|
+
}
|
|
163
|
+
size_t off = 0;
|
|
164
|
+
uint32_t cn = path_node->first_child;
|
|
165
|
+
for (size_t i = 0; i < n; i++) {
|
|
166
|
+
const yep_dnode* seg = yep_dom_node(dd, cn);
|
|
167
|
+
if (seg == NULL || seg->kind != 0 || seg->tag_id != YEPTRIS_TAG_STR) {
|
|
168
|
+
goto bad; /* every segment is a string */
|
|
169
|
+
}
|
|
170
|
+
yep_view sv = sv_view(dd, seg->value);
|
|
171
|
+
if (sv.len == 0) {
|
|
172
|
+
goto bad;
|
|
173
|
+
}
|
|
174
|
+
char* grown = realloc(plan->path, off + sv.len + 1);
|
|
175
|
+
if (grown == NULL) {
|
|
176
|
+
goto mem;
|
|
177
|
+
}
|
|
178
|
+
plan->path = grown;
|
|
179
|
+
memcpy(plan->path + off, sv.p, sv.len);
|
|
180
|
+
plan->seg_off[i] = (uint32_t)off;
|
|
181
|
+
plan->seg_len[i] = sv.len;
|
|
182
|
+
off += sv.len;
|
|
183
|
+
cn = seg->next_sibling;
|
|
184
|
+
}
|
|
185
|
+
plan->path_len = off;
|
|
186
|
+
plan->nsegs = n;
|
|
187
|
+
}
|
|
188
|
+
plan->ncols = children->count;
|
|
189
|
+
if (plan->ncols == 0) {
|
|
190
|
+
goto bad;
|
|
191
|
+
}
|
|
192
|
+
plan->cols = calloc(plan->ncols, sizeof(*plan->cols));
|
|
193
|
+
if (plan->cols == NULL) {
|
|
194
|
+
goto mem;
|
|
195
|
+
}
|
|
196
|
+
uint32_t cn = children->first_child;
|
|
197
|
+
for (size_t i = 0; i < plan->ncols; i++) {
|
|
198
|
+
const yep_dnode* leaf = yep_dom_node(dd, cn);
|
|
199
|
+
if (leaf == NULL || leaf->kind != 2) {
|
|
200
|
+
goto bad;
|
|
201
|
+
}
|
|
202
|
+
const char* name = NULL;
|
|
203
|
+
uint32_t name_len = 0;
|
|
204
|
+
int kind = -1;
|
|
205
|
+
uint32_t lp = leaf->first_child;
|
|
206
|
+
while (lp != UINT32_MAX) {
|
|
207
|
+
const yep_dnode* lk = yep_dom_node(dd, lp);
|
|
208
|
+
const yep_dnode* lv = yep_dom_node(dd, lk->next_sibling);
|
|
209
|
+
yep_view lkv = sv_view(dd, lk->value);
|
|
210
|
+
yep_view lvv = sv_view(dd, lv->value);
|
|
211
|
+
if (lkv.len == 4 && memcmp(lkv.p, "name", 4) == 0) {
|
|
212
|
+
if (lv->kind != 0 || lvv.len == 0) {
|
|
213
|
+
goto bad;
|
|
214
|
+
}
|
|
215
|
+
name = lvv.p;
|
|
216
|
+
name_len = lvv.len;
|
|
217
|
+
} else if (lkv.len == 4 && memcmp(lkv.p, "kind", 4) == 0) {
|
|
218
|
+
if (lvv.len == 3 && memcmp(lvv.p, "int", 3) == 0) {
|
|
219
|
+
kind = YEP_PLAN_INT;
|
|
220
|
+
} else if (lvv.len == 5 && memcmp(lvv.p, "float", 5) == 0) {
|
|
221
|
+
kind = YEP_PLAN_FLOAT;
|
|
222
|
+
} else if (lvv.len == 3 && memcmp(lvv.p, "str", 3) == 0) {
|
|
223
|
+
kind = YEP_PLAN_STR;
|
|
224
|
+
} else if (lvv.len == 4 && memcmp(lvv.p, "bool", 4) == 0) {
|
|
225
|
+
kind = YEP_PLAN_BOOL;
|
|
226
|
+
} else {
|
|
227
|
+
goto bad;
|
|
228
|
+
}
|
|
229
|
+
} else {
|
|
230
|
+
goto bad;
|
|
231
|
+
}
|
|
232
|
+
lp = lv->next_sibling;
|
|
233
|
+
}
|
|
234
|
+
if (name == NULL || kind < 0) {
|
|
235
|
+
goto bad;
|
|
236
|
+
}
|
|
237
|
+
plan->cols[i].name = malloc(name_len + 1);
|
|
238
|
+
if (plan->cols[i].name == NULL) {
|
|
239
|
+
goto mem;
|
|
240
|
+
}
|
|
241
|
+
memcpy(plan->cols[i].name, name, name_len);
|
|
242
|
+
plan->cols[i].name[name_len] = 0;
|
|
243
|
+
plan->cols[i].name_len = name_len;
|
|
244
|
+
plan->cols[i].kind = kind;
|
|
245
|
+
cn = leaf->next_sibling;
|
|
246
|
+
}
|
|
247
|
+
if (cn != UINT32_MAX) {
|
|
248
|
+
goto bad; /* more children than counted */
|
|
249
|
+
}
|
|
250
|
+
yeptris_document_free(doc);
|
|
251
|
+
return plan;
|
|
252
|
+
|
|
253
|
+
mem:
|
|
254
|
+
if (st != NULL) {
|
|
255
|
+
*st = YEPTRIS_ERROR_MEMORY;
|
|
256
|
+
}
|
|
257
|
+
goto out;
|
|
258
|
+
bad:
|
|
259
|
+
if (st != NULL) {
|
|
260
|
+
*st = YEPTRIS_ERROR_ARG;
|
|
261
|
+
}
|
|
262
|
+
out:
|
|
263
|
+
if (doc != NULL) {
|
|
264
|
+
yeptris_document_free(doc);
|
|
265
|
+
}
|
|
266
|
+
yeptris_plan_free(plan);
|
|
267
|
+
return NULL;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
YEPTRIS_API void yeptris_plan_free(yeptris_plan* plan) {
|
|
271
|
+
if (plan == NULL) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
for (size_t i = 0; i < plan->ncols; i++) {
|
|
275
|
+
free(plan->cols[i].name);
|
|
276
|
+
}
|
|
277
|
+
free(plan->cols);
|
|
278
|
+
free(plan->path);
|
|
279
|
+
free(plan->seg_off);
|
|
280
|
+
free(plan->seg_len);
|
|
281
|
+
free(plan);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
YEPTRIS_API size_t yeptris_plan_column_count(const yeptris_plan* plan) {
|
|
285
|
+
return plan == NULL ? 0 : plan->ncols;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/* Finds the rows container's OPEN record: the root OPEN's child
|
|
289
|
+
* matching each path segment in turn (a map root), or the root OPEN
|
|
290
|
+
* itself (a seq root). Returns the record index of the container
|
|
291
|
+
* OPEN, or 0 (the DOC record) when the shape disagrees. */
|
|
292
|
+
static size_t find_rows_open(const yeptris_json_tape* t, const yeptris_plan* plan) {
|
|
293
|
+
size_t root = 1; /* the root OPEN (tape records start after DOC) */
|
|
294
|
+
if (root >= t->count) {
|
|
295
|
+
return 0;
|
|
296
|
+
}
|
|
297
|
+
if (t->kinds[root] != YEP_T_SEQ_OPEN && t->kinds[root] != YEP_T_MAP_OPEN) {
|
|
298
|
+
return 0;
|
|
299
|
+
}
|
|
300
|
+
if (plan->nsegs == 0) {
|
|
301
|
+
return t->kinds[root] == YEP_T_SEQ_OPEN ? root : 0;
|
|
302
|
+
}
|
|
303
|
+
/* map root: walk the segments. Pairs are (STR key, value record);
|
|
304
|
+
* a container value spans to its CLOSE (offs link) */
|
|
305
|
+
size_t cur = root;
|
|
306
|
+
for (size_t s = 0; s < plan->nsegs; s++) {
|
|
307
|
+
if (t->kinds[cur] != YEP_T_MAP_OPEN) {
|
|
308
|
+
return 0;
|
|
309
|
+
}
|
|
310
|
+
const char* seg = plan->path + plan->seg_off[s];
|
|
311
|
+
uint32_t seg_len = plan->seg_len[s];
|
|
312
|
+
size_t i = cur + 1;
|
|
313
|
+
int found = 0;
|
|
314
|
+
while (i < t->count && i < t->offs[cur]) {
|
|
315
|
+
if (t->kinds[i] != YEP_T_STR) {
|
|
316
|
+
return 0; /* not a key position */
|
|
317
|
+
}
|
|
318
|
+
if (t->lens[i] == seg_len &&
|
|
319
|
+
memcmp((const char*)t->_src + t->offs[i], seg, seg_len) == 0) {
|
|
320
|
+
size_t v = i + 1;
|
|
321
|
+
if (v >= t->count) {
|
|
322
|
+
return 0;
|
|
323
|
+
}
|
|
324
|
+
if (s + 1 < plan->nsegs) {
|
|
325
|
+
if (t->kinds[v] != YEP_T_MAP_OPEN) {
|
|
326
|
+
return 0; /* the next segment needs a mapping */
|
|
327
|
+
}
|
|
328
|
+
cur = v;
|
|
329
|
+
} else {
|
|
330
|
+
return v; /* the rows container's OPEN (or scalar) */
|
|
331
|
+
}
|
|
332
|
+
found = 1;
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
335
|
+
i++; /* the value */
|
|
336
|
+
uint8_t vk = t->kinds[i];
|
|
337
|
+
if (vk == YEP_T_MAP_OPEN || vk == YEP_T_SEQ_OPEN) {
|
|
338
|
+
i = t->offs[i]; /* skip to its CLOSE */
|
|
339
|
+
}
|
|
340
|
+
i++;
|
|
341
|
+
}
|
|
342
|
+
if (!found) {
|
|
343
|
+
return 0;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return 0; /* unreachable with nsegs > 0 */
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/* Carves the result: cols array, then the typed lanes (8*rows bytes
|
|
350
|
+
* each — ints/floats directly, tape-str = offs+lens, DOM-str =
|
|
351
|
+
* views), then the null bitmaps last so every typed base stays
|
|
352
|
+
* 8-aligned. str_row_bytes is the per-row footprint of a str
|
|
353
|
+
* column's lane (8 for the tape leg, sizeof(yeptris_plan_str) for the DOM
|
|
354
|
+
* leg). Returns NULL with *st on overflow/allocation failure. */
|
|
355
|
+
static yeptris_plan_result* plan_result_carve(const yeptris_plan* plan, size_t rows,
|
|
356
|
+
size_t str_row_bytes, YeptrisStatus* st) {
|
|
357
|
+
size_t ncols = plan->ncols;
|
|
358
|
+
size_t col_bytes = ncols * sizeof(yep_result_col);
|
|
359
|
+
if (ncols != 0 && rows != 0 && rows > (SIZE_MAX - col_bytes) / (str_row_bytes + 9)) {
|
|
360
|
+
if (st != NULL) {
|
|
361
|
+
*st = YEPTRIS_ERROR_MEMORY;
|
|
362
|
+
}
|
|
363
|
+
return NULL;
|
|
364
|
+
}
|
|
365
|
+
size_t need = col_bytes;
|
|
366
|
+
for (size_t c = 0; c < ncols; c++) {
|
|
367
|
+
size_t lane = plan->cols[c].kind == YEP_PLAN_STR ? str_row_bytes : 8;
|
|
368
|
+
need += rows * lane + rows;
|
|
369
|
+
}
|
|
370
|
+
char* block = malloc(need);
|
|
371
|
+
if (block == NULL) {
|
|
372
|
+
if (st != NULL) {
|
|
373
|
+
*st = YEPTRIS_ERROR_MEMORY;
|
|
374
|
+
}
|
|
375
|
+
return NULL;
|
|
376
|
+
}
|
|
377
|
+
yeptris_plan_result* r = calloc(1, sizeof(*r));
|
|
378
|
+
if (r == NULL) {
|
|
379
|
+
free(block);
|
|
380
|
+
if (st != NULL) {
|
|
381
|
+
*st = YEPTRIS_ERROR_MEMORY;
|
|
382
|
+
}
|
|
383
|
+
return NULL;
|
|
384
|
+
}
|
|
385
|
+
r->rows = rows;
|
|
386
|
+
r->ncols = ncols;
|
|
387
|
+
r->block = block;
|
|
388
|
+
r->cols = (yep_result_col*)block;
|
|
389
|
+
memset(block, 0, col_bytes);
|
|
390
|
+
char* p = block + col_bytes;
|
|
391
|
+
for (size_t c = 0; c < ncols; c++) {
|
|
392
|
+
yep_result_col* col = &r->cols[c];
|
|
393
|
+
col->kind = plan->cols[c].kind;
|
|
394
|
+
if (col->kind == YEP_PLAN_FLOAT) {
|
|
395
|
+
col->floats = (double*)p;
|
|
396
|
+
p += rows * sizeof(double);
|
|
397
|
+
} else if (col->kind == YEP_PLAN_STR) {
|
|
398
|
+
if (str_row_bytes == sizeof(yeptris_plan_str)) {
|
|
399
|
+
col->views = (yeptris_plan_str*)p;
|
|
400
|
+
p += rows * sizeof(yep_view);
|
|
401
|
+
} else {
|
|
402
|
+
col->offs = (uint32_t*)p;
|
|
403
|
+
p += rows * sizeof(uint32_t);
|
|
404
|
+
col->lens = (uint32_t*)p;
|
|
405
|
+
p += rows * sizeof(uint32_t);
|
|
406
|
+
}
|
|
407
|
+
} else {
|
|
408
|
+
col->ints = (int64_t*)p; /* int and bool share the lane */
|
|
409
|
+
p += rows * sizeof(int64_t);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
for (size_t c = 0; c < ncols; c++) {
|
|
413
|
+
r->cols[c].nulls = (uint8_t*)p;
|
|
414
|
+
memset(r->cols[c].nulls, 1, rows); /* missing until matched */
|
|
415
|
+
p += rows;
|
|
416
|
+
}
|
|
417
|
+
return r;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
YEPTRIS_API yeptris_plan_result*
|
|
421
|
+
yeptris_tape_plan_walk(const yeptris_json_tape* tape, const yeptris_plan* plan, YeptrisStatus* st) {
|
|
422
|
+
/* item 07: the lenient tape's columns are lazy — materialize (a
|
|
423
|
+
* cache write through a const view; idempotent) */
|
|
424
|
+
yeptris_tape_columns((yeptris_json_tape*)tape);
|
|
425
|
+
if (st != NULL) {
|
|
426
|
+
*st = YEPTRIS_OK;
|
|
427
|
+
}
|
|
428
|
+
if (tape == NULL || plan == NULL || tape->count < 2) {
|
|
429
|
+
if (st != NULL) {
|
|
430
|
+
*st = YEPTRIS_ERROR_ARG;
|
|
431
|
+
}
|
|
432
|
+
return NULL;
|
|
433
|
+
}
|
|
434
|
+
size_t rows_open = find_rows_open(tape, plan);
|
|
435
|
+
if (rows_open == 0) {
|
|
436
|
+
if (st != NULL) {
|
|
437
|
+
*st = YEPTRIS_ERROR_PARSE; /* document shape disagreement */
|
|
438
|
+
}
|
|
439
|
+
return NULL;
|
|
440
|
+
}
|
|
441
|
+
uint8_t rows_kind = tape->kinds[rows_open];
|
|
442
|
+
if (rows_kind != YEP_T_SEQ_OPEN && rows_kind != YEP_T_MAP_OPEN) {
|
|
443
|
+
if (st != NULL) {
|
|
444
|
+
*st = YEPTRIS_ERROR_PARSE;
|
|
445
|
+
}
|
|
446
|
+
return NULL;
|
|
447
|
+
}
|
|
448
|
+
size_t rows_close = tape->offs[rows_open];
|
|
449
|
+
|
|
450
|
+
/* pass one: count the row MAP_OPENs directly inside the container */
|
|
451
|
+
size_t rows = 0;
|
|
452
|
+
{
|
|
453
|
+
int depth = 0;
|
|
454
|
+
for (size_t i = rows_open + 1; i < rows_close; i++) {
|
|
455
|
+
uint8_t k = tape->kinds[i];
|
|
456
|
+
if (depth == 0 && k == YEP_T_MAP_OPEN) {
|
|
457
|
+
rows++;
|
|
458
|
+
}
|
|
459
|
+
if (k == YEP_T_MAP_OPEN || k == YEP_T_SEQ_OPEN) {
|
|
460
|
+
depth++;
|
|
461
|
+
} else if (k == YEP_T_CLOSE) {
|
|
462
|
+
depth--;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
size_t ncols = plan->ncols;
|
|
468
|
+
yeptris_plan_result* r = plan_result_carve(plan, rows, 8, st);
|
|
469
|
+
if (r == NULL) {
|
|
470
|
+
return NULL;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/* pass two: fill. Rows are MAP_OPEN..CLOSE at container depth 0;
|
|
474
|
+
* each pair's key span matches a planned leaf name. */
|
|
475
|
+
const char* src = (const char*)tape->_src;
|
|
476
|
+
size_t row = 0;
|
|
477
|
+
int depth = 0;
|
|
478
|
+
int row_start = 0;
|
|
479
|
+
for (size_t i = rows_open + 1; i < rows_close && row < rows; i++) {
|
|
480
|
+
uint8_t k = tape->kinds[i];
|
|
481
|
+
if (k == YEP_T_MAP_OPEN || k == YEP_T_SEQ_OPEN) {
|
|
482
|
+
if (depth == 0 && k == YEP_T_MAP_OPEN) {
|
|
483
|
+
row_start = 1; /* inside a row */
|
|
484
|
+
}
|
|
485
|
+
depth++;
|
|
486
|
+
continue;
|
|
487
|
+
}
|
|
488
|
+
if (k == YEP_T_CLOSE) {
|
|
489
|
+
depth--;
|
|
490
|
+
if (depth == 0 && row_start) {
|
|
491
|
+
row++;
|
|
492
|
+
row_start = 0;
|
|
493
|
+
}
|
|
494
|
+
continue;
|
|
495
|
+
}
|
|
496
|
+
if (depth != 1 || !row_start || k != YEP_T_STR) {
|
|
497
|
+
continue; /* not a key position inside a row map */
|
|
498
|
+
}
|
|
499
|
+
/* the key: match against the plan leaves */
|
|
500
|
+
int col_idx = -1;
|
|
501
|
+
for (size_t c = 0; c < ncols; c++) {
|
|
502
|
+
if (tape->lens[i] == plan->cols[c].name_len &&
|
|
503
|
+
memcmp(src + tape->offs[i], plan->cols[c].name, plan->cols[c].name_len) == 0) {
|
|
504
|
+
col_idx = (int)c;
|
|
505
|
+
break;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
if (col_idx < 0) {
|
|
509
|
+
continue; /* not a planned leaf: skip its value below */
|
|
510
|
+
}
|
|
511
|
+
size_t v = i + 1;
|
|
512
|
+
if (v >= rows_close) {
|
|
513
|
+
break;
|
|
514
|
+
}
|
|
515
|
+
uint8_t vk = tape->kinds[v];
|
|
516
|
+
yep_result_col* col = &r->cols[col_idx];
|
|
517
|
+
switch (vk) {
|
|
518
|
+
case YEP_T_NULL:
|
|
519
|
+
break; /* stays null */
|
|
520
|
+
case YEP_T_TRUE:
|
|
521
|
+
case YEP_T_FALSE:
|
|
522
|
+
if (col->kind == YEP_PLAN_BOOL) {
|
|
523
|
+
col->ints[row] = vk == YEP_T_TRUE ? 1 : 0;
|
|
524
|
+
col->nulls[row] = 0;
|
|
525
|
+
} else if (col->kind == YEP_PLAN_STR) {
|
|
526
|
+
col->offs[row] = tape->offs[v];
|
|
527
|
+
col->lens[row] = tape->lens[v];
|
|
528
|
+
col->nulls[row] = 0;
|
|
529
|
+
}
|
|
530
|
+
break;
|
|
531
|
+
case YEP_T_STR:
|
|
532
|
+
if (col->kind == YEP_PLAN_STR) {
|
|
533
|
+
col->offs[row] = tape->offs[v];
|
|
534
|
+
col->lens[row] = tape->lens[v];
|
|
535
|
+
col->nulls[row] = 0;
|
|
536
|
+
}
|
|
537
|
+
break;
|
|
538
|
+
case YEP_T_INT:
|
|
539
|
+
case YEP_T_FLOAT:
|
|
540
|
+
case YEP_T_NUM: {
|
|
541
|
+
size_t j = 0;
|
|
542
|
+
int64_t iv = 0;
|
|
543
|
+
double dv = 0;
|
|
544
|
+
int shape = 0;
|
|
545
|
+
if (!yep_json_number_scan(src + tape->offs[v], tape->lens[v], &j, &shape, &iv, &dv) ||
|
|
546
|
+
j != tape->lens[v]) {
|
|
547
|
+
goto bad_row_value;
|
|
548
|
+
}
|
|
549
|
+
if (col->kind == YEP_PLAN_INT && shape == 0) {
|
|
550
|
+
col->ints[row] = iv;
|
|
551
|
+
col->nulls[row] = 0;
|
|
552
|
+
} else if (col->kind == YEP_PLAN_FLOAT) {
|
|
553
|
+
col->floats[row] = shape == 0 ? (double)iv : dv;
|
|
554
|
+
col->nulls[row] = 0;
|
|
555
|
+
} else if (col->kind == YEP_PLAN_STR) {
|
|
556
|
+
col->offs[row] = tape->offs[v];
|
|
557
|
+
col->lens[row] = tape->lens[v];
|
|
558
|
+
col->nulls[row] = 0;
|
|
559
|
+
}
|
|
560
|
+
break;
|
|
561
|
+
}
|
|
562
|
+
default:
|
|
563
|
+
/* container or mismatched scalar at a planned leaf: mark
|
|
564
|
+
* the row value unusable but keep walking */
|
|
565
|
+
break;
|
|
566
|
+
}
|
|
567
|
+
i = v; /* the value record is consumed */
|
|
568
|
+
continue;
|
|
569
|
+
bad_row_value:
|
|
570
|
+
i = v;
|
|
571
|
+
continue;
|
|
572
|
+
}
|
|
573
|
+
return r;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/* ---- the DOM leg (the YAML form of #293): the same compiled plan
|
|
577
|
+
* applied to a parsed yeptris document. Typed extraction rides the
|
|
578
|
+
* parse-time tag_id (the typing SSOT) plus the number kernels; str
|
|
579
|
+
* columns expose (ptr,len) views into the document's regions — the
|
|
580
|
+
* result borrows the document, free it first. ---- */
|
|
581
|
+
|
|
582
|
+
/* Follows alias chains to their target (bounded: a cycle fails). */
|
|
583
|
+
static const yep_dnode* dom_alias_final(const yep_dom* d, const yep_dnode* n) {
|
|
584
|
+
for (int hops = 0; n != NULL && n->kind == YEP_DOM_ALIAS; hops++) {
|
|
585
|
+
if (hops >= 64 || n->target == UINT32_MAX) {
|
|
586
|
+
return NULL;
|
|
587
|
+
}
|
|
588
|
+
n = yep_dom_node(d, n->target);
|
|
589
|
+
}
|
|
590
|
+
return n;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
/* The rows container: the root (no path), or the mapping reached by
|
|
594
|
+
* walking the path segments. NULL when the shape disagrees. */
|
|
595
|
+
static const yep_dnode* dom_find_rows(const yep_dom* d, const yep_dnode* root,
|
|
596
|
+
const yeptris_plan* plan) {
|
|
597
|
+
const yep_dnode* cur = dom_alias_final(d, root);
|
|
598
|
+
if (plan->nsegs == 0) {
|
|
599
|
+
return (cur != NULL && cur->kind == YEP_DOM_SEQUENCE) ? cur : NULL;
|
|
600
|
+
}
|
|
601
|
+
for (size_t s = 0; s < plan->nsegs; s++) {
|
|
602
|
+
if (cur == NULL || cur->kind != YEP_DOM_MAPPING) {
|
|
603
|
+
return NULL;
|
|
604
|
+
}
|
|
605
|
+
const char* seg = plan->path + plan->seg_off[s];
|
|
606
|
+
uint32_t seg_len = plan->seg_len[s];
|
|
607
|
+
const yep_dnode* hit = NULL;
|
|
608
|
+
uint32_t cn = cur->first_child;
|
|
609
|
+
while (cn != UINT32_MAX) {
|
|
610
|
+
const yep_dnode* k = yep_dom_node(d, cn);
|
|
611
|
+
const yep_dnode* v = yep_dom_node(d, k->next_sibling);
|
|
612
|
+
yep_view kv = sv_view(d, k->value);
|
|
613
|
+
if (k->kind == YEP_DOM_SCALAR && kv.len == seg_len && memcmp(kv.p, seg, seg_len) == 0) {
|
|
614
|
+
hit = dom_alias_final(d, v);
|
|
615
|
+
break;
|
|
616
|
+
}
|
|
617
|
+
cn = v->next_sibling;
|
|
618
|
+
}
|
|
619
|
+
if (hit == NULL) {
|
|
620
|
+
return NULL;
|
|
621
|
+
}
|
|
622
|
+
cur = hit;
|
|
623
|
+
}
|
|
624
|
+
if (cur == NULL || (cur->kind != YEP_DOM_SEQUENCE && cur->kind != YEP_DOM_MAPPING)) {
|
|
625
|
+
return NULL;
|
|
626
|
+
}
|
|
627
|
+
return cur;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/* One row iteration: a SEQUENCE container yields its mapping
|
|
631
|
+
* children, a MAPPING container its mapping values. Returns the
|
|
632
|
+
* next cursor (UINT32_MAX at the end); *out is the row (NULL when
|
|
633
|
+
* the child is not a mapping — callers skip it). */
|
|
634
|
+
static uint32_t dom_rows_next(const yep_dom* d, const yep_dnode* container, uint32_t cur,
|
|
635
|
+
const yep_dnode** out) {
|
|
636
|
+
*out = NULL;
|
|
637
|
+
if (cur == UINT32_MAX) {
|
|
638
|
+
return UINT32_MAX;
|
|
639
|
+
}
|
|
640
|
+
if (container->kind == YEP_DOM_SEQUENCE) {
|
|
641
|
+
const yep_dnode* self = yep_dom_node(d, cur);
|
|
642
|
+
const yep_dnode* child = dom_alias_final(d, self);
|
|
643
|
+
uint32_t next = self->next_sibling;
|
|
644
|
+
if (child != NULL && child->kind == YEP_DOM_MAPPING) {
|
|
645
|
+
*out = child;
|
|
646
|
+
}
|
|
647
|
+
return next;
|
|
648
|
+
}
|
|
649
|
+
/* mapping: pairs (key, value) — yield values */
|
|
650
|
+
const yep_dnode* k = yep_dom_node(d, cur);
|
|
651
|
+
const yep_dnode* v = yep_dom_node(d, k->next_sibling);
|
|
652
|
+
const yep_dnode* val = dom_alias_final(d, v);
|
|
653
|
+
if (val != NULL && val->kind == YEP_DOM_MAPPING) {
|
|
654
|
+
*out = val;
|
|
655
|
+
}
|
|
656
|
+
return v->next_sibling;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
YEPTRIS_API yeptris_plan_result*
|
|
660
|
+
yeptris_document_plan_walk(YeptrisDocument doc, const yeptris_plan* plan, YeptrisStatus* st) {
|
|
661
|
+
if (st != NULL) {
|
|
662
|
+
*st = YEPTRIS_OK;
|
|
663
|
+
}
|
|
664
|
+
const yep_dom* dd = doc == NULL ? NULL : yep_doc_dom((yeptris_document*)doc);
|
|
665
|
+
if (doc == NULL || plan == NULL || dd == NULL || dd->dcount == 0) {
|
|
666
|
+
if (st != NULL) {
|
|
667
|
+
*st = YEPTRIS_ERROR_ARG;
|
|
668
|
+
}
|
|
669
|
+
return NULL;
|
|
670
|
+
}
|
|
671
|
+
const yep_dnode* root = yep_dom_node(dd, dd->docs[0]);
|
|
672
|
+
const yep_dnode* container = dom_find_rows(dd, root, plan);
|
|
673
|
+
if (container == NULL) {
|
|
674
|
+
if (st != NULL) {
|
|
675
|
+
*st = YEPTRIS_ERROR_PARSE; /* document shape disagreement */
|
|
676
|
+
}
|
|
677
|
+
return NULL;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
size_t rows = 0;
|
|
681
|
+
for (uint32_t cur = container->first_child; cur != UINT32_MAX;) {
|
|
682
|
+
const yep_dnode* row;
|
|
683
|
+
cur = dom_rows_next(dd, container, cur, &row);
|
|
684
|
+
if (row != NULL) {
|
|
685
|
+
rows++;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
yeptris_plan_result* r = plan_result_carve(plan, rows, sizeof(yeptris_plan_str), st);
|
|
690
|
+
if (r == NULL) {
|
|
691
|
+
return NULL;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
size_t row_i = 0;
|
|
695
|
+
for (uint32_t cur = container->first_child; cur != UINT32_MAX && row_i < rows;) {
|
|
696
|
+
const yep_dnode* row;
|
|
697
|
+
cur = dom_rows_next(dd, container, cur, &row);
|
|
698
|
+
if (row == NULL) {
|
|
699
|
+
continue;
|
|
700
|
+
}
|
|
701
|
+
uint32_t cn = row->first_child;
|
|
702
|
+
while (cn != UINT32_MAX) {
|
|
703
|
+
const yep_dnode* k = yep_dom_node(dd, cn);
|
|
704
|
+
const yep_dnode* v = yep_dom_node(dd, k->next_sibling);
|
|
705
|
+
yep_view kv = sv_view(dd, k->value);
|
|
706
|
+
int col_idx = -1;
|
|
707
|
+
if (k->kind == YEP_DOM_SCALAR) {
|
|
708
|
+
for (size_t c = 0; c < plan->ncols; c++) {
|
|
709
|
+
if (kv.len == plan->cols[c].name_len &&
|
|
710
|
+
memcmp(kv.p, plan->cols[c].name, plan->cols[c].name_len) == 0) {
|
|
711
|
+
col_idx = (int)c;
|
|
712
|
+
break;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
if (col_idx >= 0) {
|
|
717
|
+
const yep_dnode* val = dom_alias_final(dd, v);
|
|
718
|
+
yep_result_col* col = &r->cols[col_idx];
|
|
719
|
+
if (val != NULL && val->kind == YEP_DOM_SCALAR && val->tag_id != YEPTRIS_TAG_NULL) {
|
|
720
|
+
yep_view sv = sv_view(dd, val->value);
|
|
721
|
+
int filled = 0;
|
|
722
|
+
switch (col->kind) {
|
|
723
|
+
case YEP_PLAN_STR:
|
|
724
|
+
col->views[row_i].p = sv.p;
|
|
725
|
+
col->views[row_i].len = sv.len;
|
|
726
|
+
filled = 1;
|
|
727
|
+
break;
|
|
728
|
+
case YEP_PLAN_INT: {
|
|
729
|
+
int64_t iv;
|
|
730
|
+
if (val->tag_id == YEPTRIS_TAG_INT && yep_num_i64(sv.p, sv.len, &iv) == 0) {
|
|
731
|
+
col->ints[row_i] = iv;
|
|
732
|
+
filled = 1;
|
|
733
|
+
}
|
|
734
|
+
break;
|
|
735
|
+
}
|
|
736
|
+
case YEP_PLAN_FLOAT: {
|
|
737
|
+
double dv;
|
|
738
|
+
if (val->tag_id == YEPTRIS_TAG_FLOAT) {
|
|
739
|
+
if (yep_num_f64(sv.p, sv.len, &dv) == 0) {
|
|
740
|
+
col->floats[row_i] = dv;
|
|
741
|
+
filled = 1;
|
|
742
|
+
}
|
|
743
|
+
} else if (val->tag_id == YEPTRIS_TAG_INT) {
|
|
744
|
+
int64_t iv;
|
|
745
|
+
if (yep_num_i64(sv.p, sv.len, &iv) == 0) {
|
|
746
|
+
col->floats[row_i] = (double)iv;
|
|
747
|
+
filled = 1;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
break;
|
|
751
|
+
}
|
|
752
|
+
case YEP_PLAN_BOOL:
|
|
753
|
+
if (val->tag_id == YEPTRIS_TAG_BOOL) {
|
|
754
|
+
col->ints[row_i] = yep_num_bool(sv.p, sv.len);
|
|
755
|
+
filled = 1;
|
|
756
|
+
}
|
|
757
|
+
break;
|
|
758
|
+
}
|
|
759
|
+
if (filled) {
|
|
760
|
+
col->nulls[row_i] = 0;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
/* null / missing / tag disagreement / a container at a
|
|
764
|
+
* planned leaf: the slot stays null, the walk goes on */
|
|
765
|
+
}
|
|
766
|
+
cn = v->next_sibling;
|
|
767
|
+
}
|
|
768
|
+
row_i++;
|
|
769
|
+
}
|
|
770
|
+
return r;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
YEPTRIS_API void yeptris_plan_result_free(yeptris_plan_result* r) {
|
|
774
|
+
if (r == NULL) {
|
|
775
|
+
return;
|
|
776
|
+
}
|
|
777
|
+
free(r->block);
|
|
778
|
+
free(r);
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
YEPTRIS_API size_t yeptris_plan_result_rows(const yeptris_plan_result* r) {
|
|
782
|
+
return r == NULL ? 0 : r->rows;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
YEPTRIS_API int yeptris_plan_result_kind(const yeptris_plan_result* r, size_t col) {
|
|
786
|
+
if (r == NULL || col >= r->ncols) {
|
|
787
|
+
return -1;
|
|
788
|
+
}
|
|
789
|
+
return r->cols[col].kind;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
#define YEP_RESULT_ARR(name, type) \
|
|
793
|
+
YEPTRIS_API const type* yeptris_plan_result_##name(const yeptris_plan_result* r, size_t col) { \
|
|
794
|
+
if (r == NULL || col >= r->ncols) { \
|
|
795
|
+
return NULL; \
|
|
796
|
+
} \
|
|
797
|
+
return r->cols[col].name; \
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
YEP_RESULT_ARR(ints, int64_t)
|
|
801
|
+
YEP_RESULT_ARR(floats, double)
|
|
802
|
+
YEP_RESULT_ARR(nulls, uint8_t)
|
|
803
|
+
|
|
804
|
+
YEPTRIS_API const uint32_t* yeptris_plan_result_str_offs(const yeptris_plan_result* r, size_t col) {
|
|
805
|
+
if (r == NULL || col >= r->ncols) {
|
|
806
|
+
return NULL;
|
|
807
|
+
}
|
|
808
|
+
return r->cols[col].offs;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
YEPTRIS_API const yeptris_plan_str* yeptris_plan_result_strs(const yeptris_plan_result* r,
|
|
812
|
+
size_t col) {
|
|
813
|
+
if (r == NULL || col >= r->ncols) {
|
|
814
|
+
return NULL;
|
|
815
|
+
}
|
|
816
|
+
return r->cols[col].views;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
YEPTRIS_API const uint32_t* yeptris_plan_result_str_lens(const yeptris_plan_result* r, size_t col) {
|
|
820
|
+
if (r == NULL || col >= r->ncols) {
|
|
821
|
+
return NULL;
|
|
822
|
+
}
|
|
823
|
+
return r->cols[col].lens;
|
|
824
|
+
}
|