yeptris 0.6.18.2-arm-linux-eabihf → 0.6.19.1-arm-linux-eabihf

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: d861d71fda8e06d38693a273a8c3eea7cbe96325af1eb0e4d2fdcc4bf7f08e46
4
- data.tar.gz: 1120adc922c754da05873a318e2406206606ca966d22b79a686e08192b4a0e4d
3
+ metadata.gz: 64530aa53c5671af0f95cb5f727a69cd1765fa86af7fbb51accaeb43fcb7357a
4
+ data.tar.gz: 3214755f5922f24510501628009e5dce2aab3c4c232037bc543d36435c628385
5
5
  SHA512:
6
- metadata.gz: a68230754f4f90049a59ea30d8d8abb903c8fdef3f5e26abf5b110fd966d4da973c811d8e4c55750034aaa2207289f9fed60ed50f5065125b7b6854b44c5bce4
7
- data.tar.gz: eb0d85052b73579c0809a9b1aef3f6be57ee5aff43406b9569f7f77189d23af3471d4bd29b5d9f4815a50bd661e20007a7c93fc6b3a2bac8d842a1a7001da921
6
+ metadata.gz: d14f52f172a20abe10f11604284ec9e1d7e18139da58e510a7576b205575caae0ef1adb7aed293dd9da679b066664bb89ddda5bd0c5f2121f0125b9ed95de0ab
7
+ data.tar.gz: e6d35406f4d30785f220a909e1f51e031d6c7b911b9d2fec6eda1c6c07f3b2469f0d991ee0ab6e0426862af89f7b5239a071a228065cae123d284826d88fdf7e
@@ -12,9 +12,10 @@ module Yeptris
12
12
  # materializer (Node#to_ruby) stays for node-based use; this is the
13
13
  # Yeptris::YAML fast path.
14
14
  class Materializer
15
- RECORD_SIZE = 36 # YeptrisEventRecord layout (events.h, ABI-pinned)
16
- FIELDS = 12 # unpacked values per record
17
- RECORD_UNPACK = "C4V8" # type/style/flags/tag_id, line..tag_len
15
+ RECORD_SIZE = 44 # YeptrisEventRecord layout (events.h, ABI-pinned;
16
+ # #179 added end_line/end_col in the 0.6.19 window)
17
+ FIELDS = 14 # unpacked values per record
18
+ RECORD_UNPACK = "C4V10" # type/style/flags/tag_id, line..tag_len
18
19
 
19
20
  STREAM_START = 1
20
21
  STREAM_END = 2
@@ -256,10 +257,10 @@ module Yeptris
256
257
  # not the text
257
258
  tag_id = flat[i + 3]
258
259
  v = Materializer.scan_by_tag(
259
- arena[flat[i + 6], flat[i + 7]], tag_id, (flat[i + 2] & EF_IMPLICIT) != 0
260
+ arena[flat[i + 8], flat[i + 9]], tag_id, (flat[i + 2] & EF_IMPLICIT) != 0
260
261
  )
261
- l = flat[i + 9]
262
- anchors[arena[flat[i + 8], l]] = v if l != 0
262
+ l = flat[i + 11]
263
+ anchors[arena[flat[i + 10], l]] = v if l != 0
263
264
  # place(): the scalar fast path inlined — the overwhelming
264
265
  # majority of events land here
265
266
  if stack.empty?
@@ -284,22 +285,22 @@ module Yeptris
284
285
  end
285
286
  when MAPPING_START
286
287
  h = {}
287
- l = flat[i + 9]
288
- anchors[arena[flat[i + 8], l]] = h if l != 0
288
+ l = flat[i + 11]
289
+ anchors[arena[flat[i + 10], l]] = h if l != 0
289
290
  merge_target.push(place(docs, stack, pending_key, pending_key_merge, h))
290
291
  stack.push(h)
291
292
  pending_key.push(nil)
292
293
  pending_key_merge.push(nil)
293
294
  when SEQUENCE_START
294
295
  a = []
295
- l = flat[i + 9]
296
- anchors[arena[flat[i + 8], l]] = a if l != 0
296
+ l = flat[i + 11]
297
+ anchors[arena[flat[i + 10], l]] = a if l != 0
297
298
  merge_target.push(place(docs, stack, pending_key, pending_key_merge, a))
298
299
  stack.push(a)
299
300
  pending_key.push(nil)
300
301
  pending_key_merge.push(nil)
301
302
  when ALIAS
302
- name = arena[flat[i + 6], flat[i + 7]]
303
+ name = arena[flat[i + 8], flat[i + 9]]
303
304
  raise Yeptris::ParseError, "unknown anchor: #{name.inspect}" unless anchors.key?(name)
304
305
 
