teptris 0.3.6.2 → 0.3.8.1
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 +7 -0
- data/ext/teptris_ext/engine/src/include/teptris/version.h +1 -1
- data/ext/teptris_ext/engine/src/teptris/parse/parse.h +1 -0
- data/ext/teptris_ext/engine/src/teptris/parse/parser.c +35 -2
- data/ext/teptris_ext/materialize.c +13 -0
- data/lib/teptris/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9405799997c71a6a203a7e99e2b7b5cc3b14ef4e5fc1107549a8be0a81eecc45
|
|
4
|
+
data.tar.gz: 3b63416a7a12a234c4fa002e08e74baa8685dac138c05fa8692c2fcd1213cc88
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 29a783e4396441be903921e6a59e68c1b94c43ebb5d93d4e0d6ec156ccf02be23286ad6e7501b0ca7eb199dcee61a47c303e5d8fbf508184650ccd5c9d12ab16
|
|
7
|
+
data.tar.gz: d7b054ad6b5c58558d08701f483ec70c37904846e5ad7fe68268e2db30b4b199f2ecf284b9e9fb67b691a2b3f1f082887b4416a3174e152fd3bbe114ce6ee2a5
|
|
@@ -75,6 +75,13 @@ typedef struct teptris_error {
|
|
|
75
75
|
size_t line; /* 1-based */
|
|
76
76
|
size_t column; /* 1-based */
|
|
77
77
|
const char *message; /* NUL-terminated, document-owned */
|
|
78
|
+
/* E5 machine-readable span: byte offsets into the parse input.
|
|
79
|
+
* Errors are point events, so start == end (the offset of the
|
|
80
|
+
* offending position). Appended fields: consumers hold engine-
|
|
81
|
+
* owned const pointers, so the struct may grow without breaking
|
|
82
|
+
* already-built callers. */
|
|
83
|
+
size_t start_offset;
|
|
84
|
+
size_t end_offset;
|
|
78
85
|
} teptris_error;
|
|
79
86
|
|
|
80
87
|
typedef struct teptris_options {
|
|
@@ -12,6 +12,7 @@ typedef struct teptris_parser {
|
|
|
12
12
|
uint32_t depth;
|
|
13
13
|
uint32_t max_depth;
|
|
14
14
|
teptris_node *cur; /* open table (root until the first header) */
|
|
15
|
+
teptris_view cur_path; /* input-backed header text ('' = root) */
|
|
15
16
|
} teptris_parser;
|
|
16
17
|
|
|
17
18
|
/* parser.c entry: validates UTF-8, skips BOM, runs the line loop. */
|
|
@@ -32,6 +32,8 @@ teptris_status tep_fail_at(teptris_parser *ps, const char *at, teptris_status co
|
|
|
32
32
|
}
|
|
33
33
|
doc->err.line = line;
|
|
34
34
|
doc->err.column = (size_t)(pos - bol) + 1;
|
|
35
|
+
doc->err.start_offset = (size_t)(pos - ps->src);
|
|
36
|
+
doc->err.end_offset = doc->err.start_offset;
|
|
35
37
|
return code;
|
|
36
38
|
}
|
|
37
39
|
|
|
@@ -216,6 +218,8 @@ static teptris_status validate_utf8(teptris_document *doc, const char *data,
|
|
|
216
218
|
doc->err.status = TEPTRIS_ERR_ENCODING;
|
|
217
219
|
doc->err.line = line;
|
|
218
220
|
doc->err.column = bad - (size_t)(bol - data) + 1;
|
|
221
|
+
doc->err.start_offset = bad;
|
|
222
|
+
doc->err.end_offset = bad;
|
|
219
223
|
snprintf(doc->err_msg, sizeof(doc->err_msg), "invalid UTF-8 sequence");
|
|
220
224
|
doc->err.message = doc->err_msg;
|
|
221
225
|
return TEPTRIS_ERR_ENCODING;
|
|
@@ -273,6 +277,16 @@ static teptris_status insert_dotted(teptris_parser *ps, teptris_node *table,
|
|
|
273
277
|
size_t last_slot;
|
|
274
278
|
if (teptris_dom_table_probe_slot(t, hlast, last.ptr, last.len,
|
|
275
279
|
&last_slot) != NULL) {
|
|
280
|
+
if (count > 1) {
|
|
281
|
+
/* the parent path spans parts[0]..parts[count-2] (the
|
|
282
|
+
* interior '.'/ws bytes are inside the input span) */
|
|
283
|
+
return tep_fail_at(ps, NULL, TEPTRIS_ERR_SEMANTIC,
|
|
284
|
+
"duplicate key '%.*s' in table '%.*s'",
|
|
285
|
+
(int)last.len, last.ptr,
|
|
286
|
+
(int)(parts[count - 2].ptr - parts[0].ptr +
|
|
287
|
+
parts[count - 2].len),
|
|
288
|
+
parts[0].ptr);
|
|
289
|
+
}
|
|
276
290
|
return tep_fail_at(ps, NULL, TEPTRIS_ERR_SEMANTIC, "duplicate key '%.*s'",
|
|
277
291
|
(int)last.len, last.ptr);
|
|
278
292
|
}
|
|
@@ -406,10 +420,13 @@ static teptris_status resolve_header(teptris_parser *ps, const teptris_view *par
|
|
|
406
420
|
static teptris_status parse_header(teptris_parser *ps)
|
|
407
421
|
{
|
|
408
422
|
tep_adv(ps, 1); /* '[' */
|
|
423
|
+
const char *hstart = ps->p; /* header text for dup-key context */
|
|
424
|
+
const char *hend = ps->p;
|
|
409
425
|
bool aot = false;
|
|
410
426
|
if (ps->p < ps->end && *ps->p == '[') {
|
|
411
427
|
aot = true;
|
|
412
428
|
tep_adv(ps, 1);
|
|
429
|
+
hstart = ps->p;
|
|
413
430
|
}
|
|
414
431
|
|
|
415
432
|
teptris_status st = tep_skip_ws(ps);
|
|
@@ -432,11 +449,13 @@ static teptris_status parse_header(teptris_parser *ps)
|
|
|
432
449
|
if (ps->end - ps->p < 2 || ps->p[0] != ']' || ps->p[1] != ']') {
|
|
433
450
|
return tep_fail_at(ps, NULL, TEPTRIS_ERR_SYNTAX, "expected ']]'");
|
|
434
451
|
}
|
|
452
|
+
hend = ps->p;
|
|
435
453
|
tep_adv(ps, 2);
|
|
436
454
|
} else {
|
|
437
455
|
if (ps->p >= ps->end || *ps->p != ']') {
|
|
438
456
|
return tep_fail_at(ps, NULL, TEPTRIS_ERR_SYNTAX, "expected ']'");
|
|
439
457
|
}
|
|
458
|
+
hend = ps->p;
|
|
440
459
|
tep_adv(ps, 1);
|
|
441
460
|
}
|
|
442
461
|
|
|
@@ -446,6 +465,10 @@ static teptris_status parse_header(teptris_parser *ps)
|
|
|
446
465
|
return rst;
|
|
447
466
|
}
|
|
448
467
|
ps->cur = target;
|
|
468
|
+
/* the header text is input-backed: remember it so duplicate-key
|
|
469
|
+
* errors can name the enclosing table */
|
|
470
|
+
ps->cur_path.ptr = hstart;
|
|
471
|
+
ps->cur_path.len = (size_t)(hend - hstart);
|
|
449
472
|
return TEPTRIS_OK;
|
|
450
473
|
}
|
|
451
474
|
|
|
@@ -505,6 +528,8 @@ TEP_NOINLINE static bool try_header_fast(teptris_parser *ps,
|
|
|
505
528
|
if (q >= ps->end || *q != ']') {
|
|
506
529
|
return false;
|
|
507
530
|
}
|
|
531
|
+
ps->cur_path.ptr = start + 1;
|
|
532
|
+
ps->cur_path.len = (size_t)(q - (start + 1));
|
|
508
533
|
|
|
509
534
|
/* shape confirmed — commit the resolution */
|
|
510
535
|
teptris_document *doc = ps->doc;
|
|
@@ -626,8 +651,16 @@ static bool try_keyval_fast(teptris_parser *ps, teptris_node *tbl,
|
|
|
626
651
|
}
|
|
627
652
|
size_t slot;
|
|
628
653
|
if (teptris_dom_table_probe_slot(tbl, h, key.ptr, key.len, &slot) != NULL) {
|
|
629
|
-
|
|
630
|
-
|
|
654
|
+
if (ps->cur_path.len > 0) {
|
|
655
|
+
*st_out = tep_fail_at(
|
|
656
|
+
ps, NULL, TEPTRIS_ERR_SEMANTIC,
|
|
657
|
+
"duplicate key '%.*s' in table '%.*s'", (int)key.len,
|
|
658
|
+
key.ptr, (int)ps->cur_path.len, ps->cur_path.ptr);
|
|
659
|
+
} else {
|
|
660
|
+
*st_out = tep_fail_at(ps, NULL, TEPTRIS_ERR_SEMANTIC,
|
|
661
|
+
"duplicate key '%.*s'", (int)key.len,
|
|
662
|
+
key.ptr);
|
|
663
|
+
}
|
|
631
664
|
return true;
|
|
632
665
|
}
|
|
633
666
|
*st_out = teptris_dom_table_insert_slot(ps->doc, tbl, key, h, value, slot);
|
|
@@ -1345,4 +1345,17 @@ void Init_teptris_ext(void) {
|
|
|
1345
1345
|
id_to_s = rb_intern("to_s");
|
|
1346
1346
|
id_to_i = rb_intern("to_i");
|
|
1347
1347
|
id_nsec = rb_intern("nsec");
|
|
1348
|
+
/* Compaction safety: class objects stay reachable through their
|
|
1349
|
+
* constants (never swept), but GC.compact MOVES them — an
|
|
1350
|
+
* unregistered static slot then holds a stale RVALUE and the next
|
|
1351
|
+
* rb_raise/rb_funcall through it faults (the windows ruby-4.0
|
|
1352
|
+
* segfault, teptris-ruby#161: the suite's GC.compact spec moved
|
|
1353
|
+
* Teptris::Error out from under these slots). rb_gc_register_address
|
|
1354
|
+
* roots the SLOT, so compaction updates what it points at. */
|
|
1355
|
+
rb_gc_register_address(&eError);
|
|
1356
|
+
rb_gc_register_address(&eParseError);
|
|
1357
|
+
rb_gc_register_address(&cDate);
|
|
1358
|
+
rb_gc_register_address(&cDoc);
|
|
1359
|
+
rb_gc_register_address(&cLazyOwner);
|
|
1360
|
+
rb_gc_register_address(&cLazyValue);
|
|
1348
1361
|
}
|
data/lib/teptris/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: teptris
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.8.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- teptris contributors
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: A native C extension over libteptris, a C99 TOML 1.1 parser/emitter.
|
|
14
14
|
API shape mirrors the tomlib gem.
|