예제 #1
0
        /// <summary>
        /// Consolidate two string rebuilders, taking advantage of the fact that they have already extracted the line breaks.
        /// </summary>
        public static StringRebuilder Consolidate(StringRebuilder left, StringRebuilder right)
        {
            Debug.Assert(left.Length > 0);
            Debug.Assert(right.Length > 0);

            int length = left.Length + right.Length;

            char[] result = new char[length];

            left.CopyTo(0, result, 0, left.Length);
            right.CopyTo(0, result, left.Length, right.Length);

            ILineBreaks lineBreaks;

            if ((left.LineBreakCount == 0) && (right.LineBreakCount == 0))
            {
                lineBreaks = LineBreakManager.Empty;
                //_lineBreakSpan defaults to 0, 0 which is what we want
            }
            else
            {
                ILineBreaksEditor breaks = LineBreakManager.CreateLineBreakEditor(length, left.LineBreakCount + right.LineBreakCount);

                int offset = 0;
                if ((result[left.Length] == '\n') && (result[left.Length - 1] == '\r'))
                {
                    //We have a \r\n spanning the seam ... add that as a special linebreak later.
                    offset = 1;
                }

                int leftLines = left.LineBreakCount - offset;
                for (int i = 0; (i < leftLines); ++i)
                {
                    Span extent;
                    int  lineBreakLength;
                    left.GetLineFromLineNumber(i, out extent, out lineBreakLength);
                    breaks.Add(extent.End, lineBreakLength);
                }

                if (offset == 1)
                {
                    breaks.Add(left.Length - 1, 2);
                }

                for (int i = offset; (i < right.LineBreakCount); ++i)
                {
                    Span extent;
                    int  lineBreakLength;
                    right.GetLineFromLineNumber(i, out extent, out lineBreakLength);
                    breaks.Add(extent.End + left.Length, lineBreakLength);
                }

                lineBreaks = breaks;
            }

            return(StringRebuilderForChars.Create(result, length, lineBreaks));
        }
예제 #2
0
        public override void GetLineFromLineNumber(int lineNumber, out Span extent, out int lineBreakLength)
        {
            if ((lineNumber < 0) || (lineNumber > this.LineBreakCount))
            {
                throw new ArgumentOutOfRangeException(nameof(lineNumber));
            }

            if (lineNumber < _left.LineBreakCount)
            {
                _left.GetLineFromLineNumber(lineNumber, out extent, out lineBreakLength);
            }
            else if (lineNumber > _left.LineBreakCount)
            {
                _right.GetLineFromLineNumber(lineNumber - _left.LineBreakCount, out extent, out lineBreakLength);
                extent = new Span(extent.Start + _left.Length, extent.Length);
            }
            else
            {
                // The line crosses the seam.
                int start = 0;
                if (lineNumber != 0)
                {
                    _left.GetLineFromLineNumber(lineNumber, out extent, out lineBreakLength);   // ignore the returned extend.Length

                    start = extent.Start;
                    Debug.Assert(lineBreakLength == 0);
                }

                int end;

                if (lineNumber == this.LineBreakCount)
                {
                    end             = this.Length;
                    lineBreakLength = 0;
                }
                else
                {
                    _right.GetLineFromLineNumber(0, out extent, out lineBreakLength);
                    end = extent.End + _left.Length;
                }

                extent = Span.FromBounds(start, end);
            }
        }
예제 #3
0
        public override LineSpan GetLineFromLineNumber(int lineNumber)
        {
            if ((lineNumber < 0) || (lineNumber > this.LineBreakCount))
            {
                throw new ArgumentOutOfRangeException("lineNumber");
            }

            if (lineNumber < _left.LineBreakCount)
            {
                return(_left.GetLineFromLineNumber(lineNumber));
            }
            else if (lineNumber > _left.LineBreakCount)
            {
                LineSpan rightSpan = _right.GetLineFromLineNumber(lineNumber - _left.LineBreakCount);

                return(new LineSpan(lineNumber, new Span(rightSpan.Start + _left.Length, rightSpan.Length), rightSpan.LineBreakLength));
            }
            else
            {
                int start = (lineNumber == 0)
                            ? 0
                            : _left.GetLineFromLineNumber(lineNumber).Start;

                int end;
                int breakLength;

                if (lineNumber == this.LineBreakCount)
                {
                    end         = this.Length;
                    breakLength = 0;
                }
                else
                {
                    LineSpan rightSpan = _right.GetLineFromLineNumber(0);
                    end         = rightSpan.End + _left.Length;
                    breakLength = rightSpan.LineBreakLength;
                }

                return(new LineSpan(lineNumber, Span.FromBounds(start, end), breakLength));
            }
        }
예제 #4
0
        /// <summary>
        /// Consolidate two string rebuilders, taking advantage of the fact that they have already extracted the line breaks.
        /// </summary>
        public static SimpleStringRebuilder Create(StringRebuilder left, StringRebuilder right)
        {
            Debug.Assert(left.Length > 0);
            Debug.Assert(right.Length > 0);

            int length = left.Length + right.Length;

            char[] result = new char[length];

            left.CopyTo(0, result, 0, left.Length);
            right.CopyTo(0, result, left.Length, right.Length);
            string text = new string(result);

            int[] lineBreaks;
            if ((left.LineBreakCount == 0) && (right.LineBreakCount == 0))
            {
                lineBreaks = _emptyLineBreaks;
                //_lineBreakSpan defaults to 0, 0 which is what we want
            }
            else
            {
                int offset = 0;
                if ((text[left.Length] == '\n') && (text[left.Length - 1] == '\r'))
                {
                    //We have a \r\n spanning the seam ... add that as a special linebreak later.
                    offset = 1;
                }

                lineBreaks = new int[left.LineBreakCount + right.LineBreakCount - offset];
                int lastLineBreak = 0;

                int leftLines = left.LineBreakCount - offset;
                for (int i = 0; (i < leftLines); ++i)
                {
                    LineSpan lineSpan = left.GetLineFromLineNumber(i);
                    lineBreaks[lastLineBreak++] = lineSpan.End;
                }

                if (offset == 1)
                {
                    lineBreaks[lastLineBreak++] = left.Length - 1;
                }

                for (int i = offset; (i < right.LineBreakCount); ++i)
                {
                    LineSpan lineSpan = right.GetLineFromLineNumber(i);
                    lineBreaks[lastLineBreak++] = lineSpan.End + left.Length;
                }
            }

            return(new SimpleStringRebuilder(SimpleTextStorage.Create(text, lineBreaks)));
        }