Example #1
0
        // Copy the compressed bytes to output buffer as a block. maxBytesToCopy limits the number of 
        // bytes we can copy from input. Set to any value < 1 if no limit
        internal void GetBlock(DeflateInput input, OutputBuffer output, int maxBytesToCopy) {
            Debug.Assert(InputAvailable(input), "call SetInput before trying to compress!");

            WriteDeflatePreamble(output);
            GetCompressedOutput(input, output, maxBytesToCopy);
            WriteEndOfBlock(output);
        }
Example #2
0
        private void GetCompressedOutput(DeflateInput input, OutputBuffer output, int maxBytesToCopy)
        {
            int bytesWritten = output.BytesWritten;
            int num          = 0;
            int num2         = this.BytesInHistory + input.Count;

            do
            {
                int num3 = (input.Count < this.inputWindow.FreeWindowSpace) ? input.Count : this.inputWindow.FreeWindowSpace;
                if (maxBytesToCopy >= 1)
                {
                    num3 = Math.Min(num3, maxBytesToCopy - num);
                }
                if (num3 > 0)
                {
                    this.inputWindow.CopyBytes(input.Buffer, input.StartIndex, num3);
                    input.ConsumeBytes(num3);
                    num += num3;
                }
                this.GetCompressedOutput(output);
            }while (this.SafeToWriteTo(output) && this.InputAvailable(input) && (maxBytesToCopy < 1 || num < maxBytesToCopy));
            int num4 = output.BytesWritten - bytesWritten;
            int num5 = this.BytesInHistory + input.Count;
            int num6 = num2 - num5;

            if (num4 != 0)
            {
                this.lastCompressionRatio = (double)num4 / (double)num6;
            }
        }
        public void GetBlock(DeflateInput input, OutputBuffer output, bool isFinal)
        {
            int num = 0;

            if (input != null)
            {
                num = Math.Min(input.Count, output.FreeBytes - 5 - output.BitsInBuffer);
                if (num > 65531)
                {
                    num = 65531;
                }
            }
            if (isFinal)
            {
                output.WriteBits(3, 1u);
            }
            else
            {
                output.WriteBits(3, 0u);
            }
            output.FlushBits();
            this.WriteLenNLen((ushort)num, output);
            if (input != null && num > 0)
            {
                output.WriteBytes(input.Buffer, input.StartIndex, num);
                input.ConsumeBytes(num);
            }
        }
Example #4
0
        // maxBytesToCopy limits the number of bytes we can copy from input. Set to any value < 1 if no limit
        private void GetCompressedOutput(DeflateInput input, OutputBuffer output, int maxBytesToCopy) {
            // snapshot for compression ratio stats
            int bytesWrittenPre = output.BytesWritten;
            int bytesConsumedFromInput = 0;
            int inputBytesPre = BytesInHistory + input.Count;

            do {
                // read more input data into the window if there is space available
                int bytesToCopy = (input.Count < inputWindow.FreeWindowSpace) ?
                                         input.Count : inputWindow.FreeWindowSpace;
                if (maxBytesToCopy >= 1) {
                    bytesToCopy = Math.Min(bytesToCopy, maxBytesToCopy - bytesConsumedFromInput);
                }
                if (bytesToCopy > 0) {
                    // copy data into history window
                    inputWindow.CopyBytes(input.Buffer, input.StartIndex, bytesToCopy);
                    input.ConsumeBytes(bytesToCopy);
                    bytesConsumedFromInput += bytesToCopy;
                }

                GetCompressedOutput(output);

            } while (SafeToWriteTo(output) && InputAvailable(input) && (maxBytesToCopy < 1 || bytesConsumedFromInput < maxBytesToCopy));

            // determine compression ratio, save
            int bytesWrittenPost = output.BytesWritten;
            int bytesWritten = bytesWrittenPost - bytesWrittenPre;
            int inputBytesPost = BytesInHistory + input.Count;
            int totalBytesConsumed = inputBytesPre - inputBytesPost;
            if (bytesWritten != 0) {
                lastCompressionRatio = (double)bytesWritten / (double)totalBytesConsumed;
            }

        }
Example #5
0
        // Copy the compressed bytes to output buffer as a block. maxBytesToCopy limits the number of
        // bytes we can copy from input. Set to any value < 1 if no limit
        internal void GetBlock(DeflateInput input, OutputBuffer output, int maxBytesToCopy)
        {
            Debug.Assert(InputAvailable(input), "call SetInput before trying to compress!");

            WriteDeflatePreamble(output);
            GetCompressedOutput(input, output, maxBytesToCopy);
            WriteEndOfBlock(output);
        }
