private void QuickEndBlock(Trees.CodeData *lTree, bool last) { if (this.blockOpen) { Trees.Tr_emit_end_block(this, lTree, last); this.blockStart = this.strStart; this.blockOpen = false; } }
private bool Tr_tally_dist(int dist, int len) { byte *pending = this.DynamicBuffers.PendingPointer; int dbuffindex = this.dBuf + (this.lastLit * 2); pending[dbuffindex++] = (byte)(dist >> 8); pending[dbuffindex] = (byte)dist; pending[this.lBuf + this.lastLit++] = (byte)len; this.matches++; // Here, lc is the match length - MINMATCH dist--; // dist = match distance - 1 this.DynLTree[Trees.GetLengthCode(len) + LITERALS + 1].Freq++; this.DynDTree[Trees.GetDistanceCode(dist)].Freq++; return(this.lastLit == this.litBufsize - 1); }
private void DeflateReset(ZLibStream zStream) { zStream.TotalIn = zStream.TotalOut = 0; zStream.Message = null; zStream.DataType = ZUNKNOWN; this.Pending = 0; this.PendingOut = 0; if (this.NoHeader < 0) { this.NoHeader = 0; // was set to -1 by deflate(..., Z_FINISH); } this.status = (this.NoHeader != 0) ? BUSYSTATE : INITSTATE; zStream.Adler = Adler32.SeedValue; this.lastFlush = FlushMode.NoFlush; Trees.Tr_init(this); this.Lm_init(); }
private CompressionState DeflateReset(ZStream strm) { strm.TotalIn = strm.TotalOut = 0; strm.Msg = null; strm.DataType = ZUNKNOWN; this.Pending = 0; this.PendingOut = 0; if (this.Noheader < 0) { this.Noheader = 0; // was set to -1 by deflate(..., Z_FINISH); } this.status = (this.Noheader != 0) ? BUSYSTATE : INITSTATE; strm.Adler = Adler32.SeedValue; this.lastFlush = FlushStrategy.NoFlush; Trees.Tr_init(this); this.Lm_init(); return(CompressionState.ZOK); }
private void Flush_block_only(bool eof) { Trees.Tr_flush_block(this, this.blockStart >= 0 ? this.blockStart : -1, this.strStart - this.blockStart, eof); this.blockStart = this.strStart; this.Flush_pending(this.strm); }
public CompressionState Compress(ZLibStream zStream, FlushMode flush) { FlushMode old_flush; if (flush > FlushMode.Finish || flush < 0) { return(CompressionState.ZSTREAMERROR); } if (zStream.NextOut == null || (zStream.NextIn == null && zStream.AvailableIn != 0) || (this.status == FINISHSTATE && flush != FlushMode.Finish)) { zStream.Message = ZErrmsg[CompressionState.ZNEEDDICT - CompressionState.ZSTREAMERROR]; return(CompressionState.ZSTREAMERROR); } if (zStream.AvailableOut == 0) { zStream.Message = ZErrmsg[CompressionState.ZNEEDDICT - CompressionState.ZBUFERROR]; return(CompressionState.ZBUFERROR); } this.strm = zStream; // just in case old_flush = this.lastFlush; this.lastFlush = flush; // Write the zlib header if (this.status == INITSTATE) { int header = (ZDEFLATED + ((this.wBits - 8) << 4)) << 8; int level_flags = (((int)this.level - 1) & 0xff) >> 1; if (level_flags > 3) { level_flags = 3; } header |= level_flags << 6; if (this.strStart != 0) { header |= PRESETDICT; } header += 31 - (header % 31); this.status = BUSYSTATE; this.PutShortMSB(header); // Save the adler32 of the preset dictionary: if (this.strStart != 0) { this.PutShortMSB((int)zStream.Adler >> 16); this.PutShortMSB((int)zStream.Adler); } zStream.Adler = Adler32.SeedValue; } // Flush as much pending output as possible if (this.Pending != 0) { this.Flush_pending(zStream); if (zStream.AvailableOut == 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: this.lastFlush = (FlushMode)(-1); return(CompressionState.ZOK); } // 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 (zStream.AvailableIn == 0 && flush <= old_flush && flush != FlushMode.Finish) { zStream.Message = ZErrmsg[CompressionState.ZNEEDDICT - CompressionState.ZBUFERROR]; return(CompressionState.ZBUFERROR); } // User must not provide more input after the first FINISH: if (this.status == FINISHSTATE && zStream.AvailableIn != 0) { zStream.Message = ZErrmsg[CompressionState.ZNEEDDICT - CompressionState.ZBUFERROR]; return(CompressionState.ZBUFERROR); } // Start a new block or continue the current one. if (zStream.AvailableIn != 0 || this.lookahead != 0 || (flush != FlushMode.NoFlush && this.status != FINISHSTATE)) { int bstate = -1; if (this.Strategy == CompressionStrategy.Rle) { bstate = this.DeflateRle(flush); } else { switch (ConfigTable[(int)this.level].Func) { case STORED: bstate = this.DeflateStored(flush); break; case FAST: bstate = this.DeflateFast(flush); break; case SLOW: bstate = this.DeflateSlow(flush); break; case QUICK: bstate = this.DeflateQuick(flush); break; } } if (bstate == FinishStarted || bstate == FinishDone) { this.status = FINISHSTATE; } if (bstate == NeedMore || bstate == FinishStarted) { if (zStream.AvailableOut == 0) { this.lastFlush = (FlushMode)(-1); // avoid BUF_ERROR next call, see above } return(CompressionState.ZOK); // 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 == FlushMode.PartialFlush) { Trees.Tr_align(this); } else { // FULL_FLUSH or SYNC_FLUSH Trees.Tr_stored_block(this, 0, 0, false); // For a full flush, this empty block will be recognized // as a special marker by inflate_sync(). if (flush == FlushMode.FullFlush) { // state.head[s.hash_size-1]=0; ushort *head = this.DynamicBuffers.HeadPointer; for (int i = 0; i < this.hashSize; i++) { // forget history head[i] = 0; } } } this.Flush_pending(zStream); if (zStream.AvailableOut == 0) { this.lastFlush = (FlushMode)(-1); // avoid BUF_ERROR at next call, see above return(CompressionState.ZOK); } } } if (flush != FlushMode.Finish) { return(CompressionState.ZOK); } if (this.NoHeader != 0) { return(CompressionState.ZSTREAMEND); } // Write the zlib trailer (adler32) this.PutShortMSB((int)zStream.Adler >> 16); this.PutShortMSB((int)zStream.Adler); this.Flush_pending(zStream); // If avail_out is zero, the application will call deflate again // to flush the rest. this.NoHeader = -1; // write the trailer only once! return(this.Pending != 0 ? CompressionState.ZOK : CompressionState.ZSTREAMEND); }
/// <summary> /// The deflate_quick deflate strategy, designed to be used when cycles are /// at a premium. /// </summary> /// <param name="flush">The flush strategy.</param> /// <returns>The <see cref="int"/>.</returns> internal int DeflateQuick(FlushStrategy flush) { int hash_head; // head of the hash chain int dist; int matchLen; bool last; byte * window = this.DynBuffers.WindowPointer; ushort *head = this.DynBuffers.HeadPointer; ushort *prev = this.DynBuffers.PrevPointer; fixed(Trees.CodeData *ltree = &Trees.StaticLTreeDesc.GetCodeDataReference()) fixed(Trees.CodeData * dtree = &Trees.StaticDTreeDesc.GetCodeDataReference()) { if (!this.blockOpen && this.lookahead > 0) { // Start new block when we have lookahead data, so that if no // input data is given an empty block will not be written. last = flush == FlushStrategy.Finish; this.QuickStartBlock(last); } int pendingBufferSize = this.DynBuffers.PendingSize; do { if (this.Pending + 12 >= pendingBufferSize) { this.Flush_pending(this.strm); if (this.strm.AvailIn == 0 && flush != FlushStrategy.Finish) { // Break to emit end block and return need_more break; } } if (this.lookahead < MINLOOKAHEAD) { this.Fill_window(); if (this.lookahead < MINLOOKAHEAD && flush == FlushStrategy.NoFlush) { // Always emit end block, in case next call is with Z_FINISH // and we need to emit start of last block this.QuickEndBlock(ltree, false); return(NeedMore); } if (this.lookahead == 0) { break; } if (!this.blockOpen) { // Start new block when we have lookahead data, so that if no // input data is given an empty block will not be written. last = flush == FlushStrategy.Finish; this.QuickStartBlock(last); } } if (this.lookahead >= MINMATCH) { hash_head = this.InsertString(prev, head, window, this.strStart); dist = this.strStart - hash_head; if (dist > 0 && dist < this.wSize - MINLOOKAHEAD) { matchLen = Compare258(window + this.strStart, window + hash_head); if (matchLen >= MINMATCH) { if (matchLen > this.lookahead) { matchLen = this.lookahead; } Trees.Tr_emit_distance(this, ltree, dtree, matchLen - MINMATCH, dist); this.lookahead -= matchLen; this.strStart += matchLen; continue; } } } this.Send_code(window[this.strStart], ltree); // send a literal byte this.strStart++; this.lookahead--; }while (this.strm.AvailOut != 0); last = flush == FlushStrategy.Finish; this.QuickEndBlock(ltree, last); this.Flush_pending(this.strm); if (last) { return(this.strm.AvailOut == 0 ? this.strm.AvailIn == 0 ? FinishStarted : NeedMore : FinishDone); } return(BlockDone); } }
private void QuickStartBlock(bool last) { Trees.Tr_emit_tree(this, STATICTREES, last); this.blockStart = this.strStart; this.blockOpen = true; }