Class: BinData::Array
- 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]
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.
Each data object in an array has the variable index
made available to any lambda evaluated as a parameter of that data object.
Class Method Summary collapse
-
.all_possible_field_names(sanitized_params) ⇒ Object
An array has no fields.
-
.sanitize_parameters(params, endian = nil) ⇒ Object
Returns a sanitized
params
that is of the form expected by #initialize.
Instance Method Summary collapse
-
#[](*index) ⇒ Object
(also: #slice)
Returns the element at
index
. -
#[]=(index, value) ⇒ Object
Sets the element at
index
. -
#_do_read(io) ⇒ Object
Reads the values for all fields in this object from
io
. -
#_num_bytes(index) ⇒ Object
Returns the number of bytes it will take to write the element at
index
. -
#_write(io) ⇒ Object
Writes the values for all fields in this object to
io
. -
#append(value = nil) ⇒ Object
Appends a new element to the end of the array.
-
#clear(index = nil) ⇒ Object
Clears the element at position
index
. -
#clear?(index = nil) ⇒ Boolean
Returns if the element at position
index
is clear?. -
#done_read ⇒ Object
To be called after calling #do_read.
-
#each ⇒ Object
Iterate over each element in the array.
-
#empty? ⇒ Boolean
Returns true if self array contains no elements.
-
#field_names ⇒ Object
An array has no fields.
-
#first(n = nil) ⇒ Object
Returns the first element, or the first
n
elements, of the array. -
#initialize(params = {}, env = nil) ⇒ Array
constructor
Creates a new Array.
-
#last(n = nil) ⇒ Object
Returns the last element, or the last
n
elements, of the array. -
#length ⇒ Object
(also: #size)
The number of elements in this array.
-
#single_value? ⇒ Boolean
Returns whether this data object contains a single value.
-
#snapshot ⇒ Object
Returns a snapshot of the data in this array.
-
#to_ary ⇒ Object
Allow this object to be used in array context.
Methods inherited from Base
accepted_parameters, default_parameters, #do_read, #inspect, lookup, mandatory_parameters, mutually_exclusive_parameters, #num_bytes, optional_parameters, read, #read, register, #to_s, #write
Constructor Details
#initialize(params = {}, env = nil) ⇒ Array
Creates a new Array
88 89 90 91 92 93 94 95 96 |
# File 'lib/bindata/array.rb', line 88 def initialize(params = {}, env = nil) super(params, env) klass, el_params = param(:type) @element_list = nil @element_klass = klass @element_params = el_params end |
Class Method Details
.all_possible_field_names(sanitized_params) ⇒ Object
An array has no fields.
82 83 84 |
# File 'lib/bindata/array.rb', line 82 def all_possible_field_names(sanitized_params) [] end |
.sanitize_parameters(params, endian = nil) ⇒ Object
Returns a sanitized params
that is of the form expected by #initialize.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/bindata/array.rb', line 63 def sanitize_parameters(params, endian = nil) params = params.dup unless params.has_key?(:initial_length) or params.has_key?(:read_until) # ensure one of :initial_length and :read_until exists params[:initial_length] = 0 end if params.has_key?(:type) type, el_params = params[:type] klass = lookup(type, endian) raise TypeError, "unknown type '#{type}' for #{self}" if klass.nil? params[:type] = [klass, SanitizedParameters.new(klass, el_params, endian)] end super(params, endian) end |
Instance Method Details
#[](*index) ⇒ Object Also known as: slice
Returns the element at index
. If the element is a single_value then the value of the element is returned instead.
189 190 191 192 193 194 195 196 |
# File 'lib/bindata/array.rb', line 189 def [](*index) data = elements[*index] if data.respond_to?(:each) data.collect { |el| (el && el.single_value?) ? el.value : el } else (data && data.single_value?) ? data.value : data end end |
#[]=(index, value) ⇒ Object
Sets the element at index
. If the element is a single_value then the value of the element is set instead.
201 202 203 204 205 206 207 |
# File 'lib/bindata/array.rb', line 201 def []=(index, value) obj = elements[index] unless obj.single_value? raise NoMethodError, "undefined method `[]=' for #{self}", caller end obj.value = value end |
#_do_read(io) ⇒ Object
Reads the values for all fields in this object from io
.
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/bindata/array.rb', line 125 def _do_read(io) if has_param?(:initial_length) elements.each { |f| f.do_read(io) } else # :read_until @element_list = nil loop do element = append_new_element element.do_read(io) variables = { :index => self.length - 1, :element => self.last, :array => self } finished = eval_param(:read_until, variables) break if finished end end end |
#_num_bytes(index) ⇒ Object
Returns the number of bytes it will take to write the element at index
. If index
, then returns the number of bytes required to write all fields.
154 155 156 157 158 159 160 |
# File 'lib/bindata/array.rb', line 154 def _num_bytes(index) if index.nil? elements.inject(0) { |sum, f| sum + f.num_bytes } else elements[index].num_bytes end end |
#_write(io) ⇒ Object
Writes the values for all fields in this object to io
.
147 148 149 |
# File 'lib/bindata/array.rb', line 147 def _write(io) elements.each { |f| f.write(io) } end |
#append(value = nil) ⇒ Object
Appends a new element to the end of the array. If the array contains single_values then the value
may be provided to the call. Returns the appended object, or value in the case of single_values.
181 182 183 184 185 |
# File 'lib/bindata/array.rb', line 181 def append(value = nil) append_new_element self[-1] = value unless value.nil? self.last end |
#clear(index = nil) ⇒ Object
Clears the element at position index
. If index
is not given, then the internal state of the array is reset to that of a newly created object.
101 102 103 104 105 106 107 108 109 |
# File 'lib/bindata/array.rb', line 101 def clear(index = nil) if @element_list.nil? # do nothing as the array is already clear elsif index.nil? @element_list = nil else elements[index].clear end end |
#clear?(index = nil) ⇒ Boolean
Returns if the element at position index
is clear?. If index
is not given, then returns whether all fields are clear.
113 114 115 116 117 118 119 120 121 122 |
# File 'lib/bindata/array.rb', line 113 def clear?(index = nil) if @element_list.nil? true elsif index.nil? elements.each { |f| return false if not f.clear? } true else elements[index].clear? end end |
#done_read ⇒ Object
To be called after calling #do_read.
142 143 144 |
# File 'lib/bindata/array.rb', line 142 def done_read elements.each { |f| f.done_read } end |
#each ⇒ Object
Iterate over each element in the array. If the elements are single_values then the values of the elements are iterated instead.
211 212 213 214 215 |
# File 'lib/bindata/array.rb', line 211 def each elements.each do |el| yield(el.single_value? ? el.value : el) end end |
#empty? ⇒ Boolean
Returns true if self array contains no elements.
247 248 249 |
# File 'lib/bindata/array.rb', line 247 def empty? length.zero? end |
#field_names ⇒ Object
An array has no fields.
174 175 176 |
# File 'lib/bindata/array.rb', line 174 def field_names [] 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.
220 221 222 223 224 225 226 |
# File 'lib/bindata/array.rb', line 220 def first(n = nil) if n.nil? self[0] else self[0, n] end 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.
231 232 233 234 235 236 237 238 |
# File 'lib/bindata/array.rb', line 231 def last(n = nil) if n.nil? self[-1] else n = length if n > length self[-n, n] end end |
#length ⇒ Object Also known as: size
The number of elements in this array.
241 242 243 |
# File 'lib/bindata/array.rb', line 241 def length elements.length end |
#single_value? ⇒ Boolean
Returns whether this data object contains a single value. Single value data objects respond to #value
and #value=
.
169 170 171 |
# File 'lib/bindata/array.rb', line 169 def single_value? return false end |
#snapshot ⇒ Object
Returns a snapshot of the data in this array.
163 164 165 |
# File 'lib/bindata/array.rb', line 163 def snapshot elements.collect { |e| e.snapshot } end |
#to_ary ⇒ Object
Allow this object to be used in array context.
252 253 254 |
# File 'lib/bindata/array.rb', line 252 def to_ary snapshot end |