📄 inflater.cs
字号:
/// <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> /// Sets the preset dictionary. This should only be called, if /// needsDictionary() returns true and it should set the same /// dictionary, that was used for deflating. The getAdler() /// function returns the checksum of the dictionary needed. /// </summary> /// <param name="buffer"> /// the dictionary. /// </param> /// <exception cref="System.InvalidOperationException"> /// if no dictionary is needed. /// </exception> /// <exception cref="System.ArgumentException"> /// if the dictionary checksum is wrong. /// </exception> public void SetDictionary(byte[] buffer) { SetDictionary(buffer, 0, buffer.Length); } /// <summary> /// Sets the preset dictionary. This should only be called, if /// needsDictionary() returns true and it should set the same /// dictionary, that was used for deflating. The getAdler() /// function returns the checksum of the dictionary needed. /// </summary> /// <param name="buffer"> /// the dictionary. /// </param> /// <param name="off"> /// the offset into buffer where the dictionary starts. /// </param> /// <param name="len"> /// the length of the dictionary. /// </param> /// <exception cref="System.InvalidOperationException"> /// if no dictionary is needed. /// </exception> /// <exception cref="System.ArgumentException"> /// if the dictionary checksum is wrong. /// </exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// if the off and/or len are wrong. /// </exception> public void SetDictionary(byte[] buffer, int off, int len) { if (!IsNeedingDictionary) { throw new InvalidOperationException(); } adler.Update(buffer, off, len); if ((int) adler.Value != readAdler) { throw new ArgumentException("Wrong adler checksum"); } adler.Reset(); outputWindow.CopyDict(buffer, off, len); mode = DECODE_BLOCKS; } /// <summary> /// Sets the input. This should only be called, if needsInput() /// returns true. /// </summary> /// <param name="buf"> /// the input. /// </param> /// <exception cref="System.InvalidOperationException"> /// if no input is needed. /// </exception> public void SetInput(byte[] buf) { SetInput(buf, 0, buf.Length); } /// <summary> /// Sets the input. This should only be called, if needsInput() /// returns true. /// </summary> /// <param name="buf"> /// the input. /// </param> /// <param name="off"> /// the offset into buffer where the input starts. /// </param> /// <param name="len"> /// the length of the input. /// </param> /// <exception cref="System.InvalidOperationException"> /// if no input is needed. /// </exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// if the off and/or len are wrong. /// </exception> public void SetInput(byte[] buf, int off, int len) { input.SetInput(buf, off, len); totalIn += len; } /// <summary> /// Inflates the compressed stream to the output buffer. If this /// returns 0, you should check, whether needsDictionary(), /// needsInput() or finished() returns true, to determine why no /// further output is produced. /// </summary> /// <param name = "buf"> /// the output buffer. /// </param> /// <returns> /// the number of bytes written to the buffer, 0 if no further /// output can be produced. /// </returns> /// <exception cref="System.ArgumentOutOfRangeException"> /// if buf has length 0. /// </exception> /// <exception cref="System.FormatException"> /// if deflated stream is invalid. /// </exception> public int Inflate(byte[] buf) { return Inflate(buf, 0, buf.Length); } /// <summary> /// Inflates the compressed stream to the output buffer. If this /// returns 0, you should check, whether needsDictionary(), /// needsInput() or finished() returns true, to determine why no /// further output is produced. /// </summary> /// <param name = "buf"> /// the output buffer. /// </param> /// <param name = "off"> /// the offset into buffer where the output should start. /// </param> /// <param name = "len"> /// the maximum length of the output. /// </param> /// <returns> /// the number of bytes written to the buffer, 0 if no further output can be produced. /// </returns> /// <exception cref="System.ArgumentOutOfRangeException"> /// if len is <= 0. /// </exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// if the off and/or len are wrong. /// </exception> /// <exception cref="System.FormatException"> /// if deflated stream is invalid. /// </exception> public int Inflate(byte[] buf, int off, int len) { if (len < 0) { throw new ArgumentOutOfRangeException("len < 0"); } // Special case: len may be zero if (len == 0) { return 0; } /* // Check for correct buff, off, len triple if (off < 0 || off + len >= buf.Length) { throw new ArgumentException("off/len outside buf bounds"); }*/ int count = 0; int more; do { if (mode != DECODE_CHKSUM) { /* Don't give away any output, if we are waiting for the * checksum in the input stream. * * With this trick we have always: * needsInput() and not finished() * implies more output can be produced. */ more = outputWindow.CopyOutput(buf, off, len); adler.Update(buf, off, more); off += more; count += more; totalOut += more; len -= more; if (len == 0) { return count; } } } while (Decode() || (outputWindow.GetAvailable() > 0 && mode != DECODE_CHKSUM)); return count; } /// <summary> /// Returns true, if the input buffer is empty. /// You should then call setInput(). /// NOTE: This method also returns true when the stream is finished. /// </summary> public bool IsNeedingInput { get { return input.IsNeedingInput; } } /// <summary> /// Returns true, if a preset dictionary is needed to inflate the input. /// </summary> public bool IsNeedingDictionary { get { return mode == DECODE_DICT && neededBits == 0; } } /// <summary> /// Returns true, if the inflater has finished. This means, that no /// input is needed and no output can be produced. /// </summary> public bool IsFinished { get { return mode == FINISHED && outputWindow.GetAvailable() == 0; } } /// <summary> /// Gets the adler checksum. This is either the checksum of all /// uncompressed bytes returned by inflate(), or if needsDictionary() /// returns true (and thus no output was yet produced) this is the /// adler checksum of the expected dictionary. /// </summary> /// <returns> /// the adler checksum. /// </returns> public int Adler { get { return IsNeedingDictionary ? readAdler : (int) adler.Value; } } /// <summary> /// Gets the total number of output bytes returned by inflate(). /// </summary> /// <returns> /// the total number of output bytes. /// </returns> public int TotalOut { get { return totalOut; } } /// <summary> /// Gets the total number of processed compressed input bytes. /// </summary> /// <returns> /// the total number of bytes of processed input bytes. /// </returns> public int TotalIn { get { return totalIn - RemainingInput; } } /// <summary> /// Gets the number of unprocessed input. Useful, if the end of the /// stream is reached and you want to further process the bytes after /// the deflate stream. /// </summary> /// <returns> /// the number of bytes of the input which were not processed. /// </returns> public int RemainingInput { get { return input.AvailableBytes; } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -