Class: Leptris::XML::Pull::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/leptris/xml/pull.rb

Class Method Summary collapse

Instance Method Summary collapse

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

.parse(xml_or_io) ⇒ Object



34
35
36
37
# File 'lib/leptris/xml/pull.rb', line 34

def self.parse(xml_or_io)
  xml = xml_or_io.respond_to?(:read) ? xml_or_io.read : xml_or_io.to_s
  new(Leptris::XML::FFI.leptris_pull_new(xml, xml.bytesize))
end

.parse_file(path) ⇒ Object



39
40
41
# File 'lib/leptris/xml/pull.rb', line 39

def self.parse_file(path)
  new(Leptris::XML::FFI.leptris_pull_new_file(path))
end

Instance Method Details

#eachObject



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

#freeObject

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_eventObject

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