Class: Omnizip::Algorithms::Deflate64::Decoder
- Inherits:
-
Object
- Object
- Omnizip::Algorithms::Deflate64::Decoder
- Includes:
- Constants
- Defined in:
- lib/omnizip/algorithms/deflate64/decoder.rb
Overview
Deflate64 decoder
Constant Summary
Constants included from Constants
Constants::BLOCK_TYPE_DYNAMIC, Constants::BLOCK_TYPE_FIXED, Constants::BLOCK_TYPE_STORED, Constants::DICTIONARY_SIZE, Constants::DISTANCE_CODES, Constants::END_OF_BLOCK, Constants::GOOD_MATCH, Constants::HASH_SHIFT, Constants::HASH_SIZE, Constants::LENGTH_CODES, Constants::LITERAL_CODES, Constants::MAX_CHAIN_LENGTH, Constants::MAX_DISTANCE, Constants::MAX_DISTANCE_CODE_LENGTH, Constants::MAX_LAZY_MATCH, Constants::MAX_LITERAL_CODE_LENGTH, Constants::MAX_MATCH_LENGTH, Constants::MIN_MATCH_LENGTH, Constants::NICE_MATCH
Instance Attribute Summary collapse
-
#window_size ⇒ Object
readonly
Returns the value of attribute window_size.
Instance Method Summary collapse
-
#decode_block(data) ⇒ String
Decode single block.
-
#decompress(output_stream) ⇒ Object
Decompress input stream to output stream.
-
#deserialize_with_trees(data) ⇒ Array
Deserialize compressed data with Huffman trees.
-
#initialize(input_stream) ⇒ Decoder
constructor
A new instance of Decoder.
-
#parse_tree_from_json(json) ⇒ Hash
Parse Huffman tree from JSON with integer keys.
-
#reconstruct_from_tokens(tokens) ⇒ String
Reconstruct data from LZ77 tokens.
Constructor Details
#initialize(input_stream) ⇒ Decoder
Returns a new instance of Decoder.
14 15 16 17 18 19 |
# File 'lib/omnizip/algorithms/deflate64/decoder.rb', line 14 def initialize(input_stream) @input_stream = input_stream @window_size = DICTIONARY_SIZE @window = [] @huffman = HuffmanCoder.new end |
Instance Attribute Details
#window_size ⇒ Object (readonly)
Returns the value of attribute window_size.
12 13 14 |
# File 'lib/omnizip/algorithms/deflate64/decoder.rb', line 12 def window_size @window_size end |
Instance Method Details
#decode_block(data) ⇒ String
Decode single block
109 110 111 112 |
# File 'lib/omnizip/algorithms/deflate64/decoder.rb', line 109 def decode_block(data) tokens = @huffman.decode(data, {}, {}) reconstruct_from_tokens(tokens) end |
#decompress(output_stream) ⇒ Object
Decompress input stream to output stream
24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/omnizip/algorithms/deflate64/decoder.rb', line 24 def decompress(output_stream) compressed_data = @input_stream.read # Deserialize trees and compressed data literal_tree, distance_tree, data = deserialize_with_trees(compressed_data) # Decode Huffman-encoded data tokens = @huffman.decode(data, literal_tree, distance_tree) # Reconstruct data from LZ77 tokens decompressed = reconstruct_from_tokens(tokens) output_stream.write(decompressed) end |
#deserialize_with_trees(data) ⇒ Array
Deserialize compressed data with Huffman trees
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/omnizip/algorithms/deflate64/decoder.rb', line 43 def deserialize_with_trees(data) # Extract sizes (4 bytes each) literal_size, distance_size = data.unpack("NN") offset = 8 # Extract literal tree JSON literal_json = data[offset, literal_size] offset += literal_size # Extract distance tree JSON distance_json = data[offset, distance_size] offset += distance_size # Extract compressed data compressed = data[offset..] # Parse trees from JSON with symbol keys as integers literal_tree = parse_tree_from_json(literal_json) distance_tree = parse_tree_from_json(distance_json) [literal_tree, distance_tree, compressed] end |
#parse_tree_from_json(json) ⇒ Hash
Parse Huffman tree from JSON with integer keys
70 71 72 73 74 |
# File 'lib/omnizip/algorithms/deflate64/decoder.rb', line 70 def parse_tree_from_json(json) parsed = JSON.parse(json) # Convert string keys back to integers parsed.transform_keys(&:to_i) end |
#reconstruct_from_tokens(tokens) ⇒ String
Reconstruct data from LZ77 tokens
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/omnizip/algorithms/deflate64/decoder.rb', line 80 def reconstruct_from_tokens(tokens) output = [] tokens.each do |token| if token[:type] == :literal byte_char = token[:value].chr(Encoding::BINARY) output << byte_char @window << token[:value] elsif token[:type] == :match copy_from_window( output, token[:distance], token[:length], ) end # Maintain 64KB window while @window.size > @window_size @window.shift end end output.join.force_encoding(Encoding::BINARY) end |