class Binstream::Streams::Base

Attributes

stopper[R]

Public Class Methods

new(stream, startpos: nil, whence: IO::SEEK_SET, read_length: nil, **kwargs) click to toggle source
# File lib/binstream/streams/base.rb, line 11
def initialize(stream, startpos: nil, whence: IO::SEEK_SET, read_length: nil, **kwargs)
  @stream = stream
  reset
  setup_stopper(startpos, whence, read_length)
end

Public Instance Methods

dump(filename) click to toggle source

Dump entire stream to a file (for debugging)

# File lib/binstream/streams/base.rb, line 313
def dump(filename)
  # return nil unless $TESTING
  @stream.seek(@startpos, IO::SEEK_SET)
  File.open(filename, "wb") do |f|
    f.write(@stream.read(@stopper - @startpos))
  end
end
eof?() click to toggle source
# File lib/binstream/streams/base.rb, line 154
def eof?
  remaining <= 0
end
method_missing(meth_name, *args, &block) click to toggle source

MISC

Calls superclass method
# File lib/binstream/streams/base.rb, line 323
def method_missing(meth_name, *args, &block)
  meth = "read_#{meth_name}".to_sym
  if respond_to?(meth)
    public_send(meth, *args, &block)
  else
    super
  end
end
peek(length=nil) click to toggle source

Returns data without advancing the offset pointer

# File lib/binstream/streams/base.rb, line 108
def peek(length=nil)
  original_pos = stell
  read_size = (length || size)

  if remaining - read_size < 0
    raise StreamOverrunError.new(read_size, remaining, original_pos)
  end

  @stream.seek(@startpos + @cur_offset, IO::SEEK_SET)
  resp = @stream.read(length)

  return resp
rescue => e
  raise
ensure
  @stream.seek(original_pos, IO::SEEK_SET)
end
peek_slice(new_length, offset_adjustment=nil) click to toggle source

Get a new stream at the current position, but don't advance our internal pointer

# File lib/binstream/streams/base.rb, line 61
def peek_slice(new_length, offset_adjustment=nil)
  offset_adjustment ||= 0

  self.class.new(@stream, 
                  startpos: (@startpos + @cur_offset + offset_adjustment), 
                  read_length: new_length
                )
end
pos()
Alias for: tell
read(length=nil) click to toggle source
# File lib/binstream/streams/base.rb, line 85
def read(length=nil)

  original_pos = stell
  read_size = (length || size)

  if remaining - read_size < 0
    raise StreamOverrunError.new(read_size, remaining, original_pos)
  end

  @stream.seek(@startpos + @cur_offset, IO::SEEK_SET)
  resp = @stream.read(length)
  @cur_offset += read_size

  return resp
rescue => e
  raise
ensure
  # put the stream back
  # TODO: possibly remove this, it just makes it slower
  @stream.seek(original_pos, IO::SEEK_SET)
end
read_binary(len) click to toggle source
# File lib/binstream/streams/base.rb, line 295
def read_binary(len)
  track { sprintf("READ_BINARY(%d+%d = %d)", tell, len, (tell+len)) }
  read(len)
end
read_bool() click to toggle source

8 bit boolean

# File lib/binstream/streams/base.rb, line 185
def read_bool
  res = read_single("C", 1)

  if res != 0 && res != 1
    raise InvalidBooleanValueError.new(res, (tell - 1))
  end

  track(res != 0)
end
Also aliased as: read_bool8
read_bool8()
Alias for: read_bool
read_byte() click to toggle source
# File lib/binstream/streams/base.rb, line 203
def read_byte
  track read_single("c", 1)
end
read_double() click to toggle source

8 byte double

# File lib/binstream/streams/base.rb, line 278
def read_double
  res = read_single("E", 8)
  if res.nan?
    raise InvalidFloatValueError.new(tell - 8)
  end
  track res
end
Also aliased as: read_doublele
read_doublebe() click to toggle source
# File lib/binstream/streams/base.rb, line 285
def read_doublebe
  res = read_single("G", 8)
  if res.nan?
    raise InvalidFloatValueError.new(tell - 8)
  end
  track res
end
read_doublele()
Alias for: read_double
read_float() click to toggle source

4 byte floats

# File lib/binstream/streams/base.rb, line 260
def read_float
  res = read_single("e", 4)
  if res.nan?
    raise InvalidFloatValueError.new(tell - 4)
  end
  track res
end
Also aliased as: read_floatle
read_floatbe() click to toggle source
# File lib/binstream/streams/base.rb, line 267
def read_floatbe
  res = read_single("g", 4)
  if res.nan?
    raise InvalidFloatValueError.new(tell - 4)
  end
  track res
end
read_floatle()
Alias for: read_float
read_hash(len) click to toggle source
# File lib/binstream/streams/base.rb, line 300
def read_hash(len)
  track read_single("H*", len)
end
read_int16() click to toggle source
# File lib/binstream/streams/base.rb, line 216
def read_int16
  track read_single("s<", 2)
end
Also aliased as: read_int16le
read_int16be() click to toggle source
# File lib/binstream/streams/base.rb, line 219
def read_int16be
  track read_single("s>", 2)
end
read_int16le()
Alias for: read_int16
read_int32() click to toggle source

32 bits

# File lib/binstream/streams/base.rb, line 225
def read_int32
  track read_single("l<", 4)
end
Also aliased as: read_int32le
read_int32be() click to toggle source
# File lib/binstream/streams/base.rb, line 228
def read_int32be
  track read_single("l>", 4)
end
read_int32le()
Alias for: read_int32
read_int64() click to toggle source

64 bits

# File lib/binstream/streams/base.rb, line 243
def read_int64
  track read_single("q<", 8)
