Example #1
0
        /// <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();
            }
            }
        }
Example #2
0
            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);
                        }
                    }
                }
            }