leptris 1.9.239.0 → 1.9.240.0

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: a9988358313da5babf4756d5a3393ff7a805eaabb0a6c04a240bf75173f8248b
4
- data.tar.gz: 80ddb8c442105e7afad9a1cc40e010f670e115f61e295978157182889a6f2c6e
3
+ metadata.gz: 91e18b7955af279de38382142b10d20f972c5d8fb1ceb02216efdcae5b572e8d
4
+ data.tar.gz: f30f6e5564aac12de9a5a074be4ebd706bb6fba196911fbbd752229507763b0a
5
5
  SHA512:
6
- metadata.gz: 194a8513e590353c118ff58cac0700789337ce254d8b138e5818a228134f75a5d40f2e4a54cbd8045900182bdb25ea8ca706efe5731e6ae0b3b086d16842f59a
7
- data.tar.gz: 887dbf39367b2cf2397a493c59d2bb569212acefd4a11f8c1bcd5cbc167640d254e03f4099a71b11c3a9c5f19dcf7c1c75bc4831b6aee1b2533c3cf1f9c3a790
6
+ metadata.gz: 3cc5846626e6feac81081470224e77a47da5e6094c4d57c7444d2135837aea33cdb799d34437cd717f0a4f7ae28f9df2abd0f8a3772d204693b4c27871bc4d2f
7
+ data.tar.gz: fa24557f80e5182058a320a7cf87fae1644f324750a767c971aa0a836afe2fd611fc610b0f4e57d34a862b6eabe689b13c146b8db5a98fe25f37c68dfbbee882
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Leptris
4
- VERSION = "1.9.239.0"
4
+ VERSION = "1.9.240.0"
5
5
  end
@@ -232,6 +232,32 @@ module Leptris
232
232
  SAX_EVENT_END_PREFIX = 9
233
233
  SAX_EVENT_ERROR = 10
234
234
 
235
+ # LeptrisSaxRecord (sax.h, #1298): one element or text record;
236
+ # tree as parent/next_sib record indices, strings (off,len)
237
+ # views into the records buffer. 10 x uint32 + uint8.
238
+ class SaxRecord < ::FFI::Struct
239
+ layout :kind, :uint32,
240
+ :parent, :uint32, :next_sib, :uint32,
241
+ :off, :uint32, :len, :uint32,
242
+ :line, :uint32, :start_tag_end, :uint32,
243
+ :elem_end, :uint32, :attr_first, :uint32,
244
+ :attr_count, :uint32,
245
+ :self_closing, :uint8
246
+ end
247
+
248
+ SAX_REC_ELEMENT = 0
249
+ SAX_REC_TEXT = 1
250
+ SAX_REC_NO_INDEX = 0xFFFFFFFF
251
+
252
+ # LeptrisSaxAttr: flat attribute table entry — qname + raw
253
+ # value views, value_has_ws = literal \t/\n/\r present (the
254
+ # CONSUMER applies 3.3.3 normalization). 4 x uint32 + uint8.
255
+ class SaxAttr < ::FFI::Struct
256
+ layout :name_off, :uint32, :name_len, :uint32,
257
+ :value_off, :uint32, :value_len, :uint32,
258
+ :value_has_ws, :uint8
259
+ end
260
+
235
261
  ITERPARSE_TOP_LEVEL = 0
236
262
  ITERPARSE_FULL_DOCUMENT = 1
237
263
 
@@ -1049,7 +1075,10 @@ attach_function :leptris_parse_string,
1049
1075
  attach_function :leptris_sax_records_data, [:pointer], :pointer
1050
1076
  attach_function :leptris_sax_records_attrs,
1051
1077
  [:pointer, :pointer], :pointer
1052
- attach_function :leptris_sax_records_buffer, [:pointer], UTF8_STRING
1078
+ # :pointer, NOT UTF8_STRING — the buffer carries embedded NULs
1079
+ # between views; a C string read would truncate at the first.
1080
+ # Views materialize via Pointer#get_string(off, len).
1081
+ attach_function :leptris_sax_records_buffer, [:pointer], :pointer
1053
1082
  attach_function :leptris_sax_records_free, [:pointer], :void
