class BinData::Base
This is the abstract base class for all data objects.
Add auto_call_delayed_io
keyword to BinData::Base
.
Add these offset options to Base
Attributes
Public Class Methods
The arg processor for this class.
# File lib/bindata/base.rb, line 26 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
The auto_call_delayed_io
keyword sets a data object tree to perform multi pass I/O automatically.
# File lib/bindata/delayed_io.rb, line 161 def auto_call_delayed_io include AutoCallDelayedIO return if DelayedIO.method_defined? :initialize_instance_without_record_io 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
The name of this class as used by Records, Arrays etc.
# File lib/bindata/base.rb, line 41 def bindata_name RegisteredClasses.underscore_name(name) end
Creates a new data object.
Args are optional, but if present, must be in the following order.
value
is a value that is +assign+ed immediately after initialization.
parameters
is a hash containing symbol keys. Some parameters may reference callable objects (methods or procs).
parent
is the parent data object (e.g. struct, array, choice) this object resides under.
# File lib/bindata/base.rb, line 80 def initialize(*args) value, @params, @parent = extract_args(args) initialize_shared_instance initialize_instance assign(value) if value end
Instantiates this class and reads from io
, returning the newly created data object. args
will be used when instantiating.
# File lib/bindata/base.rb, line 19 def read(io, *args, &block) obj = self.new(*args) obj.read(io, &block) obj end
Private Class Methods
Call this method if this class is abstract and not to be used.
# File lib/bindata/base.rb, line 46 def unregister_self RegisteredClasses.unregister(name) end
Public Instance Methods
Override and delegate =~ as it is defined in Object.
# File lib/bindata/base.rb, line 199 def =~(other) snapshot =~ other end
Returns the offset (in bytes) of this object with respect to its most distant ancestor.
# File lib/bindata/base.rb, line 214 def abs_offset if @parent @parent.abs_offset + @parent.offset_of(self) else 0 end end
Resets the internal state to that of a newly created object.
# File lib/bindata/base.rb, line 137 def clear initialize_instance end
Returns a user friendly name of this object for debugging purposes.
# File lib/bindata/base.rb, line 204 def debug_name if @parent @parent.debug_name_of(self) else "obj" end end
Returns the result of evaluating the parameter identified by key
.
overrides
is an optional parameters
like hash that allow the parameters given at object construction to be overridden.
Returns nil if key
does not refer to any parameter.
# File lib/bindata/base.rb, line 110 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
Returns the parameter referenced by key
. Use this method if you are sure the parameter is not to be evaluated. You most likely want eval_parameter
.
# File lib/bindata/base.rb, line 127 def get_parameter(key) @params[key] end
Returns whether key
exists in the parameters
hash.
# File lib/bindata/base.rb, line 132 def has_parameter?(key) @params.has_parameter?(key) end
# File lib/bindata/warnings.rb, line 25 def initialize_instance(*args) unless args.empty? fail "#{caller[0]} remove the call to super in #initialize_instance" end end
# File lib/bindata/warnings.rb, line 12 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
Return a human readable representation of this data object.
# File lib/bindata/base.rb, line 184 def inspect snapshot.inspect end
Creates a new data object based on this instance.
All parameters will be be duplicated. Use this method when creating multiple objects with the same parameters.
# File lib/bindata/base.rb, line 95 def new(value = nil, parent = nil) obj = clone obj.parent = parent if parent obj.initialize_instance obj.assign(value) if value obj end
Returns the number of bytes it will take to write this data object.
# File lib/bindata/base.rb, line 167 def num_bytes do_num_bytes.ceil end
Reads data into this data object.
# File lib/bindata/base.rb, line 142 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
Returns the offset (in bytes) of this object with respect to its parent.
# File lib/bindata/base.rb, line 223 def rel_offset if @parent @parent.offset_of(self) else 0 end end
Returns the string representation of this data object.
# File lib/bindata/base.rb, line 172 def to_binary_s(&block) io = BinData::IO.create_string_io write(io, &block) io.string end
Returns the hexadecimal string representation of this data object.
# File lib/bindata/base.rb, line 179 def to_hex(&block) to_binary_s(&block).unpack('H*')[0] end
Return a string representing this data object.
# File lib/bindata/base.rb, line 189 def to_s snapshot.to_s end
Writes the value for this data object to io
.
# File lib/bindata/base.rb, line 155 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
Private Instance Methods
# File lib/bindata/base.rb, line 284 def binary_string(str) str.to_s.dup.force_encoding(Encoding::BINARY) end
# File lib/bindata/base.rb, line 247 def extract_args(args) self.class.arg_processor.extract_args(self.class, args) end
Is this object tree currently being read? Used by BasePrimitive
.
# File lib/bindata/base.rb, line 259 def reading? top_level_get(:in_read) end
# File lib/bindata/base.rb, line 251 def start_read top_level_set(:in_read, true) yield ensure top_level_set(:in_read, false) end
# File lib/bindata/base.rb, line 273 def top_level if parent.nil? tl = self else tl = parent tl = tl.parent while tl.parent end tl end
# File lib/bindata/base.rb, line 267 def top_level_get(sym) tl = top_level tl.instance_variable_defined?("@tl_#{sym}") && tl.instance_variable_get("@tl_#{sym}") end
# File lib/bindata/base.rb, line 263 def top_level_set(sym, value) top_level.instance_variable_set("@tl_#{sym}", value) end