Class: BinData::IO::Read

Inherits:
Object
  • Object
show all
Defined in:
lib/bindata/io.rb

Overview

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]

Defined Under Namespace

Modules: SeekableStream, UnSeekableStream

Instance Method Summary collapse

Constructor Details

#initialize(io) ⇒ Read

Returns a new instance of Read.

Raises:

  • (ArgumentError)


33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/bindata/io.rb', line 33

def initialize(io)
  raise ArgumentError, "io must not be a BinData::IO::Read" if BinData::IO::Read === io

  # wrap strings in a StringIO
  if io.respond_to?(:to_str)
    io = BinData::IO.create_string_io(io.to_str)
  end

  @raw_io = io

  # bits when reading
  @rnbits  = 0
  @rval    = 0
  @rendian = nil

  @buffer_end_pos = nil

  extend seekable? ? SeekableStream : UnSeekableStream
end

Instance Method Details

#read_all_bytesObject

Reads all remaining bytes from the stream.



91
92
93
94
# File 'lib/bindata/io.rb', line 91

def read_all_bytes
  reset_read_bits
  read
end

#readbits(nbits, endian) ⇒ Object

Reads exactly nbits bits from the stream. endian specifies whether the bits are stored in :big or :little endian format.



98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/bindata/io.rb', line 98

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

#readbytes(n) ⇒ Object

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.

Raises:

  • (EOFError)


81
82
83
84
85
86
87
88
# File 'lib/bindata/io.rb', line 81

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

#reset_read_bitsObject

Discards any read bits so the stream becomes aligned at the next byte boundary.



114
115
116
117
# File 'lib/bindata/io.rb', line 114

def reset_read_bits
  @rnbits = 0
  @rval   = 0
end

#seekbytes(n) ⇒ Object

Seek n bytes from the current position in the io stream.



71
72
73
74
# File 'lib/bindata/io.rb', line 71

def seekbytes(n)
  reset_read_bits
  seek(n)
end

#with_buffer(n, &block) ⇒ Object

Sets a buffer of n bytes on the io stream. Any reading or seeking calls inside the block will be contained within this buffer.



55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/bindata/io.rb', line 55

def with_buffer(n, &block)
  prev = @buffer_end_pos
  if prev
    avail = prev - offset
    n = avail if n > avail
  end
  @buffer_end_pos = offset + n
  begin
    block.call
    read
  ensure
    @buffer_end_pos = prev
  end
end