FastEncoder.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Sys / System / IO / compression / FastEncoder.cs / 1305376 / FastEncoder.cs

                            namespace System.IO.Compression { 
    using System;
    using System.Diagnostics;
    using System.Globalization;
 
    internal class FastEncoder {
 
        private FastEncoderWindow inputWindow; // input history window 
        private Match currentMatch;            // current match in history window
        private double lastCompressionRatio; 

        public FastEncoder() {
            inputWindow = new FastEncoderWindow();
            currentMatch = new Match(); 
        }
 
        internal int BytesInHistory { 
            get {
                return inputWindow.BytesAvailable; 
            }
        }

        internal DeflateInput UnprocessedInput { 
            get {
                return inputWindow.UnprocessedInput; 
            } 
        }
 
        internal void FlushInput() {
            inputWindow.FlushWindow();
        }
 
        internal Double LastCompressionRatio {
            get { return lastCompressionRatio; } 
        } 

        // 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); 
        }
 
        // 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);
        } 

        internal void GetBlockHeader(OutputBuffer output) { 
            WriteDeflatePreamble(output); 
        }
 
        internal void GetBlockFooter(OutputBuffer output) {
            WriteEndOfBlock(output);
        }
 
        // 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; 
            }

        }
 
        // compress the bytes in input history window
        private void GetCompressedOutput(OutputBuffer output) { 
 
            while (inputWindow.BytesAvailable > 0 && SafeToWriteTo(output)) {
 
                // Find next match. A match can be a symbol,
                // a distance/length pair, a symbol followed by a distance/Length pair
                inputWindow.GetNextSymbolOrMatch(currentMatch);
 
                if (currentMatch.State == MatchState.HasSymbol) {
                    WriteChar(currentMatch.Symbol, output); 
                } 
                else if (currentMatch.State == MatchState.HasMatch) {
                    WriteMatch(currentMatch.Length, currentMatch.Position, output); 
                }
                else {
                    WriteChar(currentMatch.Symbol, output);
                    WriteMatch(currentMatch.Length, currentMatch.Position, output); 
                }
            } 
        } 

        private bool InputAvailable(DeflateInput input) { 
            return input.Count > 0 || BytesInHistory > 0;
        }

        private bool SafeToWriteTo(OutputBuffer output) {  // can we safely continue writing to output buffer 
            return output.FreeBytes > FastEncoderStatics.MaxCodeLen;
        } 
 
        private void WriteEndOfBlock(OutputBuffer output) {
            // The fast encoder outputs one long block, so it just needs to terminate this block 
            const int EndOfBlockCode = 256;
            uint code_info = FastEncoderStatics.FastEncoderLiteralCodeInfo[EndOfBlockCode];
            int code_len = (int)(code_info & 31);
            output.WriteBits(code_len, code_info >> 5); 
        }
 
        static internal void WriteMatch(int matchLen, int matchPos, OutputBuffer output) { 
            Debug.Assert(matchLen >= FastEncoderWindow.MinMatch && matchLen <= FastEncoderWindow.MaxMatch, "Illegal currentMatch length!");
            Debug.WriteLineIf(CompressionTracingSwitch.Verbose, String.Format(CultureInfo.InvariantCulture, "Match: {0}:{1}", matchLen, matchPos), "Compression"); 

            // Get the code information for a match code
            uint codeInfo = FastEncoderStatics.FastEncoderLiteralCodeInfo[(FastEncoderStatics.NumChars + 1 - FastEncoderWindow.MinMatch) + matchLen];
            int codeLen = (int)codeInfo & 31; 
            Debug.Assert(codeLen != 0, "Invalid Match Length!");
            if (codeLen <= 16) { 
                output.WriteBits(codeLen, codeInfo >> 5); 
            }
            else { 
                output.WriteBits(16, (codeInfo >> 5) & 65535);
                output.WriteBits(codeLen - 16, codeInfo >> (5 + 16));
            }
 
            // Get the code information for a distance code
            codeInfo = FastEncoderStatics.FastEncoderDistanceCodeInfo[FastEncoderStatics.GetSlot(matchPos)]; 
            output.WriteBits((int)(codeInfo & 15), codeInfo >> 8); 
            int extraBits = (int)(codeInfo >> 4) & 15;
            if (extraBits != 0) { 
                output.WriteBits(extraBits, (uint)matchPos & FastEncoderStatics.BitMask[extraBits]);
            }
        }
 
        static internal void WriteChar(byte b, OutputBuffer output) {
            Debug.WriteLineIf(CompressionTracingSwitch.Verbose, String.Format(CultureInfo.InvariantCulture, "Literal: {0}", b ), "Compression"); 
 
            uint code = FastEncoderStatics.FastEncoderLiteralCodeInfo[b];
            output.WriteBits((int)code & 31, code >> 5); 
        }

        // Output the block type and tree structure for our hard-coded trees.
        // Contains following data: 
        //  "final" block flag 1 bit
        //  BLOCKTYPE_DYNAMIC 2 bits 
        //  FastEncoderLiteralTreeLength 
        //  FastEncoderDistanceTreeLength
        // 
        static internal void WriteDeflatePreamble(OutputBuffer output) {
            //Debug.Assert( bitCount == 0, "bitCount must be zero before writing tree bit!");

            output.WriteBytes(FastEncoderStatics.FastEncoderTreeStructureData, 0, FastEncoderStatics.FastEncoderTreeStructureData.Length); 
            output.WriteBits(FastEncoderStatics.FastEncoderPostTreeBitCount, FastEncoderStatics.FastEncoderPostTreeBitBuf);
        } 
 
    }
 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