Example #6
0
        internal DeflaterManaged() {
            deflateEncoder = new FastEncoder();
            copyEncoder = new CopyEncoder();
            input = new DeflateInput();
            output = new OutputBuffer();

            processingState = DeflaterState.NotStarted;
        }
Example #7
0
 internal DeflaterManaged()
 {
     this.deflateEncoder  = new FastEncoder();
     this.copyEncoder     = new CopyEncoder();
     this.input           = new DeflateInput();
     this.output          = new OutputBuffer();
     this.processingState = DeflaterManaged.DeflaterState.NotStarted;
 }
Example #8
0
        internal DeflaterManaged()
        {
            deflateEncoder = new FastEncoder();
            copyEncoder    = new CopyEncoder();
            input          = new DeflateInput();
            output         = new OutputBuffer();

            processingState = DeflaterState.NotStarted;
        }
Example #9
0
        // null input means write an empty payload with formatting info. This is needed for the final block.
        public void GetBlock(DeflateInput input, OutputBuffer output, bool isFinal)
        {
            Debug.Assert(output != null);
            Debug.Assert(output.FreeBytes >= PaddingSize);

            // determine number of bytes to write
            int count = 0;

            if (input != null)
            {
                // allow space for padding and bits not yet flushed to buffer
                count = Math.Min(input.Count, output.FreeBytes - PaddingSize - output.BitsInBuffer);

                // we don't expect the output buffer to ever be this big (currently 4K), but we'll check this
                // just in case that changes.
                if (count > MaxUncompressedBlockSize - PaddingSize)
                {
                    count = MaxUncompressedBlockSize - PaddingSize;
                }
            }

            // write header and flush bits
            if (isFinal)
            {
                output.WriteBits(FastEncoderStatics.BFinalNoCompressionHeaderBitCount,
                                 FastEncoderStatics.BFinalNoCompressionHeader);
            }
            else
            {
                output.WriteBits(FastEncoderStatics.NoCompressionHeaderBitCount,
                                 FastEncoderStatics.NoCompressionHeader);
            }

            // now we're aligned
            output.FlushBits();

            // write len, nlen
            WriteLenNLen((ushort)count, output);

            // write uncompressed bytes
            if (input != null && count > 0)
            {
                output.WriteBytes(input.Buffer, input.StartIndex, count);
                input.ConsumeBytes(count);
            }
        }
Example #10
0
        // null input means write an empty payload with formatting info. This is needed for the final block.
        public void GetBlock(DeflateInput input, OutputBuffer output, bool isFinal) {
            Debug.Assert(output != null);
            Debug.Assert(output.FreeBytes >= PaddingSize);

            // determine number of bytes to write
            int count = 0;
            if (input != null) {

                // allow space for padding and bits not yet flushed to buffer
                count = Math.Min(input.Count, output.FreeBytes - PaddingSize - output.BitsInBuffer); 

                // we don't expect the output buffer to ever be this big (currently 4K), but we'll check this
                // just in case that changes.
                if (count > MaxUncompressedBlockSize - PaddingSize) {
                    count = MaxUncompressedBlockSize - PaddingSize;
                }
            }

            // write header and flush bits
            if (isFinal) {
                output.WriteBits(FastEncoderStatics.BFinalNoCompressionHeaderBitCount,
                                        FastEncoderStatics.BFinalNoCompressionHeader);
            }
            else {
                output.WriteBits(FastEncoderStatics.NoCompressionHeaderBitCount,
                                        FastEncoderStatics.NoCompressionHeader);
            }

            // now we're aligned
            output.FlushBits(); 
            
            // write len, nlen
            WriteLenNLen((ushort)count, output);

            // write uncompressed bytes
            if (input != null && count > 0) {
                output.WriteBytes(input.Buffer, input.StartIndex, count);
                input.ConsumeBytes(count);
            }

        }
