Class: Cabriolet::Binary::Bitstream

Inherits:
Object
  • Object
show all
Defined in:
lib/cabriolet/binary/bitstream.rb

Overview

Bitstream provides bit-level I/O operations for reading compressed data

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(io_system, handle, buffer_size = Cabriolet.default_buffer_size) ⇒ Bitstream

Initialize a new bitstream

Parameters:



14
15
16
17
18
19
20
21
22
23
# File 'lib/cabriolet/binary/bitstream.rb', line 14

def initialize(io_system, handle,
buffer_size = Cabriolet.default_buffer_size)
  @io_system = io_system
  @handle = handle
  @buffer_size = buffer_size
  @buffer = ""
  @buffer_pos = 0
  @bit_buffer = 0
  @bits_left = 0
end

Instance Attribute Details

#buffer_sizeObject (readonly)

Returns the value of attribute buffer_size.



7
8
9
# File 'lib/cabriolet/binary/bitstream.rb', line 7

def buffer_size
  @buffer_size
end

#handleObject (readonly)

Returns the value of attribute handle.



7
8
9
# File 'lib/cabriolet/binary/bitstream.rb', line 7

def handle
  @handle
end

#io_systemObject (readonly)

Returns the value of attribute io_system.



7
8
9
# File 'lib/cabriolet/binary/bitstream.rb', line 7

def io_system
  @io_system
end

Instance Method Details

#byte_alignvoid

This method returns an undefined value.

Align to the next byte boundary



71
72
73
74
75
# File 'lib/cabriolet/binary/bitstream.rb', line 71

def byte_align
  discard_bits = @bits_left % 8
  @bit_buffer >>= discard_bits
  @bits_left -= discard_bits
end

#peek_bits(num_bits) ⇒ Integer

Peek at bits without consuming them

Parameters:

  • num_bits (Integer)

    Number of bits to peek at

Returns:

  • (Integer)

    Bits as an integer



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/cabriolet/binary/bitstream.rb', line 81

def peek_bits(num_bits)
  if num_bits < 1 || num_bits > 32
    raise ArgumentError,
          "Can only peek 1-32 bits at a time"
  end

  # Ensure we have enough bits
  while @bits_left < num_bits
    byte = read_byte
    return 0 if byte.nil?

    @bit_buffer |= (byte << @bits_left)
    @bits_left += 8
  end

  @bit_buffer & ((1 << num_bits) - 1)
end

#read_bits(num_bits) ⇒ Integer

Read specified number of bits from the stream

Parameters:

  • num_bits (Integer)

    Number of bits to read (1-32)

Returns:

  • (Integer)

    Bits read as an integer

Raises:



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/cabriolet/binary/bitstream.rb', line 30

def read_bits(num_bits)
  if num_bits < 1 || num_bits > 32
    raise ArgumentError,
          "Can only read 1-32 bits at a time"
  end

  # Ensure we have enough bits in the buffer
  while @bits_left < num_bits
    byte = read_byte
    return 0 if byte.nil? # EOF

    @bit_buffer |= (byte << @bits_left)
    @bits_left += 8
  end

  # Extract the requested bits
  result = @bit_buffer & ((1 << num_bits) - 1)
  @bit_buffer >>= num_bits
  @bits_left -= num_bits

  result
end

#read_bits_be(num_bits) ⇒ Integer

Read bits in big-endian (MSB first) order

Parameters:

  • num_bits (Integer)

    Number of bits to read

Returns:

  • (Integer)

    Bits as an integer



112
113
114
115
116
117
118
# File 'lib/cabriolet/binary/bitstream.rb', line 112

def read_bits_be(num_bits)
  result = 0
  num_bits.times do
    result = (result << 1) | read_bits(1)
  end
  result
end

#read_byteInteger?

Read a single byte from the input

Returns:

  • (Integer, nil)

    Byte value or nil at EOF



56
57
58
59
60
61
62
63
64
65
66
# File 'lib/cabriolet/binary/bitstream.rb', line 56

def read_byte
  if @buffer_pos >= @buffer.bytesize
    @buffer = @io_system.read(@handle, @buffer_size)
    @buffer_pos = 0
    return nil if @buffer.empty?
  end

  byte = @buffer.getbyte(@buffer_pos)
  @buffer_pos += 1
  byte
end

#read_uint16_leInteger

Read a 16-bit little-endian value

Returns:

  • (Integer)

    16-bit value



123
124
125
# File 'lib/cabriolet/binary/bitstream.rb', line 123

def read_uint16_le
  read_bits(16)
end

#read_uint32_leInteger

Read a 32-bit little-endian value

Returns:

  • (Integer)

    32-bit value



130
131
132
133
134
# File 'lib/cabriolet/binary/bitstream.rb', line 130

def read_uint32_le
  low = read_bits(16)
  high = read_bits(16)
  (high << 16) | low
end

#resetvoid

This method returns an undefined value.

Reset the bitstream state



139
140
141
142
143
144
145
# File 'lib/cabriolet/binary/bitstream.rb', line 139

def reset
  @buffer = ""
  @buffer_pos = 0
  @bit_buffer = 0
  @bits_left = 0
  @io_system.seek(@handle, 0, Constants::SEEK_START)
end

#skip_bits(num_bits) ⇒ void

This method returns an undefined value.

Skip specified number of bits

Parameters:

  • num_bits (Integer)

    Number of bits to skip



103
104
105
106
# File 'lib/cabriolet/binary/bitstream.rb', line 103

def skip_bits(num_bits)
  read_bits(num_bits)
  nil
end