class Ronin::Support::Binary::Array

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

@note This class provides lazy memory mapped access to an underlying buffer. This means values are decoded/encoded each time they are read or written to.

## Examples

Creating an array of ‘int32`s:

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

@api public

@since 1.0.0

Attributes

length[R]

The number of elements in the array buffer.

@return [Integer]

type[R]

The underlying type of the data within the array buffer.

@return [CTypes::Type]

Public Class Methods

new(type, length_or_string, **kwargs) click to toggle source

Initializes the array buffer.

@param [Symbol] type

The type of each element in the array buffer.

@param [Integer, String, ByteSlice] length_or_string

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

@param [Hash{Symbol => Object}] kwargs

Additional keyword arguments.

@option kwargs [:little, :big, :net, nil] :endian

The desired endianness of the values within the array buffer.

@option kwargs [: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] :arch
The desired architecture for the values within the array buffer.

@raise [ArgumentError]

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

@example 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">

@example 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">
Calls superclass method
# 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
read_from(io,type,length) click to toggle source

Reads the struct from the IO stream.

@param [IO] io

The IO object to read from.

@param [Symbol] type

The desired type of each element in the array.

@param [Integer] length

The desired length of the array.

@return [Binary::Struct]

The read array.

@example

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

@see read_from

# File lib/ronin/support/binary/array.rb, line 152
def self.read_from(io,type,length)
  new(type,length).read_from(io)
end

Public Instance Methods

[](index) click to toggle source

Reads a value from the array at the given index.

@param [Integer] index

The index to read from.

@return [Integer, Float, String, Binary::Array, Binary::Struct]

The integer, float, or character read from the given index.

@example

array = Binary::Array.new(:uint32_le, "\x41\x00\x00\x00\x42\x00\x00\x00")
array[0]
# => 65
array[1]
# => 66
Calls superclass method
# 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) click to toggle source

Writes a value to the array at the given index.

@param [Integer] index

The array index to write the value to.

@param [Integer, Float, String, Binary::Array, Binary::Struct] value

The integer, float, or character value to write to the array.

@return [Integer, Float, String, Binary::Array, Binary::Struct]

The integer, float, or character value that was written.

@example

array = Binary::Array.new(:int32, 4)
array[0]
# => 0
array[0] = 0x11111111
array[0]
# => 286331153
Calls superclass method
# 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() { |self| ... } click to toggle source

Enumerates over every value within the array buffer.

@yield [value]

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

@yieldparam [Integer, Float, String] value

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

@return [Enumerator]

If no block was given, an Enumerator will be returned.
# 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
inspect() click to toggle source

Inspects the array buffer.

@return [String]

# File lib/ronin/support/binary/array.rb, line 245
def inspect
  "#<#{self.class}: #{@string.inspect}>"
end