Example #1
0
            // Decompresses a Lempel-Ziv buffer.
            // TODO: Add documentation
            private static void DecompressBuffer(Stream decompStream, Stream compStream /*Starting at + 20*/)
            {
                //Create sliding dictionary buffer and clear first 4078 bytes of dictionary buffer to 0
                byte[] slidingDict = new byte[SLIDING_LEN];

                //Set an offset to the dictionary insertion point
                uint dictInsertionOffset = SLIDING_LEN - 18;

                // Current chunk header
                ChunkHeader chunkHeader = new ChunkHeader(compStream);

                while (decompStream.Position < decompStream.Length)
                {
                    // Each chunk header is a byte and is a collection of 8 flags

                    // If the flag is set, load a character
                    if (chunkHeader.ReadFlag())
                    {
                        // Copy the character
                        // TODO: Add exceptions
                        byte rawByte = (byte)compStream.ReadByte();

                        decompStream.WriteByte(rawByte);
                        // Add the character to the dictionary, and slide the dictionary
                        slidingDict[dictInsertionOffset++] = rawByte;
                        dictInsertionOffset &= SLIDING_MASK;
                    }
                    // If the flag is clear, load an offset/length pair
                    else
                    {
                        // Load the offset/length pair
                        OffsetLengthPair olPair = new OffsetLengthPair(compStream);
                        // Get the offset from the offset/length pair
                        int offset = olPair.Offset;

                        // Get the length from the offset/length pair
                        int length = olPair.Length;

                        for (int i = 0; i < length; i++)
                        {
                            byte rawByte = slidingDict[(offset + i) & SLIDING_MASK];
                            decompStream.WriteByte(rawByte);

                            if (decompStream.Position >= decompStream.Length)
                            {
                                return;
                            }

                            // Add the character to the dictionary, and slide the dictionary
                            slidingDict[dictInsertionOffset++] = rawByte;
                            dictInsertionOffset &= SLIDING_MASK;
                        }
                    }
                }
            }
        /// <summary>
        /// Compress the input buffer and write it into output stream.
        /// </summary>
        /// <param name="input">The buffer needed to be compressed</param>
        private void CompressCore(byte[] input, int maxBit = 16)
        {
            int compressIndex       = 0;
            int lookAheadBytesCount = 0;

            //we don't need to find match for the last two bytes, because it
            //alway can't be found.
            while (compressIndex < (input.Length - (minimumEncodeLength - 1)))
            {
                OffsetLengthPair match = FindMatchInSlidingWindow(input, compressIndex);
                if (match.Length == 0)
                {
                    //if there is no match, move forward one byte
                    lookAheadBytesCount = 1;
                    EncodeLiteral(input[compressIndex]);
                }
                else
                {
                    lookAheadBytesCount = match.Length;
                    EncodeOffsetLengthPair(match, maxBit);
                }

                byte[] lookAheadBuffer = new byte[lookAheadBytesCount];
                Array.Copy(input, compressIndex, lookAheadBuffer, 0, lookAheadBuffer.Length);
                hashTable.Update(lookAheadBuffer);
                slidingWindow.Update(lookAheadBuffer);

                compressIndex += lookAheadBytesCount;
            }

            // upate hash table and sliding window
            byte[] toBeUptated = new byte[input.Length - compressIndex];
            Array.Copy(input, compressIndex, toBeUptated, 0, toBeUptated.Length);
            hashTable.Update(toBeUptated);
            slidingWindow.Update(toBeUptated);

            while (compressIndex < input.Length)
            {
                EncodeLiteral(input[compressIndex]);
                compressIndex++;
            }

            //write the last byte to output stream if it exists
            if (remainBitsCount > 0)
            {
                outputStream.WriteByte((byte)(remain << (oneByteBitsCount - remainBitsCount)));
                remainBitsCount = 0;
            }

            outputStream.Flush();
        }