Example #11
0
        // maxBytesToCopy limits the number of bytes we can copy from input. Set to any value < 1 if no limit
        private void GetCompressedOutput(DeflateInput input, OutputBuffer output, int maxBytesToCopy)
        {
            // snapshot for compression ratio stats
            var bytesWrittenPre        = output.BytesWritten;
            var bytesConsumedFromInput = 0;
            var inputBytesPre          = BytesInHistory + input.Count;

            do
            {
                // read more input data into the window if there is space available
                var bytesToCopy = input.Count < inputWindow.FreeWindowSpace
                                        ? input.Count
                                        : inputWindow.FreeWindowSpace;
                if (maxBytesToCopy >= 1)
                {
                    bytesToCopy = Math.Min(bytesToCopy, maxBytesToCopy - bytesConsumedFromInput);
                }
                if (bytesToCopy > 0)
                {
                    // copy data into history window
                    inputWindow.CopyBytes(input.Buffer, input.StartIndex, bytesToCopy);
                    input.ConsumeBytes(bytesToCopy);
                    bytesConsumedFromInput += bytesToCopy;
                }

                GetCompressedOutput(output);
            } while (SafeToWriteTo(output) && InputAvailable(input) &&
                     (maxBytesToCopy < 1 || bytesConsumedFromInput < maxBytesToCopy));

            // determine compression ratio, save
            var bytesWrittenPost   = output.BytesWritten;
            var bytesWritten       = bytesWrittenPost - bytesWrittenPre;
            var inputBytesPost     = BytesInHistory + input.Count;
            var totalBytesConsumed = inputBytesPre - inputBytesPost;

            if (bytesWritten != 0)
            {
                LastCompressionRatio = bytesWritten / (double)totalBytesConsumed;
            }
        }
Example #12
0
 // Compress data but don't format as block (doesn't have header and footer)
 internal void GetCompressedData(DeflateInput input, OutputBuffer output)
 {
     GetCompressedOutput(input, output, -1);
 }
Example #13
0
        int IDeflater.GetDeflateOutput(byte[] outputBuffer) {

            Debug.Assert(outputBuffer != null, "Can't pass in a null output buffer!");
            Debug.Assert(!NeedsInput(), "GetDeflateOutput should only be called after providing input");

            output.UpdateBuffer(outputBuffer);

            switch(processingState) {

                case DeflaterState.NotStarted: {
                        // first call. Try to compress but if we get bad compression ratio, switch to uncompressed blocks. 
                        Debug.Assert(deflateEncoder.BytesInHistory == 0, "have leftover bytes in window");

                        // save these in case we need to switch to uncompressed format
                        DeflateInput.InputState initialInputState = input.DumpState();
                        OutputBuffer.BufferState initialOutputState = output.DumpState();

                        deflateEncoder.GetBlockHeader(output);
                        deflateEncoder.GetCompressedData(input, output);

                        if (!UseCompressed(deflateEncoder.LastCompressionRatio)) {
                            // we're expanding; restore state and switch to uncompressed
                            input.RestoreState(initialInputState);
                            output.RestoreState(initialOutputState);
                            copyEncoder.GetBlock(input, output, false);
                            FlushInputWindows();
                            processingState = DeflaterState.CheckingForIncompressible;
                        }
                        else {
                            processingState = DeflaterState.CompressThenCheck;
                        }

                        break;
                    }
                case DeflaterState.CompressThenCheck: {
                        // continue assuming data is compressible. If we reach data that indicates otherwise
                        // finish off remaining data in history and decide whether to compress on a 
                        // block-by-block basis
                        deflateEncoder.GetCompressedData(input, output);

                        if (!UseCompressed(deflateEncoder.LastCompressionRatio)) {
                            processingState = DeflaterState.SlowDownForIncompressible1;
                            inputFromHistory = deflateEncoder.UnprocessedInput;
                        }
                        break;
                    }
                case DeflaterState.SlowDownForIncompressible1: {
                        // finish off previous compressed block
                        deflateEncoder.GetBlockFooter(output);

                        processingState = DeflaterState.SlowDownForIncompressible2;
                        goto case DeflaterState.SlowDownForIncompressible2; // yeah I know, but there's no fallthrough
                    }

                case DeflaterState.SlowDownForIncompressible2: {
                        // clear out data from history, but add them as uncompressed blocks
                        if (inputFromHistory.Count > 0) {
                            copyEncoder.GetBlock(inputFromHistory, output, false);
                        }

                        if (inputFromHistory.Count == 0) {
                            // now we're clean
                            deflateEncoder.FlushInput();
                            processingState = DeflaterState.CheckingForIncompressible;
                        }
                        break;
                    }

                case DeflaterState.CheckingForIncompressible: {
                        // decide whether to compress on a block-by-block basis
                        Debug.Assert(deflateEncoder.BytesInHistory == 0, "have leftover bytes in window");

                        // save these in case we need to store as uncompressed
                        DeflateInput.InputState initialInputState = input.DumpState();
                        OutputBuffer.BufferState initialOutputState = output.DumpState();

                        // enforce max so we can ensure state between calls
                        deflateEncoder.GetBlock(input, output, CleanCopySize);

                        if (!UseCompressed(deflateEncoder.LastCompressionRatio)) {
                            // we're expanding; restore state and switch to uncompressed
                            input.RestoreState(initialInputState);
                            output.RestoreState(initialOutputState);
                            copyEncoder.GetBlock(input, output, false);
                            FlushInputWindows();
                        }

                        break;
                    }

                case DeflaterState.StartingSmallData: {
                        // add compressed header and data, but not footer. Subsequent calls will keep 
                        // adding compressed data (no header and no footer). We're doing this to 
                        // avoid overhead of header and footer size relative to compressed payload.
                        deflateEncoder.GetBlockHeader(output);

                        processingState = DeflaterState.HandlingSmallData;
                        goto case DeflaterState.HandlingSmallData; // yeah I know, but there's no fallthrough
                    }

                case DeflaterState.HandlingSmallData: {
                        // continue adding compressed data
                        deflateEncoder.GetCompressedData(input, output);
                        break;
                    }
            }

            return output.BytesWritten;
        }