namespace System.IO.Compression { 
    using System;
    using System.Diagnostics;
    using System.Globalization;
 
    internal class FastEncoder {
 
        private FastEncoderWindow inputWindow; // input history window 
        private Match currentMatch;            // current match in history window
        private double lastCompressionRatio; 

        public FastEncoder() {
            inputWindow = new FastEncoderWindow();
            currentMatch = new Match(); 
        }
 
        internal int BytesInHistory { 
            get {
                return inputWindow.BytesAvailable; 
            }
        }

        internal DeflateInput UnprocessedInput { 
            get {
                return inputWindow.UnprocessedInput; 
            } 
        }
 
        internal void FlushInput() {
            inputWindow.FlushWindow();
        }
 
        internal Double LastCompressionRatio {
            get { return lastCompressionRatio; } 
        } 

        // 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); 
        }
 
        // 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);
        } 

        internal void GetBlockHeader(OutputBuffer output) { 
            WriteDeflatePreamble(output); 
        }
 
        internal void GetBlockFooter(OutputBuffer output) {
            WriteEndOfBlock(output);
        }
 
        // 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; 
            }

        }
 
        // compress the bytes in input history window
        private void GetCompressedOutput(OutputBuffer output) { 
 
            while (inputWindow.BytesAvailable > 0 && SafeToWriteTo(output)) {
 
                // Find next match. A match can be a symbol,
                // a distance/length pair, a symbol followed by a distance/Length pair
                inputWindow.GetNextSymbolOrMatch(currentMatch);
 
                if (currentMatch.State == MatchState.HasSymbol) {
                    WriteChar(currentMatch.Symbol, output); 
                } 
                else if (currentMatch.State == MatchState.HasMatch) {
                    WriteMatch(currentMatch.Length, currentMatch.Position, output); 
                }
                else {
                    WriteChar(currentMatch.Symbol, output);
                    WriteMatch(currentMatch.Length, currentMatch.Position, output); 
                }
            } 
        } 

        private bool InputAvailable(DeflateInput input) { 
            return input.Count > 0 || BytesInHistory > 0;
        }

        private bool SafeToWriteTo(OutputBuffer output) {  // can we safely continue writing to output buffer 
            return output.FreeBytes > FastEncoderStatics.MaxCodeLen;
        } 
 
        private void WriteEndOfBlock(OutputBuffer output) {
            // The fast encoder outputs one long block, so it just needs to terminate this block 
            const int EndOfBlockCode = 256;
            uint code_info = FastEncoderStatics.FastEncoderLiteralCodeInfo[EndOfBlockCode];
            int code_len = (int)(code_info & 31);
            output.WriteBits(code_len, code_info >> 5); 
        }
 
        static internal void WriteMatch(int matchLen, int matchPos, OutputBuffer output) { 
            Debug.Assert(matchLen >= FastEncoderWindow.MinMatch && matchLen <= FastEncoderWindow.MaxMatch, "Illegal currentMatch length!");
            Debug.WriteLineIf(CompressionTracingSwitch.Verbose, String.Format(CultureInfo.InvariantCulture, "Match: {0}:{1}", matchLen, matchPos), "Compression"); 

            // Get the code information for a match code
            uint codeInfo = FastEncoderStatics.FastEncoderLiteralCodeInfo[(FastEncoderStatics.NumChars + 1 - FastEncoderWindow.MinMatch) + matchLen];
            int codeLen = (int)codeInfo & 31; 
            Debug.Assert(codeLen != 0, "Invalid Match Length!");
            if (codeLen <= 16) { 
                output.WriteBits(codeLen, codeInfo >> 5); 
            }
            else { 
                output.WriteBits(16, (codeInfo >> 5) & 65535);
                output.WriteBits(codeLen - 16, codeInfo >> (5 + 16));
            }
 
            // Get the code information for a distance code
            codeInfo = FastEncoderStatics.FastEncoderDistanceCodeInfo[FastEncoderStatics.GetSlot(matchPos)]; 
            output.WriteBits((int)(codeInfo & 15), codeInfo >> 8); 
            int extraBits = (int)(codeInfo >> 4) & 15;
            if (extraBits != 0) { 
                output.WriteBits(extraBits, (uint)matchPos & FastEncoderStatics.BitMask[extraBits]);
            }
        }
 
        static internal void WriteChar(byte b, OutputBuffer output) {
            Debug.WriteLineIf(CompressionTracingSwitch.Verbose, String.Format(CultureInfo.InvariantCulture, "Literal: {0}", b ), "Compression"); 
 
            uint code = FastEncoderStatics.FastEncoderLiteralCodeInfo[b];
            output.WriteBits((int)code & 31, code >> 5); 
        }

        // Output the block type and tree structure for our hard-coded trees.
        // Contains following data: 
        //  "final" block flag 1 bit
        //  BLOCKTYPE_DYNAMIC 2 bits 
        //  FastEncoderLiteralTreeLength 
        //  FastEncoderDistanceTreeLength
        // 
        static internal void WriteDeflatePreamble(OutputBuffer output) {
            //Debug.Assert( bitCount == 0, "bitCount must be zero before writing tree bit!");

            output.WriteBytes(FastEncoderStatics.FastEncoderTreeStructureData, 0, FastEncoderStatics.FastEncoderTreeStructureData.Length); 
            output.WriteBits(FastEncoderStatics.FastEncoderPostTreeBitCount, FastEncoderStatics.FastEncoderPostTreeBitBuf);
        } 
 
    }
 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK