public static ILineBreaks CreateLineBreaks(string source)
        {
            IPooledLineBreaksEditor lineBreaks = null;

            int index = 0;

            while (index < source.Length)
            {
                int breakLength = TextUtilities.LengthOfLineBreak(source, index, source.Length);
                if (breakLength == 0)
                {
                    ++index;
                }
                else
                {
                    if (lineBreaks == null)
                    {
                        lineBreaks = LineBreakManager.CreatePooledLineBreakEditor(source.Length);
                    }

                    lineBreaks.Add(index, breakLength);
                    index += breakLength;
                }
            }

            if (lineBreaks != null)
            {
                lineBreaks.ReleasePooledLineBreaks();
                return(lineBreaks);
            }

            return(Empty);
        }
        // Evil performance hack (but we are on a hot path here):
        //  thresholdForInvalidCharacters should be '\u0001' if we are throwing on invalid characters.
        //                                should be '\0' if we are not.
        // (otherwise we need to check both a throwOnInvalidCharacters boolean and that c == 0).
        private static ILineBreaks ParseBlock(char[] buffer, int length, char thresholdForInvalidCharacters,
                                              ref NewlineState newlineState,
                                              ref LeadingWhitespaceState leadingWhitespaceState,
                                              ref int currentLineLength,
                                              ref int longestLineLength,
                                              ref bool nextCharIsStartOfLine)
        {
            // Note that the lineBreaks created here will (internally) use the pooled list of line breaks.
            IPooledLineBreaksEditor lineBreaks = LineBreakManager.CreatePooledLineBreakEditor(length);

            int index = 0;

            while (index < length)
            {
                int breakLength = TextUtilities.LengthOfLineBreak(buffer, index, length);
                if (breakLength == 0)
                {
                    char c = buffer[index];

                    // If we are checking for invalid characters, throw if we encounter a \0
                    if (c < thresholdForInvalidCharacters)
                    {
                        throw new FileFormatException("File contains NUL characters");
                    }

                    ++currentLineLength;
                    ++index;

                    if (nextCharIsStartOfLine)
                    {
                        switch (c)
                        {
                        case ' ':
                            leadingWhitespaceState.Increment(LeadingWhitespaceState.LineLeadingCharacter.Space, 1);
                            break;

                        case '\t':
                            leadingWhitespaceState.Increment(LeadingWhitespaceState.LineLeadingCharacter.Tab, 1);
                            break;

                        default:
                            leadingWhitespaceState.Increment(LeadingWhitespaceState.LineLeadingCharacter.Printable, 1);
                            break;
                        }

                        nextCharIsStartOfLine = false;
                    }
                }
                else
                {
                    lineBreaks.Add(index, breakLength);
                    longestLineLength = Math.Max(longestLineLength, currentLineLength);
                    currentLineLength = 0;


                    if (breakLength == 2)
                    {
                        newlineState.Increment(NewlineState.LineEnding.CRLF, 1);
                    }
                    else
                    {
                        switch (buffer[index])
                        {
                        // This code needs to be kep consistent with TextUtilities.LengthOfLineBreak()
                        case '\r': newlineState.Increment(NewlineState.LineEnding.CR, 1); break;

                        case '\n': newlineState.Increment(NewlineState.LineEnding.LF, 1); break;

                        case '\u0085': newlineState.Increment(NewlineState.LineEnding.NEL, 1); break;

                        case '\u2028': newlineState.Increment(NewlineState.LineEnding.LS, 1); break;

                        case '\u2029': newlineState.Increment(NewlineState.LineEnding.PS, 1); break;

                        default: throw new InvalidOperationException("Unexpected line ending");
                        }
                    }

                    if (nextCharIsStartOfLine)
                    {
                        leadingWhitespaceState.Increment(LeadingWhitespaceState.LineLeadingCharacter.Empty, 1);
                    }

                    nextCharIsStartOfLine = true;
                }

                index += breakLength;
            }

            lineBreaks.ReleasePooledLineBreaks();

            return(lineBreaks);
        }
Example #3
0
        private static ILineBreaks ParseBlock(char[] buffer, int length,
                                              ref LineEndingState lineEnding, ref int currentLineLength, ref int longestLineLength)
        {
            // Note that the lineBreaks created here will (internally) use the pooled list of line breaks.
            IPooledLineBreaksEditor lineBreaks = LineBreakManager.CreatePooledLineBreakEditor(length);

            int index = 0;

            while (index < length)
            {
                int breakLength = TextUtilities.LengthOfLineBreak(buffer, index, length);
                if (breakLength == 0)
                {
                    ++currentLineLength;
                    ++index;
                }
                else
                {
                    lineBreaks.Add(index, breakLength);
                    longestLineLength = Math.Max(longestLineLength, currentLineLength);
                    currentLineLength = 0;

                    if (lineEnding != LineEndingState.Inconsistent)
                    {
                        if (breakLength == 2)
                        {
                            if (lineEnding == LineEndingState.Unknown)
                            {
                                lineEnding = LineEndingState.CRLF;
                            }
                            else if (lineEnding != LineEndingState.CRLF)
                            {
                                lineEnding = LineEndingState.Inconsistent;
                            }
                        }
                        else
                        {
                            LineEndingState newLineEndingState;
                            switch (buffer[index])
                            {
                            // This code needs to be kep consistent with TextUtilities.LengthOfLineBreak()
                            case '\r': newLineEndingState = LineEndingState.CR; break;

                            case '\n': newLineEndingState = LineEndingState.LF; break;

                            case '\u0085': newLineEndingState = LineEndingState.NEL; break;

                            case '\u2028': newLineEndingState = LineEndingState.LS; break;

                            case '\u2029': newLineEndingState = LineEndingState.PS; break;

                            default: throw new InvalidOperationException("Unexpected line ending");
                            }

                            if (lineEnding == LineEndingState.Unknown)
                            {
                                lineEnding = newLineEndingState;
                            }
                            else if (lineEnding != newLineEndingState)
                            {
                                lineEnding = LineEndingState.Inconsistent;
                            }
                        }
                    }

                    index += breakLength;
                }
            }

            lineBreaks.ReleasePooledLineBreaks();

            return(lineBreaks);
        }