Ejemplo n.º 1
0
 /// <summary>
 /// <para>This method decompresses as much data as possible, and stops when the input buffer (<see cref="next_in" />) becomes empty or the output buffer (<see cref="next_out" />) becomes full. It may some introduce some output latency (reading input without producing any output) except when forced to flush. </para>
 /// <para>The detailed semantics are as follows. <see cref="inflate" /> performs one or both of the following actions: </para>
 /// <para>
 /// <list type="bullet">
 /// <item>Decompress more input starting at <see cref="ZStream.next_in" /> and update <see cref="ZStream.next_in" /> and <see cref="ZStream.avail_in" /> accordingly. If not all input can be processed (because there is not enough room in the output buffer), <see cref="next_in" /> is updated and processing will resume at this point for the next call of <see cref="inflate" />. </item>
 /// <item>Provide more output starting at <see cref="next_out" /> and update <see cref="ZStream.next_out" /> and <see cref="ZStream.avail_out" /> accordingly. <see cref="ZStream.inflate" /> provides as much output as possible, until there is no more input data or no more space in the output buffer (see below about the <paramref name="flush" /> parameter).</item>
 /// </list>
 /// </para>
 /// </summary>
 /// <param name="flush"><see cref="FlushStrategy">Flush strategy</see> to use.</param>
 /// <remarks>
 /// <para>Before the call of <see cref="inflate" />, the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating the next_* and avail_* values accordingly. The application can consume the uncompressed output when it wants, for example when the output buffer is full (<c>avail_out == 0</c>), or after each call of <see cref="inflate" />. If <see cref="inflate" /> returns <see cref="ZLibResultCode.Z_OK" /> and with zero <see cref="avail_out" />, it must be called again after making room in the <see cref="next_out">output buffer</see> because there might be more output pending. </para>
 /// <para>If the parameter <paramref name="flush" /> is set to <see cref="FlushStrategy.Z_SYNC_FLUSH" />, <see cref="inflate" /> flushes as much output as possible to the output buffer. The flushing behavior of <see cref="inflate" /> is not specified for values of the <paramref name="flush" /> parameter other than <see cref="FlushStrategy.Z_SYNC_FLUSH" /> and <see cref="FlushStrategy.Z_FINISH" />, but the current implementation actually flushes as much output as possible anyway. </para>
 /// <para><see cref="inflate" /> should normally be called until it returns <see cref="ZLibResultCode.Z_STREAM_END" /> or an error. However if all decompression is to be performed in a single step (a single call of inflate), the parameter <paramref name="flush" /> should be set to <see cref="FlushStrategy.Z_FINISH" />. In this case all pending input is processed and all pending output is flushed ; <see cref="avail_out" /> must be large enough to hold all the uncompressed data. (The size of the uncompressed data may have been saved by the compressor for this purpose.) The next operation on this stream must be <see cref="inflateEnd" /> to deallocate the decompression state. The use of <see cref="FlushStrategy.Z_FINISH" /> is never required, but can be used to inform <see cref="inflate" /> that a faster routine may be used for the single <see cref="inflate" /> call. </para>
 /// <para>If a preset dictionary is needed at this point (see <see cref = "inflateSetDictionary" />), <see cref="inflate" /> sets strm-adler to the adler32 checksum of the dictionary chosen by the compressor and returns <see cref="ZLibResultCode.Z_NEED_DICT" /> ; otherwise it sets strm->adler to the adler32 checksum of all output produced so far (that is, <see cref="total_out" /> bytes) and returns <see cref="ZLibResultCode.Z_OK" />, <see cref="ZLibResultCode.Z_STREAM_END" /> or an error code as described below. At the end of the stream, <see cref="inflate" />) checks that its computed adler32 checksum is equal to that saved by the compressor and returns <see cref="ZLibResultCode.Z_STREAM_END" /> only if the checksum is correct.</para>
 /// </remarks>
 /// <returns>
 /// <see cref="inflate" /> returns <see cref="ZLibResultCode.Z_OK" /> if some progress has been made (more input processed or more output produced), <see cref="ZLibResultCode.Z_STREAM_END" /> if the end of the compressed data has been reached and all uncompressed output has been produced, <see cref="ZLibResultCode.Z_NEED_DICT" /> if a preset dictionary is needed at this point, <see cref="ZLibResultCode.Z_DATA_ERROR" /> if the input data was corrupted (input stream not conforming to the ZLib format or incorrect adler32 checksum), <see cref="ZLibResultCode.Z_STREAM_ERROR" /> if the stream structure was inconsistent (for example if <see cref="next_in" /> or <see cref="next_out" /> was <c>null</c>), <see cref="ZLibResultCode.Z_MEM_ERROR" /> if there was not enough memory, <see cref="ZLibResultCode.Z_BUF_ERROR" /> if no progress is possible or if there was not enough room in the output buffer when <see cref="FlushStrategy.Z_FINISH" /> is used. In the <see cref="ZLibResultCode.Z_DATA_ERROR" /> case, the application may then call <see cref="inflateSync" /> to look for a good compression block.
 /// </returns>
 internal int inflate(FlushStrategy flush)
 {
     if (_istate == null)
     {
         return((int)ZLibResultCode.Z_STREAM_ERROR);
     }
     return(_istate.inflate(this, flush));
 }
