Ionic.Zlib.DeflateManager.Deflate C# (CSharp) Method

Deflate() private method

private Deflate ( FlushType flush ) : int
flush FlushType
return int
        internal int Deflate(FlushType flush)
        {
            int old_flush;

            if (_codec.OutputBuffer == null ||
                (_codec.InputBuffer == null && _codec.AvailableBytesIn != 0) ||
                (status == FINISH_STATE && flush != FlushType.Finish))
            {
                _codec.Message = _ErrorMessage[ZlibConstants.Z_NEED_DICT - (ZlibConstants.Z_STREAM_ERROR)];
                throw new ZlibException(String.Format("Something is fishy. [{0}]", _codec.Message));
            }
            if (_codec.AvailableBytesOut == 0)
            {
                _codec.Message = _ErrorMessage[ZlibConstants.Z_NEED_DICT - (ZlibConstants.Z_BUF_ERROR)];
                throw new ZlibException("OutputBuffer is full (AvailableBytesOut == 0)");
            }

            old_flush = last_flush;
            last_flush = (int)flush;

            // Write the zlib (rfc1950) header bytes
            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);
                unchecked
                {
                    pending[pendingCount++] = (byte)(header >> 8);
                    pending[pendingCount++] = (byte)header;
                }
                // Save the adler32 of the preset dictionary:
                if (strstart != 0)
                {
                    pending[pendingCount++] = (byte)((_codec._Adler32 & 0xFF000000) >> 24);
                    pending[pendingCount++] = (byte)((_codec._Adler32 & 0x00FF0000) >> 16);
                    pending[pendingCount++] = (byte)((_codec._Adler32 & 0x0000FF00) >> 8);
                    pending[pendingCount++] = (byte)(_codec._Adler32 & 0x000000FF);
                }
                _codec._Adler32 = Adler.Adler32(0, null, 0, 0);
            }

            // Flush as much pending output as possible
            if (pendingCount != 0)
            {
                _codec.flush_pending();
                if (_codec.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 (_codec.AvailableBytesIn == 0 &&
                     (int)flush <= old_flush &&
                     flush != FlushType.Finish)
            {
                // workitem 8557
                //
                // Not sure why this needs to be an error.  pendingCount == 0, which
                // means there's nothing to deflate.  And the caller has not asked
                // for a FlushType.Finish, but...  that seems very non-fatal.  We
                // can just say "OK" and do nothing.

                // _codec.Message = z_errmsg[ZlibConstants.Z_NEED_DICT - (ZlibConstants.Z_BUF_ERROR)];
                // throw new ZlibException("AvailableBytesIn == 0 && flush<=old_flush && flush != FlushType.Finish");

                return ZlibConstants.Z_OK;
            }

            // User must not provide more input after the first FINISH:
            if (status == FINISH_STATE && _codec.AvailableBytesIn != 0)
            {
                _codec.Message = _ErrorMessage[ZlibConstants.Z_NEED_DICT - (ZlibConstants.Z_BUF_ERROR)];
                throw new ZlibException("status == FINISH_STATE && _codec.AvailableBytesIn != 0");
            }

            // Start a new block or continue the current one.
            if (_codec.AvailableBytesIn != 0 || lookahead != 0 || (flush != FlushType.None && status != FINISH_STATE))
            {
                BlockState bstate = DeflateFunction(flush);

                if (bstate == BlockState.FinishStarted || bstate == BlockState.FinishDone)
                {
                    status = FINISH_STATE;
                }
                if (bstate == BlockState.NeedMore || bstate == BlockState.FinishStarted)
                {
                    if (_codec.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 == BlockState.BlockDone)
                {
                    if (flush == FlushType.Partial)
                    {
                        _tr_align();
                    }
                    else
                    {
                        // FlushType.Full or FlushType.Sync
                        _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 == FlushType.Full)
                        {
                            // clear hash (forget the history)
                            for (int i = 0; i < hash_size; i++)
                                head[i] = 0;
                        }
                    }
                    _codec.flush_pending();
                    if (_codec.AvailableBytesOut == 0)
                    {
                        last_flush = -1; // avoid BUF_ERROR at next call, see above
                        return ZlibConstants.Z_OK;
                    }
                }
            }

            if (flush != FlushType.Finish)
                return ZlibConstants.Z_OK;

            if (!WantRfc1950HeaderBytes || Rfc1950BytesEmitted)
                return ZlibConstants.Z_STREAM_END;

            // Write the zlib trailer (adler32)
            pending[pendingCount++] = (byte)((_codec._Adler32 & 0xFF000000) >> 24);
            pending[pendingCount++] = (byte)((_codec._Adler32 & 0x00FF0000) >> 16);
            pending[pendingCount++] = (byte)((_codec._Adler32 & 0x0000FF00) >> 8);
            pending[pendingCount++] = (byte)(_codec._Adler32 & 0x000000FF);
            //putShortMSB((int)(SharedUtils.URShift(_codec._Adler32, 16)));
            //putShortMSB((int)(_codec._Adler32 & 0xffff));

            _codec.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;
        }

Usage Example

Example #1
0
 /// <summary>
 /// Deflate one batch of data.
 /// </summary>
 /// <remarks>
 /// You must have set InputBuffer and OutputBuffer before calling this method.
 /// </remarks>
 /// <example>
 /// <code>
 /// private void DeflateBuffer(CompressionLevel level)
 /// {
 ///     int bufferSize = 1024;
 ///     byte[] buffer = new byte[bufferSize];
 ///     ZlibCodec compressor = new ZlibCodec();
 ///
 ///     Console.WriteLine("\n============================================");
 ///     Console.WriteLine("Size of Buffer to Deflate: {0} bytes.", UncompressedBytes.Length);
 ///     MemoryStream ms = new MemoryStream();
 ///
 ///     int rc = compressor.InitializeDeflate(level);
 ///
 ///     compressor.InputBuffer = UncompressedBytes;
 ///     compressor.NextIn = 0;
 ///     compressor.AvailableBytesIn = UncompressedBytes.Length;
 ///
 ///     compressor.OutputBuffer = buffer;
 ///
 ///     // pass 1: deflate
 ///     do
 ///     {
 ///         compressor.NextOut = 0;
 ///         compressor.AvailableBytesOut = buffer.Length;
 ///         rc = compressor.Deflate(FlushType.None);
 ///
 ///         if (rc != ZlibConstants.Z_OK &amp;&amp; rc != ZlibConstants.Z_STREAM_END)
 ///             throw new Exception("deflating: " + compressor.Message);
 ///
 ///         ms.Write(compressor.OutputBuffer, 0, buffer.Length - compressor.AvailableBytesOut);
 ///     }
 ///     while (compressor.AvailableBytesIn &gt; 0 || compressor.AvailableBytesOut == 0);
 ///
 ///     // pass 2: finish and flush
 ///     do
 ///     {
 ///         compressor.NextOut = 0;
 ///         compressor.AvailableBytesOut = buffer.Length;
 ///         rc = compressor.Deflate(FlushType.Finish);
 ///
 ///         if (rc != ZlibConstants.Z_STREAM_END &amp;&amp; rc != ZlibConstants.Z_OK)
 ///             throw new Exception("deflating: " + compressor.Message);
 ///
 ///         if (buffer.Length - compressor.AvailableBytesOut &gt; 0)
 ///             ms.Write(buffer, 0, buffer.Length - compressor.AvailableBytesOut);
 ///     }
 ///     while (compressor.AvailableBytesIn &gt; 0 || compressor.AvailableBytesOut == 0);
 ///
 ///     compressor.EndDeflate();
 ///
 ///     ms.Seek(0, SeekOrigin.Begin);
 ///     CompressedBytes = new byte[compressor.TotalBytesOut];
 ///     ms.Read(CompressedBytes, 0, CompressedBytes.Length);
 /// }
 /// </code>
 /// </example>
 /// <param name="flush">whether to flush all data as you deflate. Generally you will want to
 /// use Z_NO_FLUSH here, in a series of calls to Deflate(), and then call EndDeflate() to
 /// flush everything.
 /// </param>
 /// <returns>Z_OK if all goes well.</returns>
 public int Deflate(FlushType flush)
 {
     if (dstate == null)
     {
         throw new ZlibException("No Deflate State!");
     }
     return(dstate.Deflate(flush));
 }