class PureRubyZip::ZipDecompressor
Public Instance Methods
bit_lengths_to_tree(bit_lengths)
click to toggle source
# File lib/pure_ruby_zip.rb, line 72 def bit_lengths_to_tree(bit_lengths) max_bits = bit_lengths.max bitlen_counts = (0..max_bits).map { |count| bit_lengths.count { |length| length == count && length != 0 } } next_code = [0, 0] (2..max_bits).each do |i| next_code[i] = ((next_code[i - 1] || 0) + bitlen_counts[i - 1]) << 1 end tree = {} bit_lengths.each.with_index do |length, index| if length != 0 tree[next_code[length].to_s(2).rjust(length, "0")] = index next_code[length] += 1 end end tree end
decode_dynamic_huffman_compressed_block(file_data, file_bitstream)
click to toggle source
# File lib/pure_ruby_zip.rb, line 101 def decode_dynamic_huffman_compressed_block(file_data, file_bitstream) hlit = file_bitstream.read_int(5) + 257 hdist = file_bitstream.read_int(5) + 1 hclen = file_bitstream.read_int(4) + 4 code_length_bit_lengths = [0] * 19 (0..(hclen - 1)).each { |len| code_length_bit_lengths[CODE_LENGTH_CODES_ORDER[len]] = file_bitstream.read_int(3) } code_length_tree = bit_lengths_to_tree(code_length_bit_lengths) bit_lengths = [] while bit_lengths.count < hlit + hdist sym = decode_symbol(code_length_tree, file_bitstream) if sym < 16 bit_lengths += [sym] elsif sym == 16 prev_byte = bit_lengths[-1] bit_lengths += [prev_byte] * (file_bitstream.read_int(2) + 3) elsif sym == 17 bit_lengths += [0] * (file_bitstream.read_int(3) + 3) elsif sym == 18 bit_lengths += [0] * (file_bitstream.read_int(7) + 11) end end litlen_tree = bit_lengths_to_tree(bit_lengths[0..(hlit - 1)]) dist_tree = bit_lengths_to_tree(bit_lengths[hlit..-1]) inflate_block_data(litlen_tree, dist_tree, file_data, file_bitstream) end
decode_fixed_huffman_compressed_block(file_data, file_bitstream)
click to toggle source
# File lib/pure_ruby_zip.rb, line 94 def decode_fixed_huffman_compressed_block(file_data, file_bitstream) litlen_bit_lengths = [8] * 144 + [9] * (256 - 144) + [7] * (280 - 256) + [8] * (286 - 280) litlen_tree = bit_lengths_to_tree(litlen_bit_lengths) dist_bit_lengths = [5] * 30 dist_tree = bit_lengths_to_tree(dist_bit_lengths) inflate_block_data(litlen_tree, dist_tree, file_data, file_bitstream) end
decode_symbol(tree, file_bitstream)
click to toggle source
# File lib/pure_ruby_zip.rb, line 39 def decode_symbol(tree, file_bitstream) bits = [] while true bit = file_bitstream.read_bit bits += [bit] key = bits.map { |x| x ? "1" : "0" }.join("") return tree[key] if tree[key] end end
decode_uncompressed_block(file_data, file_bitstream)
click to toggle source
# File lib/pure_ruby_zip.rb, line 88 def decode_uncompressed_block(file_data, file_bitstream) file_bitstream.read_int(5) length = file_bitstream.read_int(16) file_bitstream.read_int(16) (0..(length - 1)).map { |x| file_bitstream.read_int(8).chr }.join("") end
decode_zipped_file(file_bitstream)
click to toggle source
# File lib/pure_ruby_zip.rb, line 126 def decode_zipped_file(file_bitstream) file_data = "" is_last_block = false until is_last_block is_last_block = file_bitstream.read_bit block_type = file_bitstream.read_int(2) file_data += if block_type == 0 decode_uncompressed_block(file_data, file_bitstream) elsif block_type == 1 decode_fixed_huffman_compressed_block(file_data, file_bitstream) else decode_dynamic_huffman_compressed_block(file_data, file_bitstream) end end file_data end
inflate_block_data(litlen_tree, dist_tree, file_data, file_bitstream)
click to toggle source
# File lib/pure_ruby_zip.rb, line 48 def inflate_block_data(litlen_tree, dist_tree, file_data, file_bitstream) data = file_data loop do sym = decode_symbol(litlen_tree, file_bitstream) if sym < 256 data += sym.chr elsif sym == 256 return data else sym -= 257 length = file_bitstream.read_int(LENGTH_EXTRA_BITS[sym]) + LENGTH_BASE[sym] dist_sym = decode_symbol(dist_tree, file_bitstream) dist = file_bitstream.read_int(DISTANCE_EXTRA_BITS[dist_sym]) + DISTANCE_BASE[dist_sym] reference_data = [] (0..(length - 1)).each { char = data[-dist] data += char reference_data += [char] } x = reference_data[0..10].join("").codepoints.join(" ") end end data end