teptris 0.3.6.3 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6c78dea6cf66de177025b3ca3ced1b166a12909487312794392a4bf9b7c6fa58
4
- data.tar.gz: 21de9b146bca1fa22df6c9e6f58b6d2c813211d56089287520ab93040558d723
3
+ metadata.gz: 9405799997c71a6a203a7e99e2b7b5cc3b14ef4e5fc1107549a8be0a81eecc45
4
+ data.tar.gz: 3b63416a7a12a234c4fa002e08e74baa8685dac138c05fa8692c2fcd1213cc88
5
5
  SHA512:
6
- metadata.gz: 55b149ca222277b998288571eb2f1a265342a64b9fca905bdfbff9f022cda772108f9ea52d78f5b583a32008f14c919d28f24d232a03fe3de279bde3084a56a3
7
- data.tar.gz: dc89589fa986b2f439775fe5aa0894974315c15f0784faf2775d2d44a20d05dda7dca3485b79bec295b7702e89e86de798fb725d8929a74645b61e494983b541
6
+ metadata.gz: 29a783e4396441be903921e6a59e68c1b94c43ebb5d93d4e0d6ec156ccf02be23286ad6e7501b0ca7eb199dcee61a47c303e5d8fbf508184650ccd5c9d12ab16
7
+ data.tar.gz: d7b054ad6b5c58558d08701f483ec70c37904846e5ad7fe68268e2db30b4b199f2ecf284b9e9fb67b691a2b3f1f082887b4416a3174e152fd3bbe114ce6ee2a5
@@ -1,4 +1,4 @@
1
- # libteptris 0.3.6 — vendored source
1
+ # libteptris 0.3.8 — vendored source
2
2
 
3
3
  This directory carries the COMPLETE C source of the engine this
4
4
  gem's extension was built from (the packaging doctrine: compiled
@@ -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 {
@@ -4,6 +4,6 @@
4
4
  #define TEPTRIS_VERSION_MAJOR 0
5
5
  #define TEPTRIS_VERSION_MINOR 3
6
6
  #define TEPTRIS_VERSION_PATCH 0
7
- #define TEPTRIS_VERSION_STRING "0.3.6"
7
+ #define TEPTRIS_VERSION_STRING "0.3.8"
8
8
 
9
9
  #endif /* TEPTRIS_VERSION_H */
@@ -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
- *st_out = tep_fail_at(ps, NULL, TEPTRIS_ERR_SEMANTIC,
630
- "duplicate key '%.*s'", (int)key.len, key.ptr);
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);
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Teptris
4
- VERSION = "0.3.6.3"
4
+ VERSION = "0.3.8.1"
5
5
  end
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.6.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-21 00:00:00.000000000 Z
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.