start on editor
This commit is contained in:
parent
7b972d9baa
commit
058d7faea1
1
.ignore
1
.ignore
@ -1,3 +1,4 @@
|
|||||||
.git
|
.git
|
||||||
src/VulkanRenderer/vma
|
src/VulkanRenderer/vma
|
||||||
src/DLibs/external
|
src/DLibs/external
|
||||||
|
build
|
||||||
|
|||||||
2
dub.json
2
dub.json
@ -15,7 +15,7 @@
|
|||||||
"libs-windows": [],
|
"libs-windows": [],
|
||||||
"preGenerateCommands-linux": ["./build.sh"],
|
"preGenerateCommands-linux": ["./build.sh"],
|
||||||
"preGenerateCommands-windows": [],
|
"preGenerateCommands-windows": [],
|
||||||
"dflags": ["-Xcc=-mno-sse", "-P-I/usr/include/freetype2", "-vgc"],
|
"dflags": ["-Xcc=-mno-sse", "-P-I/usr/include/freetype2"],
|
||||||
"dflags-dmd": ["-P=-DSTBI_NO_SIMD"]
|
"dflags-dmd": ["-P=-DSTBI_NO_SIMD"]
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
211
src/editor/buffer.d
Normal file
211
src/editor/buffer.d
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
import aliases;
|
||||||
|
import math;
|
||||||
|
import alloc;
|
||||||
|
import util;
|
||||||
|
|
||||||
|
struct GapBuffer
|
||||||
|
{
|
||||||
|
u8[] data;
|
||||||
|
u64 length;
|
||||||
|
u64 gap_start;
|
||||||
|
u64 gap_end;
|
||||||
|
u64 gap_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
GapBuffer
|
||||||
|
CreateGapBuffer(u8[] data)
|
||||||
|
{
|
||||||
|
// Match 4k page sizes
|
||||||
|
u64 capacity = RoundUp(cast(u64)data.length, KB(4));
|
||||||
|
if (data.length % KB(4) == 0)
|
||||||
|
{
|
||||||
|
capacity += KB(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8[] buf = MAllocArray!(u8)(capacity);
|
||||||
|
|
||||||
|
buf[0 .. data.length] = data[0 .. $];
|
||||||
|
|
||||||
|
GapBuffer buffer = {
|
||||||
|
data: buf,
|
||||||
|
length: data.length,
|
||||||
|
gap_start: data.length,
|
||||||
|
gap_end: data.length + (capacity - data.length),
|
||||||
|
gap_size: capacity - cast(u64)(data.length),
|
||||||
|
};
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GrowBuffer(GapBuffer* buffer)
|
||||||
|
{
|
||||||
|
u8[] temp_buf = buffer.data[0 .. buffer.length];
|
||||||
|
GapBuffer temp_gap = CreateGapBuffer(temp_buf);
|
||||||
|
MFreeArray(buffer.data);
|
||||||
|
*buffer = temp_gap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Insert(GapBuffer* buffer, u8[] insert, u64 length, i64 pos)
|
||||||
|
{
|
||||||
|
assert(length <= insert.length, "Insert Error: length is greater than insert buffer length");
|
||||||
|
|
||||||
|
if (buffer.length + length > buffer.data.length)
|
||||||
|
{
|
||||||
|
if (buffer.length < buffer.data.length)
|
||||||
|
{
|
||||||
|
Shift(buffer, buffer.data.length);
|
||||||
|
}
|
||||||
|
GrowBuffer(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
Shift(buffer, pos);
|
||||||
|
|
||||||
|
buffer.data[buffer.gap_start .. buffer.gap_start+length] = insert[0 .. length];
|
||||||
|
buffer.length += length;
|
||||||
|
buffer.gap_start += length;
|
||||||
|
buffer.gap_size -= length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Shift(GapBuffer* buffer, i64 pos)
|
||||||
|
{
|
||||||
|
if (pos < 0)
|
||||||
|
{
|
||||||
|
pos = 0;
|
||||||
|
}
|
||||||
|
else if (pos > buffer.length)
|
||||||
|
{
|
||||||
|
pos = buffer.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 old_pos = buffer.gap_start;
|
||||||
|
u64 new_pos = cast(u64)pos;
|
||||||
|
|
||||||
|
u64 diff;
|
||||||
|
if (old_pos < new_pos)
|
||||||
|
{
|
||||||
|
diff = new_pos - old_pos;
|
||||||
|
buffer.data[buffer.gap_start .. buffer.gap_start+diff] = buffer.data[buffer.gap_end .. buffer.gap_end+diff];
|
||||||
|
buffer.gap_start += diff;
|
||||||
|
buffer.gap_end += diff;
|
||||||
|
}
|
||||||
|
else if (old_pos > new_pos)
|
||||||
|
{
|
||||||
|
diff = old_pos - new_pos;
|
||||||
|
buffer.data[buffer.gap_end-diff .. buffer.gap_end] = buffer.data[buffer.gap_start-diff .. buffer.gap_start];
|
||||||
|
buffer.gap_start -= diff;
|
||||||
|
buffer.gap_end -= diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GetLines(GapBuffer* buffer, u8[][] lines, u64 start_line)
|
||||||
|
{
|
||||||
|
Shift(buffer, buffer.data.length);
|
||||||
|
|
||||||
|
u64 count;
|
||||||
|
u64 start;
|
||||||
|
foreach(i, ch; buffer.data)
|
||||||
|
{
|
||||||
|
if (count == lines.length)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch == '\n')
|
||||||
|
{
|
||||||
|
scope(exit) count += 1;
|
||||||
|
|
||||||
|
if (count < start_line)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
lines[count][start .. i-start] = buffer.data[start .. i];
|
||||||
|
lines[count][i-start] = '\0';
|
||||||
|
start = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MoveCursorL(GapBuffer* buffer, u64 length)
|
||||||
|
{
|
||||||
|
assert(length, "MoveCursorL Error: 0 length provided");
|
||||||
|
|
||||||
|
u64 new_pos = length >= buffer.length ? buffer.length - length : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
// Inserts
|
||||||
|
{
|
||||||
|
string test_str = "This is a test string for testing the GapBuffer struct.";
|
||||||
|
string test_str_2 = "This is an additional string. ";
|
||||||
|
u8[] data = (cast(u8*)test_str.ptr)[0 .. test_str.length];
|
||||||
|
GapBuffer buf = CreateGapBuffer(data);
|
||||||
|
|
||||||
|
u8[] insert = (cast(u8*)test_str_2.ptr)[0 .. test_str_2.length];
|
||||||
|
Insert(&buf, insert, insert.length, 0);
|
||||||
|
|
||||||
|
u8[][] line_buf = new u8[][](1, 1024);
|
||||||
|
GetLines(&buf, line_buf, 0);
|
||||||
|
|
||||||
|
u64 count = 0;
|
||||||
|
foreach(i, ch; test_str_2)
|
||||||
|
{
|
||||||
|
assert(buf.data[count] == ch, "Buffer doesn't match test_str_2");
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(i, ch; test_str)
|
||||||
|
{
|
||||||
|
assert(buf.data[count] == ch, "Buffer doesn't match test_str");
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
string test_str_3 = "not ";
|
||||||
|
insert = (cast(u8*)test_str_3.ptr)[0 .. test_str_3.length];
|
||||||
|
Insert(&buf, insert, insert.length, 8);
|
||||||
|
GetLines(&buf, line_buf, 0);
|
||||||
|
|
||||||
|
string result = "This is not an additional string. This is a test string for testing the GapBuffer struct.";
|
||||||
|
foreach(i, ch; result)
|
||||||
|
{
|
||||||
|
assert(buf.data[i] == ch, "Buffer doesn't match result");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grow Buffer
|
||||||
|
{
|
||||||
|
u8[] data;
|
||||||
|
GapBuffer buf = CreateGapBuffer(data);
|
||||||
|
|
||||||
|
foreach(i; 0 .. buf.data.length)
|
||||||
|
{
|
||||||
|
Insert(&buf, ['a'], 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(i; 0 .. 1024)
|
||||||
|
{
|
||||||
|
Insert(&buf, ['b'], 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8[][] line_buf = new u8[][](1, 8096);
|
||||||
|
GetLines(&buf, line_buf, 0);
|
||||||
|
|
||||||
|
foreach(i; 0 .. 5120)
|
||||||
|
{
|
||||||
|
if (i < 1024)
|
||||||
|
{
|
||||||
|
assert(line_buf[0][i] == 'b');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(line_buf[0][i] == 'a');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,76 @@
|
|||||||
|
import aliases;
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
|
import buffer;
|
||||||
|
import util;
|
||||||
|
|
||||||
void main(string[] argv)
|
void main(string[] argv)
|
||||||
{
|
{
|
||||||
writeln("Hello, World!");
|
// Inserts
|
||||||
|
{
|
||||||
|
string test_str = "This is a test string for testing the GapBuffer struct.";
|
||||||
|
string test_str_2 = "This is an additional string. ";
|
||||||
|
u8[] data = (cast(u8*)test_str.ptr)[0 .. test_str.length];
|
||||||
|
GapBuffer buf = CreateGapBuffer(data);
|
||||||
|
|
||||||
|
u8[] insert = (cast(u8*)test_str_2.ptr)[0 .. test_str_2.length];
|
||||||
|
Insert(&buf, insert, insert.length, 0);
|
||||||
|
|
||||||
|
u8[][] line_buf = new u8[][](1, 1024);
|
||||||
|
GetLines(&buf, line_buf, 0);
|
||||||
|
|
||||||
|
u64 count = 0;
|
||||||
|
foreach(i, ch; test_str_2)
|
||||||
|
{
|
||||||
|
assert(buf.data[count] == ch, "Buffer doesn't match test_str_2");
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(i, ch; test_str)
|
||||||
|
{
|
||||||
|
assert(buf.data[count] == ch, "Buffer doesn't match test_str");
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
string test_str_3 = "not ";
|
||||||
|
insert = (cast(u8*)test_str_3.ptr)[0 .. test_str_3.length];
|
||||||
|
Insert(&buf, insert, insert.length, 8);
|
||||||
|
GetLines(&buf, line_buf, 0);
|
||||||
|
|
||||||
|
string result = "This is not an additional string. This is a test string for testing the GapBuffer struct.";
|
||||||
|
foreach(i, ch; result)
|
||||||
|
{
|
||||||
|
assert(buf.data[i] == ch, "Buffer doesn't match result");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grow Buffer
|
||||||
|
{
|
||||||
|
u8[] data;
|
||||||
|
GapBuffer buf = CreateGapBuffer(data);
|
||||||
|
|
||||||
|
foreach(i; 0 .. buf.data.length)
|
||||||
|
{
|
||||||
|
Insert(&buf, ['a'], 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(i; 0 .. 1024)
|
||||||
|
{
|
||||||
|
Insert(&buf, ['b'], 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8[][] line_buf = new u8[][](1, 8096);
|
||||||
|
GetLines(&buf, line_buf, 0);
|
||||||
|
|
||||||
|
foreach(i; 0 .. 5120)
|
||||||
|
{
|
||||||
|
if (i < 1024)
|
||||||
|
{
|
||||||
|
assert(line_buf[0][i] == 'b');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(line_buf[0][i] == 'a');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user