public int CopyStored(StreamManipulator input, int len) { len = Math.Min(Math.Min(len, WINDOW_SIZE - window_filled), input.AvailableBytes); int copied; int tailLen = WINDOW_SIZE - window_end; if (len > tailLen) { copied = input.CopyBytes(window, window_end, tailLen); if (copied == tailLen) { copied += input.CopyBytes(window, 0, len - tailLen); } } else { copied = input.CopyBytes(window, window_end, len); } window_end = (window_end + copied) & WINDOW_MASK; window_filled += copied; return copied; }
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> /// Reads the next symbol from input. The symbol is encoded using the /// huffman tree. /// </summary> /// <param name="input"> /// input the input source. /// </param> /// <returns> /// the next symbol, or -1 if not enough input is available. /// </returns> public int GetSymbol(StreamManipulator input) { int lookahead, symbol; if ((lookahead = input.PeekBits(9)) >= 0) { if ((symbol = tree[lookahead]) >= 0) { input.DropBits(symbol & 15); return symbol >> 4; } int subtree = -(symbol >> 4); int bitlen = symbol & 15; if ((lookahead = input.PeekBits(bitlen)) >= 0) { symbol = tree[subtree | (lookahead >> 9)]; input.DropBits(symbol & 15); return symbol >> 4; } else { int bits = input.AvailableBits; lookahead = input.PeekBits(bits); symbol = tree[subtree | (lookahead >> 9)]; if ((symbol & 15) <= bits) { input.DropBits(symbol & 15); return symbol >> 4; } else { return -1; } } } else { int bits = input.AvailableBits; lookahead = input.PeekBits(bits); symbol = tree[lookahead]; if (symbol >= 0 && (symbol & 15) <= bits) { input.DropBits(symbol & 15); return symbol >> 4; } else { return -1; } } }
/// <summary> /// Creates a new inflater. /// </summary> /// <param name="nowrap"> /// true if no header and checksum field appears in the /// stream. This is used for GZIPed input. For compatibility with /// Sun JDK you should provide one byte of input more than needed in /// this case. /// </param> public Inflater(bool nowrap) { this.nowrap = nowrap; this.adler = new Adler32(); input = new StreamManipulator(); outputWindow = new OutputWindow(); mode = nowrap ? DECODE_BLOCKS : DECODE_HEADER; }