1054
1083
  # XSLT 1.0 engine (libleptris 1.9.1): compile once, apply many.
1055
1084
  # XQuery 1.0 core (libleptris 1.9.64-1.9.66): orchestration
@@ -1284,6 +1313,7 @@ attach_function :leptris_parse_string,
1284
1313
  LEPTRIS_ERROR_NOT_FOUND = -6
1285
1314
  LEPTRIS_ERROR_IO = -7
1286
1315
  LEPTRIS_ERROR_NOT_IMPLEMENTED = -8
1316
+ LEPTRIS_ERROR_NOT_SUPPORTED = -9
1287
1317
 
1288
1318
  XPATH_NODESET = 0
1289
1319
  XPATH_BOOLEAN = 1
@@ -0,0 +1,134 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Bulk SAX records (leptris#1298, engine leptris_sax_records_parse,
4
+ # 1.9.223+): ONE crossing drains the whole document into a flat
5
+ # record table — elements and text runs in document order, the tree
6
+ # as parent/next-sibling record indices, attributes an index range
7
+ # into a flat table, every string an (off,len) view into one
8
+ # NUL-padded buffer. The engine mints zero per-event strings; hosts
9
+ # materialize only what they consume (name/value String = one
10
+ # get_string each).
11
+ #
12
+ # Coverage: the interleaved lane's scannable subset — elements, text,
13
+ # attributes; well-formed entity-free documents without comments/
14
+ # PIs/CDATA/DOCTYPE/xmlns. Outside the subset .open answers nil
15
+ # (LEPTRIS_ERROR_NOT_SUPPORTED, zero allocation) and callers fall
16
+ # back to the callback Recorder; correctness is bit-identical.
17
+ #
18
+ # Field columns materialize once per drain via
19
+ # Pointer#read_array_of_uint32 (no Ruby object per record); the
20
+ # self_closing flag rides a separate uint8 column because it shares
21
+ # its struct tail with padding.
22
+ class Leptris::XML::SAX::Records
23
+ KIND_ELEMENT = Leptris::XML::FFI::SAX_REC_ELEMENT
24
+ KIND_TEXT = Leptris::XML::FFI::SAX_REC_TEXT
25
+
26
+ REC = Leptris::XML::FFI::SaxRecord
27
+ ATTR = Leptris::XML::FFI::SaxAttr
28
+ REC_U32 = REC.size / 4
29
+ ATTR_U32 = ATTR.size / 4
30
+
31
+ attr_reader :count, :attr_count
32
+
33
+ # Drains xml into a table. Returns nil unless the document drained
34
+ # cleanly — outside the scannable subset (NOT_SUPPORTED, zero
35
+ # allocation) OR malformed (the callback path reports parse errors
36
+ # with position) — callers fall back to the callback Recorder in
37
+ # every nil case; correctness is bit-identical.
38
+ def self.open(xml)
39
+ xml = xml.to_s
40
+ out = ::FFI::MemoryPointer.new(:pointer)
41
+ status = Leptris::XML::FFI.leptris_sax_records_parse(
42
+ xml, xml.bytesize, 0, out
43
+ )
44
+ return nil unless status == Leptris::XML::FFI::LEPTRIS_OK
45
+
46
+ new(out.read_pointer)
47
+ end
48
+
49
+ # Block form: the table dies at the end of the block — every view
50
+ # dies with it, so materialize inside.
51
+ def self.parse(xml)
52
+ table = open(xml)
53
+ return nil unless table
54
+
55
+ begin
56
+ yield table
57
+ ensure
58
+ table.free
59
+ end
60
+ end
61
+
62
+ def initialize(ptr)
63
+ @ptr = ptr
64
+ @count = Leptris::XML::FFI.leptris_sax_records_count(@ptr)
65
+ recs = Leptris::XML::FFI.leptris_sax_records_data(@ptr)
66
+ attr_out = ::FFI::MemoryPointer.new(:pointer)
67
+ attrs = Leptris::XML::FFI.leptris_sax_records_attrs(@ptr, attr_out)
68
+ @attr_count = attr_out.read_uint64
69
+ @buf = Leptris::XML::FFI.leptris_sax_records_buffer(@ptr)
70
+ # Whole-table single reads: no Ruby object per record. The u32
71
+ # columns stride by struct size; the flags (self_closing /
72
+ # value_has_ws) are u8 tails read per-byte off their layout
73
+ # offset — endian-safe.
74
+ @rec_u32 = recs.read_array_of_uint32(@count * REC_U32)
75
+ @rec_flag = recs.read_array_of_uint8(@count * REC.size)
76
+ @attr_u32 = attrs.read_array_of_uint32(@attr_count * ATTR_U32)
77
+ @attr_flag = attrs.read_array_of_uint8(@attr_count * ATTR.size)
78
+ @rec_flag_off = REC.offset_of(:self_closing)
79
+ @attr_flag_off = ATTR.offset_of(:value_has_ws)
80
+ end
81
+
82
+ def free
83
+ return if @ptr.nil?
84
+
85
+ Leptris::XML::FFI.leptris_sax_records_free(@ptr)
86
+ @ptr = nil
87
+ end
88
+
89
+ def kind(i)
90
+ @rec_u32[i * REC_U32]
91
+ end
92
+
93
+ # Parent record index (0xFFFFFFFF for document-level records).
94
+ def parent(i)
95
+ @rec_u32[i * REC_U32 + 1]
96
+ end
97
+
98
+ # Element name or text content — ONE String per call, UTF-8.
99
+ def view(i)
100
+ base = i * REC_U32
101
+ @buf.get_string(@rec_u32[base + 3], @rec_u32[base + 4])
102
+ .force_encoding(Encoding::UTF_8)
103
+ end
104
+
105
+ def self_closing?(i)
106
+ @rec_flag[i * REC.size + @rec_flag_off] != 0
107
+ end
108
+
109
+ def attr_first(i)
110
+ @rec_u32[i * REC_U32 + 8]
111
+ end
112
+
113
+ def attr_count_of(i)
114
+ @rec_u32[i * REC_U32 + 9]
115
+ end
116
+
117
+ def attr_name(k)
118
+ @buf.get_string(@attr_u32[k * ATTR_U32],
119
+ @attr_u32[k * ATTR_U32 + 1])
120
+ .force_encoding(Encoding::UTF_8)
121
+ end
122
+
123
+ def attr_value(k)
124
+ @buf.get_string(@attr_u32[k * ATTR_U32 + 2],
125
+ @attr_u32[k * ATTR_U32 + 3])
126
+ .force_encoding(Encoding::UTF_8)
127
+ end
128
+
129
+ # Literal \t/\n/\r in the raw value — the consumer applies
130
+ # XML 1.0 §3.3.3 (map each break byte to a space).
131
+ def attr_value_has_ws?(k)
132
+ @attr_flag[k * ATTR.size + @attr_flag_off] != 0
133
+ end
134
+ end
@@ -9,6 +9,7 @@ module Leptris
9
9
  autoload :Parser, "leptris/xml/sax/parser"
10
10
  autoload :Recorder, "leptris/xml/sax/recorder"
11
11
  autoload :DomDispatch, "leptris/xml/sax/dom_dispatch"
12
+ autoload :Records, "leptris/xml/sax/records"
12
13
  end
13
14
  end
14
15
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leptris
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.239.0
4
+ version: 1.9.240.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
@@ -197,6 +197,7 @@ files:
197
197
  - lib/leptris/xml/sax/dom_dispatch.rb
198
198
  - lib/leptris/xml/sax/parser.rb
199
199
  - lib/leptris/xml/sax/recorder.rb
200
+ - lib/leptris/xml/sax/records.rb
200
201
  - lib/leptris/xml/schematron.rb
201
202
  - lib/leptris/xml/searchable.rb
202
203
  - lib/leptris/xml/serialization.rb