//Each block of compressed data begins with 3 header bits // containing the following data: // first bit BFINAL // next 2 bits BTYPE // Note that the header bits do not necessarily begin on a byte // boundary, since a block does not necessarily occupy an integral // number of bytes. // BFINAL is set if and only if this is the last block of the data // set. // BTYPE specifies how the data are compressed, as follows: // 00 - no compression // 01 - compressed with fixed Huffman codes // 10 - compressed with dynamic Huffman codes // 11 - reserved (error) // The only difference between the two compressed cases is how the // Huffman codes for the literal/length and distance alphabets are // defined. // // This function returns true for success (end of block or output window is full,) // false if we are short of input // private bool Decode() { bool eob = false; bool result = false; if (Finished()) { return(true); } if (using_gzip) { if (state == InflaterState.ReadingGZIPHeader) { if (!gZipDecoder.ReadGzipHeader()) { return(false); } state = InflaterState.ReadingBFinal; } else if (state == InflaterState.StartReadingGZIPFooter || state == InflaterState.ReadingGZIPFooter) { if (!gZipDecoder.ReadGzipFooter()) { return(false); } state = InflaterState.VerifyingGZIPFooter; return(true); } } if (state == InflaterState.ReadingBFinal) // reading bfinal bit // Need 1 bit { if (!input.EnsureBitsAvailable(1)) { return(false); } bfinal = input.GetBits(1); state = InflaterState.ReadingBType; } if (state == InflaterState.ReadingBType) { // Need 2 bits if (!input.EnsureBitsAvailable(2)) { state = InflaterState.ReadingBType; return(false); } blockType = (BlockType)input.GetBits(2); if (blockType == BlockType.Dynamic) { Debug.WriteLineIf(CompressionTracingSwitch.Informational, "Decoding Dynamic Block", "Compression"); state = InflaterState.ReadingNumLitCodes; } else if (blockType == BlockType.Static) { Debug.WriteLineIf(CompressionTracingSwitch.Informational, "Decoding Static Block", "Compression"); literalLengthTree = HuffmanTree.StaticLiteralLengthTree; distanceTree = HuffmanTree.StaticDistanceTree; state = InflaterState.DecodeTop; } else if (blockType == BlockType.Uncompressed) { Debug.WriteLineIf(CompressionTracingSwitch.Informational, "Decoding UnCompressed Block", "Compression"); state = InflaterState.UncompressedAligning; } else { throw new InvalidDataException(SR.GetString(SR.UnknownBlockType)); } } if (blockType == BlockType.Dynamic) { if (state < InflaterState.DecodeTop) // we are reading the header { result = DecodeDynamicBlockHeader(); } else { result = DecodeBlock(out eob); // this can returns true when output is full } } else if (blockType == BlockType.Static) { result = DecodeBlock(out eob); } else if (blockType == BlockType.Uncompressed) { result = DecodeUncompressedBlock(out eob); } else { throw new InvalidDataException(SR.GetString(SR.UnknownBlockType)); } // // If we reached the end of the block and the block we were decoding had // bfinal=1 (final block) // if (eob && (bfinal != 0)) { if (using_gzip) { state = InflaterState.StartReadingGZIPFooter; } else { state = InflaterState.Done; } } return(result); }
//Each block of compressed data begins with 3 header bits // containing the following data: // first bit BFINAL // next 2 bits BTYPE // Note that the header bits do not necessarily begin on a byte // boundary, since a block does not necessarily occupy an integral // number of bytes. // BFINAL is set if and only if this is the last block of the data // set. // BTYPE specifies how the data are compressed, as follows: // 00 - no compression // 01 - compressed with fixed Huffman codes // 10 - compressed with dynamic Huffman codes // 11 - reserved (error) // The only difference between the two compressed cases is how the // Huffman codes for the literal/length and distance alphabets are // defined. // // This function returns true for success (end of block or output window is full,) // false if we are short of input // private bool Decode() { bool eob = false; bool result; if (Finished()) { return(true); } if (_state == InflaterState.ReadingBFinal) { // reading bfinal bit // Need 1 bit if (!_input.EnsureBitsAvailable(1)) { return(false); } _bfinal = _input.GetBits(1); _state = InflaterState.ReadingBType; } if (_state == InflaterState.ReadingBType) { // Need 2 bits if (!_input.EnsureBitsAvailable(2)) { _state = InflaterState.ReadingBType; return(false); } _blockType = (BlockType)_input.GetBits(2); if (_blockType == BlockType.Dynamic) { _state = InflaterState.ReadingNumLitCodes; } else if (_blockType == BlockType.Static) { _literalLengthTree = HuffmanTree.StaticLiteralLengthTree; _distanceTree = HuffmanTree.StaticDistanceTree; _state = InflaterState.DecodeTop; } else if (_blockType == BlockType.Uncompressed) { _state = InflaterState.UncompressedAligning; } else { throw new InvalidDataException(SR.UnknownBlockType); } } if (_blockType == BlockType.Dynamic) { if (_state < InflaterState.DecodeTop) { // we are reading the header result = DecodeDynamicBlockHeader(); } else { result = DecodeBlock(out eob); // this can returns true when output is full } } else if (_blockType == BlockType.Static) { result = DecodeBlock(out eob); } else if (_blockType == BlockType.Uncompressed) { result = DecodeUncompressedBlock(out eob); } else { throw new InvalidDataException(SR.UnknownBlockType); } // // If we reached the end of the block and the block we were decoding had // bfinal=1 (final block) // if (eob && (_bfinal != 0)) { _state = InflaterState.Done; } return(result); }