Class: LZW::Decompressor

Inherits:
Object
  • Object
show all
Includes:
Constants
Defined in:
lib/lzw/decompressor.rb

Overview

Scaling LZW decompressor

Constant Summary

Constants included from Constants

Constants::BL_INIT_CODE, Constants::CHECKPOINT_BITS, Constants::INIT_CODE_SIZE, Constants::MAGIC, Constants::MASK_BITS, Constants::MASK_BLOCK, Constants::NR_INIT_CODE, Constants::RESET_CODE

Instance Method Summary collapse

Instance Method Details

#decompress(data) ⇒ String

Given a String(ish) of LZW-compressed data, return the decompressed data as a String left in “ASCII-8BIT” encoding.

Parameters:

  • data (String)

    Compressed input data

Returns:

  • (String)

Raises:



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/lzw/decompressor.rb', line 11

def decompress(data)
  reset

  @data = LZW::BitBuf.new(field: data)
  @data_pos = 0

  read_magic(@data)
  @data_pos = 24

  # we've read @block_mode from the header now, so make sure our init_code
  # is set properly
  str_reset

  next_increase = 2**@code_size

  seen = read_code
  @buf << @str_table[seen]

  while (code = read_code)

    if @block_mode && code == RESET_CODE
      str_reset

      seen = read_code
      # warn "reset at #{data_pos} initial code #{@str_table[seen]}"
      next
    end

    if (word = @str_table.fetch(code, nil))
      @buf << word

      @str_table[@next_code] = @str_table[seen] + word[0, 1]

    elsif code == @next_code
      word = @str_table[seen]
      @str_table[code] = word + word[0, 1]

      @buf << @str_table[code]

    else
      raise LZW::InputStreamError, "(#{code} != #{@next_code}) input may be corrupt at bit #{data_pos - @code_size}"
    end

    seen = code
    @next_code += 1

    if @next_code >= next_increase
      if @code_size < @max_code_size
        @code_size += 1
        next_increase *= 2
        # warn "decode up to #{@code_size} for next #{@next_code} max #{@max_code_size} at #{data_pos}"
      end
    end

  end

  @buf
end

#reset

Reset the state of the decompressor. This is run at the beginning of #decompress, so it’s not necessary for reuse of an instance, but this allows wiping the string code table and buffer from the object instance.



73
74
75
76
# File 'lib/lzw/decompressor.rb', line 73

def reset
  @buf = "".b
  @str_table = []
end