1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
|
module BinData
# reference to the current tracer
@tracer ||= nil
class Tracer #:nodoc:
def initialize(io)
@trace_io = io
end
def trace(msg)
@trace_io.puts(msg)
end
def trace_obj(obj_name, val)
if val.length > 30
val = val.slice(0..30) + "..."
end
trace "#{obj_name} => #{val}"
end
end
# Turn on trace information when reading a BinData object.
# If +block+ is given then the tracing only occurs for that block.
# This is useful for debugging a BinData declaration.
def trace_reading(io = STDERR)
@tracer = Tracer.new(io)
[BasePrimitive, Choice].each(&:turn_on_tracing)
if block_given?
begin
yield
ensure
[BasePrimitive, Choice].each(&:turn_off_tracing)
@tracer = nil
end
end
end
def trace_message #:nodoc:
yield @tracer if @tracer
end
module_function :trace_reading, :trace_message
class BasePrimitive < BinData::Base
class << self
def turn_on_tracing
alias_method :do_read_without_hook, :do_read
alias_method :do_read, :do_read_with_hook
end
def turn_off_tracing
alias_method :do_read, :do_read_without_hook
end
end
def do_read_with_hook(io)
do_read_without_hook(io)
trace_value
end
def trace_value
BinData.trace_message do |tracer|
value_string = _value.inspect
tracer.trace_obj(debug_name, value_string)
end
end
end
class Choice < BinData::Base
class << self
def turn_on_tracing
alias_method :do_read_without_hook, :do_read
alias_method :do_read, :do_read_with_hook
end
def turn_off_tracing
alias_method :do_read, :do_read_without_hook
end
end
def do_read_with_hook(io)
trace_selection
do_read_without_hook(io)
end
def trace_selection
BinData.trace_message do |tracer|
selection_string = eval_parameter(:selection).inspect
tracer.trace_obj("#{debug_name}-selection-", selection_string)
end
end
end
end
|