private static void Push(UInt16BE_NE_H_OutputBitStream bitStream, bool bit, Stream destination, MemoryStream data) { if (bitStream.Push(bit)) { byte[] bytes = data.ToArray(); destination.Write(bytes, 0, bytes.Length); data.SetLength(0); } }
private static void EncodeInternal(Stream destination, byte[] buffer, long slidingWindow, long recLength, long size) { UInt16BE_NE_H_OutputBitStream bitStream = new UInt16BE_NE_H_OutputBitStream(destination); MemoryStream data = new MemoryStream(); if (size > 0) { long bPointer = 2, longestMatchOffset = 0; bitStream.Push(false); NeutralEndian.Write1(data, buffer[0]); NeutralEndian.Write1(data, buffer[1]); while (bPointer < size) { long matchMax = Math.Min(recLength, size - bPointer); long backSearchMax = Math.Max(bPointer - slidingWindow, 0); long longestMatch = 2; long backSearch = bPointer; do { backSearch -= 2; long currentCount = 0; while (buffer[backSearch + currentCount] == buffer[bPointer + currentCount] && buffer[backSearch + currentCount + 1] == buffer[bPointer + currentCount + 1]) { currentCount += 2; if (currentCount >= matchMax) { // Match is as big as the look-forward buffer (or file) will let it be break; } } if (currentCount > longestMatch) { // New 'best' match longestMatch = currentCount; longestMatchOffset = backSearch; } } while (backSearch > backSearchMax); // Repeat for as far back as search buffer will let us long iCount = longestMatch / 2; // Comper counts in words (16 bits) long iOffset = (longestMatchOffset - bPointer) / 2; // Comper's offsets count in words (16-bits) if (iCount == 1) { // Symbolwise match Push(bitStream, false, destination, data); NeutralEndian.Write1(data, buffer[bPointer]); NeutralEndian.Write1(data, buffer[bPointer + 1]); } else { // Dictionary match Push(bitStream, true, destination, data); NeutralEndian.Write1(data, (byte)(iOffset)); NeutralEndian.Write1(data, (byte)(iCount - 1)); } bPointer += iCount * 2; // iCount counts in words (16-bits), so we correct it to bytes (8-bits) here } } Push(bitStream, true, destination, data); NeutralEndian.Write1(data, 0); NeutralEndian.Write1(data, 0); bitStream.Flush(true); byte[] bytes = data.ToArray(); destination.Write(bytes, 0, bytes.Length); }