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]
# File lib/bindata/io.rb, line 239 def initialize(io) super(io) # bits when reading @rnbits = 0 @rval = 0 @rendian = nil end
Returns the current offset of the io stream. Offset will be rounded up when reading bitfields.
# File lib/bindata/io.rb, line 259 def offset offset_raw end
Reads all remaining bytes from the stream.
# File lib/bindata/io.rb, line 280 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 287 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 274 def readbytes(n) reset_read_bits read(n) end
Discards any read bits so the stream becomes aligned at the next byte boundary.
# File lib/bindata/io.rb, line 303 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 264 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 250 def with_buffer(n) with_buffer_common(n) do yield read end end
# File lib/bindata/io.rb, line 332 def accumulate_big_endian_bits byte = read(1).unpack('C').at(0) & 0xff @rval = (@rval << 8) | byte @rnbits += 8 end
# File lib/bindata/io.rb, line 350 def accumulate_little_endian_bits byte = read(1).unpack('C').at(0) & 0xff @rval = @rval | (byte << @rnbits) @rnbits += 8 end
# File lib/bindata/io.rb, line 356 def mask(nbits) (1 << nbits) - 1 end
# File lib/bindata/io.rb, line 311 def read(n = nil) str = read_raw(buffer_limited_n(n)) if n raise EOFError, "End of file reached" if str.nil? raise IOError, "data truncated" if str.size < n end str end
# File lib/bindata/io.rb, line 320 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 338 def read_little_endian_bits(nbits) while @rnbits < nbits accumulate_little_endian_bits end val = @rval & mask(nbits) @rnbits -= nbits @rval >>= nbits val end