class BinData::IO::Read
Create a new IO Read
wrapper around io
. io
must provide read, pos if reading the current stream
position and seek if setting the
current stream position. If io
is a string it will be
automatically wrapped in an StringIO object.
The IO can handle bitstreams in either big or little endian format.
M byte1 L M byte2 L S 76543210 S S fedcba98 S B B B B
In big endian format:
readbits(6), readbits(5) #=> [765432, 10fed]
In little endian format:
readbits(6), readbits(5) #=> [543210, a9876]
Public Class Methods
# File lib/bindata/io.rb, line 173 def initialize(io) super(io) # bits when reading @rnbits = 0 @rval = 0 @rendian = nil end
Public Instance Methods
Returns the current offset of the io stream. Offset will be rounded up when reading bitfields.
# File lib/bindata/io.rb, line 193 def offset offset_raw end
Reads all remaining bytes from the stream.
# File lib/bindata/io.rb, line 218 def read_all_bytes reset_read_bits read end
Reads exactly nbits
bits from the stream. endian
specifies whether the bits are stored in :big
or
:little
endian format.
# File lib/bindata/io.rb, line 225 def readbits(nbits, endian) if @rendian != endian # don't mix bits of differing endian reset_read_bits @rendian = endian end if endian == :big read_big_endian_bits(nbits) else read_little_endian_bits(nbits) end end
Reads exactly n
bytes from io
.
If the data read is nil an EOFError is raised.
If the data read is too short an IOError is raised.
# File lib/bindata/io.rb, line 208 def readbytes(n) reset_read_bits str = read(n) raise EOFError, "End of file reached" if str.nil? raise IOError, "data truncated" if str.size < n str end
Discards any read bits so the stream becomes aligned at the next byte boundary.
# File lib/bindata/io.rb, line 241 def reset_read_bits @rnbits = 0 @rval = 0 end
Seek n
bytes from the current position in the io stream.
# File lib/bindata/io.rb, line 198 def seekbytes(n) reset_read_bits seek(n) end
Sets a buffer of n
bytes on the io stream. Any reading or
seeking calls inside the block
will be contained within this
buffer.
# File lib/bindata/io.rb, line 184 def with_buffer(n, &block) with_buffer_common(n) do block.call read end end
Private Instance Methods
# File lib/bindata/io.rb, line 265 def accumulate_big_endian_bits byte = read(1) raise EOFError, "End of file reached" if byte.nil? byte = byte.unpack('C').at(0) & 0xff @rval = (@rval << 8) | byte @rnbits += 8 end
# File lib/bindata/io.rb, line 286 def accumulate_little_endian_bits byte = read(1) raise EOFError, "End of file reached" if byte.nil? byte = byte.unpack('C').at(0) & 0xff @rval = @rval | (byte << @rnbits) @rnbits += 8 end
# File lib/bindata/io.rb, line 295 def mask(nbits) (1 << nbits) - 1 end
# File lib/bindata/io.rb, line 249 def read(n = nil) read_raw(buffer_limited_n(n)) end
# File lib/bindata/io.rb, line 253 def read_big_endian_bits(nbits) while @rnbits < nbits accumulate_big_endian_bits end val = (@rval >> (@rnbits - nbits)) & mask(nbits) @rnbits -= nbits @rval &= mask(@rnbits) val end
# File lib/bindata/io.rb, line 274 def read_little_endian_bits(nbits) while @rnbits < nbits accumulate_little_endian_bits end val = @rval & mask(nbits) @rnbits -= nbits @rval >>= nbits val end