//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) { _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)) { if (_hasFormatReader) _state = InflaterState.StartReadingFooter; else _state = InflaterState.Done; } return result; }
// Format of the dynamic block header: // 5 Bits: HLIT, # of Literal/Length codes - 257 (257 - 286) // 5 Bits: HDIST, # of Distance codes - 1 (1 - 32) // 4 Bits: HCLEN, # of Code Length codes - 4 (4 - 19) // // (HCLEN + 4) x 3 bits: code lengths for the code length // alphabet given just above, in the order: 16, 17, 18, // 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 // // These code lengths are interpreted as 3-bit integers // (0-7); as above, a code length of 0 means the // corresponding symbol (literal/length or distance code // length) is not used. // // HLIT + 257 code lengths for the literal/length alphabet, // encoded using the code length Huffman code // // HDIST + 1 code lengths for the distance alphabet, // encoded using the code length Huffman code // // The code length repeat codes can cross from HLIT + 257 to the // HDIST + 1 code lengths. In other words, all code lengths form // a single sequence of HLIT + HDIST + 258 values. private bool DecodeDynamicBlockHeader() { switch (_state) { case InflaterState.ReadingNumLitCodes: _literalLengthCodeCount = _input.GetBits(5); if (_literalLengthCodeCount < 0) { return false; } _literalLengthCodeCount += 257; _state = InflaterState.ReadingNumDistCodes; goto case InflaterState.ReadingNumDistCodes; case InflaterState.ReadingNumDistCodes: _distanceCodeCount = _input.GetBits(5); if (_distanceCodeCount < 0) { return false; } _distanceCodeCount += 1; _state = InflaterState.ReadingNumCodeLengthCodes; goto case InflaterState.ReadingNumCodeLengthCodes; case InflaterState.ReadingNumCodeLengthCodes: _codeLengthCodeCount = _input.GetBits(4); if (_codeLengthCodeCount < 0) { return false; } _codeLengthCodeCount += 4; _loopCounter = 0; _state = InflaterState.ReadingCodeLengthCodes; goto case InflaterState.ReadingCodeLengthCodes; case InflaterState.ReadingCodeLengthCodes: while (_loopCounter < _codeLengthCodeCount) { int bits = _input.GetBits(3); if (bits < 0) { return false; } _codeLengthTreeCodeLength[s_codeOrder[_loopCounter]] = (byte)bits; ++_loopCounter; } for (int i = _codeLengthCodeCount; i < s_codeOrder.Length; i++) { _codeLengthTreeCodeLength[s_codeOrder[i]] = 0; } // create huffman tree for code length _codeLengthTree = new HuffmanTree(_codeLengthTreeCodeLength); _codeArraySize = _literalLengthCodeCount + _distanceCodeCount; _loopCounter = 0; // reset loop count _state = InflaterState.ReadingTreeCodesBefore; goto case InflaterState.ReadingTreeCodesBefore; case InflaterState.ReadingTreeCodesBefore: case InflaterState.ReadingTreeCodesAfter: while (_loopCounter < _codeArraySize) { if (_state == InflaterState.ReadingTreeCodesBefore) { if ((_lengthCode = _codeLengthTree.GetNextSymbol(_input)) < 0) { return false; } } // The alphabet for code lengths is as follows: // 0 - 15: Represent code lengths of 0 - 15 // 16: Copy the previous code length 3 - 6 times. // The next 2 bits indicate repeat length // (0 = 3, ... , 3 = 6) // Example: Codes 8, 16 (+2 bits 11), // 16 (+2 bits 10) will expand to // 12 code lengths of 8 (1 + 6 + 5) // 17: Repeat a code length of 0 for 3 - 10 times. // (3 bits of length) // 18: Repeat a code length of 0 for 11 - 138 times // (7 bits of length) if (_lengthCode <= 15) { _codeList[_loopCounter++] = (byte)_lengthCode; } else { int repeatCount; if (_lengthCode == 16) { if (!_input.EnsureBitsAvailable(2)) { _state = InflaterState.ReadingTreeCodesAfter; return false; } if (_loopCounter == 0) { // can't have "prev code" on first code throw new InvalidDataException(); } byte previousCode = _codeList[_loopCounter - 1]; repeatCount = _input.GetBits(2) + 3; if (_loopCounter + repeatCount > _codeArraySize) { throw new InvalidDataException(); } for (int j = 0; j < repeatCount; j++) { _codeList[_loopCounter++] = previousCode; } } else if (_lengthCode == 17) { if (!_input.EnsureBitsAvailable(3)) { _state = InflaterState.ReadingTreeCodesAfter; return false; } repeatCount = _input.GetBits(3) + 3; if (_loopCounter + repeatCount > _codeArraySize) { throw new InvalidDataException(); } for (int j = 0; j < repeatCount; j++) { _codeList[_loopCounter++] = 0; } } else { // code == 18 if (!_input.EnsureBitsAvailable(7)) { _state = InflaterState.ReadingTreeCodesAfter; return false; } repeatCount = _input.GetBits(7) + 11; if (_loopCounter + repeatCount > _codeArraySize) { throw new InvalidDataException(); } for (int j = 0; j < repeatCount; j++) { _codeList[_loopCounter++] = 0; } } } _state = InflaterState.ReadingTreeCodesBefore; // we want to read the next code. } break; default: Debug.Assert(false, "check why we are here!"); throw new InvalidDataException(SR.UnknownState); } byte[] literalTreeCodeLength = new byte[HuffmanTree.MaxLiteralTreeElements]; byte[] distanceTreeCodeLength = new byte[HuffmanTree.MaxDistTreeElements]; // Create literal and distance tables Array.Copy(_codeList, 0, literalTreeCodeLength, 0, _literalLengthCodeCount); Array.Copy(_codeList, _literalLengthCodeCount, distanceTreeCodeLength, 0, _distanceCodeCount); // Make sure there is an end-of-block code, otherwise how could we ever end? if (literalTreeCodeLength[HuffmanTree.EndOfBlockCode] == 0) { throw new InvalidDataException(); } _literalLengthTree = new HuffmanTree(literalTreeCodeLength); _distanceTree = new HuffmanTree(distanceTreeCodeLength); _state = InflaterState.DecodeTop; return true; }
//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); }
// Format of the dynamic block header: // 5 Bits: HLIT, # of Literal/Length codes - 257 (257 - 286) // 5 Bits: HDIST, # of Distance codes - 1 (1 - 32) // 4 Bits: HCLEN, # of Code Length codes - 4 (4 - 19) // // (HCLEN + 4) x 3 bits: code lengths for the code length // alphabet given just above, in the order: 16, 17, 18, // 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 // // These code lengths are interpreted as 3-bit integers // (0-7); as above, a code length of 0 means the // corresponding symbol (literal/length or distance code // length) is not used. // // HLIT + 257 code lengths for the literal/length alphabet, // encoded using the code length Huffman code // // HDIST + 1 code lengths for the distance alphabet, // encoded using the code length Huffman code // // The code length repeat codes can cross from HLIT + 257 to the // HDIST + 1 code lengths. In other words, all code lengths form // a single sequence of HLIT + HDIST + 258 values. bool DecodeDynamicBlockHeader() { switch (state) { case InflaterState.ReadingNumLitCodes: literalLengthCodeCount = input.GetBits(5); if (literalLengthCodeCount < 0) { return(false); } literalLengthCodeCount += 257; state = InflaterState.ReadingNumDistCodes; goto case InflaterState.ReadingNumDistCodes; case InflaterState.ReadingNumDistCodes: distanceCodeCount = input.GetBits(5); if (distanceCodeCount < 0) { return(false); } distanceCodeCount += 1; state = InflaterState.ReadingNumCodeLengthCodes; goto case InflaterState.ReadingNumCodeLengthCodes; case InflaterState.ReadingNumCodeLengthCodes: codeLengthCodeCount = input.GetBits(4); if (codeLengthCodeCount < 0) { return(false); } codeLengthCodeCount += 4; loopCounter = 0; state = InflaterState.ReadingCodeLengthCodes; goto case InflaterState.ReadingCodeLengthCodes; case InflaterState.ReadingCodeLengthCodes: while (loopCounter < codeLengthCodeCount) { int bits = input.GetBits(3); if (bits < 0) { return(false); } codeLengthTreeCodeLength[codeOrder[loopCounter]] = (byte)bits; ++loopCounter; } for (int i = codeLengthCodeCount; i < codeOrder.Length; i++) { codeLengthTreeCodeLength[codeOrder[i]] = 0; } // create huffman tree for code length codeLengthTree = new HuffmanTree(codeLengthTreeCodeLength); codeArraySize = literalLengthCodeCount + distanceCodeCount; loopCounter = 0; // reset loop count state = InflaterState.ReadingTreeCodesBefore; goto case InflaterState.ReadingTreeCodesBefore; case InflaterState.ReadingTreeCodesBefore: case InflaterState.ReadingTreeCodesAfter: while (loopCounter < codeArraySize) { if (state == InflaterState.ReadingTreeCodesBefore) { if ((lengthCode = codeLengthTree.GetNextSymbol(input)) < 0) { return(false); } } // The alphabet for code lengths is as follows: // 0 - 15: Represent code lengths of 0 - 15 // 16: Copy the previous code length 3 - 6 times. // The next 2 bits indicate repeat length // (0 = 3, ... , 3 = 6) // Example: Codes 8, 16 (+2 bits 11), // 16 (+2 bits 10) will expand to // 12 code lengths of 8 (1 + 6 + 5) // 17: Repeat a code length of 0 for 3 - 10 times. // (3 bits of length) // 18: Repeat a code length of 0 for 11 - 138 times // (7 bits of length) if (lengthCode <= 15) { codeList[loopCounter++] = (byte)lengthCode; } else { if (!input.EnsureBitsAvailable(7)) // it doesn't matter if we require more bits here { state = InflaterState.ReadingTreeCodesAfter; return(false); } int repeatCount; if (lengthCode == 16) { if (loopCounter == 0) // can't have "prev code" on first code { throw new InvalidDataException(); } byte previousCode = codeList[loopCounter - 1]; repeatCount = input.GetBits(2) + 3; if (loopCounter + repeatCount > codeArraySize) { throw new InvalidDataException(); } for (int j = 0; j < repeatCount; j++) { codeList[loopCounter++] = previousCode; } } else if (lengthCode == 17) { repeatCount = input.GetBits(3) + 3; if (loopCounter + repeatCount > codeArraySize) { throw new InvalidDataException(); } for (int j = 0; j < repeatCount; j++) { codeList[loopCounter++] = 0; } } else // code == 18 { repeatCount = input.GetBits(7) + 11; if (loopCounter + repeatCount > codeArraySize) { throw new InvalidDataException(); } for (int j = 0; j < repeatCount; j++) { codeList[loopCounter++] = 0; } } } state = InflaterState.ReadingTreeCodesBefore; // we want to read the next code. } break; default: Debug.Assert(false, "check why we are here!"); throw new InvalidDataException(SR.GetString(SR.UnknownState)); } byte[] literalTreeCodeLength = new byte[HuffmanTree.MaxLiteralTreeElements]; byte[] distanceTreeCodeLength = new byte[HuffmanTree.MaxDistTreeElements]; // Create literal and distance tables Array.Copy(codeList, literalTreeCodeLength, literalLengthCodeCount); Array.Copy(codeList, literalLengthCodeCount, distanceTreeCodeLength, 0, distanceCodeCount); // Make sure there is an end-of-block code, otherwise how could we ever end? if (literalTreeCodeLength[HuffmanTree.EndOfBlockCode] == 0) { throw new InvalidDataException(); } literalLengthTree = new HuffmanTree(literalTreeCodeLength); distanceTree = new HuffmanTree(distanceTreeCodeLength); state = InflaterState.DecodeTop; return(true); }
static HuffmanTree() { // construct the static literal tree and distance tree staticLiteralLengthTree = new HuffmanTree(GetStaticLiteralTreeLength()); staticDistanceTree = new HuffmanTree(GetStaticDistanceTreeLength()); }
//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; }
// Format of the dynamic block header: // 5 Bits: HLIT, # of Literal/Length codes - 257 (257 - 286) // 5 Bits: HDIST, # of Distance codes - 1 (1 - 32) // 4 Bits: HCLEN, # of Code Length codes - 4 (4 - 19) // // (HCLEN + 4) x 3 bits: code lengths for the code length // alphabet given just above, in the order: 16, 17, 18, // 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 // // These code lengths are interpreted as 3-bit integers // (0-7); as above, a code length of 0 means the // corresponding symbol (literal/length or distance code // length) is not used. // // HLIT + 257 code lengths for the literal/length alphabet, // encoded using the code length Huffman code // // HDIST + 1 code lengths for the distance alphabet, // encoded using the code length Huffman code // // The code length repeat codes can cross from HLIT + 257 to the // HDIST + 1 code lengths. In other words, all code lengths form // a single sequence of HLIT + HDIST + 258 values. private bool DecodeDynamicBlockHeader() { switch (_state) { case InflaterState.ReadingNumLitCodes: _literalLengthCodeCount = _input.GetBits(5); if (_literalLengthCodeCount < 0) { return(false); } _literalLengthCodeCount += 257; _state = InflaterState.ReadingNumDistCodes; goto case InflaterState.ReadingNumDistCodes; case InflaterState.ReadingNumDistCodes: _distanceCodeCount = _input.GetBits(5); if (_distanceCodeCount < 0) { return(false); } _distanceCodeCount += 1; _state = InflaterState.ReadingNumCodeLengthCodes; goto case InflaterState.ReadingNumCodeLengthCodes; case InflaterState.ReadingNumCodeLengthCodes: _codeLengthCodeCount = _input.GetBits(4); if (_codeLengthCodeCount < 0) { return(false); } _codeLengthCodeCount += 4; _loopCounter = 0; _state = InflaterState.ReadingCodeLengthCodes; goto case InflaterState.ReadingCodeLengthCodes; case InflaterState.ReadingCodeLengthCodes: while (_loopCounter < _codeLengthCodeCount) { int bits = _input.GetBits(3); if (bits < 0) { return(false); } _codeLengthTreeCodeLength[s_codeOrder[_loopCounter]] = (byte)bits; ++_loopCounter; } for (int i = _codeLengthCodeCount; i < s_codeOrder.Length; i++) { _codeLengthTreeCodeLength[s_codeOrder[i]] = 0; } // create huffman tree for code length _codeLengthTree = new HuffmanTree(_codeLengthTreeCodeLength); _codeArraySize = _literalLengthCodeCount + _distanceCodeCount; _loopCounter = 0; // reset loop count _state = InflaterState.ReadingTreeCodesBefore; goto case InflaterState.ReadingTreeCodesBefore; case InflaterState.ReadingTreeCodesBefore: case InflaterState.ReadingTreeCodesAfter: while (_loopCounter < _codeArraySize) { if (_state == InflaterState.ReadingTreeCodesBefore) { if ((_lengthCode = _codeLengthTree.GetNextSymbol(_input)) < 0) { return(false); } } // The alphabet for code lengths is as follows: // 0 - 15: Represent code lengths of 0 - 15 // 16: Copy the previous code length 3 - 6 times. // The next 2 bits indicate repeat length // (0 = 3, ... , 3 = 6) // Example: Codes 8, 16 (+2 bits 11), // 16 (+2 bits 10) will expand to // 12 code lengths of 8 (1 + 6 + 5) // 17: Repeat a code length of 0 for 3 - 10 times. // (3 bits of length) // 18: Repeat a code length of 0 for 11 - 138 times // (7 bits of length) if (_lengthCode <= 15) { _codeList[_loopCounter++] = (byte)_lengthCode; } else { int repeatCount; if (_lengthCode == 16) { if (!_input.EnsureBitsAvailable(2)) { _state = InflaterState.ReadingTreeCodesAfter; return(false); } if (_loopCounter == 0) { // can't have "prev code" on first code throw new InvalidDataException(); } byte previousCode = _codeList[_loopCounter - 1]; repeatCount = _input.GetBits(2) + 3; if (_loopCounter + repeatCount > _codeArraySize) { throw new InvalidDataException(); } for (int j = 0; j < repeatCount; j++) { _codeList[_loopCounter++] = previousCode; } } else if (_lengthCode == 17) { if (!_input.EnsureBitsAvailable(3)) { _state = InflaterState.ReadingTreeCodesAfter; return(false); } repeatCount = _input.GetBits(3) + 3; if (_loopCounter + repeatCount > _codeArraySize) { throw new InvalidDataException(); } for (int j = 0; j < repeatCount; j++) { _codeList[_loopCounter++] = 0; } } else { // code == 18 if (!_input.EnsureBitsAvailable(7)) { _state = InflaterState.ReadingTreeCodesAfter; return(false); } repeatCount = _input.GetBits(7) + 11; if (_loopCounter + repeatCount > _codeArraySize) { throw new InvalidDataException(); } for (int j = 0; j < repeatCount; j++) { _codeList[_loopCounter++] = 0; } } } _state = InflaterState.ReadingTreeCodesBefore; // we want to read the next code. } break; default: Debug.Fail("check why we are here!"); throw new InvalidDataException(SR.UnknownState); } byte[] literalTreeCodeLength = new byte[HuffmanTree.MaxLiteralTreeElements]; byte[] distanceTreeCodeLength = new byte[HuffmanTree.MaxDistTreeElements]; // Create literal and distance tables Array.Copy(_codeList, 0, literalTreeCodeLength, 0, _literalLengthCodeCount); Array.Copy(_codeList, _literalLengthCodeCount, distanceTreeCodeLength, 0, _distanceCodeCount); // Make sure there is an end-of-block code, otherwise how could we ever end? if (literalTreeCodeLength[HuffmanTree.EndOfBlockCode] == 0) { throw new InvalidDataException(); } _literalLengthTree = new HuffmanTree(literalTreeCodeLength); _distanceTree = new HuffmanTree(distanceTreeCodeLength); _state = InflaterState.DecodeTop; return(true); }
//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) { _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)) { if (_hasFormatReader) { _state = InflaterState.StartReadingFooter; } else { _state = InflaterState.Done; } } return(result); }
static HuffmanTree() { // construct the static literal tree and distance tree s_staticLiteralLengthTree = new HuffmanTree(GetStaticLiteralTreeLength()); s_staticDistanceTree = new HuffmanTree(GetStaticDistanceTreeLength()); }
private bool DecodeDynamicBlockHeader() { switch (this.state) { case InflaterState.ReadingNumLitCodes: this.literalLengthCodeCount = this.input.GetBits(5); if (this.literalLengthCodeCount >= 0) { this.literalLengthCodeCount += 0x101; this.state = InflaterState.ReadingNumDistCodes; break; } return false; case InflaterState.ReadingNumDistCodes: break; case InflaterState.ReadingNumCodeLengthCodes: goto Label_0096; case InflaterState.ReadingCodeLengthCodes: goto Label_0107; case InflaterState.ReadingTreeCodesBefore: case InflaterState.ReadingTreeCodesAfter: goto Label_0315; default: throw new InvalidDataException("Decoder is in some unknown state. This might be caused by corrupted data."); } this.distanceCodeCount = this.input.GetBits(5); if (this.distanceCodeCount < 0) { return false; } this.distanceCodeCount++; this.state = InflaterState.ReadingNumCodeLengthCodes; Label_0096: this.codeLengthCodeCount = this.input.GetBits(4); if (this.codeLengthCodeCount < 0) { return false; } this.codeLengthCodeCount += 4; this.loopCounter = 0; this.state = InflaterState.ReadingCodeLengthCodes; Label_0107: while (this.loopCounter < this.codeLengthCodeCount) { int bits = this.input.GetBits(3); if (bits < 0) { return false; } this.codeLengthTreeCodeLength[codeOrder[this.loopCounter]] = (byte)bits; this.loopCounter++; } for (int i = this.codeLengthCodeCount; i < codeOrder.Length; i++) { this.codeLengthTreeCodeLength[codeOrder[i]] = 0; } this.codeLengthTree = new HuffmanTree(this.codeLengthTreeCodeLength); this.codeArraySize = this.literalLengthCodeCount + this.distanceCodeCount; this.loopCounter = 0; this.state = InflaterState.ReadingTreeCodesBefore; Label_0315: while (this.loopCounter < this.codeArraySize) { if ((this.state == InflaterState.ReadingTreeCodesBefore) && ((this.lengthCode = this.codeLengthTree.GetNextSymbol(this.input)) < 0)) { return false; } if (this.lengthCode <= 15) { this.codeList[this.loopCounter++] = (byte)this.lengthCode; } else { int num3; if (!this.input.EnsureBitsAvailable(7)) { this.state = InflaterState.ReadingTreeCodesAfter; return false; } if (this.lengthCode == 0x10) { if (this.loopCounter == 0) { throw new InvalidDataException(); } byte num4 = this.codeList[this.loopCounter - 1]; num3 = this.input.GetBits(2) + 3; if ((this.loopCounter + num3) > this.codeArraySize) { throw new InvalidDataException(); } for (int j = 0; j < num3; j++) { this.codeList[this.loopCounter++] = num4; } } else if (this.lengthCode == 0x11) { num3 = this.input.GetBits(3) + 3; if ((this.loopCounter + num3) > this.codeArraySize) { throw new InvalidDataException(); } for (int k = 0; k < num3; k++) { this.codeList[this.loopCounter++] = 0; } } else { num3 = this.input.GetBits(7) + 11; if ((this.loopCounter + num3) > this.codeArraySize) { throw new InvalidDataException(); } for (int m = 0; m < num3; m++) { this.codeList[this.loopCounter++] = 0; } } } this.state = InflaterState.ReadingTreeCodesBefore; } byte[] destinationArray = new byte[0x120]; byte[] buffer2 = new byte[0x20]; Array.Copy(this.codeList, 0, destinationArray, 0, this.literalLengthCodeCount); Array.Copy(this.codeList, this.literalLengthCodeCount, buffer2, 0, this.distanceCodeCount); if (destinationArray[0x100] == 0) { throw new InvalidDataException(); } this.literalLengthTree = new HuffmanTree(destinationArray); this.distanceTree = new HuffmanTree(buffer2); this.state = InflaterState.DecodeTop; return true; }
private bool Decode() { bool flag = false; bool flag2 = false; if (this.Finished()) { return true; } if (this.using_gzip) { if (this.state == InflaterState.ReadingGZIPHeader) { if (!this.gZipDecoder.ReadGzipHeader()) { return false; } this.state = InflaterState.ReadingBFinal; } else if ((this.state == InflaterState.StartReadingGZIPFooter) || (this.state == InflaterState.ReadingGZIPFooter)) { if (!this.gZipDecoder.ReadGzipFooter()) { return false; } this.state = InflaterState.VerifyingGZIPFooter; return true; } } if (this.state == InflaterState.ReadingBFinal) { if (!this.input.EnsureBitsAvailable(1)) { return false; } this.bfinal = this.input.GetBits(1); this.state = InflaterState.ReadingBType; } if (this.state == InflaterState.ReadingBType) { if (!this.input.EnsureBitsAvailable(2)) { this.state = InflaterState.ReadingBType; return false; } this.blockType = (BlockType)this.input.GetBits(2); if (this.blockType != BlockType.Dynamic) { if (this.blockType != BlockType.Static) { if (this.blockType != BlockType.Uncompressed) { throw new InvalidDataException("Unknown block type. Stream might be corrupted."); } this.state = InflaterState.UncompressedAligning; } else { this.literalLengthTree = HuffmanTree.StaticLiteralLengthTree; this.distanceTree = HuffmanTree.StaticDistanceTree; this.state = InflaterState.DecodeTop; } } else { this.state = InflaterState.ReadingNumLitCodes; } } if (this.blockType == BlockType.Dynamic) { if (this.state < InflaterState.DecodeTop) { flag2 = this.DecodeDynamicBlockHeader(); } else { flag2 = this.DecodeBlock(out flag); } } else if (this.blockType == BlockType.Static) { flag2 = this.DecodeBlock(out flag); } else { if (this.blockType != BlockType.Uncompressed) { throw new InvalidDataException("Unknown block type. Stream might be corrupted."); } flag2 = this.DecodeUncompressedBlock(out flag); } if (flag && (this.bfinal != 0)) { if (this.using_gzip) { this.state = InflaterState.StartReadingGZIPFooter; return flag2; } this.state = InflaterState.Done; } return flag2; }
private bool Decode() { bool flag = false; bool flag2 = false; if (this.Finished()) { return(true); } if (this.using_gzip) { if (this.state == InflaterState.ReadingGZIPHeader) { if (!this.gZipDecoder.ReadGzipHeader()) { return(false); } this.state = InflaterState.ReadingBFinal; } else if ((this.state == InflaterState.StartReadingGZIPFooter) || (this.state == InflaterState.ReadingGZIPFooter)) { if (!this.gZipDecoder.ReadGzipFooter()) { return(false); } this.state = InflaterState.VerifyingGZIPFooter; return(true); } } if (this.state == InflaterState.ReadingBFinal) { if (!this.input.EnsureBitsAvailable(1)) { return(false); } this.bfinal = this.input.GetBits(1); this.state = InflaterState.ReadingBType; } if (this.state == InflaterState.ReadingBType) { if (!this.input.EnsureBitsAvailable(2)) { this.state = InflaterState.ReadingBType; return(false); } this.blockType = (BlockType)this.input.GetBits(2); if (this.blockType != BlockType.Dynamic) { if (this.blockType != BlockType.Static) { if (this.blockType != BlockType.Uncompressed) { throw new InvalidDataException("Unknown block type. Stream might be corrupted."); } this.state = InflaterState.UncompressedAligning; } else { this.literalLengthTree = HuffmanTree.StaticLiteralLengthTree; this.distanceTree = HuffmanTree.StaticDistanceTree; this.state = InflaterState.DecodeTop; } } else { this.state = InflaterState.ReadingNumLitCodes; } } if (this.blockType == BlockType.Dynamic) { if (this.state < InflaterState.DecodeTop) { flag2 = this.DecodeDynamicBlockHeader(); } else { flag2 = this.DecodeBlock(out flag); } } else if (this.blockType == BlockType.Static) { flag2 = this.DecodeBlock(out flag); } else { if (this.blockType != BlockType.Uncompressed) { throw new InvalidDataException("Unknown block type. Stream might be corrupted."); } flag2 = this.DecodeUncompressedBlock(out flag); } if (flag && (this.bfinal != 0)) { if (this.using_gzip) { this.state = InflaterState.StartReadingGZIPFooter; return(flag2); } this.state = InflaterState.Done; } return(flag2); }
private bool DecodeDynamicBlockHeader() { switch (this.state) { case InflaterState.ReadingNumLitCodes: this.literalLengthCodeCount = this.input.GetBits(5); if (this.literalLengthCodeCount >= 0) { this.literalLengthCodeCount += 0x101; this.state = InflaterState.ReadingNumDistCodes; break; } return(false); case InflaterState.ReadingNumDistCodes: break; case InflaterState.ReadingNumCodeLengthCodes: goto Label_0096; case InflaterState.ReadingCodeLengthCodes: goto Label_0107; case InflaterState.ReadingTreeCodesBefore: case InflaterState.ReadingTreeCodesAfter: goto Label_0315; default: throw new InvalidDataException("Decoder is in some unknown state. This might be caused by corrupted data."); } this.distanceCodeCount = this.input.GetBits(5); if (this.distanceCodeCount < 0) { return(false); } this.distanceCodeCount++; this.state = InflaterState.ReadingNumCodeLengthCodes; Label_0096: this.codeLengthCodeCount = this.input.GetBits(4); if (this.codeLengthCodeCount < 0) { return(false); } this.codeLengthCodeCount += 4; this.loopCounter = 0; this.state = InflaterState.ReadingCodeLengthCodes; Label_0107: while (this.loopCounter < this.codeLengthCodeCount) { int bits = this.input.GetBits(3); if (bits < 0) { return(false); } this.codeLengthTreeCodeLength[codeOrder[this.loopCounter]] = (byte)bits; this.loopCounter++; } for (int i = this.codeLengthCodeCount; i < codeOrder.Length; i++) { this.codeLengthTreeCodeLength[codeOrder[i]] = 0; } this.codeLengthTree = new HuffmanTree(this.codeLengthTreeCodeLength); this.codeArraySize = this.literalLengthCodeCount + this.distanceCodeCount; this.loopCounter = 0; this.state = InflaterState.ReadingTreeCodesBefore; Label_0315: while (this.loopCounter < this.codeArraySize) { if ((this.state == InflaterState.ReadingTreeCodesBefore) && ((this.lengthCode = this.codeLengthTree.GetNextSymbol(this.input)) < 0)) { return(false); } if (this.lengthCode <= 15) { this.codeList[this.loopCounter++] = (byte)this.lengthCode; } else { int num3; if (!this.input.EnsureBitsAvailable(7)) { this.state = InflaterState.ReadingTreeCodesAfter; return(false); } if (this.lengthCode == 0x10) { if (this.loopCounter == 0) { throw new InvalidDataException(); } byte num4 = this.codeList[this.loopCounter - 1]; num3 = this.input.GetBits(2) + 3; if ((this.loopCounter + num3) > this.codeArraySize) { throw new InvalidDataException(); } for (int j = 0; j < num3; j++) { this.codeList[this.loopCounter++] = num4; } } else if (this.lengthCode == 0x11) { num3 = this.input.GetBits(3) + 3; if ((this.loopCounter + num3) > this.codeArraySize) { throw new InvalidDataException(); } for (int k = 0; k < num3; k++) { this.codeList[this.loopCounter++] = 0; } } else { num3 = this.input.GetBits(7) + 11; if ((this.loopCounter + num3) > this.codeArraySize) { throw new InvalidDataException(); } for (int m = 0; m < num3; m++) { this.codeList[this.loopCounter++] = 0; } } } this.state = InflaterState.ReadingTreeCodesBefore; } byte[] destinationArray = new byte[0x120]; byte[] buffer2 = new byte[0x20]; Array.Copy(this.codeList, 0, destinationArray, 0, this.literalLengthCodeCount); Array.Copy(this.codeList, this.literalLengthCodeCount, buffer2, 0, this.distanceCodeCount); if (destinationArray[0x100] == 0) { throw new InvalidDataException(); } this.literalLengthTree = new HuffmanTree(destinationArray); this.distanceTree = new HuffmanTree(buffer2); this.state = InflaterState.DecodeTop; return(true); }