leptris 1.9.16 → 1.9.17

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: 85d05772181a6d3c913f331b48f900f0781596428308759b12ac07d6cdc392d5
4
- data.tar.gz: 2e267b1225848fff3d265d0b810df576d3114e84e2a1627aacb143e650340a59
3
+ metadata.gz: 790fde1b932902a17438b2abed525393ebb61464a61ff35081384409277a42cc
4
+ data.tar.gz: 356b2a9a9426c03a25c42577952f3634127162e449e3540816b99a8bf6cd354f
5
5
  SHA512:
6
- metadata.gz: 959165b993b24b641b64246799168ef0d53d2180866596996069c28adabbf7305d1d78600af0eb25bf7bccac8a8053f6a0714d97315df61fb032fd4fcb2ef4ac
7
- data.tar.gz: 2a41355f33fcfefff1ee6b8aa2274a1d5464a8f567f611c7035df328eae3620f5b74018cea500f9bae4240593d4e8f9b9e263b17b32573e13cfcd81f4d2cd847
6
+ metadata.gz: 8fdfd7ed098ae1501040d5f82808c57813f5f2f8dec606d6ac966bd916cff635dd510ebf68e235a4a3e9c0da6a5a10cc9765ffe20eb06a476876dc2cf6dbc2fc
7
+ data.tar.gz: 26142e64a808758e72332fa8aaef029b7fee19c82c3f634f6f0ec9ba7afe7990261f958173a124f2f89ced5270c253f53256f4b12eafc99235a066e38c5b7f3a
data/CHANGELOG.md CHANGED
@@ -5,6 +5,22 @@ All notable changes to Leptris will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.9.17] - 2026-08-27
9
+
10
+ ### Changed
11
+
12
+ - **Element-hinted batch materialization**: the XPath result-set
13
+ batch (`leptris_xpath_result_get_nodes_ex`) fills an out_kinds
14
+ array the binding discarded; `Node.wrap` now accepts a known
15
+ `node_type:` so element entries skip the per-node get_type
16
+ dispatch. ELEMENT is the only hintable value — XPath's data
17
+ model reports CDATA as TEXT, so a TEXT hint cannot distinguish
18
+ Text from CDATA (different content getters); comments/CDATA/PIs
19
+ keep the get_type fallback. Cold 500-element materialization:
20
+ 0.131 s -> 0.110 s (~15%). Upstream note: a full-type out_kinds
21
+ (or kinds on `leptris_node_children`) belongs to the #560/#562
22
+ ask family.
23
+
8
24
  ## [1.9.16] - 2026-08-27
9
25
 
10
26
  ### Changed
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Leptris
4
- VERSION = "1.9.16"
4
+ VERSION = "1.9.17"
5
5
  end
@@ -747,14 +747,27 @@ module Leptris
747
747
  end
748
748
 
749
749
  # XPath result-set batch (leptris_xpath_result_get_nodes_ex):
750
- # copies all node kinds into a caller buffer and hands back
751
- # the pointer array.
750
+ # the call fills out_kinds in the 4-value XPATH_NODE space
751
+ # (ELEMENT/ATTRIBUTE/TEXT/OTHER). ELEMENT is the only value
752
+ # that maps unambiguously — XPath's data model reports CDATA
753
+ # as TEXT, so a TEXT hint cannot distinguish Text from CDATA
754
+ # (different content getters) — everything else falls back to
755
+ # get_type in the wrapper. Returns [pointers, element_hints].
756
+ XPATH_KIND_HINT = { XPATH_NODE_ELEMENT => NODE_ELEMENT }.freeze
757
+
752
758
  def self.fetch_result_nodes(result_ptr, count)
753
- return [] if count.zero?
759
+ return [[], nil] if count.zero?
754
760
  with_pointer_buffer(count) do |buffer|
755
- copied = leptris_xpath_result_get_nodes_ex(
756
- result_ptr, buffer, nil, count)
757
- buffer.get_array_of_pointer(0, copied)
761
+ kinds = ::FFI::MemoryPointer.new(:int, count)
762
+ begin
763
+ copied = leptris_xpath_result_get_nodes_ex(
764
+ result_ptr, buffer, kinds, count)
765
+ hints = kinds.get_array_of_int(0, copied)
766
+ .map { |k| XPATH_KIND_HINT[k] }
767
+ [buffer.get_array_of_pointer(0, copied), hints]
768
+ ensure
769
+ kinds.free
770
+ end
758
771
  end
759
772
  end
760
773
 
@@ -12,7 +12,10 @@ class Leptris::XML::Node
12
12
  @node_type = node_type
13
13
  end
14
14
 
15
- def self.wrap(c_ptr, document, parent: nil)
15
+ # node_type: callers holding a batch-fetched kind (the XPath
16
+ # result-set batch fills out_kinds) pass it so the wrap skips the
17
+ # get_type dispatch; nil (the default) dispatches as before.
18
+ def self.wrap(c_ptr, document, parent: nil, node_type: nil)
16
19
  # Per-document weak-ref cache. Returns the existing wrapper when the
17
20
  # same c_ptr is wrapped twice (common in children/sibling walks,
18
21
  # repeated xpath queries, traverse-then-access patterns). The cache
@@ -21,7 +24,7 @@ class Leptris::XML::Node
21
24
  return cached
22
25
  end
23
26
 
24
- node_type = Leptris::XML::FFI.leptris_node_get_type(c_ptr)
27
+ node_type ||= Leptris::XML::FFI.leptris_node_get_type(c_ptr)
25
28
  node =
26
29
  case node_type
27
30
  when Leptris::XML::FFI::NODE_ELEMENT
@@ -81,11 +81,11 @@ class Leptris::XML::NodeSet
81
81
  # not just elements); the batch accessor under-copies
82
82
  # mixed-kind results (upstream leptris#477), so per-index
83
83
  # fetch covers the remainder.
84
- pointers = Leptris::XML::FFI.fetch_result_nodes(@result_ptr, n)
84
+ pointers, kinds = Leptris::XML::FFI.fetch_result_nodes(@result_ptr, n)
85
85
  nodes = []
86
- pointers.each do |ptr|
86
+ pointers.each_with_index do |ptr, i|
87
87
  next if ptr.null?
88
- nodes << Leptris::XML::Node.wrap(ptr, @document)
88
+ nodes << Leptris::XML::Node.wrap(ptr, @document, node_type: kinds[i])
89
89
  end
90
90
  (pointers.length...n).each do |i|
91
91
  ptr = Leptris::XML::FFI.leptris_xpath_result_get_node(@result_ptr, i)
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.16
4
+ version: 1.9.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.