flush_pending() private method

private flush_pending ( ) : void
return void
Example #1
0
        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;
        }