tranfi 0.0.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +395 -0
- package/app/assets/index-6quYZ5Ap.css +5 -0
- package/app/assets/index-pDFMluyz.js +160 -0
- package/app/assets/materialdesignicons-webfont-B7mPwVP_.ttf +0 -0
- package/app/assets/materialdesignicons-webfont-CSr8KVlo.eot +0 -0
- package/app/assets/materialdesignicons-webfont-Dp5v-WZN.woff2 +0 -0
- package/app/assets/materialdesignicons-webfont-PXm3-2wK.woff +0 -0
- package/app/index.html +13 -0
- package/binding.gyp +69 -0
- package/csrc/arena.c +91 -0
- package/csrc/batch.c +229 -0
- package/csrc/buffer.c +78 -0
- package/csrc/cJSON.c +3143 -0
- package/csrc/cJSON.h +300 -0
- package/csrc/codec_csv.c +1058 -0
- package/csrc/codec_jsonl.c +374 -0
- package/csrc/codec_table.c +218 -0
- package/csrc/codec_text.c +229 -0
- package/csrc/compiler.c +102 -0
- package/csrc/date_utils.h +94 -0
- package/csrc/dsl.c +1180 -0
- package/csrc/dsl.h +22 -0
- package/csrc/expr.c +1245 -0
- package/csrc/expr.h +56 -0
- package/csrc/internal.h +250 -0
- package/csrc/ir.c +119 -0
- package/csrc/ir.h +167 -0
- package/csrc/ir_schema.c +60 -0
- package/csrc/ir_serialize.c +104 -0
- package/csrc/ir_sql.c +1211 -0
- package/csrc/ir_validate.c +120 -0
- package/csrc/main.c +392 -0
- package/csrc/op_acf.c +133 -0
- package/csrc/op_anomaly.c +120 -0
- package/csrc/op_bin.c +109 -0
- package/csrc/op_cast.c +195 -0
- package/csrc/op_clip.c +88 -0
- package/csrc/op_date_trunc.c +181 -0
- package/csrc/op_datetime.c +212 -0
- package/csrc/op_derive.c +248 -0
- package/csrc/op_diff.c +134 -0
- package/csrc/op_ewma.c +103 -0
- package/csrc/op_explode.c +108 -0
- package/csrc/op_fill_down.c +163 -0
- package/csrc/op_fill_null.c +123 -0
- package/csrc/op_filter.c +132 -0
- package/csrc/op_frequency.c +193 -0
- package/csrc/op_grep.c +163 -0
- package/csrc/op_group_agg.c +285 -0
- package/csrc/op_hash.c +126 -0
- package/csrc/op_head.c +149 -0
- package/csrc/op_interpolate.c +239 -0
- package/csrc/op_join.c +384 -0
- package/csrc/op_label_encode.c +144 -0
- package/csrc/op_lead.c +190 -0
- package/csrc/op_normalize.c +226 -0
- package/csrc/op_onehot.c +185 -0
- package/csrc/op_pivot.c +370 -0
- package/csrc/op_registry.c +1148 -0
- package/csrc/op_rename.c +138 -0
- package/csrc/op_replace.c +202 -0
- package/csrc/op_sample.c +101 -0
- package/csrc/op_select.c +140 -0
- package/csrc/op_skip.c +152 -0
- package/csrc/op_sort.c +273 -0
- package/csrc/op_split.c +114 -0
- package/csrc/op_split_data.c +87 -0
- package/csrc/op_stack.c +315 -0
- package/csrc/op_stats.c +779 -0
- package/csrc/op_step.c +171 -0
- package/csrc/op_tail.c +96 -0
- package/csrc/op_top.c +150 -0
- package/csrc/op_trim.c +109 -0
- package/csrc/op_unique.c +300 -0
- package/csrc/op_unpivot.c +159 -0
- package/csrc/op_validate.c +71 -0
- package/csrc/op_window.c +150 -0
- package/csrc/pipeline.c +315 -0
- package/csrc/plan.c +206 -0
- package/csrc/recipes.c +102 -0
- package/csrc/recipes.h +27 -0
- package/csrc/report.c +463 -0
- package/csrc/report.h +22 -0
- package/csrc/tranfi.h +123 -0
- package/csrc/wasm_api.c +157 -0
- package/napi_api.c +326 -0
- package/package.json +46 -57
- package/src/cli.js +193 -0
- package/src/engines/duckdb.js +109 -0
- package/src/index.js +306 -0
- package/src/native.js +22 -0
- package/src/pipeline.js +286 -0
- package/src/server.js +277 -0
- package/src/wasm.js +19 -0
- package/wasm/index.js +244 -0
- package/wasm/package.json +1 -0
- package/wasm/tranfi_core.js +0 -0
- package/LICENSE +0 -21
- package/dist/bundle.js +0 -1
- package/index.html +0 -18
- package/logo.png +0 -0
- package/src/app.css +0 -160
- package/src/app.js +0 -203
- package/src/app.vue +0 -253
- package/src/bulma-input.vue +0 -110
- package/src/common-inputs.js +0 -28
- package/src/main.js +0 -18
- package/src/transforms.js +0 -166
- package/webpack.config.js +0 -108
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/app/index.html
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Tranfi</title>
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-pDFMluyz.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/assets/index-6quYZ5Ap.css">
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div id="app"></div>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
package/binding.gyp
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"targets": [
|
|
3
|
+
{
|
|
4
|
+
"target_name": "tranfi_napi",
|
|
5
|
+
"sources": [
|
|
6
|
+
"napi_api.c",
|
|
7
|
+
"csrc/cJSON.c",
|
|
8
|
+
"csrc/arena.c",
|
|
9
|
+
"csrc/buffer.c",
|
|
10
|
+
"csrc/batch.c",
|
|
11
|
+
"csrc/pipeline.c",
|
|
12
|
+
"csrc/plan.c",
|
|
13
|
+
"csrc/expr.c",
|
|
14
|
+
"csrc/codec_csv.c",
|
|
15
|
+
"csrc/codec_jsonl.c",
|
|
16
|
+
"csrc/codec_text.c",
|
|
17
|
+
"csrc/codec_table.c",
|
|
18
|
+
"csrc/op_filter.c",
|
|
19
|
+
"csrc/op_select.c",
|
|
20
|
+
"csrc/op_rename.c",
|
|
21
|
+
"csrc/op_head.c",
|
|
22
|
+
"csrc/op_skip.c",
|
|
23
|
+
"csrc/op_derive.c",
|
|
24
|
+
"csrc/op_stats.c",
|
|
25
|
+
"csrc/op_unique.c",
|
|
26
|
+
"csrc/op_sort.c",
|
|
27
|
+
"csrc/op_validate.c",
|
|
28
|
+
"csrc/op_trim.c",
|
|
29
|
+
"csrc/op_fill_null.c",
|
|
30
|
+
"csrc/op_cast.c",
|
|
31
|
+
"csrc/op_clip.c",
|
|
32
|
+
"csrc/op_replace.c",
|
|
33
|
+
"csrc/op_hash.c",
|
|
34
|
+
"csrc/op_bin.c",
|
|
35
|
+
"csrc/op_fill_down.c",
|
|
36
|
+
"csrc/op_step.c",
|
|
37
|
+
"csrc/op_window.c",
|
|
38
|
+
"csrc/op_explode.c",
|
|
39
|
+
"csrc/op_split.c",
|
|
40
|
+
"csrc/op_unpivot.c",
|
|
41
|
+
"csrc/op_tail.c",
|
|
42
|
+
"csrc/op_top.c",
|
|
43
|
+
"csrc/op_sample.c",
|
|
44
|
+
"csrc/op_group_agg.c",
|
|
45
|
+
"csrc/op_frequency.c",
|
|
46
|
+
"csrc/op_datetime.c",
|
|
47
|
+
"csrc/op_grep.c",
|
|
48
|
+
"csrc/op_pivot.c",
|
|
49
|
+
"csrc/op_join.c",
|
|
50
|
+
"csrc/op_stack.c",
|
|
51
|
+
"csrc/op_lead.c",
|
|
52
|
+
"csrc/op_date_trunc.c",
|
|
53
|
+
"csrc/ir.c",
|
|
54
|
+
"csrc/ir_serialize.c",
|
|
55
|
+
"csrc/ir_sql.c",
|
|
56
|
+
"csrc/ir_validate.c",
|
|
57
|
+
"csrc/ir_schema.c",
|
|
58
|
+
"csrc/op_registry.c",
|
|
59
|
+
"csrc/compiler.c",
|
|
60
|
+
"csrc/dsl.c",
|
|
61
|
+
"csrc/recipes.c"
|
|
62
|
+
],
|
|
63
|
+
"include_dirs": [
|
|
64
|
+
"csrc"
|
|
65
|
+
],
|
|
66
|
+
"cflags": ["-std=c11", "-Wall", "-D_POSIX_C_SOURCE=200809L"]
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
}
|
package/csrc/arena.c
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* arena.c — Simple arena (bump) allocator.
|
|
3
|
+
* Allocates from fixed-size blocks, grows by adding new blocks.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
#include "internal.h"
|
|
7
|
+
#include <stdlib.h>
|
|
8
|
+
#include <string.h>
|
|
9
|
+
|
|
10
|
+
#define DEFAULT_BLOCK_SIZE (64 * 1024) /* 64 KB */
|
|
11
|
+
#define ALIGN_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
|
12
|
+
|
|
13
|
+
static tf_arena_block *block_create(size_t cap) {
|
|
14
|
+
tf_arena_block *blk = malloc(sizeof(tf_arena_block));
|
|
15
|
+
if (!blk) return NULL;
|
|
16
|
+
blk->data = malloc(cap);
|
|
17
|
+
if (!blk->data) { free(blk); return NULL; }
|
|
18
|
+
blk->used = 0;
|
|
19
|
+
blk->cap = cap;
|
|
20
|
+
blk->next = NULL;
|
|
21
|
+
return blk;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static void block_free(tf_arena_block *blk) {
|
|
25
|
+
while (blk) {
|
|
26
|
+
tf_arena_block *next = blk->next;
|
|
27
|
+
free(blk->data);
|
|
28
|
+
free(blk);
|
|
29
|
+
blk = next;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
tf_arena *tf_arena_create(size_t block_size) {
|
|
34
|
+
if (block_size == 0) block_size = DEFAULT_BLOCK_SIZE;
|
|
35
|
+
tf_arena *a = malloc(sizeof(tf_arena));
|
|
36
|
+
if (!a) return NULL;
|
|
37
|
+
a->block_size = block_size;
|
|
38
|
+
a->head = block_create(block_size);
|
|
39
|
+
if (!a->head) { free(a); return NULL; }
|
|
40
|
+
a->current = a->head;
|
|
41
|
+
return a;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
void *tf_arena_alloc(tf_arena *a, size_t size) {
|
|
45
|
+
if (!a || size == 0) return NULL;
|
|
46
|
+
size = ALIGN_UP(size, 8);
|
|
47
|
+
|
|
48
|
+
/* Try current block */
|
|
49
|
+
if (a->current->used + size <= a->current->cap) {
|
|
50
|
+
void *ptr = a->current->data + a->current->used;
|
|
51
|
+
a->current->used += size;
|
|
52
|
+
return ptr;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* Need a new block — at least big enough for this allocation */
|
|
56
|
+
size_t new_cap = a->block_size;
|
|
57
|
+
if (new_cap < size) new_cap = size;
|
|
58
|
+
tf_arena_block *blk = block_create(new_cap);
|
|
59
|
+
if (!blk) return NULL;
|
|
60
|
+
|
|
61
|
+
a->current->next = blk;
|
|
62
|
+
a->current = blk;
|
|
63
|
+
void *ptr = blk->data;
|
|
64
|
+
blk->used = size;
|
|
65
|
+
return ptr;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
char *tf_arena_strdup(tf_arena *a, const char *s) {
|
|
69
|
+
if (!s) return NULL;
|
|
70
|
+
size_t len = strlen(s) + 1;
|
|
71
|
+
char *copy = tf_arena_alloc(a, len);
|
|
72
|
+
if (copy) memcpy(copy, s, len);
|
|
73
|
+
return copy;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
void tf_arena_reset(tf_arena *a) {
|
|
77
|
+
if (!a) return;
|
|
78
|
+
/* Free all blocks except the first, reset the first */
|
|
79
|
+
if (a->head->next) {
|
|
80
|
+
block_free(a->head->next);
|
|
81
|
+
a->head->next = NULL;
|
|
82
|
+
}
|
|
83
|
+
a->head->used = 0;
|
|
84
|
+
a->current = a->head;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
void tf_arena_free(tf_arena *a) {
|
|
88
|
+
if (!a) return;
|
|
89
|
+
block_free(a->head);
|
|
90
|
+
free(a);
|
|
91
|
+
}
|
package/csrc/batch.c
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* batch.c — Columnar batch: typed columns with per-cell null tracking.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
#include "internal.h"
|
|
6
|
+
#include <stdlib.h>
|
|
7
|
+
#include <string.h>
|
|
8
|
+
|
|
9
|
+
static size_t type_size(tf_type t) {
|
|
10
|
+
switch (t) {
|
|
11
|
+
case TF_TYPE_BOOL: return sizeof(uint8_t);
|
|
12
|
+
case TF_TYPE_INT64: return sizeof(int64_t);
|
|
13
|
+
case TF_TYPE_FLOAT64: return sizeof(double);
|
|
14
|
+
case TF_TYPE_STRING: return sizeof(char *);
|
|
15
|
+
case TF_TYPE_DATE: return sizeof(int32_t);
|
|
16
|
+
case TF_TYPE_TIMESTAMP: return sizeof(int64_t);
|
|
17
|
+
default: return 0;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
tf_batch *tf_batch_create(size_t n_cols, size_t capacity) {
|
|
22
|
+
tf_arena *arena = tf_arena_create(0);
|
|
23
|
+
if (!arena) return NULL;
|
|
24
|
+
|
|
25
|
+
tf_batch *b = tf_arena_alloc(arena, sizeof(tf_batch));
|
|
26
|
+
if (!b) { tf_arena_free(arena); return NULL; }
|
|
27
|
+
|
|
28
|
+
b->arena = arena;
|
|
29
|
+
b->n_cols = n_cols;
|
|
30
|
+
b->n_rows = 0;
|
|
31
|
+
b->capacity = capacity;
|
|
32
|
+
b->col_names = tf_arena_alloc(arena, n_cols * sizeof(char *));
|
|
33
|
+
b->col_types = tf_arena_alloc(arena, n_cols * sizeof(tf_type));
|
|
34
|
+
b->columns = tf_arena_alloc(arena, n_cols * sizeof(void *));
|
|
35
|
+
b->nulls = tf_arena_alloc(arena, n_cols * sizeof(uint8_t *));
|
|
36
|
+
|
|
37
|
+
if (!b->col_names || !b->col_types || !b->columns || !b->nulls) {
|
|
38
|
+
tf_arena_free(arena);
|
|
39
|
+
return NULL;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
for (size_t i = 0; i < n_cols; i++) {
|
|
43
|
+
b->col_names[i] = NULL;
|
|
44
|
+
b->col_types[i] = TF_TYPE_NULL;
|
|
45
|
+
b->columns[i] = NULL;
|
|
46
|
+
b->nulls[i] = NULL;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return b;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
int tf_batch_set_schema(tf_batch *b, size_t col, const char *name, tf_type type) {
|
|
53
|
+
if (col >= b->n_cols) return TF_ERROR;
|
|
54
|
+
b->col_names[col] = tf_arena_strdup(b->arena, name);
|
|
55
|
+
b->col_types[col] = type;
|
|
56
|
+
|
|
57
|
+
/* Allocate column storage */
|
|
58
|
+
size_t sz = type_size(type);
|
|
59
|
+
if (sz > 0 && b->capacity > 0) {
|
|
60
|
+
b->columns[col] = tf_arena_alloc(b->arena, sz * b->capacity);
|
|
61
|
+
b->nulls[col] = tf_arena_alloc(b->arena, b->capacity);
|
|
62
|
+
if (!b->columns[col] || !b->nulls[col]) return TF_ERROR;
|
|
63
|
+
memset(b->nulls[col], 1, b->capacity); /* all null by default */
|
|
64
|
+
}
|
|
65
|
+
return TF_OK;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
int tf_batch_ensure_capacity(tf_batch *b, size_t min_rows) {
|
|
69
|
+
if (min_rows <= b->capacity) return TF_OK;
|
|
70
|
+
|
|
71
|
+
/* We need to reallocate columns — but arena doesn't support realloc.
|
|
72
|
+
* Allocate new larger arrays and copy. */
|
|
73
|
+
size_t new_cap = b->capacity ? b->capacity : 16;
|
|
74
|
+
while (new_cap < min_rows) new_cap *= 2;
|
|
75
|
+
|
|
76
|
+
for (size_t i = 0; i < b->n_cols; i++) {
|
|
77
|
+
size_t sz = type_size(b->col_types[i]);
|
|
78
|
+
if (sz == 0) continue;
|
|
79
|
+
|
|
80
|
+
void *new_col = tf_arena_alloc(b->arena, sz * new_cap);
|
|
81
|
+
uint8_t *new_null = tf_arena_alloc(b->arena, new_cap);
|
|
82
|
+
if (!new_col || !new_null) return TF_ERROR;
|
|
83
|
+
|
|
84
|
+
if (b->columns[i] && b->n_rows > 0) {
|
|
85
|
+
memcpy(new_col, b->columns[i], sz * b->n_rows);
|
|
86
|
+
memcpy(new_null, b->nulls[i], b->n_rows);
|
|
87
|
+
}
|
|
88
|
+
memset(new_null + b->n_rows, 1, new_cap - b->n_rows);
|
|
89
|
+
b->columns[i] = new_col;
|
|
90
|
+
b->nulls[i] = new_null;
|
|
91
|
+
}
|
|
92
|
+
b->capacity = new_cap;
|
|
93
|
+
return TF_OK;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* ---- Setters ---- */
|
|
97
|
+
|
|
98
|
+
void tf_batch_set_null(tf_batch *b, size_t row, size_t col) {
|
|
99
|
+
if (row < b->capacity && col < b->n_cols && b->nulls[col])
|
|
100
|
+
b->nulls[col][row] = 1;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
void tf_batch_set_bool(tf_batch *b, size_t row, size_t col, bool val) {
|
|
104
|
+
if (row < b->capacity && col < b->n_cols && b->col_types[col] == TF_TYPE_BOOL) {
|
|
105
|
+
((uint8_t *)b->columns[col])[row] = val ? 1 : 0;
|
|
106
|
+
b->nulls[col][row] = 0;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
void tf_batch_set_int64(tf_batch *b, size_t row, size_t col, int64_t val) {
|
|
111
|
+
if (row < b->capacity && col < b->n_cols && b->col_types[col] == TF_TYPE_INT64) {
|
|
112
|
+
((int64_t *)b->columns[col])[row] = val;
|
|
113
|
+
b->nulls[col][row] = 0;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
void tf_batch_set_float64(tf_batch *b, size_t row, size_t col, double val) {
|
|
118
|
+
if (row < b->capacity && col < b->n_cols && b->col_types[col] == TF_TYPE_FLOAT64) {
|
|
119
|
+
((double *)b->columns[col])[row] = val;
|
|
120
|
+
b->nulls[col][row] = 0;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
void tf_batch_set_string(tf_batch *b, size_t row, size_t col, const char *val) {
|
|
125
|
+
if (row < b->capacity && col < b->n_cols && b->col_types[col] == TF_TYPE_STRING) {
|
|
126
|
+
((char **)b->columns[col])[row] = tf_arena_strdup(b->arena, val);
|
|
127
|
+
b->nulls[col][row] = 0;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
void tf_batch_set_date(tf_batch *b, size_t row, size_t col, int32_t val) {
|
|
132
|
+
if (row < b->capacity && col < b->n_cols && b->col_types[col] == TF_TYPE_DATE) {
|
|
133
|
+
((int32_t *)b->columns[col])[row] = val;
|
|
134
|
+
b->nulls[col][row] = 0;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
void tf_batch_set_timestamp(tf_batch *b, size_t row, size_t col, int64_t val) {
|
|
139
|
+
if (row < b->capacity && col < b->n_cols && b->col_types[col] == TF_TYPE_TIMESTAMP) {
|
|
140
|
+
((int64_t *)b->columns[col])[row] = val;
|
|
141
|
+
b->nulls[col][row] = 0;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/* ---- Getters ---- */
|
|
146
|
+
|
|
147
|
+
bool tf_batch_is_null(const tf_batch *b, size_t row, size_t col) {
|
|
148
|
+
if (row >= b->n_rows || col >= b->n_cols) return true;
|
|
149
|
+
return b->nulls[col][row] != 0;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
bool tf_batch_get_bool(const tf_batch *b, size_t row, size_t col) {
|
|
153
|
+
if (row >= b->n_rows || col >= b->n_cols) return false;
|
|
154
|
+
return ((uint8_t *)b->columns[col])[row] != 0;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
int64_t tf_batch_get_int64(const tf_batch *b, size_t row, size_t col) {
|
|
158
|
+
if (row >= b->n_rows || col >= b->n_cols) return 0;
|
|
159
|
+
return ((int64_t *)b->columns[col])[row];
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
double tf_batch_get_float64(const tf_batch *b, size_t row, size_t col) {
|
|
163
|
+
if (row >= b->n_rows || col >= b->n_cols) return 0.0;
|
|
164
|
+
return ((double *)b->columns[col])[row];
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const char *tf_batch_get_string(const tf_batch *b, size_t row, size_t col) {
|
|
168
|
+
if (row >= b->n_rows || col >= b->n_cols) return NULL;
|
|
169
|
+
return ((char **)b->columns[col])[row];
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
int32_t tf_batch_get_date(const tf_batch *b, size_t row, size_t col) {
|
|
173
|
+
if (row >= b->n_rows || col >= b->n_cols) return 0;
|
|
174
|
+
return ((int32_t *)b->columns[col])[row];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
int64_t tf_batch_get_timestamp(const tf_batch *b, size_t row, size_t col) {
|
|
178
|
+
if (row >= b->n_rows || col >= b->n_cols) return 0;
|
|
179
|
+
return ((int64_t *)b->columns[col])[row];
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
int tf_batch_copy_row(tf_batch *dst, size_t dst_row,
|
|
183
|
+
const tf_batch *src, size_t src_row) {
|
|
184
|
+
if (tf_batch_ensure_capacity(dst, dst_row + 1) != TF_OK) return TF_ERROR;
|
|
185
|
+
for (size_t c = 0; c < src->n_cols; c++) {
|
|
186
|
+
if (tf_batch_is_null(src, src_row, c)) {
|
|
187
|
+
tf_batch_set_null(dst, dst_row, c);
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
switch (src->col_types[c]) {
|
|
191
|
+
case TF_TYPE_BOOL:
|
|
192
|
+
tf_batch_set_bool(dst, dst_row, c, tf_batch_get_bool(src, src_row, c));
|
|
193
|
+
break;
|
|
194
|
+
case TF_TYPE_INT64:
|
|
195
|
+
tf_batch_set_int64(dst, dst_row, c, tf_batch_get_int64(src, src_row, c));
|
|
196
|
+
break;
|
|
197
|
+
case TF_TYPE_FLOAT64:
|
|
198
|
+
tf_batch_set_float64(dst, dst_row, c, tf_batch_get_float64(src, src_row, c));
|
|
199
|
+
break;
|
|
200
|
+
case TF_TYPE_STRING:
|
|
201
|
+
tf_batch_set_string(dst, dst_row, c, tf_batch_get_string(src, src_row, c));
|
|
202
|
+
break;
|
|
203
|
+
case TF_TYPE_DATE:
|
|
204
|
+
tf_batch_set_date(dst, dst_row, c, tf_batch_get_date(src, src_row, c));
|
|
205
|
+
break;
|
|
206
|
+
case TF_TYPE_TIMESTAMP:
|
|
207
|
+
tf_batch_set_timestamp(dst, dst_row, c, tf_batch_get_timestamp(src, src_row, c));
|
|
208
|
+
break;
|
|
209
|
+
default:
|
|
210
|
+
tf_batch_set_null(dst, dst_row, c);
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return TF_OK;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
int tf_batch_col_index(const tf_batch *b, const char *name) {
|
|
218
|
+
for (size_t i = 0; i < b->n_cols; i++) {
|
|
219
|
+
if (b->col_names[i] && strcmp(b->col_names[i], name) == 0)
|
|
220
|
+
return (int)i;
|
|
221
|
+
}
|
|
222
|
+
return -1;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
void tf_batch_free(tf_batch *b) {
|
|
226
|
+
if (!b) return;
|
|
227
|
+
tf_arena *arena = b->arena;
|
|
228
|
+
tf_arena_free(arena);
|
|
229
|
+
}
|
package/csrc/buffer.c
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* buffer.c — Growable byte buffer for streaming I/O.
|
|
3
|
+
* Supports write (append), read (consume), and compact operations.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
#include "internal.h"
|
|
7
|
+
#include <stdlib.h>
|
|
8
|
+
#include <string.h>
|
|
9
|
+
|
|
10
|
+
#define INITIAL_CAP 4096
|
|
11
|
+
|
|
12
|
+
void tf_buffer_init(tf_buffer *b) {
|
|
13
|
+
b->data = NULL;
|
|
14
|
+
b->len = 0;
|
|
15
|
+
b->cap = 0;
|
|
16
|
+
b->read_pos = 0;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static int buffer_ensure(tf_buffer *b, size_t extra) {
|
|
20
|
+
size_t needed = b->len + extra;
|
|
21
|
+
if (needed <= b->cap) return TF_OK;
|
|
22
|
+
size_t new_cap = b->cap ? b->cap : INITIAL_CAP;
|
|
23
|
+
while (new_cap < needed) new_cap *= 2;
|
|
24
|
+
uint8_t *new_data = realloc(b->data, new_cap);
|
|
25
|
+
if (!new_data) return TF_ERROR;
|
|
26
|
+
b->data = new_data;
|
|
27
|
+
b->cap = new_cap;
|
|
28
|
+
return TF_OK;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
int tf_buffer_write(tf_buffer *b, const uint8_t *data, size_t len) {
|
|
32
|
+
if (len == 0) return TF_OK;
|
|
33
|
+
if (buffer_ensure(b, len) != TF_OK) return TF_ERROR;
|
|
34
|
+
memcpy(b->data + b->len, data, len);
|
|
35
|
+
b->len += len;
|
|
36
|
+
return TF_OK;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
int tf_buffer_write_str(tf_buffer *b, const char *s) {
|
|
40
|
+
return tf_buffer_write(b, (const uint8_t *)s, strlen(s));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
size_t tf_buffer_read(tf_buffer *b, uint8_t *out, size_t len) {
|
|
44
|
+
size_t avail = b->len - b->read_pos;
|
|
45
|
+
if (len > avail) len = avail;
|
|
46
|
+
if (len > 0) {
|
|
47
|
+
memcpy(out, b->data + b->read_pos, len);
|
|
48
|
+
b->read_pos += len;
|
|
49
|
+
}
|
|
50
|
+
/* Auto-compact when all data consumed */
|
|
51
|
+
if (b->read_pos == b->len) {
|
|
52
|
+
b->read_pos = 0;
|
|
53
|
+
b->len = 0;
|
|
54
|
+
}
|
|
55
|
+
return len;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
size_t tf_buffer_readable(const tf_buffer *b) {
|
|
59
|
+
return b->len - b->read_pos;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
void tf_buffer_compact(tf_buffer *b) {
|
|
63
|
+
if (b->read_pos == 0) return;
|
|
64
|
+
size_t remaining = b->len - b->read_pos;
|
|
65
|
+
if (remaining > 0) {
|
|
66
|
+
memmove(b->data, b->data + b->read_pos, remaining);
|
|
67
|
+
}
|
|
68
|
+
b->len = remaining;
|
|
69
|
+
b->read_pos = 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
void tf_buffer_free(tf_buffer *b) {
|
|
73
|
+
free(b->data);
|
|
74
|
+
b->data = NULL;
|
|
75
|
+
b->len = 0;
|
|
76
|
+
b->cap = 0;
|
|
77
|
+
b->read_pos = 0;
|
|
78
|
+
}
|