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
andarray
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
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
Sets the element at index
.
# File lib/bindata/array.rb, line 174 def []=(index, value) extend_array(index) elements[index].assign(value) end
# 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
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
# File lib/bindata/array.rb, line 78 def clear? @element_list.nil? || elements.all?(&:clear?) end
# File lib/bindata/array.rb, line 117 def concat(array) insert(-1, *array.to_ary) self end
# File lib/bindata/array.rb, line 219 def each elements.each { |el| yield el } end
# File lib/bindata/array.rb, line 210 def empty? length.zero? end
# File lib/bindata/array.rb, line 94 def find_index(obj) elements.index(obj) end
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
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
# File lib/bindata/array.rb, line 74 def initialize_instance @element_list = nil end
# 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
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
# File lib/bindata/array.rb, line 205 def length elements.length end
# File lib/bindata/array.rb, line 106 def push(*args) insert(-1, *args) self end
# File lib/bindata/array.rb, line 90 def snapshot elements.collect(&:snapshot) end
Allow this object to be used in array context.
# File lib/bindata/array.rb, line 215 def to_ary collect { |el| el } end
# File lib/bindata/array.rb, line 112 def unshift(*args) insert(0, *args) self end
Private Instance Methods
# File lib/bindata/array.rb, line 257 def append_new_element element = new_element elements << element element end
# File lib/bindata/array.rb, line 253 def elements @element_list ||= [] end
# 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
# File lib/bindata/array.rb, line 263 def new_element @element_prototype.instantiate(nil, self) end
# File lib/bindata/array.rb, line 153 def slice_index(index) extend_array(index) at(index) end
# File lib/bindata/array.rb, line 162 def slice_range(range) elements[range] end
# File lib/bindata/array.rb, line 158 def slice_start_length(start, length) elements[start, length] end
# 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
# File lib/bindata/array.rb, line 267 def sum_num_bytes_for_all_elements sum_num_bytes_below_index(length) end