class BinData::Array

An Array is a list of data objects of the same type.

require 'bindata'

data = "\x03\x04\x05\x06\x07\x08\x09"

obj = BinData::Array.new(type: :int8, initial_length: 6)
obj.read(data) #=> [3, 4, 5, 6, 7, 8]

obj = BinData::Array.new(type: :int8,
                         read_until: -> { index == 1 })
obj.read(data) #=> [3, 4]

obj = BinData::Array.new(type: :int8,
                         read_until: -> { element >= 6 })
obj.read(data) #=> [3, 4, 5, 6]

obj = BinData::Array.new(type: :int8,
        read_until: -> { array[index] + array[index - 1] == 13 })
obj.read(data) #=> [3, 4, 5, 6, 7]

obj = BinData::Array.new(type: :int8, read_until: :eof)
obj.read(data) #=> [3, 4, 5, 6, 7, 8, 9]

Parameters

Parameters may be provided at initialisation to control the behaviour of an object. These params are:

:type

The symbol representing the data type of the array elements. If the type is to have params passed to it, then it should be provided as [type_symbol, hash_params].

:initial_length

The initial length of the array.

:read_until

While reading, elements are read until this condition is true. This is typically used to read an array until a sentinel value is found. The variables index, element and array are made available to any lambda assigned to this parameter. If the value of this parameter is the symbol :eof, then the array will read as much data from the stream as possible.

Each data object in an array has the variable index made available to any lambda evaluated as a parameter of that data object.

Public Instance Methods

<<(*args)
Alias for: push
[](arg1, arg2 = nil) click to toggle source

Returns the element at index.

# File lib/bindata/array.rb, line 139
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
Also aliased as: slice
[]=(index, value) click to toggle source

Sets the element at index.

# File lib/bindata/array.rb, line 174
def []=(index, value)
  extend_array(index)
  elements[index].assign(value)
end
assign(array) click to toggle source
# File lib/bindata/array.rb, line 82
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?

  @element_list = []
  concat(array)
end
at(index) click to toggle source

Returns the element at index. Unlike slice, if index is out of range the array will not be automatically extended.

# File lib/bindata/array.rb, line 169
def at(index)
  elements[index]
end
clear?() click to toggle source
# File lib/bindata/array.rb, line 78
def clear?
  @element_list.nil? || elements.all?(&:clear?)
end
concat(array) click to toggle source
# File lib/bindata/array.rb, line 117
def concat(array)
  insert(-1, *array.to_ary)
  self
end
each() { |el| ... } click to toggle source
# File lib/bindata/array.rb, line 219
def each
  elements.each { |el| yield el }
end
empty?() click to toggle source
# File lib/bindata/array.rb, line 210
def empty?
  length.zero?
end
find_index(obj) click to toggle source
# File lib/bindata/array.rb, line 94
def find_index(obj)
  elements.index(obj)
end
Also aliased as: index
find_index_of(obj) click to toggle source

Returns the first index of obj in self.

Uses equal? for the comparator.

# File lib/bindata/array.rb, line 102
def find_index_of(obj)
  elements.index { |el| el.equal?(obj) }
end
first(n = nil) click to toggle source

Returns the first element, or the first n elements, of the array. If the array is empty, the first form returns nil, and the second form returns an empty array.

# File lib/bindata/array.rb, line 182
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
index(obj)
Alias for: find_index
initialize_instance() click to toggle source
# File lib/bindata/array.rb, line 74
def initialize_instance
  @element_list = nil
end
initialize_shared_instance() click to toggle source
# File lib/bindata/array.rb, line 61
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
insert(index, *objs) click to toggle source
# File lib/bindata/array.rb, line 122
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
last(n = nil) click to toggle source

Returns the last element, or the last n elements, of the array. If the array is empty, the first form returns nil, and the second form returns an empty array.

# File lib/bindata/array.rb, line 196
def last(n = nil)
  if n.nil?
    self[-1]
  else
    n = length if n > length
    self[-n, n]
  end
end
length() click to toggle source
# File lib/bindata/array.rb, line 205
def length
  elements.length
end
Also aliased as: size
push(*args) click to toggle source
# File lib/bindata/array.rb, line 106
def push(*args)
  insert(-1, *args)
  self
end
Also aliased as: <<
size()
Alias for: length
slice(arg1, arg2 = nil)
Alias for: []
snapshot() click to toggle source
# File lib/bindata/array.rb, line 90
def snapshot
  elements.collect(&:snapshot)
end
to_ary() click to toggle source

Allow this object to be used in array context.

# File lib/bindata/array.rb, line 215
def to_ary
  collect { |el| el }
end
unshift(*args) click to toggle source
# File lib/bindata/array.rb, line 112
def unshift(*args)
  insert(0, *args)
  self
end

Private Instance Methods

append_new_element() click to toggle source
# File lib/bindata/array.rb, line 257
def append_new_element
  element = new_element
  elements << element
  element
end
elements() click to toggle source
# File lib/bindata/array.rb, line 253
def elements
  @element_list ||= []
end
extend_array(max_index) click to toggle source
# File lib/bindata/array.rb, line 246
def extend_array(max_index)
  max_length = max_index + 1
  while elements.length < max_length
    append_new_element
  end
end
new_element() click to toggle source
# File lib/bindata/array.rb, line 263
def new_element
  @element_prototype.instantiate(nil, self)
end
slice_index(index) click to toggle source
# File lib/bindata/array.rb, line 153
def slice_index(index)
  extend_array(index)
  at(index)
end
slice_range(range) click to toggle source
# File lib/bindata/array.rb, line 162
def slice_range(range)
  elements[range]
end
slice_start_length(start, length) click to toggle source
# File lib/bindata/array.rb, line 158
def slice_start_length(start, length)
  elements[start, length]
end
sum_num_bytes_below_index(index) click to toggle source
# File lib/bindata/array.rb, line 271
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
sum_num_bytes_for_all_elements() click to toggle source
# File lib/bindata/array.rb, line 267
def sum_num_bytes_for_all_elements
  sum_num_bytes_below_index(length)
end