diff --git a/src/Ramstack.Parsing/ParseContext.cs b/src/Ramstack.Parsing/ParseContext.cs index 068b76c..b9df527 100644 --- a/src/Ramstack.Parsing/ParseContext.cs +++ b/src/Ramstack.Parsing/ParseContext.cs @@ -278,8 +278,7 @@ public readonly override string ToString() => /// internal static string GenerateErrorMessage(ReadOnlySpan source, int position, string message) { - var line = TextHelper.GetLine(source, position); - var column = TextHelper.GetColumn(source, position); + var (line, column) = TextHelper.GetLineColumn(source, position); return $"({line}:{column}) {message}"; } } diff --git a/src/Ramstack.Parsing/Utilities/TextHelper.cs b/src/Ramstack.Parsing/Utilities/TextHelper.cs index e0f693d..c2d83ad 100644 --- a/src/Ramstack.Parsing/Utilities/TextHelper.cs +++ b/src/Ramstack.Parsing/Utilities/TextHelper.cs @@ -6,58 +6,39 @@ namespace Ramstack.Parsing.Utilities; internal static class TextHelper { /// - /// Returns the line number for the specified index in the given source string. + /// Calculates the line and column numbers for the specified index in the specified character span. /// - /// The source string. - /// The index in the source string for which to determine the line number. + /// The character span representing the text content. + /// The index within the span for which to determine the line and column numbers. /// - /// The line number corresponding to the specified index. + /// A tuple containing the line and column numbers corresponding to the specified index. /// - public static int GetLine(ReadOnlySpan source, int index) + public static (int Line, int Column) GetLineColumn(ReadOnlySpan source, int index) { var line = 1; + var column = 1; - if (index >= source.Length) - index = source.Length - 1; + if ((uint)index < (uint)source.Length) + source = source[..index]; - while (true) + for (var i = 0; i < source.Length; i++) { - if ((uint)index >= (uint)source.Length) - break; + column++; - if (source[index] == '\n') + if (source[i] == '\n') + { line++; + column = 1; + } + else if (source[i] == '\r' && i + 1 < source.Length && source[i + 1] == '\n') + { + i++; - index--; - } - - return line; - } - - /// - /// Returns the column number for the specified index in the given source string. - /// - /// The source string. - /// The index in the source string for which to determine the column number. - /// - /// The column number corresponding to the specified index. - /// - public static int GetColumn(ReadOnlySpan source, int index) - { - var column = 1; - index--; - - if (index >= source.Length) - index = source.Length - 1; - - while ((uint)index < (uint)source.Length - && source[index] != '\n' - && source[index] != '\r') - { - column++; - index--; + line++; + column = 1; + } } - return column; + return (line, column); } }