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

new(io) click to toggle source
Calls superclass method 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

flush()
Alias for: flushbits
flushbits() click to toggle source

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
Also aliased as: flush
offset() click to toggle source

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
seekbytes(n) click to toggle source

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
with_buffer(n) { || ... } click to toggle source

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("\00"" * (buf_end - offset))
  end
end
writebits(val, nbits, endian) click to toggle source

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
writebytes(str) click to toggle source

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

mask(nbits) click to toggle source
# File lib/bindata/io.rb, line 489
def mask(nbits)
  (1 << nbits) - 1
end
write(data) click to toggle source
# 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
write_big_endian_bits(val, nbits) click to toggle source
# 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
write_little_endian_bits(val, nbits) click to toggle source
# 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