Ejemplo n.º 2
0
 /// <summary>
 /// <para>Deflate compresses as much data as possible, and stops when the <see cref="next_in">input buffer</see> becomes empty or the
 /// <see cref="next_out">output buffer</see> becomes full. It may introduce some output latency (reading input without producing any output)
 /// except when forced to flush.</para>
 /// <para>The detailed semantics are as follows. deflate performs one or both of the following actions:
 /// <list type="bullet">
 /// <item>Compress more input starting at <see cref="next_in" /> and update <see cref="next_in" /> and <see cref="avail_in" /> accordingly.
 /// If not all input can be processed (because there is not enough room in the output buffer), <see cref="next_in" /> and <see cref="avail_in" />
 /// are updated and processing will resume at this point for the next call of <see cref="deflate" />. </item>
 /// <item>Provide more output starting at <see cref="next_out" /> and update <see cref="next_out" /> and <see cref="avail_out" /> accordingly.
 /// This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter should
 /// be set only when necessary (in interactive applications). Some output may be provided even if flush is not set.</item>
 /// </list>
 /// </para>
 /// </summary>
 /// <param name="flush">The <see cref="FlushStrategy">flush strategy</see> to use.</param>
 /// <remarks>
 /// <para>
 /// Before the call of <seec ref="deflate" />, the application should ensure that at least one of the actions is possible, by providing
 /// more input and/or consuming more output, and updating <see cref="avail_in" /> or <see cref="avail_out" /> accordingly ; <see cref="avail_out" />
 /// should never be zero before the call. The application can consume the compressed output when it wants, for example when the output buffer is full
 /// (<c>avail_out == 0</c>), or after each call of <see cref="deflate" />. If <see cref="deflate" /> returns <see cref="ZLibResultCode.Z_OK" />
 /// and with zero <see cref="avail_out" />, it must be called again after making room in the output buffer because there might be more output pending.
 /// </para>
 /// <para>
 /// If the parameter <paramref name="flush"/> is set to <see cref="FlushStrategy.Z_SYNC_FLUSH" />, all pending output is flushed to the
 /// <see cref="next_out">output buffer</see> and the output is aligned on a byte boundary, so that the decompressor can get all input
 /// data available so far. (In particular <see cref="avail_in" /> is zero after the call if enough output space has been provided before the call.)
 /// Flushing may degrade compression for some compression algorithms and so it should be used only when necessary.
 /// </para>
 /// <para>
 /// If flush is set to <see cref="FlushStrategy.Z_FULL_FLUSH" />, all output is flushed as with <see cref="FlushStrategy.Z_SYNC_FLUSH" />,
 /// and the compression state is reset so that decompression can restart from this point if previous compressed data has been damaged or if
 /// random access is desired. Using <see cref="FlushStrategy.Z_FULL_FLUSH" /> too often can seriously degrade the compression.
 /// </para>
 /// </remarks>
 /// <returns>
 /// <para>
 /// If deflate returns with <c><see cref="avail_out" /> == 0</c>, this function must be called again with the same value of the flush
 /// parameter and more output space (updated <see cref="avail_out" />), until the flush is complete (<see cref="deflate" /> returns with
 /// non-zero <see cref="avail_out" />).
 /// </para>
 /// <para>
 /// If the parameter <paramref name="flush"/> is set to <see cref="FlushStrategy.Z_FINISH" />, pending input is processed, pending
 /// output is flushed and deflate returns with <see cref="ZLibResultCode.Z_STREAM_END" /> if there was enough output space ;
 /// if deflate returns with <see cref="ZLibResultCode.Z_OK" />, this function must be called again with <see cref="FlushStrategy.Z_FINISH" />
 /// and more output space (updated <see cref="avail_out" />) but no more input data, until it returns with <see cref="ZLibResultCode.Z_STREAM_END" />
 /// or an error. After deflate has returned <see cref="ZLibResultCode.Z_STREAM_END" />, the only possible operation on the stream is
 /// <see cref="deflateEnd" />. </para>
 /// <para>
 /// <see cref="FlushStrategy.Z_FINISH" /> can be used immediately after <see cref="DeflateInit(int)" /> if all the compression is to be
 /// done in a single step. In this case, avail_out must be at least 0.1% larger than avail_in plus 12 bytes. If deflate does not return
 /// Z_STREAM_END, then it must be called again as described above.
 /// </para>
 /// <para>
 /// <see cref="deflate" /> sets strm-> adler to the adler32 checksum of all input read so far (that is, <see cref="total_in" /> bytes).
 /// </para>
 /// <para>
 /// <see cref="deflate" /> may update data_type if it can make a good guess about the input data type (<see cref="BlockType">Z_ASCII or Z_BINARY</see>).
 /// In doubt, the data is considered binary. This field is only for information purposes and does not affect the compression algorithm in any manner.
 /// </para>
 /// <para>
 /// <see cref="deflate" /> returns <see cref="ZLibResultCode.Z_OK" /> if some progress has been made (more input processed or more output produced),
 /// <see cref="ZLibResultCode.Z_STREAM_END" /> if all input has been consumed and all output has been produced (only when flush is set to
 /// <see cref="FlushStrategy.Z_FINISH" />), <see cref="ZLibResultCode.Z_STREAM_ERROR" /> if the stream state was inconsistent (for example if
 /// <see cref="next_in" /> or <see cref="next_out" /> was <c>null</c>), <see cref="ZLibResultCode.Z_BUF_ERROR" /> if no progress is possible
 /// (for example <see cref="avail_in" /> or <see cref="avail_out" /> was zero).
 /// </para>
 /// </returns>
 public int deflate(FlushStrategy flush)
 {
     if (_dstate == null)
     {
         return((int)ZLibResultCode.Z_STREAM_ERROR);
     }
     return(_dstate.deflate(this, flush));
 }
Ejemplo n.º 3
0
 public TestRecoveryScenarios(FlushStrategy flush)
 {
     if (!InstanceFieldsInitialized)
     {
         InitializeInstanceFields();
         InstanceFieldsInitialized = true;
     }
     this._flush = flush;
 }
Ejemplo n.º 4
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Parameterized.Parameters(name = "{0}") public static java.util.List<Object[]> flushStrategy()
        public static IList <object[]> FlushStrategy()
        {
            IList <object[]> parameters = new List <object[]>();

            foreach (FlushStrategy flushStrategy in FlushStrategy.values())
            {
                parameters.Add(flushStrategy.parameters);
            }
            return(parameters);
        }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// For Z_RLE, simply look for runs of bytes, generate matches only of distance
        /// one.Do not maintain a hash table.  (It will be regenerated if this run of
        /// deflate switches away from Z_RLE.
        /// </summary>
        /// <param name="flush">The flush strategy.</param>
        /// <returns>The <see cref="int"/>.</returns>
        internal int DeflateRle(FlushStrategy flush)
        {
            bool  bflush; // set if current block must be flushed
            int   prev;   // byte at distance one to match
            byte *scan;   // scan goes up to strend for length of run
            byte *strend;
            byte *window = this.DynBuffers.WindowPointer;

            while (true)
            {
                // Make sure that we always have enough lookahead, except
                // at the end of the input file. We need MAX_MATCH bytes
                // for the longest run, plus one for the unrolled loop.
                if (this.lookahead <= MAXMATCH)
                {
                    this.Fill_window();
                    if (this.lookahead <= MAXMATCH && flush == FlushStrategy.NoFlush)
                    {
                        return(NeedMore);
                    }
                }

                if (this.lookahead == 0)
                {
                    break;
                }

                // See how many times the previous byte repeats
                this.matchLength = 0;
                if (this.lookahead >= MINMATCH && this.strStart > 0)
                {
                    scan = window + this.strStart - 1;
                    prev = *scan;

                    if (prev == *++scan && prev == *++scan && prev == *++scan)
                    {
                        strend = window + this.strStart + MAXMATCH;
                        do
                        {
                        }while (prev == *++scan && prev == *++scan &&
                                prev == *++scan && prev == *++scan &&
                                prev == *++scan && prev == *++scan &&
                                prev == *++scan && prev == *++scan &&
                                scan < strend);

                        this.matchLength = MAXMATCH - (int)(strend - scan);

                        if (this.matchLength > this.lookahead)
                        {
                            this.matchLength = this.lookahead;
                        }
                    }
                }

                // Emit match if have run of MIN_MATCH or longer, else emit literal
                if (this.matchLength >= MINMATCH)
                {
                    bflush = this.Tr_tally_dist(1, this.matchLength - MINMATCH);

                    this.lookahead  -= this.matchLength;
                    this.strStart   += this.matchLength;
                    this.matchLength = 0;
                }
                else
                {
                    // No match, output a literal byte
                    bflush = this.Tr_tally_lit(window[this.strStart]);
                    this.lookahead--;
                    this.strStart++;
                }

                if (bflush)
                {
                    this.Flush_block_only(false);
                    if (this.strm.AvailOut == 0)
                    {
                        return(NeedMore);
                    }
                }
            }

            this.Flush_block_only(flush == FlushStrategy.Finish);
            return(this.strm.AvailOut == 0
                ? flush == FlushStrategy.Finish ? FinishStarted : NeedMore
                : flush == FlushStrategy.Finish ? FinishDone : BlockDone);
        }
Ejemplo n.º 7
0
 /// <summary>
 /// Compress data.
 /// </summary>
 /// <param name="flush">The flush mode to use on the data.</param>
 /// <returns>The zlib status state.</returns>
 public CompressionState Deflate(FlushStrategy flush)
 => this.Dstate == null
     ? CompressionState.ZSTREAMERROR
     : this.Dstate.Compress(this, flush);
Ejemplo n.º 8
0
 /// <summary>
 /// Decompresses data.
 /// </summary>
 /// <param name="f">The flush mode to use.</param>
 /// <returns>The zlib status state.</returns>
 public CompressionState Inflate(FlushStrategy f)
 => this.Istate == null
     ? CompressionState.ZSTREAMERROR
     : ZlibStream.Inflate.Decompress(this, f);
Ejemplo n.º 9
0
 /// <summary>
 /// Initializes a block
 /// </summary>
 private void  InitBlock()
 {
     flush = FlushStrategy.Z_NO_FLUSH;
     buf   = new byte[ZLibUtil.zLibBufSize];
 }
