//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 (hasFormatReader) { if (state == InflaterState.ReadingHeader) { if (!formatReader.ReadHeader(input)) { return(false); } state = InflaterState.ReadingBFinal; } else if (state == InflaterState.StartReadingFooter || state == InflaterState.ReadingFooter) { if (!formatReader.ReadFooter(input)) { return(false); } state = InflaterState.VerifyingFooter; 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("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("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 (hasFormatReader) { state = InflaterState.StartReadingFooter; } 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 (_hasFormatReader) { if (_state == Inflater64State.ReadingHeader) { if (!_formatReader.ReadHeader(_input)) { return(false); } _state = Inflater64State.ReadingBFinal; } else if (_state == Inflater64State.StartReadingFooter || _state == Inflater64State.ReadingFooter) { if (!_formatReader.ReadFooter(_input)) { return(false); } _state = Inflater64State.VerifyingFooter; return(true); } } if (_state == Inflater64State.ReadingBFinal) { // reading bfinal bit // Need 1 bit if (!_input.EnsureBitsAvailable(1)) { return(false); } _bfinal = _input.GetBits(1); _state = Inflater64State.ReadingBType; } if (_state == Inflater64State.ReadingBType) { // Need 2 bits if (!_input.EnsureBitsAvailable(2)) { _state = Inflater64State.ReadingBType; return(false); } _blockType = (BlockType)_input.GetBits(2); if (_blockType == BlockType.Dynamic) { _state = Inflater64State.ReadingNumLitCodes; } else if (_blockType == BlockType.Static) { _literalLengthTree = HuffmanTree.StaticLiteralLengthTree; _distanceTree = HuffmanTree.StaticDistanceTree; _state = Inflater64State.DecodeTop; } else if (_blockType == BlockType.Uncompressed) { _state = Inflater64State.UncompressedAligning; } else { throw new InvalidDataException(SR.UnknownBlockType); } } if (_blockType == BlockType.Dynamic) { if (_state < Inflater64State.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)) { if (_hasFormatReader) { _state = Inflater64State.StartReadingFooter; } else { _state = Inflater64State.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() { var eob = false; var result = false; if (Finished()) { return(true); } if (_hasFormatReader) { switch (_state) { case InflaterState.ReadingHeader: if (!_formatReader.ReadHeader(_input)) { return(false); } _state = InflaterState.ReadingBFinal; break; case InflaterState.ReadingFooter: case InflaterState.StartReadingFooter: if (!_formatReader.ReadFooter(_input)) { return(false); } _state = InflaterState.VerifyingFooter; 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); switch (_blockType) { case BlockType.Dynamic: _state = InflaterState.ReadingNumLitCodes; break; case BlockType.Static: _literalLengthTree = HuffmanTree.StaticLiteralLengthTree; _distanceTree = HuffmanTree.StaticDistanceTree; _state = InflaterState.DecodeTop; break; case BlockType.Uncompressed: _state = InflaterState.UncompressedAligning; break; default: throw new InvalidDataContractException("Unknown block type."); } } switch (_blockType) { case BlockType.Dynamic: result = _state < InflaterState.DecodeTop ? DecodeDynamicBlockHeader() : DecodeBlock(out eob); break; case BlockType.Static: result = DecodeBlock(out eob); break; case BlockType.Uncompressed: result = DecodeUncompressedBlock(out eob); break; default: throw new InvalidDataContractException("Unknown block type."); } // // If we reached the end of the block and the block we were decoding had // bfinal=1 (final block) // if (!eob || (_bfinal == 0)) { return(result); } _state = _hasFormatReader ? InflaterState.StartReadingFooter : InflaterState.Done; return(result); }