/// <summary>Compare two sequences and identify a list of edits between them.</summary> /// <remarks>Compare two sequences and identify a list of edits between them.</remarks> /// <?></?> /// <param name="cmp">the comparator supplying the element equivalence function.</param> /// <param name="a"> /// the first (also known as old or pre-image) sequence. Edits /// returned by this algorithm will reference indexes using the /// 'A' side: /// <see cref="Edit.GetBeginA()">Edit.GetBeginA()</see> /// , /// <see cref="Edit.GetEndA()">Edit.GetEndA()</see> /// . /// </param> /// <param name="b"> /// the second (also known as new or post-image) sequence. Edits /// returned by this algorithm will reference indexes using the /// 'B' side: /// <see cref="Edit.GetBeginB()">Edit.GetBeginB()</see> /// , /// <see cref="Edit.GetEndB()">Edit.GetEndB()</see> /// . /// </param> /// <returns> /// a modifiable edit list comparing the two sequences. If empty, the /// sequences are identical according to /// <code>cmp</code> /// 's rules. The /// result list is never null. /// </returns> public virtual EditList Diff <S>(SequenceComparator <S> cmp, S a, S b) where S : Sequence { Edit region = cmp.ReduceCommonStartEnd(a, b, CoverEdit(a, b)); switch (region.GetType()) { case Edit.Type.INSERT: case Edit.Type.DELETE: { return(EditList.Singleton(region)); } case Edit.Type.REPLACE: { SubsequenceComparator <S> cs = new SubsequenceComparator <S>(cmp); Subsequence <S> @as = Subsequence <S> .A(a, region); Subsequence <S> bs = Subsequence <S> .B(b, region); EditList e = Subsequence <S> .ToBase(DiffNonCommon(cs, @as, bs), @as, bs); // The last insertion may need to be shifted later if it // inserts elements that were previously reduced out as // common at the end. // Edit last = e[e.Count - 1]; if (last.GetType() == Edit.Type.INSERT) { while (last.endB < b.Size() && cmp.Equals(b, last.beginB, b, last.endB)) { last.beginA++; last.endA++; last.beginB++; last.endB++; } } return(e); } case Edit.Type.EMPTY: { return(new EditList(0)); } default: { throw new InvalidOperationException(); } } }
internal virtual void DiffReplace(Edit r) { Edit lcs = new HistogramDiffIndex <S>(this._enclosing.maxChainLength, this.cmp, this .a, this.b, r).FindLongestCommonSequence(); if (lcs != null) { // If we were given an edit, we can prove a result here. // if (lcs.IsEmpty()) { // An empty edit indicates there is nothing in common. // Replace the entire region. // this.edits.AddItem(r); } else { this.Diff(r.Before(lcs)); this.Diff(r.After(lcs)); } } else { if (this._enclosing.fallback is LowLevelDiffAlgorithm) { LowLevelDiffAlgorithm fb = (LowLevelDiffAlgorithm)this._enclosing.fallback; fb.DiffNonCommon(this.edits, this.cmp, this.a, this.b, r); } else { if (this._enclosing.fallback != null) { SubsequenceComparator <HashedSequence <S> > cs = this.Subcmp(); Subsequence <HashedSequence <S> > @as = Subsequence <S> .A(this.a, r); Subsequence <HashedSequence <S> > bs = Subsequence <S> .B(this.b, r); EditList res = this._enclosing.fallback.DiffNonCommon(cs, @as, bs); Sharpen.Collections.AddAll(this.edits, Subsequence <S> .ToBase(res, @as, bs)); } else { this.edits.AddItem(r); } } } }