teptris 0.3.4.1 → 0.3.6.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.
- checksums.yaml +4 -4
- data/ext/teptris_ext/engine/README.md +1 -1
- data/ext/teptris_ext/engine/src/include/teptris/teptris.h +17 -0
- data/ext/teptris_ext/engine/src/include/teptris/version.h +1 -1
- data/ext/teptris_ext/engine/src/teptris/emit/emit_shared.h +419 -0
- data/ext/teptris_ext/engine/src/teptris/emit/emitter.c +1 -404
- data/ext/teptris_ext/engine/src/teptris/emit/writer.c +575 -0
- data/ext/teptris_ext/materialize.c +125 -21
- data/lib/teptris/toml.rb +18 -0
- data/lib/teptris/version.rb +1 -1
- data/sig/teptris.rbs +6 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c15f2a655540df82c9f9b71b8e4fe8e713fba91e95f516388eb86362730ff339
|
|
4
|
+
data.tar.gz: 14fdd01070f4955c1e86d5e0ae1137a8aa71da42ee24502560fcb3dc7b2f2ae1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b53af53b9141a34e077cd25cc12a4cde4337806b2fc8a43d3d8abcd1b7d9c40707094f1a58138eb26e5abcff459473657e4d1ae2368642639e2a3c7b617d3590
|
|
7
|
+
data.tar.gz: cacdf91ad8607e05dcb6c6f1a8f7c303de10d0a1f53136df215b68495b55ef5b9c2e280e71ac6036833d7cd5a3d96e949edea813f725b48f2eee1b5bfe382e6e
|
|
@@ -187,6 +187,23 @@ TEPTRIS_API const char * teptris_version_string(void);
|
|
|
187
187
|
* kept alive). Duplicate keys are TEPTRIS_ERR_ARG.
|
|
188
188
|
* Memory: the builder owns its document until teptris_builder_finish
|
|
189
189
|
* transfers it; otherwise teptris_builder_free destroys it. */
|
|
190
|
+
/* Streaming TOML writer: op-stream in (grammar in
|
|
191
|
+
* src/teptris/emit/writer.c), TOML text out - the fused dumps path
|
|
192
|
+
* for bindings that walk host objects. Caller contract: within each
|
|
193
|
+
* table, scalar values must be fed before nested tables/AOTs;
|
|
194
|
+
* violations are ERR_STATE (invalid TOML is never emitted).
|
|
195
|
+
* Memory: *buf from teptris_writer_finish is malloc'd; free it with
|
|
196
|
+
* free(). */
|
|
197
|
+
typedef struct teptris_writer teptris_writer;
|
|
198
|
+
|
|
199
|
+
TEPTRIS_API teptris_writer *teptris_writer_new(void);
|
|
200
|
+
TEPTRIS_API void teptris_writer_free(teptris_writer *w);
|
|
201
|
+
TEPTRIS_API teptris_status teptris_writer_feed(teptris_writer *w,
|
|
202
|
+
const uint8_t *ops,
|
|
203
|
+
size_t len);
|
|
204
|
+
TEPTRIS_API teptris_status teptris_writer_finish(teptris_writer *w,
|
|
205
|
+
char **buf, size_t *len);
|
|
206
|
+
|
|
190
207
|
typedef struct teptris_builder teptris_builder;
|
|
191
208
|
|
|
192
209
|
TEPTRIS_API teptris_builder *teptris_builder_new(void);
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
/* Shared emit layer: buffer + scalar/escape/key writers used by both
|
|
2
|
+
* the DOM emitters (emitter.c) and the streaming writer (writer.c).
|
|
3
|
+
* Static-in-header: each TU gets its own copy; these are small and
|
|
4
|
+
* monomorphic. */
|
|
5
|
+
#ifndef TEPTRIS_EMIT_SHARED_H
|
|
6
|
+
#define TEPTRIS_EMIT_SHARED_H
|
|
7
|
+
|
|
8
|
+
#include <math.h>
|
|
9
|
+
#include <stdio.h>
|
|
10
|
+
#include <stdbool.h>
|
|
11
|
+
#include <stdint.h>
|
|
12
|
+
#include <stdlib.h>
|
|
13
|
+
#include <string.h>
|
|
14
|
+
|
|
15
|
+
#include "teptris/common/chartype.h"
|
|
16
|
+
#include "teptris/common/ryu/ryu_d2s.h"
|
|
17
|
+
#include "teptris/dom/dom.h"
|
|
18
|
+
|
|
19
|
+
typedef struct {
|
|
20
|
+
char *p;
|
|
21
|
+
size_t len, cap;
|
|
22
|
+
teptris_status st;
|
|
23
|
+
} ebuf;
|
|
24
|
+
|
|
25
|
+
static inline void eb_reserve(ebuf *b, size_t extra)
|
|
26
|
+
{
|
|
27
|
+
if (b->st != TEPTRIS_OK) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (b->len + extra + 1 <= b->cap) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
size_t ncap = b->cap ? b->cap : 256;
|
|
34
|
+
while (b->len + extra + 1 > ncap) {
|
|
35
|
+
ncap *= 2;
|
|
36
|
+
}
|
|
37
|
+
char *np = realloc(b->p, ncap);
|
|
38
|
+
if (np == NULL) {
|
|
39
|
+
free(b->p);
|
|
40
|
+
b->p = NULL;
|
|
41
|
+
b->st = TEPTRIS_ERR_ALLOC;
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
b->p = np;
|
|
45
|
+
b->cap = ncap;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static inline void eb_put(ebuf *b, const char *s, size_t n)
|
|
49
|
+
{
|
|
50
|
+
if (b->st != TEPTRIS_OK) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (b->len + n + 1 <= b->cap) {
|
|
54
|
+
memcpy(b->p + b->len, s, n);
|
|
55
|
+
b->len += n;
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
eb_reserve(b, n);
|
|
59
|
+
if (b->st != TEPTRIS_OK) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
memcpy(b->p + b->len, s, n);
|
|
63
|
+
b->len += n;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
static inline void eb_c(ebuf *b, char c)
|
|
67
|
+
{
|
|
68
|
+
if (b->st == TEPTRIS_OK && b->len + 2 <= b->cap) {
|
|
69
|
+
b->p[b->len++] = c;
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
eb_put(b, &c, 1);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* ", " — the element/entry separator — as one direct 2-byte write;
|
|
76
|
+
* the densest loops pay it per element */
|
|
77
|
+
static inline void eb_sep2(ebuf *b)
|
|
78
|
+
{
|
|
79
|
+
if (b->st == TEPTRIS_OK && b->len + 3 <= b->cap) {
|
|
80
|
+
b->p[b->len] = ',';
|
|
81
|
+
b->p[b->len + 1] = ' ';
|
|
82
|
+
b->len += 2;
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
eb_put(b, ", ", 2);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
static inline void eb_str(ebuf *b, const char *s)
|
|
89
|
+
{
|
|
90
|
+
eb_put(b, s, strlen(s));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* ------------------------------------------------------------- scalars -- */
|
|
94
|
+
|
|
95
|
+
/* direct writer, shared by both emit views: snprintf costs a
|
|
96
|
+
* format-parse + locale check per number */
|
|
97
|
+
static inline void emit_i64(ebuf *b, int64_t v)
|
|
98
|
+
{
|
|
99
|
+
uint64_t mag;
|
|
100
|
+
bool neg = v < 0;
|
|
101
|
+
if (neg) {
|
|
102
|
+
mag = (uint64_t)(-(v + 1)) + 1; /* INT64_MIN safe */
|
|
103
|
+
} else {
|
|
104
|
+
mag = (uint64_t)v;
|
|
105
|
+
}
|
|
106
|
+
char tmp[32];
|
|
107
|
+
char *q = tmp + sizeof(tmp);
|
|
108
|
+
*--q = '\0';
|
|
109
|
+
do {
|
|
110
|
+
*--q = (char)('0' + (mag % 10));
|
|
111
|
+
mag /= 10;
|
|
112
|
+
} while (mag != 0);
|
|
113
|
+
if (neg) {
|
|
114
|
+
*--q = '-';
|
|
115
|
+
}
|
|
116
|
+
eb_put(b, q, (size_t)(tmp + sizeof(tmp) - 1 - q));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
static inline void emit_float(ebuf *b, double f)
|
|
120
|
+
{
|
|
121
|
+
if (isnan(f)) {
|
|
122
|
+
eb_str(b, "nan");
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (isinf(f)) {
|
|
126
|
+
eb_str(b, f < 0 ? "-inf" : "inf");
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
/* ryu shortest round-trip digits ("D[.DD]E[X]"), re-rendered in TOML
|
|
130
|
+
* notation: fixed-point when compact, scientific otherwise. */
|
|
131
|
+
char tmp[32];
|
|
132
|
+
int n = teptris_ryu_d2s_buffered_n(f, tmp);
|
|
133
|
+
/* the _n ryu variant does NOT terminate: bound every later read */
|
|
134
|
+
tmp[n] = '\0';
|
|
135
|
+
|
|
136
|
+
size_t i = 0;
|
|
137
|
+
bool neg = false;
|
|
138
|
+
if (tmp[0] == '-') {
|
|
139
|
+
neg = true;
|
|
140
|
+
i = 1;
|
|
141
|
+
}
|
|
142
|
+
char digits[24];
|
|
143
|
+
size_t nd = 0;
|
|
144
|
+
for (; i < (size_t)n && tmp[i] != 'E'; i++) {
|
|
145
|
+
if (tmp[i] != '.') {
|
|
146
|
+
digits[nd++] = tmp[i];
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
long sci_exp = (i < (size_t)n) ? strtol(tmp + i + 1, NULL, 10) : 0;
|
|
150
|
+
long e10 = sci_exp - (long)nd + 1; /* value = digits * 10^e10 */
|
|
151
|
+
|
|
152
|
+
char out[44];
|
|
153
|
+
size_t o = 0;
|
|
154
|
+
if (neg) {
|
|
155
|
+
out[o++] = '-';
|
|
156
|
+
}
|
|
157
|
+
if (e10 >= 0 && e10 + (long)nd <= 16) {
|
|
158
|
+
memcpy(out + o, digits, nd);
|
|
159
|
+
o += nd;
|
|
160
|
+
for (long k = 0; k < e10; k++) {
|
|
161
|
+
out[o++] = '0';
|
|
162
|
+
}
|
|
163
|
+
out[o++] = '.';
|
|
164
|
+
out[o++] = '0';
|
|
165
|
+
} else if (e10 < 0 && -e10 <= (long)nd) {
|
|
166
|
+
long ip = (long)nd + e10;
|
|
167
|
+
if (ip > 0) {
|
|
168
|
+
memcpy(out + o, digits, (size_t)ip);
|
|
169
|
+
o += (size_t)ip;
|
|
170
|
+
out[o++] = '.';
|
|
171
|
+
memcpy(out + o, digits + ip, nd - (size_t)ip);
|
|
172
|
+
o += nd - (size_t)ip;
|
|
173
|
+
} else {
|
|
174
|
+
out[o++] = '0';
|
|
175
|
+
out[o++] = '.';
|
|
176
|
+
memcpy(out + o, digits, nd);
|
|
177
|
+
o += nd;
|
|
178
|
+
}
|
|
179
|
+
} else if (e10 < 0 && -e10 - (long)nd <= 6) {
|
|
180
|
+
out[o++] = '0';
|
|
181
|
+
out[o++] = '.';
|
|
182
|
+
for (long k = 0; k < -e10 - (long)nd; k++) {
|
|
183
|
+
out[o++] = '0';
|
|
184
|
+
}
|
|
185
|
+
memcpy(out + o, digits, nd);
|
|
186
|
+
o += nd;
|
|
187
|
+
} else {
|
|
188
|
+
out[o++] = digits[0];
|
|
189
|
+
if (nd > 1) {
|
|
190
|
+
out[o++] = '.';
|
|
191
|
+
memcpy(out + o, digits + 1, nd - 1);
|
|
192
|
+
o += nd - 1;
|
|
193
|
+
}
|
|
194
|
+
o += (size_t)snprintf(out + o, sizeof(out) - o, "e%ld", sci_exp);
|
|
195
|
+
}
|
|
196
|
+
eb_put(b, out, o);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
static inline size_t put_digits2(char *p, unsigned v)
|
|
200
|
+
{
|
|
201
|
+
p[0] = (char)('0' + (v / 10));
|
|
202
|
+
p[1] = (char)('0' + (v % 10));
|
|
203
|
+
return 2;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
static inline size_t put_digits4(char *p, unsigned v)
|
|
207
|
+
{
|
|
208
|
+
put_digits2(p, v / 100);
|
|
209
|
+
put_digits2(p + 2, v % 100);
|
|
210
|
+
return 4;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
static inline void emit_dt(ebuf *b, const teptris_datetime *dt, teptris_kind k)
|
|
214
|
+
{
|
|
215
|
+
char tmp[64];
|
|
216
|
+
size_t n = 0;
|
|
217
|
+
if (k != TEPTRIS_TIME_LOCAL) {
|
|
218
|
+
n += put_digits4(tmp + n, (unsigned)dt->year);
|
|
219
|
+
tmp[n++] = '-';
|
|
220
|
+
n += put_digits2(tmp + n, dt->month);
|
|
221
|
+
tmp[n++] = '-';
|
|
222
|
+
n += put_digits2(tmp + n, dt->day);
|
|
223
|
+
if (k != TEPTRIS_DATE_LOCAL) {
|
|
224
|
+
tmp[n++] = 'T';
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
if (k != TEPTRIS_DATE_LOCAL) {
|
|
228
|
+
n += put_digits2(tmp + n, dt->hour);
|
|
229
|
+
tmp[n++] = ':';
|
|
230
|
+
n += put_digits2(tmp + n, dt->minute);
|
|
231
|
+
tmp[n++] = ':';
|
|
232
|
+
n += put_digits2(tmp + n, dt->second);
|
|
233
|
+
}
|
|
234
|
+
if (dt->nanosecond != 0 && k != TEPTRIS_DATE_LOCAL) {
|
|
235
|
+
tmp[n++] = '.';
|
|
236
|
+
unsigned v = dt->nanosecond;
|
|
237
|
+
for (int i = 8; i >= 0; i--) {
|
|
238
|
+
tmp[n + (size_t)i] = (char)('0' + v % 10);
|
|
239
|
+
v /= 10;
|
|
240
|
+
}
|
|
241
|
+
n += 9;
|
|
242
|
+
while (n > 0 && tmp[n - 1] == '0') {
|
|
243
|
+
n--; /* trim trailing fraction zeros, keep at least one digit */
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
if (k == TEPTRIS_DATETIME_OFFSET) {
|
|
247
|
+
int32_t off = dt->offset_seconds;
|
|
248
|
+
if (off == 0) {
|
|
249
|
+
tmp[n++] = 'Z';
|
|
250
|
+
} else {
|
|
251
|
+
int32_t a = (off < 0) ? -off : off;
|
|
252
|
+
tmp[n++] = (off < 0) ? '-' : '+';
|
|
253
|
+
n += put_digits2(tmp + n, (unsigned)(a / 3600));
|
|
254
|
+
tmp[n++] = ':';
|
|
255
|
+
n += put_digits2(tmp + n, (unsigned)((a % 3600) / 60));
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
eb_put(b, tmp, n);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
static inline void emit_basic_bytes(ebuf *b, const char *s, size_t n)
|
|
262
|
+
{
|
|
263
|
+
eb_c(b, '"');
|
|
264
|
+
size_t i = 0;
|
|
265
|
+
while (i < n) {
|
|
266
|
+
/* span-scan to the next byte needing escape; the clean run
|
|
267
|
+
* goes out as one eb_put instead of per-byte eb_c */
|
|
268
|
+
size_t start = i;
|
|
269
|
+
while (i < n) {
|
|
270
|
+
unsigned char c = (unsigned char)s[i];
|
|
271
|
+
if (c == '"' || c == '\\' || c < 0x20 || c == 0x7F) {
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
i++;
|
|
275
|
+
}
|
|
276
|
+
eb_put(b, s + start, i - start);
|
|
277
|
+
if (i == n) {
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
unsigned char c = (unsigned char)s[i++];
|
|
281
|
+
switch (c) {
|
|
282
|
+
case '"':
|
|
283
|
+
eb_str(b, "\\\"");
|
|
284
|
+
break;
|
|
285
|
+
case '\\':
|
|
286
|
+
eb_str(b, "\\\\");
|
|
287
|
+
break;
|
|
288
|
+
case '\b':
|
|
289
|
+
eb_str(b, "\\b");
|
|
290
|
+
break;
|
|
291
|
+
case '\t':
|
|
292
|
+
eb_str(b, "\\t");
|
|
293
|
+
break;
|
|
294
|
+
case '\n':
|
|
295
|
+
eb_str(b, "\\n");
|
|
296
|
+
break;
|
|
297
|
+
case '\f':
|
|
298
|
+
eb_str(b, "\\f");
|
|
299
|
+
break;
|
|
300
|
+
case '\r':
|
|
301
|
+
eb_str(b, "\\r");
|
|
302
|
+
break;
|
|
303
|
+
default:
|
|
304
|
+
if (c < 0x20 || c == 0x7F) {
|
|
305
|
+
char esc[8];
|
|
306
|
+
snprintf(esc, sizeof(esc), "\\u%04X", c);
|
|
307
|
+
eb_str(b, esc);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
eb_c(b, '"');
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
static inline void emit_string_value(ebuf *b, teptris_view s)
|
|
315
|
+
{
|
|
316
|
+
bool literal = true;
|
|
317
|
+
for (size_t i = 0; i < s.len; i++) {
|
|
318
|
+
unsigned char c = (unsigned char)s.ptr[i];
|
|
319
|
+
if (c == '\'' || (c < 0x20 && c != '\t') || c == 0x7F) {
|
|
320
|
+
literal = false;
|
|
321
|
+
break;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
if (literal) {
|
|
325
|
+
eb_c(b, '\'');
|
|
326
|
+
eb_put(b, s.ptr, s.len);
|
|
327
|
+
eb_c(b, '\'');
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
emit_basic_bytes(b, s.ptr, s.len);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/* Worst-case quoted-key length: 6 bytes per input byte (\u00XX) + 2 quotes. */
|
|
334
|
+
static inline size_t key_buf_cap(teptris_view key)
|
|
335
|
+
{
|
|
336
|
+
return key.len * 6 + 4;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
static inline size_t key_to_buf(char *dst, teptris_view key)
|
|
340
|
+
{
|
|
341
|
+
bool bare = key.len > 0;
|
|
342
|
+
for (size_t i = 0; i < key.len; i++) {
|
|
343
|
+
if (!tep_is_barekey((unsigned char)key.ptr[i])) {
|
|
344
|
+
bare = false;
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
if (bare) {
|
|
349
|
+
memcpy(dst, key.ptr, key.len);
|
|
350
|
+
return key.len;
|
|
351
|
+
}
|
|
352
|
+
bool literal = true;
|
|
353
|
+
for (size_t i = 0; i < key.len; i++) {
|
|
354
|
+
unsigned char c = (unsigned char)key.ptr[i];
|
|
355
|
+
if (c == '\'' || (c < 0x20 && c != '\t') || c == 0x7F) {
|
|
356
|
+
literal = false;
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
size_t n = 0;
|
|
361
|
+
if (literal) {
|
|
362
|
+
dst[n++] = '\'';
|
|
363
|
+
memcpy(dst + n, key.ptr, key.len);
|
|
364
|
+
n += key.len;
|
|
365
|
+
dst[n++] = '\'';
|
|
366
|
+
return n;
|
|
367
|
+
}
|
|
368
|
+
dst[n++] = '"';
|
|
369
|
+
for (size_t i = 0; i < key.len; i++) {
|
|
370
|
+
unsigned char c = (unsigned char)key.ptr[i];
|
|
371
|
+
switch (c) {
|
|
372
|
+
case '"':
|
|
373
|
+
dst[n++] = '\\';
|
|
374
|
+
dst[n++] = '"';
|
|
375
|
+
break;
|
|
376
|
+
case '\\':
|
|
377
|
+
dst[n++] = '\\';
|
|
378
|
+
dst[n++] = '\\';
|
|
379
|
+
break;
|
|
380
|
+
default:
|
|
381
|
+
if (c < 0x20) {
|
|
382
|
+
static const char hex[] = "0123456789ABCDEF";
|
|
383
|
+
dst[n++] = '\\';
|
|
384
|
+
dst[n++] = 'u';
|
|
385
|
+
dst[n++] = '0';
|
|
386
|
+
dst[n++] = '0';
|
|
387
|
+
dst[n++] = hex[c >> 4];
|
|
388
|
+
dst[n++] = hex[c & 0xF];
|
|
389
|
+
} else {
|
|
390
|
+
dst[n++] = (char)c;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
dst[n++] = '"';
|
|
395
|
+
return n;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
static inline void emit_key(ebuf *b, teptris_view key)
|
|
399
|
+
{
|
|
400
|
+
/* keys <= ~42 bytes (every bare key, nearly all quoted) never
|
|
401
|
+
* touch the allocator */
|
|
402
|
+
char stack[256];
|
|
403
|
+
if (key_buf_cap(key) <= sizeof(stack)) {
|
|
404
|
+
size_t n = key_to_buf(stack, key);
|
|
405
|
+
eb_put(b, stack, n);
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
char *ks = malloc(key_buf_cap(key));
|
|
409
|
+
if (ks == NULL) {
|
|
410
|
+
b->st = TEPTRIS_ERR_ALLOC;
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
size_t n = key_to_buf(ks, key);
|
|
414
|
+
eb_put(b, ks, n);
|
|
415
|
+
free(ks);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/* --------------------------------------------------------------- values -- */
|
|
419
|
+
#endif /* TEPTRIS_EMIT_SHARED_H */
|