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);
}