GZipDecoder.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

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

                            namespace System.IO.Compression { 
    using System;
    using System.Diagnostics;

    // This class decodes GZip header and footer information. 
    // See RFC 1952 for details about the format.
    internal class GZipDecoder : IFileFormatReader { 
 
        private GzipHeaderState gzipHeaderSubstate;
        private GzipHeaderState gzipFooterSubstate; 

        private int gzip_header_flag;
        private int gzip_header_xlen;
        private uint expectedCrc32; 
        private uint expectedOutputStreamSize;
        private int loopCounter; 
        private uint actualCrc32; 
        private long actualStreamSize;
 
        public GZipDecoder() {
            Reset();
        }
 
        public void Reset() {
            gzipHeaderSubstate = GzipHeaderState.ReadingID1; 
            gzipFooterSubstate = GzipHeaderState.ReadingCRC; 
            expectedCrc32 = 0;
            expectedOutputStreamSize = 0; 
        }

        public bool ReadHeader(InputBuffer input) {
 
            while (true) {
                int bits; 
                switch (gzipHeaderSubstate) { 
                    case GzipHeaderState.ReadingID1:
                        bits = input.GetBits(8); 
                        if (bits < 0) {
                            return false;
                        }
 
                        if (bits != GZipConstants.ID1) {
                            throw new InvalidDataException(SR.GetString(SR.CorruptedGZipHeader)); 
                        } 
                        gzipHeaderSubstate = GzipHeaderState.ReadingID2;
                        goto case GzipHeaderState.ReadingID2; 

                    case GzipHeaderState.ReadingID2:
                        bits = input.GetBits(8);
                        if (bits < 0) { 
                            return false;
                        } 
 
                        if (bits != GZipConstants.ID2) {
                            throw new InvalidDataException(SR.GetString(SR.CorruptedGZipHeader)); 
                        }

                        gzipHeaderSubstate = GzipHeaderState.ReadingCM;
                        goto case GzipHeaderState.ReadingCM; 

                    case GzipHeaderState.ReadingCM: 
                        bits = input.GetBits(8); 
                        if (bits < 0) {
                            return false; 
                        }

                        if (bits != GZipConstants.Deflate) {         // compression mode must be 8 (deflate)
                            throw new InvalidDataException(SR.GetString(SR.UnknownCompressionMode)); 
                        }
 
                        gzipHeaderSubstate = GzipHeaderState.ReadingFLG; ; 
                        goto case GzipHeaderState.ReadingFLG;
 
                    case GzipHeaderState.ReadingFLG:
                        bits = input.GetBits(8);
                        if (bits < 0) {
                            return false; 
                        }
 
                        gzip_header_flag = bits; 
                        gzipHeaderSubstate = GzipHeaderState.ReadingMMTime;
                        loopCounter = 0; // 4 MMTIME bytes 
                        goto case GzipHeaderState.ReadingMMTime;

                    case GzipHeaderState.ReadingMMTime:
                        bits = 0; 
                        while (loopCounter < 4) {
                            bits = input.GetBits(8); 
                            if (bits < 0) { 
                                return false;
                            } 

                            loopCounter++;
                        }
 
                        gzipHeaderSubstate = GzipHeaderState.ReadingXFL;
                        loopCounter = 0; 
                        goto case GzipHeaderState.ReadingXFL; 

                    case GzipHeaderState.ReadingXFL:      // ignore XFL 
                        bits = input.GetBits(8);
                        if (bits < 0) {
                            return false;
                        } 

                        gzipHeaderSubstate = GzipHeaderState.ReadingOS; 
                        goto case GzipHeaderState.ReadingOS; 

                    case GzipHeaderState.ReadingOS:      // ignore OS 
                        bits = input.GetBits(8);
                        if (bits < 0) {
                            return false;
                        } 

                        gzipHeaderSubstate = GzipHeaderState.ReadingXLen1; 
                        goto case GzipHeaderState.ReadingXLen1; 

                    case GzipHeaderState.ReadingXLen1: 
                        if ((gzip_header_flag & (int)GZipOptionalHeaderFlags.ExtraFieldsFlag) == 0) {
                            goto case GzipHeaderState.ReadingFileName;
                        }
 
                        bits = input.GetBits(8);
                        if (bits < 0) { 
                            return false; 
                        }
 
                        gzip_header_xlen = bits;
                        gzipHeaderSubstate = GzipHeaderState.ReadingXLen2;
                        goto case GzipHeaderState.ReadingXLen2;
 
                    case GzipHeaderState.ReadingXLen2:
                        bits = input.GetBits(8); 
                        if (bits < 0) { 
                            return false;
                        } 

                        gzip_header_xlen |= (bits << 8);
                        gzipHeaderSubstate = GzipHeaderState.ReadingXLenData;
                        loopCounter = 0; // 0 bytes of XLEN data read so far 
                        goto case GzipHeaderState.ReadingXLenData;
 
                    case GzipHeaderState.ReadingXLenData: 
                        bits = 0;
                        while (loopCounter < gzip_header_xlen) { 
                            bits = input.GetBits(8);
                            if (bits < 0) {
                                return false;
                            } 

                            loopCounter++; 
                        } 
                        gzipHeaderSubstate = GzipHeaderState.ReadingFileName;
                        loopCounter = 0; 
                        goto case GzipHeaderState.ReadingFileName;

                    case GzipHeaderState.ReadingFileName:
                        if ((gzip_header_flag & (int)GZipOptionalHeaderFlags.FileNameFlag) == 0) { 
                            gzipHeaderSubstate = GzipHeaderState.ReadingComment;
                            goto case GzipHeaderState.ReadingComment; 
                        } 

                        do { 
                            bits = input.GetBits(8);
                            if (bits < 0) {
                                return false;
                            } 

                            if (bits == 0) {   // see '\0' in the file name string 
                                break; 
                            }
                        } while (true); 

                        gzipHeaderSubstate = GzipHeaderState.ReadingComment;
                        goto case GzipHeaderState.ReadingComment;
 
                    case GzipHeaderState.ReadingComment:
                        if ((gzip_header_flag & (int)GZipOptionalHeaderFlags.CommentFlag) == 0) { 
                            gzipHeaderSubstate = GzipHeaderState.ReadingCRC16Part1; 
                            goto case GzipHeaderState.ReadingCRC16Part1;
                        } 

                        do {
                            bits = input.GetBits(8);
                            if (bits < 0) { 
                                return false;
                            } 
 
                            if (bits == 0) {   // see '\0' in the file name string
                                break; 
                            }
                        } while (true);

                        gzipHeaderSubstate = GzipHeaderState.ReadingCRC16Part1; 
                        goto case GzipHeaderState.ReadingCRC16Part1;
 
                    case GzipHeaderState.ReadingCRC16Part1: 
                        if ((gzip_header_flag & (int)GZipOptionalHeaderFlags.CRCFlag) == 0) {
                            gzipHeaderSubstate = GzipHeaderState.Done; 
                            goto case GzipHeaderState.Done;
                        }

                        bits = input.GetBits(8);     // ignore crc 
                        if (bits < 0) {
                            return false; 
                        } 

                        gzipHeaderSubstate = GzipHeaderState.ReadingCRC16Part2; 
                        goto case GzipHeaderState.ReadingCRC16Part2;

                    case GzipHeaderState.ReadingCRC16Part2:
                        bits = input.GetBits(8);     // ignore crc 
                        if (bits < 0) {
                            return false; 
                        } 

                        gzipHeaderSubstate = GzipHeaderState.Done; 
                        goto case GzipHeaderState.Done;

                    case GzipHeaderState.Done:
                        return true; 
                    default:
                        Debug.Assert(false, "We should not reach unknown state!"); 
                        throw new InvalidDataException(SR.GetString(SR.UnknownState)); 
                }
            } 
        }

        public bool ReadFooter(InputBuffer input) {
            input.SkipToByteBoundary(); 
            if (gzipFooterSubstate == GzipHeaderState.ReadingCRC) {
                while (loopCounter < 4) { 
                    int bits = input.GetBits(8); 
                    if (bits < 0) {
                        return false; 
                    }

                    expectedCrc32 |= ((uint)bits << (8 * loopCounter));
                    loopCounter++; 
                }
                gzipFooterSubstate = GzipHeaderState.ReadingFileSize; 
                loopCounter = 0; 

            } 

            if (gzipFooterSubstate == GzipHeaderState.ReadingFileSize) {
                if (loopCounter == 0)
                    expectedOutputStreamSize = 0; 

                while (loopCounter < 4) { 
                    int bits = input.GetBits(8); 
                    if (bits < 0) {
                        return false; 
                    }

                    expectedOutputStreamSize |= ((uint)bits << (8 * loopCounter));
                    loopCounter++; 
                }
            } 
 
            return true;
        } 

        public void UpdateWithBytesRead(byte[] buffer, int offset, int copied) {
            actualCrc32 = Crc32Helper.UpdateCrc32(actualCrc32, buffer, offset, copied);
 
            long n = actualStreamSize + (uint)copied;
            if (n > GZipConstants.FileLengthModulo) { 
                long temp = Math.DivRem(n, GZipConstants.FileLengthModulo, out n); 
            }
            actualStreamSize = n; 
        }

        public void Validate() {
 
            if (expectedCrc32 != actualCrc32) {
                throw new InvalidDataException(SR.GetString(SR.InvalidCRC)); 
            } 

            if (actualStreamSize != expectedOutputStreamSize) { 
                throw new InvalidDataException(SR.GetString(SR.InvalidStreamSize));
            }
        }
 
        internal enum GzipHeaderState {
            // GZIP header 
            ReadingID1, 
            ReadingID2,
            ReadingCM, 
            ReadingFLG,
            ReadingMMTime, // iterates 4 times
            ReadingXFL,
            ReadingOS, 
            ReadingXLen1,
            ReadingXLen2, 
            ReadingXLenData, 
            ReadingFileName,
            ReadingComment, 
            ReadingCRC16Part1,
            ReadingCRC16Part2,
            Done, // done reading GZIP header
 
            // GZIP footer
            ReadingCRC, // iterates 4 times 
            ReadingFileSize // iterates 4 times 
        }
 
        [Flags]
        internal enum GZipOptionalHeaderFlags {
            CRCFlag = 2,
            ExtraFieldsFlag = 4, 
            FileNameFlag = 8,
            CommentFlag = 16 
        } 

    } 
}

// 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