public override StringRebuilder GetSubText(Span span) { if (span.End > this.Length) { throw new ArgumentOutOfRangeException(nameof(span)); } if (span.Length == this.Length) { return(this); } else if (span.End <= _left.Length) { return(_left.GetSubText(span)); } else if (span.Start >= _left.Length) { return(_right.GetSubText(new Span(span.Start - _left.Length, span.Length))); } else { return(BinaryStringRebuilder.Create(_left.GetSubText(Span.FromBounds(span.Start, _left.Length)), _right.GetSubText(Span.FromBounds(0, span.End - _left.Length)))); } }
private static IList <TextChange> GetChangesFromDifferenceCollection(ref int delta, TextChange originalChange, StringRebuilder oldText, StringRebuilder newText, IHierarchicalDifferenceCollection diffCollection, int leftOffset = 0, int rightOffset = 0) { List <TextChange> changes = new List <TextChange>(); for (int i = 0; i < diffCollection.Differences.Count; i++) { Difference currentDiff = diffCollection.Differences[i]; Span leftDiffSpan = Translate(diffCollection.LeftDecomposition.GetSpanInOriginal(currentDiff.Left), leftOffset); Span rightDiffSpan = Translate(diffCollection.RightDecomposition.GetSpanInOriginal(currentDiff.Right), rightOffset); // TODO: Since this evaluates differences lazily, we should add something here to *not* compute the next // level of differences if we think it would be too expensive. IHierarchicalDifferenceCollection nextLevelDiffs = diffCollection.GetContainedDifferences(i); if (nextLevelDiffs != null) { changes.AddRange(GetChangesFromDifferenceCollection(ref delta, originalChange, oldText, newText, nextLevelDiffs, leftDiffSpan.Start, rightDiffSpan.Start)); } else { TextChange minimalChange = new TextChange(originalChange.OldPosition + leftDiffSpan.Start, oldText.GetSubText(leftDiffSpan), newText.GetSubText(rightDiffSpan), ComputeBoundaryConditions(originalChange, oldText, leftDiffSpan)); minimalChange.NewPosition = originalChange.NewPosition + rightDiffSpan.Start; if (minimalChange.OldLength > 0 && minimalChange.NewLength > 0) { minimalChange.IsOpaque = true; } delta += minimalChange.Delta; changes.Add(minimalChange); } } return(changes); }
public static StringRebuilder Create(StringRebuilder left, StringRebuilder right) { if (left == null) { throw new ArgumentNullException(nameof(left)); } if (right == null) { throw new ArgumentNullException(nameof(right)); } if (left.Length == 0) { return(right); } else if (right.Length == 0) { return(left); } else if ((left.Length + right.Length < TextModelOptions.StringRebuilderMaxCharactersToConsolidate) && (left.LineBreakCount + right.LineBreakCount <= TextModelOptions.StringRebuilderMaxLinesToConsolidate)) { //Consolidate the two rebuilders into a single simple string rebuilder return(StringRebuilder.Consolidate(left, right)); } else if ((right.FirstCharacter == '\n') && (left.LastCharacter == '\r')) { //Don't allow a line break to be broken across the seam return(BinaryStringRebuilder.Create(BinaryStringRebuilder.Create(left.GetSubText(new Span(0, left.Length - 1)), _crlf), right.GetSubText(Span.FromBounds(1, right.Length)))); } else { return(BinaryStringRebuilder.BalanceStringRebuilder(left, right)); } }