305
306
  place(docs, stack, pending_key, pending_key_merge, anchors[name])
@@ -49,6 +49,11 @@ module Yeptris
49
49
 
50
50
  def alias(anchor); end
51
51
 
52
+ # #179: called before EVERY event with the event's 0-based marks
53
+ # (psych 5's contract — TreeBuilder stashes them for node
54
+ # locations). No-op by default; handlers that care override it.
55
+ def event_location(start_line, start_column, end_line, end_column); end
56
+
52
57
  # +style+ is one of the scalar constants above; +plain+ /
53
58
  # +quoted+ are the implicit-typing flags (plain: resolvable
54
59
  # without a tag).
@@ -52,12 +52,17 @@ module Yeptris
52
52
  h = @handler
53
53
  i = 0
54
54
  while i < flat.length
55
+ # #179: psych's parser calls event_location before every
56
+ # event; TreeBuilder stashes the marks for node locations
57
+ # (0-based).
58
+ h.event_location(flat[i + 4] - 1, flat[i + 5] - 1,
59
+ flat[i + 6] - 1, flat[i + 7] - 1)
55
60
  type = flat[i]
56
61
  style = flat[i + 1]
57
62
  flags = flat[i + 2]
58
- value = field(flat, arena, i + 6)
59
- anchor = field(flat, arena, i + 8)
60
- tag = field(flat, arena, i + 10)
63
+ value = field(flat, arena, i + 8)
64
+ anchor = field(flat, arena, i + 10)
65
+ tag = field(flat, arena, i + 12)
61
66
  case type
62
67
  when STREAM_START then h.start_stream(UTF8)
63
68
  when STREAM_END then h.end_stream
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yeptris
4
+ module Psych
5
+ # The stdlib TreeBuilder port (#179): builds a Nodes tree carrying
6
+ # start/end line:column on every node. The parser calls
7
+ # event_location before each event (psych 5's exact contract);
8
+ # stdlib's class is the reference — this port follows it
9
+ # function-for-function over the binding's keyword-arg Nodes.
10
+ class TreeBuilder < Handler
11
+ attr_reader :root
12
+
13
+ def initialize
14
+ super
15
+ @stack = []
16
+ @last = nil
17
+ @root = nil
18
+ @start_line = nil
19
+ @start_column = nil
20
+ @end_line = nil
21
+ @end_column = nil
22
+ end
23
+
24
+ def event_location(start_line, start_column, end_line, end_column)
25
+ @start_line = start_line
26
+ @start_column = start_column
27
+ @end_line = end_line
28
+ @end_column = end_column
29
+ end
30
+
31
+ %w[Sequence Mapping].each do |node|
32
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
33
+ def start_#{node.downcase}(anchor, tag, implicit, style)
34
+ n = Nodes::#{node}.new(anchor: anchor, tag: tag, style: style)
35
+ set_start_location(n)
36
+ @last.children << n
37
+ push n
38
+ end
39
+
40
+ def end_#{node.downcase}
41
+ n = pop
42
+ set_end_location(n)
43
+ n
44
+ end
45
+ RUBY
46
+ end
47
+
48
+ def start_document(version, tag_directives, implicit)
49
+ n = Nodes::Document.new(version, tag_directives)
50
+ set_start_location(n)
51
+ @last.children << n
52
+ push n
53
+ end
54
+
55
+ def end_document(_implicit = false)
56
+ n = pop
57
+ set_end_location(n)
58
+ n
59
+ end
60
+
61
+ def start_stream(_encoding)
62
+ n = Nodes::Stream.new
63
+ set_start_location(n)
64
+ @root = n
65
+ push n
66
+ end
67
+
68
+ def end_stream
69
+ n = pop
70
+ set_end_location(n)
71
+ n
72
+ end
73
+
74
+ def scalar(value, anchor, tag, plain, quoted, style)
75
+ n = Nodes::Scalar.new(value, anchor: anchor, tag: tag,
76
+ plain: plain, quoted: quoted, style: style)
77
+ set_location(n)
78
+ @last.children << n
79
+ n
80
+ end
81
+
82
+ def alias(anchor)
83
+ n = Nodes::Alias.new(anchor)
84
+ set_location(n)
85
+ @last.children << n
86
+ n
87
+ end
88
+
89
+ private
90
+
91
+ def push(value)
92
+ @stack.push(value)
93
+ @last = value
94
+ end
95
+
96
+ def pop
97
+ value = @stack.pop
98
+ @last = @stack.last
99
+ value
100
+ end
101
+
102
+ def set_location(n)
103
+ n.start_line = @start_line
104
+ n.start_column = @start_column
105
+ n.end_line = @end_line
106
+ n.end_column = @end_column
107
+ end
108
+
109
+ def set_start_location(n)
110
+ set_location(n)
111
+ end
112
+
113
+ def set_end_location(n)
114
+ n.end_line = @end_line
115
+ n.end_column = @end_column
116
+ end
117
+ end
118
+ end
119
+ end
data/lib/yeptris/psych.rb CHANGED
@@ -86,6 +86,8 @@ module Yeptris
86
86
  # own entry so referencing Psych::Handlers triggers the load
