Пример #1
0
        private byte[] PatternCompress(byte[] data)
        {
            for (int i = 0; i < data.Length; i++)
            {
                UInt16 matchCount     = 0;
                int    current        = data[i];
                int    lookupPos      = 0;
                UInt16 bestMatchCount = 0;
                int    bestMatchPos   = 0;

                if (i < data.Length - 2)
                {
                    byte current2 = data[i + 1];
                    byte current3 = data[i + 2];

                    T key = (T)current << 16;
                    key |= (T)current2 << 8;
                    key |= (T)current3;

                    int prevIndex = (int)patternHashArray[key];

                    int currentPrevIndex = prevIndex;


                    bestMatchCount = 0;
                    bestMatchPos   = 0;
                    if (prevIndex != 0)
                    {
                        do
                        {
                            matchCount = 0;
                            PatternLink link = patternLinkArray[currentPrevIndex];
                            lookupPos = (int)link.FilePosition;

                            while (matchCount + i < data.Length && matchCount < UInt16.MaxValue &&
                                   data[i + matchCount] == data[lookupPos + matchCount])
                            {
                                matchCount++;
                            }

                            //matchCount --;

                            if (matchCount > bestMatchCount)
                            {
                                bestMatchCount = matchCount;
                                bestMatchPos   = lookupPos;
                            }

                            currentPrevIndex = link.NextMatch;
                        } while (currentPrevIndex != 0);
                    }


                    patternHashArray[key] = (T)i + 1;
                    PatternLink newLink = new PatternLink();
                    newLink.FilePosition    = (T)i;
                    newLink.NextMatch       = prevIndex;
                    patternLinkArray[i + 1] = newLink;
                }

                int relativeLookupPos = i - bestMatchPos;

                if (bestMatchCount > 4 && relativeLookupPos < 0x100 && bestMatchCount < 0x100)
                {
                    WriteBytes(escapeByte, 1);
                    WriteBytes(0u, 1); // 0 = short relative
                    WriteBytes((T)bestMatchCount, 1);
                    WriteBytes((T)relativeLookupPos, 1);
                    i += bestMatchCount - 1;
                }
                else if (bestMatchCount > 5 && relativeLookupPos < 0x10000 && bestMatchCount < 0x100)
                {
                    WriteBytes(escapeByte, 1);
                    WriteBytes(1u, 1); // 1 = 65k range relative
                    WriteBytes((T)bestMatchCount, 1);
                    WriteBytes((T)relativeLookupPos, 2);

                    i += bestMatchCount - 1;
                }
                else if (bestMatchCount > 8)
                {
                    WriteBytes(escapeByte, 1);
                    WriteBytes(2u, 1); // long lookup
                    WriteBytes((T)bestMatchCount, 2);
                    WriteBytes((T)bestMatchPos, 4);
                    i += bestMatchCount - 1;
                }
                else
                {
                    WriteBytes((T)current, 1);
                }
            }


            byte[] compressedBytes = new byte[compressedStream.Length];
            compressedStream.Position = 0;
            compressedStream.Read(compressedBytes, 0, compressedBytes.Length);
            return(compressedBytes);
        }
        private byte[] PatternCompress(byte[] data)
        {
            for (int i = 0; i < data.Length; i++)
            {
                UInt16 matchCount = 0;
                int current = data[i];
                int lookupPos = 0;
                UInt16 bestMatchCount = 0;
                int bestMatchPos = 0;

                if (i < data.Length - 2)
                {
                    byte current2 = data[i + 1];
                    byte current3 = data[i + 2];

                    T key = (T) current << 16;
                    key |= (T) current2 << 8;
                    key |= (T) current3;

                    int prevIndex = (int) patternHashArray[key];

                    int currentPrevIndex = prevIndex;

                    bestMatchCount = 0;
                    bestMatchPos = 0;
                    if (prevIndex != 0)
                    {
                        do
                        {
                            matchCount = 0;
                            PatternLink link = patternLinkArray[currentPrevIndex];
                            lookupPos = (int) link.FilePosition;

                            while (matchCount + i < data.Length && matchCount < UInt16.MaxValue &&
                                   data[i + matchCount] == data[lookupPos + matchCount])
                                matchCount++;

                            //matchCount --;

                            if (matchCount > bestMatchCount)
                            {
                                bestMatchCount = matchCount;
                                bestMatchPos = lookupPos;
                            }

                            currentPrevIndex = link.NextMatch;
                        } while (currentPrevIndex != 0);
                    }

                    patternHashArray[key] = (T) i + 1;
                    PatternLink newLink = new PatternLink();
                    newLink.FilePosition = (T) i;
                    newLink.NextMatch = prevIndex;
                    patternLinkArray[i + 1] = newLink;
                }

                int relativeLookupPos = i - bestMatchPos;

                if (bestMatchCount > 4 && relativeLookupPos < 0x100 && bestMatchCount < 0x100)
                {
                    WriteBytes(escapeByte, 1);
                    WriteBytes(0u, 1); // 0 = short relative
                    WriteBytes((T) bestMatchCount, 1);
                    WriteBytes((T) relativeLookupPos, 1);
                    i += bestMatchCount - 1;
                }
                else if (bestMatchCount > 5 && relativeLookupPos < 0x10000 && bestMatchCount < 0x100)
                {
                    WriteBytes(escapeByte, 1);
                    WriteBytes(1u, 1); // 1 = 65k range relative
                    WriteBytes((T) bestMatchCount, 1);
                    WriteBytes((T) relativeLookupPos, 2);

                    i += bestMatchCount - 1;
                }
                else if (bestMatchCount > 8)
                {
                    WriteBytes(escapeByte, 1);
                    WriteBytes(2u, 1); // long lookup
                    WriteBytes((T) bestMatchCount, 2);
                    WriteBytes((T) bestMatchPos, 4);
                    i += bestMatchCount - 1;
                }
                else
                {
                    WriteBytes((T) current, 1);
                }
            }

            byte[] compressedBytes = new byte[compressedStream.Length];
            compressedStream.Position = 0;
            compressedStream.Read(compressedBytes, 0, compressedBytes.Length);
            return compressedBytes;
        }