Beispiel #1
0
        public Delta Diff(Delta other)
        {
            if (this == other)
            {
                return(new Delta());
            }

            if (!TryConcatInserts(this, out string thisStr) || !TryConcatInserts(other, out string otherStr))
            {
                throw new InvalidOperationException("Both deltas must be documents.");
            }

            var         delta      = new Delta();
            List <Diff> diffResult = Differ.Compute(thisStr, otherStr);
            var         thisIter   = new OpIterator(this.Ops);
            var         otherIter  = new OpIterator(other.Ops);

            foreach (Diff component in diffResult)
            {
                int length = component.Text.Length;
                while (length > 0)
                {
                    int opLength = 0;
                    switch (component.Operation)
                    {
                    case Operation.Insert:
                        opLength = Math.Min(otherIter.PeekLength(), length);
                        delta.Add(otherIter.Next(opLength));
                        break;

                    case Operation.Delete:
                        opLength = Math.Min(length, thisIter.PeekLength());
                        thisIter.Next(opLength);
                        delta.Delete(opLength);
                        break;

                    case Operation.Equal:
                        opLength = Math.Min(Math.Min(thisIter.PeekLength(), otherIter.PeekLength()), length);
                        JToken thisOp  = thisIter.Next(opLength);
                        JToken otherOp = otherIter.Next(opLength);
                        if (JToken.DeepEquals(thisOp[InsertType], otherOp[InsertType]))
                        {
                            delta.Retain(opLength, DiffAttributes(thisOp[Attributes], otherOp[Attributes]));
                        }
                        else
                        {
                            delta.Add(otherOp);
                            delta.Delete(opLength);
                        }
                        break;
                    }
                    length -= opLength;
                }
            }
            return(delta.Chop());
        }
Beispiel #2
0
        public Delta Compose(Delta other)
        {
            var thisIter  = new OpIterator(_ops);
            var otherIter = new OpIterator(other._ops);
            var delta     = new Delta();

            while (thisIter.HasNext() || otherIter.HasNext())
            {
                if (otherIter.PeekType() == InsertType)
                {
                    delta.Add(otherIter.Next());
                }
                else if (thisIter.PeekType() == DeleteType)
                {
                    delta.Add(thisIter.Next());
                }
                else
                {
                    int    length  = Math.Min(thisIter.PeekLength(), otherIter.PeekLength());
                    JToken thisOp  = thisIter.Next(length);
                    JToken otherOp = otherIter.Next(length);
                    if (otherOp.OpType() == RetainType)
                    {
                        var newOp = new JObject();
                        if (thisOp.OpType() == RetainType)
                        {
                            newOp[RetainType] = length;
                        }
                        else
                        {
                            newOp[InsertType] = thisOp[InsertType];
                        }

                        JToken attributes = ComposeAttributes(thisOp[Attributes], otherOp[Attributes],
                                                              thisOp.OpType() == RetainType);
                        if (attributes != null)
                        {
                            newOp[Attributes] = attributes;
                        }
                        delta.Add(newOp);
                    }
                    else if (otherOp.OpType() == DeleteType && thisOp.OpType() == RetainType)
                    {
                        delta.Add(otherOp);
                    }
                }
            }
            return(delta.Chop());
        }