Class: Cabriolet::HLP::QuickHelp::HuffmanStream

Inherits:
Object
  • Object
show all
Defined in:
lib/cabriolet/hlp/quickhelp/huffman_stream.rb

Overview

Huffman stream decoder for QuickHelp topics

Wraps a bitstream and uses a Huffman tree to decode symbols. Reads bits from MSB to LSB within each byte.

Instance Method Summary collapse

Constructor Details

#initialize(input, huffman_tree) ⇒ HuffmanStream

Initialize Huffman stream decoder

Parameters:

  • input (String, IO)

    Input data (Huffman-encoded bitstream)

  • huffman_tree (HuffmanTree)

    Huffman tree for decoding



17
18
19
20
21
22
# File 'lib/cabriolet/hlp/quickhelp/huffman_stream.rb', line 17

def initialize(input, huffman_tree)
  @input = input.is_a?(String) ? StringIO.new(input) : input
  @huffman_tree = huffman_tree
  # QuickHelp uses MSB-first bit order
  @bitstream = Binary::Bitstream.new(@input, true) # MSB first
end

Instance Method Details

#eof?Boolean

Check if at end of stream

Returns:

  • (Boolean)

    true if EOF



68
69
70
# File 'lib/cabriolet/hlp/quickhelp/huffman_stream.rb', line 68

def eof?
  @input.eof?
end

#read(length) ⇒ String

Read and decode bytes from the Huffman stream

Parameters:

  • length (Integer)

    Number of decoded bytes to read

Returns:

  • (String)

    Decoded data



28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/cabriolet/hlp/quickhelp/huffman_stream.rb', line 28

def read(length)
  result = String.new(encoding: Encoding::BINARY)

  length.times do
    byte = read_byte
    break if byte.nil?

    result << byte.chr
  end

  result
end

#read_byteInteger?

Read and decode a single byte

Returns:

  • (Integer, nil)

    Decoded byte value or nil on EOF



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/cabriolet/hlp/quickhelp/huffman_stream.rb', line 44

def read_byte
  return nil if @huffman_tree.empty?

  # Handle singular tree (single symbol, no bits needed)
  if @huffman_tree.singular?
    return @huffman_tree.root.symbol
  end

  # Decode using tree
  decoder = @huffman_tree.create_decoder

  until decoder.has_value?
    bit = @bitstream.read_bits(1)
    return nil if bit.nil? # EOF

    decoder.push(bit != 0)
  end

  decoder.value
end