public override string GetText(Span span)
        {
            if (span.End > this.Length)
            {
                throw new ArgumentOutOfRangeException("span");
            }

            if (span.End <= _left.Length)
            {
                return(_left.GetText(span));
            }
            else if (span.Start >= _left.Length)
            {
                return(_right.GetText(new Span(span.Start - _left.Length, span.Length)));
            }
            else
            {
                char[] result = new char[span.Length];

                int leftLength = _left.Length - span.Start;
                _left.CopyTo(span.Start, result, 0, leftLength);
                _right.CopyTo(0, result, leftLength, span.Length - leftLength);

                return(new string(result));
            }
        }
        /// <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));
        }
        /// <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)));
        }