Ejemplo n.º 10
0
        /// <summary>
        /// Same as fast, but achieves better compression. We use a lazy
        /// evaluation for matches: a match is finally adopted only if there is
        /// no better match at the next window position.
        /// </summary>
        /// <param name="flush">The flush strategy.</param>
        /// <returns>The <see cref="int"/>.</returns>
        private int DeflateSlow(FlushStrategy flush)
        {
            int  hash_head = 0; // head of hash chain
            bool bflush;        // set if current block must be flushed

            byte *  window = this.DynBuffers.WindowPointer;
            ushort *head   = this.DynBuffers.HeadPointer;
            ushort *prev   = this.DynBuffers.PrevPointer;

            // Process the input block.
            while (true)
            {
                // Make sure that we always have enough lookahead, except
                // at the end of the input file. We need MAX_MATCH bytes
                // for the next match, plus MINMATCH bytes to insert the
                // string following the next match.
                if (this.lookahead < MINLOOKAHEAD)
                {
                    this.Fill_window();
                    if (this.lookahead < MINLOOKAHEAD && flush == FlushStrategy.NoFlush)
                    {
                        return(NeedMore);
                    }

                    if (this.lookahead == 0)
                    {
                        break; // flush the current block
                    }
                }

                // Insert the string window[strstart .. strstart+2] in the
                // dictionary, and set hash_head to the head of the hash chain:
                if (this.lookahead >= MINMATCH)
                {
                    hash_head = this.InsertString(prev, head, window, this.strStart);
                }

                // Find the longest match, discarding those <= prev_length.
                this.prevLength  = this.matchLength;
                this.prevMatch   = this.matchStart;
                this.matchLength = MINMATCH - 1;

                if (hash_head != 0 && this.prevLength < this.maxLazyMatch &&
                    this.strStart - hash_head <= this.wSize - MINLOOKAHEAD)
                {
                    // To simplify the code, we prevent matches with the string
                    // of window index 0 (in particular we have to avoid a match
                    // of the string with itself at the start of the input file).
                    if (this.strategy != CompressionStrategy.HuffmanOnly)
                    {
                        this.matchLength = this.Longest_match(hash_head);
                    }

                    // longest_match() sets match_start
                    if (this.matchLength <= 5 && (this.strategy == CompressionStrategy.Filtered ||
                                                  (this.matchLength == MINMATCH && this.strStart - this.matchStart > 4096)))
                    {
                        // If prev_match is also MINMATCH, match_start is garbage
                        // but we will ignore the current match anyway.
                        this.matchLength = MINMATCH - 1;
                    }
                }

                // If there was a match at the previous step and the current
                // match is not better, output the previous match:
                if (this.prevLength >= MINMATCH && this.matchLength <= this.prevLength)
                {
                    int max_insert = this.strStart + this.lookahead - MINMATCH;

                    // Do not insert strings in hash table beyond this.

                    // check_match(strstart-1, prev_match, prev_length);
                    bflush = this.Tr_tally_dist(this.strStart - 1 - this.prevMatch, this.prevLength - MINMATCH);

                    // Insert in hash table all strings up to the end of the match.
                    // strstart-1 and strstart are already inserted. If there is not
                    // enough lookahead, the last two strings are not inserted in
                    // the hash table.
                    this.lookahead  -= this.prevLength - 1;
                    this.prevLength -= 2;
                    do
                    {
                        if (++this.strStart <= max_insert)
                        {
                            hash_head = this.InsertString(prev, head, window, this.strStart);
                        }
                    }while (--this.prevLength != 0);
                    this.matchAvailable = 0;
                    this.matchLength    = MINMATCH - 1;
                    this.strStart++;

                    if (bflush)
                    {
                        this.Flush_block_only(false);
                        if (this.strm.AvailOut == 0)
                        {
                            return(NeedMore);
                        }
                    }
                }
                else if (this.matchAvailable != 0)
                {
                    // If there was no match at the previous position, output a
                    // single literal. If there was a match but the current match
                    // is longer, truncate the previous match to a single literal.
                    bflush = this.Tr_tally_lit(window[this.strStart - 1]);

                    if (bflush)
                    {
                        this.Flush_block_only(false);
                    }

                    this.strStart++;
                    this.lookahead--;
                    if (this.strm.AvailOut == 0)
                    {
                        return(NeedMore);
                    }
                }
                else
                {
                    // There is no previous match to compare with, wait for
                    // the next step to decide.
                    this.matchAvailable = 1;
                    this.strStart++;
                    this.lookahead--;
                }
            }

            if (this.matchAvailable != 0)
            {
                _ = this.Tr_tally_lit(window[this.strStart - 1]);
                this.matchAvailable = 0;
            }

            this.Flush_block_only(flush == FlushStrategy.Finish);

            return(this.strm.AvailOut == 0
                ? flush == FlushStrategy.Finish ? FinishStarted : NeedMore
                : flush == FlushStrategy.Finish ? FinishDone : BlockDone);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Compress as much as possible from the input stream, return the current
        /// block state.
        /// This function does not perform lazy evaluation of matches and inserts
        /// new strings in the dictionary only for unmatched strings or for ushort
        /// matches. It is used only for the fast compression options.
        /// </summary>
        /// <param name="flush">The flush strategy.</param>
        /// <returns>The <see cref="int"/>.</returns>
        internal int DeflateFast(FlushStrategy flush)
        {
            int  hash_head; // head of the hash chain
            bool bflush;    // set if current block must be flushed

            byte *  window = this.DynBuffers.WindowPointer;
            ushort *head   = this.DynBuffers.HeadPointer;
            ushort *prev   = this.DynBuffers.PrevPointer;

            while (true)
            {
                // Make sure that we always have enough lookahead, except
                // at the end of the input file. We need MAX_MATCH bytes
                // for the next match, plus MINMATCH bytes to insert the
                // string following the next match.
                if (this.lookahead < MINLOOKAHEAD)
                {
                    this.Fill_window();
                    if (this.lookahead < MINLOOKAHEAD && flush == FlushStrategy.NoFlush)
                    {
                        return(NeedMore);
                    }

                    if (this.lookahead == 0)
                    {
                        break; // flush the current block
                    }
                }

                // Insert the string window[strstart .. strstart+2] in the
                // dictionary, and set hash_head to the head of the hash chain:
                hash_head = 0;
                if (this.lookahead >= MINMATCH)
                {
                    hash_head = this.InsertString(prev, head, window, this.strStart);
                }

                // Find the longest match, discarding those <= prev_length.
                // At this point we have always match_length < MINMATCH
                if (hash_head != 0 && (this.strStart - hash_head) <= this.wSize - MINLOOKAHEAD)
                {
                    // To simplify the code, we prevent matches with the string
                    // of window index 0 (in particular we have to avoid a match
                    // of the string with itself at the start of the input file).
                    if (this.strategy != CompressionStrategy.HuffmanOnly)
                    {
                        this.matchLength = this.Longest_match(hash_head);

                        // longest_match() sets match_start
                    }
                }

                if (this.matchLength >= MINMATCH)
                {
                    // check_match(strstart, match_start, match_length);
                    bflush = this.Tr_tally_dist(this.strStart - this.matchStart, this.matchLength - MINMATCH);

                    this.lookahead -= this.matchLength;

                    // Insert new strings in the hash table only if the match length
                    // is not too large. This saves time but degrades compression.
                    if (this.matchLength <= this.maxLazyMatch && this.lookahead >= MINMATCH)
                    {
                        this.matchLength--; // string at strstart already in hash table
                        do
                        {
                            this.strStart++;
                            this.InsertString(prev, head, window, this.strStart);

                            // strstart never exceeds WSIZE-MAX_MATCH, so there are
                            // always MINMATCH bytes ahead.
                        }while (--this.matchLength != 0);
                        this.strStart++;
                    }
                    else
                    {
                        this.strStart   += this.matchLength;
                        this.matchLength = 0;

                        this.UpdateHash(window[this.strStart + 1]);

                        // If lookahead < MINMATCH, insH is garbage, but it does not
                        // matter since it will be recomputed at next deflate call.
                    }
                }
                else
                {
                    // No match, output a literal byte
                    bflush = this.Tr_tally_lit(window[this.strStart]);
                    this.lookahead--;
                    this.strStart++;
                }

                if (bflush)
                {
                    this.Flush_block_only(false);
                    if (this.strm.AvailOut == 0)
                    {
                        return(NeedMore);
                    }
                }
            }

            this.Flush_block_only(flush == FlushStrategy.Finish);
            return(this.strm.AvailOut == 0
                ? flush == FlushStrategy.Finish ? FinishStarted : NeedMore
                : flush == FlushStrategy.Finish ? FinishDone : BlockDone);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Runs inflate algorithm
        /// </summary>
        /// <param name="z">A ZStream object</param>
        /// <param name="flush">Flush strategy</param>
        /// <returns>Operation result code</returns>
        internal int inflate(ZStream z, FlushStrategy flush)
        {
            int r;
            int b;

            int internalFlush = (int)flush;

            int res_temp;

            if (z == null || z.istate == null || z.next_in == null)
                return (int)ZLibResultCode.Z_STREAM_ERROR;
            res_temp = internalFlush == (int)FlushStrategy.Z_FINISH ? (int)ZLibResultCode.Z_BUF_ERROR : (int)ZLibResultCode.Z_OK;
            r = (int)ZLibResultCode.Z_BUF_ERROR;
            while (true)
            {

                switch (z.istate.mode)
                {

                    case  InflateMode.METHOD:

                        if (z.avail_in == 0)
                            return r; r = res_temp;

                        z.avail_in--; z.total_in++;
                        if (((z.istate.method = z.next_in[z.next_in_index++]) & 0xf) != ZLibUtil.Z_DEFLATED)
                        {
                            z.istate.mode =  InflateMode.BAD;
                            z.msg = "unknown compression method";
                            z.istate.marker = 5; // can't try inflateSync
                            break;
                        }
                        if ((z.istate.method >> 4) + 8 > z.istate.wbits)
                        {
                            z.istate.mode =  InflateMode.BAD;
                            z.msg = "invalid Window size";
                            z.istate.marker = 5; // can't try inflateSync
                            break;
                        }
                        z.istate.mode =  InflateMode.FLAG;
                        goto case  InflateMode.FLAG;

                    case  InflateMode.FLAG:

                        if (z.avail_in == 0)
                            return r; r = res_temp;

                        z.avail_in--; z.total_in++;
                        b = (z.next_in[z.next_in_index++]) & 0xff;

                        if ((((z.istate.method << 8) + b) % 31) != 0)
                        {
                            z.istate.mode =  InflateMode.BAD;
                            z.msg = "incorrect header check";
                            z.istate.marker = 5; // can't try inflateSync
                            break;
                        }

                        if ((b & ZLibUtil.PRESET_DICT) == 0)
                        {
                            z.istate.mode =  InflateMode.BLOCKS;
                            break;
                        }
                        z.istate.mode =  InflateMode.DICT4;
                        goto case  InflateMode.DICT4;

                    case  InflateMode.DICT4:

                        if (z.avail_in == 0)
                            return r; r = res_temp;

                        z.avail_in--; z.total_in++;
                        z.istate.need = ((long)(z.next_in[z.next_in_index++] & 0xff) << 24) & unchecked((int) 0xff000000L);
                        z.istate.mode =  InflateMode.DICT3;
                        goto case  InflateMode.DICT3;

                    case  InflateMode.DICT3:

                        if (z.avail_in == 0)
                            return r; r = res_temp;

                        z.avail_in--; z.total_in++;
                        z.istate.need += (((long)(z.next_in[z.next_in_index++] & 0xff) << 16) & 0xff0000L);
                        z.istate.mode =  InflateMode.DICT2;
                        goto case  InflateMode.DICT2;

                    case  InflateMode.DICT2:

                        if (z.avail_in == 0)
                            return r; r = res_temp;

                        z.avail_in--; z.total_in++;
                        z.istate.need += (((long)(z.next_in[z.next_in_index++] & 0xff) << 8) & 0xff00L);
                        z.istate.mode =  InflateMode.DICT1;
                        goto case  InflateMode.DICT1;

                    case  InflateMode.DICT1:

                        if (z.avail_in == 0)
                            return r; r = res_temp;

                        z.avail_in--; z.total_in++;
                        z.istate.need += (z.next_in[z.next_in_index++] & 0xffL);
                        z.adler = z.istate.need;
                        z.istate.mode =  InflateMode.DICT0;
                        return (int)ZLibResultCode.Z_NEED_DICT;

                    case  InflateMode.DICT0:
                        z.istate.mode =  InflateMode.BAD;
                        z.msg = "need dictionary";
                        z.istate.marker = 0; // can try inflateSync
                        return (int)ZLibResultCode.Z_STREAM_ERROR;

                    case  InflateMode.BLOCKS:

                        r = z.istate.blocks.proc(z, r);
                        if (r == (int)ZLibResultCode.Z_DATA_ERROR)
                        {
                            z.istate.mode =  InflateMode.BAD;
                            z.istate.marker = 0; // can try inflateSync
                            break;
                        }
                        if (r == (int)ZLibResultCode.Z_OK)
                        {
                            r = res_temp;
                        }
                        if (r != (int)ZLibResultCode.Z_STREAM_END)
                        {
                            return r;
                        }
                        r = res_temp;
                        z.istate.blocks.reset(z, z.istate.was);
                        if (z.istate.nowrap != 0)
                        {
                            z.istate.mode =  InflateMode.DONE;
                            break;
                        }
                        z.istate.mode =  InflateMode.CHECK4;
                        goto case  InflateMode.CHECK4;

                    case  InflateMode.CHECK4:

                        if (z.avail_in == 0)
                            return r; r = res_temp;

                        z.avail_in--; z.total_in++;
                        z.istate.need = ((z.next_in[z.next_in_index++] & 0xff) << 24) & unchecked((int) 0xff000000L);
                        z.istate.mode =  InflateMode.CHECK3;
                        goto case  InflateMode.CHECK3;

                    case  InflateMode.CHECK3:

                        if (z.avail_in == 0)
                            return r; r = res_temp;

                        z.avail_in--; z.total_in++;
                        z.istate.need += (((z.next_in[z.next_in_index++] & 0xff) << 16) & 0xff0000L);
                        z.istate.mode =  InflateMode.CHECK2;
                        goto case  InflateMode.CHECK2;

                    case  InflateMode.CHECK2:

                        if (z.avail_in == 0)
                            return r; r = res_temp;

                        z.avail_in--; z.total_in++;
                        z.istate.need += (((z.next_in[z.next_in_index++] & 0xff) << 8) & 0xff00L);
                        z.istate.mode =  InflateMode.CHECK1;
                        goto case  InflateMode.CHECK1;

                    case  InflateMode.CHECK1:

                        if (z.avail_in == 0)
                            return r; r = res_temp;

                        z.avail_in--; z.total_in++;
                        z.istate.need += (z.next_in[z.next_in_index++] & 0xffL);

                        if (unchecked(((int) (z.istate.was[0])) != ((int) (z.istate.need))))
                        {
                            z.istate.mode =  InflateMode.BAD;
                            z.msg = "incorrect data check";
                            z.istate.marker = 5; // can't try inflateSync
                            break;
                        }

                        z.istate.mode =  InflateMode.DONE;
                        goto case  InflateMode.DONE;

                    case  InflateMode.DONE:
                        return (int)ZLibResultCode.Z_STREAM_END;

                    case  InflateMode.BAD:
                        return (int)ZLibResultCode.Z_DATA_ERROR;

                    default:
                        return (int)ZLibResultCode.Z_STREAM_ERROR;

                }
            }
        }
Ejemplo n.º 13
0
        /// <summary>
        /// <para>Deflate compresses as much data as possible, and stops when the <see cref="next_in">input buffer</see> becomes empty or the <see cref="next_out">output buffer</see> becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush.</para>
        /// <para>The detailed semantics are as follows. deflate performs one or both of the following actions:
        /// <list type="bullet">
        /// <item>Compress more input starting at <see cref="next_in" /> and update <see cref="next_in" /> and <see cref="avail_in" /> accordingly. If not all input can be processed (because there is not enough room in the output buffer), <see cref="next_in" /> and <see cref="avail_in" /> are updated and processing will resume at this point for the next call of <see cref="deflate" />. </item>
        /// <item>Provide more output starting at <see cref="next_out" /> and update <see cref="next_out" /> and <see cref="avail_out" /> accordingly. This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter should be set only when necessary (in interactive applications). Some output may be provided even if flush is not set.</item>
        /// </list>
        /// </para>
        /// </summary>
        /// <param name="flush">The <see cref="FlushStrategy">flush strategy</see> to use.</param>
        /// <remarks>
        /// <para>Before the call of <seec ref="deflate" />, the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating <see cref="avail_in" /> or <see cref="avail_out" /> accordingly ; <see cref="avail_out" /> should never be zero before the call. The application can consume the compressed output when it wants, for example when the output buffer is full (<c>avail_out == 0</c>), or after each call of <see cref="deflate" />. If <see cref="deflate" /> returns <see cref="ZLibResultCode.Z_OK" /> and with zero <see cref="avail_out" />, it must be called again after making room in the output buffer because there might be more output pending. </para>
        /// <para>If the parameter <paramref name="flush"/> is set to <see cref="FlushStrategy.Z_SYNC_FLUSH" />, all pending output is flushed to the <see cref="next_out">output buffer</see> and the output is aligned on a byte boundary, so that the decompressor can get all input data available so far. (In particular <see cref="avail_in" /> is zero after the call if enough output space has been provided before the call.) Flushing may degrade compression for some compression algorithms and so it should be used only when necessary. </para>
        /// <para>If flush is set to <see cref="FlushStrategy.Z_FULL_FLUSH" />, all output is flushed as with <see cref="FlushStrategy.Z_SYNC_FLUSH" />, and the compression state is reset so that decompression can restart from this point if previous compressed data has been damaged or if random access is desired. Using <see cref="FlushStrategy.Z_FULL_FLUSH" /> too often can seriously degrade the compression.</para>
        /// </remarks>
        /// <returns>
        /// <para>If deflate returns with <c><see cref="avail_out" /> == 0</c>, this function must be called again with the same value of the flush parameter and more output space (updated <see cref="avail_out" />), until the flush is complete (<see cref="deflate" /> returns with non-zero <see cref="avail_out" />). </para>
        /// <para>If the parameter <paramref name="flush"/> is set to <see cref="FlushStrategy.Z_FINISH" />, pending input is processed, pending output is flushed and deflate returns with <see cref="ZLibResultCode.Z_STREAM_END" /> if there was enough output space ; if deflate returns with <see cref="ZLibResultCode.Z_OK" />, this function must be called again with <see cref="FlushStrategy.Z_FINISH" /> and more output space (updated <see cref="avail_out" />) but no more input data, until it returns with <see cref="ZLibResultCode.Z_STREAM_END" /> or an error. After deflate has returned <see cref="ZLibResultCode.Z_STREAM_END" />, the only possible operation on the stream is<see cref="deflateEnd" />. </para>
        /// <para><see cref="FlushStrategy.Z_FINISH" /> can be used immediately after <see cref="deflateInit(int)" /> if all the compression is to be done in a single step. In this case, avail_out must be at least 0.1% larger than avail_in plus 12 bytes. If deflate does not return Z_STREAM_END, then it must be called again as described above. </para>
        /// <para><see cref="deflate" /> sets strm-> adler to the adler32 checksum of all input read so far (that is, <see cref="total_in" /> bytes). </para>
        /// <para><see cref="deflate" /> may update data_type if it can make a good guess about the input data type (<see cref="BlockType">Z_ASCII or Z_BINARY</see>). In doubt, the data is considered binary. This field is only for information purposes and does not affect the compression algorithm in any manner. </para>
        /// <para><see cref="deflate" /> returns <see cref="ZLibResultCode.Z_OK" /> if some progress has been made (more input processed or more output produced), <see cref="ZLibResultCode.Z_STREAM_END" /> if all input has been consumed and all output has been produced (only when flush is set to <see cref="FlushStrategy.Z_FINISH" />), <see cref="ZLibResultCode.Z_STREAM_ERROR" /> if the stream state was inconsistent (for example if <see cref="next_in" /> or <see cref="next_out" /> was <c>null</c>), <see cref="ZLibResultCode.Z_BUF_ERROR" /> if no progress is possible (for example <see cref="avail_in" /> or <see cref="avail_out" /> was zero).</para>
        /// </returns>
		public int deflate(FlushStrategy flush)
		{
			if (_dstate == null)
			{
				return (int)ZLibResultCode.Z_STREAM_ERROR;
			}
			return _dstate.deflate(this, flush);
		}
Ejemplo n.º 14
0
        /// <summary>
        /// <para>This method decompresses as much data as possible, and stops when the input buffer (<see cref="next_in" />) becomes empty or the output buffer (<see cref="next_out" />) becomes full. It may some introduce some output latency (reading input without producing any output) except when forced to flush. </para>
        /// <para>The detailed semantics are as follows. <see cref="inflate" /> performs one or both of the following actions: </para>
        /// <para>
        /// <list type="bullet">
        /// <item>Decompress more input starting at <see cref="ZStream.next_in" /> and update <see cref="ZStream.next_in" /> and <see cref="ZStream.avail_in" /> accordingly. If not all input can be processed (because there is not enough room in the output buffer), <see cref="next_in" /> is updated and processing will resume at this point for the next call of <see cref="inflate" />. </item>
        /// <item>Provide more output starting at <see cref="next_out" /> and update <see cref="ZStream.next_out" /> and <see cref="ZStream.avail_out" /> accordingly. <see cref="ZStream.inflate" /> provides as much output as possible, until there is no more input data or no more space in the output buffer (see below about the <paramref name="flush" /> parameter).</item>
        /// </list>
        /// </para>
        /// </summary>
        /// <param name="flush"><see cref="FlushStrategy">Flush strategy</see> to use.</param>
        /// <remarks>
        /// <para>Before the call of <see cref="inflate" />, the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating the next_* and avail_* values accordingly. The application can consume the uncompressed output when it wants, for example when the output buffer is full (<c>avail_out == 0</c>), or after each call of <see cref="inflate" />. If <see cref="inflate" /> returns <see cref="ZLibResultCode.Z_OK" /> and with zero <see cref="avail_out" />, it must be called again after making room in the <see cref="next_out">output buffer</see> because there might be more output pending. </para>
        /// <para>If the parameter <paramref name="flush" /> is set to <see cref="FlushStrategy.Z_SYNC_FLUSH" />, <see cref="inflate" /> flushes as much output as possible to the output buffer. The flushing behavior of <see cref="inflate" /> is not specified for values of the <paramref name="flush" /> parameter other than <see cref="FlushStrategy.Z_SYNC_FLUSH" /> and <see cref="FlushStrategy.Z_FINISH" />, but the current implementation actually flushes as much output as possible anyway. </para>
        /// <para><see cref="inflate" /> should normally be called until it returns <see cref="ZLibResultCode.Z_STREAM_END" /> or an error. However if all decompression is to be performed in a single step (a single call of inflate), the parameter <paramref name="flush" /> should be set to <see cref="FlushStrategy.Z_FINISH" />. In this case all pending input is processed and all pending output is flushed ; <see cref="avail_out" /> must be large enough to hold all the uncompressed data. (The size of the uncompressed data may have been saved by the compressor for this purpose.) The next operation on this stream must be <see cref="inflateEnd" /> to deallocate the decompression state. The use of <see cref="FlushStrategy.Z_FINISH" /> is never required, but can be used to inform <see cref="inflate" /> that a faster routine may be used for the single <see cref="inflate" /> call. </para>
        /// <para>If a preset dictionary is needed at this point (see <see cref = "inflateSetDictionary" />), <see cref="inflate" /> sets strm-adler to the adler32 checksum of the dictionary chosen by the compressor and returns <see cref="ZLibResultCode.Z_NEED_DICT" /> ; otherwise it sets strm->adler to the adler32 checksum of all output produced so far (that is, <see cref="total_out" /> bytes) and returns <see cref="ZLibResultCode.Z_OK" />, <see cref="ZLibResultCode.Z_STREAM_END" /> or an error code as described below. At the end of the stream, <see cref="inflate" />) checks that its computed adler32 checksum is equal to that saved by the compressor and returns <see cref="ZLibResultCode.Z_STREAM_END" /> only if the checksum is correct.</para>
        /// </remarks>
        /// <returns>
        /// <see cref="inflate" /> returns <see cref="ZLibResultCode.Z_OK" /> if some progress has been made (more input processed or more output produced), <see cref="ZLibResultCode.Z_STREAM_END" /> if the end of the compressed data has been reached and all uncompressed output has been produced, <see cref="ZLibResultCode.Z_NEED_DICT" /> if a preset dictionary is needed at this point, <see cref="ZLibResultCode.Z_DATA_ERROR" /> if the input data was corrupted (input stream not conforming to the ZLib format or incorrect adler32 checksum), <see cref="ZLibResultCode.Z_STREAM_ERROR" /> if the stream structure was inconsistent (for example if <see cref="next_in" /> or <see cref="next_out" /> was <c>null</c>), <see cref="ZLibResultCode.Z_MEM_ERROR" /> if there was not enough memory, <see cref="ZLibResultCode.Z_BUF_ERROR" /> if no progress is possible or if there was not enough room in the output buffer when <see cref="FlushStrategy.Z_FINISH" /> is used. In the <see cref="ZLibResultCode.Z_DATA_ERROR" /> case, the application may then call <see cref="inflateSync" /> to look for a good compression block.
        /// </returns>
		public int inflate(FlushStrategy flush)
		{
			if (_istate == null)
				return (int)ZLibResultCode.Z_STREAM_ERROR;
			return _istate.inflate(this, flush);
		}
Ejemplo n.º 15
0
        public CompressionState Compress(ZStream strm, FlushStrategy flush)
        {
            FlushStrategy old_flush;

            if (flush > FlushStrategy.Finish || flush < 0)
            {
                return(CompressionState.ZSTREAMERROR);
            }

            if (strm.INextOut == null ||
                (strm.INextIn == null && strm.AvailIn != 0) ||
                (this.status == FINISHSTATE && flush != FlushStrategy.Finish))
            {
                strm.Msg = ZErrmsg[CompressionState.ZNEEDDICT - CompressionState.ZSTREAMERROR];
                return(CompressionState.ZSTREAMERROR);
            }

            if (strm.AvailOut == 0)
            {
                strm.Msg = ZErrmsg[CompressionState.ZNEEDDICT - CompressionState.ZBUFERROR];
                return(CompressionState.ZBUFERROR);
            }

            this.strm      = strm; // 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)strm.Adler >> 16);
                    this.PutShortMSB((int)strm.Adler);
                }

                strm.Adler = Adler32.SeedValue;
            }

            // Flush as much pending output as possible
            if (this.Pending != 0)
            {
                this.Flush_pending(strm);
                if (strm.AvailOut == 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 = (FlushStrategy)(-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 (strm.AvailIn == 0 && flush <= old_flush && flush != FlushStrategy.Finish)
            {
                strm.Msg = ZErrmsg[CompressionState.ZNEEDDICT - CompressionState.ZBUFERROR];
                return(CompressionState.ZBUFERROR);
            }

            // User must not provide more input after the first FINISH:
            if (this.status == FINISHSTATE && strm.AvailIn != 0)
            {
                strm.Msg = ZErrmsg[CompressionState.ZNEEDDICT - CompressionState.ZBUFERROR];
                return(CompressionState.ZBUFERROR);
            }

            // Start a new block or continue the current one.
            if (strm.AvailIn != 0 ||
                this.lookahead != 0 ||
                (flush != FlushStrategy.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 (strm.AvailOut == 0)
                    {
                        this.lastFlush = (FlushStrategy)(-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 == FlushStrategy.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 == FlushStrategy.FullFlush)
                        {
                            // state.head[s.hash_size-1]=0;
                            ushort *head = this.DynBuffers.HeadPointer;
                            for (int i = 0; i < this.hashSize; i++)
                            {
                                // forget history
                                head[i] = 0;
                            }
                        }
                    }

                    this.Flush_pending(strm);
                    if (strm.AvailOut == 0)
                    {
                        this.lastFlush = (FlushStrategy)(-1); // avoid BUF_ERROR at next call, see above
                        return(CompressionState.ZOK);
                    }
                }
            }

            if (flush != FlushStrategy.Finish)
            {
                return(CompressionState.ZOK);
            }

            if (this.Noheader != 0)
            {
                return(CompressionState.ZSTREAMEND);
            }

            // Write the zlib trailer (adler32)
            this.PutShortMSB((int)strm.Adler >> 16);
            this.PutShortMSB((int)strm.Adler);
            this.Flush_pending(strm);

            // 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);
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Copy without compression as much as possible from the input stream, return
        /// the current block state.
        /// This function does not insert new strings in the dictionary since
        /// uncompressible data is probably not useful. This function is used
        /// only for the level=0 compression option.
        /// NOTE: this function should be optimized to avoid extra copying from
        /// window to pending_buf.
        /// </summary>
        /// <param name="flush">The flush strategy.</param>
        /// <returns>The <see cref="int"/>.</returns>
        private int DeflateStored(FlushStrategy flush)
        {
            // Smallest worthy block size when not flushing or finishing. By default
            // this is 32K.This can be as small as 507 bytes for memLevel == 1., pending_buf is limited
            // to pending_buf_size, and each stored block has a 5 byte header:
            int max_block_size = Math.Min(this.DynBuffers.PendingSize - 5, this.wSize);
            int max_start;

            // Copy as much as possible from input to output:
            while (true)
            {
                // Fill the window as much as possible:
                if (this.lookahead <= 1)
                {
                    this.Fill_window();
                    if (this.lookahead == 0 && flush == FlushStrategy.NoFlush)
                    {
                        return(NeedMore);
                    }

                    if (this.lookahead == 0)
                    {
                        break; // flush the current block
                    }
                }

                this.strStart += this.lookahead;
                this.lookahead = 0;

                // Emit a stored block if pending_buf will be full:
                max_start = this.blockStart + max_block_size;
                if (this.strStart == 0 || this.strStart >= max_start)
                {
                    // strstart == 0 is possible when wraparound on 16-bit machine
                    this.lookahead = this.strStart - max_start;
                    this.strStart  = max_start;

                    this.Flush_block_only(false);
                    if (this.strm.AvailOut == 0)
                    {
                        return(NeedMore);
                    }
                }

                // Flush if we may have to slide, otherwise block_start may become
                // negative and the data will be gone:
                if (this.strStart - this.blockStart >= this.wSize - MINLOOKAHEAD)
                {
                    this.Flush_block_only(false);
                    if (this.strm.AvailOut == 0)
                    {
                        return(NeedMore);
                    }
                }
            }

            this.Flush_block_only(flush == FlushStrategy.Finish);
            return(this.strm.AvailOut == 0 ? (flush == FlushStrategy.Finish)
                ? FinishStarted
                : NeedMore : flush == FlushStrategy.Finish ? FinishDone : BlockDone);
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Runs inflate algorithm
        /// </summary>
        /// <param name="z">A ZStream object</param>
        /// <param name="flush">Flush strategy</param>
        /// <returns>Operation result code</returns>
        internal int inflate(ZStream z, FlushStrategy flush)
        {
            int r;
            int b;

            int internalFlush = (int)flush;

            int res_temp;

            if (z == null || z.istate == null || z.next_in == null)
            {
                return((int)ZLibResultCode.Z_STREAM_ERROR);
            }
            res_temp = internalFlush == (int)FlushStrategy.Z_FINISH ? (int)ZLibResultCode.Z_BUF_ERROR : (int)ZLibResultCode.Z_OK;
            r        = (int)ZLibResultCode.Z_BUF_ERROR;
            while (true)
            {
                switch (z.istate.mode)
                {
                case  InflateMode.METHOD:

                    if (z.avail_in == 0)
                    {
                        return(r);
                    }
                    r = res_temp;

                    z.avail_in--; z.total_in++;
                    if (((z.istate.method = z.next_in[z.next_in_index++]) & 0xf) != ZLibUtil.Z_DEFLATED)
                    {
                        z.istate.mode   = InflateMode.BAD;
                        z.msg           = "unknown compression method";
                        z.istate.marker = 5;                                 // can't try inflateSync
                        break;
                    }
                    if ((z.istate.method >> 4) + 8 > z.istate.wbits)
                    {
                        z.istate.mode   = InflateMode.BAD;
                        z.msg           = "invalid Window size";
                        z.istate.marker = 5;                                 // can't try inflateSync
                        break;
                    }
                    z.istate.mode = InflateMode.FLAG;
                    goto case InflateMode.FLAG;

                case  InflateMode.FLAG:

                    if (z.avail_in == 0)
                    {
                        return(r);
                    }
                    r = res_temp;

                    z.avail_in--; z.total_in++;
                    b = (z.next_in[z.next_in_index++]) & 0xff;

                    if ((((z.istate.method << 8) + b) % 31) != 0)
                    {
                        z.istate.mode   = InflateMode.BAD;
                        z.msg           = "incorrect header check";
                        z.istate.marker = 5;                                 // can't try inflateSync
                        break;
                    }

                    if ((b & ZLibUtil.PRESET_DICT) == 0)
                    {
                        z.istate.mode = InflateMode.BLOCKS;
                        break;
                    }
                    z.istate.mode = InflateMode.DICT4;
                    goto case InflateMode.DICT4;

                case  InflateMode.DICT4:

                    if (z.avail_in == 0)
                    {
                        return(r);
                    }
                    r = res_temp;

                    z.avail_in--; z.total_in++;
                    z.istate.need = ((long)(z.next_in[z.next_in_index++] & 0xff) << 24) & unchecked ((int)0xff000000L);
                    z.istate.mode = InflateMode.DICT3;
                    goto case InflateMode.DICT3;

                case  InflateMode.DICT3:

                    if (z.avail_in == 0)
                    {
                        return(r);
                    }
                    r = res_temp;

                    z.avail_in--; z.total_in++;
                    z.istate.need += (((long)(z.next_in[z.next_in_index++] & 0xff) << 16) & 0xff0000L);
                    z.istate.mode  = InflateMode.DICT2;
                    goto case InflateMode.DICT2;

                case  InflateMode.DICT2:

                    if (z.avail_in == 0)
                    {
                        return(r);
                    }
                    r = res_temp;

                    z.avail_in--; z.total_in++;
                    z.istate.need += (((long)(z.next_in[z.next_in_index++] & 0xff) << 8) & 0xff00L);
                    z.istate.mode  = InflateMode.DICT1;
                    goto case InflateMode.DICT1;

                case  InflateMode.DICT1:

                    if (z.avail_in == 0)
                    {
                        return(r);
                    }
                    r = res_temp;

                    z.avail_in--; z.total_in++;
                    z.istate.need += (z.next_in[z.next_in_index++] & 0xffL);
                    z.adler        = z.istate.need;
                    z.istate.mode  = InflateMode.DICT0;
                    return((int)ZLibResultCode.Z_NEED_DICT);

                case  InflateMode.DICT0:
                    z.istate.mode   = InflateMode.BAD;
                    z.msg           = "need dictionary";
                    z.istate.marker = 0;                             // can try inflateSync
                    return((int)ZLibResultCode.Z_STREAM_ERROR);

                case  InflateMode.BLOCKS:

                    r = z.istate.blocks.proc(z, r);
                    if (r == (int)ZLibResultCode.Z_DATA_ERROR)
                    {
                        z.istate.mode   = InflateMode.BAD;
                        z.istate.marker = 0;                                 // can try inflateSync
                        break;
                    }
                    if (r == (int)ZLibResultCode.Z_OK)
                    {
                        r = res_temp;
                    }
                    if (r != (int)ZLibResultCode.Z_STREAM_END)
                    {
                        return(r);
                    }
                    r = res_temp;
                    z.istate.blocks.reset(z, z.istate.was);
                    if (z.istate.nowrap != 0)
                    {
                        z.istate.mode = InflateMode.DONE;
                        break;
                    }
                    z.istate.mode = InflateMode.CHECK4;
                    goto case InflateMode.CHECK4;

                case  InflateMode.CHECK4:

                    if (z.avail_in == 0)
                    {
                        return(r);
                    }
                    r = res_temp;

                    z.avail_in--; z.total_in++;
                    z.istate.need = ((z.next_in[z.next_in_index++] & 0xff) << 24) & unchecked ((int)0xff000000L);
                    z.istate.mode = InflateMode.CHECK3;
                    goto case InflateMode.CHECK3;

                case  InflateMode.CHECK3:

                    if (z.avail_in == 0)
                    {
                        return(r);
                    }
                    r = res_temp;

                    z.avail_in--; z.total_in++;
                    z.istate.need += (((z.next_in[z.next_in_index++] & 0xff) << 16) & 0xff0000L);
                    z.istate.mode  = InflateMode.CHECK2;
                    goto case InflateMode.CHECK2;

                case  InflateMode.CHECK2:

                    if (z.avail_in == 0)
                    {
                        return(r);
                    }
                    r = res_temp;

                    z.avail_in--; z.total_in++;
                    z.istate.need += (((z.next_in[z.next_in_index++] & 0xff) << 8) & 0xff00L);
                    z.istate.mode  = InflateMode.CHECK1;
                    goto case InflateMode.CHECK1;

                case  InflateMode.CHECK1:

                    if (z.avail_in == 0)
                    {
                        return(r);
                    }
                    r = res_temp;

                    z.avail_in--; z.total_in++;
                    z.istate.need += (z.next_in[z.next_in_index++] & 0xffL);

                    if (unchecked (((int)(z.istate.was[0])) != ((int)(z.istate.need))))
                    {
                        z.istate.mode   = InflateMode.BAD;
                        z.msg           = "incorrect data check";
                        z.istate.marker = 5;                                 // can't try inflateSync
                        break;
                    }

                    z.istate.mode = InflateMode.DONE;
                    goto case InflateMode.DONE;

                case  InflateMode.DONE:
                    return((int)ZLibResultCode.Z_STREAM_END);

                case  InflateMode.BAD:
                    return((int)ZLibResultCode.Z_DATA_ERROR);

                default:
                    return((int)ZLibResultCode.Z_STREAM_ERROR);
                }
            }
        }
Ejemplo n.º 18
0
        internal static CompressionState Decompress(ZStream z, FlushStrategy f)
        {
            CompressionState r;
            int b;

            if (z == null || z.Istate == null || z.INextIn == null)
            {
                return(CompressionState.ZSTREAMERROR);
            }

            // f = f == ZlibFlushStrategy.ZFINISH ? ZlibCompressionState.ZBUFERROR : ZlibCompressionState.ZOK;
            r = CompressionState.ZBUFERROR;
            while (true)
            {
                // System.out.println("mode: "+z.istate.mode);
                switch (z.Istate.Mode)
                {
                case METHOD:

                    if (z.AvailIn == 0)
                    {
                        return(r);
                    }

                    r = f == FlushStrategy.Finish ? CompressionState.ZBUFERROR : CompressionState.ZOK;

                    z.AvailIn--; z.TotalIn++;
                    if (((z.Istate.Method = z.INextIn[z.NextInIndex++]) & 0xf) != ZDEFLATED)
                    {
                        z.Istate.Mode   = BAD;
                        z.Msg           = "unknown compression method";
                        z.Istate.Marker = 5;     // can't try inflateSync
                        break;
                    }

                    if ((z.Istate.Method >> 4) + 8 > z.Istate.Wbits)
                    {
                        z.Istate.Mode   = BAD;
                        z.Msg           = "invalid window size";
                        z.Istate.Marker = 5;     // can't try inflateSync
                        break;
                    }

                    z.Istate.Mode = FLAG;
                    goto case FLAG;

                case FLAG:

                    if (z.AvailIn == 0)
                    {
                        return(r);
                    }

                    r = f == FlushStrategy.Finish ? CompressionState.ZBUFERROR : CompressionState.ZOK;

                    z.AvailIn--; z.TotalIn++;
                    b = z.INextIn[z.NextInIndex++] & 0xff;

                    if ((((z.Istate.Method << 8) + b) % 31) != 0)
                    {
                        z.Istate.Mode   = BAD;
                        z.Msg           = "incorrect header check";
                        z.Istate.Marker = 5;     // can't try inflateSync
                        break;
                    }

                    if ((b & PRESETDICT) == 0)
                    {
                        z.Istate.Mode = BLOCKS;
                        break;
                    }

                    z.Istate.Mode = DICT4;
                    goto case DICT4;

                case DICT4:

                    if (z.AvailIn == 0)
                    {
                        return(r);
                    }

                    r = f == FlushStrategy.Finish ? CompressionState.ZBUFERROR : CompressionState.ZOK;

                    z.AvailIn--; z.TotalIn++;
                    z.Istate.Need = ((z.INextIn[z.NextInIndex++] & 0xff) << 24) & unchecked ((int)0xff000000L);
                    z.Istate.Mode = DICT3;
                    goto case DICT3;

                case DICT3:

                    if (z.AvailIn == 0)
                    {
                        return(r);
                    }

                    r = f == FlushStrategy.Finish ? CompressionState.ZBUFERROR : CompressionState.ZOK;

                    z.AvailIn--; z.TotalIn++;
                    z.Istate.Need += ((z.INextIn[z.NextInIndex++] & 0xff) << 16) & 0xff0000L;
                    z.Istate.Mode  = DICT2;
                    goto case DICT2;

                case DICT2:

                    if (z.AvailIn == 0)
                    {
                        return(r);
                    }

                    r = f == FlushStrategy.Finish ? CompressionState.ZBUFERROR : CompressionState.ZOK;

                    z.AvailIn--; z.TotalIn++;
                    z.Istate.Need += ((z.INextIn[z.NextInIndex++] & 0xff) << 8) & 0xff00L;
                    z.Istate.Mode  = DICT1;
                    goto case DICT1;

                case DICT1:

                    if (z.AvailIn == 0)
                    {
                        return(r);
                    }

                    r = f == FlushStrategy.Finish ? CompressionState.ZBUFERROR : CompressionState.ZOK;

                    z.AvailIn--; z.TotalIn++;
                    z.Istate.Need += z.INextIn[z.NextInIndex++] & 0xffL;
                    z.Adler        = (uint)z.Istate.Need;
                    z.Istate.Mode  = DICT0;
                    return(CompressionState.ZNEEDDICT);

                case DICT0:
                    z.Istate.Mode   = BAD;
                    z.Msg           = "need dictionary";
                    z.Istate.Marker = 0;     // can try inflateSync
                    return(CompressionState.ZSTREAMERROR);

                case BLOCKS:

                    r = z.Istate.Blocks.Proc(z, r);
                    if (r == CompressionState.ZDATAERROR)
                    {
                        z.Istate.Mode   = BAD;
                        z.Istate.Marker = 0;     // can try inflateSync
                        break;
                    }

                    if (r == CompressionState.ZOK)
                    {
                        r = f == FlushStrategy.Finish ? CompressionState.ZBUFERROR : CompressionState.ZOK;
                    }

                    if (r != CompressionState.ZSTREAMEND)
                    {
                        return(r);
                    }

                    r = f == FlushStrategy.Finish ? CompressionState.ZBUFERROR : CompressionState.ZOK;
                    z.Istate.Blocks.Reset(z, z.Istate.Was);
                    if (z.Istate.Nowrap != 0)
                    {
                        z.Istate.Mode = DONE;
                        break;
                    }

                    z.Istate.Mode = CHECK4;
                    goto case CHECK4;

                case CHECK4:

                    if (z.AvailIn == 0)
                    {
                        return(r);
                    }

                    r = f == FlushStrategy.Finish ? CompressionState.ZBUFERROR : CompressionState.ZOK;

                    z.AvailIn--; z.TotalIn++;
                    z.Istate.Need = ((z.INextIn[z.NextInIndex++] & 0xff) << 24) & unchecked ((int)0xff000000L);
                    z.Istate.Mode = CHECK3;
                    goto case CHECK3;

                case CHECK3:

                    if (z.AvailIn == 0)
                    {
                        return(r);
                    }

                    r = f == FlushStrategy.Finish ? CompressionState.ZBUFERROR : CompressionState.ZOK;

                    z.AvailIn--; z.TotalIn++;
                    z.Istate.Need += ((z.INextIn[z.NextInIndex++] & 0xff) << 16) & 0xff0000L;
                    z.Istate.Mode  = CHECK2;
                    goto case CHECK2;

                case CHECK2:

                    if (z.AvailIn == 0)
                    {
                        return(r);
                    }

                    r = f == FlushStrategy.Finish ? CompressionState.ZBUFERROR : CompressionState.ZOK;

                    z.AvailIn--; z.TotalIn++;
                    z.Istate.Need += ((z.INextIn[z.NextInIndex++] & 0xff) << 8) & 0xff00L;
                    z.Istate.Mode  = CHECK1;
                    goto case CHECK1;

                case CHECK1:

                    if (z.AvailIn == 0)
                    {
                        return(r);
                    }

                    r = f == FlushStrategy.Finish ? CompressionState.ZBUFERROR : CompressionState.ZOK;

                    z.AvailIn--; z.TotalIn++;
                    z.Istate.Need += z.INextIn[z.NextInIndex++] & 0xffL;

                    if (((int)z.Istate.Was[0]) != ((int)z.Istate.Need))
                    {
                        z.Istate.Mode   = BAD;
                        z.Msg           = "incorrect data check";
                        z.Istate.Marker = 5;     // can't try inflateSync
                        break;
                    }

                    z.Istate.Mode = DONE;
                    goto case DONE;

                case DONE:
                    return(CompressionState.ZSTREAMEND);

                case BAD:
                    return(CompressionState.ZDATAERROR);

                default:
                    return(CompressionState.ZSTREAMERROR);
                }
            }
        }
Ejemplo n.º 19
0
        /// <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;
        }
Ejemplo n.º 20
0
        /// <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);
            }
        }