Example #1
0
        public static (int[] match, float score) FuzzyMatch(IReadOnlyList <string> wmPattern, IReadOnlyList <string> wmText, int loc, FuzzyMatchOptions options = default, LineRange[] ranges = default)
        {
            if (ranges == null)
            {
                ranges = new LineRange[] { new LineRange {
                                               length = wmText.Count
                                           } }
            }
            ;

            options ??= new();

            // we're creating twice as many MatchMatrix objects as we need, incurring some wasted allocation and setup time, but it reads easier than trying to precompute all the edge cases
            var fwdMatchers = ranges.Select(r => new MatchMatrix(wmPattern, wmText, options.MaxMatchOffset, r)).SkipWhile(m => loc > m.WorkingRange.last).ToArray();
            var revMatchers = ranges.Reverse().Select(r => new MatchMatrix(wmPattern, wmText, options.MaxMatchOffset, r)).SkipWhile(m => loc < m.WorkingRange.first).ToArray();

            int   warnDist       = OffsetWarnDistance(wmPattern.Count, wmText.Count);
            float penaltyPerLine = options.EnableDistancePenalty ? 1f / (10 * warnDist) : 0;

            var fwd = new MatchRunner(loc, 1, fwdMatchers, penaltyPerLine);
            var rev = new MatchRunner(loc, -1, revMatchers, penaltyPerLine);

            float bestScore = options.MinMatchScore;

            int[] bestMatch = null;
            while (fwd.Step(ref bestScore, ref bestMatch) | rev.Step(ref bestScore, ref bestMatch))
            {
                ;
            }

            return(bestMatch, bestScore);
        }
Example #2
0
        private LineRange TrimRange(LineRange range)
        {
            int start = 0;

            while (start < diffs.Count && diffs[start].op == Operation.EQUAL)
            {
                start++;
            }

            if (start == diffs.Count)
            {
                return new LineRange {
                           start = range.start, length = 0
                }
            }
            ;

            int end = diffs.Count;

            while (end > start && diffs[end - 1].op == Operation.EQUAL)
            {
                end--;
            }

            return(new LineRange {
                start = range.start + start, end = range.end - (diffs.Count - end)
            });
        }
Example #3
0
 public MatchRunner(int loc, int dir, MatchMatrix[] mms, float penaltyPerLine)
 {
     this.loc            = loc;
     this.dir            = dir;
     this.mms            = mms;
     this.penaltyPerLine = penaltyPerLine;
     active  = new LineRange();
     penalty = -0.1f;                 // start penalty at -10%, to give some room for finding the best match if it's not "too far"
 }
Example #4
0
        private (int[] match, float score) FindMatch(int loc, IReadOnlyList <string> wmContext)
        {
            // fuzzy matching is more complex because we need to split up the patched file to only search _between_ previously applied patches
            var keepoutRanges = patches.Select(p => p.KeepoutRange2).Where(r => r != null).Select(r => r.Value);

            // parts of file to search in
            var ranges = new LineRange {
                length = wmLines.Count
            }.Except(keepoutRanges).ToArray();

            return(FuzzyMatch(wmContext, wmLines, loc, FuzzyOptions, ranges));
        }
Example #5
0
            public StraightMatch(IReadOnlyList <string> pattern, IReadOnlyList <string> search, LineRange range)
            {
                patternLength = pattern.Count;
                this.pattern  = pattern;
                this.search   = search;
                this.range    = range;

                nodes = new MatchNodes[patternLength];
                for (int i = 0; i < patternLength; i++)
                {
                    nodes[i] = new MatchNodes();
                }
            }
Example #6
0
        private bool CanApplySafelyAt(int loc, Patch patch)
        {
            if (loc >= ModifiedRange.end)
            {
                return(true);
            }

            var range = new LineRange {
                start = loc, length = patch.length1
            };

            return(patches.All(p => !p.KeepoutRange2?.Contains(range) ?? true));
        }
Example #7
0
        public MatchMatrix(IReadOnlyList <string> pattern, IReadOnlyList <string> search, int maxOffset = DefaultMaxOffset, LineRange range = default)
        {
            if (range == default)
            {
                range = new LineRange {
                    length = search.Count
                }
            }
            ;

            patternLength  = pattern.Count;
            this.range     = range;
            this.maxOffset = maxOffset;
            WorkingRange   = new LineRange {
                first = range.start - maxOffset, last = range.end - patternLength
            };

            matches = new StraightMatch[maxOffset + 1];
            for (int i = 0; i <= maxOffset; i++)
            {
                matches[i] = new StraightMatch(pattern, search, range);
            }
        }
Example #8
0
 public static IReadOnlyList <T> Slice <T>(this IReadOnlyList <T> list, LineRange range) =>
 range.start == 0 && range.length == list.Count ? list :
 new ReadOnlyListSlice <T>(list, range);
Example #9
0
 public ReadOnlyListSlice(IReadOnlyList <T> wrapped, LineRange range)
 {
     this.wrapped = wrapped;
     this.range   = range;
 }