class BinData::IO::Write
Create a new IO
Write
wrapper around io
. io
must provide write
. 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.
See IO::Read
for more information.
Public Class Methods
BinData::IO::Common::new
# File lib/bindata/io.rb, line 370 def initialize(io) super(io) @wnbits = 0 @wval = 0 @wendian = nil end
Public Instance Methods
To be called after all writebits
have been applied.
# File lib/bindata/io.rb, line 426 def flushbits raise "Internal state error nbits = #{@wnbits}" if @wnbits >= 8 if @wnbits > 0 writebits(0, 8 - @wnbits, @wendian) end end
Returns the current offset of the io stream. Offset will be rounded up when writing bitfields.
# File lib/bindata/io.rb, line 391 def offset offset_raw + (@wnbits > 0 ? 1 : 0) end
Seek n
bytes from the current position in the io stream.
# File lib/bindata/io.rb, line 396 def seekbytes(n) flushbits seek(n) end
Sets a buffer of n
bytes on the io stream. Any writes inside the block
will be contained within this buffer. If less than n
bytes are written inside the block, the remainder will be padded with '0' bytes.
# File lib/bindata/io.rb, line 382 def with_buffer(n) with_buffer_common(n) do |_buf_start, buf_end| yield write("\0" * (buf_end - offset)) end end
Writes nbits
bits from val
to the stream. endian
specifies whether the bits are to be stored in :big
or :little
endian format.
# File lib/bindata/io.rb, line 409 def writebits(val, nbits, endian) if @wendian != endian # don't mix bits of differing endian flushbits @wendian = endian end clamped_val = val & mask(nbits) if endian == :big write_big_endian_bits(clamped_val, nbits) else write_little_endian_bits(clamped_val, nbits) end end
Writes the given string of bytes to the io stream.
# File lib/bindata/io.rb, line 402 def writebytes(str) flushbits write(str) end
Private Instance Methods
# File lib/bindata/io.rb, line 489 def mask(nbits) (1 << nbits) - 1 end
# File lib/bindata/io.rb, line 438 def write(data) n = buffer_limited_n(data.size) if n < data.size data = data[0, n] end write_raw(data) end
# File lib/bindata/io.rb, line 447 def write_big_endian_bits(val, nbits) while nbits > 0 bits_req = 8 - @wnbits if nbits >= bits_req msb_bits = (val >> (nbits - bits_req)) & mask(bits_req) nbits -= bits_req val &= mask(nbits) @wval = (@wval << bits_req) | msb_bits write(@wval.chr) @wval = 0 @wnbits = 0 else @wval = (@wval << nbits) | val @wnbits += nbits nbits = 0 end end end
# File lib/bindata/io.rb, line 468 def write_little_endian_bits(val, nbits) while nbits > 0 bits_req = 8 - @wnbits if nbits >= bits_req lsb_bits = val & mask(bits_req) nbits -= bits_req val >>= bits_req @wval = @wval | (lsb_bits << @wnbits) write(@wval.chr) @wval = 0 @wnbits = 0 else @wval = @wval | (val << @wnbits) @wnbits += nbits nbits = 0 end end end