Class: Cabriolet::Decompressors::LZSS
- Defined in:
- lib/cabriolet/decompressors/lzss.rb
Overview
LZSS decompressor for LZSS-compressed CAB data
LZSS (Lempel-Ziv-Storer-Szymanski) is a derivative of LZ77 compression. It uses a 4096-byte sliding window with a control byte mechanism to indicate whether the next operation is a literal byte copy or a match from the window history.
Constant Summary collapse
- WINDOW_SIZE =
LZSS algorithm constants
4096- WINDOW_FILL =
0x20- MODE_EXPAND =
LZSS modes
0- MODE_MSHELP =
1- MODE_QBASIC =
2
Instance Attribute Summary collapse
-
#mode ⇒ Object
readonly
Returns the value of attribute mode.
-
#window ⇒ Object
readonly
Returns the value of attribute window.
-
#window_pos ⇒ Object
readonly
Returns the value of attribute window_pos.
Attributes inherited from Base
#buffer_size, #input, #io_system, #output
Instance Method Summary collapse
-
#decompress(_bytes) ⇒ Integer
Decompress LZSS data.
-
#initialize(io_system, input, output, buffer_size, mode = MODE_EXPAND) ⇒ LZSS
constructor
Initialize LZSS decompressor.
Methods inherited from Base
Constructor Details
#initialize(io_system, input, output, buffer_size, mode = MODE_EXPAND) ⇒ LZSS
Initialize LZSS decompressor
30 31 32 33 34 35 36 37 38 39 |
# File 'lib/cabriolet/decompressors/lzss.rb', line 30 def initialize(io_system, input, output, buffer_size, mode = MODE_EXPAND) super(io_system, input, output, buffer_size) @mode = mode @window = Array.new(WINDOW_SIZE, WINDOW_FILL) @window_pos = initialize_window_position @input_buffer = "" @input_pos = 0 @invert = mode == MODE_MSHELP ? 0xFF : 0x00 end |
Instance Attribute Details
#mode ⇒ Object (readonly)
Returns the value of attribute mode.
21 22 23 |
# File 'lib/cabriolet/decompressors/lzss.rb', line 21 def mode @mode end |
#window ⇒ Object (readonly)
Returns the value of attribute window.
21 22 23 |
# File 'lib/cabriolet/decompressors/lzss.rb', line 21 def window @window end |
#window_pos ⇒ Object (readonly)
Returns the value of attribute window_pos.
21 22 23 |
# File 'lib/cabriolet/decompressors/lzss.rb', line 21 def window_pos @window_pos end |
Instance Method Details
#decompress(_bytes) ⇒ Integer
Decompress LZSS data
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/cabriolet/decompressors/lzss.rb', line 46 def decompress(_bytes) bytes_written = 0 loop do # Read control byte control_byte = read_input_byte break if control_byte.nil? control_byte ^= @invert # Process each bit in the control byte 8.times do |bit_index| mask = 1 << bit_index if control_byte.anybits?(mask) # Bit is 1: literal byte literal = read_input_byte break if literal.nil? @window[@window_pos] = literal write_output_byte(literal) bytes_written += 1 @window_pos = (@window_pos + 1) & (WINDOW_SIZE - 1) else # Bit is 0: match from window offset_low = read_input_byte break if offset_low.nil? offset_high_and_length = read_input_byte break if offset_high_and_length.nil? # Decode match position and length match_pos = offset_low | ((offset_high_and_length & 0xF0) << 4) length = (offset_high_and_length & 0x0F) + 3 # Copy from window length.times do byte = @window[match_pos] @window[@window_pos] = byte write_output_byte(byte) bytes_written += 1 @window_pos = (@window_pos + 1) & (WINDOW_SIZE - 1) match_pos = (match_pos + 1) & (WINDOW_SIZE - 1) end end end end bytes_written end |