class BinData::IO::Write
See IO::Read for more information.
The IO can handle bitstreams in either big or little endian format.
object.
If io
is a string it will be automatically wrapped in an StringIO
Create a new IO Write wrapper around io
. io
must provide #write.
def flushbits
def flushbits raise "Internal state error nbits = #{@wnbits}" if @wnbits >= 8 if @wnbits > 0 writebits(0, 8 - @wnbits, @wendian) end end
def initialize(io)
def initialize(io) if self.class === io raise ArgumentError, "io must not be a #{self.class}" end # wrap strings in a StringIO if io.respond_to?(:to_str) io = BinData::IO.create_string_io(io.to_str) end @io = RawIO.new(io) @wnbits = 0 @wval = 0 @wendian = nil end
def mask(nbits)
def mask(nbits) (1 << nbits) - 1 end
def seek_to_abs_offset(n)
def seek_to_abs_offset(n) raise IOError, "stream is unseekable" unless @io.seekable? flushbits @io.seek_abs(n) end
def transform(io)
+io+ must be an instance of +Transform+.
See +BinData::Buffer+ as an example.
Allow transforming data in the output stream.
def transform(io) flushbits saved = @io @io = io.prepend_to_chain(@io) yield(self, io) io.after_write_transform ensure @io = saved end
def write(data)
def write(data) @io.write(data) end
def write_big_endian_bits(val, nbits)
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
def write_little_endian_bits(val, nbits)
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
def writebits(val, nbits, endian)
Writes +nbits+ bits from +val+ to the stream. +endian+ specifies whether
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
def writebytes(str)
def writebytes(str) flushbits write(str) end