Beispiel #1
0
        private static int GetCommand0ByteCount(byte[] buffer, int i)
        {
            int j = i + 1; // Forward iterator for buffer

            while (j < buffer.Length)
            {
                if (
                    #region A command is coming up
                    (
                        // Matches command 3
                        (j + 2) < buffer.Length &&
                        (buffer[j] == ((buffer[j + 1] - 1) & 0xFF) &&
                         buffer[j + 2] == ((buffer[j + 1] + 1) & 0xFF))
                    )
                    ||
                    (
                        // Matches command 1
                        (j + 2) < buffer.Length &&
                        (buffer[j] == buffer[j + 1] &&
                         buffer[j] == buffer[j + 2])
                    )
                    ||
                    (
                        // Matches command 2
                        (j + 3) < buffer.Length &&
                        (buffer[j] == buffer[j + 2] &&
                         buffer[j + 1] == buffer[j + 3])
                    )
                    ||
                    // Matches command 4 or 6
                    OptimalCompressor.IsBackCommandComing(buffer, j)
                    #endregion
                    )
                {
                    break;
                }

                j++;
            }

            return(j - i);
        }
Beispiel #2
0
        private static void CreateChildNodes(byte[] buffer, ChunkNodeCollection nodeCollection, int i, ChunkNode parentNode, ByteDictionary byteDictionary)
        {
            // NOTE: Command 5 (ie: the same as command 4 except it inverts each byte)
            // is not implemented, because it's almost never used.
            // Implementing it would complicate the code and slow down the compression for little to no benefit.

            // NOTE: Checking out command 0 every time (ie: putting it out of the if conditions)
            // can improve compression a tiny bit (like just one byte) in some rare cases,
            // but it's not worth the huge hit on compression speed.

            OptimalCompressor.CreateNodesFromBackCommands(nodeCollection, i, parentNode, byteDictionary);

            int command;
            int byteCount;

            if ((i + 1) < buffer.Length &&
                buffer[i] == buffer[i + 1])
            {
                command   = 1;
                byteCount = OptimalCompressor.GetCommand1ByteCount(buffer, i);
            }
            else if ((i + 2) < buffer.Length &&
                     buffer[i] == buffer[i + 2])
            {
                command   = 2;
                byteCount = OptimalCompressor.GetCommand2ByteCount(buffer, i);
            }
            else if ((i + 1) < buffer.Length &&
                     ((buffer[i] + 1) & 0xFF) == buffer[i + 1])
            {
                command   = 3;
                byteCount = OptimalCompressor.GetCommand3ByteCount(buffer, i);
            }
            else
            {
                command   = 0;
                byteCount = OptimalCompressor.GetCommand0ByteCount(buffer, i);
            }

            OptimalCompressor.CreateNodesFromCommand(command, byteCount, nodeCollection, i, parentNode);
        }
Beispiel #3
0
        public byte[] Compress(byte[] buffer)
        {
            ByteDictionary      byteDictionary = new ByteDictionary(buffer);
            ChunkNodeCollection nodeCollection = new ChunkNodeCollection();

            while (nodeCollection.Count > 0)
            {
                if (nodeCollection.IsNextNodeOptimal())
                {
                    KeyValuePair <int, ChunkNode> parentNode = nodeCollection.GetNextNode();

                    if (parentNode.Key < buffer.Length)
                    {
                        OptimalCompressor.CreateChildNodes(buffer, nodeCollection, parentNode.Key, parentNode.Value, byteDictionary);
                    }
                }
            }

            ChunkNode bestNode = nodeCollection[buffer.Length];

            return(bestNode.GetCompressedBuffer(buffer));
        }