Example #1
0
        /// <summary>
        /// Perform lookup for byte string at position.
        /// </summary>
        /// <param name="src">Source buffer.</param>
        /// <param name="position">Position in source buffer.</param>
        /// <param name="window">Deltas window.</param>
        /// <param name="recents">Recents buffer.</param>
        /// <returns></returns>
        static LookupResult Lookup(
            ReadOnlySpan <byte> src,
            int position,
            ref RevolvingBufferTracker <int> window,
            Span <int> recents)
        {
            // Get offset to previous index of current byte value.
            var c      = src[position];
            var recent = recents[c] - 1;

            // Check if: recent is 0 (no previous byte with this value), or offset is out-of-range of window.
            if (recent < 0 || window.Length < (position - recent))
            {
                return(LookupResult.NoneFound());
            }
            else
            {
                // Start searching at recent position.
                var searchPosition = recent;

                var currentSlice        = src.Slice(position, Math.Min(MaxCompare, src.Length - position));
                var windowStartPosition = Math.Max(position - window.Length, 0);
                var result = LookupResult.NoneFound();

                // Follow chain backwards and look for matches.
                while (windowStartPosition <= searchPosition)
                {
                    // Get slice for bytes to compare against currentSlice
                    var searchSlice = src.Slice(searchPosition);

                    // Find number of potential matches in search slice.
                    var potentialMatches = Math.Min(currentSlice.Length, searchSlice.Length);

                    // Set matches count to maximum, will update if loop exits early.
                    var matches = potentialMatches;
                    for (int i = 0; i < potentialMatches; i++)
                    {
                        if (currentSlice[i] != searchSlice[i])
                        {
                            matches = i;
                            break;
                        }
                    }

                    // Update lookup result if found new longest match.
                    if (matches >= 3 && matches >= result.Length)
                    {
                        result = new LookupResult(searchPosition, matches);

                        // If we have found a matching string with the max compare size, return early.
                        if (result.Length == MaxCompare)
                        {
                            break;
                        }
                    }

                    // Get search position relative to window start, and update search position.
                    var windowIndex = searchPosition - windowStartPosition;
                    searchPosition = window.Get(windowIndex);

                    // If next index is less-than 0, no previous instance of this value.
                    if (searchPosition < 0)
                    {
                        break;
                    }
                }

                return(result);
            }
        }