Example #14
0
 private bool InputAvailable(DeflateInput input)
 {
     return(input.Count > 0 || BytesInHistory > 0);
 }
Example #15
0
 private bool InputAvailable(DeflateInput input) {
     return input.Count > 0 || BytesInHistory > 0;
 }
Example #16
0
 // Compress data but don't format as block (doesn't have header and footer)
 internal void GetCompressedData(DeflateInput input, OutputBuffer output) {
     GetCompressedOutput(input, output, -1);
 }
Example #17
0
 internal void GetBlock(DeflateInput input, OutputBuffer output, int maxBytesToCopy)
 {
     FastEncoder.WriteDeflatePreamble(output);
     this.GetCompressedOutput(input, output, maxBytesToCopy);
     this.WriteEndOfBlock(output);
 }
Example #18
0
        int IDeflater.GetDeflateOutput(byte[] outputBuffer)
        {
            Debug.Assert(outputBuffer != null, "Can't pass in a null output buffer!");
            Debug.Assert(!NeedsInput(), "GetDeflateOutput should only be called after providing input");

            output.UpdateBuffer(outputBuffer);

            switch (processingState)
            {
            case DeflaterState.NotStarted: {
                // first call. Try to compress but if we get bad compression ratio, switch to uncompressed blocks.
                Debug.Assert(deflateEncoder.BytesInHistory == 0, "have leftover bytes in window");

                // save these in case we need to switch to uncompressed format
                DeflateInput.InputState  initialInputState  = input.DumpState();
                OutputBuffer.BufferState initialOutputState = output.DumpState();

                deflateEncoder.GetBlockHeader(output);
                deflateEncoder.GetCompressedData(input, output);

                if (!UseCompressed(deflateEncoder.LastCompressionRatio))
                {
                    // we're expanding; restore state and switch to uncompressed
                    input.RestoreState(initialInputState);
                    output.RestoreState(initialOutputState);
                    copyEncoder.GetBlock(input, output, false);
                    FlushInputWindows();
                    processingState = DeflaterState.CheckingForIncompressible;
                }
                else
                {
                    processingState = DeflaterState.CompressThenCheck;
                }

                break;
            }

            case DeflaterState.CompressThenCheck: {
                // continue assuming data is compressible. If we reach data that indicates otherwise
                // finish off remaining data in history and decide whether to compress on a
                // block-by-block basis
                deflateEncoder.GetCompressedData(input, output);

                if (!UseCompressed(deflateEncoder.LastCompressionRatio))
                {
                    processingState  = DeflaterState.SlowDownForIncompressible1;
                    inputFromHistory = deflateEncoder.UnprocessedInput;
                }
                break;
            }

            case DeflaterState.SlowDownForIncompressible1: {
                // finish off previous compressed block
                deflateEncoder.GetBlockFooter(output);

                processingState = DeflaterState.SlowDownForIncompressible2;
                goto case DeflaterState.SlowDownForIncompressible2;         // yeah I know, but there's no fallthrough
            }

            case DeflaterState.SlowDownForIncompressible2: {
                // clear out data from history, but add them as uncompressed blocks
                if (inputFromHistory.Count > 0)
                {
                    copyEncoder.GetBlock(inputFromHistory, output, false);
                }

                if (inputFromHistory.Count == 0)
                {
                    // now we're clean
                    deflateEncoder.FlushInput();
                    processingState = DeflaterState.CheckingForIncompressible;
                }
                break;
            }

            case DeflaterState.CheckingForIncompressible: {
                // decide whether to compress on a block-by-block basis
                Debug.Assert(deflateEncoder.BytesInHistory == 0, "have leftover bytes in window");

                // save these in case we need to store as uncompressed
                DeflateInput.InputState  initialInputState  = input.DumpState();
                OutputBuffer.BufferState initialOutputState = output.DumpState();

                // enforce max so we can ensure state between calls
                deflateEncoder.GetBlock(input, output, CleanCopySize);

                if (!UseCompressed(deflateEncoder.LastCompressionRatio))
                {
                    // we're expanding; restore state and switch to uncompressed
                    input.RestoreState(initialInputState);
                    output.RestoreState(initialOutputState);
                    copyEncoder.GetBlock(input, output, false);
                    FlushInputWindows();
                }

                break;
            }

            case DeflaterState.StartingSmallData: {
                // add compressed header and data, but not footer. Subsequent calls will keep
                // adding compressed data (no header and no footer). We're doing this to
                // avoid overhead of header and footer size relative to compressed payload.
                deflateEncoder.GetBlockHeader(output);

                processingState = DeflaterState.HandlingSmallData;
                goto case DeflaterState.HandlingSmallData;         // yeah I know, but there's no fallthrough
            }

            case DeflaterState.HandlingSmallData: {
                // continue adding compressed data
                deflateEncoder.GetCompressedData(input, output);
                break;
            }
            }

            return(output.BytesWritten);
        }
