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