예제 #1
0
        public void Fire(RdTextChange value)
        {
            Assertion.Assert(Delegate.IsBound || BufferVersion == TextBufferVersion.InitVersion, "Delegate.IsBound || BufferVersion == TextBufferVersion.InitVersion");
            if (Delegate.IsBound)
            {
                Proto.Scheduler.AssertThread();
            }

            BufferVersion = IsMaster ? BufferVersion.IncrementMaster() : BufferVersion.IncrementSlave();
            var ts        = GetCurrentTs();
            var operation = value.ToOperation(LocalOrigin, ts);

            switch (operation.Kind)
            {
            case OtOperationKind.Normal:
                myDiff.Add(operation);
                break;

            case OtOperationKind.Reset:
                myDiff = new List <OtOperation>();
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            SendOperation(operation);
        }
예제 #2
0
        public void Fire(RdTextChange change)
        {
            Assertion.Assert(Delegate.IsBound || BufferVersion == TextBufferVersion.InitVersion,
                             "Delegate.IsBound || BufferVersion == TextBufferVersion.InitVersion");
            if (Delegate.IsBound)
            {
                Proto.Scheduler.AssertThread();
            }

            if (IsMaster && myActiveSession != null && myActiveSession.IsCommitting)
            {
                return;
            }

            IncrementBufferVersion();
            var bufferChange = new RdTextBufferChange(BufferVersion, myLocalOrigin, change);

            if (change.Kind == RdTextChangeKind.Reset)
            {
                ClearState();
            }
            else if (!IsMaster)
            {
                myChangesToConfirmOrRollback.Add(bufferChange);
            }

            myActiveSession?.TryPushLocalChange(change);

            Delegate.Changes.SetValue(bufferChange);
        }
예제 #3
0
            public bool TryPushLocalChange(RdTextChange change)
            {
                if (myState != State.Opened)
                {
                    return(false);
                }

                myLocalChanges.Add(change);
                return(true);
            }
예제 #4
0
파일: RdTextChangeEx.cs 프로젝트: yvvan/rd
 public static void AssertDocumentLength(this RdTextChange that, int currentLen)
 {
     if (that.Kind != RdTextChangeKind.Reset && that.FullTextLength != -1)
     {
         var actual   = currentLen + that.GetDelta();
         var expected = that.FullTextLength;
         if (actual != expected)
         {
             throw new InvalidOperationException($"Expected the document size: {expected}, but actual: {actual}.");
         }
     }
 }
예제 #5
0
파일: OtOperationEx.cs 프로젝트: epeshk/rd
        public static OtOperation ToOperation(this RdTextChange textChange, RdChangeOrigin origin, int ts)
        {
            var changes = new List <OtChange>();

            changes.Add(new Retain(textChange.StartOffset));
            switch (textChange.Kind)
            {
            case RdTextChangeKind.Insert:
                changes.Add(new InsertText(textChange.New));
                break;

            case RdTextChangeKind.Remove:
                changes.Add(new DeleteText(textChange.Old));
                break;

            case RdTextChangeKind.Replace:
            {
                changes.Add(new InsertText(textChange.New));
                changes.Add(new DeleteText(textChange.Old));
                break;
            }

            case RdTextChangeKind.Reset:
                changes.Add(new InsertText(textChange.New));
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            var currentOffset = changes.Sum(x => x.GetTextLengthAfter());

            changes.Add(new Retain(textChange.FullTextLength - currentOffset));

            var kind      = textChange.Kind == RdTextChangeKind.Reset ? OtOperationKind.Reset : OtOperationKind.Normal;
            var operation = new OtOperation(changes, origin, ts, kind);

            Assertion.Assert(operation.DocumentLengthAfter() == textChange.FullTextLength,
                             "operation.DocumentLengthAfter() == textChange.FullTextLength");
            return(operation);
        }
예제 #6
0
        private static string PlayChange(string initText, RdTextChange change)
        {
            var    x0 = change.StartOffset;
            var    x1 = change.StartOffset + change.Old.Length;
            string newText;

            switch (change.Kind)
            {
            case RdTextChangeKind.Insert:
            {
                newText = initText.Substring(0, x0) + change.New + initText.Substring(x0);
                break;
            }

            case RdTextChangeKind.Remove:
            {
                newText = initText.Substring(0, x0) + initText.Substring(x1);
                break;
            }

            case RdTextChangeKind.Replace:
            {
                newText = initText.Substring(0, x0) + change.New + initText.Substring(x1);
                break;
            }

            case RdTextChangeKind.Reset:
            {
                newText = change.New;
                break;
            }

            default:
                throw new ArgumentOutOfRangeException();
            }
            Assert.AreEqual(change.FullTextLength, newText.Length);

            return(newText);
        }
예제 #7
0
 public TextBufferCommand(RdTextChange change, RdChangeOrigin origin, bool deliverImmediately)
 {
     Change             = change;
     Origin             = origin;
     DeliverImmediately = deliverImmediately;
 }
예제 #8
0
 public RdTextBufferChange(TextBufferVersion version, RdChangeOrigin origin, RdTextChange change)
 {
     Change  = change;
     Version = version;
     Origin  = origin;
 }
예제 #9
0
파일: RdTextChangeEx.cs 프로젝트: yvvan/rd
 public static int GetDelta(this RdTextChange that) => that.New.Length - that.Old.Length;