Class: Omnizip::Implementations::SevenZip::LZMA::RangeDecoder
- Inherits:
-
Object
- Object
- Omnizip::Implementations::SevenZip::LZMA::RangeDecoder
- Includes:
- Algorithms::LZMA::Constants
- Defined in:
- lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb
Overview
Range decoder for 7-Zip SDK LZMA decompression
This is a direct port of 7-Zip SDK's range decoder implementation from LzmaDec.c for guaranteed compatibility with 7-Zip archives.
Reference: /Users/mulgogi/src/external/7-Zip/C/LzmaDec.c
Constant Summary
Constants included from Algorithms::LZMA::Constants
Algorithms::LZMA::Constants::BIT_MODEL_TOTAL, Algorithms::LZMA::Constants::COMPRESSION_LEVEL_DEFAULT, Algorithms::LZMA::Constants::COMPRESSION_LEVEL_MAX, Algorithms::LZMA::Constants::COMPRESSION_LEVEL_MIN, Algorithms::LZMA::Constants::DICT_SIZE_MAX, Algorithms::LZMA::Constants::DICT_SIZE_MIN, Algorithms::LZMA::Constants::DIST_ALIGN_BITS, Algorithms::LZMA::Constants::DIST_ALIGN_SIZE, Algorithms::LZMA::Constants::DIST_SLOT_FAST_LIMIT, Algorithms::LZMA::Constants::END_POS_MODEL_INDEX, Algorithms::LZMA::Constants::EOS_MARKER, Algorithms::LZMA::Constants::INIT_PROBS, Algorithms::LZMA::Constants::LEN_HIGH_SYMBOLS, Algorithms::LZMA::Constants::LEN_LOW_SYMBOLS, Algorithms::LZMA::Constants::LEN_MID_SYMBOLS, Algorithms::LZMA::Constants::LIT_SIZE_MAX, Algorithms::LZMA::Constants::MATCH_LEN_MAX, Algorithms::LZMA::Constants::MATCH_LEN_MIN, Algorithms::LZMA::Constants::MOVE_BITS, Algorithms::LZMA::Constants::NUM_DIRECT_BITS, Algorithms::LZMA::Constants::NUM_DIST_SLOTS, Algorithms::LZMA::Constants::NUM_DIST_SLOT_BITS, Algorithms::LZMA::Constants::NUM_FULL_DISTANCES, Algorithms::LZMA::Constants::NUM_LEN_HIGH_BITS, Algorithms::LZMA::Constants::NUM_LEN_LOW_BITS, Algorithms::LZMA::Constants::NUM_LEN_MID_BITS, Algorithms::LZMA::Constants::NUM_LEN_TO_POS_STATES, Algorithms::LZMA::Constants::NUM_LIT_CONTEXT_BITS_MAX, Algorithms::LZMA::Constants::NUM_LIT_POS_BITS_MAX, Algorithms::LZMA::Constants::NUM_POS_BITS_MAX, Algorithms::LZMA::Constants::NUM_STATES, Algorithms::LZMA::Constants::POS_STATES_MAX, Algorithms::LZMA::Constants::START_POS_MODEL_INDEX, Algorithms::LZMA::Constants::TOP
Instance Attribute Summary collapse
-
#code ⇒ Object
readonly
Returns the value of attribute code.
Instance Method Summary collapse
-
#decode_bit(model) ⇒ Integer
Decode a single bit using a probability model.
-
#decode_direct_bits(num_bits) ⇒ Integer
Decode bits directly without using probability model.
-
#decode_direct_bits_with_base(num_bits, base) ⇒ Integer
Decode bits directly with a base value.
-
#initialize(input_stream) ⇒ RangeDecoder
constructor
Initialize the range decoder.
-
#reset ⇒ void
Reset the decoder state (for LZMA2 chunks).
-
#update_stream(new_stream) ⇒ void
Update the input stream (for LZMA2 multi-chunk streams).
Constructor Details
#initialize(input_stream) ⇒ RangeDecoder
Initialize the range decoder
45 46 47 48 49 50 |
# File 'lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb', line 45 def initialize(input_stream) @stream = input_stream @range = 0xFFFFFFFF @code = 0 init_decoder end |
Instance Attribute Details
#code ⇒ Object (readonly)
Returns the value of attribute code.
40 41 42 |
# File 'lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb', line 40 def code @code end |
Instance Method Details
#decode_bit(model) ⇒ Integer
Decode a single bit using a probability model
Ported from 7-Zip SDK IF_BIT_0/UPDATE_0/UPDATE_1 macros (LzmaDec.c lines 22-26)
SDK pattern:
#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound)
#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb', line 64 def decode_bit(model) prob = model.probability # NORMALIZE (SDK pattern: normalize BEFORE decoding) normalize # Calculate bound bound = (@range >> 11) * prob if @code < bound # UPDATE_0: bit is 0 @range = bound & 0xFFFFFFFF new_prob = prob + ((BIT_MODEL_TOTAL - prob) >> MOVE_BITS) model.probability = new_prob 0 else # UPDATE_1: bit is 1 @range = (@range - bound) & 0xFFFFFFFF @code = (@code - bound) & 0xFFFFFFFF new_prob = prob - (prob >> MOVE_BITS) model.probability = new_prob 1 end end |
#decode_direct_bits(num_bits) ⇒ Integer
Decode bits directly without using probability model
93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb', line 93 def decode_direct_bits(num_bits) result = 0 num_bits.times do normalize @range >>= 1 @range &= 0xFFFFFFFF @code = (@code - @range) & 0xFFFFFFFF bit = (@code >> 31) & 1 @code = (@code + (@range & (0 - bit))) & 0xFFFFFFFF result = (result << 1) | bit end result end |
#decode_direct_bits_with_base(num_bits, base) ⇒ Integer
Decode bits directly with a base value
Used by distance decoder for slots 14+ where we need to build on a base value (2 or 3) iteratively.
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb', line 115 def decode_direct_bits_with_base(num_bits, base) result = base num_bits.times do result = (result << 1) + 1 normalize @range >>= 1 @range &= 0xFFFFFFFF # Check if bit is 1 bit = @code >= @range ? 1 : 0 if bit == 1 @code = (@code - @range) & 0xFFFFFFFF else result -= 1 end end result end |
#reset ⇒ void
This method returns an undefined value.
Reset the decoder state (for LZMA2 chunks)
146 147 148 149 150 151 |
# File 'lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb', line 146 def reset @range = 0xFFFFFFFF @code = 0 # Read initial 5 bytes for code 5.times { @code = ((@code << 8) | read_byte) & 0xFFFFFFFF } end |
#update_stream(new_stream) ⇒ void
This method returns an undefined value.
Update the input stream (for LZMA2 multi-chunk streams)
139 140 141 |
# File 'lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb', line 139 def update_stream(new_stream) @stream = new_stream end |