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]; ulong key = (ulong)current << 16; key |= (ulong)current2 << 8; key |= (ulong)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] = (ulong)i+1; PatternLink newLink = new PatternLink() ; newLink.FilePosition = (ulong)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((ulong)bestMatchCount,1); WriteBytes((ulong)relativeLookupPos,1); i += bestMatchCount-1; } else if (bestMatchCount > 5 && relativeLookupPos < 0x10000 && bestMatchCount <0x100) { WriteBytes (escapeByte,1); WriteBytes (1u,1); // 1 = 65k range relative WriteBytes((ulong)bestMatchCount,1); WriteBytes((ulong)relativeLookupPos,2); i += bestMatchCount-1; } else if (bestMatchCount > 8 ) { WriteBytes (escapeByte,1); WriteBytes (2u,1); // long lookup WriteBytes((ulong)bestMatchCount,2); WriteBytes((ulong)bestMatchPos,4); i += bestMatchCount-1; } else { WriteBytes((ulong)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]; ulong key = (ulong)current << 16; key |= (ulong)current2 << 8; key |= (ulong)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] = (ulong)i + 1; PatternLink newLink = new PatternLink(); newLink.FilePosition = (ulong)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((ulong)bestMatchCount, 1); WriteBytes((ulong)relativeLookupPos, 1); i += bestMatchCount - 1; } else if (bestMatchCount > 5 && relativeLookupPos < 0x10000 && bestMatchCount < 0x100) { WriteBytes(escapeByte, 1); WriteBytes(1u, 1); // 1 = 65k range relative WriteBytes((ulong)bestMatchCount, 1); WriteBytes((ulong)relativeLookupPos, 2); i += bestMatchCount - 1; } else if (bestMatchCount > 8) { WriteBytes(escapeByte, 1); WriteBytes(2u, 1); // long lookup WriteBytes((ulong)bestMatchCount, 2); WriteBytes((ulong)bestMatchPos, 4); i += bestMatchCount - 1; } else { WriteBytes((ulong)current, 1); } } byte[] compressedBytes = new byte[compressedStream.Length]; compressedStream.Position = 0; compressedStream.Read(compressedBytes, 0, compressedBytes.Length); return(compressedBytes); }