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); }
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 > 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 Debug.Assert(_literalLengthTree != null); // 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 ((uint)symbol >= ExtraLengthBits.Length) { throw new InvalidDataException(SR.GenericInvalidData); } _extraBits = ExtraLengthBits[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_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) { Debug.Assert(_distanceTree != null); _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 > 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_distanceBasePosition[_distanceCode] + bits; } else { offset = _distanceCode + 1; } _output.WriteLengthDistance(_length, offset); freeBytes -= _length; _state = InflaterState.DecodeTop; break; default: Debug.Fail("check why we are here!"); throw new InvalidDataException(SR.UnknownState); } } return(true); }