Class: Ronin::Support::Binary::Array

Inherits:
Memory
  • Object
show all
Includes:
Enumerable, CTypes::Mixin
Defined in:
lib/ronin/support/binary/array.rb

Overview

Note:

This class provides lazy memory mapped access to an underlying

Represents an Array of binary types that can be read from and written to.

buffer. This means values are decoded/encoded each time they are read or written to.

Examples

Creating an array of int32s:

array = Binary::Binary::Array.new(:int32, 4)
# => #<Ronin::Support::Binary::Binary::Array: "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00">
array[0] = 0x11111111
array[1] = 0x22222222
array[2] = 0x33333333
array[3] = -1
array.to_s
# => "\x11\x11\x11\x11\"\"\"\"3333\xFF\xFF\xFF\xFF"

Creating an array from an existing String:

array = Binary::Array.new(:uint32_le, "\x41\x00\x00\x00\x42\x00\x00\x00")
# => #<Ronin::Support::Binary::Binary::Array: "A\u0000\u0000\u0000B\u0000\u0000\u0000">
array[0]
# => 65
array[1]
# => 66

Since:

  • 1.0.0

Instance Attribute Summary collapse

Attributes included from CTypes::Mixin

#arch, #endian, #os, #type_resolver, #type_system

Attributes inherited from Memory

#string

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Enumerable

#map_hash

Methods included from CTypes::Mixin

#initialize_type_system

Methods inherited from Memory

#+, #byteslice, #clear, #copy_from, #copy_to, #pack, #read_from, #size

Constructor Details

#initialize(type, length_or_string, **kwargs) ⇒ Array

Initializes the array buffer.

The desired architecture for the values within the array buffer.

Examples:

Creating a new array buffer:

array = Binary::Array.new(:uint32_le, 10)
# => #<Ronin::Support::Binary::Binary::Array: "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00">

Creating a new array buffer from a String:

array = Binary::Array.new(:uint32_le, "\x41\x00\x00\x00\x42\x00\x00\x00")
# => #<Ronin::Support::Binary::Binary::Array: "A\u0000\u0000\u0000B\u0000\u0000\u0000">

Parameters:

  • type (Symbol)

    The type of each element in the array buffer.

  • length_or_string (Integer, String, ByteSlice)

    The length of the buffer or an existing String which will be used as the underlying buffer.

  • kwargs (Hash{Symbol => Object})

    Additional keyword arguments.

Options Hash (**kwargs):

  • :endian (:little, :big, :net, nil)

    The desired endianness of the values within the array buffer.

  • :arch (:x86, :x86_64, :ppc, :ppc64, :mips, :mips_le, :mips_be, :mips64, :mips64_le, :mips64_be, :arm, :arm_le, :arm_be, :arm64, :arm64_le, :arm64_be)

Raises:

  • (ArgumentError)

    Either the length_or_string argument was not an Integer or a String.

Since:

  • 1.0.0



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/ronin/support/binary/array.rb', line 111

def initialize(type, length_or_string, **kwargs)
  initialize_type_system(**kwargs)

  @type  = @type_resolver.resolve(type)
  @cache = []

  case length_or_string
  when String, ByteSlice
    super(length_or_string)

    @length = size / @type.size
  when Integer
    @length = length_or_string

    super(@type.size * @length)
  else
    raise(ArgumentError,"first argument must be either a length (Integer) or a buffer (String): #{length_or_string.inspect}")
  end
end

Instance Attribute Details

#lengthInteger (readonly)

The number of elements in the array buffer.

Returns:

Since:

  • 1.0.0



73
74
75
# File 'lib/ronin/support/binary/array.rb', line 73

def length
  @length
end

#typeCTypes::Type (readonly)

The underlying type of the data within the array buffer.

Returns:

Since:

  • 1.0.0



68
69
70
# File 'lib/ronin/support/binary/array.rb', line 68

def type
  @type
end

Class Method Details

.read_from(io, type, length) ⇒ Binary::Struct

Reads the struct from the IO stream.

Examples:

file  = File.new('binary.dat','b')
array = Binary::Array.read_from(file,:int32,10)

Parameters:

  • io (IO)

    The IO object to read from.

  • type (Symbol)

    The desired type of each element in the array.

  • length (Integer)

    The desired length of the array.

Returns:

See Also:

Since:

  • 1.0.0



152
153
154
# File 'lib/ronin/support/binary/array.rb', line 152

def self.read_from(io,type,length)
  new(type,length).read_from(io)
end

Instance Method Details

#[](index) ⇒ Integer, ...

Reads a value from the array at the given index.

Examples:

array = Binary::Array.new(:uint32_le, "\x41\x00\x00\x00\x42\x00\x00\x00")
array[0]
# => 65
array[1]
# => 66

Parameters:

  • index (Integer)

    The index to read from.

Returns:

Since:

  • 1.0.0



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/ronin/support/binary/array.rb', line 172

def [](index)
  offset = index * @type.size

  if (index < 0) || ((offset + @type.size) > size)
    raise(IndexError,"index #{index} is out of bounds: 0...#{@length}")
  end

  case @type
  when CTypes::ObjectType
    @cache[index] ||= @type.unpack(byteslice(offset,@type.size))
  else
    data = super(offset,@type.size)
    @type.unpack(data)
  end
end

#[]=(index, value) ⇒ Integer, ...

Writes a value to the array at the given index.

Examples:

array = Binary::Array.new(:int32, 4)
array[0]
# => 0
array[0] = 0x11111111
array[0]
# => 286331153

Parameters:

Returns:

Since:

  • 1.0.0



208
209
210
211
212
213
214
215
216
217
# File 'lib/ronin/support/binary/array.rb', line 208

def []=(index,value)
  offset = index * @type.size

  if (index < 0) || ((offset + @type.size) > size)
    raise(IndexError,"index #{index} is out of bounds: 0...#{@length}")
  end

  data = @type.pack(value)
  return super(offset,@type.size,data)
end

#each {|value| ... } ⇒ Enumerator

Enumerates over every value within the array buffer.

Yields:

  • (value)

    The given block will be passed each value at each index within the array buffer.

Yield Parameters:

  • value (Integer, Float, String)

    The integer, float, or character read from the array buffer.

Returns:

  • (Enumerator)

    If no block was given, an Enumerator will be returned.

Since:

  • 1.0.0



232
233
234
235
236
237
238
# File 'lib/ronin/support/binary/array.rb', line 232

def each
  return enum_for(__method__) unless block_given?

  (0...@length).each do |index|
    yield self[index]
  end
end

#inspectString

Inspects the array buffer.

Returns:

Since:

  • 1.0.0



245
246
247
# File 'lib/ronin/support/binary/array.rb', line 245

def inspect
  "#<#{self.class}: #{@string.inspect}>"
end