Class: BinData::Array

Inherits:
Base
  • Object
show all
Includes:
Enumerable
Defined in:
lib/bindata/array.rb

Overview

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)
obj.snapshot #=> [3, 4, 5, 6, 7, 8]

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

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

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

obj = BinData::Array.new(:type => :int8, :read_until => :eof)
obj.read(data)
obj.snapshot #=> [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.

Instance Attribute Summary

Attributes inherited from Base

#parent

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#==, accepted_parameters, #assign, #debug_name, default_parameters, #eval_parameter, #get_parameter, #has_parameter?, #inspect, mandatory_parameters, mutually_exclusive_parameters, #num_bytes, #offset, optional_parameters, #pretty_print, #read, read, #rel_offset, #snapshot, #to_binary_s, #to_s, #write

Constructor Details

#initialize(params = {}, parent = nil) ⇒ Array

Returns a new instance of Array.



81
82
83
84
85
86
# File 'lib/bindata/array.rb', line 81

def initialize(params = {}, parent = nil)
  super(params, parent)

  @element_list      = nil
  @element_prototype = get_parameter(:type)
end

Class Method Details

.sanitize_parameters!(params, sanitizer) ⇒ Object

:nodoc:



65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/bindata/array.rb', line 65

def sanitize_parameters!(params, sanitizer) #:nodoc:
  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

Instance Method Details

#[](arg1, arg2 = nil) ⇒ Object Also known as: slice

Returns the element at index.



132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/bindata/array.rb', line 132

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

#[]=(index, value) ⇒ Object

Sets the element at index.



167
168
169
170
# File 'lib/bindata/array.rb', line 167

def []=(index, value)
  extend_array(index)
  elements[index].assign(value)
end

#at(index) ⇒ Object

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



162
163
164
# File 'lib/bindata/array.rb', line 162

def at(index)
  elements[index]
end

#clearObject



93
94
95
# File 'lib/bindata/array.rb', line 93

def clear
  @element_list = nil
end

#clear?Boolean

Returns:

  • (Boolean)


88
89
90
91
# File 'lib/bindata/array.rb', line 88

def clear?
  @element_list.nil? or
    elements.inject(true) { |all_clear, el| all_clear and el.clear? }
end

#concat(array) ⇒ Object



120
121
122
123
# File 'lib/bindata/array.rb', line 120

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

#debug_name_of(child) ⇒ Object

:nodoc:



216
217
218
219
# File 'lib/bindata/array.rb', line 216

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

#eachObject



212
213
214
# File 'lib/bindata/array.rb', line 212

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

#empty?Boolean

Returns:

  • (Boolean)


203
204
205
# File 'lib/bindata/array.rb', line 203

def empty?
  length.zero?
end

#find_index(obj) ⇒ Object Also known as: index



97
98
99
# File 'lib/bindata/array.rb', line 97

def find_index(obj)
  elements.index(obj)
end

#find_index_of(obj) ⇒ Object

Returns the first index of obj in self.

Uses equal? for the comparator.



105
106
107
# File 'lib/bindata/array.rb', line 105

def find_index_of(obj)
  elements.index { |el| el.equal?(obj) }
end

#first(n = nil) ⇒ Object

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.



175
176
177
178
179
180
181
182
183
184
# File 'lib/bindata/array.rb', line 175

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

#insert(index, *objs) ⇒ Object



125
126
127
128
129
# File 'lib/bindata/array.rb', line 125

def insert(index, *objs)
  extend_array(index - 1)
  elements.insert(index, *to_storage_formats(objs))
  self
end

#last(n = nil) ⇒ Object

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.



189
190
191
192
193
194
195
196
# File 'lib/bindata/array.rb', line 189

def last(n = nil)
  if n.nil?
    self[-1]
  else
    n = length if n > length
    self[-n, n]
  end
end

#lengthObject Also known as: size



198
199
200
# File 'lib/bindata/array.rb', line 198

def length
  elements.length
end

#offset_of(child) ⇒ Object

:nodoc:



221
222
223
224
225
226
# File 'lib/bindata/array.rb', line 221

def offset_of(child) #:nodoc:
  index = find_index_of(child)
  sum = sum_num_bytes_below_index(index)

  child.do_num_bytes.is_a?(Integer) ? sum.ceil : sum.floor
end

#push(*args) ⇒ Object Also known as: <<



109
110
111
112
# File 'lib/bindata/array.rb', line 109

def push(*args)
  insert(-1, *args)
  self
end

#to_aryObject

Allow this object to be used in array context.



208
209
210
# File 'lib/bindata/array.rb', line 208

def to_ary
  collect { |el| el }
end

#unshift(*args) ⇒ Object



115
116
117
118
# File 'lib/bindata/array.rb', line 115

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