class Baikal::Pool

Represents a byte pool. Byte pools are resizeable arrays of bytes. Data can be stored into or read from byte pool as integers or as blobs.

Each byte pool has an associated /integer byte order indicator/; see go_network_byte_order, go_reverse_network_byte_order and go_native_byte_order.

Byte pools have no concept of current position; for linear traversal, see Cursor.

Attributes

bytes[R]

A Ruby string containing all the bytes currently in this pool.

Public Class Methods

new(initial_content = '') click to toggle source

Creates a new byte pool of the host system’s native byte order. If initial_content is given, loads its bytes to the newly created byte pool. Otherwise, the byte pool will be empty after creation.

Calls superclass method
# File lib/baikal.rb, line 29
def initialize initial_content = ''
  raise 'Type mismatch' unless initial_content.is_a? String
  super()
  @bytes = initial_content.dup
  @bytes.force_encoding Encoding::ASCII_8BIT
  @byte_order = '!' # native
  return
end
new_of_network_byte_order(initial_content = '') click to toggle source

Creates a new byte pool of the network byte order. If initial_content is given, loads its bytes to the newly created byte pool. Otherwise, the byte pool will be empty after creation.

# File lib/baikal.rb, line 43
def Pool::new_of_network_byte_order initial_content = ''
  raise 'Type mismatch' unless initial_content.is_a? String
  pool = Pool.new(initial_content)
  pool.go_network_byte_order
  return pool
end
new_of_reverse_network_byte_order(initial_content = '') click to toggle source

Creates a new byte pool of the reverse network byte order. If initial_content is given, loads its bytes to the newly created byte pool. Otherwise, the byte pool will be empty after creation.

# File lib/baikal.rb, line 55
def Pool::new_of_reverse_network_byte_order initial_content = ''
  raise 'Type mismatch' unless initial_content.is_a? String
  pool = Pool.new(initial_content)
  pool.go_reverse_network_byte_order
  return pool
end

Public Instance Methods

align(alignment, padding = 0) click to toggle source

Pads the byte pool to the specified alignment using the specified padding byte. If padding is not given, zero is used by default.

# File lib/baikal.rb, line 374
def align alignment, padding = 0
  raise 'Type mismatch' unless alignment.is_a? Integer
  raise 'Type mismatch' unless padding.is_a? Integer
  emit_repeated_bytes bytes_until_alignment(alignment), padding
  return
end
byte_order() click to toggle source

