summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2012-03-08 13:23:08 -0800
committerAaron Patterson <aaron.patterson@gmail.com>2012-03-08 13:23:08 -0800
commit34d3b22d2b94e58b0e51ac922ea48d686fcbb901 (patch)
tree7b9599abf65a350c7a680f15f4ccf0614674c2f9 /lib
parent90acf338b14a31498e8888493b31a90f13978918 (diff)
downloadpsych-34d3b22d2b94e58b0e51ac922ea48d686fcbb901.zip
* ext/psych/lib/psych.rb (parse_stream, load_stream): if a block is
given, documents will be yielded to the block as they are parsed. [ruby-core:42404] [Bug #5978] * ext/psych/lib/psych/handlers/document_stream.rb: add a handler that yields documents as they are parsed * test/psych/test_stream.rb: corresponding tests.
Diffstat (limited to 'lib')
-rw-r--r--lib/psych.rb40
-rw-r--r--lib/psych/handlers/document_stream.rb22
2 files changed, 56 insertions, 6 deletions
diff --git a/lib/psych.rb b/lib/psych.rb
index cb5c4a5..69f3a7c 100644
--- a/lib/psych.rb
+++ b/lib/psych.rb
@@ -13,6 +13,7 @@ require 'psych/deprecated'
require 'psych/stream'
require 'psych/json/tree_builder'
require 'psych/json/stream'
+require 'psych/handlers/document_stream'
###
# = Overview
@@ -173,12 +174,19 @@ module Psych
# +filename+ is used in the exception message if a Psych::SyntaxError is
# raised.
#
+ # If a block is given, a Psych::Nodes::Document node will be yielded to the
+ # block as it's being parsed.
+ #
# Raises a Psych::SyntaxError when a YAML syntax error is detected.
#
# Example:
#
# Psych.parse_stream("---\n - a\n - b") # => #<Psych::Nodes::Stream:0x00>
#
+ # Psych.parse_stream("--- a\n--- b") do |node|
+ # node # => #<Psych::Nodes::Document:0x00>
+ # end
+ #
# begin
# Psych.parse_stream("--- `", "file.txt")
# rescue Psych::SyntaxError => ex
@@ -187,10 +195,15 @@ module Psych
# end
#
# See Psych::Nodes for more information about YAML AST.
- def self.parse_stream yaml, filename = nil
- parser = self.parser
- parser.parse yaml, filename
- parser.handler.root
+ def self.parse_stream yaml, filename = nil, &block
+ if block_given?
+ parser = Psych::Parser.new(Handlers::DocumentStream.new(&block))
+ parser.parse yaml, filename
+ else
+ parser = self.parser
+ parser.parse yaml, filename
+ parser.handler.root
+ end
end
###
@@ -252,12 +265,27 @@ module Psych
###
# Load multiple documents given in +yaml+. Returns the parsed documents
- # as a list. For example:
+ # as a list. If a block is given, each document will be converted to ruby
+ # and passed to the block during parsing
+ #
+ # Example:
#
# Psych.load_stream("--- foo\n...\n--- bar\n...") # => ['foo', 'bar']
#
+ # list = []
+ # Psych.load_stream("--- foo\n...\n--- bar\n...") do |ruby|
+ # list << ruby
+ # end
+ # list # => ['foo', 'bar']
+ #
def self.load_stream yaml, filename = nil
- parse_stream(yaml, filename).children.map { |child| child.to_ruby }
+ if block_given?
+ parse_stream(yaml, filename) do |node|
+ yield node.to_ruby
+ end
+ else
+ parse_stream(yaml, filename).children.map { |child| child.to_ruby }
+ end
end
###
diff --git a/lib/psych/handlers/document_stream.rb b/lib/psych/handlers/document_stream.rb
new file mode 100644
index 0000000..e429993
--- /dev/null
+++ b/lib/psych/handlers/document_stream.rb
@@ -0,0 +1,22 @@
+require 'psych/tree_builder'
+
+module Psych
+ module Handlers
+ class DocumentStream < Psych::TreeBuilder # :nodoc:
+ def initialize &block
+ super
+ @block = block
+ end
+
+ def start_document version, tag_directives, implicit
+ n = Nodes::Document.new version, tag_directives, implicit
+ push n
+ end
+
+ def end_document implicit_end = !streaming?
+ @last.implicit_end = implicit_end
+ @block.call pop
+ end
+ end
+ end
+end