end
Also aliased as: read_int64le
read_int64be() click to toggle source
# File lib/binstream/streams/base.rb, line 246
def read_int64be
  track read_single("q>", 8)
end
read_int64le()
Alias for: read_int64
read_int8() click to toggle source

8 Bits

# File lib/binstream/streams/base.rb, line 197
def read_int8
  track read_single("c", 1)
end
read_single(fmt, bytes = 4) click to toggle source
# File lib/binstream/streams/base.rb, line 304
def read_single(fmt, bytes = 4)
  read(bytes).unpack1(fmt)
end
read_string(length, encoding: "UTF-8", packfmt: "Z*") click to toggle source

Reads a null terminated string off the stream

# File lib/binstream/streams/base.rb, line 175
def read_string(length, encoding: "UTF-8", packfmt: "Z*")
  if length > 0
    res = read_single(packfmt, length).force_encoding(encoding).encode(encoding)
    track res
  else
    raise InvalidLengthError.new(length)
  end
end
read_uint16() click to toggle source

16 Bits

# File lib/binstream/streams/base.rb, line 208
def read_uint16
  track read_single("S<", 2)
end
Also aliased as: read_uint16le
read_uint16be() click to toggle source
# File lib/binstream/streams/base.rb, line 211
def read_uint16be
  track read_single("S>", 2)
end
read_uint16le()
Alias for: read_uint16
read_uint32() click to toggle source
# File lib/binstream/streams/base.rb, line 233
def read_uint32
  track read_single("L<", 4)
end
Also aliased as: read_uint32le
read_uint32be() click to toggle source
# File lib/binstream/streams/base.rb, line 236
def read_uint32be
  track read_single("L>", 4)
end
read_uint32le()
Alias for: read_uint32
read_uint64() click to toggle source
# File lib/binstream/streams/base.rb, line 251
def read_uint64
  track read_single("Q<", 8)
end
Also aliased as: read_uint64le
read_uint64be() click to toggle source
# File lib/binstream/streams/base.rb, line 254
def read_uint64be
  track read_single("Q>", 8)
end
read_uint64le()
Alias for: read_uint64
read_uint8() click to toggle source
# File lib/binstream/streams/base.rb, line 200
def read_uint8
  track read_single("C", 1)
end
read_unpack(bytes, fmt) click to toggle source
# File lib/binstream/streams/base.rb, line 308
def read_unpack(bytes, fmt)
  read(bytes).unpack(fmt)
end
remaining() click to toggle source

How many remaining bytes are there

# File lib/binstream/streams/base.rb, line 71
def remaining
  size - tell
end
remaining?(len_to_check=1) click to toggle source

Do we have any remaining bytes?

# File lib/binstream/streams/base.rb, line 76
def remaining?(len_to_check=1)
  remaining >= len_to_check
end
reset() click to toggle source
# File lib/binstream/streams/base.rb, line 35
def reset
  @cur_offset = 0
  @stopper = nil
  @startpos = 0
end
rewind() click to toggle source

Reset the position pointer back to the start

# File lib/binstream/streams/base.rb, line 81
def rewind
  @cur_offset = 0
end
seek(seek_len, whence=IO::SEEK_CUR) click to toggle source

Seek to a specific position, or relative

# File lib/binstream/streams/base.rb, line 127
def seek(seek_len, whence=IO::SEEK_CUR)
  raise ArgumentError.new("Position must be an integer") if seek_len.nil?

  case whence
  when IO::SEEK_SET, :SET
    proposal = seek_len
  when IO::SEEK_CUR, :CUR
    proposal = @cur_offset + seek_len
  when IO::SEEK_END, :END
    proposal = @stopper + seek_len # This will actually be a +(-999)
  else
    raise ArgumentError.new("whence must be :SET, :CUR, :END")
  end

  if valid_position?(proposal)
    @cur_offset = proposal
  else
    raise InvalidPositionError.new(proposal)
  end
  return true
end
setup_stopper(startpos, whence, max_length) click to toggle source
# File lib/binstream/streams/base.rb, line 17
def setup_stopper(startpos, whence, max_length)
  if whence == IO::SEEK_CUR
    startpos += @stream.tell
  end

  @startpos = startpos || @stream.tell

  if max_length
    @stopper = startpos + max_length
  else
    @stopper = @stream.size
  end
end
size()
Alias for: total_size
slice(new_length, new_offset=nil) click to toggle source

Create a new stream based off this one using an offset and length

# File lib/binstream/streams/base.rb, line 42
def slice(new_length, new_offset=nil)
  new_stream = peek_slice(new_length, new_offset)
  
  # advance our pointer
  @cur_offset += new_length

  return new_stream
end
slice!(new_length, new_offset) click to toggle source

slice!(length, offset) Get new stream using absolute position

# File lib/binstream/streams/base.rb, line 53
def slice!(new_length, new_offset)
  self.class.new(@stream, 
    startpos: (@startpos + new_offset), 
    read_length: new_length
  )
end
starting_offset() click to toggle source
# File lib/binstream/streams/base.rb, line 31
def starting_offset
  @startpos
end
stell() click to toggle source

Position on the underlying stream

# File lib/binstream/streams/base.rb, line 165
def stell
  @stream.tell
end
tell() click to toggle source

Position in our current high level stream

# File lib/binstream/streams/base.rb, line 159
def tell
  @cur_offset
end
Also aliased as: pos
total_size() click to toggle source
# File lib/binstream/streams/base.rb, line 169
def total_size
  stopper - @startpos
end
Also aliased as: size
valid_position?(proposal) click to toggle source

Is this actually a valid position?

# File lib/binstream/streams/base.rb, line 150
def valid_position?(proposal)
  proposal.abs <= size
end