module BinData
# WARNING: THIS IS UNSUPPORTED!!
#
# This was a (failed) experimental feature that allowed seeking within the
# input stream. It remains here for backwards compatability for the few
# people that used it.
#
# The official way to skip around the stream is to use BinData::Skip with
# the `:to_abs_offset` parameter.
#
# == Parameters
#
# Parameters may be provided at initialisation to control the behaviour of
# an object. These parameters are:
#
# [:check_offset] Raise an error if the current IO offset doesn't
# meet this criteria. A boolean return indicates
# success or failure. Any other return is compared
# to the current offset. The variable +offset+
# is made available to any lambda assigned to
# this parameter. This parameter is only checked
# before reading.
# [:adjust_offset] Ensures that the current IO offset is at this
# position before reading. This is like
# :check_offset, except that it will
# adjust the IO offset instead of raising an error.
module CheckOrAdjustOffsetPlugin
def self.included(base) #:nodoc:
base.optional_parameters :check_offset, :adjust_offset
base.mutually_exclusive_parameters :check_offset, :adjust_offset
end
def initialize_shared_instance
extend CheckOffsetMixin if has_parameter?(:check_offset)
extend AdjustOffsetMixin if has_parameter?(:adjust_offset)
super
end
module CheckOffsetMixin
def do_read(io) #:nodoc:
check_offset(io)
super(io)
end
#---------------
private
def check_offset(io)
actual_offset = io.offset
expected = eval_parameter(:check_offset, :offset => actual_offset)
if not expected
raise ValidityError, "offset not as expected for #{debug_name}"
elsif actual_offset != expected and expected != true
raise ValidityError,
"offset is '#{actual_offset}' but " +
"expected '#{expected}' for #{debug_name}"
end
end
end
module AdjustOffsetMixin
def do_read(io) #:nodoc:
adjust_offset(io)
super(io)
end
#---------------
private
def adjust_offset(io)
actual_offset = io.offset
expected = eval_parameter(:adjust_offset)
if actual_offset != expected
begin
seek = expected - actual_offset
io.seekbytes(seek)
warn "adjusting stream position by #{seek} bytes" if $VERBOSE
rescue
raise ValidityError,
"offset is '#{actual_offset}' but couldn't seek to " +
"expected '#{expected}' for #{debug_name}"
end
end
end
end
end
# Add these offset options to Base
class Base
include CheckOrAdjustOffsetPlugin
end
end