Class: Omnizip::Implementations::XZUtils::LZMA2::Decoder
- Inherits:
-
Object
- Object
- Omnizip::Implementations::XZUtils::LZMA2::Decoder
- Includes:
- Algorithms::LZMA2Const
- Defined in:
- lib/omnizip/implementations/xz_utils/lzma2/decoder.rb
Overview
XZ Utils LZMA2 decoder implementation.
This is the original Decoder moved from algorithms/lzma2/decoder.rb to the new namespace structure.
Constant Summary
Constants included from Algorithms::LZMA2Const
Algorithms::LZMA2Const::CHUNK_MAX, Algorithms::LZMA2Const::CONTROL_END, Algorithms::LZMA2Const::CONTROL_LZMA_MIN, Algorithms::LZMA2Const::CONTROL_UNCOMPRESSED, Algorithms::LZMA2Const::CONTROL_UNCOMPRESSED_RESET, Algorithms::LZMA2Const::DICT_SIZE_MAX, Algorithms::LZMA2Const::DICT_SIZE_MIN, Algorithms::LZMA2Const::FLAG_RESET_DICT, Algorithms::LZMA2Const::FLAG_RESET_PROPERTIES, Algorithms::LZMA2Const::FLAG_RESET_STATE, Algorithms::LZMA2Const::FLAG_UNCOMPRESSED_SIZE, Algorithms::LZMA2Const::HEADER_MAX, Algorithms::LZMA2Const::HEADER_UNCOMPRESSED, Algorithms::LZMA2Const::UNCOMPRESSED_MAX
Instance Attribute Summary collapse
-
#dict_size ⇒ Object
readonly
Returns the value of attribute dict_size.
Instance Method Summary collapse
-
#decode_stream ⇒ String
Decode a compressed stream.
-
#initialize(input, options = {}) ⇒ Decoder
constructor
Initialize the decoder.
Constructor Details
#initialize(input, options = {}) ⇒ Decoder
Initialize the decoder
44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/omnizip/implementations/xz_utils/lzma2/decoder.rb', line 44 def initialize(input, = {}) @input = input @options = @raw_mode = [:raw_mode] || false if @raw_mode # In raw_mode (XZ format), property byte is provided by caller # Only dict_size comes from the XZ filter properties @dict_size = [:dict_size] || (8 * 1024 * 1024) @properties = Omnizip::Algorithms::LZMA2::Properties.new(@dict_size) else read_property_byte end end |
Instance Attribute Details
#dict_size ⇒ Object (readonly)
Returns the value of attribute dict_size.
36 37 38 |
# File 'lib/omnizip/implementations/xz_utils/lzma2/decoder.rb', line 36 def dict_size @dict_size end |
Instance Method Details
#decode_stream ⇒ String
Decode a compressed stream
XZ Utils pattern (lzma2_decoder.c):
- LZMA decoder is created ONCE and reused across all chunks
- State (dictionary, probability models) persists between chunks
- Reset only when control byte indicates new properties (control >= 0xC0)
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 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/omnizip/implementations/xz_utils/lzma2/decoder.rb', line 67 def decode_stream output_io = StringIO.new output_io.set_encoding("ASCII-8BIT") # XZ Utils pattern: Create LZMA decoder ONCE (lzma2_decoder_init) # The decoder will be reused across all chunks @lzma_decoder = nil @need_properties = true # First LZMA chunk needs properties (XZ Utils line 45) @need_dictionary_reset = true # First chunk must reset dictionary (XZ Utils line 43) chunk_num = 0 loop do control = read_control_byte break if control == CONTROL_END # XZ Utils pattern (lzma2_decoder.c:75-82): # Dictionary reset is needed if control >= 0xE0 or control == 1 # If dictionary reset is needed but control doesn't do it, error # Reference: /Users/mulgogi/src/external/xz/src/liblzma/lzma/lzma2_decoder.c:75-82 if control >= 0xE0 || control == CONTROL_UNCOMPRESSED_RESET @need_properties = true @need_dictionary_reset = true elsif @need_dictionary_reset raise Omnizip::FormatError, "LZMA2 dictionary reset required but not performed (control=0x#{control.to_s(16).upcase})" end # XZ Utils pattern (lzma2_decoder.c:121-126): # Clear dictionary reset flag. The actual dict_reset is handled # by the LZMA decoder when processing the chunk data. # Reference: /Users/mulgogi/src/external/xz/src/liblzma/lzma/lzma2_decoder.c:121-127 if @need_dictionary_reset @need_dictionary_reset = false end # XZ Utils pattern (lzma2_decoder.c:84-110): # For LZMA chunks (control >= 0x80), validate properties requirements # Reference: /Users/mulgogi/src/external/xz/src/liblzma/lzma/lzma2_decoder.c:98-99 if control >= 0x80 if control >= 0xC0 # New properties present - properties will be read below @need_properties = false elsif @need_properties # LZMA chunk without properties but properties are needed # This happens after dictionary reset when next chunk must have properties raise Omnizip::FormatError, "LZMA2 properties required but not provided (control=0x#{control.to_s(16).upcase})" end end chunk_data = decode_chunk(control, chunk_num) # XZ Utils pattern: Uncompressed chunks ALWAYS produce output # Dictionary reset chunks (control == 1) initialize the dictionary # with the chunk data, then the dictionary is flushed to output # So we should NEVER skip output for valid chunks # Reference: /Users/mulgogi/src/external/xz/src/liblzma/lzma/lzma2_decoder.c:121-127 output_io.write(chunk_data) chunk_num += 1 end output_io.string.force_encoding("ASCII-8BIT") end |