Returns the byte order indicator for the currently selected endianness: +>+ for BigEndian, +<+ for LittleEndian, or +!+ for whatever the native byte order is. (+Array#pack+ can accept such since Ruby 1.9.3.)

# File lib/baikal.rb, line 427
def byte_order
  return @byte_order
end
bytes_until_alignment(alignment) click to toggle source

Returns the difference between current size of the byte pool and the alignment requirement given by alignment. alignment needs not be a two’s power.

# File lib/baikal.rb, line 364
def bytes_until_alignment alignment
  raise 'Type mismatch' unless alignment.is_a? Integer
  raise 'Invalid alignment requirement' unless alignment > 0
  return -@bytes.size % alignment
end
emit_blob(blob) click to toggle source

Appends blob given as a Ruby string to this byte pool, growing the byte pool by the blob’s length.

# File lib/baikal.rb, line 318
def emit_blob blob
  @bytes << blob.to_s
  return
end
emit_byte(value) click to toggle source

Appends the byte given by value to this byte pool, growing the byte pool by one byte.

# File lib/baikal.rb, line 66
def emit_byte value
  set_byte @bytes.size, value
  return
end
emit_octa(value) click to toggle source

Appends the octabyte given by value to this byte pool using the currently selected byte order, growing the byte pool by eight bytes.

# File lib/baikal.rb, line 93
def emit_octa value
  set_octa @bytes.size, value
  return
end
emit_repeated_bytes(count, value = 0) click to toggle source

Appends count copies of the byte given by value to this byte pool, growing the byte pool by as many bytes. If value is not given, zero is used by default.

# File lib/baikal.rb, line 103
def emit_repeated_bytes count, value = 0
  raise 'Type mismatch' unless count.is_a? Integer
  raise 'Type mismatch' unless value.is_a? Integer
  @bytes << [value].pack('C') * count
  return
end
emit_tetra(value) click to toggle source

Appends the tetrabyte given by value to this byte pool using the currently selected byte order, growing the byte pool by four bytes.

# File lib/baikal.rb, line 84
def emit_tetra value
  set_tetra @bytes.size, value
  return
end
emit_wyde(value) click to toggle source

Appends the wyde given by value to this byte pool using the currently selected byte order, growing the byte pool by two bytes.

# File lib/baikal.rb, line 75
def emit_wyde value
  set_wyde @bytes.size, value
  return
end
get_blob(offset, size) click to toggle source

Extracts a blob of given size from this byte pool’s given offset and returns it as a Ruby string.

Error if such a blob lies outside of the boundaries of the pool, even partially.

# File lib/baikal.rb, line 329
def get_blob offset, size
  raise 'Type mismatch' unless offset.is_a? Integer
  raise 'Type mismatch' unless size.is_a? Integer
  raise 'Invalid blob size' if size < 0
  raise 'Offset out of range' if offset < 0 or offset + size > @bytes.size
  return @bytes[offset, size]
end
get_signed_byte(offset) click to toggle source

Retrieves one signed byte from this byte pool from the given offset.

Error if such a byte lies outside the boundaries of the pool.

# File lib/baikal.rb, line 167
def get_signed_byte offset
  raise 'Type mismatch' unless offset.is_a? Integer
  raise 'Offset out of range' if offset < 0 or offset + 1 > @bytes.size
  return @bytes.unpack("@#{offset} c").first
end
get_signed_octa(offset) click to toggle source

Retrieves one signed octabyte from this byte pool from the given offset, using the currently selected byte order.

Error if such an octa lies outside the boundaries of the pool, even partially.

# File lib/baikal.rb, line 206
def get_signed_octa offset
  raise 'Type mismatch' unless offset.is_a? Integer
  raise 'Offset out of range' if offset < 0 or offset + 8 > @bytes.size
  return @bytes.unpack("@#{offset} q#@byte_order").first
end
get_signed_tetra(offset) click to toggle source

Retrieves one signed tetrabyte from this byte pool from the given offset, using the currently selected byte order.

Error if such a tetra lies outside the boundaries of the pool, even partially.

# File lib/baikal.rb, line 193
def get_signed_tetra offset
  raise 'Type mismatch' unless offset.is_a? Integer
  raise 'Offset out of range' if offset < 0 or offset + 4 > @bytes.size
  return @bytes.unpack("@#{offset} l#@byte_order").first
end
get_signed_wyde(offset) click to toggle source

Retrieves one signed wyde from this byte pool from the given offset, using the currently selected byte order.

Error if such a wyde lies outside the boundaries of the pool, even partially.

# File lib/baikal.rb, line 180
def get_signed_wyde offset
  raise 'Type mismatch' unless offset.is_a? Integer
  raise 'Offset out of range' if offset < 0 or offset + 2 > @bytes.size
  return @bytes.unpack("@#{offset} s#@byte_order").first
end
get_unsigned_byte(offset) click to toggle source

Retrieves one unsigned byte from this byte pool from the given offset.

Error if such a byte lies outside the boundaries of the pool.

# File lib/baikal.rb, line 116
def get_unsigned_byte offset
  raise 'Type mismatch' unless offset.is_a? Integer
  raise 'Offset out of range' if offset < 0 or offset + 1 > @bytes.size
  return @bytes.unpack("@#{offset}C").first
end
get_unsigned_integer(size, offset) click to toggle source

Retrieves an unsigned integer of the given size (which must be either 1, 2, 4 or 8) from this byte pool from the given offset, using the currently selected byte order.

Error if such an integer lies outside the boundaries of the pool, even partially.

# File lib/baikal.rb, line 220
def get_unsigned_integer size, offset
  raise 'Type mismatch' unless offset.is_a? Integer
  pack_code = case size
  when 1 then 'C'
  when 2 then "S#@byte_order"
  when 4 then "L#@byte_order"
  when 8 then "Q#@byte_order"
  else raise "Unsupported integer size #{size.inspect}"
  end
  raise 'Offset out of range' if offset < 0 or offset + size > @bytes.size
  return @bytes.unpack("@#{offset} #{pack_code}").first
end
get_unsigned_octa(offset) click to toggle source

Retrieves one unsigned octabyte from this byte pool from the given offset, using the currently selected byte order.

Error if such an octa lies outside the boundaries of the pool, even partially.

# File lib/baikal.rb, line 155
def get_unsigned_octa offset
  raise 'Type mismatch' unless offset.is_a? Integer
  raise 'Offset out of range' if offset < 0 or offset + 8 > @bytes.size
  return @bytes.unpack("@#{offset} Q#@byte_order").first
end
get_unsigned_tetra(offset) click to toggle source

Retrieves one unsigned tetrabyte from this byte pool from the given offset, using the currently selected byte order.

Error if such a tetra lies outside the boundaries of the pool, even partially.

# File lib/baikal.rb, line 142
def get_unsigned_tetra offset
  raise 'Type mismatch' unless offset.is_a? Integer
  raise 'Offset out of range' if offset < 0 or offset + 4 > @bytes.size
  return @bytes.unpack("@#{offset} L#@byte_order").first
end
get_unsigned_wyde(offset) click to toggle source

Retrieves one unsigned wyde from this byte pool from the given offset, using the currently selected byte order.

Error if such a wyde lies outside the boundaries of the pool, even partially.

# File lib/baikal.rb, line 129
def get_unsigned_wyde offset
  raise 'Type mismatch' unless offset.is_a? Integer
  raise 'Offset out of range' if offset < 0 or offset + 2 > @bytes.size
  return @bytes.unpack("@#{offset} S#@byte_order").first
end
go_native_byte_order() click to toggle source

Selects the host system’s native byte order for following multibyte integer read or write operations.

# File lib/baikal.rb, line 417
def go_native_byte_order
  @byte_order = '!'
  return
end
go_network_byte_order() click to toggle source

Selects the network byte order for following multibyte integer read or write operations.

# File lib/baikal.rb, line 399
def go_network_byte_order
  @byte_order = '>'
  return
end
go_reverse_network_byte_order() click to toggle source

Selects the reverse network byte order for following multibyte integer read or write operations.

# File lib/baikal.rb, line 408
def go_reverse_network_byte_order
  @byte_order = '<'
  return
end
native_byte_order_selected?() click to toggle source

Returns whether this byte pool’s currently selected byte order is the host system’s native byte order.

# File lib/baikal.rb, line 451
def native_byte_order_selected?
  return @byte_order == '!'
end
network_byte_order_selected?() click to toggle source

Returns whether this byte pool’s currently selected byte order is the network byte order.

# File lib/baikal.rb, line 435
def network_byte_order_selected?
  return @byte_order == '>'
end
reverse_network_byte_order_selected?() click to toggle source

Returns whether this byte pool’s currently selected byte order is the reverse network byte order.

# File lib/baikal.rb, line 443
def reverse_network_byte_order_selected?
  return @byte_order == '<'
end
set_blob(offset, blob) click to toggle source

Stores a blob, given as a Ruby string, into this byte pool at the given offset.

Error if the offset lies outside the boundaries of the pool. (But it’s OK for it to point at the end of the pool.)

# File lib/baikal.rb, line 344
def set_blob offset, blob
  raise 'Type mismatch' unless offset.is_a? Integer
  blob = blob.to_s.dup.force_encoding Encoding::ASCII_8BIT
  raise 'Offset out of range' if offset < 0 or offset > @bytes.size
  @bytes[offset, blob.bytesize] = blob
  return
end
set_byte(offset, value) click to toggle source

Sets the byte in this byte pool on the given offset to the given value.

Error if the offset lies outside the boundaries of the pool. (But it’s OK for it to point at the end of the pool.)

# File lib/baikal.rb, line 239
def set_byte offset, value
  raise 'Type mismatch' unless offset.is_a? Integer
  raise 'Type mismatch' unless value.is_a? Integer
  raise 'Offset out of range' if offset < 0 or offset > @bytes.size
  @bytes[offset] = [value].pack('c')
  return
end
set_integer(size, offset, value) click to toggle source

Sets integer of the given size (which must be either 1, 2, 4 or 8) in this byte pool on the given offset to the given value, using the currently selected byte order.

Error if such an integer lies outside the boundaries of the pool, even partially.

# File lib/baikal.rb, line 300
def set_integer size, offset, value
  raise 'Type mismatch' unless offset.is_a? Integer
  pack_code = case size
  when 1 then 'C'
  when 2 then "S#@byte_order"
  when 4 then "L#@byte_order"
  when 8 then "Q#@byte_order"
  else raise "Unsupported integer size #{size.inspect}"
  end
  raise 'Offset out of range' if offset < 0 or offset > @bytes.size
  @bytes[offset, size] = [value].pack(pack_code)
  return
end
set_octa(offset, value) click to toggle source

Sets the octabyte in this byte pool on the given offset to the given value, using the currently selected byte order.

Error if the offset lies outside the boundaries of the pool. (But it’s OK for it to point at the end of the pool.)

# File lib/baikal.rb, line 284
def set_octa offset, value
  raise 'Type mismatch' unless offset.is_a? Integer
  raise 'Type mismatch' unless value.is_a? Integer
  raise 'Offset out of range' if offset < 0 or offset > @bytes.size
  @bytes[offset, 8] = [value].pack("q#@byte_order")
  return
end
set_tetra(offset, value) click to toggle source

Sets the tetrabyte in this byte pool on the given offset to the given value, using the currently selected byte order.

Error if the offset lies outside the boundaries of the pool. (But it’s OK for it to point at the end of the pool.)

# File lib/baikal.rb, line 269
def set_tetra offset, value
  raise 'Type mismatch' unless offset.is_a? Integer
  raise 'Type mismatch' unless value.is_a? Integer
  raise 'Offset out of range' if offset < 0 or offset > @bytes.size
  @bytes[offset, 4] = [value].pack("l#@byte_order")
  return
end
set_wyde(offset, value) click to toggle source

Sets the wyde in this byte pool on the given offset to the given value, using the currently selected byte order.

Error if the offset lies outside the boundaries of the pool. (But it’s OK for it to point at the end of the pool.)

# File lib/baikal.rb, line 254
def set_wyde offset, value
  raise 'Type mismatch' unless offset.is_a? Integer
  raise 'Type mismatch' unless value.is_a? Integer
  raise 'Offset out of range' if offset < 0 or offset > @bytes.size
  @bytes[offset, 2] = [value].pack("s#@byte_order")
  return
end
size() click to toggle source

Returns the number of bytes in this byte pool.

# File lib/baikal.rb, line 355
def size
  return @bytes.size
end
truncate(new_size) click to toggle source

Truncates this byte pool to new_size bytes, discarding all bytes after this offset.

Error if the byte pool is already shorter than new_size bytes.

# File lib/baikal.rb, line 387
def truncate new_size
  raise 'Type mismatch' unless new_size.is_a? Integer
  raise 'Invalid size' if new_size < 0
  raise 'Unable to truncate to grow' if new_size > @bytes.size
  @bytes[new_size .. -1] = ''
  return
end
tweak_signed_byte(offset) { |get_signed_byte(offset)| ... } click to toggle source

Fetches a signed byte from offset in this byte pool, calls thunk with the byte as its argument, and stores the result of calling thunk as a byte at the same offset.

Error if the byte lies outside this byte pool.

# File lib/baikal/tweak.rb, line 24
def tweak_signed_byte offset, &thunk
  set_byte offset, yield(get_signed_byte(offset))
  return
end
tweak_signed_octa(offset) { |get_signed_octa(offset)| ... } click to toggle source

Fetches a signed octa from offset in this byte pool, calls thunk with the octa as its argument, and stores the result of calling thunk as a octa at the same offset.

Error if the octa lies outside this byte pool, even partially.

# File lib/baikal/tweak.rb, line 96
def tweak_signed_octa offset, &thunk
  set_octa offset, yield(get_signed_octa(offset))
  return
end
tweak_signed_tetra(offset) { |get_signed_tetra(offset)| ... } click to toggle source

Fetches a signed tetra from offset in this byte pool, calls thunk with the tetra as its argument, and stores the result of calling thunk as a tetra at the same offset.

Error if the tetra lies outside this byte pool, even partially.

# File lib/baikal/tweak.rb, line 72
def tweak_signed_tetra offset, &thunk
  set_tetra offset, yield(get_signed_tetra(offset))
  return
end
tweak_signed_wyde(offset) { |get_signed_wyde(offset)| ... } click to toggle source

Fetches a signed wyde from offset in this byte pool, calls thunk with the wyde as its argument, and stores the result of calling thunk as a wyde at the same offset.

Error if the wyde lies outside this byte pool, even partially.

# File lib/baikal/tweak.rb, line 48
def tweak_signed_wyde offset, &thunk
  set_wyde offset, yield(get_signed_wyde(offset))
  return
end
tweak_unsigned_byte(offset) { |get_unsigned_byte(offset)| ... } click to toggle source

Fetches an unsigned byte from offset in this byte pool, calls thunk with the byte as its argument, and stores the result of calling thunk as a byte at the same offset.

Error if the byte lies outside this byte pool.

# File lib/baikal/tweak.rb, line 12
def tweak_unsigned_byte offset, &thunk
  set_byte offset, yield(get_unsigned_byte(offset))
  return
end
tweak_unsigned_octa(offset) { |get_unsigned_octa(offset)| ... } click to toggle source

Fetches an unsigned octa from offset in this byte pool, calls thunk with the octa as its argument, and stores the result of calling thunk as a octa at the same offset.

Error if the octa lies outside this byte pool, even partially.

# File lib/baikal/tweak.rb, line 84
def tweak_unsigned_octa offset, &thunk
  set_octa offset, yield(get_unsigned_octa(offset))
  return
end
tweak_unsigned_tetra(offset) { |get_unsigned_tetra(offset)| ... } click to toggle source

Fetches an unsigned tetra from offset in this byte pool, calls thunk with the tetra as its argument, and stores the result of calling thunk as a tetra at the same offset.

Error if the tetra lies outside this byte pool, even partially.

# File lib/baikal/tweak.rb, line 60
def tweak_unsigned_tetra offset, &thunk
  set_tetra offset, yield(get_unsigned_tetra(offset))
  return
end
tweak_unsigned_wyde(offset) { |get_unsigned_wyde(offset)| ... } click to toggle source

Fetches an unsigned wyde from offset in this byte pool, calls thunk with the wyde as its argument, and stores the result of calling thunk as a wyde at the same offset.

Error if the wyde lies outside this byte pool, even partially.

# File lib/baikal/tweak.rb, line 36
def tweak_unsigned_wyde offset, &thunk
  set_wyde offset, yield(get_unsigned_wyde(offset))
  return
end