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]

Instance Method Summary collapse

Constructor Details

#initialize(io) ⇒ Read

Returns a new instance of Read.



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

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)

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

Instance Method Details

#num_bytes_remainingObject

The number of bytes remaining in the io steam.



68
69
70
# File 'lib/bindata/io.rb', line 68

def num_bytes_remaining
  @io.num_bytes_remaining
end

#read_all_bytesObject

Reads all remaining bytes from the stream.



95
96
97
98
# File 'lib/bindata/io.rb', line 95

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.



102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/bindata/io.rb', line 102

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.



89
90
91
92
# File 'lib/bindata/io.rb', line 89

def readbytes(n)
  reset_read_bits
  read(n)
end

#reset_read_bitsObject

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



118
119
120
121
# File 'lib/bindata/io.rb', line 118

def reset_read_bits
  @rnbits = 0
  @rval   = 0
end

#seek_to_abs_offset(n) ⇒ Object

Seek to an absolute offset within the io stream.



79
80
81
82
# File 'lib/bindata/io.rb', line 79

def seek_to_abs_offset(n)
  reset_read_bits
  @io.seek_abs(n)
end

#skipbytes(n) ⇒ Object

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



73
74
75
76
# File 'lib/bindata/io.rb', line 73

def skipbytes(n)
  reset_read_bits
  @io.skip(n)
end

#transform(io) ⇒ Object

Allow transforming data in the input stream. See BinData::Buffer as an example.

io must be an instance of Transform.

yields self and io to the given block



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

def transform(io)
  reset_read_bits

  saved = @io
  @io = io.prepend_to_chain(@io)
  yield(self, io)
  io.after_read_transform
ensure
  @io = saved
end