Class: Leptris::XML::Pull::Parser
- Inherits:
-
Object
- Object
- Leptris::XML::Pull::Parser
- Defined in:
- lib/leptris/xml/pull.rb
Class Method Summary collapse
Instance Method Summary collapse
- #each ⇒ Object
-
#each_batch(max_count = 256) ⇒ Object
Bulk-delivers events (libleptris 1.9.7, upstream #589): ONE C call stages up to
max_countevents — the per-event dispatch that made streaming ~145x slower than a DOM parse collapses to amortized noise. -
#free ⇒ Object
Releases the C parser.
-
#initialize(handle) ⇒ Parser
constructor
A new instance of Parser.
-
#next_event ⇒ Object
Advances the cursor and returns the next Event, or nil after the end of the document.
Constructor Details
#initialize(handle) ⇒ Parser
Returns a new instance of Parser.
43 44 45 46 |
# File 'lib/leptris/xml/pull.rb', line 43 def initialize(handle) raise Leptris::XML::ParseError, "leptris_pull_new failed" if handle.null? @handle = handle end |
Class Method Details
Instance Method Details
#each ⇒ Object
55 56 57 58 59 60 61 62 63 64 |
# File 'lib/leptris/xml/pull.rb', line 55 def each return enum_for(:each) unless block_given? loop do event = next_event break if event.nil? yield event break if event.type == :end_document || event.type == :error end self end |
#each_batch(max_count = 256) ⇒ Object
Bulk-delivers events (libleptris 1.9.7, upstream #589): ONE C
call stages up to max_count events — the per-event dispatch
that made streaming ~145x slower than a DOM parse collapses to
amortized noise. Per the engine's protocol, attributes are
captured only for the LAST start_element of each batch
(earlier starts in the same batch carry nil attrs — segment
boundaries fall where they fall); use #each when every
start's attrs must be captured.
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/leptris/xml/pull.rb', line 74 def each_batch(max_count = 256) return enum_for(:each_batch, max_count) unless block_given? stride = Leptris::XML::FFI::PullEventStruct.size type_off = 0 name_off = Leptris::XML::FFI::PullEventStruct.offset_of(:name) text_off = Leptris::XML::FFI::PullEventStruct.offset_of(:text) buffer = Leptris::XML::FFI.scratch_events(max_count) while (n = Leptris::XML::FFI.leptris_pull_next_batch( @handle, buffer, max_count)) > 0 events = Array.new(n) do |i| base = i * stride name_ptr = buffer.get_pointer(base + name_off) text_ptr = buffer.get_pointer(base + text_off) Event.new( TYPES[buffer.get_int(base + type_off)], name_ptr.null? ? nil : name_ptr.read_string.force_encoding(Encoding::UTF_8), text_ptr.null? ? nil : text_ptr.read_string.force_encoding(Encoding::UTF_8), nil ) end # The attr mirror holds the batch's most recent start. last_start = nil events.each_with_index do |event, i| last_start = i if event.type == :start_element end events[last_start].attrs = capture_attrs if last_start events.each { |event| yield event } tail = events.last.type break if tail == :end_document || tail == :error end self end |
#free ⇒ Object
Releases the C parser. Safe to call twice.
49 50 51 52 53 |
# File 'lib/leptris/xml/pull.rb', line 49 def free return if @handle.nil? Leptris::XML::FFI.leptris_pull_free(@handle) @handle = nil end |
#next_event ⇒ Object
Advances the cursor and returns the next Event, or nil after the end of the document. Attribute values are captured during start_element because the C accessors are valid only for the most recently returned event.
121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/leptris/xml/pull.rb', line 121 def next_event raw = Leptris::XML::FFI.leptris_pull_next(@handle) return nil if raw.null? type = TYPES[raw.get_int(0)] name_ptr = raw.get_pointer(NAME_OFFSET) text_ptr = raw.get_pointer(TEXT_OFFSET) attrs = type == :start_element ? capture_attrs : nil Event.new( type, name_ptr.null? ? nil : name_ptr.read_string.force_encoding(Encoding::UTF_8), text_ptr.null? ? nil : text_ptr.read_string.force_encoding(Encoding::UTF_8), attrs ) end |