87
87
  autoload :Handlers, "yeptris/psych/handler"
88
88
  autoload :Parser, "yeptris/psych/parser"
89
+ # #179: the located tree builder (stdlib's class, ported)
90
+ autoload :TreeBuilder, "yeptris/psych/tree_builder"
89
91
  autoload :CoderShim, "yeptris/psych/coder_shim"
90
92
  autoload :Visitors, "yeptris/psych/visitors"
91
93
  # The typed opt-in marker for arbitrary-object dump/load
@@ -425,6 +427,8 @@ module Yeptris
425
427
  include Enumerable
426
428
 
427
429
  attr_reader :children
430
+ # #179: the event marks (0-based), applied by TreeBuilder
431
+ attr_accessor :start_line, :start_column, :end_line, :end_column
428
432
  attr_reader :handle # @api private — the Yeptris::Node
429
433
  # @api private — the tree builder attaches handles; a writer,
430
434
  # never instance_variable_set from outside
data/lib/yeptris.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module Yeptris
4
4
  # The gem's version lives in the parent namespace's file — the last
5
5
  # internal require (yeptris/version) retired with it.
6
- VERSION = "0.6.18.2".freeze
6
+ VERSION = "0.6.19.1".freeze
7
7
  # The error hierarchy lives in THIS file (the parent namespace's
8
8
  # own file): nested constants do not trigger a parent-constant
9
9
  # autoload, and the law forbids internal requires — defining the
data/libyeptris.so CHANGED
Binary file
@@ -3,7 +3,7 @@
3
3
  cmake_minimum_required(VERSION 3.20)
4
4
 
5
5
  project(yeptris
6
- VERSION 0.6.18
6
+ VERSION 0.6.19
7
7
  DESCRIPTION "Ultra-fast YAML 1.2 parser, emitter and streamer in C"
8
8
  LANGUAGES C CXX
9
9
  )
@@ -66,6 +66,9 @@ typedef struct {
66
66
  size_t tag_len;
67
67
  uint32_t line; /* 1-based node start */
68
68
  uint32_t col;
69
+ uint32_t end_line; /* #179: libyaml end_mark semantics — 1-based line,
70
+ * col one past the node's end token */
71
+ uint32_t end_col;
69
72
  } YeptrisEvent;
70
73
 
71
74
  /* ---- push ------------------------------------------------------------- */
@@ -106,13 +109,17 @@ typedef struct {
106
109
  * struct's pad byte: sizeof stays 36 (ABI-pinned) */
107
110
  uint32_t line;
108
111
  uint32_t col;
112
+ uint32_t end_line; /* #179: libyaml end_mark semantics (see the
113
+ * internal event) — 1-based, col past the end */
114
+ uint32_t end_col;
109
115
  uint32_t value_off;
110
116
  uint32_t value_len;
111
117
  uint32_t anchor_off;
112
118
  uint32_t anchor_len;
113
119
  uint32_t tag_off;
114
120
  uint32_t tag_len;
115
- } YeptrisEventRecord;
121
+ } YeptrisEventRecord; /* 44B — the bindings mirror this layout in the
122
+ same lockstep window (the 0.6.9 law) */
116
123
 
117
124
  YEPTRIS_API YeptrisRecorder yeptris_recorder_new(void);
118
125
 
@@ -7,7 +7,7 @@
7
7
  #include "../../include/yeptris/events.h"
8
8
 
9
9
  /* The record IS the public ABI shape (events.h pins it). */
10
- YEPTRIS_CT_ASSERT(sizeof(YeptrisEventRecord) == 36);
10
+ YEPTRIS_CT_ASSERT(sizeof(YeptrisEventRecord) == 44);
11
11
 
