68 lines
1.9 KiB
C#
68 lines
1.9 KiB
C#
using System;
|
|
|
|
namespace Upsilon.Text
|
|
{
|
|
public class SourceText
|
|
{
|
|
private readonly string _text;
|
|
private readonly SourceTextLine[] _lines;
|
|
|
|
public SourceText(string text)
|
|
{
|
|
_text = text;
|
|
var lines = text.Split('\n');
|
|
_lines = new SourceTextLine[lines.Length];
|
|
var linePos = 0;
|
|
for (var index = 0; index < lines.Length; index++)
|
|
{
|
|
var line = lines[index];
|
|
_lines[index] = new SourceTextLine(linePos, line.Length);
|
|
linePos += line.Length;
|
|
}
|
|
}
|
|
|
|
public string GetSpan(int start, int length)
|
|
{
|
|
if (start < 0)
|
|
{
|
|
length += start;
|
|
start = 0;
|
|
};
|
|
if (start >= _text.Length)
|
|
return string.Empty;
|
|
if (start + length >= _text.Length) length = _text.Length - start;
|
|
return _text.Substring(start, length);
|
|
}
|
|
|
|
public (int Line, int Pos) GetLinePosition(int spanPos)
|
|
{
|
|
var min = 0;
|
|
var max = _lines.Length - 1;
|
|
while (min <= max)
|
|
{
|
|
var mid = (min + max) / 2 ;
|
|
var midLine = _lines[mid];
|
|
if (midLine.Start <= spanPos && midLine.End > spanPos)
|
|
{
|
|
var pos = spanPos - midLine.Start;
|
|
return (mid, pos);
|
|
}
|
|
if (spanPos >= midLine.End)
|
|
{
|
|
min = mid + 1;
|
|
}
|
|
else if (spanPos < midLine.Start)
|
|
{
|
|
max = mid - 1;
|
|
}
|
|
}
|
|
var newPos = spanPos - _lines[min].Start;
|
|
return (min, newPos);
|
|
}
|
|
|
|
public string GetSpan(TextSpan span)
|
|
{
|
|
return GetSpan(span.Start, span.Length);
|
|
}
|
|
}
|
|
} |