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

parent[RW]

Public Class Methods

arg_processor(name = nil) click to toggle source

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
auto_call_delayed_io() click to toggle source

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 154
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
bindata_name() click to toggle source

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
new(*args) click to toggle source

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
read(io, *args, &block) click to toggle source

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

unregister_self() click to toggle source

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

=~(other) click to toggle source

Override and delegate =~ as it is defined in Object.

# File lib/bindata/base.rb, line 200
def =~(other)
  snapshot =~ other
end
abs_offset() click to toggle source

Returns the offset (in bytes) of this object with respect to its most distant ancestor.

# File lib/bindata/base.rb, line 215
def abs_offset
  if @parent
    @parent.abs_offset + @parent.offset_of(self)
  else
    0
  end
end
clear() click to toggle source

Resets the internal state to that of a newly created object.

# File lib/bindata/base.rb, line 137
def clear
  initialize_instance
end
debug_name() click to toggle source

Returns a user friendly name of this object for debugging purposes.

# File lib/bindata/base.rb, line 205
def debug_name
  if @parent
    @parent.debug_name_of(self)
  else
    "obj"
  end
end
eval_parameter(key, overrides = nil) click to toggle source

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
get_parameter(key) click to toggle source

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
has_parameter?(key) click to toggle source

Returns whether key exists in the parameters hash.

# File lib/bindata/base.rb, line 132
def has_parameter?(key)
  @params.has_parameter?(key)
end
initialize_instance(*args) click to toggle source
# 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
initialize_with_warning(*args) click to toggle source
# 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
Also aliased as: initialize
inspect() click to toggle source

Return a human readable representation of this data object.

# File lib/bindata/base.rb, line 185
def inspect
  snapshot.inspect
end
new(value = nil, parent = nil) click to toggle source

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
num_bytes() click to toggle source

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
read(io, &block) click to toggle source

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
rel_offset() click to toggle source

Returns the offset (in bytes) of this object with respect to its parent.

# File lib/bindata/base.rb, line 224
def rel_offset
  if @parent
    @parent.offset_of(self)
  else
    0
  end
end
to_binary_s(&block) click to toggle source

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.rewind
  io.read
end
to_hex(&block) click to toggle source

Returns the hexadecimal string representation of this data object.

# File lib/bindata/base.rb, line 180
def to_hex(&block)
  to_binary_s(&block).unpack('H*')[0]
end
to_s() click to toggle source

Return a string representing this data object.

# File lib/bindata/base.rb, line 190
def to_s
  snapshot.to_s
end
write(io, &block) click to toggle source

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

binary_string(str) click to toggle source
# File lib/bindata/base.rb, line 285
def binary_string(str)
  str.to_s.dup.force_encoding(Encoding::BINARY)
end
extract_args(args) click to toggle source
# File lib/bindata/base.rb, line 248
def extract_args(args)
  self.class.arg_processor.extract_args(self.class, args)
end
reading?() click to toggle source

Is this object tree currently being read? Used by BasePrimitive.

# File lib/bindata/base.rb, line 260
def reading?
  top_level_get(:in_read)
end
start_read() { || ... } click to toggle source
# File lib/bindata/base.rb, line 252
def start_read
  top_level_set(:in_read, true)
  yield
ensure
  top_level_set(:in_read, false)
end
top_level() click to toggle source
# File lib/bindata/base.rb, line 274
def top_level
  if parent.nil?
    tl = self
  else
    tl = parent
    tl = tl.parent while tl.parent
  end

  tl
end
top_level_get(sym) click to toggle source
# File lib/bindata/base.rb, line 268
def top_level_get(sym)
  tl = top_level
  tl.instance_variable_defined?("@tl_#{sym}") &&
    tl.instance_variable_get("@tl_#{sym}")
end
top_level_set(sym, value) click to toggle source
# File lib/bindata/base.rb, line 264
def top_level_set(sym, value)
  top_level.instance_variable_set("@tl_#{sym}", value)
end