예제 #1
0
        public void Pack(byte[] rawBytes, IPackerOutput packerOutput, Object consumerContext)
        {
            var hash    = new PrefixHash(rawBytes, false);
            int dictLen = dictionary.Length;

            int previousMatchIndex  = 0;
            int previousMatchLength = 0;

            int curr, count;

            for (curr = 0, count = rawBytes.Length; curr < count; curr++)
            {
                int bestMatchIndex  = 0;
                int bestMatchLength = 0;

                if (curr + PrefixHash.PrefixLength - 1 < count)
                {
                    PrefixHash.Match match = dictHash.GetBestMatch(curr, rawBytes);
                    bestMatchIndex  = match.BestMatchIndex;
                    bestMatchLength = match.BestMatchLength;

                    match = hash.GetBestMatch(curr, rawBytes);

                    // Note the >= because we prefer a match that is nearer (and a match
                    // in the string being compressed is always closer than one from the dict).
                    if (match.BestMatchLength >= bestMatchLength)
                    {
                        bestMatchIndex  = match.BestMatchIndex + dictLen;
                        bestMatchLength = match.BestMatchLength;
                    }

                    hash.Put(curr);
                }

                if (bestMatchLength < MinimumMatchLength)
                {
                    bestMatchIndex = bestMatchLength = 0;
                }

                if (previousMatchLength > 0 && bestMatchLength <= previousMatchLength)
                {
                    // We didn't get a match or we got one and the previous match is better
                    packerOutput.EncodeSubstring(-(curr + dictLen - 1 - previousMatchIndex), previousMatchLength, consumerContext);

                    // Make sure locations are added for the match.  This allows repetitions to always
                    // encode the same relative locations which is better for compressing the locations.
                    int endMatch = curr - 1 + previousMatchLength;
                    curr++;
                    while (curr < endMatch && curr + PrefixHash.PrefixLength < count)
                    {
                        hash.Put(curr);
                        curr++;
                    }
                    curr = endMatch - 1; // Make sure 'curr' is pointing to the last processed byte so it is at the right place in the next iteration
                    previousMatchIndex = previousMatchLength = 0;
                }
                else if (previousMatchLength > 0 && bestMatchLength > previousMatchLength)
                {
                    // We have a match, and we had a previous match, and this one is better.
                    previousMatchIndex  = bestMatchIndex;
                    previousMatchLength = bestMatchLength;
                    packerOutput.EncodeLiteral(rawBytes[curr - 1], consumerContext);
                }
                else if (bestMatchLength > 0)
                {
                    // We have a match, but no previous match
                    previousMatchIndex  = bestMatchIndex;
                    previousMatchLength = bestMatchLength;
                }
                else if (bestMatchLength == 0 && previousMatchLength == 0)
                {
                    // No match, and no previous match.
                    packerOutput.EncodeLiteral(rawBytes[curr], consumerContext);
                }
            }
            packerOutput.EndEncoding(consumerContext);
        }
        public void Pack(byte[] rawBytes, IPackerOutput packerOutput, Object consumerContext)
        {
            var hash = new PrefixHash(rawBytes, false);
            int dictLen = dictionary.Length;

            int previousMatchIndex = 0;
            int previousMatchLength = 0;

            int curr, count;
            for (curr = 0, count = rawBytes.Length; curr < count; curr++)
            {
                int bestMatchIndex = 0;
                int bestMatchLength = 0;

                if (curr + PrefixHash.PrefixLength - 1 < count)
                {
                    PrefixHash.Match match = dictHash.GetBestMatch(curr, rawBytes);
                    bestMatchIndex = match.BestMatchIndex;
                    bestMatchLength = match.BestMatchLength;

                    match = hash.GetBestMatch(curr, rawBytes);

                    // Note the >= because we prefer a match that is nearer (and a match
                    // in the string being compressed is always closer than one from the dict).
                    if (match.BestMatchLength >= bestMatchLength)
                    {
                        bestMatchIndex = match.BestMatchIndex + dictLen;
                        bestMatchLength = match.BestMatchLength;
                    }

                    hash.Put(curr);
                }

                if (bestMatchLength < MinimumMatchLength)
                {
                    bestMatchIndex = bestMatchLength = 0;
                }

                if (previousMatchLength > 0 && bestMatchLength <= previousMatchLength)
                {
                    // We didn't get a match or we got one and the previous match is better
                    packerOutput.EncodeSubstring(-(curr + dictLen - 1 - previousMatchIndex), previousMatchLength, consumerContext);

                    // Make sure locations are added for the match.  This allows repetitions to always
                    // encode the same relative locations which is better for compressing the locations.
                    int endMatch = curr - 1 + previousMatchLength;
                    curr++;
                    while (curr < endMatch && curr + PrefixHash.PrefixLength < count)
                    {
                        hash.Put(curr);
                        curr++;
                    }
                    curr = endMatch - 1; // Make sure 'curr' is pointing to the last processed byte so it is at the right place in the next iteration
                    previousMatchIndex = previousMatchLength = 0;
                }
                else if (previousMatchLength > 0 && bestMatchLength > previousMatchLength)
                {
                    // We have a match, and we had a previous match, and this one is better.
                    previousMatchIndex = bestMatchIndex;
                    previousMatchLength = bestMatchLength;
                    packerOutput.EncodeLiteral(rawBytes[curr - 1], consumerContext);
                }
                else if (bestMatchLength > 0)
                {
                    // We have a match, but no previous match
                    previousMatchIndex = bestMatchIndex;
                    previousMatchLength = bestMatchLength;
                }
                else if (bestMatchLength == 0 && previousMatchLength == 0)
                {
                    // No match, and no previous match.
                    packerOutput.EncodeLiteral(rawBytes[curr], consumerContext);
                }
            }
            packerOutput.EndEncoding(consumerContext);
        }