class GQTP::Parser

Attributes

header[R]

Public Class Methods

new() click to toggle source
# File lib/gqtp/parser.rb, line 86
def initialize
  reset
  initialize_hooks
end
parse(data, &block) click to toggle source
# File lib/gqtp/parser.rb, line 27
def parse(data, &block)
  if block_given?
    event_parse(data, &block)
  else
    stand_alone_parse(data)
  end
end

Private Class Methods

consume_data(parser, data) click to toggle source
# File lib/gqtp/parser.rb, line 74
def consume_data(parser, data)
  if data.respond_to?(:each)
    data.each do |chunk|
      parser << chunk
    end
  else
    parser << data
  end
end
event_parse(data) { |:on_header, header| ... } click to toggle source
# File lib/gqtp/parser.rb, line 36
def event_parse(data)
  parser = new

  parser.on_header do |header|
    yield(:on_header, header)
  end
  parser.on_body do |chunk|
    yield(:on_body, chunk)
  end
  parser.on_complete do
    yield(:on_complete)
  end

  consume_data(parser, data)
end
stand_alone_parse(data) click to toggle source
# File lib/gqtp/parser.rb, line 52
def stand_alone_parse(data)
  received_header = nil
  body = "".force_encoding("ASCII-8BIT")
  completed = false

  parser = new
  parser.on_header do |header|
    received_header = header
  end
  parser.on_body do |chunk|
    body << chunk
  end
  parser.on_complete do
    completed = true
  end

  consume_data(parser, data)
  raise ParseError, "not completed: <#{data.inspect}>" unless completed

  [received_header, body]
end

Public Instance Methods

<<(chunk) click to toggle source
# File lib/gqtp/parser.rb, line 91
def <<(chunk)
  if @header.nil?
    parse_header(chunk)
  else
    parse_body(chunk)
  end
  self
end
on_body(*arguments, &block) click to toggle source

@overload on_body(chunk) @overload on_body {|chunk| }

# File lib/gqtp/parser.rb, line 112
def on_body(*arguments, &block)
  if block_given?
    @on_body_hook = block
  else
    @on_body_hook.call(*arguments) if @on_body_hook
  end
end
on_complete(&block) click to toggle source

@overload on_complete @overload on_complete { }

# File lib/gqtp/parser.rb, line 122
def on_complete(&block)
  if block_given?
    @on_complete_hook = block
  else
    @on_complete_hook.call if @on_complete_hook
  end
end
on_header(*arguments, &block) click to toggle source

@overload on_header(header) @overload on_header {|header| }

# File lib/gqtp/parser.rb, line 102
def on_header(*arguments, &block)
  if block_given?
    @on_header_hook = block
  else
    @on_header_hook.call(*arguments) if @on_header_hook
  end
end

Private Instance Methods

initialize_hooks() click to toggle source
# File lib/gqtp/parser.rb, line 137
def initialize_hooks
  @on_header_hook = nil
  @on_body_hook = nil
  @on_complete_hook = nil
end
parse_body(chunk) click to toggle source
# File lib/gqtp/parser.rb, line 155
def parse_body(chunk)
  @body_size += chunk.bytesize
  if @body_size < @header.size
    on_body(chunk)
  elsif @body_size == @header.size
    on_body(chunk)
    on_complete
    reset
  else
    rest_body_size = @header.size - (@body_size - chunk.bytesize)
    on_body(chunk[0, rest_body_size])
    on_complete
    reset
    self << chunk[rest_body_size..-1]
  end
end
parse_header(chunk) click to toggle source
# File lib/gqtp/parser.rb, line 143
def parse_header(chunk)
  @buffer << chunk
  return if @buffer.bytesize < Header.size
  @header = Header.parse(@buffer)
  on_header(@header)
  buffer = @buffer
  @buffer = nil
  if buffer.bytesize > Header.size
    parse_body(buffer[Header.size..-1])
  end
end
reset() click to toggle source
# File lib/gqtp/parser.rb, line 131
def reset
  @buffer = "".force_encoding("ASCII-8BIT")
  @header = nil
  @body_size = 0
end