diff --git a/lib/oga/xml/lexer.rb b/lib/oga/xml/lexer.rb index 1fd396d..b28a5ae 100644 --- a/lib/oga/xml/lexer.rb +++ b/lib/oga/xml/lexer.rb @@ -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 ## diff --git a/spec/oga/xml/lexer/enumerator_spec.rb b/spec/oga/xml/lexer/enumerator_spec.rb new file mode 100644 index 0000000..afda915 --- /dev/null +++ b/spec/oga/xml/lexer/enumerator_spec.rb @@ -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 << '

foo' + yielder << '

' + 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 diff --git a/spec/oga/xml/lexer/io_spec.rb b/spec/oga/xml/lexer/io_spec.rb index 35c41b1..66c8f63 100644 --- a/spec/oga/xml/lexer/io_spec.rb +++ b/spec/oga/xml/lexer/io_spec.rb @@ -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("

\nHello

") + before do + @io = StringIO.new("

\nHello

") + 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(('foo'))) + lexer = described_class.new(@io) lexer.lex.empty?.should == false lexer.lex.empty?.should == false