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); }
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); }
public bool TryPushLocalChange(RdTextChange change) { if (myState != State.Opened) { return(false); } myLocalChanges.Add(change); return(true); }
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}."); } } }
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); }
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); }
public TextBufferCommand(RdTextChange change, RdChangeOrigin origin, bool deliverImmediately) { Change = change; Origin = origin; DeliverImmediately = deliverImmediately; }
public RdTextBufferChange(TextBufferVersion version, RdChangeOrigin origin, RdTextChange change) { Change = change; Version = version; Origin = origin; }
public static int GetDelta(this RdTextChange that) => that.New.Length - that.Old.Length;