Exemplo n.º 1
0
        /// <summary>
        /// Deflates the current input block to the given array.
        /// </summary>
        /// <param name="output">
        /// Buffer to store the compressed data.
        /// </param>
        /// <param name="offset">
        /// Offset into the output array.
        /// </param>
        /// <param name="length">
        /// The maximum number of bytes that may be stored.
        /// </param>
        /// <returns>
        /// The number of compressed bytes added to the output, or 0 if either
        /// needsInput() or finished() returns true or length is zero.
        /// </returns>
        /// <exception cref="System.InvalidOperationException">
        /// If end() was previously called.
        /// </exception>
        /// <exception cref="System.ArgumentOutOfRangeException">
        /// If offset and/or length don't match the array length.
        /// </exception>
        public int Deflate(byte[] output, int offset, int length)
        {
            int origLength = length;

            if (state == CLOSED_STATE)
            {
                throw new InvalidOperationException("Deflater closed");
            }

            if (state < BUSY_STATE)
            {
                /* output header */
                int header = (DEFLATED +
                              ((DeflaterConstants.MAX_WBITS - 8) << 4)) << 8;
                int level_flags = (level - 1) >> 1;
                if (level_flags < 0 || level_flags > 3)
                {
                    level_flags = 3;
                }
                header |= level_flags << 6;
                if ((state & IS_SETDICT) != 0)
                {
                    /* Dictionary was set */
                    header |= DeflaterConstants.PRESET_DICT;
                }
                header += 31 - (header % 31);


                pending.WriteShortMSB(header);
                if ((state & IS_SETDICT) != 0)
                {
                    int chksum = engine.Adler;
                    engine.ResetAdler();
                    pending.WriteShortMSB(chksum >> 16);
                    pending.WriteShortMSB(chksum & 0xffff);
                }

                state = BUSY_STATE | (state & (IS_FLUSHING | IS_FINISHING));
            }

            for (;;)
            {
                int count = pending.Flush(output, offset, length);
                offset   += count;
                totalOut += count;
                length   -= count;

                if (length == 0 || state == FINISHED_STATE)
                {
                    break;
                }

                if (!engine.Deflate((state & IS_FLUSHING) != 0, (state & IS_FINISHING) != 0))
                {
                    if (state == BUSY_STATE)
                    {
                        /* We need more input now */
                        return(origLength - length);
                    }
                    else if (state == FLUSHING_STATE)
                    {
                        if (level != NO_COMPRESSION)
                        {
                            /* We have to supply some lookahead.  8 bit lookahead
                             * is needed by the zlib inflater, and we must fill
                             * the next byte, so that all bits are flushed.
                             */
                            int neededbits = 8 + ((-pending.BitCount) & 7);
                            while (neededbits > 0)
                            {
                                /* write a static tree block consisting solely of
                                 * an EOF:
                                 */
                                pending.WriteBits(2, 10);
                                neededbits -= 10;
                            }
                        }
                        state = BUSY_STATE;
                    }
                    else if (state == FINISHING_STATE)
                    {
                        pending.AlignToByte();

                        // Compressed data is complete.  Write footer information if required.
                        if (!noZlibHeaderOrFooter)
                        {
                            int adler = engine.Adler;
                            pending.WriteShortMSB(adler >> 16);
                            pending.WriteShortMSB(adler & 0xffff);
                        }
                        state = FINISHED_STATE;
                    }
                }
            }
            return(origLength - length);
        }