private bool HandleBlocksState(CompressionStream stream, out ErrorCode result) { result = ErrorCode.Ok; this.error = (ErrorCode)this.blocks.Process(stream, (int)this.error); if (this.error == ErrorCode.DataError) { this.state = InflaterState.Error; this.marker = 0; return(true); } if (this.error == ErrorCode.Ok) { this.error = this.startError; } if (this.error != ErrorCode.StreamEnd) { result = this.error; return(false); } this.error = this.startError; this.blocks.Reset(stream, this.was); if (this.nowrap != 0) { this.state = InflaterState.Done; return(true); } this.state = InflaterState.CheckFour; return(true); }
private bool HandleFlagState(CompressionStream stream, out ErrorCode result) { result = ErrorCode.Ok; if (stream.InputCount == 0) { result = this.error; return(false); } this.error = this.startError; --stream.InputCount; ++stream.InputTotal; int num = (int)stream.Input[stream.InputIndex++] & (int)byte.MaxValue; if (((this.method << 8) + num) % 31 != 0) { this.state = InflaterState.Error; stream.ErrorMessage = "incorrect header check"; this.marker = 5; return(true); } if ((num & 32) == 0) { this.state = InflaterState.Blocks; return(true); } this.state = InflaterState.DictionaryFour; return(true); }
public void Recycle() { output.Recycle(); input.Recycle(); literalLengthTree = null; distanceTree = null; Array.Clear(codeList, 0, codeList.Length); Array.Clear(codeLengthTreeCodeLength, 0, codeLengthTreeCodeLength.Length); state = InflaterState.ReadingHeader; // hasFormatReader = false; bfinal = 0; blockType = BlockType.Uncompressed; Array.Clear(blockLengthBuffer, 0, blockLengthBuffer.Length); blockLength = 0; length = 0; distanceCode = 0; extraBits = 0; loopCounter = 0; literalLengthCodeCount = 0; distanceCodeCount = 0; codeLengthCodeCount = 0; codeArraySize = 0; lengthCode = 0; codeLengthTree = null; Reset(); }
private bool HandleMethodState(CompressionStream stream, out ErrorCode result) { result = ErrorCode.Ok; if (stream.InputCount == 0) { result = this.error; return(false); } this.error = this.startError; --stream.InputCount; ++stream.InputTotal; if (((this.method = (int)stream.Input[stream.InputIndex++]) & 15) != 8) { this.state = InflaterState.Error; stream.ErrorMessage = "unknown compression method"; this.marker = 5; return(true); } if ((this.method >> 4) + 8 > this.wbits) { this.state = InflaterState.Error; stream.ErrorMessage = "invalid window size"; this.marker = 5; return(true); } this.state = InflaterState.Flag; return(true); }
public int Inflate(byte[] bytes, int offset, int length) { // copy bytes from output to outputbytes if we have available bytes // if buffer is not filled up. keep decoding until no input are available // if decodeBlock returns false. Throw an exception. int count = 0; do { int copied = 0; if (_uncompressedSize == -1) { copied = _output.CopyTo(bytes, offset, length); } else { if (_uncompressedSize > _currentInflatedCount) { length = (int)Math.Min(length, _uncompressedSize - _currentInflatedCount); copied = _output.CopyTo(bytes, offset, length); _currentInflatedCount += copied; } else { _state = InflaterState.Done; _output.ClearBytesUsed(); } } if (copied > 0) { if (_hasFormatReader) { _formatReader.UpdateWithBytesRead(bytes, offset, copied); } offset += copied; count += copied; length -= copied; } if (length == 0) { // filled in the bytes array break; } // Decode will return false when more input is needed } while (!Finished() && Decode()); if (_state == InflaterState.VerifyingFooter) { // finished reading CRC // In this case finished is true and output window has all the data. // But some data in output window might not be copied out. if (_output.AvailableBytes == 0) { _formatReader.Validate(); } } return(count); }
private bool DecodeUncompressedBlock(out bool end_of_block) { end_of_block = false; while (true) { switch (this.state) { case InflaterState.UncompressedAligning: this.input.SkipToByteBoundary(); this.state = InflaterState.UncompressedByte1; goto case InflaterState.UncompressedByte1; case InflaterState.UncompressedByte1: case InflaterState.UncompressedByte2: case InflaterState.UncompressedByte3: case InflaterState.UncompressedByte4: int bits = this.input.GetBits(8); if (bits >= 0) { this.blockLengthBuffer[(int)(this.state - 16)] = (byte)bits; if (this.state == InflaterState.UncompressedByte4) { this.blockLength = (int)this.blockLengthBuffer[0] + (int)this.blockLengthBuffer[1] * 256; if ((int)(ushort)this.blockLength != (int)(ushort)~((int)this.blockLengthBuffer[2] + (int)this.blockLengthBuffer[3] * 256)) { goto label_6; } } ++this.state; continue; } goto label_3; case InflaterState.DecodingUncompressed: goto label_8; default: goto label_13; } } label_3: return(false); label_6: throw new InvalidDataException(SR.GetString("Invalid block length")); label_8: this.blockLength -= this.output.CopyFrom(this.input, this.blockLength); if (this.blockLength == 0) { this.state = InflaterState.ReadingBFinal; end_of_block = true; return(true); } return(this.output.FreeBytes == 0); label_13: Debug.Assert(false, "check why we are here!"); throw new InvalidDataException(SR.GetString("Unknown state")); }
private bool HandleDictionaryZeroState(CompressionStream stream, out ErrorCode result) { this.state = InflaterState.Error; stream.ErrorMessage = "need dictionary"; this.marker = 0; result = ErrorCode.StreamError; return(false); }
private void Reset() { if (this.hasFormatReader) { this.state = InflaterState.ReadingHeader; return; } this.state = InflaterState.ReadingBFinal; }
private bool DecodeUncompressedBlock(out bool end_of_block) { end_of_block = false; while (true) { switch (this.state) { case InflaterState.UncompressedAligning: this.input.SkipToByteBoundary(); this.state = InflaterState.UncompressedByte1; goto IL_43; case InflaterState.UncompressedByte1: case InflaterState.UncompressedByte2: case InflaterState.UncompressedByte3: case InflaterState.UncompressedByte4: goto IL_43; case InflaterState.DecodingUncompressed: goto IL_D6; } break; IL_43: int bits = this.input.GetBits(8); if (bits < 0) { return(false); } this.blockLengthBuffer[this.state - InflaterState.UncompressedByte1] = (byte)bits; if (this.state == InflaterState.UncompressedByte4) { this.blockLength = (int)this.blockLengthBuffer[0] + (int)this.blockLengthBuffer[1] * 256; int num = (int)this.blockLengthBuffer[2] + (int)this.blockLengthBuffer[3] * 256; if ((ushort)this.blockLength != (ushort)(~(ushort)num)) { goto Block_4; } } this.state++; } throw new InvalidDataException(SR.GetString("Unknown state")); Block_4: throw new InvalidDataException(SR.GetString("Invalid block length")); IL_D6: int num2 = this.output.CopyFrom(this.input, this.blockLength); this.blockLength -= num2; if (this.blockLength == 0) { this.state = InflaterState.ReadingBFinal; end_of_block = true; return(true); } return(this.output.FreeBytes == 0); }
private void Reset() { if (_hasFormatReader) { _state = InflaterState.ReadingHeader; // start by reading Header info } else { _state = InflaterState.ReadingBFinal; // start by reading BFinal bit } }
internal InflaterManaged(bool deflate64, long uncompressedSize) { _output = new OutputWindow(); _input = new InputBuffer(); _codeList = new byte[HuffmanTree.MaxLiteralTreeElements + HuffmanTree.MaxDistTreeElements]; _codeLengthTreeCodeLength = new byte[HuffmanTree.NumberOfCodeLengthTreeElements]; _deflate64 = deflate64; _uncompressedSize = uncompressedSize; _state = InflaterState.ReadingBFinal; // start by reading BFinal bit }
private bool DecodeUncompressedBlock(out bool end_of_block) { end_of_block = false; while (true) { switch (this.state) { case InflaterState.UncompressedAligning: this.input.SkipToByteBoundary(); this.state = InflaterState.UncompressedByte1; break; case InflaterState.UncompressedByte1: case InflaterState.UncompressedByte2: case InflaterState.UncompressedByte3: case InflaterState.UncompressedByte4: break; case InflaterState.DecodingUncompressed: { int num3 = this.output.CopyFrom(this.input, this.blockLength); this.blockLength -= num3; if (this.blockLength != 0) { return(this.output.FreeBytes == 0); } this.state = InflaterState.ReadingBFinal; end_of_block = true; return(true); } default: throw new InvalidDataException(SR.GetString("UnknownState")); } int bits = this.input.GetBits(8); if (bits < 0) { return(false); } this.blockLengthBuffer[((int)this.state) - 0x10] = (byte)bits; if (this.state == InflaterState.UncompressedByte4) { this.blockLength = this.blockLengthBuffer[0] + (this.blockLengthBuffer[1] * 0x100); int num2 = this.blockLengthBuffer[2] + (this.blockLengthBuffer[3] * 0x100); if (((ushort)this.blockLength) != ((ushort)~num2)) { throw new InvalidDataException(SR.GetString("InvalidBlockLength")); } } this.state += 1; } }
private int Reset(CompressionStream stream) { if (stream == null) { return(-2); } stream.InputTotal = 0L; stream.OutputTotal = 0L; stream.ErrorMessage = (string)null; this.state = this.nowrap != 0 ? InflaterState.Blocks : InflaterState.Method; this.blocks.Reset(stream, (long[])null); return(0); }
public void Reset() { if (this.using_gzip) { this.gZipDecoder.Reset(); this.state = InflaterState.ReadingGZIPHeader; this.streamSize = 0; this.crc32 = 0; } else { this.state = InflaterState.ReadingBFinal; } }
public void Reset() { if (using_gzip) { gZipDecoder.Reset(); state = InflaterState.ReadingGZIPHeader; // start by reading GZip Header info streamSize = 0; crc32 = 0; } else { state = InflaterState.ReadingBFinal; // start by reading BFinal bit } }
public void Reset() { if (_usingGzip) { _gZipDecoder.Reset(); _state = InflaterState.ReadingGZIPHeader; // start by reading GZip Header info _streamSize = 0; _crc32 = 0; } else { _state = InflaterState.ReadingBFinal; // start by reading BFinal bit } }
public int Sync(CompressionStream stream) { if (stream == null) { return(-2); } if (this.state != InflaterState.Error) { this.state = InflaterState.Error; this.marker = 0; } int inputCount = stream.InputCount; if (inputCount == 0) { return(-5); } int inputIndex = stream.InputIndex; int index; for (index = this.marker; inputCount != 0 && index < 4; --inputCount) { if ((int)stream.Input[inputIndex] == (int)Inflater.mark[index]) { ++index; } else { index = stream.Input[inputIndex] == (byte)0 ? 4 - index : 0; } ++inputIndex; } stream.InputTotal += (long)(inputIndex - stream.InputIndex); stream.InputIndex = inputIndex; stream.InputCount = inputCount; this.marker = index; if (index != 4) { return(-3); } long inputTotal = stream.InputTotal; long outputTotal = stream.OutputTotal; this.Reset(stream); stream.InputTotal = inputTotal; stream.OutputTotal = outputTotal; this.state = InflaterState.Blocks; return(0); }
private bool HandleCheckTwoState(CompressionStream stream, out ErrorCode result) { result = ErrorCode.Ok; if (stream.InputCount == 0) { result = this.error; return(false); } this.error = this.startError; --stream.InputCount; ++stream.InputTotal; this.need += (uint)((ulong)(((int)stream.Input[stream.InputIndex++] & (int)byte.MaxValue) << 8) & 65280UL); this.state = InflaterState.CheckOne; return(true); }
private bool HandleCheckFourState(CompressionStream stream, out ErrorCode result) { result = ErrorCode.Ok; if (stream.InputCount == 0) { result = this.error; return(false); } this.error = this.startError; --stream.InputCount; ++stream.InputTotal; this.need = (uint)(((int)stream.Input[stream.InputIndex++] & (int)byte.MaxValue) << 24 & -16777216); this.state = InflaterState.CheckThree; return(true); }
private bool HandleDictionaryThreeState(CompressionStream stream, out ErrorCode result) { result = ErrorCode.Ok; if (stream.InputCount == 0) { result = this.error; return(false); } this.error = this.startError; --stream.InputCount; ++stream.InputTotal; this.need += (uint)((ulong)(((int)stream.Input[stream.InputIndex++] & (int)byte.MaxValue) << 16) & 16711680UL); this.state = InflaterState.DictionaryTwo; return(true); }
private bool HandleDictionaryOneState(CompressionStream stream, out ErrorCode result) { result = ErrorCode.Ok; if (stream.InputCount == 0) { result = this.error; return(false); } this.error = this.startError; --stream.InputCount; ++stream.InputTotal; this.need += (uint)((ulong)stream.Input[stream.InputIndex++] & (ulong)byte.MaxValue); stream.Checksum = new Adler32(this.need); this.state = InflaterState.DictionaryZero; result = ErrorCode.NeedsDictionary; return(false); }
public int Inflate(byte[] bytes, int offset, int length) { // copy bytes from output to outputbytes if we have available bytes // if buffer is not filled up. keep decoding until no input are available // if decodeBlock returns false. Throw an exception. int count = 0; do { int copied = 0; if (_uncompressedSize == -1) { copied = _output.CopyTo(bytes, offset, length); } else { if (_uncompressedSize > _currentInflatedCount) { length = (int)Math.Min(length, _uncompressedSize - _currentInflatedCount); copied = _output.CopyTo(bytes, offset, length); _currentInflatedCount += copied; } else { _state = InflaterState.Done; _output.ClearBytesUsed(); } } if (copied > 0) { offset += copied; count += copied; length -= copied; } if (length == 0) { // filled in the bytes array break; } // Decode will return false when more input is needed } while (!Finished() && Decode()); return(count); }
public int Inflate(Span <byte> bytes) { // copy bytes from output to outputbytes if we have available bytes // if buffer is not filled up. keep decoding until no input are available // if decodeBlock returns false. Throw an exception. int count = 0; do { int copied = 0; if (_uncompressedSize == -1) { copied = _output.CopyTo(bytes); } else { if (_uncompressedSize > _currentInflatedCount) { bytes = bytes.Slice(0, (int)Math.Min(bytes.Length, _uncompressedSize - _currentInflatedCount)); copied = _output.CopyTo(bytes); _currentInflatedCount += copied; } else { _state = InflaterState.Done; _output.ClearBytesUsed(); } } if (copied > 0) { bytes = bytes.Slice(copied, bytes.Length - copied); count += copied; } if (bytes.IsEmpty) { // filled in the bytes buffer break; } // Decode will return false when more input is needed } while (!Finished() && Decode()); return(count); }
private bool HandleCheckOneState(CompressionStream stream, out ErrorCode result) { result = ErrorCode.Ok; if (stream.InputCount == 0) { result = this.error; return(false); } this.error = this.startError; --stream.InputCount; ++stream.InputTotal; this.need += (uint)((ulong)stream.Input[stream.InputIndex++] & (ulong)byte.MaxValue); if ((int)this.was[0] != (int)this.need) { this.state = InflaterState.Error; stream.ErrorMessage = "incorrect data check"; this.marker = 5; return(true); } this.state = InflaterState.Done; return(true); }
public int SetDictionary(CompressionStream stream, byte[] dictionary, int dictLength) { int start = 0; int n = dictLength; if (stream == null || this.state != InflaterState.DictionaryZero) { return(-2); } if (Adler32.Get(dictionary, 0, dictLength) != stream.Checksum.Get()) { return(-3); } stream.Checksum = new Adler32(); if (n >= 1 << this.wbits) { n = (1 << this.wbits) - 1; start = dictLength - n; } this.blocks.SetDictionary(dictionary, start, n); this.state = InflaterState.Blocks; return(0); }
//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("Deflate64: unknown block type"); } } 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("Deflate64: 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)) { //if (_hasFormatReader) // _state = InflaterState.StartReadingFooter; //else _state = InflaterState.Done; } return(result); }
private void Reset() { _state = //_hasFormatReader ? //InflaterState.ReadingHeader : // start by reading Header info InflaterState.ReadingBFinal; // start by reading BFinal bit }
private bool DecodeBlock(out bool end_of_block_code_seen) { end_of_block_code_seen = false; int freeBytes = this.output.FreeBytes; while (freeBytes > 0x102) { int nextSymbol; int num4; switch (this.state) { case InflaterState.DecodeTop: nextSymbol = this.literalLengthTree.GetNextSymbol(this.input); if (nextSymbol >= 0) { break; } return false; case InflaterState.HaveInitialLength: goto Label_00C6; case InflaterState.HaveFullLength: goto Label_010B; case InflaterState.HaveDistCode: goto Label_016D; default: throw new InvalidDataException("Decoder is in some unknown state. This might be caused by corrupted data."); } if (nextSymbol < 0x100) { this.output.Write((byte)nextSymbol); freeBytes--; continue; } if (nextSymbol == 0x100) { end_of_block_code_seen = true; this.state = InflaterState.ReadingBFinal; return true; } nextSymbol -= 0x101; if (nextSymbol < 8) { nextSymbol += 3; this.extraBits = 0; } else if (nextSymbol == 0x1c) { nextSymbol = 0x102; this.extraBits = 0; } else { this.extraBits = extraLengthBits[nextSymbol]; } this.length = nextSymbol; Label_00C6: if (this.extraBits > 0) { this.state = InflaterState.HaveInitialLength; int bits = this.input.GetBits(this.extraBits); if (bits < 0) { return false; } this.length = lengthBase[this.length] + bits; } this.state = InflaterState.HaveFullLength; Label_010B: if (this.blockType == BlockType.Dynamic) { this.distanceCode = this.distanceTree.GetNextSymbol(this.input); } else { this.distanceCode = this.input.GetBits(5); if (this.distanceCode >= 0) { this.distanceCode = staticDistanceTreeTable[this.distanceCode]; } } if (this.distanceCode < 0) { return false; } this.state = InflaterState.HaveDistCode; Label_016D: if (this.distanceCode > 3) { this.extraBits = (this.distanceCode - 2) >> 1; int num5 = this.input.GetBits(this.extraBits); if (num5 < 0) { return false; } num4 = distanceBasePosition[this.distanceCode] + num5; } else { num4 = this.distanceCode + 1; } this.output.WriteLengthDistance(this.length, num4); freeBytes -= this.length; this.state = InflaterState.DecodeTop; } return true; }
bool DecodeBlock(out bool end_of_block_code_seen) { end_of_block_code_seen = false; int freeBytes = output.FreeBytes; // it is a little bit faster than frequently accessing the property while(freeBytes > 258) { // 258 means we can safely do decoding since maximum repeat length is 258 int symbol; switch (state) { case InflaterState.DecodeTop: symbol = literalLengthTree.GetNextSymbol(input); if( symbol < 0) { // running out of input return false; } if (symbol < 256) { // literal output.Write((byte)symbol); --freeBytes; } else if( symbol == 256) { // end of block end_of_block_code_seen = true; Debug.WriteLineIf(CompressionTracingSwitch.Informational, "End of Block", "Compression"); // Reset state state = InflaterState.ReadingBFinal; return true; // *********** } else { // length/distance pair symbol -= 257; // length code started at 257 if( symbol < 8) { symbol += 3; // match length = 3,4,5,6,7,8,9,10 extraBits = 0; } else if( symbol == 28) { // extra bits for code 285 is 0 symbol = 258; // code 285 means length 258 extraBits = 0; } else { extraBits = extraLengthBits[symbol]; Debug.Assert(extraBits != 0, "We handle other cases seperately!"); } length = symbol; goto case InflaterState.HaveInitialLength; } break; case InflaterState.HaveInitialLength: if( extraBits > 0) { state = InflaterState.HaveInitialLength; int bits = input.GetBits(extraBits); if( bits < 0) { return false; } length = lengthBase[length] + bits; } state = InflaterState.HaveFullLength; goto case InflaterState.HaveFullLength; case InflaterState.HaveFullLength: if( blockType == BlockType.Dynamic) { distanceCode = distanceTree.GetNextSymbol(input); } else { // get distance code directly for static block distanceCode = input.GetBits(5); if( distanceCode >= 0 ) { distanceCode = staticDistanceTreeTable[distanceCode]; } } if( distanceCode < 0) { // running out input return false; } state = InflaterState.HaveDistCode; goto case InflaterState.HaveDistCode; case InflaterState.HaveDistCode: // To avoid a table lookup we note that for distanceCode >= 2, // extra_bits = (distanceCode-2) >> 1 int offset; if( distanceCode > 3) { extraBits = (distanceCode-2) >> 1; int bits = input.GetBits(extraBits); if( bits < 0 ) { return false; } offset = distanceBasePosition[distanceCode] + bits; } else { offset = distanceCode + 1; } Debug.Assert(freeBytes>= 258, "following operation is not safe!"); output.WriteLengthDistance(length, offset); freeBytes -= length; state = InflaterState.DecodeTop; break; default: Debug.Assert(false, "check why we are here!"); throw new InvalidDataException(SR.GetString(SR.UnknownState)); } } 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; }
public void Reset() { if ( using_gzip) { gZipDecoder.Reset(); state = InflaterState.ReadingGZIPHeader; // start by reading GZip Header info streamSize = 0; crc32 = 0; } else { state = InflaterState.ReadingBFinal; // start by reading BFinal bit } }
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 DecodeUncompressedBlock(out bool end_of_block) { end_of_block = false; while (true) { switch (this.state) { case InflaterState.UncompressedAligning: this.input.SkipToByteBoundary(); this.state = InflaterState.UncompressedByte1; break; case InflaterState.UncompressedByte1: case InflaterState.UncompressedByte2: case InflaterState.UncompressedByte3: case InflaterState.UncompressedByte4: break; case InflaterState.DecodingUncompressed: { int num3 = this.output.CopyFrom(this.input, this.blockLength); this.blockLength -= num3; if (this.blockLength != 0) { return (this.output.FreeBytes == 0); } this.state = InflaterState.ReadingBFinal; end_of_block = true; return true; } default: throw new InvalidDataException("Decoder is in some unknown state. This might be caused by corrupted data."); } int bits = this.input.GetBits(8); if (bits < 0) { return false; } this.blockLengthBuffer[((int)this.state) - 0x10] = (byte)bits; if (this.state == InflaterState.UncompressedByte4) { this.blockLength = this.blockLengthBuffer[0] + (this.blockLengthBuffer[1] * 0x100); int num2 = this.blockLengthBuffer[2] + (this.blockLengthBuffer[3] * 0x100); if (((ushort)this.blockLength) != ((ushort)~num2)) { throw new InvalidDataException("Block length does not match with its complement."); } } this.state += 1; } }
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 DecodeBlock(out bool end_of_block_code_seen) { end_of_block_code_seen = false; int freeBytes = _output.FreeBytes; // it is a little bit faster than frequently accessing the property while (freeBytes > 258) { // 258 means we can safely do decoding since maximum repeat length is 258 int symbol; switch (_state) { case InflaterState.DecodeTop: // decode an element from the literal tree // TODO: optimize this!!! symbol = _literalLengthTree.GetNextSymbol(_input); if (symbol < 0) { // running out of input return false; } if (symbol < 256) { // literal _output.Write((byte)symbol); --freeBytes; } else if (symbol == 256) { // end of block end_of_block_code_seen = true; // Reset state _state = InflaterState.ReadingBFinal; return true; // *********** } else { // length/distance pair symbol -= 257; // length code started at 257 if (symbol < 8) { symbol += 3; // match length = 3,4,5,6,7,8,9,10 _extraBits = 0; } else if (!_deflate64 && symbol == 28) { // extra bits for code 285 is 0 symbol = 258; // code 285 means length 258 _extraBits = 0; } else { if (symbol < 0 || symbol >= s_extraLengthBits.Length) { throw new InvalidDataException(SR.GenericInvalidData); } _extraBits = s_extraLengthBits[symbol]; Debug.Assert(_extraBits != 0, "We handle other cases seperately!"); } _length = symbol; goto case InflaterState.HaveInitialLength; } break; case InflaterState.HaveInitialLength: if (_extraBits > 0) { _state = InflaterState.HaveInitialLength; int bits = _input.GetBits(_extraBits); if (bits < 0) { return false; } if (_length < 0 || _length >= s_lengthBase.Length) { throw new InvalidDataException(SR.GenericInvalidData); } _length = s_lengthBase[_length] + bits; } _state = InflaterState.HaveFullLength; goto case InflaterState.HaveFullLength; case InflaterState.HaveFullLength: if (_blockType == BlockType.Dynamic) { _distanceCode = _distanceTree.GetNextSymbol(_input); } else { // get distance code directly for static block _distanceCode = _input.GetBits(5); if (_distanceCode >= 0) { _distanceCode = s_staticDistanceTreeTable[_distanceCode]; } } if (_distanceCode < 0) { // running out input return false; } _state = InflaterState.HaveDistCode; goto case InflaterState.HaveDistCode; case InflaterState.HaveDistCode: // To avoid a table lookup we note that for distanceCode >= 2, // extra_bits = (distanceCode-2) >> 1 int offset; if (_distanceCode > 3) { _extraBits = (_distanceCode - 2) >> 1; int bits = _input.GetBits(_extraBits); if (bits < 0) { return false; } offset = s_distanceBasePosition[_distanceCode] + bits; } else { offset = _distanceCode + 1; } Debug.Assert(freeBytes >= 258, "following operation is not safe!"); _output.WriteLengthDistance(_length, offset); freeBytes -= _length; _state = InflaterState.DecodeTop; break; default: Debug.Assert(false, "check why we are here!"); throw new InvalidDataException(SR.UnknownState); } } 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; }
// 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_CODE_ORDER[_loopCounter]] = (byte)bits; ++_loopCounter; } for (int i = _codeLengthCodeCount; i < S_CODE_ORDER.Length; i++) { _codeLengthTreeCodeLength[S_CODE_ORDER[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*/ Assert(false, "check why we are here!"); throw new InvalidDataException("Deflate64: unknown state"); } byte[] literalTreeCodeLength = new byte[HuffmanTree.MAX_LITERAL_TREE_ELEMENTS]; byte[] distanceTreeCodeLength = new byte[HuffmanTree.MAX_DIST_TREE_ELEMENTS]; // 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.END_OF_BLOCK_CODE] == 0) { throw new InvalidDataException(); } _literalLengthTree = new HuffmanTree(literalTreeCodeLength); _distanceTree = new HuffmanTree(distanceTreeCodeLength); _state = InflaterState.DecodeTop; return(true); }
// Format of Non-compressed blocks (BTYPE=00): // // Any bits of input up to the next byte boundary are ignored. // The rest of the block consists of the following information: // // 0 1 2 3 4... // +---+---+---+---+================================+ // | LEN | NLEN |... LEN bytes of literal data...| // +---+---+---+---+================================+ // // LEN is the number of data bytes in the block. NLEN is the // one's complement of LEN. private bool DecodeUncompressedBlock(out bool endOfBlock) { endOfBlock = false; while (true) { switch (_state) { case InflaterState.UncompressedAligning: // initial state when calling this function // we must skip to a byte boundary _input.SkipToByteBoundary(); _state = InflaterState.UncompressedByte1; goto case InflaterState.UncompressedByte1; case InflaterState.UncompressedByte1: // decoding block length case InflaterState.UncompressedByte2: case InflaterState.UncompressedByte3: case InflaterState.UncompressedByte4: int bits = _input.GetBits(8); if (bits < 0) { return(false); } _blockLengthBuffer[_state - InflaterState.UncompressedByte1] = (byte)bits; if (_state == InflaterState.UncompressedByte4) { _blockLength = _blockLengthBuffer[0] + ((int)_blockLengthBuffer[1]) * 256; int blockLengthComplement = _blockLengthBuffer[2] + ((int)_blockLengthBuffer[3]) * 256; // make sure complement matches if ((ushort)_blockLength != (ushort)(~blockLengthComplement)) { throw new InvalidDataException("Deflate64: invalid block length"); } } _state += 1; break; case InflaterState.DecodingUncompressed: // copying block data // Directly copy bytes from input to output. int bytesCopied = _output.CopyFrom(_input, _blockLength); _blockLength -= bytesCopied; if (_blockLength == 0) { // Done with this block, need to re-init bit buffer for next block _state = InflaterState.ReadingBFinal; endOfBlock = true; return(true); } // We can fail to copy all bytes for two reasons: // Running out of Input // running out of free space in output window if (_output.FreeBytes == 0) { return(true); } return(false); default: Debug./*Fail*/ Assert(false, "check why we are here!"); throw new InvalidDataException("Deflate64: unknown state"); } } }
private bool DecodeBlock(out bool endOfBlockCodeSeen) { endOfBlockCodeSeen = false; int freeBytes = _output.FreeBytes; // it is a little bit faster than frequently accessing the property while (freeBytes > 65536) { // With Deflate64 we can have up to a 64kb length, so we ensure at least that much space is available // in the OutputWindow to avoid overwriting previous unflushed output data. int symbol; switch (_state) { case InflaterState.DecodeTop: // decode an element from the literal tree // TODO: optimize this!!! symbol = _literalLengthTree.GetNextSymbol(_input); if (symbol < 0) { // running out of input return(false); } if (symbol < 256) { // literal _output.Write((byte)symbol); --freeBytes; } else if (symbol == 256) { // end of block endOfBlockCodeSeen = true; // Reset state _state = InflaterState.ReadingBFinal; return(true); } else { // length/distance pair symbol -= 257; // length code started at 257 if (symbol < 8) { symbol += 3; // match length = 3,4,5,6,7,8,9,10 _extraBits = 0; } else if (!_deflate64 && symbol == 28) { // extra bits for code 285 is 0 symbol = 258; // code 285 means length 258 _extraBits = 0; } else { if (symbol < 0 || symbol >= S_EXTRA_LENGTH_BITS.Length) { throw new InvalidDataException("Deflate64: invalid data"); } _extraBits = S_EXTRA_LENGTH_BITS[symbol]; Debug.Assert(_extraBits != 0, "We handle other cases separately!"); } _length = symbol; goto case InflaterState.HaveInitialLength; } break; case InflaterState.HaveInitialLength: if (_extraBits > 0) { _state = InflaterState.HaveInitialLength; int bits = _input.GetBits(_extraBits); if (bits < 0) { return(false); } if (_length < 0 || _length >= S_LENGTH_BASE.Length) { throw new InvalidDataException("Deflate64: invalid data"); } _length = S_LENGTH_BASE[_length] + bits; } _state = InflaterState.HaveFullLength; goto case InflaterState.HaveFullLength; case InflaterState.HaveFullLength: if (_blockType == BlockType.Dynamic) { _distanceCode = _distanceTree.GetNextSymbol(_input); } else { // get distance code directly for static block _distanceCode = _input.GetBits(5); if (_distanceCode >= 0) { _distanceCode = S_STATIC_DISTANCE_TREE_TABLE[_distanceCode]; } } if (_distanceCode < 0) { // running out input return(false); } _state = InflaterState.HaveDistCode; goto case InflaterState.HaveDistCode; case InflaterState.HaveDistCode: // To avoid a table lookup we note that for distanceCode > 3, // extra_bits = (distanceCode-2) >> 1 int offset; if (_distanceCode > 3) { _extraBits = (_distanceCode - 2) >> 1; int bits = _input.GetBits(_extraBits); if (bits < 0) { return(false); } offset = S_DISTANCE_BASE_POSITION[_distanceCode] + bits; } else { offset = _distanceCode + 1; } _output.WriteLengthDistance(_length, offset); freeBytes -= _length; _state = InflaterState.DecodeTop; break; default: Debug./*Fail*/ Assert(false, "check why we are here!"); throw new InvalidDataException("Deflate64: unknown state"); } } return(true); }
private void Reset() { if (this.hasFormatReader) { this.state = InflaterState.ReadingHeader; } else { this.state = InflaterState.ReadingBFinal; } }
private void Reset() { _state = _hasFormatReader ? InflaterState.ReadingHeader : InflaterState.ReadingBFinal; }
// Format of Non-compressed blocks (BTYPE=00): // // Any bits of input up to the next byte boundary are ignored. // The rest of the block consists of the following information: // // 0 1 2 3 4... // +---+---+---+---+================================+ // | LEN | NLEN |... LEN bytes of literal data...| // +---+---+---+---+================================+ // // LEN is the number of data bytes in the block. NLEN is the // one's complement of LEN. private bool DecodeUncompressedBlock(out bool end_of_block) { end_of_block = false; while (true) { switch (_state) { case InflaterState.UncompressedAligning: // intial state when calling this function // we must skip to a byte boundary _input.SkipToByteBoundary(); _state = InflaterState.UncompressedByte1; goto case InflaterState.UncompressedByte1; case InflaterState.UncompressedByte1: // decoding block length case InflaterState.UncompressedByte2: case InflaterState.UncompressedByte3: case InflaterState.UncompressedByte4: int bits = _input.GetBits(8); if (bits < 0) { return false; } _blockLengthBuffer[_state - InflaterState.UncompressedByte1] = (byte)bits; if (_state == InflaterState.UncompressedByte4) { _blockLength = _blockLengthBuffer[0] + ((int)_blockLengthBuffer[1]) * 256; int blockLengthComplement = _blockLengthBuffer[2] + ((int)_blockLengthBuffer[3]) * 256; // make sure complement matches if ((ushort)_blockLength != (ushort)(~blockLengthComplement)) { throw new InvalidDataException(SR.InvalidBlockLength); } } _state += 1; break; case InflaterState.DecodingUncompressed: // copying block data // Directly copy bytes from input to output. int bytesCopied = _output.CopyFrom(_input, _blockLength); _blockLength -= bytesCopied; if (_blockLength == 0) { // Done with this block, need to re-init bit buffer for next block _state = InflaterState.ReadingBFinal; end_of_block = true; return true; } // We can fail to copy all bytes for two reasons: // Running out of Input // running out of free space in output window if (_output.FreeBytes == 0) { return true; } return false; default: Debug.Assert(false, "check why we are here!"); throw new InvalidDataException(SR.UnknownState); } } }
//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; }
// 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; }