Exemplo n.º 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));
        }
Exemplo n.º 2
0
        public override StringRebuilder GetSubText(Span span)
        {
            if (span.End > this.Length)
            {
                throw new ArgumentOutOfRangeException("span");
            }

            if (span.Length == 0)
            {
                return(StringRebuilder.Empty);
            }
            else if (span.Length == this.Length)
            {
                return(this);
            }
            else
            {
                int firstLineNumber;
                int lastLineNumber;
                this.FindFirstAndLastLines(span, out firstLineNumber, out lastLineNumber);
                return(StringRebuilderForChars.Create(_content, _lineBreaks, span.Start + _textSpanStart, span.Length, firstLineNumber, lastLineNumber - firstLineNumber));
            }
        }
Exemplo n.º 3
0
        internal static StringRebuilder Load(TextReader reader, long fileSize,
                                             out NewlineState newlineState,
                                             out LeadingWhitespaceState leadingWhitespaceState,
                                             out int longestLineLength,
                                             int blockSize = 0,
                                             int minCompressedBlockSize    = TextImageLoader.BlockSize,                                          // Exposed for unit tests
                                             bool throwOnInvalidCharacters = false)
        {
            newlineState           = new NewlineState();
            leadingWhitespaceState = new LeadingWhitespaceState();

            int currentLineLength = 0;

            longestLineLength = 0;
            char thresholdForInvalidCharacters = throwOnInvalidCharacters ? '\u0001' : '\0';    // Basically the only invalid character is \0, if we are looking for invalid characters.

            bool useCompressedStringRebuilders = (fileSize >= TextModelOptions.CompressedStorageFileSizeThreshold);

            if (blockSize == 0)
            {
                blockSize = useCompressedStringRebuilders ? TextModelOptions.CompressedStoragePageSize : TextImageLoader.BlockSize;
            }

            PageManager pageManager = null;

            char[] buffer;
            if (useCompressedStringRebuilders)
            {
                pageManager = new PageManager();
                buffer      = new char[blockSize];
            }
            else
            {
                buffer = TextImageLoader.AcquireBuffer(blockSize);
            }

            StringRebuilder content = StringRebuilderForChars.Empty;

            try
            {
                bool nextCharIsStartOfLine = true;
                while (true)
                {
                    int read = TextImageLoader.LoadNextBlock(reader, buffer);

                    if (read == 0)
                    {
                        break;
                    }

                    var lineBreaks = TextImageLoader.ParseBlock(
                        buffer,
                        read,
                        thresholdForInvalidCharacters,
                        ref newlineState,
                        ref leadingWhitespaceState,
                        ref currentLineLength,
                        ref longestLineLength,
                        ref nextCharIsStartOfLine);

                    char[] bufferForStringBuilder = buffer;
                    if (read < (buffer.Length / 2))
                    {
                        // We read far less characters than buffer so copy the contents to a new buffer and reuse the original buffer.
                        bufferForStringBuilder = new char[read];
                        Array.Copy(buffer, bufferForStringBuilder, read);
                    }
                    else
                    {
                        // We're using most of buffer so allocate a new block for the next chunk.
                        buffer = new char[blockSize];
                    }

                    var newContent = (useCompressedStringRebuilders && (read > minCompressedBlockSize))
                                     ? StringRebuilderForCompressedChars.Create(new Page(pageManager, bufferForStringBuilder, read), lineBreaks)
                                     : StringRebuilderForChars.Create(bufferForStringBuilder, read, lineBreaks);

                    content = content.Insert(content.Length, newContent);
                }

                longestLineLength = Math.Max(longestLineLength, currentLineLength);
            }
            finally
            {
                if (!useCompressedStringRebuilders)
                {
                    TextImageLoader.ReleaseBuffer(buffer);
                }
            }

            return(content);
        }
Exemplo n.º 4
0
        internal readonly char[] _content;   // Contents should be treated as immutable.

        internal static StringRebuilder Create(char[] source, int length, ILineBreaks lineBreaks)
        {
            return(StringRebuilderForChars.Create(source, lineBreaks, 0, length, 0, lineBreaks.Length));
        }
Exemplo n.º 5
0
        internal static StringRebuilder Load(TextReader reader, long fileSize, string id,
                                             out bool hasConsistentLineEndings, out int longestLineLength,
                                             int blockSize = 0,
                                             int minCompressedBlockSize = TextImageLoader.BlockSize)                                             // Exposed for unit tests
        {
            LineEndingState lineEnding        = LineEndingState.Unknown;
            int             currentLineLength = 0;

            longestLineLength = 0;

            bool useCompressedStringRebuilders = (fileSize >= TextModelOptions.CompressedStorageFileSizeThreshold);

            if (blockSize == 0)
            {
                blockSize = useCompressedStringRebuilders ? TextModelOptions.CompressedStoragePageSize : TextImageLoader.BlockSize;
            }

            PageManager pageManager = null;

            char[] buffer;
            if (useCompressedStringRebuilders)
            {
                pageManager = new PageManager();
                buffer      = new char[blockSize];
            }
            else
            {
                buffer = TextImageLoader.AcquireBuffer(blockSize);
            }

            StringRebuilder content = StringRebuilderForChars.Empty;

            try
            {
                while (true)
                {
                    int read = TextImageLoader.LoadNextBlock(reader, buffer);

                    if (read == 0)
                    {
                        break;
                    }

                    var lineBreaks = LineBreakManager.CreateLineBreakEditor(read);
                    TextImageLoader.ParseBlock(buffer, read, lineBreaks, ref lineEnding, ref currentLineLength, ref longestLineLength);

                    char[] bufferForStringBuilder = buffer;
                    if (read < (buffer.Length / 2))
                    {
                        // We read far less characters than buffer so copy the contents to a new buffer and reuse the original buffer.
                        bufferForStringBuilder = new char[read];
                        Array.Copy(buffer, bufferForStringBuilder, read);
                    }
                    else
                    {
                        // We're using most of bufferForStringRebuilder so allocate a new block for the next chunk.
                        buffer = new char[blockSize];
                    }

                    var newContent = (useCompressedStringRebuilders && (read > minCompressedBlockSize))
                                     ? StringRebuilderForCompressedChars.Create(new Page(pageManager, bufferForStringBuilder, read), lineBreaks)
                                     : StringRebuilderForChars.Create(bufferForStringBuilder, read, lineBreaks);

                    content = content.Insert(content.Length, newContent);
                }

                longestLineLength        = Math.Max(longestLineLength, currentLineLength);
                hasConsistentLineEndings = lineEnding != LineEndingState.Inconsistent;
            }
            finally
            {
                if (!useCompressedStringRebuilders)
                {
                    TextImageLoader.ReleaseBuffer(buffer);
                }
            }

            return(content);
        }