teptris 0.2.37-arm-linux → 0.2.39-arm-linux
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 +4 -4
- data/ext/teptris_ext/engine/LICENSE.md +21 -0
- data/ext/teptris_ext/engine/src/include/teptris/plan.h +123 -0
- data/ext/teptris_ext/engine/src/include/teptris/teptris.h +208 -0
- data/ext/teptris_ext/engine/src/include/teptris/version.h +9 -0
- data/ext/teptris_ext/engine/src/teptris/api.c +362 -0
- data/ext/teptris_ext/engine/src/teptris/build.c +355 -0
- data/ext/teptris_ext/engine/src/teptris/common/chartype.c +70 -0
- data/ext/teptris_ext/engine/src/teptris/common/chartype.h +41 -0
- data/ext/teptris_ext/engine/src/teptris/common/ryu/common.h +114 -0
- data/ext/teptris_ext/engine/src/teptris/common/ryu/d2s.c +496 -0
- data/ext/teptris_ext/engine/src/teptris/common/ryu/d2s_full_table.h +367 -0
- data/ext/teptris_ext/engine/src/teptris/common/ryu/d2s_intrinsics.h +357 -0
- data/ext/teptris_ext/engine/src/teptris/common/ryu/digit_table.h +35 -0
- data/ext/teptris_ext/engine/src/teptris/common/ryu/ryu_d2s.h +39 -0
- data/ext/teptris_ext/engine/src/teptris/common/ryu/ryu_parse.h +45 -0
- data/ext/teptris_ext/engine/src/teptris/common/ryu/s2d.c +259 -0
- data/ext/teptris_ext/engine/src/teptris/common/simd.h +119 -0
- data/ext/teptris_ext/engine/src/teptris/dom/dom.c +192 -0
- data/ext/teptris_ext/engine/src/teptris/dom/dom.h +124 -0
- data/ext/teptris_ext/engine/src/teptris/emit/emitter.c +718 -0
- data/ext/teptris_ext/engine/src/teptris/emit/emitter.h +11 -0
- data/ext/teptris_ext/engine/src/teptris/memory/arena.c +104 -0
- data/ext/teptris_ext/engine/src/teptris/memory/arena.h +53 -0
- data/ext/teptris_ext/engine/src/teptris/parse/datetime.c +218 -0
- data/ext/teptris_ext/engine/src/teptris/parse/keys.c +121 -0
- data/ext/teptris_ext/engine/src/teptris/parse/parse.h +76 -0
- data/ext/teptris_ext/engine/src/teptris/parse/parser.c +931 -0
- data/ext/teptris_ext/engine/src/teptris/parse/scalars.c +940 -0
- data/ext/teptris_ext/engine/src/teptris/plan/plan.c +472 -0
- data/ext/teptris_ext/engine/src/teptris/version.c +6 -0
- data/ext/teptris_ext/extconf.rb +61 -0
- data/ext/teptris_ext/materialize.c +608 -0
- data/lib/teptris/version.rb +1 -1
- data/lib/teptris.rb +19 -11
- metadata +35 -3
- /data/lib/{teptris_ext.so → teptris/3.2/teptris_ext.so} +0 -0
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
/* Plan-walk materialization (teptris#46, mirroring leptris's v1
|
|
2
|
+
* descriptor ABI): compile a schema plan once, then materialize a
|
|
3
|
+
* whole TOML subtree against it in one native pass. Keys the plan
|
|
4
|
+
* does not describe are skipped — the read-once-and-drop fields the
|
|
5
|
+
* lutaml-model profile showed as GC pressure never materialize. */
|
|
6
|
+
#include <stdlib.h>
|
|
7
|
+
#include <string.h>
|
|
8
|
+
|
|
9
|
+
#include "teptris/dom/dom.h"
|
|
10
|
+
#include "teptris/plan.h"
|
|
11
|
+
|
|
12
|
+
typedef struct plan_row {
|
|
13
|
+
char *name; /* owned, NUL-terminated */
|
|
14
|
+
uint8_t kind;
|
|
15
|
+
uint32_t sub; /* sub-plan index for NESTED */
|
|
16
|
+
} plan_row;
|
|
17
|
+
|
|
18
|
+
struct teptris_plan {
|
|
19
|
+
uint32_t plan_count;
|
|
20
|
+
uint32_t *first_row; /* plan_count + 1 entries into rows */
|
|
21
|
+
plan_row *rows;
|
|
22
|
+
uint32_t row_total;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
typedef struct rnode rnode;
|
|
26
|
+
struct rnode {
|
|
27
|
+
uint8_t kind; /* teptris_plan_result_kind */
|
|
28
|
+
const teptris_node *src; /* document node for value access */
|
|
29
|
+
rnode **kids; /* ARRAY children / NESTED-of-array items */
|
|
30
|
+
rnode **entries; /* RAW table entries (value side) */
|
|
31
|
+
uint32_t n;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
struct teptris_plan_result {
|
|
35
|
+
const rnode *root;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/* ------------------------------------------------------------- build -- */
|
|
39
|
+
|
|
40
|
+
teptris_plan *teptris_plan_build(const teptris_plan_spec *spec,
|
|
41
|
+
teptris_status *status)
|
|
42
|
+
{
|
|
43
|
+
*status = TEPTRIS_ERR_ARG;
|
|
44
|
+
if (spec == NULL || spec->abi_version != TEPTRIS_PLAN_ABI_VERSION ||
|
|
45
|
+
spec->plan_count == 0 || spec->plans == NULL ||
|
|
46
|
+
spec->plan_first_row == NULL) {
|
|
47
|
+
return NULL;
|
|
48
|
+
}
|
|
49
|
+
teptris_plan *p = calloc(1, sizeof(*p));
|
|
50
|
+
if (p == NULL) {
|
|
51
|
+
*status = TEPTRIS_ERR_ALLOC;
|
|
52
|
+
return NULL;
|
|
53
|
+
}
|
|
54
|
+
p->plan_count = spec->plan_count;
|
|
55
|
+
p->row_total = spec->plan_first_row[spec->plan_count];
|
|
56
|
+
p->first_row =
|
|
57
|
+
malloc((spec->plan_count + 1) * sizeof(*p->first_row));
|
|
58
|
+
/* calloc, not malloc: a mid-loop rejection frees every row name,
|
|
59
|
+
* and uninitialized pointers must read as NULL (ASan caught this) */
|
|
60
|
+
p->rows = p->row_total
|
|
61
|
+
? calloc(p->row_total, sizeof(*p->rows))
|
|
62
|
+
: NULL;
|
|
63
|
+
if (p->first_row == NULL || (p->row_total > 0 && p->rows == NULL)) {
|
|
64
|
+
teptris_plan_free(p);
|
|
65
|
+
*status = TEPTRIS_ERR_ALLOC;
|
|
66
|
+
return NULL;
|
|
67
|
+
}
|
|
68
|
+
memcpy(p->first_row, spec->plan_first_row,
|
|
69
|
+
(spec->plan_count + 1) * sizeof(*p->first_row));
|
|
70
|
+
for (uint32_t i = 0; i < p->row_total; i++) {
|
|
71
|
+
const teptris_plan_row *r = &spec->plans[i];
|
|
72
|
+
if (r->name == NULL || r->name[0] == '\0' ||
|
|
73
|
+
r->kind < TEPTRIS_PLAN_SCALAR || r->kind > TEPTRIS_PLAN_RAW ||
|
|
74
|
+
(r->kind == TEPTRIS_PLAN_NESTED && r->sub >= spec->plan_count)) {
|
|
75
|
+
teptris_plan_free(p);
|
|
76
|
+
return NULL;
|
|
77
|
+
}
|
|
78
|
+
size_t nlen = strlen(r->name) + 1;
|
|
79
|
+
p->rows[i].name = malloc(nlen);
|
|
80
|
+
if (p->rows[i].name == NULL) {
|
|
81
|
+
teptris_plan_free(p);
|
|
82
|
+
*status = TEPTRIS_ERR_ALLOC;
|
|
83
|
+
return NULL;
|
|
84
|
+
}
|
|
85
|
+
memcpy(p->rows[i].name, r->name, nlen);
|
|
86
|
+
p->rows[i].kind = r->kind;
|
|
87
|
+
p->rows[i].sub = r->sub;
|
|
88
|
+
}
|
|
89
|
+
*status = TEPTRIS_OK;
|
|
90
|
+
return p;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
void teptris_plan_free(teptris_plan *plan)
|
|
94
|
+
{
|
|
95
|
+
if (plan == NULL) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
for (uint32_t i = 0; i < plan->row_total; i++) {
|
|
99
|
+
free(plan->rows[i].name);
|
|
100
|
+
}
|
|
101
|
+
free(plan->rows);
|
|
102
|
+
free(plan->first_row);
|
|
103
|
+
free(plan);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* -------------------------------------------------------------- walk -- */
|
|
107
|
+
|
|
108
|
+
static rnode *rnode_new(uint8_t kind, const teptris_node *src)
|
|
109
|
+
{
|
|
110
|
+
rnode *r = calloc(1, sizeof(*r));
|
|
111
|
+
if (r != NULL) {
|
|
112
|
+
r->kind = kind;
|
|
113
|
+
r->src = src;
|
|
114
|
+
}
|
|
115
|
+
return r;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
static void rnode_free(rnode *r)
|
|
119
|
+
{
|
|
120
|
+
if (r == NULL) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
for (uint32_t i = 0; i < r->n; i++) {
|
|
124
|
+
rnode_free(r->kids ? r->kids[i] : r->entries[i]);
|
|
125
|
+
}
|
|
126
|
+
free(r->kids);
|
|
127
|
+
free(r->entries);
|
|
128
|
+
free(r);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
static rnode *walk_table(const teptris_plan *p, uint32_t plan_idx,
|
|
132
|
+
const teptris_node *t);
|
|
133
|
+
|
|
134
|
+
static rnode *walk_value(const teptris_plan *p, const plan_row *row,
|
|
135
|
+
const teptris_node *v)
|
|
136
|
+
{
|
|
137
|
+
switch (row->kind) {
|
|
138
|
+
case TEPTRIS_PLAN_SCALAR:
|
|
139
|
+
if (v->kind == TEPTRIS_ARRAY || v->kind == TEPTRIS_TABLE) {
|
|
140
|
+
return rnode_new(TEPTRIS_PLAN_MISSING, NULL);
|
|
141
|
+
}
|
|
142
|
+
return rnode_new(TEPTRIS_PLAN_SCALAR, v);
|
|
143
|
+
case TEPTRIS_PLAN_COLLECTION: {
|
|
144
|
+
if (v->kind != TEPTRIS_ARRAY) {
|
|
145
|
+
return rnode_new(TEPTRIS_PLAN_MISSING, NULL);
|
|
146
|
+
}
|
|
147
|
+
rnode *arr = rnode_new(TEPTRIS_PLAN_ARRAY, v);
|
|
148
|
+
arr->n = (uint32_t)teptris_node_array_length(v);
|
|
149
|
+
if (arr->n > 0) {
|
|
150
|
+
arr->kids = calloc(arr->n, sizeof(rnode *));
|
|
151
|
+
}
|
|
152
|
+
for (uint32_t i = 0; i < arr->n; i++) {
|
|
153
|
+
const teptris_node *item = teptris_node_array_at(v, i);
|
|
154
|
+
if (item->kind == TEPTRIS_ARRAY || item->kind == TEPTRIS_TABLE) {
|
|
155
|
+
arr->kids[i] = rnode_new(TEPTRIS_PLAN_MISSING, NULL);
|
|
156
|
+
} else {
|
|
157
|
+
arr->kids[i] = rnode_new(TEPTRIS_PLAN_SCALAR, item);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return arr;
|
|
161
|
+
}
|
|
162
|
+
case TEPTRIS_PLAN_NESTED:
|
|
163
|
+
if (v->kind == TEPTRIS_TABLE) {
|
|
164
|
+
return walk_table(p, row->sub, v);
|
|
165
|
+
}
|
|
166
|
+
if (v->kind == TEPTRIS_ARRAY) { /* array of tables */
|
|
167
|
+
rnode *arr = rnode_new(TEPTRIS_PLAN_ARRAY, v);
|
|
168
|
+
arr->n = (uint32_t)teptris_node_array_length(v);
|
|
169
|
+
if (arr->n > 0) {
|
|
170
|
+
arr->kids = calloc(arr->n, sizeof(rnode *));
|
|
171
|
+
}
|
|
172
|
+
for (uint32_t i = 0; i < arr->n; i++) {
|
|
173
|
+
const teptris_node *item = teptris_node_array_at(v, i);
|
|
174
|
+
arr->kids[i] = item->kind == TEPTRIS_TABLE
|
|
175
|
+
? walk_table(p, row->sub, item)
|
|
176
|
+
: rnode_new(TEPTRIS_PLAN_MISSING, NULL);
|
|
177
|
+
}
|
|
178
|
+
return arr;
|
|
179
|
+
}
|
|
180
|
+
return rnode_new(TEPTRIS_PLAN_MISSING, NULL);
|
|
181
|
+
default: /* RAW: the full native subtree */
|
|
182
|
+
return rnode_new(TEPTRIS_PLAN_RAW, v);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
static rnode *walk_table(const teptris_plan *p, uint32_t plan_idx,
|
|
187
|
+
const teptris_node *t)
|
|
188
|
+
{
|
|
189
|
+
if (t == NULL || t->kind != TEPTRIS_TABLE) {
|
|
190
|
+
return rnode_new(TEPTRIS_PLAN_MISSING, NULL);
|
|
191
|
+
}
|
|
192
|
+
rnode *out = rnode_new(TEPTRIS_PLAN_TABLE, t);
|
|
193
|
+
uint32_t lo = p->first_row[plan_idx];
|
|
194
|
+
uint32_t hi = p->first_row[plan_idx + 1];
|
|
195
|
+
out->kids = hi > lo ? calloc(hi - lo, sizeof(rnode *)) : NULL;
|
|
196
|
+
for (uint32_t i = lo; i < hi; i++) {
|
|
197
|
+
const teptris_node *v =
|
|
198
|
+
teptris_node_table_get(t, p->rows[i].name, strlen(p->rows[i].name));
|
|
199
|
+
out->kids[out->n++] =
|
|
200
|
+
v != NULL ? walk_value(p, &p->rows[i], v)
|
|
201
|
+
: rnode_new(TEPTRIS_PLAN_MISSING, NULL);
|
|
202
|
+
}
|
|
203
|
+
return out;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
teptris_plan_result *teptris_plan_walk(const teptris_plan *plan,
|
|
207
|
+
const teptris_node *node,
|
|
208
|
+
teptris_status *status)
|
|
209
|
+
{
|
|
210
|
+
*status = TEPTRIS_ERR_ARG;
|
|
211
|
+
if (plan == NULL || node == NULL) {
|
|
212
|
+
return NULL;
|
|
213
|
+
}
|
|
214
|
+
teptris_plan_result *res = calloc(1, sizeof(*res));
|
|
215
|
+
if (res == NULL) {
|
|
216
|
+
*status = TEPTRIS_ERR_ALLOC;
|
|
217
|
+
return NULL;
|
|
218
|
+
}
|
|
219
|
+
res->root = walk_table(plan, 0, node);
|
|
220
|
+
if (res->root == NULL) {
|
|
221
|
+
free(res);
|
|
222
|
+
*status = TEPTRIS_ERR_ALLOC;
|
|
223
|
+
return NULL;
|
|
224
|
+
}
|
|
225
|
+
*status = TEPTRIS_OK;
|
|
226
|
+
return res;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
void teptris_plan_result_free(teptris_plan_result *result)
|
|
230
|
+
{
|
|
231
|
+
if (result != NULL) {
|
|
232
|
+
/* sole owner: reclaim the const view to destroy the tree */
|
|
233
|
+
rnode_free((rnode *)result->root);
|
|
234
|
+
free(result);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/* ---------------------------------------------------------- accessors -- */
|
|
239
|
+
|
|
240
|
+
static const rnode *child_of(const teptris_plan_result *r, uint32_t i)
|
|
241
|
+
{
|
|
242
|
+
const rnode *root = r->root;
|
|
243
|
+
if (root->kind != TEPTRIS_PLAN_TABLE || i >= root->n) {
|
|
244
|
+
return NULL;
|
|
245
|
+
}
|
|
246
|
+
return root->kids[i];
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
uint8_t teptris_plan_result_kind_at(const teptris_plan_result *r, uint32_t row)
|
|
250
|
+
{
|
|
251
|
+
const rnode *c = child_of(r, row);
|
|
252
|
+
return c != NULL ? c->kind : TEPTRIS_PLAN_MISSING;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
uint8_t teptris_plan_result_value_kind_at(const teptris_plan_result *r,
|
|
256
|
+
uint32_t row)
|
|
257
|
+
{
|
|
258
|
+
const rnode *c = child_of(r, row);
|
|
259
|
+
return (c != NULL && c->src != NULL) ? teptris_node_kind(c->src)
|
|
260
|
+
: (uint8_t)TEPTRIS_STRING;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
#define SCALAR_AT(fn, field, out_type) \
|
|
264
|
+
teptris_status fn(const teptris_plan_result *r, uint32_t row, out_type o) \
|
|
265
|
+
{ \
|
|
266
|
+
const rnode *c = child_of(r, row); \
|
|
267
|
+
if (c == NULL || c->kind != TEPTRIS_PLAN_SCALAR) { \
|
|
268
|
+
return TEPTRIS_ERR_ARG; \
|
|
269
|
+
} \
|
|
270
|
+
return teptris_node_##field(c->src, o); \
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
SCALAR_AT(teptris_plan_result_string_at, string, teptris_view *)
|
|
274
|
+
SCALAR_AT(teptris_plan_result_integer_at, integer, int64_t *)
|
|
275
|
+
SCALAR_AT(teptris_plan_result_float_at, float, double *)
|
|
276
|
+
SCALAR_AT(teptris_plan_result_boolean_at, boolean, bool *)
|
|
277
|
+
SCALAR_AT(teptris_plan_result_datetime_at, datetime, teptris_datetime *)
|
|
278
|
+
|
|
279
|
+
uint32_t teptris_plan_result_array_len_at(const teptris_plan_result *r,
|
|
280
|
+
uint32_t row)
|
|
281
|
+
{
|
|
282
|
+
const rnode *c = child_of(r, row);
|
|
283
|
+
return (c != NULL && c->kind == TEPTRIS_PLAN_ARRAY) ? c->n : 0;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
uint8_t teptris_plan_result_array_kind_at(const teptris_plan_result *r,
|
|
287
|
+
uint32_t row, uint32_t i)
|
|
288
|
+
{
|
|
289
|
+
const rnode *c = child_of(r, row);
|
|
290
|
+
if (c == NULL || c->kind != TEPTRIS_PLAN_ARRAY || i >= c->n) {
|
|
291
|
+
return TEPTRIS_PLAN_MISSING;
|
|
292
|
+
}
|
|
293
|
+
return c->kids[i]->kind;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/* The TOML value kind of an ARRAY element (drives scalar dispatch). */
|
|
297
|
+
uint8_t teptris_plan_result_array_value_kind_at(const teptris_plan_result *r,
|
|
298
|
+
uint32_t row, uint32_t i)
|
|
299
|
+
{
|
|
300
|
+
const rnode *c = child_of(r, row);
|
|
301
|
+
if (c == NULL || c->kind != TEPTRIS_PLAN_ARRAY || i >= c->n) {
|
|
302
|
+
return (uint8_t)TEPTRIS_STRING;
|
|
303
|
+
}
|
|
304
|
+
const rnode *k = c->kids[i];
|
|
305
|
+
return (k->kind == TEPTRIS_PLAN_SCALAR && k->src != NULL)
|
|
306
|
+
? (uint8_t)teptris_node_kind(k->src)
|
|
307
|
+
: (uint8_t)TEPTRIS_STRING;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
teptris_status teptris_plan_result_array_string_at(const teptris_plan_result *r,
|
|
311
|
+
uint32_t row, uint32_t i,
|
|
312
|
+
teptris_view *out)
|
|
313
|
+
{
|
|
314
|
+
const rnode *c = child_of(r, row);
|
|
315
|
+
if (c == NULL || c->kind != TEPTRIS_PLAN_ARRAY || i >= c->n) {
|
|
316
|
+
return TEPTRIS_ERR_ARG;
|
|
317
|
+
}
|
|
318
|
+
const rnode *k = c->kids[i];
|
|
319
|
+
if (k->kind != TEPTRIS_PLAN_SCALAR) {
|
|
320
|
+
return TEPTRIS_ERR_ARG;
|
|
321
|
+
}
|
|
322
|
+
return teptris_node_string(k->src, out);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
teptris_status teptris_plan_result_array_integer_at(const teptris_plan_result *r,
|
|
326
|
+
uint32_t row, uint32_t i,
|
|
327
|
+
int64_t *out)
|
|
328
|
+
{
|
|
329
|
+
const rnode *c = child_of(r, row);
|
|
330
|
+
if (c == NULL || c->kind != TEPTRIS_PLAN_ARRAY || i >= c->n) {
|
|
331
|
+
return TEPTRIS_ERR_ARG;
|
|
332
|
+
}
|
|
333
|
+
const rnode *k = c->kids[i];
|
|
334
|
+
if (k->kind != TEPTRIS_PLAN_SCALAR) {
|
|
335
|
+
return TEPTRIS_ERR_ARG;
|
|
336
|
+
}
|
|
337
|
+
return teptris_node_integer(k->src, out);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/* Borrowed sub-result: navigates an ARRAY element (e.g. a table from
|
|
341
|
+
* an array-of-tables) so its plan rows stay addressable. Shares the
|
|
342
|
+
* parent's lifetime — do not free. */
|
|
343
|
+
/* Borrowed sub-result for a TABLE-kind row (a NESTED row's walked
|
|
344
|
+
* subtree): its plan rows stay addressable. Same lifetime rules as
|
|
345
|
+
* array_entry_at. */
|
|
346
|
+
teptris_plan_result *teptris_plan_result_row_view(const teptris_plan_result *r,
|
|
347
|
+
uint32_t row)
|
|
348
|
+
{
|
|
349
|
+
const rnode *c = child_of(r, row);
|
|
350
|
+
if (c == NULL || c->kind != TEPTRIS_PLAN_TABLE) {
|
|
351
|
+
return NULL;
|
|
352
|
+
}
|
|
353
|
+
teptris_plan_result *view = malloc(sizeof(*view));
|
|
354
|
+
if (view != NULL) {
|
|
355
|
+
view->root = c;
|
|
356
|
+
}
|
|
357
|
+
return view;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
teptris_status teptris_plan_result_array_float_at(const teptris_plan_result *r,
|
|
361
|
+
uint32_t row, uint32_t i,
|
|
362
|
+
double *out)
|
|
363
|
+
{
|
|
364
|
+
const rnode *c = child_of(r, row);
|
|
365
|
+
if (c == NULL || c->kind != TEPTRIS_PLAN_ARRAY || i >= c->n) {
|
|
366
|
+
return TEPTRIS_ERR_ARG;
|
|
367
|
+
}
|
|
368
|
+
const rnode *k = c->kids[i];
|
|
369
|
+
if (k->kind != TEPTRIS_PLAN_SCALAR) {
|
|
370
|
+
return TEPTRIS_ERR_ARG;
|
|
371
|
+
}
|
|
372
|
+
return teptris_node_float(k->src, out);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
teptris_status teptris_plan_result_array_boolean_at(
|
|
376
|
+
const teptris_plan_result *r, uint32_t row, uint32_t i, bool *out)
|
|
377
|
+
{
|
|
378
|
+
const rnode *c = child_of(r, row);
|
|
379
|
+
if (c == NULL || c->kind != TEPTRIS_PLAN_ARRAY || i >= c->n) {
|
|
380
|
+
return TEPTRIS_ERR_ARG;
|
|
381
|
+
}
|
|
382
|
+
const rnode *k = c->kids[i];
|
|
383
|
+
if (k->kind != TEPTRIS_PLAN_SCALAR) {
|
|
384
|
+
return TEPTRIS_ERR_ARG;
|
|
385
|
+
}
|
|
386
|
+
return teptris_node_boolean(k->src, out);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
teptris_status teptris_plan_result_array_datetime_at(
|
|
390
|
+
const teptris_plan_result *r, uint32_t row, uint32_t i,
|
|
391
|
+
teptris_datetime *out)
|
|
392
|
+
{
|
|
393
|
+
const rnode *c = child_of(r, row);
|
|
394
|
+
if (c == NULL || c->kind != TEPTRIS_PLAN_ARRAY || i >= c->n) {
|
|
395
|
+
return TEPTRIS_ERR_ARG;
|
|
396
|
+
}
|
|
397
|
+
const rnode *k = c->kids[i];
|
|
398
|
+
if (k->kind != TEPTRIS_PLAN_SCALAR) {
|
|
399
|
+
return TEPTRIS_ERR_ARG;
|
|
400
|
+
}
|
|
401
|
+
return teptris_node_datetime(k->src, out);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
uint8_t teptris_plan_row_kind_at(const teptris_plan *p, uint32_t plan_idx,
|
|
405
|
+
uint32_t row)
|
|
406
|
+
{
|
|
407
|
+
uint32_t lo = p->first_row[plan_idx];
|
|
408
|
+
if (plan_idx >= p->plan_count || row >= p->first_row[plan_idx + 1] - lo) {
|
|
409
|
+
return 0;
|
|
410
|
+
}
|
|
411
|
+
return p->rows[lo + row].kind;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
uint32_t teptris_plan_row_sub_at(const teptris_plan *p, uint32_t plan_idx,
|
|
415
|
+
uint32_t row)
|
|
416
|
+
{
|
|
417
|
+
uint32_t lo = p->first_row[plan_idx];
|
|
418
|
+
if (plan_idx >= p->plan_count || row >= p->first_row[plan_idx + 1] - lo) {
|
|
419
|
+
return 0;
|
|
420
|
+
}
|
|
421
|
+
return p->rows[lo + row].sub;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
const char *teptris_plan_row_name_at(const teptris_plan *p, uint32_t plan_idx,
|
|
425
|
+
uint32_t row)
|
|
426
|
+
{
|
|
427
|
+
uint32_t lo = p->first_row[plan_idx];
|
|
428
|
+
if (plan_idx >= p->plan_count || row >= p->first_row[plan_idx + 1] - lo) {
|
|
429
|
+
return NULL;
|
|
430
|
+
}
|
|
431
|
+
return p->rows[lo + row].name;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
teptris_plan_result *teptris_plan_result_array_entry_at(
|
|
435
|
+
const teptris_plan_result *r, uint32_t row, uint32_t i)
|
|
436
|
+
{
|
|
437
|
+
const rnode *c = child_of(r, row);
|
|
438
|
+
if (c == NULL || c->kind != TEPTRIS_PLAN_ARRAY || i >= c->n) {
|
|
439
|
+
return NULL;
|
|
440
|
+
}
|
|
441
|
+
teptris_plan_result *view = malloc(sizeof(*view));
|
|
442
|
+
if (view != NULL) {
|
|
443
|
+
view->root = c->kids[i];
|
|
444
|
+
}
|
|
445
|
+
return view;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
void teptris_plan_result_view_free(teptris_plan_result *view)
|
|
449
|
+
{
|
|
450
|
+
/* the view's tree is owned by the parent result */
|
|
451
|
+
free(view);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
const teptris_node *teptris_plan_result_raw_at(const teptris_plan_result *r,
|
|
455
|
+
uint32_t row)
|
|
456
|
+
{
|
|
457
|
+
const rnode *c = child_of(r, row);
|
|
458
|
+
return (c != NULL && c->kind == TEPTRIS_PLAN_RAW) ? c->src : NULL;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
uint32_t teptris_plan_row_count(const teptris_plan *plan, uint32_t plan_idx)
|
|
462
|
+
{
|
|
463
|
+
if (plan == NULL || plan_idx >= plan->plan_count) {
|
|
464
|
+
return 0;
|
|
465
|
+
}
|
|
466
|
+
return plan->first_row[plan_idx + 1] - plan->first_row[plan_idx];
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
uint32_t teptris_plan_abi_version(void)
|
|
470
|
+
{
|
|
471
|
+
return TEPTRIS_PLAN_ABI_VERSION;
|
|
472
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
require "mkmf"
|
|
2
|
+
|
|
3
|
+
# Two modes:
|
|
4
|
+
# - archive mode (precompiled platform gems): --with-teptris-libdir
|
|
5
|
+
# points at the cmake-built static archive; everything else links
|
|
6
|
+
# from it. One self-contained teptris_ext artifact per platform, no
|
|
7
|
+
# soname/rpath/dylib-chain distribution to get wrong (issue #38 —
|
|
8
|
+
# 0.2.17's linux/mingw gems shipped the ext without the
|
|
9
|
+
# libteptris.so.0 soname it linked).
|
|
10
|
+
# - source mode (the ruby-platform gem): the engine tree is vendored
|
|
11
|
+
# at engine/ and mkmf compiles it together with the ext — no cmake,
|
|
12
|
+
# no archive. The ext is still mandatory: a platform without a C
|
|
13
|
+
# toolchain fails the install instead of silently degrading.
|
|
14
|
+
eng = File.expand_path("engine", __dir__)
|
|
15
|
+
archive_mode = !File.file?(File.join(eng, "src/include/teptris/teptris.h"))
|
|
16
|
+
if archive_mode
|
|
17
|
+
libdir = with_config("teptris-libdir") || ENV["TEPTRIS_LIBDIR"] ||
|
|
18
|
+
File.dirname(ENV["TEPTRIS_LIB_PATH"].to_s)
|
|
19
|
+
archive = Dir.glob("#{libdir}/libteptris*.a").first
|
|
20
|
+
abort "libteptris static archive not found under #{libdir}" unless archive
|
|
21
|
+
inc = with_config("teptris-include") || ENV["TEPTRIS_INCLUDE"] ||
|
|
22
|
+
File.expand_path("../../../teptris/src/include", __dir__)
|
|
23
|
+
abort "teptris headers not found (#{inc})" unless File.file?(File.join(inc, "teptris/teptris.h"))
|
|
24
|
+
$INCFLAGS << " -I#{inc}"
|
|
25
|
+
else
|
|
26
|
+
$INCFLAGS << " -I#{eng}/src -I#{eng}/src/include"
|
|
27
|
+
$srcs = ["materialize.c"] + Dir["engine/src/teptris/**/*.c"].sort
|
|
28
|
+
# link rule must carry the subdir paths (mkmf flattens $objs to
|
|
29
|
+
# basenames, which breaks once sources live below the ext root)
|
|
30
|
+
$objs = $srcs.map { |s| s.sub(/\.c\z/, ".o") }
|
|
31
|
+
end
|
|
32
|
+
# On ELF/Mach-O, ruby symbols resolve from the running Ruby process
|
|
33
|
+
# (macOS: dynamic_lookup; ELF shared objects allow undefined syms).
|
|
34
|
+
# On Windows the .so MUST link the ruby DLL import lib — symbols do
|
|
35
|
+
# not resolve at load otherwise.
|
|
36
|
+
win = RUBY_PLATFORM =~ /mingw/
|
|
37
|
+
unless win
|
|
38
|
+
$LIBS = $LIBS.sub("-lruby", "")
|
|
39
|
+
end
|
|
40
|
+
if RUBY_PLATFORM =~ /darwin/
|
|
41
|
+
$DLDFLAGS << " -Wl,-undefined,dynamic_lookup"
|
|
42
|
+
end
|
|
43
|
+
if archive_mode
|
|
44
|
+
# Link the whole archive: every teptris symbol lands inside the ext.
|
|
45
|
+
$LDFLAGS << " #{archive}"
|
|
46
|
+
end
|
|
47
|
+
create_makefile "teptris_ext"
|
|
48
|
+
|
|
49
|
+
# mkmf buries the absolute builder libruby path in librubyarg_shared;
|
|
50
|
+
# blank the variable DEFINITIONS in the generated Makefile so any
|
|
51
|
+
# spelling dies — Ruby symbols come from the running process
|
|
52
|
+
# (dynamic_lookup on macOS, undefined-allowed on ELF). Not on Windows:
|
|
53
|
+
# the import-lib link binds the ruby DLL by name.
|
|
54
|
+
unless win
|
|
55
|
+
makefile = File.read("Makefile")
|
|
56
|
+
makefile.gsub!(/^LIBRUBYARG_SHARED = .*$/, "LIBRUBYARG_SHARED =")
|
|
57
|
+
makefile.gsub!(/^LIBRUBYARG_STATIC = .*$/, "LIBRUBYARG_STATIC =")
|
|
58
|
+
makefile.gsub!(/^LIBRUBY = .*$/, "LIBRUBY =")
|
|
59
|
+
makefile.gsub!(/(^|\s)\S*libruby[\w.\/-]*/, "")
|
|
60
|
+
File.write("Makefile", makefile)
|
|
61
|
+
end
|