leptris 1.9.209.0 → 1.9.209.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/leptris/native/native.c +28 -0
- data/lib/leptris/vendor/aarch64-linux-musl/libleptris.so +0 -0
- data/lib/leptris/version.rb +1 -1
- data/lib/leptris/xml/element.rb +25 -0
- data/lib/leptris/xml/iterparse.rb +14 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c7f9ee6f6fa740c91bbb444f605bd68fcae043d8184f220774e89b749eb521fc
|
|
4
|
+
data.tar.gz: b22ed76f401235b0731cbeeeec011655a07ffd189e02a25dd675659fd076798f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a9bd90a1a9d941ad5814a13dd659213de9ab86e21e38a8064b681d6d127fe91c935ba5635a2b2e4938699769aca76953e8bcb4db42fee893eef5ab6f55166cb3
|
|
7
|
+
data.tar.gz: f261d4206b02aefa6bfbc57866da62f82c627059fba9fdbab640178e3e7ab6cf19272b6590f20587e50efe170872368930ce5f117d604f1c9c225746643d3cf9
|
data/ext/leptris/native/native.c
CHANGED
|
@@ -1932,6 +1932,32 @@ static void walk_rows_impl(void *node, int depth, VALUE out)
|
|
|
1932
1932
|
}
|
|
1933
1933
|
}
|
|
1934
1934
|
|
|
1935
|
+
/* ---- Attribute pairs (leptris-ruby#278) --------------------------
|
|
1936
|
+
* Read-only attribute listing as a flat [name, value, ...] array —
|
|
1937
|
+
* names interned (they repeat across documents), values fresh
|
|
1938
|
+
* UTF-8 strings, document order, duplicates included, NO Attr
|
|
1939
|
+
* objects minted. One crossing per element; the walk-hot shape for
|
|
1940
|
+
* consumers that only read name/value. Mutation and per-attribute
|
|
1941
|
+
* namespace resolution stay on attribute_nodes. */
|
|
1942
|
+
static VALUE nf_attribute_pairs(VALUE self, VALUE document, VALUE addr)
|
|
1943
|
+
{
|
|
1944
|
+
(void)self;
|
|
1945
|
+
(void)document;
|
|
1946
|
+
void *node = (void *)(uintptr_t)NUM2ULL(addr);
|
|
1947
|
+
VALUE out = rb_ary_new();
|
|
1948
|
+
if (f_node_type(node) != WS_NODE_ELEMENT) return out;
|
|
1949
|
+
|
|
1950
|
+
for (void *a = f_attr_first(node); a; a = f_attr_next(a)) {
|
|
1951
|
+
const char *an = f_attr_name(a);
|
|
1952
|
+
const char *av = f_attr_value(node, a);
|
|
1953
|
+
rb_ary_push(out, an ? rb_enc_interned_str(an, strlen(an),
|
|
1954
|
+
rb_utf8_encoding())
|
|
1955
|
+
: Qnil);
|
|
1956
|
+
rb_ary_push(out, av ? rb_utf8_str_new_cstr(av) : Qnil);
|
|
1957
|
+
}
|
|
1958
|
+
return out;
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1935
1961
|
static VALUE nf_snapshot_rows(VALUE self, VALUE document, VALUE addr)
|
|
1936
1962
|
{
|
|
1937
1963
|
(void)self;
|
|
@@ -2606,6 +2632,8 @@ void Init_native(void)
|
|
|
2606
2632
|
nf_snapshot_subtree, 2);
|
|
2607
2633
|
rb_define_module_function(m_native, "snapshot_rows",
|
|
2608
2634
|
nf_snapshot_rows, 2);
|
|
2635
|
+
rb_define_module_function(m_native, "attribute_pairs",
|
|
2636
|
+
nf_attribute_pairs, 2);
|
|
2609
2637
|
rb_define_module_function(m_native, "plan_structs",
|
|
2610
2638
|
nf_plan_structs, 3);
|
|
2611
2639
|
rb_define_module_function(m_native, "doc_handle_attach",
|
|
Binary file
|
data/lib/leptris/version.rb
CHANGED
data/lib/leptris/xml/element.rb
CHANGED
|
@@ -284,6 +284,31 @@ class Leptris::XML::Element < Leptris::XML::Node
|
|
|
284
284
|
result
|
|
285
285
|
end
|
|
286
286
|
|
|
287
|
+
# Read-only attribute listing as [name, value] pairs — no Attr
|
|
288
|
+
# objects. Names are interned frozen strings (shared across
|
|
289
|
+
# documents; dup before mutating), values fresh UTF-8 strings.
|
|
290
|
+
# Document order, duplicates included. One C crossing per element
|
|
291
|
+
# on the native layer (leptris-ruby#278) — the walk-hot shape for
|
|
292
|
+
# consumers that only read name/value. Mutation and per-attribute
|
|
293
|
+
# namespace resolution stay on attribute_nodes.
|
|
294
|
+
def attribute_pairs
|
|
295
|
+
ensure_alive!
|
|
296
|
+
return @attribute_pairs if memo_hit?(@attribute_pairs_version)
|
|
297
|
+
result = if @c_address && @document &&
|
|
298
|
+
defined?(::Leptris::XML::Native) &&
|
|
299
|
+
::Leptris::XML::Native.respond_to?(:attribute_pairs)
|
|
300
|
+
::Leptris::XML::Native.attribute_pairs(@document, @c_address)
|
|
301
|
+
.each_slice(2).to_a
|
|
302
|
+
else
|
|
303
|
+
each_attribute.to_a.map { |a| [a.name, a.value] }
|
|
304
|
+
end
|
|
305
|
+
if @document
|
|
306
|
+
@attribute_pairs = result
|
|
307
|
+
@attribute_pairs_version = @document.version
|
|
308
|
+
end
|
|
309
|
+
result
|
|
310
|
+
end
|
|
311
|
+
|
|
287
312
|
def attribute_nodes
|
|
288
313
|
return @attribute_nodes if memo_hit?(@attribute_nodes_version)
|
|
289
314
|
result = each_attribute.to_a
|
|
@@ -46,6 +46,12 @@ class Leptris::XML::Iterparse
|
|
|
46
46
|
xml = xml_or_io.is_a?(String) ? xml_or_io : xml_or_io.read
|
|
47
47
|
iterator = new(Leptris::XML::FFI.leptris_iterparse_new_ex(
|
|
48
48
|
xml, xml.bytesize, mode_code(mode)))
|
|
49
|
+
# leptris_iterparse_new_ex retains the buffer and reads it
|
|
50
|
+
# lazily in bounded slices (#1207-class): without this
|
|
51
|
+
# reference the input String is collectable the moment parse
|
|
52
|
+
# returns, and the iterator walks freed memory — attribute
|
|
53
|
+
# reads intermittently come back nil (#279)
|
|
54
|
+
iterator.keepalive_input(xml)
|
|
49
55
|
return iterator unless block
|
|
50
56
|
begin
|
|
51
57
|
iterator.run(&block)
|
|
@@ -78,9 +84,17 @@ class Leptris::XML::Iterparse
|
|
|
78
84
|
def initialize(handle)
|
|
79
85
|
raise Leptris::XML::ParseError, "leptris_iterparse_new failed" if handle.null?
|
|
80
86
|
@handle = handle
|
|
87
|
+
@input_keepalive = nil
|
|
81
88
|
@scope = Leptris::XML::IterationScope.new(handle)
|
|
82
89
|
end
|
|
83
90
|
|
|
91
|
+
# Pins the input buffer for the iterator's lifetime (see
|
|
92
|
+
# self.parse). Public but internal — not part of the API.
|
|
93
|
+
def keepalive_input(buffer)
|
|
94
|
+
@input_keepalive = buffer
|
|
95
|
+
self
|
|
96
|
+
end
|
|
97
|
+
|
|
84
98
|
# Yields completed elements until the document is exhausted or the
|
|
85
99
|
# parse fails (see #error). Does not free the iterator — the block
|
|
86
100
|
# form of .parse/.parse_file does, or call #free explicitly.
|