class BinData::Base
adjust the IO offset instead of raising an error.:check_offset
, except that it will
position before reading. This is like
[:adjust_offset
] Ensures that the current IO offset is at this
before reading.
this parameter. This parameter is only checked
is made available to any lambda assigned to
to the current offset. The variable offset
success or failure. Any other return is compared
meet this criteria. A boolean return indicates
[:check_offset
] Raise an error if the current IO offset doesn’t
an object. These params are:
Parameters may be provided at initialisation to control the behaviour of
== Parameters
This is the abstract base class for all data objects.
def ==(other)
def ==(other) # double dispatch other == snapshot end
def _assign(val)
Assigns the value of +val+ to this data object. Note that +val+ will
def _assign(val) raise NotImplementedError end
def _do_num_bytes(deprecated)
def _do_num_bytes(deprecated) raise NotImplementedError end
def _do_read(io)
def _do_read(io) raise NotImplementedError end
def _do_write(io)
def _do_write(io) raise NotImplementedError end
def _done_read
def _done_read raise NotImplementedError end
def _snapshot
def _snapshot raise NotImplementedError end
def accepted_parameters
def accepted_parameters unless defined? @accepted_parameters ancestor = ancestors[1..-1].find { |cls| cls.respond_to?(:accepted_parameters) } ancestor_params = ancestor.nil? ? nil : ancestor.accepted_parameters @accepted_parameters = AcceptedParameters.new(ancestor_params) end @accepted_parameters end
def adjust_offset(io)
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
def assign(val)
Assigns the value of +val+ to this data object. Note that +val+ will
def assign(val) _assign(val) end
def check_offset(io)
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
def check_or_adjust_offset(io)
def check_or_adjust_offset(io) if has_parameter?(:check_offset) check_offset(io) elsif has_parameter?(:adjust_offset) adjust_offset(io) end end
def clear
def clear raise NotImplementedError end
def clear?
def clear? raise NotImplementedError end
def debug_name
def debug_name if parent parent.debug_name_of(self) else "obj" end end
def debug_name_of(child)
Returns the debug name of +child+. This only needs to be implemented
def debug_name_of(child) raise NotImplementedError end
def default_parameters(*args)
def default_parameters(*args) accepted_parameters.default(*args) end
def do_num_bytes(deprecated = nil)
def do_num_bytes(deprecated = nil) _do_num_bytes(deprecated) end
def do_read(io)
def do_read(io) check_or_adjust_offset(io) clear _do_read(io) end
def do_write(io)
def do_write(io) _do_write(io) end
def done_read
def done_read _done_read end
def eval_parameter(key, overrides = {})
parameters given at object construction to be overridden.
+overrides+ is an optional +parameters+ like hash that allow the
Returns the result of evaluating the parameter identified by +key+.
def eval_parameter(key, overrides = {}) LazyEvaluator.eval(self, get_parameter(key), overrides) end
def get_parameter(key)
Use this method if you are sure the parameter is not to be evaluated.
Returns the parameter referenced by +key+.
def get_parameter(key) @params[key] end
def has_parameter?(key)
def has_parameter?(key) @params.has_parameter?(key) end
def initialize(params = {}, parent = nil)
parent data object (e.g. struct, array, choice) this object resides
reference callable objects (methods or procs). +parent+ is the
+params+ is a hash containing symbol keys. Some params may
Creates a new data object.
def initialize(params = {}, parent = nil) @params = Sanitizer.sanitize(params, self.class) @parent = parent end
def inspect
def inspect snapshot.inspect end
def mandatory_parameters(*args)
def mandatory_parameters(*args) accepted_parameters.mandatory(*args) end
def mutually_exclusive_parameters(*args)
def mutually_exclusive_parameters(*args) accepted_parameters.mutually_exclusive(*args) end
def num_bytes(deprecated = nil)
def num_bytes(deprecated = nil) num = do_num_bytes(deprecated) num.ceil end
def offset
def offset if parent parent.offset_of(self) else 0 end end
def offset_of(child)
Returns the offset of +child+. This only needs to be implemented
def offset_of(child) raise NotImplementedError end
def optional_parameters(*args)
def optional_parameters(*args) accepted_parameters.optional(*args) end
def read(io)
Instantiates this class and reads from +io+, returning the newly
def read(io) data = self.new data.read(io) data end
def read(io)
def read(io) io = BinData::IO.new(io) unless BinData::IO === io do_read(io) done_read self end
def register(name, class_to_register)
def register(name, class_to_register) RegisteredClasses.register(name, class_to_register) end
def sanitize_parameters!(params, sanitizer)
def sanitize_parameters!(params, sanitizer) end
def single_value?
def single_value? warn "#single_value? is deprecated. It should no longer be needed" false end
def snapshot
def snapshot _snapshot end
def to_binary_s
def to_binary_s io = StringIO.new write(io) io.rewind io.read end
def to_s
def to_s snapshot.to_s end
def warn_replacement_parameter(params, bad_key, suggested_key)
def warn_replacement_parameter(params, bad_key, suggested_key) if params.has_parameter?(bad_key) warn ":#{bad_key} is not used with #{self}. " + "You probably want to change this to :#{suggested_key}" end end
def write(io)
def write(io) io = BinData::IO.new(io) unless BinData::IO === io do_write(io) io.flush self end