class BinData::Array

to any lambda evaluated as a parameter of that data object.
Each data object in an array has the variable index 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 variables index, element and array
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.read(data) #=> [3, 4, 5, 6, 7, 8, 9]
obj = BinData::Array.new(type: :int8, read_until: :eof)
obj.read(data) #=> [3, 4, 5, 6, 7]
read_until: -> { array + array[index - 1] == 13 })
obj = BinData::Array.new(type: :int8,
obj.read(data) #=> [3, 4, 5, 6]
read_until: -> { element >= 6 })
obj = BinData::Array.new(type: :int8,
obj.read(data) #=> [3, 4]
read_until: -> { index == 1 })
obj = BinData::Array.new(type: :int8,
obj.read(data) #=> [3, 4, 5, 6, 7, 8]
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.

def [](arg1, arg2 = nil)

Returns the element at +index+.
def [](arg1, arg2 = nil)
  if arg1.respond_to?(:to_int) && arg2.nil?
    slice_index(arg1.to_int)
  elsif arg1.respond_to?(:to_int) && arg2.respond_to?(:to_int)
    slice_start_length(arg1.to_int, arg2.to_int)
  elsif arg1.is_a?(Range) && 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)

Sets the element at +index+.
def []=(index, value)
  extend_array(index)
  elements[index].assign(value)
end

def append_new_element

def append_new_element
  element = new_element
  elements << element
  element
end

def assign(array)

def assign(array)
  return if self.equal?(array)  # prevent self assignment
  raise ArgumentError, "can't set a nil value for #{debug_name}" if array.nil?
  @elements = []
  concat(array)
end

def at(index)

of range the array will not be automatically extended.
Returns the element at +index+. Unlike +slice+, if +index+ is out
def at(index)
  elements[index]
end

def clear?

def clear?
  @elements.nil? || elements.all?(&:clear?)
end

def concat(array)

def concat(array)
  insert(-1, *array.to_ary)
  self
end

def debug_name_of(child) # :nodoc:

:nodoc:
def debug_name_of(child) # :nodoc:
  index = find_index_of(child)
  "#{debug_name}[#{index}]"
end

def do_num_bytes # :nodoc:

:nodoc:
def do_num_bytes # :nodoc:
  sum_num_bytes_for_all_elements
end

def do_write(io) # :nodoc:

:nodoc:
def do_write(io) # :nodoc:
  elements.each { |el| el.do_write(io) }
end

def each

def each
  elements.each { |el| yield el }
end

def elements

def elements
  @elements ||= []
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.index(obj)
end

def find_index_of(obj)

Uses equal? for the comparator.

Returns the first index of +obj+ in self.
def find_index_of(obj)
  elements.index { |el| el.equal?(obj) }
end

def first(n = nil)

form returns an empty array.
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? && empty?
    # explicitly return nil as arrays grow automatically
    nil
  elsif n.nil?
    self[0]
  else
    self[0, n]
  end
end

def initialize_instance

def initialize_instance
  @elements = nil
end

def initialize_shared_instance

def initialize_shared_instance
  @element_prototype = get_parameter(:type)
  if get_parameter(:read_until) == :eof
    extend ReadUntilEOFPlugin
  elsif has_parameter?(:read_until)
    extend ReadUntilPlugin
  elsif has_parameter?(:initial_length)
    extend InitialLengthPlugin
  end
  super
end

def insert(index, *objs)

def insert(index, *objs)
  extend_array(index - 1)
  abs_index = (index >= 0) ? index : index + 1 + length
  # insert elements before...
  new_elements = objs.map { new_element }
  elements.insert(index, *new_elements)
  # ...assigning values
  objs.each_with_index do |obj, i|
    self[abs_index + i] = obj
  end
  self
end

def last(n = nil)

form returns an empty array.
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(nil, self)
end

def offset_of(child) # :nodoc:

:nodoc:
def offset_of(child) # :nodoc:
  index = find_index_of(child)
  sum = sum_num_bytes_below_index(index)
  child.bit_aligned? ? sum.floor : sum.ceil
end

def push(*args)

def push(*args)
  insert(-1, *args)
  self
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 snapshot

def snapshot
  elements.collect(&:snapshot)
end

def sum_num_bytes_below_index(index)

def sum_num_bytes_below_index(index)
  (0...index).inject(0) do |sum, i|
    nbytes = elements[i].do_num_bytes
    if nbytes.is_a?(Integer)
      sum.ceil + nbytes
    else
      sum + nbytes
    end
  end
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

Allow this object to be used in array context.
def to_ary
  collect { |el| el }
end

def unshift(*args)

def unshift(*args)
  insert(0, *args)
  self
end