Refactored lines to contain 'new line'

This commit is contained in:
Krzosa Karol
2024-06-28 15:43:41 +02:00
parent 63adca1fac
commit 2dacc969a3
3 changed files with 179 additions and 271 deletions

View File

@@ -27,6 +27,7 @@ struct Range {
struct Line {
int64_t number;
Range range;
int64_t max_without_new_line;
};
struct LineAndColumn {
@@ -91,6 +92,11 @@ Range MakeRange(int64_t a, int64_t b) {
return result;
}
Range MakeRange(int64_t a) {
Range result = {a, a};
return result;
}
int64_t GetFront(Cursor cursor) {
int64_t result = cursor.pos[cursor.ifront];
return result;
@@ -342,7 +348,7 @@ void ApplyEdits(Buffer *buffer, Array<Edit> edits) {
int64_t index = 0;
int64_t base_index = 0;
while (Seek(string, delimiter, &index)) {
buffer->lines.add({base_index, base_index + index});
buffer->lines.add({base_index, base_index + index + delimiter.len});
base_index += index + delimiter.len;
string = string.skip(index + delimiter.len);
}
@@ -457,25 +463,28 @@ BufferIter Iterate(Buffer &buffer, Range range, int64_t direction = ITERATE_FORW
return result;
}
Line GetLine(Buffer &buffer, int64_t line) {
Line GetLineByIndex(Buffer &buffer, int64_t line) {
Assert(buffer.lines.len);
line = Clamp(line, (int64_t)0, buffer.lines.len - 1);
Range range = buffer.lines[line];
Line result = {line, range};
Line result = {line, range, range.max};
if (GetChar(buffer, range.max - 1) == '\n') result.max_without_new_line -= 1;
return result;
}
Line FindLine(Buffer &buffer, int64_t pos) {
Line result = {};
For(buffer.lines) {
// The program is doing '<= it.max' so as to include the new line.
// Otherwise this function wouldn't be able to find certain positions.
if (pos >= it.min && pos <= it.max) {
Line result = {buffer.lines.get_index(it), it};
return result;
bool found_last = (pos == it.min && pos == it.max);
bool found = pos >= it.min && pos < it.max;
if (found || found_last) {
result = {buffer.lines.get_index(it), it, it.max};
if (GetChar(buffer, it.max - 1) == '\n') result.max_without_new_line -= 1;
break;
}
}
return {};
return result;
}
LineAndColumn FindLineAndColumn(Buffer &buffer, int64_t pos) {
@@ -493,8 +502,8 @@ LineAndColumn FindLineAndColumn(Buffer &buffer, int64_t pos) {
}
int64_t FindPos(Buffer &buffer, int64_t line_number, int64_t column) {
Line line = GetLine(buffer, line_number);
int64_t result = line.range.max;
Line line = GetLineByIndex(buffer, line_number);
int64_t result = line.max_without_new_line;
for (BufferIter iter = Iterate(buffer, line.range); IsValid(iter); Advance(&iter)) {
if (iter.codepoint_index == column) {
result = iter.pos;
@@ -552,146 +561,3 @@ int64_t Seek(Buffer &buffer, int64_t pos, int64_t direction = ITERATE_FORWARD) {
}
return result;
}
void RunBufferTests() {
Scratch scratch;
{
Buffer buffer = {scratch};
Array<Edit> edits = {scratch};
AddEdit(&edits, {0, 0}, "Things and other things");
ApplyEdits(&buffer, edits);
String string = {buffer.data[buffer.bi], buffer.len};
Assert(string == "Things and other things");
Assert(buffer.lines.len == 1);
Assert(GetString(buffer, buffer.lines[0]) == "Things and other things");
edits.clear();
AddEdit(&edits, GetEnd(buffer), " memes");
ApplyEdits(&buffer, edits);
Assert(GetString(buffer, buffer.lines[0]) == "Things and other things memes");
}
{
Buffer buffer = {scratch};
Array<Edit> edits = {scratch};
edits.add({});
ApplyEdits(&buffer, edits);
Assert("" == GetString(buffer));
Assert(buffer.lines.len == 1);
}
{
Buffer buffer = {scratch};
Array<Edit> edits = {scratch};
edits.add({
{0, 0},
"Things and other things"
});
ApplyEdits(&buffer, edits);
edits.clear();
AddEdit(&edits, {0, 6}, "Memes");
AddEdit(&edits, {7, 10}, "dna");
AddEdit(&edits, {11, 16}, "BigOther");
ApplyEdits(&buffer, edits);
String string = {buffer.data[buffer.bi], buffer.len};
Assert(string == "Memes dna BigOther things");
Assert(buffer.lines.len == 1);
Assert(GetString(buffer, buffer.lines[0]) == "Memes dna BigOther things");
}
{
Buffer buffer = {scratch};
Array<Edit> edits = {scratch};
edits.add({
{0, 0},
"Things and other things\n"
"Things and other things\n"
});
ApplyEdits(&buffer, edits);
Assert(buffer.lines.len == 3);
Assert(GetString(buffer, buffer.lines[1]) == "Things and other things");
Assert(GetString(buffer, buffer.lines[0]) == "Things and other things");
Assert(GetString(buffer, buffer.lines[2]) == "");
{
Array<char> s = {scratch};
for (BufferIter iter = Iterate(buffer, {0, 6}); IsValid(iter); Advance(&iter)) {
Assert(iter.item < 255);
s.add((char)iter.item);
}
String str = {s.data, s.len};
Assert(str == "Things");
}
{
Array<char> s = {scratch};
for (BufferIter iter = Iterate(buffer, {0, 6}, ITERATE_BACKWARD); IsValid(iter); Advance(&iter)) {
Assert(iter.item < 255);
s.add((char)iter.item);
}
String str = {s.data, s.len};
Assert(str == "sgnihT");
}
{
Array<char> s = {scratch};
for (BufferIter iter = Iterate(buffer, {0, buffer.len}); IsValid(iter); Advance(&iter)) {
Assert(iter.item < 255);
s.add((char)iter.item);
}
String str = {s.data, s.len};
String b = {GetCharP(buffer, 0), buffer.len};
Assert(str == b);
}
{
Array<char> s = {scratch};
for (BufferIter iter = Iterate(buffer, {0, buffer.len}, ITERATE_BACKWARD); IsValid(iter); Advance(&iter)) {
Assert(iter.item < 255);
s.add((char)iter.item);
}
String str = {s.data, s.len};
String b = {GetCharP(buffer, 0), buffer.len};
Assert(str.len == b.len);
}
}
{
Arena *arena = AllocArena();
Buffer buffer = {*arena};
Array<Edit> edits = {*arena};
edits.add({
{0, 0},
"Things and other things\n"
"Things and other things\n"
});
int iters = 100;
for (int i = 0; i < iters; i += 1) {
ApplyEdits(&buffer, edits);
for (int64_t j = 0; j < i; j += 1) {
String string = GetString(buffer, {edits[0].string.len * j, edits[0].string.len * (j + 1)});
Assert(string == edits[0].string);
}
}
Assert(edits[0].string.len * iters == buffer.len);
Assert(buffer.lines.len == iters * 2 + 1);
Line l0 = FindLine(buffer, 4);
Assert(l0.number == 0);
Assert(l0.range.min == 0);
Assert(l0.range.max < 30);
Line l1 = FindLine(buffer, 30);
Assert(l1.number == 1);
Assert(l1.range.min > 20);
Assert(l1.range.max < 50);
Assert(l1.range.max == GetLine(buffer, 1).range.max);
// Make sure there are no gaps
for (int64_t i = 100; i < 600; i += 1) {
Line l2 = FindLine(buffer, i);
Assert(l2.number > 0);
}
}
}