class BinData::Array
- to any lambda evaluated as a parameter of that data object.
Each data object in an array has the variableindex
made available
as much data from the stream as possible.
is the symbol :eof, then the array will read
this parameter. If the value of this parameter
are made available to any lambda assigned to
The variablesindex
,element
andarray
read an array until a sentinel value is found.
condition is true. This is typically used to:read_until
- While reading, elements are read until this
:initial_length
- The initial length of the array.
[type_symbol, hash_params]
.
passed to it, then it should be provided as
array elements. If the type is to have params:type
-
The symbol representing the data type of the
an object. These params are:
Parameters may be provided at initialisation to control the behaviour of
== Parameters
obj.snapshot #=> [3, 4, 5, 6, 7, 8, 9]
obj.read(data)
obj = BinData::Array.new(:type => :int8, :read_until => :eof)
obj.snapshot #=> [3, 4, 5, 6, 7]
obj.read(data)
:read_until => lambda { array + array[index - 1] == 13 })
obj = BinData::Array.new(:type => :int8,
obj.snapshot #=> [3, 4, 5, 6]
obj.read(data)
:read_until => lambda { element >= 6 })
obj = BinData::Array.new(:type => :int8,
obj.snapshot #=> [3, 4]
obj.read(data)
:read_until => lambda { index == 1 })
obj = BinData::Array.new(:type => :int8,
obj.snapshot #=> [3, 4, 5, 6, 7, 8]
obj.read(data)
obj = BinData::Array.new(:type => :int8, :initial_length => 6)
data = “x03x04x05x06x07x08x09”
require ‘bindata’
An Array is a list of data objects of the same type.
- The initial length of the array.
- While reading, elements are read until this
def [](arg1, arg2 = nil)
def [](arg1, arg2 = nil) if arg1.respond_to?(:to_int) and arg2.nil? slice_index(arg1.to_int) elsif arg1.respond_to?(:to_int) and arg2.respond_to?(:to_int) slice_start_length(arg1.to_int, arg2.to_int) elsif arg1.is_a?(Range) and arg2.nil? slice_range(arg1) else raise TypeError, "can't convert #{arg1} into Integer" unless arg1.respond_to?(:to_int) raise TypeError, "can't convert #{arg2} into Integer" unless arg2.respond_to?(:to_int) end end
def []=(index, value)
def []=(index, value) extend_array(index) elements[index].assign(value) end
def _assign(array)
def _assign(array) raise ArgumentError, "can't set a nil value for #{debug_name}" if array.nil? @element_list = to_storage_formats(array.to_ary) end
def _do_num_bytes(deprecated)
def _do_num_bytes(deprecated) sum_num_bytes_for_all_elements.ceil end
def _do_num_bytes(index) #:nodoc:
def _do_num_bytes(index) #:nodoc: if index.nil? orig__do_num_bytes(nil) elsif index < elements.length warn "'obj.num_bytes(n)' is deprecated. Replacing with 'obj[n].num_bytes'" elements[index].do_num_bytes else 0 end end
def _do_read(io)
def _do_read(io) if has_parameter?(:initial_length) elements.each { |el| el.do_read(io) } elsif has_parameter?(:read_until) read_until(io) end end
def _do_write(io)
def _do_write(io) elements.each { |el| el.do_write(io) } end
def _done_read
def _done_read elements.each { |el| el.done_read } end
def _snapshot
def _snapshot elements.collect { |el| el.snapshot } end
def append(value = nil) #:nodoc:
def append(value = nil) #:nodoc: warn "#append is deprecated, use push or slice instead" if value.nil? slice(length) else push(value) end self.last end
def append_new_element
def append_new_element element = new_element elements << element element end
def at(index)
Returns the element at +index+. Unlike +slice+, if +index+ is out
def at(index) elements[index] end
def clear
def clear @element_list = nil end
def clear(index = nil) #:nodoc:
def clear(index = nil) #:nodoc: if index.nil? orig_clear elsif index < elements.length warn "'obj.clear(n)' is deprecated. Replacing with 'obj[n].clear'" elements[index].clear end end
def clear?
def clear? @element_list.nil? or elements.inject(true) { |all_clear, el| all_clear and el.clear? } end
def clear?(index = nil) #:nodoc:
def clear?(index = nil) #:nodoc: if index.nil? orig_clear? elsif index < elements.length warn "'obj.clear?(n)' is deprecated. Replacing with 'obj[n].clear?'" elements[index].clear? else true end end
def concat(array)
def concat(array) insert(-1, *array.to_ary) self end
def debug_name_of(child)
def debug_name_of(child) index = find_index_of(child) "#{debug_name}[#{index}]" end
def each
def each elements.each { |el| yield el } end
def elements
def elements if @element_list.nil? @element_list = [] if has_parameter?(:initial_length) eval_parameter(:initial_length).times do @element_list << new_element end end end @element_list end
def empty?
def empty? length.zero? end
def extend_array(max_index)
def extend_array(max_index) max_length = max_index + 1 while elements.length < max_length append_new_element end end
def find_index(obj)
def find_index(obj) elements.find_index(obj) end
def find_index_of(obj)
Returns the first index of +obj+ in self.
def find_index_of(obj) elements.find_index { |el| el.equal?(obj) } end
def first(n = nil)
If the array is empty, the first form returns nil, and the second
Returns the first element, or the first +n+ elements, of the array.
def first(n = nil) if n.nil? and empty? # explicitly return nil as arrays grow automatically nil elsif n.nil? self[0] else self[0, n] end end
def initialize(params = {}, parent = nil)
def initialize(params = {}, parent = nil) super(params, parent) @element_list = nil @element_prototype = get_parameter(:type) end
def insert(index, *objs)
def insert(index, *objs) extend_array(index - 1) elements.insert(index, *to_storage_formats(objs)) self end
def last(n = nil)
If the array is empty, the first form returns nil, and the second
Returns the last element, or the last +n+ elements, of the array.
def last(n = nil) if n.nil? self[-1] else n = length if n > length self[-n, n] end end
def length
def length elements.length end
def new_element
def new_element @element_prototype.instantiate(self) end
def offset_of(child)
def offset_of(child) index = find_index_of(child) sum = sum_num_bytes_below_index(index) child_offset = (::Integer === child.do_num_bytes) ? sum.ceil : sum.floor offset + child_offset end
def push(*args)
def push(*args) insert(-1, *args) self end
def read_until(io)
def read_until(io) if get_parameter(:read_until) == :eof read_until_eof(io) else read_until_condition(io) end end
def read_until_condition(io)
def read_until_condition(io) loop do element = append_new_element element.do_read(io) variables = { :index => self.length - 1, :element => self.last, :array => self } break if eval_parameter(:read_until, variables) end end
def read_until_eof(io)
def read_until_eof(io) loop do element = append_new_element begin element.do_read(io) rescue elements.pop break end end end
def sanitize_parameters!(params, sanitizer)
def sanitize_parameters!(params, sanitizer) unless params.has_parameter?(:initial_length) or params.has_parameter?(:read_until) # ensure one of :initial_length and :read_until exists params[:initial_length] = 0 end warn_replacement_parameter(params, :read_length, :initial_length) if params.needs_sanitizing?(:type) el_type, el_params = params[:type] params[:type] = sanitizer.create_sanitized_object_prototype(el_type, el_params) end end
def slice_index(index)
def slice_index(index) extend_array(index) at(index) end
def slice_range(range)
def slice_range(range) elements[range] end
def slice_start_length(start, length)
def slice_start_length(start, length) elements[start, length] end
def sum_num_bytes_below_index(index)
def sum_num_bytes_below_index(index) sum = 0 (0...index).each do |i| nbytes = elements[i].do_num_bytes sum = ((::Integer === nbytes) ? sum.ceil : sum) + nbytes end sum end
def sum_num_bytes_for_all_elements
def sum_num_bytes_for_all_elements sum_num_bytes_below_index(length) end
def to_ary
def to_ary collect { |el| el } end
def to_storage_format(obj)
def to_storage_format(obj) element = new_element element.assign(obj) element end
def to_storage_formats(els)
def to_storage_formats(els) els.collect { |el| to_storage_format(el) } end
def unshift(*args)
def unshift(*args) insert(0, *args) self end