12
12
  void yep_rec_init(yep_rec_store* s) {
13
13
  s->recs = NULL;
@@ -114,6 +114,8 @@ int yep_rec_on_event(void* ctx, const yep_event* ev) {
114
114
  }
115
115
  r->line = ev->line;
116
116
  r->col = ev->col;
117
+ r->end_line = ev->end_line;
118
+ r->end_col = ev->end_col;
117
119
  r->value_off = arena_put(s, (const char*)ev->value.p, (uint32_t)ev->value.len);
118
120
  r->value_len = (uint32_t)ev->value.len;
119
121
  r->anchor_off = arena_put(s, (const char*)ev->anchor.p, (uint32_t)ev->anchor.len);
@@ -135,6 +137,8 @@ void yep_rec_materialize(const yep_rec_store* s, size_t i, void* out) {
135
137
  e->implicit = (r->flags & YEPTRIS_EF_IMPLICIT) != 0;
136
138
  e->line = r->line;
137
139
  e->col = r->col;
140
+ e->end_line = r->end_line;
141
+ e->end_col = r->end_col;
138
142
  if (r->value_len > 0) {
139
143
  e->value = s->arena + r->value_off;
140
144
  e->value_len = r->value_len;
@@ -104,8 +104,11 @@ struct yep_engine {
104
104
  yep_view handle, prefix;
105
105
  } tagmap[8];
106
106
  int tagmap_n;
107
- int saw_yaml; /* %YAML seen for the pending document */
108
- void* step; /* yep_stepstate: resumable stepping (07) */
107
+ int saw_yaml; /* %YAML seen for the pending document */
108
+ size_t doc_begin; /* #179: first directive line of the pending doc
109
+ * (SIZE_MAX = none) — libyaml's DOCUMENT_START
110
+ * start_mark includes directives */
111
+ void* step; /* yep_stepstate: resumable stepping (07) */
109
112
 
110
113
  /* Flow single-pair deferral: a sequence entry's events are buffered
111
114
  * until we know whether ':' follows ("[a: b]" needs MAP_START before
@@ -134,6 +137,34 @@ static uint32_t e_col(const yep_engine* e, size_t at) {
134
137
  return at >= e->line_start ? (uint32_t)(at - e->line_start) : 0;
135
138
  }
136
139
 
140
+ /* #179: the (1-based line, 1-based col) of a byte offset. Unlike
141
+ * e_col this handles offsets on PRIOR lines — event ends whose scan
142
+ * already advanced past them (block scalars, collection closes).
143
+ * The backward walk covers only the span's own lines, so the total
144
+ * across a document stays linear in its size. */
145
+ static void e_pos_mark(const yep_engine* e, size_t at, uint32_t* line, uint32_t* col) {
146
+ if (at >= e->line_start) {
147
+ *line = e->line;
148
+ *col = (uint32_t)(at - e->line_start) + 1;
149
+ return;
150
+ }
151
+ uint32_t l = e->line;
152
+ size_t ls = e->line_start;
153
+ while (at < ls && ls > 0) {
154
+ /* p[ls-1] is the newline ENDED the previous line: start the
155
+ * walk below it, or ls never decreases (the infinite-loop bug
156
+ * the Stepping.Directive hang found) */
157
+ size_t q = ls - 1;
158
+ while (q > 0 && e->p[q - 1] != '\n') {
159
+ q--;
160
+ }
161
+ ls = q; /* line_start(l-1) */
162
+ l--;
163
+ }
164
+ *line = l;
165
+ *col = (uint32_t)(at - ls) + 1;
166
+ }
167
+
137
168
  static int e_fail(yep_engine* e, yep_err_code code, size_t at) {
138
169
  yep_error_set(&e->err, code, e->line, e_col(e, at) + 1, at, NULL);
139
170
  return -1;
@@ -374,6 +405,18 @@ static int e_open_seq(yep_engine* e, uint16_t col, uint32_t line, uint32_t coln,
374
405
  ev.tag = tag;
375
406
  ev.line = line;
376
407
  ev.col = coln;
408
+ ev.end_line = line; /* block opens are zero-span (libyaml) — except
409
+ * the sequence at its parent mapping's column
410
+ * ("k:\n- a"), which ends after the dash */
411
+ ev.end_col = coln;
412
+ for (int i = e->depth - 1; i >= 0; i--) {
413
+ if (e->frames[i].kind == YEP_FRAME_MAP) {
414
+ if (col == e->frames[i].col) {
415
+ ev.end_col = coln + 1;
416
+ }
417
+ break;
418
+ }
419
+ }
377
420
  return emit_now(e, &ev) == 0 ? 0 : -2;
378
421
  }
379
422
 
@@ -403,6 +446,8 @@ static int e_open_map(yep_engine* e, uint16_t col, uint32_t line, uint32_t coln,
403
446
  ev.tag = tag;
404
447
  ev.line = line;
405
448
  ev.col = coln;
449
+ ev.end_line = line; /* block opens are zero-span (libyaml) */
450
+ ev.end_col = coln;
406
451
  return emit_now(e, &ev) == 0 ? 0 : -2;
407
452
  }
408
453
 
@@ -436,6 +481,16 @@ static int e_close_to(yep_engine* e, int to_depth) {
436
481
  yep_event ev;
437
482
  e_event_init(&ev,
438
483
  e->frames[e->depth].kind == YEP_FRAME_SEQ ? YEP_EV_SEQ_END : YEP_EV_MAP_END);
484
+ { /* libyaml: a block END's mark is the next token's position
485
+ * (zero-span) — the first non-space at the cursor, or EOF */
486
+ size_t at = e->pos;
487
+ while (at < e->len && e->p[at] == ' ') {
488
+ at++;
489
+ }
490
+ e_pos_mark(e, at, &ev.line, &ev.col);
491
+ ev.end_line = ev.line;
492
+ ev.end_col = ev.col;
493
+ }
439
494
  if (emit_now(e, &ev) != 0) {
440
495
  return -2;
441
496
  }
@@ -631,6 +686,7 @@ static int e_quoted_floor(yep_engine* e, yep_event* ev, uint16_t min_indent, int
631
686
  e->line_start = ls;
632
687
  }
633
688
  e->pos = after;
689
+ e_pos_mark(e, after, &ev->end_line, &ev->end_col);
634
690
  e_skip_inline_space(e);
635
691
  return 0;
636
692
  }
@@ -810,6 +866,7 @@ static int e_block_scalar(yep_engine* e, yep_event* ev, int parent_col) {
810
866
  ev->value.p = out; /* may be NULL for an empty block; len 0 */
811
867
  ev->borrowed = 0;
812
868
  ev->style = folded ? YEP_STYLE_FOLDED : YEP_STYLE_LITERAL;
869
+ e_pos_mark(e, e->pos, &ev->end_line, &ev->end_col);
813
870
  return 0;
814
871
  }
815
872
 
@@ -887,6 +944,11 @@ static int e_plain_multiline(yep_engine* e, yep_span s0, uint32_t block_floor, y
887
944
  break; /* the comment ends the scalar; later lines are new */
888
945
  }
889
946
  }
947
+ { /* #179: the source end = the last piece's content end */
948
+ const yep_view* last = &e->fold[e->fold_n - 1].content;
949
+ size_t lend = (size_t)(last->p - e->p) + last->len;
950
+ e_pos_mark(e, lend, &ev->end_line, &ev->end_col);
951
+ }
890
952
  if (e->fold_n == 1) {
891
953
  return 0; /* single line: the borrowed view stands */
892
954
  }
@@ -1082,6 +1144,7 @@ static int e_alias(yep_engine* e, yep_event* ev) {
1082
1144
  the DOM borrows it like any plain scalar — no
1083
1145
  arena copy per alias */
1084
1146
  ev->anchor_id = target;
1147
+ e_pos_mark(e, e->pos, &ev->end_line, &ev->end_col);
1085
1148
  e_skip_inline_space(e);
1086
1149
  return 0;
1087
1150
  }
@@ -1224,6 +1287,7 @@ static int e_flow_node(yep_engine* e, yep_event* ev, int keyish) {
1224
1287
  if ((c == ',' || c == ']' || c == '}' || c == ':') &&
1225
1288
  (!yep_view_is_empty(anchor) || !yep_view_is_empty(tag))) {
1226
1289
  ev->implicit = 1; /* properties with no node: a tagged null */
1290
+ e_pos_mark(e, e->pos, &ev->end_line, &ev->end_col);
1227
1291
  return 1;
1228
1292
  }
1229
1293
  if (c == '"' || c == '\'') {
@@ -1313,6 +1377,10 @@ static int e_flow_node(yep_engine* e, yep_event* ev, int keyish) {
1313
1377
  ev->style = YEP_STYLE_PLAIN;
1314
1378
  ev->implicit = 1;
1315
1379
  ev->multiline = (e->fold_n > 1) || crossed_break;
1380
+ { /* #179: the source end = the last fold piece's content end */
1381
+ const yep_view* lastp = &e->fold[e->fold_n - 1].content;
1382
+ e_pos_mark(e, (size_t)(lastp->p - e->p) + lastp->len, &ev->end_line, &ev->end_col);
1383
+ }
1316
1384
  return 1;
1317
1385
  }
1318
1386
 
@@ -1464,6 +1532,8 @@ static int e_flow_json(yep_engine* e, yep_view anchor, yep_view tag, uint32_t an
1464
1532
  ev.tag = tag;
1465
1533
  ev.line = cur_line;
1466
1534
  ev.col = (uint32_t)(open_pos + 1 - cur_ls) + 1;
1535
+ ev.end_line = cur_line; /* flow opens end after the indicator */
1536
+ ev.end_col = (uint32_t)(open_pos + 2 - cur_ls) + 1;
1467
1537
  if (emit_now(e, &ev) != 0) {
1468
1538
  return -2;
1469
1539
  }
@@ -1488,6 +1558,8 @@ static int e_flow_json(yep_engine* e, yep_view anchor, yep_view tag, uint32_t an
1488
1558
  jx_advance_line(e, &cur_scan, i, &cur_line, &cur_ls);
1489
1559
  ev.line = cur_line;
1490
1560
  ev.col = (uint32_t)(i - cur_ls) + 1;
1561
+ ev.end_line = cur_line;
1562
+ ev.end_col = (uint32_t)(i + 1 - cur_ls) + 1;
1491
1563
  if (emit_now(e, &ev) != 0) {
1492
1564
  return -2;
1493
1565
  }
@@ -1509,6 +1581,8 @@ static int e_flow_json(yep_engine* e, yep_view anchor, yep_view tag, uint32_t an
1509
1581
  jx_advance_line(e, &cur_scan, i, &cur_line, &cur_ls);
1510
1582
  ev.line = cur_line;
1511
1583
  ev.col = (uint32_t)(i + 1 - cur_ls) + 1;
1584
+ ev.end_line = cur_line; /* flow opens end after the indicator */
1585
+ ev.end_col = (uint32_t)(i + 2 - cur_ls) + 1;
1512
1586
  if (emit_now(e, &ev) != 0) {
1513
1587
  return -2;
1514
1588
  }
@@ -1582,6 +1656,11 @@ static int e_flow_json(yep_engine* e, yep_view anchor, yep_view tag, uint32_t an
1582
1656
  return e_fail(e, YEP_ERR_KEY_TOO_LONG, vstart);
1583
1657
  }
1584
1658
  }
1659
+ if (raw_end == vstart) {
1660
+ raw_end = i; /* numbers/literals advance i, not raw_end */
1661
+ }
1662
+ ev.end_line = cur_line;
1663
+ ev.end_col = (uint32_t)(raw_end - cur_ls) + 1;
1585
1664
  if (emit_now(e, &ev) != 0) {
1586
1665
  return -2;
1587
1666
  }
@@ -1652,6 +1731,8 @@ static int e_flow(yep_engine* e, yep_view anchor, yep_view tag, uint32_t anchor_
1652
1731
  ev.tag = tag;
1653
1732
  ev.line = e->line;
1654
1733
  ev.col = e_col(e, e->pos);
1734
+ ev.end_line = e->line; /* flow opens end after the indicator */
1735
+ ev.end_col = e_col(e, e->pos) + 1;
1655
1736
  if (emit_now(e, &ev) != 0) {
1656
1737
  return -2;
1657
1738
  }
@@ -1755,6 +1836,8 @@ static int e_flow(yep_engine* e, yep_view anchor, yep_view tag, uint32_t anchor_
1755
1836
  ev.tag = pt;
1756
1837
  ev.line = e->line;
1757
1838
  ev.col = e_col(e, e->pos);
1839
+ ev.end_line = e->line; /* flow opens end after the indicator */
1840
+ ev.end_col = e_col(e, e->pos) + 1;
1758
1841
  if (emit_now(e, &ev) != 0) {
1759
1842
  return -2;
1760
1843
  }
@@ -1861,6 +1944,9 @@ static int e_flow(yep_engine* e, yep_view anchor, yep_view tag, uint32_t anchor_
1861
1944
  mk.flow = 1;
1862
1945
  mk.line = ev.line;
1863
1946
  mk.col = ev.col;
1947
+ mk.end_line = ev.line; /* virtual opener: zero-span
1948
+ * at the implied position */
1949
+ mk.end_col = ev.col;
1864
1950
  if (emit_now(e, &mk) != 0) {
1865
1951
  return -2;
1866
1952
  }
@@ -2045,6 +2131,11 @@ static int e_flow(yep_engine* e, yep_view anchor, yep_view tag, uint32_t anchor_
2045
2131
  }
2046
2132
  e->pos++;
2047
2133
  e_event_init(&ev, st[n - 1].kind ? YEP_EV_MAP_END : YEP_EV_SEQ_END);
2134
+ /* the close indicator's span: e->pos sits just past it */
2135
+ ev.line = e->line;
2136
+ ev.col = e_col(e, e->pos - 1) + 1;
2137
+ ev.end_line = e->line;
2138
+ ev.end_col = e_col(e, e->pos) + 1;
2048
2139
  if (emit_now(e, &ev) != 0) {
2049
2140
  return -2;
2050
2141
  }
@@ -2135,6 +2226,9 @@ static int e_flow(yep_engine* e, yep_view anchor, yep_view tag, uint32_t anchor_
2135
2226
  yep_event mk;
2136
2227
  e_event_init(&mk, YEP_EV_MAP_START);
2137
2228
  mk.flow = 1;
2229
+ e_pos_mark(e, e->pos, &mk.line, &mk.col);
2230
+ mk.end_line = mk.line; /* virtual opener: zero-span */
2231
+ mk.end_col = mk.col;
2138
2232
  if (emit_now(e, &mk) != 0) {
2139
2233
  return -2;
2140
2234
  }
@@ -2282,6 +2376,9 @@ static void e_key_event(const yep_engine* e, const yep_line_shape* sh, uint16_t
2282
2376
  kv->borrowed = 1;
2283
2377
  kv->line = line;
2284
2378
  kv->col = key_col + 1;
2379
+ /* keys are single-line by the simple-key law; the cursor may have
2380
+ * advanced past the line, so the mark comes from e_pos_mark */
2381
+ e_pos_mark(e, sh->key_end, &kv->end_line, &kv->end_col);
2285
2382
  }
2286
2383
 
2287
2384
  static int e_classified(yep_engine* e, uint16_t floor_col) {
@@ -2786,6 +2883,7 @@ static int e_node(yep_engine* e, yep_ctx ctx, uint16_t floor_col) {
2786
2883
  kv.borrowed = 1;
2787
2884
  kv.line = e->line;
2788
2885
  kv.col = key_col + 1;
2886
+ e_pos_mark(e, s.end, &kv.end_line, &kv.end_col);
2789
2887
  if (emit_now(e, &kv) != 0) {
2790
2888
  return -2;
2791
2889
  }
@@ -2958,6 +3056,20 @@ empty_value: {
2958
3056
  e->pend_anchor_id = 0;
2959
3057
  e->pend_tag.p = NULL;
2960
3058
  e->pend_tag.len = 0;
3059
+ { /* libyaml: the implicit null sits just past the key's colon
3060
+ * ("k: " -> col 2, not the line end), zero-span */
3061
+ size_t at = e->pos;
3062
+ while (at > 0 && (e->p[at - 1] == ' ' || e->p[at - 1] == '\t' || e->p[at - 1] == '\n' ||
3063
+ e->p[at - 1] == '\r')) {
3064
+ at--; /* the cursor may sit lines past the deferred key */
3065
+ }
3066
+ if (at == 0 || e->p[at - 1] != ':') {
3067
+ at = e->pos; /* not a plain "key:" defer: the cursor stands */
3068
+ }
3069
+ e_pos_mark(e, at, &ev.line, &ev.col);
3070
+ ev.end_line = ev.line;
3071
+ ev.end_col = ev.col;
3072
+ }
2961
3073
  return emit_now(e, &ev) == 0 ? 0 : -2;
2962
3074
  }
2963
3075
  }
@@ -3300,6 +3412,7 @@ static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep
3300
3412
  yep_nametab_clear(&e->anchors);
3301
3413
  e->tagmap_n = 0;
3302
3414
  e->saw_yaml = 0;
3415
+ e->doc_begin = (size_t)-1;
3303
3416
  e->doc_content = 0;
3304
3417
  e->q_key_pending = 0;
3305
3418
  e->q_value_pending = 0;
@@ -3312,6 +3425,10 @@ static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep
3312
3425
  yep_event ev;
3313
3426
  if (emit_start) {
3314
3427
  e_event_init(&ev, YEP_EV_STREAM_START);
3428
+ ev.line = 1;
3429
+ ev.col = 1;
3430
+ ev.end_line = 1;
3431
+ ev.end_col = 1;
3315
3432
  if (emit_now(e, &ev) != 0) {
3316
3433
  return -2;
3317
3434
  }
@@ -3406,6 +3523,11 @@ static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep
3406
3523
  e->tagmap_n++;
3407
3524
  }
3408
3525
  }
3526
+ if (e->doc_begin == (size_t)-1) {
3527
+ e->doc_begin = li.offset; /* libyaml: DOCUMENT_START's
3528
+ * start_mark includes the
3529
+ * leading directive lines */
3530
+ }
3409
3531
  e_line_done(e, li.end);
3410
3532
  continue;
3411
3533
  }
@@ -3428,6 +3550,10 @@ static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep
3428
3550
  }
3429
3551
  e->doc_content = 0;
3430
3552
  e_event_init(&ev, YEP_EV_DOCUMENT_END);
3553
+ e_pos_mark(e, li.offset + li.indent, &ev.line, &ev.col);
3554
+ ev.end_line = ev.line; /* zero-span at the new marker —
3555
+ * libyaml's implicit close mark */
3556
+ ev.end_col = ev.col;
3431
3557
  if (emit_now(e, &ev) != 0) {
3432
3558
  return -2;
3433
3559
  }
@@ -3437,6 +3563,10 @@ static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep
3437
3563
  }
3438
3564
  e_event_init(&ev, YEP_EV_DOCUMENT_START);
3439
3565
  ev.style = 1; /* explicit marker */
3566
+ e_pos_mark(e, e->doc_begin != (size_t)-1 ? e->doc_begin : li.offset + li.indent,
3567
+ &ev.line, &ev.col);
3568
+ e_pos_mark(e, li.offset + li.indent + 3, &ev.end_line, &ev.end_col);
3569
+ e->doc_begin = (size_t)-1;
3440
3570
  if (emit_now(e, &ev) != 0) {
3441
3571
  return -2;
3442
3572
  }
@@ -3485,7 +3615,9 @@ static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep
3485
3615
  }
3486
3616
  }
3487
3617
  e_event_init(&ev, YEP_EV_DOCUMENT_END);
3488
- ev.style = 1; /* explicit "..." marker */
3618
+ ev.style = 1; /* explicit "..." marker */
3619
+ e_pos_mark(e, li.offset + li.indent, &ev.line, &ev.col);
3620
+ e_pos_mark(e, li.offset + li.indent + 3, &ev.end_line, &ev.end_col);
3489
3621
  e->tagmap_n = 0; /* directives are per-document */
3490
3622
  yep_nametab_clear(&e->anchors);
3491
3623
  if (emit_now(e, &ev) != 0) {
@@ -3494,6 +3626,7 @@ static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep
3494
3626
  doc_open = 0;
3495
3627
  e->doc_content = 0;
3496
3628
  e->saw_yaml = 0;
3629
+ e->doc_begin = (size_t)-1;
3497
3630
  }
3498
3631
  e_line_done(e, li.end);
3499
3632
  continue;
@@ -3501,6 +3634,14 @@ static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep
3501
3634
 
3502
3635
  if (!doc_open) {
3503
3636
  e_event_init(&ev, YEP_EV_DOCUMENT_START);
3637
+ if (e->doc_begin != (size_t)-1) {
3638
+ e_pos_mark(e, e->doc_begin, &ev.line, &ev.col);
3639
+ } else {
3640
+ e_pos_mark(e, li.offset + li.indent, &ev.line, &ev.col);
3641
+ }
3642
+ ev.end_line = ev.line;
3643
+ ev.end_col = ev.col;
3644
+ e->doc_begin = (size_t)-1;
3504
3645
  if (emit_now(e, &ev) != 0) {
3505
3646
  return -2;
3506
3647
  }
@@ -3670,6 +3811,9 @@ static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep
3670
3811
  }
3671
3812
  }
3672
3813
  e_event_init(&ev, YEP_EV_DOCUMENT_END);
3814
+ e_pos_mark(e, e->len, &ev.line, &ev.col);
3815
+ ev.end_line = ev.line;
3816
+ ev.end_col = ev.col;
3673
3817
  if (emit_now(e, &ev) != 0) {
3674
3818
  return -2;
3675
3819
  }
@@ -3678,6 +3822,9 @@ static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep
3678
3822
  }
3679
3823
  if (emit_end) {
3680
3824
  e_event_init(&ev, YEP_EV_STREAM_END);
3825
+ e_pos_mark(e, e->len, &ev.line, &ev.col);
3826
+ ev.end_line = ev.line;
3827
+ ev.end_col = ev.col;
3681
3828
  if (emit_now(e, &ev) != 0) {
3682
3829
  return -2;
3683
3830
  }
@@ -55,6 +55,12 @@ typedef struct yep_event {
55
55
  * that key on it skip the name hash entirely. */
56
56
  uint32_t line; /* 1-based position of the node start */
57
57
  uint32_t col;
58
+ uint32_t end_line; /* #179: 1-based position of the node's end —
59
+ * libyaml's end_mark semantics: a START event
60
+ * ends after its opening token, a scalar/alias
61
+ * spans anchor/tag through content, an END
62
+ * event spans its closing indicator */
63
+ uint32_t end_col;
58
64
  } yep_event;
59
65
 
60
66
  struct yep_block_value; /* value facts for on_block_pair (below) */
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yeptris
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.18.2
4
+ version: 0.6.19.1
5
5
  platform: arm-linux-eabihf
6
6
  authors:
7
7
  - Ribose Inc.
@@ -56,6 +56,7 @@ files:
56
56
  - lib/yeptris/psych/handler.rb
57
57
  - lib/yeptris/psych/parser.rb
58
58
  - lib/yeptris/psych/scalar_scanner.rb
59
+ - lib/yeptris/psych/tree_builder.rb
59
60
  - lib/yeptris/psych/visitors.rb
60
61
  - lib/yeptris/schema.rb
61
62
  - lib/yeptris/valueml.rb