-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSourceText.cs
More file actions
85 lines (67 loc) · 2.18 KB
/
Copy pathSourceText.cs
File metadata and controls
85 lines (67 loc) · 2.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
namespace DotPython.Language.Text;
public sealed class SourceText
{
private readonly int[] _lineStarts;
public SourceText(string text, string? filePath = null)
{
ArgumentNullException.ThrowIfNull(text);
Content = text;
FilePath = filePath;
_lineStarts = FindLineStarts(text);
}
public string Content { get; }
public string? FilePath { get; }
public int Length => Content.Length;
public int LineCount => _lineStarts.Length;
public char this[int index] => Content[index];
public string GetText(TextSpan span)
{
ValidateSpan(span);
return Content.Substring(span.Start, span.Length);
}
public LinePosition GetLinePosition(int position)
{
ArgumentOutOfRangeException.ThrowIfNegative(position);
ArgumentOutOfRangeException.ThrowIfGreaterThan(position, Length);
var line = Array.BinarySearch(_lineStarts, position);
if (line < 0)
{
line = ~line - 1;
}
return new LinePosition(line, position - _lineStarts[line]);
}
public TextSpan GetLineSpan(int line)
{
ArgumentOutOfRangeException.ThrowIfNegative(line);
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(line, LineCount);
var start = _lineStarts[line];
var end = line + 1 < LineCount ? _lineStarts[line + 1] : Length;
return TextSpan.FromBounds(start, end);
}
private static int[] FindLineStarts(string text)
{
var starts = new List<int> { 0 };
for (var position = 0; position < text.Length; position++)
{
switch (text[position])
{
case '\r' when position + 1 < text.Length && text[position + 1] == '\n':
position++;
starts.Add(position + 1);
break;
case '\r':
case '\n':
starts.Add(position + 1);
break;
}
}
return [.. starts];
}
private void ValidateSpan(TextSpan span)
{
if (span.End > Length)
{
throw new ArgumentOutOfRangeException(nameof(span));
}
}
}