Exemplo n.º 1
0
        internal int DeflateFast(ZlibFlushStrategy flush)
        {
            int  hash_head; // head of the hash chain
            bool bflush;    // set if current block must be flushed

            byte *  window = this.windowPointer;
            ushort *head   = this.headPointer;
            ushort *prev   = this.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 == ZlibFlushStrategy.ZNOFLUSH)
                    {
                        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 != ZlibCompressionStrategy.ZHUFFMANONLY)
                    {
                        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++;
                            hash_head = 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 == ZlibFlushStrategy.ZFINISH);
            return(this.strm.AvailOut == 0
                ? flush == ZlibFlushStrategy.ZFINISH ? FinishStarted : NeedMore
                : flush == ZlibFlushStrategy.ZFINISH ? FinishDone : BlockDone);
        }
Exemplo n.º 2
0
        private int DeflateSlow(ZlibFlushStrategy flush)
        {
            int  hash_head = 0; // head of hash chain
            bool bflush;        // set if current block must be flushed

            byte *  window = this.windowPointer;
            ushort *head   = this.headPointer;
            ushort *prev   = this.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 == ZlibFlushStrategy.ZNOFLUSH)
                    {
                        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 != ZlibCompressionStrategy.ZHUFFMANONLY)
                    {
                        this.matchLength = this.Longest_match(hash_head);
                    }

                    // longest_match() sets match_start
                    if (this.matchLength <= 5 && (this.strategy == ZlibCompressionStrategy.ZFILTERED ||
                                                  (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 == ZlibFlushStrategy.ZFINISH);

            return(this.strm.AvailOut == 0
                ? flush == ZlibFlushStrategy.ZFINISH ? FinishStarted : NeedMore
                : flush == ZlibFlushStrategy.ZFINISH ? FinishDone : BlockDone);
        }
Exemplo n.º 3
0
 /// <summary>
 /// Compress data.
 /// </summary>
 /// <param name="flush">The flush mode to use on the data.</param>
 /// <returns>The zlib status state.</returns>
 public ZlibCompressionState Deflate(ZlibFlushStrategy flush) => this.Dstate == null ? ZlibCompressionState.ZSTREAMERROR : this.Dstate.Compress(this, flush);
Exemplo n.º 4
0
 /// <summary>
 /// Decompresses data.
 /// </summary>
 /// <param name="f">The flush mode to use.</param>
 /// <returns>The zlib status state.</returns>
 public ZlibCompressionState Inflate(ZlibFlushStrategy f) => this.Istate == null ? ZlibCompressionState.ZSTREAMERROR : Libs.Inflate.Decompress(this, f);
Exemplo n.º 5
0
        internal static ZlibCompressionState Decompress(ZStream z, ZlibFlushStrategy f)
        {
            ZlibCompressionState r;
            int b;

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

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

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

                    r = f == ZlibFlushStrategy.ZFINISH ? ZlibCompressionState.ZBUFERROR : ZlibCompressionState.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 == ZlibFlushStrategy.ZFINISH ? ZlibCompressionState.ZBUFERROR : ZlibCompressionState.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 == ZlibFlushStrategy.ZFINISH ? ZlibCompressionState.ZBUFERROR : ZlibCompressionState.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 == ZlibFlushStrategy.ZFINISH ? ZlibCompressionState.ZBUFERROR : ZlibCompressionState.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 == ZlibFlushStrategy.ZFINISH ? ZlibCompressionState.ZBUFERROR : ZlibCompressionState.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 == ZlibFlushStrategy.ZFINISH ? ZlibCompressionState.ZBUFERROR : ZlibCompressionState.ZOK;

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

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

                case BLOCKS:

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

                    if (r == ZlibCompressionState.ZOK)
                    {
                        r = f == ZlibFlushStrategy.ZFINISH ? ZlibCompressionState.ZBUFERROR : ZlibCompressionState.ZOK;
                    }

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

                    r = f == ZlibFlushStrategy.ZFINISH ? ZlibCompressionState.ZBUFERROR : ZlibCompressionState.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 == ZlibFlushStrategy.ZFINISH ? ZlibCompressionState.ZBUFERROR : ZlibCompressionState.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 == ZlibFlushStrategy.ZFINISH ? ZlibCompressionState.ZBUFERROR : ZlibCompressionState.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 == ZlibFlushStrategy.ZFINISH ? ZlibCompressionState.ZBUFERROR : ZlibCompressionState.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 == ZlibFlushStrategy.ZFINISH ? ZlibCompressionState.ZBUFERROR : ZlibCompressionState.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(ZlibCompressionState.ZSTREAMEND);

                case BAD:
                    return(ZlibCompressionState.ZDATAERROR);

                default:
                    return(ZlibCompressionState.ZSTREAMERROR);
                }
            }
        }
Exemplo n.º 6
0
        private int DeflateStored(ZlibFlushStrategy 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.pendingBufferSize - 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 == ZlibFlushStrategy.ZNOFLUSH)
                    {
                        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 == ZlibFlushStrategy.ZFINISH);
            return(this.strm.AvailOut == 0 ? (flush == ZlibFlushStrategy.ZFINISH)
                ? FinishStarted
                : NeedMore : flush == ZlibFlushStrategy.ZFINISH ? FinishDone : BlockDone);
        }