/// <summary> /// Decodes the huffman encoded symbols in the input stream. /// </summary> /// <returns> /// false if more input is needed, true if output window is /// full or the current block ends. /// </returns> /// <exception cref="SharpZipBaseException"> /// if deflated stream is invalid. /// </exception> private bool DecodeHuffman() { int free = outputWindow.GetFreeSpace(); while (free >= 258) { int symbol; switch (mode) { case DECODE_HUFFMAN: /* This is the inner loop so it is optimized a bit */ while (((symbol = litlenTree.GetSymbol(input)) & ~0xff) == 0) { outputWindow.Write(symbol); if (--free < 258) { return true; } } if (symbol < 257) { if (symbol < 0) { return false; } else { /* symbol == 256: end of block */ distTree = null; litlenTree = null; mode = DECODE_BLOCKS; return true; } } try { repLength = CPLENS[symbol - 257]; neededBits = CPLEXT[symbol - 257]; } catch (Exception) { throw new SharpZipBaseException("Illegal rep length code"); } goto case DECODE_HUFFMAN_LENBITS; /* fall through */ case DECODE_HUFFMAN_LENBITS: if (neededBits > 0) { mode = DECODE_HUFFMAN_LENBITS; int i = input.PeekBits(neededBits); if (i < 0) { return false; } input.DropBits(neededBits); repLength += i; } mode = DECODE_HUFFMAN_DIST; goto case DECODE_HUFFMAN_DIST;/* fall through */ case DECODE_HUFFMAN_DIST: symbol = distTree.GetSymbol(input); if (symbol < 0) { return false; } try { repDist = CPDIST[symbol]; neededBits = CPDEXT[symbol]; } catch (Exception) { throw new SharpZipBaseException("Illegal rep dist code"); } goto case DECODE_HUFFMAN_DISTBITS;/* fall through */ case DECODE_HUFFMAN_DISTBITS: if (neededBits > 0) { mode = DECODE_HUFFMAN_DISTBITS; int i = input.PeekBits(neededBits); if (i < 0) { return false; } input.DropBits(neededBits); repDist += i; } outputWindow.Repeat(repLength, repDist); free -= repLength; mode = DECODE_HUFFMAN; break; default: throw new SharpZipBaseException("Inflater unknown mode"); } } return true; }
/// <summary> /// Decodes the deflated stream. /// </summary> /// <returns> /// false if more input is needed, or if finished. /// </returns> /// <exception cref="SharpZipBaseException"> /// if deflated stream is invalid. /// </exception> private bool Decode() { switch (mode) { case DECODE_HEADER: return DecodeHeader(); case DECODE_DICT: return DecodeDict(); case DECODE_CHKSUM: return DecodeChksum(); case DECODE_BLOCKS: if (isLastBlock) { if (noHeader) { mode = FINISHED; return false; } else { input.SkipToByteBoundary(); neededBits = 32; mode = DECODE_CHKSUM; return true; } } int type = input.PeekBits(3); if (type < 0) { return false; } input.DropBits(3); if ((type & 1) != 0) { isLastBlock = true; } switch (type >> 1){ case DeflaterConstants.STORED_BLOCK: input.SkipToByteBoundary(); mode = DECODE_STORED_LEN1; break; case DeflaterConstants.STATIC_TREES: litlenTree = InflaterHuffmanTree.defLitLenTree; distTree = InflaterHuffmanTree.defDistTree; mode = DECODE_HUFFMAN; break; case DeflaterConstants.DYN_TREES: dynHeader = new InflaterDynHeader(); mode = DECODE_DYN_HEADER; break; default: throw new SharpZipBaseException("Unknown block type " + type); } return true; case DECODE_STORED_LEN1: { if ((uncomprLen = input.PeekBits(16)) < 0) { return false; } input.DropBits(16); mode = DECODE_STORED_LEN2; } goto case DECODE_STORED_LEN2; /* fall through */ case DECODE_STORED_LEN2: { int nlen = input.PeekBits(16); if (nlen < 0) { return false; } input.DropBits(16); if (nlen != (uncomprLen ^ 0xffff)) { throw new SharpZipBaseException("broken uncompressed block"); } mode = DECODE_STORED; } goto case DECODE_STORED;/* fall through */ case DECODE_STORED: { int more = outputWindow.CopyStored(input, uncomprLen); uncomprLen -= more; if (uncomprLen == 0) { mode = DECODE_BLOCKS; return true; } return !input.IsNeedingInput; } case DECODE_DYN_HEADER: if (!dynHeader.Decode(input)) { return false; } litlenTree = dynHeader.BuildLitLenTree(); distTree = dynHeader.BuildDistTree(); mode = DECODE_HUFFMAN; goto case DECODE_HUFFMAN; /* fall through */ case DECODE_HUFFMAN: case DECODE_HUFFMAN_LENBITS: case DECODE_HUFFMAN_DIST: case DECODE_HUFFMAN_DISTBITS: return DecodeHuffman(); case FINISHED: return false; default: throw new SharpZipBaseException("Inflater.Decode unknown mode"); } }
static InflaterHuffmanTree() { try { byte[] codeLengths = new byte[288]; int i = 0; while (i < 144) { codeLengths[i++] = 8; } while (i < 256) { codeLengths[i++] = 9; } while (i < 280) { codeLengths[i++] = 7; } while (i < 288) { codeLengths[i++] = 8; } defLitLenTree = new InflaterHuffmanTree(codeLengths); codeLengths = new byte[32]; i = 0; while (i < 32) { codeLengths[i++] = 5; } defDistTree = new InflaterHuffmanTree(codeLengths); } catch (Exception) { throw new SharpZipBaseException("InflaterHuffmanTree: static tree length illegal"); } }
/// <summary> /// Resets the inflater so that a new stream can be decompressed. All /// pending input and output will be discarded. /// </summary> public void Reset() { mode = noHeader ? DECODE_BLOCKS : DECODE_HEADER; totalIn = totalOut = 0; input.Reset(); outputWindow.Reset(); dynHeader = null; litlenTree = null; distTree = null; isLastBlock = false; adler.Reset(); }
public bool Decode(StreamManipulator input) { decode_loop: for (;;) { switch (mode) { case LNUM: lnum = input.PeekBits(5); if (lnum < 0) { return false; } lnum += 257; input.DropBits(5); // System.err.println("LNUM: "+lnum); mode = DNUM; goto case DNUM; // fall through case DNUM: dnum = input.PeekBits(5); if (dnum < 0) { return false; } dnum++; input.DropBits(5); // System.err.println("DNUM: "+dnum); num = lnum+dnum; litdistLens = new byte[num]; mode = BLNUM; goto case BLNUM; // fall through case BLNUM: blnum = input.PeekBits(4); if (blnum < 0) { return false; } blnum += 4; input.DropBits(4); blLens = new byte[19]; ptr = 0; // System.err.println("BLNUM: "+blnum); mode = BLLENS; goto case BLLENS; // fall through case BLLENS: while (ptr < blnum) { int len = input.PeekBits(3); if (len < 0) { return false; } input.DropBits(3); // System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len); blLens[BL_ORDER[ptr]] = (byte) len; ptr++; } blTree = new InflaterHuffmanTree(blLens); blLens = null; ptr = 0; mode = LENS; goto case LENS; // fall through case LENS: { int symbol; while (((symbol = blTree.GetSymbol(input)) & ~15) == 0) { /* Normal case: symbol in [0..15] */ // System.err.println("litdistLens["+ptr+"]: "+symbol); litdistLens[ptr++] = lastLen = (byte)symbol; if (ptr == num) { /* Finished */ return true; } } /* need more input ? */ if (symbol < 0) { return false; } /* otherwise repeat code */ if (symbol >= 17) { /* repeat zero */ // System.err.println("repeating zero"); lastLen = 0; } else { if (ptr == 0) { throw new SharpZipBaseException(); } } repSymbol = symbol-16; } mode = REPS; goto case REPS; // fall through case REPS: { int bits = repBits[repSymbol]; int count = input.PeekBits(bits); if (count < 0) { return false; } input.DropBits(bits); count += repMin[repSymbol]; // System.err.println("litdistLens repeated: "+count); if (ptr + count > num) { throw new SharpZipBaseException(); } while (count-- > 0) { litdistLens[ptr++] = lastLen; } if (ptr == num) { /* Finished */ return true; } } mode = LENS; goto decode_loop; } } }