Support for Enumerator inputs in the XML lexer.

This fixes #48.
This commit is contained in:
Yorick Peterse 2014-09-28 22:27:30 +02:00
parent 27ee23eb31
commit 0299ff1ea4
3 changed files with 45 additions and 22 deletions

View File

@ -66,7 +66,7 @@ module Oga
@line = 1
@elements = []
@data.rewind if io_input?
@data.rewind if @data.respond_to?(:rewind)
reset_native
end
@ -78,25 +78,18 @@ module Oga
# @yieldparam [String]
#
def read_data
# We can't check for #each_line since String also defines that. Using
# String#each_line has no benefit over just lexing the String in one
# go.
if io_input?
@data.each_line do |line|
yield line
end
else
if @data.is_a?(String)
yield @data
end
end
##
# Returns `true` if the input is an IO like object, false otherwise.
#
# @return [TrueClass|FalseClass]
#
def io_input?
return @data.is_a?(IO) || @data.is_a?(StringIO)
# IO, StringIO, etc
# THINK: read(N) would be nice, but currently this screws up the C code
elsif @data.respond_to?(:each_line)
@data.each_line { |line| yield line }
# Enumerator, Array, etc
elsif @data.respond_to?(:each)
@data.each { |chunk| yield chunk }
end
end
##

View File

@ -0,0 +1,28 @@
require 'spec_helper'
describe Oga::XML::Lexer do
context 'Enumerator as input' do
before do
@enum = Enumerator.new do |yielder|
yielder << '<p>foo'
yielder << '</p>'
end
end
example 'lex a paragraph element' do
lex(@enum).should == [
[:T_ELEM_START, nil, 1],
[:T_ELEM_NAME, 'p', 1],
[:T_TEXT, 'foo', 1],
[:T_ELEM_END, nil, 1]
]
end
example 'rewind input when resetting the lexer' do
lexer = described_class.new(@enum)
lexer.lex.empty?.should == false
lexer.lex.empty?.should == false
end
end
end

View File

@ -2,10 +2,12 @@ require 'spec_helper'
describe Oga::XML::Lexer do
context 'IO as input' do
example 'lex a paragraph element with attributes' do
io = StringIO.new("<p class='foo'>\nHello</p>")
before do
@io = StringIO.new("<p class='foo'>\nHello</p>")
end
lex(io).should == [
example 'lex a paragraph element with attributes' do
lex(@io).should == [
[:T_ELEM_START, nil, 1],
[:T_ELEM_NAME, 'p', 1],
[:T_ATTR, 'class', 1],
@ -17,7 +19,7 @@ describe Oga::XML::Lexer do
end
example 'rewind input when resetting the lexer' do
lexer = described_class.new(StringIO.new(('<a>foo</a>')))
lexer = described_class.new(@io)
lexer.lex.empty?.should == false
lexer.lex.empty?.should == false