/// <summary>
/// Deflates the current input block to the given array. It returns
/// the number of bytes compressed, or 0 if either
/// needsInput() or finished() returns true or length is zero.
/// </summary>
/// <param name="output">
/// the buffer where to write the compressed data.
/// </param>
/// <param name="offset">
/// the offset into the output array.
/// </param>
/// <param name="length">
/// the maximum number of bytes that may be written.
/// </param>
/// <exception cref="System.InvalidOperationException">
/// if end() was called.
/// </exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// if offset and/or length don't match the array length.
/// </exception>
public int Deflate(byte[] output, int offset, int length)
{
int origLength = length;
if (state == CLOSED_STATE)
{
throw new InvalidOperationException("Deflater closed");
}
if (state < BUSY_STATE)
{
/* output header */
int header = (DEFLATED +
((DeflaterConstants.MAX_WBITS - 8) << 4)) << 8;
int level_flags = (level - 1) >> 1;
if (level_flags < 0 || level_flags > 3)
{
level_flags = 3;
}
header |= level_flags << 6;
if ((state & IS_SETDICT) != 0)
{
/* Dictionary was set */
header |= DeflaterConstants.PRESET_DICT;
}
header += 31 - (header % 31);
pending.WriteShortMSB(header);
if ((state & IS_SETDICT) != 0)
{
int chksum = engine.Adler;
engine.ResetAdler();
pending.WriteShortMSB(chksum >> 16);
pending.WriteShortMSB(chksum & 0xffff);
}
state = BUSY_STATE | (state & (IS_FLUSHING | IS_FINISHING));
}
for (;;)
{
int count = pending.Flush(output, offset, length);
offset += count;
totalOut += count;
length -= count;
if (length == 0 || state == FINISHED_STATE)
{
break;
}
if (!engine.Deflate((state & IS_FLUSHING) != 0, (state & IS_FINISHING) != 0))
{
if (state == BUSY_STATE)
{
/* We need more input now */
return(origLength - length);
}
else if (state == FLUSHING_STATE)
{
if (level != NO_COMPRESSION)
{
/* We have to supply some lookahead. 8 bit lookahead
* are needed by the zlib inflater, and we must fill
* the next byte, so that all bits are flushed.
*/
int neededbits = 8 + ((-pending.BitCount) & 7);
while (neededbits > 0)
{
/* write a static tree block consisting solely of
* an EOF:
*/
pending.WriteBits(2, 10);
neededbits -= 10;
}
}
state = BUSY_STATE;
}
else if (state == FINISHING_STATE)
{
pending.AlignToByte();
/* We have completed the stream */
if (!noHeader)
{
int adler = engine.Adler;
pending.WriteShortMSB(adler >> 16);
pending.WriteShortMSB(adler & 0xffff);
}
state = FINISHED_STATE;
}
}
}
return(origLength - length);
}