Squeak Class Documentation category index | class index  
 
InflateStream
  category: System-Compression
  superclass: ReadStream
  subclasses: FastInflateStream

This class implements the Inflate decompression algorithm as defined by RFC1951 and used in PKZip, GZip and ZLib (and many, many more). It is a variant of the LZ77 compression algorithm described in

[LZ77] Ziv J., Lempel A., "A Universal Algorithm for Sequential Data Compression", IEEE Transactions on Information Theory", Vol. 23, No. 3, pp. 337-343.

[RFC1951] Deutsch. P, "DEFLATE Compressed Data Format Specification version 1.3"

For more information see the above mentioned RFC 1951 which can for instance be found at

http://www.leo.org/pub/comp/doc/standards/rfc/index.html

Huffman Tree Implementation Notes:
===========================================
The huffman tree used for decoding literal, distance and length codes in the inflate algorithm has been encoded in a single Array. The tree is made up of subsequent tables storing all entries at the current bit depth. Each entry in the table (e.g., a 32bit Integer value) is either a leaf or a non-leaf node. Leaf nodes store the immediate value in its low 16 bits whereas non-leaf nodes store the offset of the subtable in its low 16bits. The high 8 bits of non-leaf nodes contain the number of additional bits needed for the sub table (the high 8 bits of leaf-nodes are always zero). The first entry in each table is always a non-leaf node indicating how many bits we need to fetch initially. We can thus travel down the tree as follows (written in sort-of-pseudocode the actual implementation can be seen in InflateStream>>decodeValueFrom:):

table _ initialTable.
bitsNeeded _ high 8 bits of (table at: 1). "Determine initial bits"
table _ initialTable + (low 16 bits of (table at: 1)). "Determine start of first real table"
[bits _ fetch next bitsNeeded bits. "Grab the bits"
value _ table at: bits. "Lookup the value"
value has high 8 bit set] whileTrue:[ "Check if it's leaf"
table _ initialTable + (low 16 bits of value). "No - compute new sub table start"
bitsNeeded _ high 8 bit of value]. "Compute additional number of bits needed"
^value

instance methods
  accessing
  close
contents
next
next:
next:into:startingAt:
size
sourceLimit
sourcePosition
sourceStream
upTo:
upToEnd

  bit access
  bitPosition
nextBits:
nextByte
nextSingleBits:

  huffman trees
  computeHuffmanValues:counts:from:to:
createHuffmanTables:counts:from:to:
decodeDynamicTable:from:
distanceMap
growHuffmanTable:
huffmanTableFrom:mappedBy:
increment:bits:
literalLengthMap
mapValues:by:

  inflating
  decodeValueFrom:
decompressBlock:with:
proceedDynamicBlock
proceedFixedBlock
proceedStoredBlock
processDynamicBlock
processFixedBlock
processStoredBlock

  initialize
  on:
on:from:to:
reset

  private
  decompressAll
getFirstBuffer
getNextBlock
moveContentsToFront
moveSourceToFront
pastEndRead
profile

  testing
  atEnd

class methods
  class initialization
  initialize

instance methods
  accessing top  
 

close


 

contents

Answer with a copy of my collection from 1 to readLimit.


 

next

Answer the next decompressed object in the Stream represented by the
receiver.


 

next:

Answer the next anInteger elements of my collection. overriden for simplicity


 

next:into:startingAt:

Read n objects into the given collection.
Return aCollection or a partial copy if less than
n elements have been read.


 

size

This is a compressed stream - we don't know the size beforehand


 

sourceLimit


 

sourcePosition


 

sourceStream


 

upTo:

Answer a subcollection from the current access position to the
occurrence (if any, but not inclusive) of anObject in the receiver. If
anObject is not in the collection, answer the entire rest of the receiver.


 

upToEnd

Answer a subcollection from the current access position through the last element of the receiver.


  bit access top  
 

bitPosition

Return the current bit position of the source


 

nextBits:


 

nextByte


 

nextSingleBits:


  huffman trees top  
 

computeHuffmanValues:counts:from:to:

Assign numerical values to all codes.
Note: The values are stored according to the bit length


 

createHuffmanTables:counts:from:to:

Create the actual tables


 

decodeDynamicTable:from:

Decode the code length of the literal/length and distance table
in a block compressed with dynamic huffman trees


 

distanceMap

This is used by the fast decompressor


 

growHuffmanTable:


 

huffmanTableFrom:mappedBy:

Create a new huffman table from the given code lengths.
Map the actual values by valueMap if it is given.
See the class comment for a documentation of the huffman
tables used in this decompressor.


 

increment:bits:

Increment a value of nBits length.
The fast decompressor will do this differently


 

literalLengthMap

This is used by the fast decompressor


 

mapValues:by:


  inflating top  
 

decodeValueFrom:

Decode the next value in the receiver using the given huffman table.


 

decompressBlock:with:

Process the compressed data in the block.
llTable is the huffman table for literal/length codes
and dTable is the huffman table for distance codes.


 

proceedDynamicBlock


 

proceedFixedBlock


 

proceedStoredBlock

Proceed decompressing a stored (e.g., uncompressed) block


 

processDynamicBlock


 

processFixedBlock


 

processStoredBlock

Skip to byte boundary


  initialize top  
 

on:


 

on:from:to:


 

reset

Position zero - nothing decoded yet


  private top  
 

decompressAll

Profile the decompression speed


 

getFirstBuffer

Get the first source buffer after initialization has been done


 

getNextBlock


 

moveContentsToFront

Move the decoded contents of the receiver to the front so that we have enough space for decoding more data.


 

moveSourceToFront

Move the encoded contents of the receiver to the front so that we have enough space for decoding more data.


 

pastEndRead

A client has attempted to read beyond the read limit.
Check in what state we currently are and perform
the appropriate action


 

profile

Profile the decompression speed


  testing top  
 

atEnd

Note: It is possible that we have a few bits left,
representing just the EOB marker. To check for
this we must force decompression of the next
block if at end of data.


class methods
  class initialization top  
 

initialize

InflateStream initialize