class BinData::Base
This is the abstract base class for all data objects.
def ==(other) #:nodoc:
def ==(other) #:nodoc: # double dispatch other == snapshot end
def =~(other)
def =~(other) snapshot =~ other end
def abs_offset
Returns the offset (in bytes) of this object with respect to its most
def abs_offset if @parent @parent.abs_offset + @parent.offset_of(self) else 0 end end
def arg_processor(name = nil)
def arg_processor(name = nil) @arg_processor ||= nil if name @arg_processor = "#{name}_arg_processor".gsub(/(?:^|_)(.)/) { $1.upcase }.to_sym elsif @arg_processor.is_a? Symbol @arg_processor = BinData.const_get(@arg_processor).new elsif @arg_processor.nil? @arg_processor = superclass.arg_processor else @arg_processor end end
def auto_call_delayed_io
The +auto_call_delayed_io+ keyword sets a data object tree to perform
def auto_call_delayed_io return if DelayedIO.method_defined? :initialize_instance_without_record_io include AutoCallDelayedIO DelayedIO.send(:alias_method, :initialize_instance_without_record_io, :initialize_instance) DelayedIO.send(:define_method, :initialize_instance) do if @parent && !defined? @delayed_io_recorded @delayed_io_recorded = true list = top_level_get(:delayed_ios) list << self if list end initialize_instance_without_record_io end end
def binary_string(str)
def binary_string(str) str.to_s.dup.force_encoding(Encoding::BINARY) end
def bindata_name
def bindata_name RegisteredClasses.underscore_name(name) end
def clear
def clear initialize_instance end
def debug_name
def debug_name if @parent @parent.debug_name_of(self) else "obj" end end
def eval_parameter(key, overrides = nil)
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 = nil) value = get_parameter(key) if value.is_a?(Symbol) || value.respond_to?(:arity) lazy_evaluator.lazy_eval(value, overrides) else value end end
def extract_args(args)
def extract_args(args) self.class.arg_processor.extract_args(self.class, args) 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(*args)
object resides under.
+parent+ is the parent data object (e.g. struct, array, choice) this
reference callable objects (methods or procs).
+parameters+ is a hash containing symbol keys. Some parameters may
+value+ is a value that is +assign+ed immediately after initialization.
Args are optional, but if present, must be in the following order.
Creates a new data object.
def initialize(*args) value, @params, @parent = extract_args(args) initialize_shared_instance initialize_instance assign(value) if value end
def initialize_instance(*args)
def initialize_instance(*args) unless args.empty? fail "#{caller[0]} remove the call to super in #initialize_instance" end end
def initialize_with_warning(*args)
def initialize_with_warning(*args) owner = method(:initialize).owner if owner != BinData::Base msg = "Don't override #initialize on #{owner}." if %w(BinData::Base BinData::BasePrimitive).include? self.class.superclass.name msg += "\nrename #initialize to #initialize_instance." end fail msg end initialize_without_warning(*args) end
def inspect
def inspect snapshot.inspect end
def lazy_evaluator #:nodoc:
Returns a lazy evaluator for this object.
def lazy_evaluator #:nodoc: @lazy ||= LazyEvaluator.new(self) end
def new(value = nil, parent = nil)
All parameters will be be duplicated. Use this method
Creates a new data object based on this instance.
def new(value = nil, parent = nil) obj = clone obj.parent = parent if parent obj.initialize_instance obj.assign(value) if value obj end
def num_bytes
def num_bytes do_num_bytes.ceil end
def pretty_print(pp) #:nodoc:
Work with Ruby's pretty-printer library.
def pretty_print(pp) #:nodoc: pp.pp(snapshot) end
def read(io, *args, &block)
Instantiates this class and reads from +io+, returning the newly
def read(io, *args, &block) obj = self.new(*args) obj.read(io, &block) obj end
def read(io, &block)
def read(io, &block) io = BinData::IO::Read.new(io) unless BinData::IO::Read === io start_read do clear do_read(io) end block.call(self) if block_given? self end
def reading?
def reading? top_level_get(:in_read) end
def register_subclasses #:nodoc:
Registers all subclasses of this class for use
def register_subclasses #:nodoc: singleton_class.send(:undef_method, :inherited) define_singleton_method(:inherited) do |subclass| RegisteredClasses.register(subclass.name, subclass) register_subclasses end end
def rel_offset
def rel_offset if @parent @parent.offset_of(self) else 0 end end
def safe_respond_to?(symbol, include_private = false) #:nodoc:
reinvoke the evaluator so as to avoid infinite evaluation loops.
A version of +respond_to?+ used by the lazy evaluator. It doesn't
def safe_respond_to?(symbol, include_private = false) #:nodoc: base_respond_to?(symbol, include_private) end
def start_read
def start_read top_level_set(:in_read, true) yield ensure top_level_set(:in_read, false) end
def to_binary_s(&block)
def to_binary_s(&block) io = BinData::IO.create_string_io write(io, &block) io.string end
def to_hex(&block)
def to_hex(&block) to_binary_s(&block).unpack('H*')[0] end
def to_s
def to_s snapshot.to_s end
def top_level
def top_level if parent.nil? tl = self else tl = parent tl = tl.parent while tl.parent end tl end
def top_level_get(sym)
def top_level_get(sym) tl = top_level tl.instance_variable_defined?("@tl_#{sym}") && tl.instance_variable_get("@tl_#{sym}") end
def top_level_set(sym, value)
def top_level_set(sym, value) top_level.instance_variable_set("@tl_#{sym}", value) end
def unregister_self
def unregister_self RegisteredClasses.unregister(name) end
def write(io, &block)
def write(io, &block) io = BinData::IO::Write.new(io) unless BinData::IO::Write === io do_write(io) io.flush block.call(self) if block_given? self end