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
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_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_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_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_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_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_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_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_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_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
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