/// <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 ? State.Blocks : State.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 State.Done. /// </returns> /// <exception cref="InvalidDataException"> /// if deflated stream is invalid. /// </exception> bool Decode() { switch (mode) { case State.Header: return(DecodeHeader()); case State.Dictionary: return(DecodeDict()); case State.Checksum: return(DecodeChksum()); case State.Blocks: if (isLastBlock) { if (noHeader) { mode = State.Done; return(false); } else { input.SkipToByteBoundary(); neededBits = 32; mode = State.Checksum; return(true); } } var type = input.PeekBits(3); if (type < 0) { return(false); } input.DropBits(3); isLastBlock |= (type & 1) != 0; switch (type >> 1) { case DeflaterConstants.StoredBlock: input.SkipToByteBoundary(); mode = State.StoredLen1; break; case DeflaterConstants.StaticTree: litlenTree = InflaterHuffmanTree.DefLitLenTree; distTree = InflaterHuffmanTree.DefDistTree; mode = State.Huffman; break; case DeflaterConstants.DynamicTree: dynHeader = new InflaterDynHeader(); mode = State.DynamicHeader; break; default: throw new NotSupportedException("Unknown block type " + type); } return(true); case State.StoredLen1: { if ((uncomprLen = input.PeekBits(16)) < 0) { return(false); } input.DropBits(16); mode = State.StoredLen2; } goto case State.StoredLen2; // fall through case State.StoredLen2: { var nlen = input.PeekBits(16); if (nlen < 0) { return(false); } input.DropBits(16); if (nlen != (uncomprLen ^ 0xffff)) { throw new InvalidDataException("broken uncompressed block"); } mode = State.Stored; goto case State.Stored; // fall through } case State.Stored: { var more = outputWindow.CopyStored(input, uncomprLen); uncomprLen -= more; if (uncomprLen == 0) { mode = State.Blocks; return(true); } return(!input.IsNeedingInput); } case State.DynamicHeader: if (!dynHeader.Decode(input)) { return(false); } litlenTree = dynHeader.BuildLitLenTree(); distTree = dynHeader.BuildDistTree(); mode = State.Huffman; goto case State.Huffman; // fall through case State.Huffman: case State.HuffmanLenBits: case State.HuffmanDist: case State.HuffmanDistBits: return(DecodeHuffman()); case State.Done: return(false); default: throw new InvalidDataException("Inflater.Decode unknown mode"); } }