class CouchRest::StreamRowParser
CouchRest
Stream Row Parser
Will parse a stream containing a standard CouchDB response including rows. Allows each row to be parsed individually, and provided in a block for efficient memory usage.
The StreamRowParser#parse
method expects to be called multiple times with segments of data, typcially provided by the Net::HTTPResponse#read_body method.
Data will be cached until usable objects can be extracted in rows and provied in the block.
Attributes
header[RW]
String containing the fields provided before and after the rows.
row_level[R]
The row level at which we expect to receive “rows” of data. Typically this will be 0 for contious feeds, and 1 for most other users.
Public Class Methods
new(mode = :array)
click to toggle source
Instantiate a new StreamRowParser
with the mode set according to the type of data. The supported modes are:
* `:array` - objects are contianed in a data array, the default. * `:feed` - each row of the stream is an object, like in continuous changes feeds.
# File lib/couchrest/helper/stream_row_parser.rb, line 29 def initialize(mode = :array) @header = "" @data = "" @string = false @escape = false @row_level = mode == :array ? 1 : 0 @in_rows = false @obj_level = 0 @obj_close = false end
Public Instance Methods
parse(segment, &block)
click to toggle source
# File lib/couchrest/helper/stream_row_parser.rb, line 41 def parse(segment, &block) @in_rows = true if @row_level == 0 segment.each_char do |c| if @string # Inside a string, handling escaping and closure if @escape @escape = false else if c == '"' @string = false elsif c == '\\' @escape = true end end else # Inside an object @obj_close = false if @obj_level == @row_level && c == "[" # start of rows @in_rows = true elsif @obj_level == @row_level && c == "]" # end of rows @in_rows = false elsif c == "{" # object @obj_level += 1 elsif c == "}" # object end @obj_level -= 1 @obj_close = true elsif c == '"' @string = true end end # Append data if @row_level > 0 if @obj_level == 0 || (@obj_level == @row_level && !@obj_close) @header << c unless @in_rows && (c == ',' || c == ' ' || c == "\n") # skip row whitespace else @data << c end else @data << c end # Determine if we need to trigger an event if @obj_close && @obj_level == @row_level block.call(@data) @data = "" end end end