/// <summary> /// Performs data compression with the deflate algorithm /// </summary> internal int deflate(ZStream strm, FlushStrategy f) { int old_flush; int internalFlush = (int)f; if (internalFlush > (int)FlushStrategy.Z_FINISH || internalFlush < 0) { return (int)ZLibResultCode.Z_STREAM_ERROR; } if (strm.next_out == null || (strm.next_in == null && strm.avail_in != 0) || (status == DeflateState.FINISH_STATE && internalFlush != (int)FlushStrategy.Z_FINISH)) { strm.msg = ZLibUtil.z_errmsg[(int)ZLibResultCode.Z_NEED_DICT - ((int)ZLibResultCode.Z_STREAM_ERROR)]; return (int)ZLibResultCode.Z_STREAM_ERROR; } if (strm.avail_out == 0) { strm.msg = ZLibUtil.z_errmsg[(int)ZLibResultCode.Z_NEED_DICT - ((int)ZLibResultCode.Z_BUF_ERROR)]; return (int)ZLibResultCode.Z_DATA_ERROR; } this.strm = strm; // just in case old_flush = last_flush; last_flush = internalFlush; // Write the zlib header if (status == DeflateState.INIT_STATE) { int header = (Z_DEFLATED + ((w_bits - 8) << 4)) << 8; int level_flags = ((level - 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 = DeflateState.BUSY_STATE; putShortMSB(header); // Save the adler32 of the preset dictionary: if (strstart != 0) { putShortMSB((int)(ZLibUtil.URShift(strm.adler, 16))); putShortMSB((int)(strm.adler & 0xffff)); } strm.adler = Adler32.GetAdler32Checksum(0, null, 0, 0); } // Flush as much pending output as possible if (pending != 0) { strm.flush_pending(); if (strm.avail_out == 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 (int)ZLibResultCode.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 (int)ZLibResultCode.Z_STREAM_END instead of Z_BUFF_ERROR. } else if (strm.avail_in == 0 && internalFlush <= old_flush && internalFlush != (int)FlushStrategy.Z_FINISH) { strm.msg = ZLibUtil.z_errmsg[(int)ZLibResultCode.Z_NEED_DICT - ((int)ZLibResultCode.Z_BUF_ERROR)]; return (int)ZLibResultCode.Z_DATA_ERROR; } // User must not provide more input after the first FINISH: if (status == DeflateState.FINISH_STATE && strm.avail_in != 0) { strm.msg = ZLibUtil.z_errmsg[(int)ZLibResultCode.Z_NEED_DICT - ((int)ZLibResultCode.Z_BUF_ERROR)]; return (int)ZLibResultCode.Z_DATA_ERROR; } // Start a new block or continue the current one. if (strm.avail_in != 0 || lookahead != 0 || (internalFlush != (int)FlushStrategy.Z_NO_FLUSH && status != DeflateState.FINISH_STATE)) { int bstate = - 1; switch (config_table[level].func) { case STORED: bstate = deflate_stored(internalFlush); break; case FAST: bstate = deflate_fast(internalFlush); break; case SLOW: bstate = deflate_slow(internalFlush); break; default: break; } if (bstate == FinishStarted || bstate == FinishDone) { status = DeflateState.FINISH_STATE; } if (bstate == NeedMore || bstate == FinishStarted) { if (strm.avail_out == 0) { last_flush = -1; // avoid BUF_ERROR next call, see above } return (int)ZLibResultCode.Z_OK; // If internalFlush != Z_NO_FLUSH && _avail_out == 0, the next call // of deflate should use the same internalFlush parameter to make sure // that the internalFlush 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 (internalFlush == (int)FlushStrategy.Z_PARTIAL_FLUSH) { _tr_align(); } else { // FULL_FLUSH or SYNC_FLUSH _tr_stored_block(0, 0, false); // For a full internalFlush, this empty block will be recognized // as a special marker by inflate_sync(). if (internalFlush == (int)FlushStrategy.Z_FULL_FLUSH) { for (int i = 0; i < hash_size; i++) // forget history head[i] = 0; } } strm.flush_pending(); if (strm.avail_out == 0) { last_flush = -1; // avoid BUF_ERROR at next call, see above return (int)ZLibResultCode.Z_OK; } } } if (internalFlush != (int)FlushStrategy.Z_FINISH) return (int)ZLibResultCode.Z_OK; if (NoHeader != 0) return (int)ZLibResultCode.Z_STREAM_END; // Write the zlib trailer (adler32) putShortMSB((int) (ZLibUtil.URShift(strm.adler, 16))); putShortMSB((int) (strm.adler & 0xffff)); strm.flush_pending(); // If _avail_out is zero, the application will call deflate again // to internalFlush the rest. NoHeader = - 1; // WritePos the trailer only once! return pending != 0 ? (int)ZLibResultCode.Z_OK : (int)ZLibResultCode.Z_STREAM_END; }
/// <summary> /// Resets the current state of deflate object /// </summary> internal int deflateReset(ZStream strm) { strm.total_in = strm.total_out = 0; strm.msg = null; // strm.Data_type = BlockType.Z_UNKNOWN; pending = 0; Pending_out = 0; if (NoHeader < 0) { NoHeader = 0; // was set to -1 by deflate(..., Z_FINISH); } status = (NoHeader != 0) ? DeflateState.BUSY_STATE : DeflateState.INIT_STATE; strm.adler = Adler32.GetAdler32Checksum(0, null, 0, 0); last_flush = (int)FlushStrategy.Z_NO_FLUSH; tr_init(); lm_init(); return (int)ZLibResultCode.Z_OK; }