/// <summary> /// Decodes a zlib/RFC1950 header. /// </summary> /// <returns> /// False if more input is needed. /// </returns> /// <exception cref="SharpZipBaseException"> /// The header is invalid. /// </exception> private bool DecodeHeader() { int header = input.PeekBits(16); if (header < 0) { return(false); } input.DropBits(16); /* The header is written in "wrong" byte order */ header = ((header << 8) | (header >> 8)) & 0xffff; if (header % 31 != 0) { throw new SharpZipBaseException("Header checksum illegal"); } if ((header & 0x0f00) != (Deflater.DEFLATED << 8)) { throw new SharpZipBaseException("Compression Method unknown"); } /* Maximum size of the backwards window in bits. * We currently ignore this, but we could use it to make the * inflater window more space efficient. On the other hand the * full window (15 bits) is needed most times, anyway. * int max_wbits = ((header & 0x7000) >> 12) + 8; */ if ((header & 0x0020) == 0) // Dictionary flag? { mode = DECODE_BLOCKS; } else { mode = DECODE_DICT; neededBits = 32; } return(true); }
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; } } }
/// <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; } } }
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; } } }