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 ApplicationException("InflaterHuffmanTree: static tree length illegal"); } }
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); litlenLens = new byte[lnum]; // 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); distLens = new byte[dnum]; // System.err.println("DNUM: "+dnum); 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 = LLENS; goto case LLENS;/* fall through */ case LLENS: while (ptr < lnum) { int symbol = blTree.GetSymbol(input); if (symbol < 0) { return false; } switch (symbol) { default: // System.err.println("litlenLens["+ptr+"]: "+symbol); litlenLens[ptr++] = (byte) symbol; break; case 16: /* repeat last len 3-6 times */ if (ptr == 0) { throw new Exception("Repeating, but no prev len"); } // System.err.println("litlenLens["+ptr+"]: repeat"); repeatedLen = litlenLens[ptr-1]; repBits = 2; for (int i = 3; i-- > 0; ) { if (ptr >= lnum) { throw new Exception(); } litlenLens[ptr++] = repeatedLen; } mode = LREPS; goto decode_loop; case 17: /* repeat zero 3-10 times */ // System.err.println("litlenLens["+ptr+"]: zero repeat"); repeatedLen = 0; repBits = 3; for (int i = 3; i-- > 0; ) { if (ptr >= lnum) { throw new Exception(); } litlenLens[ptr++] = repeatedLen; } mode = LREPS; goto decode_loop; case 18: /* repeat zero 11-138 times */ // System.err.println("litlenLens["+ptr+"]: zero repeat"); repeatedLen = 0; repBits = 7; for (int i = 11; i-- > 0; ) { if (ptr >= lnum) { throw new Exception(); } litlenLens[ptr++] = repeatedLen; } mode = LREPS; goto decode_loop; } } ptr = 0; mode = DLENS; goto case DLENS;/* fall through */ case DLENS: while (ptr < dnum) { int symbol = blTree.GetSymbol(input); if (symbol < 0) { return false; } switch (symbol) { default: distLens[ptr++] = (byte) symbol; // System.err.println("distLens["+ptr+"]: "+symbol); break; case 16: /* repeat last len 3-6 times */ if (ptr == 0) { throw new Exception("Repeating, but no prev len"); } // System.err.println("distLens["+ptr+"]: repeat"); repeatedLen = distLens[ptr-1]; repBits = 2; for (int i = 3; i-- > 0; ) { if (ptr >= dnum) { throw new Exception(); } distLens[ptr++] = repeatedLen; } mode = DREPS; goto decode_loop; case 17: /* repeat zero 3-10 times */ // System.err.println("distLens["+ptr+"]: repeat zero"); repeatedLen = 0; repBits = 3; for (int i = 3; i-- > 0; ) { if (ptr >= dnum) { throw new Exception(); } distLens[ptr++] = repeatedLen; } mode = DREPS; goto decode_loop; case 18: /* repeat zero 11-138 times */ // System.err.println("distLens["+ptr+"]: repeat zero"); repeatedLen = 0; repBits = 7; for (int i = 11; i-- > 0; ) { if (ptr >= dnum) { throw new Exception(); } distLens[ptr++] = repeatedLen; } mode = DREPS; goto decode_loop; } } mode = FINISH; return true; case LREPS: { int count = input.PeekBits(repBits); if (count < 0) { return false; } input.DropBits(repBits); // System.err.println("litlenLens repeat: "+repBits); while (count-- > 0) { if (ptr >= lnum) { throw new Exception(); } litlenLens[ptr++] = repeatedLen; } } mode = LLENS; goto decode_loop; case DREPS: { int count = input.PeekBits(repBits); if (count < 0) { return false; } input.DropBits(repBits); while (count-- > 0) { if (ptr >= dnum) { throw new Exception(); } distLens[ptr++] = repeatedLen; } } mode = DLENS; goto decode_loop; } } }
/// <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="System.FormatException"> /// 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 FormatException("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 FormatException("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 FormatException(); } } return true; }
/// <summary> /// Decodes the deflated stream. /// </summary> /// <returns> /// false if more input is needed, or if finished. /// </returns> /// <exception cref="System.FormatException"> /// DataFormatException, 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 (nowrap) { 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 FormatException("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 FormatException("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 FormatException(); } }
/// <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 = nowrap ? DECODE_BLOCKS : DECODE_HEADER; totalIn = totalOut = 0; input.Reset(); outputWindow.Reset(); dynHeader = null; litlenTree = null; distTree = null; isLastBlock = false; adler.Reset(); }