Class: Cabriolet::Decompressors::LZX
- Defined in:
- lib/cabriolet/decompressors/lzx.rb
Overview
LZX handles LZX compressed data Based on libmspack lzxd.c implementation
The LZX method was created by Jonathan Forbes and Tomi Poutanen, adapted by Microsoft Corporation.
Constant Summary collapse
- FRAME_SIZE =
Frame size (32KB per frame)
32_768- BLOCKTYPE_INVALID =
Block types
0- BLOCKTYPE_VERBATIM =
1- BLOCKTYPE_ALIGNED =
2- BLOCKTYPE_UNCOMPRESSED =
3- MIN_MATCH =
Match constants
2- MAX_MATCH =
257- NUM_CHARS =
256- PRETREE_NUM_ELEMENTS =
Tree constants
20- PRETREE_MAXSYMBOLS =
20- PRETREE_TABLEBITS =
6- ALIGNED_NUM_ELEMENTS =
8- ALIGNED_MAXSYMBOLS =
8- ALIGNED_TABLEBITS =
7- NUM_PRIMARY_LENGTHS =
7- NUM_SECONDARY_LENGTHS =
249- LENGTH_MAXSYMBOLS =
250- LENGTH_TABLEBITS =
12- POSITION_SLOTS =
Position slots for different window sizes
[30, 32, 34, 36, 38, 42, 50, 66, 98, 162, 290].freeze
- EXTRA_BITS =
Extra bits for position slots
[ 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, 14, 14, 15, 15, 16, 16 ].freeze
- POSITION_BASE =
Position base offsets
[ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12_288, 16_384, 24_576, 32_768, 49_152, 65_536, 98_304, 131_072, 196_608, 262_144, 393_216, 524_288, 655_360, 786_432, 917_504, 1_048_576, 1_179_648, 1_310_720, 1_441_792, 1_572_864, 1_703_936, 1_835_008, 1_966_080, 2_097_152, 2_228_224, 2_359_296, 2_490_368, 2_621_440, 2_752_512, 2_883_584, 3_014_656, 3_145_728, 3_276_800, 3_407_872, 3_538_944, 3_670_016, 3_801_088, 3_932_160, 4_063_232, 4_194_304, 4_325_376, 4_456_448, 4_587_520, 4_718_592, 4_849_664, 4_980_736, 5_111_808, 5_242_880, 5_373_952, 5_505_024, 5_636_096, 5_767_168, 5_898_240, 6_029_312, 6_160_384, 6_291_456, 6_422_528, 6_553_600, 6_684_672, 6_815_744, 6_946_816, 7_077_888, 7_208_960, 7_340_032, 7_471_104, 7_602_176, 7_733_248, 7_864_320, 7_995_392, 8_126_464, 8_257_536, 8_388_608, 8_519_680, 8_650_752, 8_781_824, 8_912_896, 9_043_968, 9_175_040, 9_306_112, 9_437_184, 9_568_256, 9_699_328, 9_830_400, 9_961_472, 10_092_544, 10_223_616, 10_354_688, 10_485_760, 10_616_832, 10_747_904, 10_878_976, 11_010_048, 11_141_120, 11_272_192, 11_403_264, 11_534_336, 11_665_408, 11_796_480, 11_927_552, 12_058_624, 12_189_696, 12_320_768, 12_451_840, 12_582_912, 12_713_984, 12_845_056, 12_976_128, 13_107_200, 13_238_272, 13_369_344, 13_500_416, 13_631_488, 13_762_560, 13_893_632, 14_024_704, 14_155_776, 14_286_848, 14_417_920, 14_548_992, 14_680_064, 14_811_136, 14_942_208, 15_073_280, 15_204_352, 15_335_424, 15_466_496, 15_597_568, 15_728_640, 15_859_712, 15_990_784, 16_121_856, 16_252_928, 16_384_000, 16_515_072, 16_646_144, 16_777_216, 16_908_288, 17_039_360, 17_170_432, 17_301_504, 17_432_576, 17_563_648, 17_694_720, 17_825_792, 17_956_864, 18_087_936, 18_219_008, 18_350_080, 18_481_152, 18_612_224, 18_743_296, 18_874_368, 19_005_440, 19_136_512, 19_267_584, 19_398_656, 19_529_728, 19_660_800, 19_791_872, 19_922_944, 20_054_016, 20_185_088, 20_316_160, 20_447_232, 20_578_304, 20_709_376, 20_840_448, 20_971_520, 21_102_592, 21_233_664, 21_364_736, 21_495_808, 21_626_880, 21_757_952, 21_889_024, 22_020_096, 22_151_168, 22_282_240, 22_413_312, 22_544_384, 22_675_456, 22_806_528, 22_937_600, 23_068_672, 23_199_744, 23_330_816, 23_461_888, 23_592_960, 23_724_032, 23_855_104, 23_986_176, 24_117_248, 24_248_320, 24_379_392, 24_510_464, 24_641_536, 24_772_608, 24_903_680, 25_034_752, 25_165_824, 25_296_896, 25_427_968, 25_559_040, 25_690_112, 25_821_184, 25_952_256, 26_083_328, 26_214_400, 26_345_472, 26_476_544, 26_607_616, 26_738_688, 26_869_760, 27_000_832, 27_131_904, 27_262_976, 27_394_048, 27_525_120, 27_656_192, 27_787_264, 27_918_336, 28_049_408, 28_180_480, 28_311_552, 28_442_624, 28_573_696, 28_704_768, 28_835_840, 28_966_912, 29_097_984, 29_229_056, 29_360_128, 29_491_200, 29_622_272, 29_753_344, 29_884_416, 30_015_488, 30_146_560, 30_277_632, 30_408_704, 30_539_776, 30_670_848, 30_801_920, 30_932_992, 31_064_064, 31_195_136, 31_326_208, 31_457_280, 31_588_352, 31_719_424, 31_850_496, 31_981_568, 32_112_640, 32_243_712, 32_374_784, 32_505_856, 32_636_928, 32_768_000, 32_899_072, 33_030_144, 33_161_216, 33_292_288, 33_423_360 ].freeze
Instance Attribute Summary collapse
-
#is_delta ⇒ Object
readonly
Returns the value of attribute is_delta.
-
#output_length ⇒ Object
readonly
Returns the value of attribute output_length.
-
#reset_interval ⇒ Object
readonly
Returns the value of attribute reset_interval.
-
#window_bits ⇒ Object
readonly
Returns the value of attribute window_bits.
Attributes inherited from Base
#buffer_size, #input, #io_system, #output
Instance Method Summary collapse
-
#decompress(bytes) ⇒ Integer
Decompress LZX data.
-
#initialize(io_system, input, output, buffer_size, window_bits:, reset_interval: 0, output_length: 0, is_delta: false) ⇒ LZX
constructor
Initialize LZX decompressor.
-
#set_output_length(length) ⇒ void
Set output length (for Intel E8 processing).
Methods inherited from Base
Constructor Details
#initialize(io_system, input, output, buffer_size, window_bits:, reset_interval: 0, output_length: 0, is_delta: false) ⇒ LZX
Initialize LZX decompressor
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 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/cabriolet/decompressors/lzx.rb', line 102 def initialize(io_system, input, output, buffer_size, window_bits:, reset_interval: 0, output_length: 0, is_delta: false) super(io_system, input, output, buffer_size) # Validate window_bits if is_delta unless (17..25).cover?(window_bits) raise ArgumentError, "LZX DELTA window_bits must be 17-25, got #{window_bits}" end elsif !(15..21).cover?(window_bits) raise ArgumentError, "LZX window_bits must be 15-21, got #{window_bits}" end @window_bits = window_bits @window_size = 1 << window_bits @reset_interval = reset_interval @output_length = output_length @is_delta = is_delta # Calculate number of position slots @num_offsets = POSITION_SLOTS[window_bits - 15] << 3 @maintree_maxsymbols = NUM_CHARS + @num_offsets # Initialize window @window = "\0" * @window_size @window_posn = 0 @frame_posn = 0 @frame = 0 # Initialize R0, R1, R2 (LRU offset registers) @r0 = 1 @r1 = 1 @r2 = 1 # Initialize block state @block_type = BLOCKTYPE_INVALID @block_length = 0 @block_remaining = 0 @header_read = false # Intel E8 transformation state @intel_filesize = 0 @intel_started = false @e8_buf = "\0" * FRAME_SIZE # Initialize bitstream @bitstream = Binary::Bitstream.new(io_system, input, buffer_size) # Initialize Huffman trees initialize_trees # Output tracking @offset = 0 @output_ptr = 0 @output_end = 0 end |
Instance Attribute Details
#is_delta ⇒ Object (readonly)
Returns the value of attribute is_delta.
90 91 92 |
# File 'lib/cabriolet/decompressors/lzx.rb', line 90 def is_delta @is_delta end |
#output_length ⇒ Object (readonly)
Returns the value of attribute output_length.
90 91 92 |
# File 'lib/cabriolet/decompressors/lzx.rb', line 90 def output_length @output_length end |
#reset_interval ⇒ Object (readonly)
Returns the value of attribute reset_interval.
90 91 92 |
# File 'lib/cabriolet/decompressors/lzx.rb', line 90 def reset_interval @reset_interval end |
#window_bits ⇒ Object (readonly)
Returns the value of attribute window_bits.
90 91 92 |
# File 'lib/cabriolet/decompressors/lzx.rb', line 90 def window_bits @window_bits end |
Instance Method Details
#decompress(bytes) ⇒ Integer
Decompress LZX data
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/cabriolet/decompressors/lzx.rb', line 173 def decompress(bytes) return 0 if bytes <= 0 total_written = 0 end_frame = ((@offset + bytes) / FRAME_SIZE) + 1 while @frame < end_frame # Check reset interval reset_state if @reset_interval.positive? && (@frame % @reset_interval).zero? # Read DELTA chunk size if needed @bitstream.read_bits(16) if @is_delta # Read Intel filesize header if needed read_intel_header unless @header_read # Calculate frame size frame_size = calculate_frame_size # Decode blocks until frame is complete decode_frame(frame_size) # Apply Intel E8 transformation if needed frame_data = if should_apply_e8_transform?(frame_size) apply_e8_transform(frame_size) else @window[@frame_posn, frame_size] end # Write frame write_amount = [bytes - total_written, frame_size].min io_system.write(output, frame_data[0, write_amount]) total_written += write_amount @offset += frame_size # Advance frame @frame += 1 @frame_posn += frame_size @frame_posn = 0 if @frame_posn == @window_size @window_posn = 0 if @window_posn == @window_size # Re-align bitstream (byte_align is safe to call even if already aligned) @bitstream.byte_align end total_written end |
#set_output_length(length) ⇒ void
This method returns an undefined value.
Set output length (for Intel E8 processing)
165 166 167 |
# File 'lib/cabriolet/decompressors/lzx.rb', line 165 def set_output_length(length) @output_length = length if length.positive? end |