internal int Deflate(ZlibCodec strm, int flush)
{
int old_flush;
if (flush > ZlibConstants.Z_FINISH || flush < 0) {
throw new ZlibException (String.Format ("Flush value is invalid. Should be 0 < x < {0}", ZlibConstants.Z_FINISH));
//return ZlibConstants.Z_STREAM_ERROR;
}
if (strm.OutputBuffer == null || (strm.InputBuffer == null && strm.AvailableBytesIn != 0) || (status == FINISH_STATE && flush != ZlibConstants.Z_FINISH)) {
strm.Message = z_errmsg [ZlibConstants.Z_NEED_DICT - (ZlibConstants.Z_STREAM_ERROR)];
throw new ZlibException (String.Format ("Something is fishy. [{0}]", strm.Message));
//return ZlibConstants.Z_STREAM_ERROR;
}
if (strm.AvailableBytesOut == 0) {
strm.Message = z_errmsg [ZlibConstants.Z_NEED_DICT - (ZlibConstants.Z_BUF_ERROR)];
throw new ZlibException ("OutputBuffer is full (AvailableBytesOut == 0)");
//return ZlibConstants.Z_BUF_ERROR;
}
this.strm = strm; // just in case
old_flush = last_flush;
last_flush = flush;
// Write the zlib header
if (status == INIT_STATE) {
int header = (Z_DEFLATED + ((w_bits - 8) << 4)) << 8;
int level_flags = (((int)compressionLevel - 1) & 0xff) >> 1;
if (level_flags > 3)
level_flags = 3;
header |= (level_flags << 6);
if (strstart != 0)
header |= PRESET_DICT;
header += 31 - (header % 31);
status = BUSY_STATE;
putShortMSB (header);
// Save the adler32 of the preset dictionary:
if (strstart != 0) {
putShortMSB ((int)(SharedUtils.URShift (strm._Adler32, 16)));
putShortMSB ((int)(strm._Adler32 & 0xffff));
}
strm._Adler32 = Adler.Adler32 (0, null, 0, 0);
}
// Flush as much pending output as possible
if (pendingCount != 0) {
strm.flush_pending ();
if (strm.AvailableBytesOut == 0) {
//System.out.println(" avail_out==0");
// Since avail_out is 0, deflate will be called again with
// more output space, but possibly with both pending and
// avail_in equal to zero. There won't be anything to do,
// but this is not an error situation so make sure we
// return OK instead of BUF_ERROR at next call of deflate:
last_flush = - 1;
return ZlibConstants.Z_OK;
}
// Make sure there is something to do and avoid duplicate consecutive
// flushes. For repeated and useless calls with Z_FINISH, we keep
// returning Z_STREAM_END instead of Z_BUFF_ERROR.
} else if (strm.AvailableBytesIn == 0 && flush <= old_flush && flush != ZlibConstants.Z_FINISH) {
strm.Message = z_errmsg [ZlibConstants.Z_NEED_DICT - (ZlibConstants.Z_BUF_ERROR)];
throw new ZlibException ("AvailableBytesOut == 0 && flush<=old_flush && flush != ZlibConstants.Z_FINISH");
//return ZlibConstants.Z_BUF_ERROR;
}
// User must not provide more input after the first FINISH:
if (status == FINISH_STATE && strm.AvailableBytesIn != 0) {
strm.Message = z_errmsg [ZlibConstants.Z_NEED_DICT - (ZlibConstants.Z_BUF_ERROR)];
throw new ZlibException ("status == FINISH_STATE && strm.AvailableBytesIn != 0");
//return ZlibConstants.Z_BUF_ERROR;
}
// Start a new block or continue the current one.
if (strm.AvailableBytesIn != 0 || lookahead != 0 || (flush != ZlibConstants.Z_NO_FLUSH && status != FINISH_STATE)) {
int bstate = - 1;
switch (configTable [(int)compressionLevel].func) {
case STORED:
bstate = DeflateNone (flush);
break;
case FAST:
bstate = DeflateFast (flush);
break;
case SLOW:
bstate = DeflateSlow (flush);
break;
default:
break;
}
if (bstate == FinishStarted || bstate == FinishDone) {
status = FINISH_STATE;
}
if (bstate == NeedMore || bstate == FinishStarted) {
if (strm.AvailableBytesOut == 0) {
last_flush = - 1; // avoid BUF_ERROR next call, see above
}
return ZlibConstants.Z_OK;
// If flush != Z_NO_FLUSH && avail_out == 0, the next call
// of deflate should use the same flush parameter to make sure
// that the flush is complete. So we don't have to output an
// empty block here, this will be done at next call. This also
// ensures that for a very small output buffer, we emit at most
// one empty block.
}
if (bstate == BlockDone) {
if (flush == ZlibConstants.Z_PARTIAL_FLUSH) {
_tr_align ();
} else {
// FULL_FLUSH or SYNC_FLUSH
_tr_stored_block (0, 0, false);
// For a full flush, this empty block will be recognized
// as a special marker by inflate_sync().
if (flush == ZlibConstants.Z_FULL_FLUSH) {
//state.head[s.hash_size-1]=0;
for (int i = 0; i < hash_size; i++)
// forget history
head [i] = 0;
}
}
strm.flush_pending ();
if (strm.AvailableBytesOut == 0) {
last_flush = - 1; // avoid BUF_ERROR at next call, see above
return ZlibConstants.Z_OK;
}
}
}
if (flush != ZlibConstants.Z_FINISH)
return ZlibConstants.Z_OK;
if (!WantRfc1950HeaderBytes || Rfc1950BytesEmitted)
return ZlibConstants.Z_STREAM_END;
// Write the zlib trailer (adler32)
putShortMSB ((int)(SharedUtils.URShift (strm._Adler32, 16)));
putShortMSB ((int)(strm._Adler32 & 0xffff));
strm.flush_pending ();
// If avail_out is zero, the application will call deflate again
// to flush the rest.
Rfc1950BytesEmitted = true; // write the trailer only once!
return pendingCount != 0 ? ZlibConstants.Z_OK : ZlibConstants.Z_STREAM_END;
}