Example #3
0
            // Decompresses a Lempel-Ziv buffer.
            // TODO: Add documentation
            private static void DecompressBuffer(byte[] decompBuf, byte[] compBuf /*Starting at + 20*/)
            {
                OffsetLengthPair olPair = new OffsetLengthPair();

                int compBufPtr   = 0;
                int decompBufPtr = 0;

                //Create sliding dictionary buffer and clear first 4078 bytes of dictionary buffer to 0
                byte[] slidingDict = new byte[SLIDING_LEN];

                //Set an offset to the dictionary insertion point
                uint dictInsertionOffset = SLIDING_LEN - 18;

                // Current chunk header
                ChunkHeader chunkHeader = new ChunkHeader();

                while (decompBufPtr < decompBuf.Length)
                {
                    // At the start of each chunk...
                    if (!chunkHeader.ReadFlag(out bool flag))
                    {
                        // Load the chunk header
                        chunkHeader = new ChunkHeader(compBuf[compBufPtr++]);
                        chunkHeader.ReadFlag(out flag);
                    }

                    // Each chunk header is a byte and is a collection of 8 flags

                    // If the flag is set, load a character
                    if (flag)
                    {
                        // Copy the character
                        byte rawByte = compBuf[compBufPtr++];
                        decompBuf[decompBufPtr++] = rawByte;

                        // Add the character to the dictionary, and slide the dictionary
                        slidingDict[dictInsertionOffset++] = rawByte;
                        dictInsertionOffset &= SLIDING_MASK;
                    }
                    // If the flag is clear, load an offset/length pair
                    else
                    {
                        // Load the offset/length pair
                        olPair.highByte = compBuf[compBufPtr++];
                        olPair.lowByte  = compBuf[compBufPtr++];

                        // Get the offset from the offset/length pair
                        int offset = olPair.Offset;

                        // Get the length from the offset/length pair
                        int length = olPair.Length;

                        for (int i = 0; i < length; i++)
                        {
                            byte rawByte = slidingDict[(offset + i) & SLIDING_MASK];
                            decompBuf[decompBufPtr++] = rawByte;

                            if (decompBufPtr >= decompBuf.Length)
                            {
                                return;
                            }

                            // Add the character to the dictionary, and slide the dictionary
                            slidingDict[dictInsertionOffset++] = rawByte;
                            dictInsertionOffset &= SLIDING_MASK;
                        }
                    }
                }
            }
 /// <summary>
 /// Encode offset and length according to RFC2118
 /// </summary>
 /// <param name="pair">offset and length pair</param>
 private void EncodeOffsetLengthPair(OffsetLengthPair pair, int maxBit = 16)
 {
     EncodeOffset(pair.Offset);
     EncodeLength(pair.Length, maxBit);
 }
        private OffsetLengthPair FindMatchInSlidingWindow(byte[] input, int startIndex)
        {
            OffsetLengthPair match = new OffsetLengthPair();

            if ((input.Length - startIndex) < minimumEncodeLength)
            {
                return(match);
            }

            //create minimumEncodeLength bytes key
            byte[] threeBytesHashKey = new byte[minimumEncodeLength];
            Array.Copy(input, startIndex, threeBytesHashKey, 0, threeBytesHashKey.Length);
            int[] findedPositions = hashTable.GetKeyMatchPositions(threeBytesHashKey);

            //because hash table does not contain the hash value of last two characters
            //so we need to caculate it after getting hash value from hash table.
            List <int> matchPositions = new List <int>(findedPositions);

            // indicate the match position
            int  matchedPosition = -1;
            bool isMatchFound    = false;

            // if sliding windows count <=0, there is no match can be found, so do nothing
            if (slidingWindow.Count > 0)
            {
                // test if there is a match at the last position of sliding windows
                if (slidingWindow[slidingWindow.Count - 1] == input[startIndex] &&
                    input[startIndex] == input[startIndex + 1] &&
                    input[startIndex + 1] == input[startIndex + 2])
                {
                    // the position is the last byte in sliding window
                    matchedPosition = slidingWindow.Count - 1;
                    isMatchFound    = true;
                }
                // test if there is a match at the second last position of sliding windows
                if (slidingWindow.Count > 1)
                {
                    if (slidingWindow[slidingWindow.Count - 2] == input[startIndex] &&
                        slidingWindow[slidingWindow.Count - 1] == input[startIndex + 1] &&
                        input[startIndex] == input[startIndex + 2])
                    {
                        // the position is the second last byte in sliding window
                        matchPositions.Add(slidingWindow.Count - 2);
                        isMatchFound = true;
                    }
                }
            }

            //make sure the position will be added in ascending order.
            if (matchedPosition != -1)
            {
                matchPositions.Add(matchedPosition);
            }

            // translate list to array if match is found from the second last position of sliding window
            if (isMatchFound)
            {
                findedPositions = matchPositions.ToArray();
            }

            // if there is no match, return default match
            if (findedPositions == null || findedPositions.Length == 0)
            {
                return(match);
            }

            //caculate the offset and length
            match.Offset = slidingWindow.Count - findedPositions[findedPositions.Length - 1];
            match.Length = minimumEncodeLength;

            for (int i = 0; i < findedPositions.Length; i++)
            {
                //skip already matched 3 characters
                int searchIndex = startIndex + minimumEncodeLength;

                int j;

                for (j = (findedPositions[i] + minimumEncodeLength); j < slidingWindow.Count; j++)
                {
                    // get the last unmatched position
                    if ((searchIndex == input.Length) ||
                        (slidingWindow[j] != input[searchIndex++]))
                    {
                        if (match.Length < (searchIndex - startIndex - 1))
                        {
                            match.Length = searchIndex - startIndex - 1;
                            match.Offset = slidingWindow.Count - findedPositions[i];
                        }
                        break;
                    }
                }

                // if length > offset
                if (j >= slidingWindow.Count)
                {
                    int mark = startIndex;

                    // the last two character case
                    if (j > 0)
                    {
                        mark = startIndex + j - slidingWindow.Count;
                    }

                    //continue find match against the current data
                    while (searchIndex < input.Length)
                    {
                        if (input[mark++] != input[searchIndex++])
                        {
                            // because upper line use searchIndex++, so at this position
                            // we need to reduce it by 1;
                            if (match.Length < (searchIndex - startIndex - 1))
                            {
                                match.Length = searchIndex - startIndex - 1;
                                match.Offset = slidingWindow.Count - findedPositions[i];
                            }
                            break;
                        }
                    }

                    // if searchIndex == inputLength, the way to caculate offset and length
                    // is different with the normal situation.
                    if (searchIndex == input.Length)
                    {
                        if (match.Length < searchIndex - startIndex)
                        {
                            match.Length = searchIndex - startIndex;
                            match.Offset = slidingWindow.Count - findedPositions[i];
                        }
                    }
                }
            }

            return(match);
        }
        private OffsetLengthPair FindMatchInSlidingWindow(byte[] input, int startIndex)
        {
            OffsetLengthPair match = new OffsetLengthPair();

            if ((input.Length - startIndex) < minimumEncodeLength)
            {
                return match;
            }

            //create minimumEncodeLength bytes key
            byte[] threeBytesHashKey = new byte[minimumEncodeLength];
            Array.Copy(input, startIndex, threeBytesHashKey, 0, threeBytesHashKey.Length);
            int[] findedPositions = hashTable.GetKeyMatchPositions(threeBytesHashKey);

            //because hash table does not contain the hash value of last two characters
            //so we need to caculate it after getting hash value from hash table.
            List<int> matchPositions = new List<int>(findedPositions);

            // indicate the match position
            int matchedPosition = -1;
            bool isMatchFound = false;

            // if sliding windows count <=0, there is no match can be found, so do nothing
            if (slidingWindow.Count > 0)
            {
                // test if there is a match at the last position of sliding windows
                if (slidingWindow[slidingWindow.Count - 1] == input[startIndex]
                    && input[startIndex] == input[startIndex + 1]
                    && input[startIndex + 1] == input[startIndex + 2])
                {
                    // the position is the last byte in sliding window
                    matchedPosition  = slidingWindow.Count-1;
                    isMatchFound = true;
                }
                // test if there is a match at the second last position of sliding windows
                if (slidingWindow.Count > 1)
                {
                    if (slidingWindow[slidingWindow.Count - 2] == input[startIndex]
                        && slidingWindow[slidingWindow.Count - 1] == input[startIndex + 1]
                        && input[startIndex] == input[startIndex + 2])
                    {
                        // the position is the second last byte in sliding window
                        matchPositions.Add(slidingWindow.Count - 2);
                        isMatchFound = true;
                    }
                }
            }

            //make sure the position will be added in ascending order.
            if (matchedPosition != -1)
            {
                matchPositions.Add(matchedPosition);
            }

            // translate list to array if match is found from the second last position of sliding window
            if (isMatchFound)
            {
                findedPositions = matchPositions.ToArray();
            }

            // if there is no match, return default match
            if (findedPositions == null || findedPositions.Length == 0)
            {
                return match;
            }

            //caculate the offset and length
            match.Offset = slidingWindow.Count - findedPositions[findedPositions.Length - 1];
            match.Length = minimumEncodeLength;

            for (int i = 0; i < findedPositions.Length; i++)
            {
                //skip already matched 3 characters
                int searchIndex = startIndex + minimumEncodeLength;

                int j;

                for (j = (findedPositions[i]+minimumEncodeLength); j < slidingWindow.Count; j++)
                {
                    // get the last unmatched position
                    if ((searchIndex == input.Length)
                        || (slidingWindow[j] != input[searchIndex++]))
                    {
                        if (match.Length < (searchIndex - startIndex -1))
                        {
                            match.Length = searchIndex - startIndex -1;
                            match.Offset = slidingWindow.Count - findedPositions[i];
                        }
                        break;
                    }
                }

                // if length > offset
                if (j >= slidingWindow.Count)
                {
                    int mark = startIndex;

                    // the last two character case
                    if (j > 0)
                    {
                        mark = startIndex + j - slidingWindow.Count;
                    }

                    //continue find match against the current data
                    while (searchIndex < input.Length)
                    {
                        if (input[mark++] != input[searchIndex++])
                        {
                            // because upper line use searchIndex++, so at this position
                            // we need to reduce it by 1;
                            if (match.Length < (searchIndex - startIndex - 1))
                            {
                                match.Length = searchIndex - startIndex - 1;
                                match.Offset = slidingWindow.Count - findedPositions[i];
                            }
                            break;
                        }
                    }

                    // if searchIndex == inputLength, the way to caculate offset and length
                    // is different with the normal situation.
                    if (searchIndex == input.Length)
                    {
                        if (match.Length < searchIndex - startIndex)
                        {
                            match.Length = searchIndex - startIndex;
                            match.Offset = slidingWindow.Count - findedPositions[i];
                        }
                    }
                }
            }

            return match;
        }
 /// <summary>
 /// Encode offset and length according to RFC2118
 /// </summary>
 /// <param name="pair">offset and length pair</param>
 private void EncodeOffsetLengthPair(OffsetLengthPair pair)
 {
     EncodeOffset(pair.Offset);
     EncodeLength(pair.Length);
 }
Example #8
0
 /// <summary>
 /// Encode offset and length according to RFC2118
 /// </summary>
 /// <param name="pair">offset and length pair</param>
 private void EncodeOffsetLengthPair(OffsetLengthPair pair)
 {
     EncodeOffset(pair.Offset);
     EncodeLength(pair.Length);
 }
 /// <summary>
 /// Encode offset and length according to RFC2118
 /// </summary>
 /// <param name="pair">offset and length pair</param>
 private void EncodeOffsetLengthPair(OffsetLengthPair pair, int maxBit = 16)
 {
     EncodeOffset(pair.Offset);
     EncodeLength(pair.Length, maxBit);
 }