class BinData::Struct
def _assign(val)
def _assign(val) clear assign_fields(as_snapshot(val)) end
def _do_num_bytes(name) #:nodoc:
def _do_num_bytes(name) #:nodoc: if name.nil? orig__do_num_bytes(nil) else warn "'obj.num_bytes(name)' is deprecated. Replacing with 'obj.name.num_bytes'" obj = find_obj_for_name(name) obj.nil? ? 0 : obj.do_num_bytes end end
def _do_num_bytes(deprecated)
def _do_num_bytes(deprecated) instantiate_all_objs sum_num_bytes_for_all_fields.ceil end
def _do_read(io)
def _do_read(io) instantiate_all_objs @field_objs.each { |f| f.do_read(io) if include_obj(f) } end
def _do_write(io)
def _do_write(io) instantiate_all_objs @field_objs.each { |f| f.do_write(io) if include_obj(f) } end
def _done_read
def _done_read @field_objs.each { |f| f.done_read if include_obj(f) } end
def _snapshot
def _snapshot snapshot = Snapshot.new field_names.each do |name| obj = find_obj_for_name(name) snapshot[name] = obj.snapshot if include_obj(obj) end snapshot end
def as_snapshot(val)
def as_snapshot(val) if val.class == Hash snapshot = Snapshot.new val.each_pair { |k,v| snapshot[k.to_s] = v unless v.nil? } snapshot elsif val.nil? Snapshot.new else val end end
def assign_fields(snapshot)
def assign_fields(snapshot) field_names(true).each do |name| obj = find_obj_for_name(name) if obj and snapshot.respond_to?(name) obj.assign(snapshot.__send__(name)) end end end
def clear(name = nil) #:nodoc:
def clear(name = nil) #:nodoc: if name.nil? orig_clear else warn "'obj.clear(name)' is deprecated. Replacing with 'obj.name.clear'" obj = find_obj_for_name(name) obj.clear unless obj.nil? end end
def clear
def clear @field_objs.each { |f| f.clear unless f.nil? } end
def clear?(name = nil) #:nodoc:
def clear?(name = nil) #:nodoc: if name.nil? orig_clear? else warn "'obj.clear?(name)' is deprecated. Replacing with 'obj.name.clear?'" obj = find_obj_for_name(name) obj.nil? ? true : obj.clear? end end
def clear?
def clear? @field_objs.inject(true) { |all_clear, f| all_clear and (f.nil? or f.clear?) } end
def debug_name_of(child)
def debug_name_of(child) field_name = @field_names[find_index_of(child)] "#{debug_name}.#{field_name}" end
def ensure_field_names_are_valid(field_names)
def ensure_field_names_are_valid(field_names) instance_methods = self.instance_methods reserved_names = RESERVED field_names.each do |name| if instance_methods.include?(name) raise NameError.new("Rename field '#{name}' in #{self}, " + "as it shadows an existing method.", name) end if reserved_names.include?(name) raise NameError.new("Rename field '#{name}' in #{self}, " + "as it is a reserved name.", name) end if field_names.count(name) != 1 raise NameError.new("field '#{name}' in #{self}, " + "is defined multiple times.", name) end end end
def field_names(include_hidden = false)
object. +include_hidden+ specifies whether to include hidden names
Returns a list of the names of all fields accessible through this
def field_names(include_hidden = false) if include_hidden @field_names.dup else hidden = get_parameter(:hide) || [] @field_names - hidden end end
def find_index_of(obj)
def find_index_of(obj) @field_objs.find_index { |el| el.equal?(obj) } end
def find_obj_for_name(name)
def find_obj_for_name(name) field_name = name.to_s.chomp("=") index = @field_names.find_index(field_name) if index instantiate_obj_at(index) @field_objs[index] else nil end end
def hidden_field_names(hidden)
def hidden_field_names(hidden) (hidden || []).collect { |h| h.to_s } end
def include_obj(obj)
def include_obj(obj) not obj.has_parameter?(:onlyif) or obj.eval_parameter(:onlyif) end
def inherited(subclass) #:nodoc:
def inherited(subclass) #:nodoc: if subclass != Record fail "error: inheriting from BinData::Struct has been deprecated. Inherit from BinData::Record instead." end end
def initialize(params = {}, parent = nil)
def initialize(params = {}, parent = nil) super(params, parent) @field_names = get_parameter(:fields).field_names @field_objs = [] end
def instantiate_all_objs
def instantiate_all_objs @field_names.each_index { |i| instantiate_obj_at(i) } end
def instantiate_obj_at(index)
def instantiate_obj_at(index) if @field_objs[index].nil? field = get_parameter(:fields)[index] @field_objs[index] = field.instantiate(self) end end
def invoke_field(obj, symbol, args)
def invoke_field(obj, symbol, args) name = symbol.to_s is_writer = (name[-1, 1] == "=") if is_writer obj.assign(*args) else obj end end
def method_missing(symbol, *args, &block)
def method_missing(symbol, *args, &block) obj = find_obj_for_name(symbol) if obj invoke_field(obj, symbol, args) else super end end
def offset_of(child)
def offset_of(child) if child.class == ::String fail "error: 'offset_of(\"fieldname\")' is deprecated. Use 'fieldname.offset' instead" end orig_offset_of(child) end
def offset_of(child)
def offset_of(child) instantiate_all_objs sum = sum_num_bytes_below_index(find_index_of(child)) child_offset = (::Integer === child.do_num_bytes) ? sum.ceil : sum.floor offset + child_offset end
def respond_to?(symbol, include_private = false)
def respond_to?(symbol, include_private = false) super(symbol, include_private) || field_names(true).include?(symbol.to_s.chomp("=")) end
def sanitize_endian(params, sanitizer)
def sanitize_endian(params, sanitizer) if params.needs_sanitizing?(:endian) params[:endian] = sanitizer.create_sanitized_endian(params[:endian]) end end
def sanitize_fields(params, sanitizer)
def sanitize_fields(params, sanitizer) if params.needs_sanitizing?(:fields) fields = params[:fields] params[:fields] = sanitizer.create_sanitized_fields(params[:endian]) fields.each do |ftype, fname, fparams| params[:fields].add_field(ftype, fname, fparams) end field_names = sanitized_field_names(params[:fields]) ensure_field_names_are_valid(field_names) end end
def sanitize_hide(params, sanitizer)
def sanitize_hide(params, sanitizer) if params.needs_sanitizing?(:hide) and params.has_parameter?(:fields) field_names = sanitized_field_names(params[:fields]) hfield_names = hidden_field_names(params[:hide]) params[:hide] = (hfield_names & field_names) end end
def sanitize_parameters!(params, sanitizer)
def sanitize_parameters!(params, sanitizer) sanitize_endian(params, sanitizer) sanitize_fields(params, sanitizer) sanitize_hide(params, sanitizer) end
def sanitized_field_names(sanitized_fields)
def sanitized_field_names(sanitized_fields) sanitized_fields.field_names end
def sum_num_bytes_below_index(index)
def sum_num_bytes_below_index(index) sum = 0 (0...index).each do |i| obj = @field_objs[i] if include_obj(obj) nbytes = obj.do_num_bytes sum = ((::Integer === nbytes) ? sum.ceil : sum) + nbytes end end sum end
def sum_num_bytes_for_all_fields
def sum_num_bytes_for_all_fields sum_num_bytes_below_index(@field_objs.length) end