/// <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 = 0; totalOut = 0; input.Reset(); outputWindow.Reset(); dynHeader = null; litlenTree = null; distTree = null; isLastBlock = false; adler.Reset(); }
/// <summary> /// Decodes the deflated stream. /// </summary> /// <returns> /// false if more input is needed, or if finished. /// </returns> /// <exception cref="BlubbZipBaseException"> /// 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 BlubbZipBaseException( "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 BlubbZipBaseException( "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 BlubbZipBaseException( "Inflater.Decode unknown mode" ); } }
/// <summary> /// Decodes the deflated stream. /// </summary> /// <returns> /// false if more input is needed, or if finished. /// </returns> /// <exception cref="BlubbZipBaseException"> /// 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 BlubbZipBaseException("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 BlubbZipBaseException("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 BlubbZipBaseException("Inflater.Decode unknown mode"); } }