Class: Omnizip::Formats::SevenZip::Bcj2StreamDecompressor

Inherits:
Object
  • Object
show all
Includes:
Constants
Defined in:
lib/omnizip/formats/seven_zip/bcj2_stream_decompressor.rb

Overview

Decompresses BCJ2 multi-stream folders

BCJ2 archives have 4 separate pack streams that need to be:

  1. Read separately
  2. Decompressed individually (main is LZMA, others are usually COPY)
  3. Combined via BCJ2 decoder

Constant Summary

Constants included from Constants

Constants::MAJOR_VERSION, Constants::MAX_NUM_BONDS, Constants::MAX_NUM_CODERS, Constants::MAX_NUM_PACK_STREAMS, Constants::MINOR_VERSION, Constants::SIGNATURE, Constants::SIGNATURE_SIZE, Constants::START_HEADER_SIZE

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(archive_io, folder, pack_pos, pack_sizes, stream_info) ⇒ Bcj2StreamDecompressor

Initialize BCJ2 decompressor

Parameters:

  • archive_io (IO)

    Archive file handle

  • folder (Models::Folder)

    Folder with BCJ2 coder

  • pack_pos (Integer)

    Base position of packed data

  • pack_sizes (Array<Integer>)

    Sizes of each pack stream

  • stream_info (Models::StreamInfo)

    Stream info for unpack sizes



24
25
26
27
28
29
30
# File 'lib/omnizip/formats/seven_zip/bcj2_stream_decompressor.rb', line 24

def initialize(archive_io, folder, pack_pos, pack_sizes, stream_info)
  @archive_io = archive_io
  @folder = folder
  @pack_pos = pack_pos
  @pack_sizes = pack_sizes
  @stream_info = stream_info
end

Class Method Details

.bcj2_folder?(folder) ⇒ Boolean

Check if a folder contains BCJ2 coder

Parameters:

Returns:

  • (Boolean)

    true if folder has BCJ2



36
37
38
# File 'lib/omnizip/formats/seven_zip/bcj2_stream_decompressor.rb', line 36

def self.bcj2_folder?(folder)
  folder.coders.any? { |c| c.method_id == FilterId::BCJ2 }
end

Instance Method Details

#decompress(expected_size) ⇒ String

Decompress BCJ2 multi-stream folder

Parameters:

  • expected_size (Integer)

    Expected final output size

Returns:

  • (String)

    Decompressed and BCJ2-decoded data



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/omnizip/formats/seven_zip/bcj2_stream_decompressor.rb', line 44

def decompress(expected_size)
  # Find BCJ2 coder and compression coder
  bcj2_coder = @folder.coders.find { |c| c.method_id == FilterId::BCJ2 }
  compression_coder = find_compression_coder

  raise "BCJ2 coder not found" unless bcj2_coder

  # Determine stream layout based on folder structure
  # BCJ2 has 4 input streams: main, call, jump, rc
  stream_layout = determine_stream_layout(bcj2_coder, compression_coder)

  # Read and decompress each of the 4 streams
  streams = read_bcj2_streams(stream_layout)

  # Apply BCJ2 decoder
  bcj2_data = Omnizip::Filters::Bcj2StreamData.new
  bcj2_data.main = streams[:main]
  bcj2_data.call = streams[:call]
  bcj2_data.jump = streams[:jump]
  bcj2_data.rc = streams[:rc]

  decoder = Omnizip::Filters::Bcj2Decoder.new(bcj2_data)
  decoder.decode(expected_size)
end