Class: Cabriolet::Compressors::MSZIP

Inherits:
Base
  • Object
show all
Defined in:
lib/cabriolet/compressors/mszip.rb

Overview

MSZIP handles MSZIP (DEFLATE) compression Based on RFC 1951 and libmspack implementation

Constant Summary collapse

FRAME_SIZE =

MSZIP frame size (32KB sliding window)

32_768
SIGNATURE =

MSZIP signature bytes

[0x43, 0x4B].freeze
STORED_BLOCK =

Block types

0
FIXED_HUFFMAN_BLOCK =
1
DYNAMIC_HUFFMAN_BLOCK =
2
MIN_MATCH =

Match length constants

3
MAX_MATCH =
258
WINDOW_SIZE =

Window size for LZ77

32_768
LIT_LENGTHS =

Match lengths for literal codes 257-285

[
  3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27,
  31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
].freeze
DIST_OFFSETS =

Match offsets for distance codes 0-29

[
  1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385,
  513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12_289, 16_385, 24_577
].freeze
LIT_EXTRABITS =

Extra bits for literal codes 257-285

[
  0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2,
  2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
].freeze
DIST_EXTRABITS =

Extra bits for distance codes 0-29

[
  0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6,
  6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13
].freeze

Instance Attribute Summary

Attributes inherited from Base

#buffer_size, #input, #io_system, #output

Instance Method Summary collapse

Constructor Details

#initialize(io_system, input, output, buffer_size) ⇒ MSZIP

Initialize MSZIP compressor

Parameters:



59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/cabriolet/compressors/mszip.rb', line 59

def initialize(io_system, input, output, buffer_size)
  super

  # Initialize bitstream writer
  @bitstream = Binary::BitstreamWriter.new(io_system, output, buffer_size)

  # Build fixed Huffman codes
  @fixed_codes = Huffman::Encoder.build_fixed_codes

  # Initialize sliding window for LZ77
  @window = "\0" * WINDOW_SIZE
  @window_pos = 0
end

Instance Method Details

#compressInteger

Compress input data using MSZIP (DEFLATE) algorithm

Returns:

  • (Integer)

    Number of bytes written



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/cabriolet/compressors/mszip.rb', line 76

def compress
  input_data = read_all_input
  total_written = 0
  pos = 0

  # Handle empty input - still need to write a block
  if input_data.empty?
    write_signature
    compress_block("", true)
    @bitstream.flush
    return 0
  end

  # Process data in FRAME_SIZE chunks
  # Each frame is independent and contains blocks ending with last_block=1
  while pos < input_data.bytesize
    chunk_size = [FRAME_SIZE, input_data.bytesize - pos].min
    chunk = input_data[pos, chunk_size]

    # Write CK signature
    write_signature

    # Compress block with fixed Huffman
    # Each frame's block is always marked as last within that frame
    compress_block(chunk, true)

    pos += chunk_size
    total_written += chunk_size
  end

  # Flush any remaining bits
  @bitstream.flush

  total_written
end