Microsoft.Protocols.TestSuites.Common.Common.LZ77Decompress C# (CSharp) Method

LZ77Decompress() private static method

Decodes stream using Direct2 algorithm and decompresses using LZ77 algorithm.
private static LZ77Decompress ( byte inputStream, int actualSize ) : byte[]
inputStream byte The input stream needed to be decompressed.
actualSize int The expected size of the decompressed output stream.
return byte[]
        private static byte[] LZ77Decompress(byte[] inputStream, int actualSize)
        {
            if (inputStream == null)
            {
                throw new ArgumentNullException("inputStream");
            }

            #region Variables
            // To distinguish data from metadata in the compressed byte stream. [MS-OXCRPC], section 3.1.7.2.2.1.
            int bitMask;

            // Indicates the bit representing the next byte to be processed is "1".
            uint bitMaskPointer;

            // The count of bitmask.
            uint bitMaskCount;

            // Metadata offset.
            int offset;

            // The length of metadata.
            int length;

            // The container of redundant information which is used to reduce the size of input data.
            int metadata;

            // The length of metadata. For more detail, refer to [MS-OXCRPC], section 3.1.7.2.2.4.
            int metadataLength;

            // The additive length contained by the nibble of shared byte.
            int lengthInSharedByte;

            // The byte follows the bitmask.
            byte nextByte;

            // The byte follows the initial 2-byte metadata whenever the match length is greater than nine.
            // The nibble of this byte is "reserved" for the next metadata instance when the length is greater than nine.
            // For more detail, refer to [MS-OXCRPC], section 3.1.7.2.2.4.
            byte sharedByte;

            // Indicates which nibble of shared byte to be used. True indicates high-order nibble, false indicates low-order nibble.
            bool useSharedByteHighOrderNibble;

            // The count of bytes in inStream.
            int inputBytesCount;

            // The count of bytes in outStream.
            int outCount;
            #endregion

            #region Consts
            // Means the first 31 bytes are actual data. (1000 0000 0000 0000 0000 0000 0000 0000)
            // Uses as the beginning of checking bitmask.
            const uint BitMaskOf31ActualData = 0x80000000;

            // The high-order 13 bits are a first complement of the offset. (1111 1111 1111 1000)
            const int BitMaskOfHigh13AreFirstComplementOfOffset = 0xFFF8;

            // The size of metadata. [MS-OXCRPC], section 3.1.7.2.2.3.
            const int SizeOfMetadata = sizeof(short);

            // The size of shared byte.
            const int SizeOfSharedByte = sizeof(byte);

            // The low-order three bits are the length. [MS-OXCRPC], section 3.1.7.2.2.3.
            const int OffsetOfLengthInMetadata = 3;

            // The three bits in the original two bytes of metadata with value b'111'
            const int BitSetLower3Bits = 0x7;

            // The size of nibble in shared byte.
            const int SizeOfNibble = 4;

            // The minimum match is 3 bytes. [MS-OXCRPC], section 3.1.7.2.2.4.
            const int SizeOfMinimumMatch = 3;

            // Three low-order bits of the 2-bytes metadata allow for the expression of lengths from 3 to 9.
            // Because 3 is the minimum match and b'111' is reserved.
            // So every time the match length is greater than 9, there will be an additional byte follows the initial 2-byte metadata.
            // Refer to [MS-OXCRPC], section 3.1.7.2.2.4.
            const int MatchLengthWithAdditionalByte = 10;

            // The shared byte with value 1111.
            const byte SharedByteSetLow4Bits = 0xF;

            // The next byte with value 11111111.
            const byte NextByteSetAllBits = 0xFF;

            // The size of final two bytes which is used to calculate the match length equal or greater than 280.
            const int SizeOfFinalTwoBytes = 4;

            // Each bit in bitmask (4 bytes) can distinguish data from metadata in the compressed byte stream.
            const int CountOfBitmask = 32;

            #endregion

            byte[] outStream = new byte[actualSize];
            int size = inputStream.Length;

            outCount = 0;
            inputBytesCount = 0;
            useSharedByteHighOrderNibble = false;
            sharedByte = 0;
            while (inputBytesCount < size)
            {
                bitMask = BitConverter.ToInt32(inputStream, inputBytesCount);

                // The size of bitmask is 4 bytes.
                inputBytesCount += sizeof(uint);
                bitMaskPointer = BitMaskOf31ActualData;
                bitMaskCount = 0;
                do
                {
                    // The size of RPC_HEADER_EXT.
                    if (inputBytesCount < size)
                    {
                        // If the next byte in inStream is not metadata
                        if ((bitMask & bitMaskPointer) == 0)
                        {
                            outStream[outCount] = inputStream[inputBytesCount];
                            outCount++;
                            inputBytesCount++;

                            // Move to the next bitmask.
                            bitMaskPointer >>= 1;
                            bitMaskCount++;
                        }
                        else
                        {
                            // If next set of bytes is metadata, count offset and length
                            // This protocol assumes the metadata is two bytes in length
                            metadata = (int)BitConverter.ToInt16(inputStream, inputBytesCount);

                            // The high-order 13 bits are a first complement of the offset
                            offset = (metadata & BitMaskOfHigh13AreFirstComplementOfOffset) >> OffsetOfLengthInMetadata;
                            offset++;

                            #region Count Length
                            // If three bits in the original two bytes of metadata is not b'111', length equals to bit value plus 3. (Less than 10)
                            if ((metadata & BitSetLower3Bits) != BitSetLower3Bits)
                            {
                                length = (metadata & BitSetLower3Bits) + SizeOfMinimumMatch;
                                metadataLength = SizeOfMetadata;
                            }
                            else
                            {
                                // If three bits in the original two bytes of metadata is b'111', need shared byte. (Larger than 9)
                                // First time use low-order nibble
                                if (!useSharedByteHighOrderNibble)
                                {
                                    sharedByte = inputStream[inputBytesCount + SizeOfMetadata];
                                    lengthInSharedByte = sharedByte & SharedByteSetLow4Bits;

                                    // Next time will use high-order nibble of shared byte.
                                    useSharedByteHighOrderNibble = true;
                                    metadataLength = SizeOfMetadata + SizeOfSharedByte;
                                }
                                else
                                {
                                    // Next time use high-order nibble
                                    lengthInSharedByte = sharedByte >> SizeOfNibble;

                                    // Next time will use low-order nibble of shared byte.
                                    useSharedByteHighOrderNibble = false;
                                    metadataLength = SizeOfMetadata;
                                }

                                // If length in shared byte is not b'1111', length equals to 3+7+lengthInSharedByte
                                if (lengthInSharedByte != SharedByteSetLow4Bits)
                                {
                                    length = MatchLengthWithAdditionalByte + lengthInSharedByte;
                                }
                                else
                                {
                                    // If length in shared byte is b'1111'(larger than 24), next byte will be use.
                                    if (useSharedByteHighOrderNibble)
                                    {
                                        nextByte = inputStream[inputBytesCount + SizeOfMetadata + 1];
                                    }
                                    else
                                    {
                                        nextByte = inputStream[inputBytesCount + SizeOfMetadata];
                                    }

                                    // If next byte is not b'11111111', length equals to 3+7+lengthInSharedByte + nextByte
                                    if (nextByte != NextByteSetAllBits)
                                    {
                                        length = MatchLengthWithAdditionalByte + lengthInSharedByte + nextByte;
                                        metadataLength++;
                                    }
                                    else
                                    {
                                        // If next byte is b'11111111' (larger than 279), use the next two bytes to represent length
                                        // These two bytes represent a length of 277+3 (minimum match length)
                                        length = (int)BitConverter.ToInt16(inputStream, inputBytesCount + SizeOfFinalTwoBytes) + SizeOfMinimumMatch;
                                        metadataLength += SizeOfMinimumMatch;
                                    }
                                }
                            }
                            #endregion

                            for (int counter = 0; counter < length; counter++)
                            {
                                outStream[outCount + counter] = outStream[outCount - offset + counter];
                            }

                            inputBytesCount += metadataLength;
                            outCount += length;

                            // Move to the next bitmask.
                            bitMaskPointer >>= 1;
                            bitMaskCount++;
                        }
                    }
                    else
                    {
                        break;
                    }
                }
                while (bitMaskCount != CountOfBitmask);
            }

            // If the output stream's length doesn't equal to the expected size, the decompression is failed.
            if (outCount != actualSize)
            {
                throw new InvalidOperationException(string.Format("Decompression failed because decompressed byte array length ({0}) doesn't equal to the expected length ({1}).", outCount, actualSize));
            }

            return outStream;
        }
    }
Common