Example #19
0
        int IDeflater.GetDeflateOutput(byte[] outputBuffer)
        {
            this.output.UpdateBuffer(outputBuffer);
            switch (this.processingState)
            {
            case DeflaterManaged.DeflaterState.NotStarted:
            {
                DeflateInput.InputState  state  = this.input.DumpState();
                OutputBuffer.BufferState state2 = this.output.DumpState();
                this.deflateEncoder.GetBlockHeader(this.output);
                this.deflateEncoder.GetCompressedData(this.input, this.output);
                if (!this.UseCompressed(this.deflateEncoder.LastCompressionRatio))
                {
                    this.input.RestoreState(state);
                    this.output.RestoreState(state2);
                    this.copyEncoder.GetBlock(this.input, this.output, false);
                    this.FlushInputWindows();
                    this.processingState = DeflaterManaged.DeflaterState.CheckingForIncompressible;
                    goto IL_23A;
                }
                this.processingState = DeflaterManaged.DeflaterState.CompressThenCheck;
                goto IL_23A;
            }

            case DeflaterManaged.DeflaterState.SlowDownForIncompressible1:
                this.deflateEncoder.GetBlockFooter(this.output);
                this.processingState = DeflaterManaged.DeflaterState.SlowDownForIncompressible2;
                break;

            case DeflaterManaged.DeflaterState.SlowDownForIncompressible2:
                break;

            case DeflaterManaged.DeflaterState.StartingSmallData:
                this.deflateEncoder.GetBlockHeader(this.output);
                this.processingState = DeflaterManaged.DeflaterState.HandlingSmallData;
                goto IL_223;

            case DeflaterManaged.DeflaterState.CompressThenCheck:
                this.deflateEncoder.GetCompressedData(this.input, this.output);
                if (!this.UseCompressed(this.deflateEncoder.LastCompressionRatio))
                {
                    this.processingState  = DeflaterManaged.DeflaterState.SlowDownForIncompressible1;
                    this.inputFromHistory = this.deflateEncoder.UnprocessedInput;
                    goto IL_23A;
                }
                goto IL_23A;

            case DeflaterManaged.DeflaterState.CheckingForIncompressible:
            {
                DeflateInput.InputState  state3 = this.input.DumpState();
                OutputBuffer.BufferState state4 = this.output.DumpState();
                this.deflateEncoder.GetBlock(this.input, this.output, 8072);
                if (!this.UseCompressed(this.deflateEncoder.LastCompressionRatio))
                {
                    this.input.RestoreState(state3);
                    this.output.RestoreState(state4);
                    this.copyEncoder.GetBlock(this.input, this.output, false);
                    this.FlushInputWindows();
                    goto IL_23A;
                }
                goto IL_23A;
            }

            case DeflaterManaged.DeflaterState.HandlingSmallData:
                goto IL_223;

            default:
                goto IL_23A;
            }
            if (this.inputFromHistory.Count > 0)
            {
                this.copyEncoder.GetBlock(this.inputFromHistory, this.output, false);
            }
            if (this.inputFromHistory.Count == 0)
            {
                this.deflateEncoder.FlushInput();
                this.processingState = DeflaterManaged.DeflaterState.CheckingForIncompressible;
                goto IL_23A;
            }
            goto IL_23A;
IL_223:
            this.deflateEncoder.GetCompressedData(this.input, this.output);
IL_23A:
            return(this.output.BytesWritten);
        }
Example #20
0
 private Boolean InputAvailable(DeflateInput input)
 {
     return(input.Count > 0 || this.BytesInHistory > 0);
 }