Class: Cabriolet::Decompressors::MSZIP

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

Overview

MSZIP handles MSZIP (deflate) compressed data Based on RFC 1951 and libmspack implementation

Constant Summary collapse

FRAME_SIZE =

MSZIP frame size (32KB sliding window)

32_768
LITERAL_MAXSYMBOLS =

Huffman tree constants

288
LITERAL_TABLEBITS =
9
DISTANCE_MAXSYMBOLS =
32
DISTANCE_TABLEBITS =
6
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
BITLEN_ORDER =

Order of bit length code lengths

[
  16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
].freeze

Instance Attribute Summary

Attributes inherited from Base

#buffer_size, #input, #io_system, #output

Instance Method Summary collapse

Methods inherited from Base

#free

Constructor Details

#initialize(io_system, input, output, buffer_size, fix_mszip: false) ⇒ MSZIP

Initialize MSZIP decompressor

Parameters:



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/cabriolet/decompressors/mszip.rb', line 53

def initialize(io_system, input, output, buffer_size, fix_mszip: false)
  super(io_system, input, output, buffer_size)
  @fix_mszip = fix_mszip

  # Initialize sliding window
  @window = "\0" * FRAME_SIZE
  @window_posn = 0
  @bytes_output = 0

  # Initialize bitstream
  @bitstream = Binary::Bitstream.new(io_system, input, buffer_size)

  # Initialize Huffman trees
  @literal_lengths = Array.new(LITERAL_MAXSYMBOLS, 0)
  @distance_lengths = Array.new(DISTANCE_MAXSYMBOLS, 0)
  @literal_tree = nil
  @distance_tree = nil
end

Instance Method Details

#decompress(bytes) ⇒ Integer

Decompress MSZIP data

Parameters:

  • bytes (Integer)

    Number of bytes to decompress

Returns:

  • (Integer)

    Number of bytes decompressed



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
# File 'lib/cabriolet/decompressors/mszip.rb', line 76

def decompress(bytes)
  total_written = 0

  while bytes.positive?
    # Read 'CK' signature
    read_signature

    # Reset window state for new block
    @window_posn = 0
    @bytes_output = 0

    # Inflate the block
    begin
      inflate_block
    rescue DecompressionError
      raise unless @fix_mszip

      # In repair mode, pad with zeros
      (@bytes_output...FRAME_SIZE).each do |i|
        @window.setbyte(i, 0)
      end
      @bytes_output = FRAME_SIZE
    end

    # Write output
    write_amount = [bytes, @bytes_output].min
    io_system.write(output, @window[0, write_amount])
    total_written += write_amount
    bytes -= write_amount
  end

  total_written
end