Remove old deprecated dqn lib
This commit is contained in:
parent
21104f85d5
commit
2f681515f6
@ -1,38 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
|
|
||||||
<Type Name="DqnArray<*>">
|
|
||||||
<DisplayString>{{len={len}/{max}}}</DisplayString>
|
|
||||||
<Expand>
|
|
||||||
<Item Name="[len]">len</Item>
|
|
||||||
<Item Name="[max]">max</Item>
|
|
||||||
<ArrayItems>
|
|
||||||
<Size>len</Size>
|
|
||||||
<ValuePointer>data</ValuePointer>
|
|
||||||
</ArrayItems>
|
|
||||||
</Expand>
|
|
||||||
</Type>
|
|
||||||
|
|
||||||
<Type Name="DqnMemStack::Block">
|
|
||||||
<DisplayString>{{used={head-tail}/{size} prev_block={prev_block}}}</DisplayString>
|
|
||||||
</Type>
|
|
||||||
|
|
||||||
<Type Name="DqnSlice<*>">
|
|
||||||
<DisplayString>{len={len} data={data,[len]}}</DisplayString>
|
|
||||||
<StringView>data,s</StringView>
|
|
||||||
</Type>
|
|
||||||
|
|
||||||
<Type Name="DqnBuffer<*>">
|
|
||||||
<DisplayString>{len={len} data={data,[len]}}</DisplayString>
|
|
||||||
<StringView>data,s</StringView>
|
|
||||||
</Type>
|
|
||||||
|
|
||||||
<Type Name="DqnFixedString<*>">
|
|
||||||
<DisplayString>{{len={len} {str,s}}}</DisplayString>
|
|
||||||
<StringView>str,s</StringView>
|
|
||||||
</Type>
|
|
||||||
|
|
||||||
<Type Name="DqnString">
|
|
||||||
<DisplayString>{{len={len}/{max} {str,s}}}</DisplayString>
|
|
||||||
<StringView>str,s</StringView>
|
|
||||||
</Type>
|
|
||||||
</AutoVisualizer>
|
|
@ -1,77 +0,0 @@
|
|||||||
void DqnFixedString_Test()
|
|
||||||
{
|
|
||||||
LOG_HEADER();
|
|
||||||
{
|
|
||||||
DqnFixedString<512> str = DQN_BUFFER_STR_LIT("hello world");
|
|
||||||
DQN_ASSERT(DqnStr_Cmp(str.str, "hello world") == 0);
|
|
||||||
|
|
||||||
Log(Status::Ok, "Copy constructor DqnSlice<char>");
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
DqnFixedString<512> zero = {};
|
|
||||||
DqnFixedString<512> str = DQN_BUFFER_STR_LIT("hello world");
|
|
||||||
str = zero;
|
|
||||||
DQN_ASSERT(str.len == 0 && str.str[0] == 0);
|
|
||||||
|
|
||||||
DqnSlice<char const> helloSlice = DQN_BUFFER_STR_LIT("hello");
|
|
||||||
str = helloSlice;
|
|
||||||
DQN_ASSERT(DqnStr_Cmp(str.str, "hello") == 0);
|
|
||||||
|
|
||||||
Log(Status::Ok, "Copy constructor (DqnFixedString<>)");
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
DqnFixedString<512> str = DQN_BUFFER_STR_LIT("hello world");
|
|
||||||
DQN_ASSERT(str.Sprintf("hello %s", "sailor"));
|
|
||||||
DQN_ASSERTM(DqnStr_Cmp(str.str, "hello sailor") == 0, "Result: %s", str.str);
|
|
||||||
|
|
||||||
Log(Status::Ok, "Sprintf");
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
{
|
|
||||||
DqnFixedString<512> str = DQN_BUFFER_STR_LIT("hello world");
|
|
||||||
DQN_ASSERT(str.Sprintf("hello %s", "sailor"));
|
|
||||||
str += DQN_BUFFER_STR_LIT(".end");
|
|
||||||
DQN_ASSERTM(DqnStr_Cmp(str.str, "hello sailor.end") == 0, "Result: %s", str.str);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
DqnFixedString<512> str = DQN_BUFFER_STR_LIT("hello world");
|
|
||||||
DQN_ASSERT(str.Sprintf("hello %s", "sailor"));
|
|
||||||
DQN_ASSERT(str.SprintfAppend(" %d, %d", 100, 200));
|
|
||||||
DQN_ASSERT(DqnStr_Cmp(str.str, "hello sailor 100, 200") == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Log(Status::Ok, "Concatenation, operator +=, SprintfAppend");
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
DqnFixedString<512> str;
|
|
||||||
str = "hello big world";
|
|
||||||
DQN_ASSERT(DqnStr_Cmp(str.str, "hello big world") == 0);
|
|
||||||
str = DqnFixedString<512>("goodbye", DQN_CHAR_COUNT("goodbye"));
|
|
||||||
DQN_ASSERT(DqnStr_Cmp(str.str, "goodbye") == 0);
|
|
||||||
|
|
||||||
Log(Status::Ok, "Copy constructor (char const *str, int len)");
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
DqnFixedString<512> str = DQN_BUFFER_STR_LIT("hello world");
|
|
||||||
DQN_ASSERT(str.Sprintf("hello %s", "sailor"));
|
|
||||||
str = str + " end" + DQN_BUFFER_STR_LIT(" of");
|
|
||||||
DQN_ASSERT(DqnStr_Cmp(str.str, "hello sailor end of") == 0);
|
|
||||||
|
|
||||||
Log(Status::Ok, "Operator +");
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
DqnFixedString<512> str = "localhost";
|
|
||||||
str.SprintfAppend(":%d", 16832);
|
|
||||||
str += "/json_rpc";
|
|
||||||
DQN_ASSERT(str.len == 24 && DqnStr_Cmp("localhost:16832/json_rpc", str.str) == 0);
|
|
||||||
|
|
||||||
Log(Status::Ok, "Copy constructor, sprintf, operator +=");
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,119 +0,0 @@
|
|||||||
void DqnJson_Test()
|
|
||||||
{
|
|
||||||
LOG_HEADER();
|
|
||||||
char const json[] =
|
|
||||||
R"FOO(
|
|
||||||
{
|
|
||||||
"result": {
|
|
||||||
"cumulative_difficulty": 282912831023,
|
|
||||||
"difficulty": 18293,
|
|
||||||
"name": "Block",
|
|
||||||
"array_of_objects": [{
|
|
||||||
"hash": "83abdc3f",
|
|
||||||
"time": 102981029381,
|
|
||||||
}, {
|
|
||||||
"hash": "12acf73d",
|
|
||||||
"time": 123761239789,
|
|
||||||
}],
|
|
||||||
"time": 3498573485,
|
|
||||||
"embed_object": {
|
|
||||||
"proof": "axcbde",
|
|
||||||
"signature": "l9382kjabmznmx129aslzejs"
|
|
||||||
}
|
|
||||||
"bits": [1, 0, 1, 1, 0, 1, 0],
|
|
||||||
"hex": ["AF", "BE", "0C", "FF"],
|
|
||||||
"extra": [123],
|
|
||||||
"serialise": [],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)FOO";
|
|
||||||
|
|
||||||
DqnJson result = DqnJson_Get(DqnSlice<const char>(json, DQN_ARRAY_COUNT(json)), DQN_BUFFER_STR_LIT("result"));
|
|
||||||
DqnJson cum_difficulty = DqnJson_Get(result, DQN_BUFFER_STR_LIT("cumulative_difficulty"));
|
|
||||||
DqnJson difficulty = DqnJson_Get(result, DQN_BUFFER_STR_LIT("difficulty"));
|
|
||||||
DqnJson name = DqnJson_Get(result, DQN_BUFFER_STR_LIT("name"));
|
|
||||||
DqnJson array_of_objects = DqnJson_Get(result, DQN_BUFFER_STR_LIT("array_of_objects"));
|
|
||||||
DqnJson time = DqnJson_Get(result, DQN_BUFFER_STR_LIT("time"));
|
|
||||||
DqnJson embed_object = DqnJson_Get(result, DQN_BUFFER_STR_LIT("embed_object"));
|
|
||||||
DqnJson bits = DqnJson_Get(result, DQN_BUFFER_STR_LIT("bits"));
|
|
||||||
DqnJson hex = DqnJson_Get(result, DQN_BUFFER_STR_LIT("hex"));
|
|
||||||
DqnJson extra = DqnJson_Get(result, DQN_BUFFER_STR_LIT("extra"));
|
|
||||||
DqnJson serialise = DqnJson_Get(result, DQN_BUFFER_STR_LIT("serialise"));
|
|
||||||
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(cum_difficulty.value, DQN_BUFFER_STR_LIT("282912831023"), Dqn::IgnoreCase::No));
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(difficulty.value, DQN_BUFFER_STR_LIT("18293"), Dqn::IgnoreCase::No));
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(name.value, DQN_BUFFER_STR_LIT("\"Block\""), Dqn::IgnoreCase::No));
|
|
||||||
|
|
||||||
{
|
|
||||||
DQN_ASSERT(array_of_objects.IsArray() && array_of_objects.num_entries == 2);
|
|
||||||
isize count = 0;
|
|
||||||
while(DqnJson it = DqnJson_GetNextArrayItem(&array_of_objects))
|
|
||||||
{
|
|
||||||
DqnJson hash = DqnJson_Get(it, DQN_BUFFER_STR_LIT("hash"));
|
|
||||||
DqnJson time2 = DqnJson_Get(it, DQN_BUFFER_STR_LIT("time"));
|
|
||||||
if (count == 0)
|
|
||||||
{
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(hash.value, DQN_BUFFER_STR_LIT("\"83abdc3f\""), Dqn::IgnoreCase::No));
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(time2.value, DQN_BUFFER_STR_LIT("102981029381"), Dqn::IgnoreCase::No));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(hash.value, DQN_BUFFER_STR_LIT("\"12acf73d\""), Dqn::IgnoreCase::No));
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(time2.value, DQN_BUFFER_STR_LIT("123761239789"), Dqn::IgnoreCase::No));
|
|
||||||
}
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
DqnJson proof = DqnJson_Get(embed_object, DQN_BUFFER_STR_LIT("proof"));
|
|
||||||
DqnJson signature = DqnJson_Get(embed_object, DQN_BUFFER_STR_LIT("signature"));
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(proof.value, DQN_BUFFER_STR_LIT("\"axcbde\""), Dqn::IgnoreCase::No));
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(signature.value, DQN_BUFFER_STR_LIT("\"l9382kjabmznmx129aslzejs\""), Dqn::IgnoreCase::No));
|
|
||||||
}
|
|
||||||
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(time.value, DQN_BUFFER_STR_LIT("3498573485"), Dqn::IgnoreCase::No));
|
|
||||||
|
|
||||||
{
|
|
||||||
DQN_ASSERT(bits.IsArray() && bits.num_entries == 7);
|
|
||||||
DqnJson bits_array[7];
|
|
||||||
isize bitsIndex = 0;
|
|
||||||
|
|
||||||
while(DqnJson it = DqnJson_GetNextArrayItem(&bits))
|
|
||||||
bits_array[bitsIndex++] = it;
|
|
||||||
|
|
||||||
DQN_ASSERT(bitsIndex == DQN_ARRAY_COUNT(bits_array));
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(bits_array[0].value, DQN_BUFFER_STR_LIT("1"), Dqn::IgnoreCase::No));
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(bits_array[1].value, DQN_BUFFER_STR_LIT("0"), Dqn::IgnoreCase::No));
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(bits_array[2].value, DQN_BUFFER_STR_LIT("1"), Dqn::IgnoreCase::No));
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(bits_array[3].value, DQN_BUFFER_STR_LIT("1"), Dqn::IgnoreCase::No));
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(bits_array[4].value, DQN_BUFFER_STR_LIT("0"), Dqn::IgnoreCase::No));
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(bits_array[5].value, DQN_BUFFER_STR_LIT("1"), Dqn::IgnoreCase::No));
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(bits_array[6].value, DQN_BUFFER_STR_LIT("0"), Dqn::IgnoreCase::No));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
DQN_ASSERT(hex.IsArray() && hex.num_entries == 4);
|
|
||||||
DqnJson hex_array[4];
|
|
||||||
isize hex_index = 0;
|
|
||||||
|
|
||||||
while(DqnJson it = DqnJson_GetNextArrayItem(&hex))
|
|
||||||
hex_array[hex_index++] = it;
|
|
||||||
|
|
||||||
DQN_ASSERT(hex_index == DQN_ARRAY_COUNT(hex_array));
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(hex_array[0].value, DQN_BUFFER_STR_LIT("\"AF\""), Dqn::IgnoreCase::No));
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(hex_array[1].value, DQN_BUFFER_STR_LIT("\"BE\""), Dqn::IgnoreCase::No));
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(hex_array[2].value, DQN_BUFFER_STR_LIT("\"0C\""), Dqn::IgnoreCase::No));
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(hex_array[3].value, DQN_BUFFER_STR_LIT("\"FF\""), Dqn::IgnoreCase::No));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
DQN_ASSERT(extra.IsArray() && extra.num_entries == 1);
|
|
||||||
while(DqnJson it = DqnJson_GetNextArrayItem(&extra))
|
|
||||||
{
|
|
||||||
DQN_ASSERT(DQN_BUFFER_STRCMP(it.value, DQN_BUFFER_STR_LIT("123"), Dqn::IgnoreCase::No));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Log(Status::Ok, "DqnJson sample structure parsed");
|
|
||||||
}
|
|
@ -1,520 +0,0 @@
|
|||||||
FILE_SCOPE void DqnMemStack_Test()
|
|
||||||
{
|
|
||||||
LOG_HEADER();
|
|
||||||
|
|
||||||
// Check Alignment
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, 0, DqnMemTracker::Flag::Simple);
|
|
||||||
|
|
||||||
i32 const ALIGN64 = 64;
|
|
||||||
i32 const ALIGN16 = 16;
|
|
||||||
i32 const ALIGN4 = 4;
|
|
||||||
DqnMemStack::PushType push_type = DqnMemStack::PushType::Head;
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
u8 *result1 = (u8 *)stack.Push_(2, push_type, ALIGN4);
|
|
||||||
u8 *result2 = (u8 *)DQN_ALIGN_POW_N(result1, ALIGN4);
|
|
||||||
DQN_ASSERT(result1 == result2);
|
|
||||||
stack.Pop(result1);
|
|
||||||
DQN_ASSERT(stack.block->head == stack.block->memory);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
u8 *result1 = (u8 *)stack.Push_(120, push_type, ALIGN16);
|
|
||||||
u8 *result2 = (u8 *)DQN_ALIGN_POW_N(result1, ALIGN16);
|
|
||||||
DQN_ASSERT(result1 == result2);
|
|
||||||
stack.Pop(result1);
|
|
||||||
DQN_ASSERT(stack.block->head == stack.block->memory);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
u8 *result1 = (u8 *)stack.Push_(12, push_type, ALIGN64);
|
|
||||||
u8 *result2 = (u8 *)DQN_ALIGN_POW_N(result1, ALIGN64);
|
|
||||||
DQN_ASSERT(result1 == result2);
|
|
||||||
stack.Pop(result1);
|
|
||||||
DQN_ASSERT(stack.block->head == stack.block->memory);
|
|
||||||
}
|
|
||||||
|
|
||||||
stack.Free();
|
|
||||||
Log(Status::Ok, "Check allocated alignment to 4, 16, 64");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check Non-Expandable
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::NonExpandable);
|
|
||||||
auto *result1 = stack.Push_(DQN_MEGABYTE(2));
|
|
||||||
DQN_ASSERT(result1 == nullptr);
|
|
||||||
DQN_ASSERT(stack.block->prev_block == nullptr);
|
|
||||||
|
|
||||||
stack.Free();
|
|
||||||
Log(Status::Ok, "Check non-expandable flag prevents expansion.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check Expansion
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes);
|
|
||||||
auto *old_block = stack.block;
|
|
||||||
DQN_ASSERT(old_block);
|
|
||||||
DQN_ASSERT(old_block->size == DQN_MEGABYTE(1));
|
|
||||||
DQN_ASSERT(old_block->head == old_block->head);
|
|
||||||
DQN_ASSERT(old_block->tail == old_block->tail);
|
|
||||||
DQN_ASSERT(old_block->prev_block == nullptr);
|
|
||||||
|
|
||||||
auto *result1 = stack.Push_(DQN_MEGABYTE(2));
|
|
||||||
DQN_ASSERT(result1);
|
|
||||||
DQN_ASSERT(stack.block->prev_block == old_block);
|
|
||||||
DQN_ASSERT(stack.block != old_block);
|
|
||||||
|
|
||||||
Log(Status::Ok, "Check memory stack allocates additional memory blocks.");
|
|
||||||
stack.Free();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Temporary Regions
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
// Check temporary regions
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, 0, DqnMemTracker::Flag::Simple);
|
|
||||||
|
|
||||||
DqnMemStack::Block *block_to_return_to = stack.block;
|
|
||||||
auto head_before = block_to_return_to->head;
|
|
||||||
auto tail_before = block_to_return_to->tail;
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
auto mem_guard1 = stack.MemRegionScope();
|
|
||||||
auto *result2 = stack.Push_(100);
|
|
||||||
auto *result3 = stack.Push_(100);
|
|
||||||
auto *result4 = stack.Push_(100);
|
|
||||||
DQN_ASSERT(result2 && result3 && result4);
|
|
||||||
DQN_ASSERT(stack.block->head != head_before);
|
|
||||||
DQN_ASSERT(stack.block->tail == tail_before);
|
|
||||||
DQN_ASSERT(stack.block->memory == block_to_return_to->memory);
|
|
||||||
|
|
||||||
// Force allocation of new block
|
|
||||||
auto *result5 = stack.Push_(DQN_MEGABYTE(5));
|
|
||||||
DQN_ASSERT(result5);
|
|
||||||
DQN_ASSERT(stack.block != block_to_return_to);
|
|
||||||
DQN_ASSERT(stack.mem_region_count == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
DQN_ASSERT(stack.block == block_to_return_to);
|
|
||||||
DQN_ASSERT(stack.block->head == head_before);
|
|
||||||
DQN_ASSERT(stack.block->tail == tail_before);
|
|
||||||
|
|
||||||
stack.Free();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check temporary regions keep state
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, 0, DqnMemTracker::Flag::Simple);
|
|
||||||
DqnMemStack::Block *block_to_return_to = stack.block;
|
|
||||||
auto head_before = block_to_return_to->head;
|
|
||||||
auto tail_before = block_to_return_to->tail;
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
auto mem_guard1 = stack.MemRegionScope();
|
|
||||||
auto *result2 = stack.Push_(100);
|
|
||||||
auto *result3 = stack.Push_(100);
|
|
||||||
auto *result4 = stack.Push_(100);
|
|
||||||
DQN_ASSERT(result2 && result3 && result4);
|
|
||||||
DQN_ASSERT(stack.block->head != head_before);
|
|
||||||
DQN_ASSERT(stack.block->tail == tail_before);
|
|
||||||
DQN_ASSERT(stack.block->memory == block_to_return_to->memory);
|
|
||||||
|
|
||||||
// Force allocation of new block
|
|
||||||
auto *result5 = stack.Push_(DQN_MEGABYTE(5));
|
|
||||||
DQN_ASSERT(result5);
|
|
||||||
DQN_ASSERT(stack.block != block_to_return_to);
|
|
||||||
DQN_ASSERT(stack.mem_region_count == 1);
|
|
||||||
stack.MemRegionSave(&mem_guard1);
|
|
||||||
}
|
|
||||||
|
|
||||||
DQN_ASSERT(stack.block != block_to_return_to);
|
|
||||||
DQN_ASSERT(stack.block->prev_block == block_to_return_to);
|
|
||||||
DQN_ASSERT(stack.mem_region_count == 0);
|
|
||||||
|
|
||||||
stack.Free();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check temporary regions with tail and head pushes
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, 0, DqnMemTracker::Flag::Simple);
|
|
||||||
|
|
||||||
auto *pop1 = stack.Push_(222);
|
|
||||||
auto *pop2 = stack.Push_(333, DqnMemStack::PushType::Tail);
|
|
||||||
|
|
||||||
DqnMemStack::Block *block_to_return_to = stack.block;
|
|
||||||
auto head_before = block_to_return_to->head;
|
|
||||||
auto tail_before = block_to_return_to->tail;
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
auto mem_guard1 = stack.MemRegionScope();
|
|
||||||
auto *result2 = stack.Push_(100);
|
|
||||||
auto *result3 = stack.Push_(100, DqnMemStack::PushType::Tail);
|
|
||||||
auto *result4 = stack.Push_(100);
|
|
||||||
auto *result5 = stack.Push_(100, DqnMemStack::PushType::Tail);
|
|
||||||
DQN_ASSERT(result2 && result3 && result4 && result5);
|
|
||||||
DQN_ASSERT(result3 > result5);
|
|
||||||
DQN_ASSERT(result2 < result4);
|
|
||||||
DQN_ASSERT(stack.block->head > head_before && stack.block->head < stack.block->tail);
|
|
||||||
DQN_ASSERT(stack.block->tail >= stack.block->head && stack.block->tail < (stack.block->memory + stack.block->size));
|
|
||||||
DQN_ASSERT(stack.block->memory == block_to_return_to->memory);
|
|
||||||
|
|
||||||
// Force allocation of new block
|
|
||||||
auto *result6 = stack.Push_(DQN_MEGABYTE(5));
|
|
||||||
DQN_ASSERT(result6);
|
|
||||||
DQN_ASSERT(stack.block != block_to_return_to);
|
|
||||||
DQN_ASSERT(stack.mem_region_count == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
DQN_ASSERT(stack.block == block_to_return_to);
|
|
||||||
DQN_ASSERT(stack.block->head == head_before);
|
|
||||||
DQN_ASSERT(stack.block->tail == tail_before);
|
|
||||||
|
|
||||||
stack.Pop(pop1);
|
|
||||||
stack.Pop(pop2);
|
|
||||||
DQN_ASSERT(stack.block->head == stack.block->memory);
|
|
||||||
DQN_ASSERT(stack.block->tail == stack.block->memory + stack.block->size);
|
|
||||||
|
|
||||||
stack.Free();
|
|
||||||
}
|
|
||||||
Log(Status::Ok, "Temporary regions revert state and save state");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check Fixed Mem Init
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
// Check success
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
isize const buf_size = sizeof(DqnMemStack::Block) * 5;
|
|
||||||
char buf[buf_size] = {};
|
|
||||||
auto stack = DqnMemStack(&buf, buf_size, Dqn::ZeroMem::No);
|
|
||||||
|
|
||||||
DQN_ASSERT(stack.block);
|
|
||||||
DQN_ASSERT(stack.block->prev_block == false);
|
|
||||||
DQN_ASSERT(stack.mem_region_count == 0);
|
|
||||||
DQN_ASSERT(stack.flags == DqnMemStack::Flag::NonExpandable);
|
|
||||||
|
|
||||||
auto *result1 = stack.Push_(32);
|
|
||||||
DQN_ASSERT(result1);
|
|
||||||
stack.Pop(result1);
|
|
||||||
|
|
||||||
auto *result2 = stack.Push_(buf_size * 2);
|
|
||||||
DQN_ASSERT(result2 == nullptr);
|
|
||||||
DQN_ASSERT(stack.block);
|
|
||||||
DQN_ASSERT(stack.block->prev_block == false);
|
|
||||||
DQN_ASSERT(stack.mem_region_count == 0);
|
|
||||||
DQN_ASSERT(stack.flags == DqnMemStack::Flag::NonExpandable);
|
|
||||||
|
|
||||||
stack.Free();
|
|
||||||
}
|
|
||||||
|
|
||||||
Log(Status::Ok, "Checked fixed mem initialisation");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check Freeing Blocks
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
usize size = 32;
|
|
||||||
usize additional_size = DqnMemStack::MINIMUM_BLOCK_SIZE;
|
|
||||||
|
|
||||||
auto stack = DqnMemStack(size, Dqn::ZeroMem::Yes, 0);
|
|
||||||
auto *block1 = stack.block;
|
|
||||||
|
|
||||||
size += additional_size;
|
|
||||||
auto *result1 = stack.Push_(size);
|
|
||||||
auto *block2 = stack.block;
|
|
||||||
|
|
||||||
size += additional_size;
|
|
||||||
auto *result2 = stack.Push_(size);
|
|
||||||
auto *block3 = stack.block;
|
|
||||||
|
|
||||||
size += additional_size;
|
|
||||||
auto *result3 = stack.Push_(size);
|
|
||||||
auto *block4 = stack.block;
|
|
||||||
|
|
||||||
size += additional_size;
|
|
||||||
auto *result4 = stack.Push_(size);
|
|
||||||
auto *block5 = stack.block;
|
|
||||||
|
|
||||||
DQN_ASSERT(result1 && result2 && result3 && result4);
|
|
||||||
DQN_ASSERT(block1 && block2 && block3 && block4 && block5);
|
|
||||||
DQN_ASSERT(block5->prev_block == block4);
|
|
||||||
DQN_ASSERT(block4->prev_block == block3);
|
|
||||||
DQN_ASSERT(block3->prev_block == block2);
|
|
||||||
DQN_ASSERT(block2->prev_block == block1);
|
|
||||||
DQN_ASSERT(block1->prev_block == nullptr);
|
|
||||||
|
|
||||||
DQN_ASSERT(stack.FreeBlock(block4));
|
|
||||||
DQN_ASSERT(stack.block == block5);
|
|
||||||
DQN_ASSERT(block5->prev_block == block3);
|
|
||||||
DQN_ASSERT(block3->prev_block == block2);
|
|
||||||
DQN_ASSERT(block2->prev_block == block1);
|
|
||||||
DQN_ASSERT(block1->prev_block == nullptr);
|
|
||||||
|
|
||||||
DQN_ASSERT(stack.FreeBlock(block5));
|
|
||||||
DQN_ASSERT(stack.block == block3);
|
|
||||||
DQN_ASSERT(block3->prev_block == block2);
|
|
||||||
DQN_ASSERT(block2->prev_block == block1);
|
|
||||||
DQN_ASSERT(block1->prev_block == nullptr);
|
|
||||||
|
|
||||||
stack.Free();
|
|
||||||
DQN_ASSERT(stack.block == nullptr);
|
|
||||||
Log(Status::Ok, "Check freeing arbitrary blocks and freeing");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check bounds guard places magic values
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, 0, DqnMemTracker::Flag::Simple);
|
|
||||||
char *result = static_cast<char *>(stack.Push_(64));
|
|
||||||
|
|
||||||
// TODO(doyle): check head and tail are adjacent to the bounds of the allocation
|
|
||||||
u32 *head = stack.tracker.PtrToHeadGuard(result);
|
|
||||||
u32 *tail = stack.tracker.PtrToTailGuard(result);
|
|
||||||
DQN_ASSERT(*head == DqnMemTracker::HEAD_GUARD_VALUE);
|
|
||||||
DQN_ASSERT(*tail == DqnMemTracker::TAIL_GUARD_VALUE);
|
|
||||||
|
|
||||||
stack.Free();
|
|
||||||
Log(Status::Ok, "Bounds guards are placed adjacent and have magic values.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
// Push_ to tail and head
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
DqnMemStack stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, 0, DqnMemTracker::Flag::Simple);
|
|
||||||
|
|
||||||
auto *result1 = stack.Push_(100);
|
|
||||||
auto *result2 = stack.Push_(100, DqnMemStack::PushType::Tail);
|
|
||||||
auto *head_before = stack.block->head;
|
|
||||||
auto *tail_before = stack.block->tail;
|
|
||||||
DQN_ASSERT(result2 && result1);
|
|
||||||
DQN_ASSERT(result2 != result1 && result1 < result2);
|
|
||||||
|
|
||||||
stack.Pop(result2);
|
|
||||||
DQN_ASSERT(head_before == stack.block->head)
|
|
||||||
DQN_ASSERT(tail_before != stack.block->tail)
|
|
||||||
|
|
||||||
stack.Pop(result1);
|
|
||||||
DQN_ASSERT(stack.block->prev_block == false);
|
|
||||||
DQN_ASSERT(stack.block->head == stack.block->memory);
|
|
||||||
DQN_ASSERT(stack.block->tail == stack.block->memory + stack.block->size);
|
|
||||||
stack.Free();
|
|
||||||
Log(Status::Ok, "Push_, pop to tail and head.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expansion with tail
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
// Push_ too much to tail causes expansion
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
DqnMemStack stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, 0, DqnMemTracker::Flag::Simple);
|
|
||||||
|
|
||||||
auto *result1 = stack.Push_(100);
|
|
||||||
DQN_ASSERT(stack.block->prev_block == nullptr);
|
|
||||||
DQN_ASSERT(stack.block->head > stack.block->memory && stack.block->head < stack.block->tail);
|
|
||||||
DQN_ASSERT(stack.block->tail == stack.block->memory + stack.block->size);
|
|
||||||
auto *block_before = stack.block;
|
|
||||||
|
|
||||||
auto *result2 = stack.Push_(DQN_MEGABYTE(1), DqnMemStack::PushType::Tail);
|
|
||||||
DQN_ASSERT(result2 && result1);
|
|
||||||
DQN_ASSERT(result2 != result1);
|
|
||||||
DQN_ASSERT(stack.block->prev_block == block_before);
|
|
||||||
DQN_ASSERT(stack.block != block_before);
|
|
||||||
|
|
||||||
DQN_ASSERT(stack.block->head == stack.block->memory);
|
|
||||||
DQN_ASSERT(stack.block->tail < stack.block->memory + stack.block->size &&
|
|
||||||
stack.block->tail >= stack.block->head);
|
|
||||||
|
|
||||||
stack.Pop(result2);
|
|
||||||
DQN_ASSERT(block_before == stack.block);
|
|
||||||
|
|
||||||
stack.Pop(result1);
|
|
||||||
DQN_ASSERT(block_before == stack.block);
|
|
||||||
|
|
||||||
stack.Free();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push_ too much to tail fails to expand when non expandable
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
DqnMemStack stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::NonExpandable);
|
|
||||||
|
|
||||||
auto *result1 = stack.Push_(100);
|
|
||||||
DQN_ASSERT(stack.block->prev_block == nullptr);
|
|
||||||
DQN_ASSERT(stack.block->head != stack.block->memory);
|
|
||||||
DQN_ASSERT(stack.block->tail == stack.block->memory + stack.block->size);
|
|
||||||
auto *block_before = stack.block;
|
|
||||||
|
|
||||||
auto *result2 = stack.Push_(DQN_MEGABYTE(1), DqnMemStack::PushType::Tail);
|
|
||||||
DQN_ASSERT(result2 == nullptr);
|
|
||||||
DQN_ASSERT(stack.block->prev_block == nullptr);
|
|
||||||
DQN_ASSERT(stack.block == block_before);
|
|
||||||
DQN_ASSERT(stack.block->head > stack.block->memory && stack.block->head < stack.block->tail);
|
|
||||||
DQN_ASSERT(stack.block->tail == stack.block->memory + stack.block->size);
|
|
||||||
|
|
||||||
stack.Pop(result2);
|
|
||||||
DQN_ASSERT(block_before == stack.block);
|
|
||||||
|
|
||||||
stack.Pop(result1);
|
|
||||||
DQN_ASSERT(block_before == stack.block);
|
|
||||||
|
|
||||||
stack.Free();
|
|
||||||
}
|
|
||||||
|
|
||||||
Log(Status::Ok, "Non-Expanding and expanding stack with tail push.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check stack allocator mem api callbacks
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
// Realloc in same block and allow it to grow in place.
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
// Using push on head
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
DqnMemStack stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::BoundsGuard);
|
|
||||||
auto *api = &stack.myHeadAPI;
|
|
||||||
|
|
||||||
auto *block_before = stack.block;
|
|
||||||
auto *head_before = stack.block->head;
|
|
||||||
|
|
||||||
isize buf_size = 16;
|
|
||||||
char *buf = (char *)stack.Push_(buf_size);
|
|
||||||
DqnMem_Set(buf, 'X', buf_size);
|
|
||||||
for (auto i = 0; i < buf_size; i++) DQN_ASSERT(buf[i] == 'X');
|
|
||||||
|
|
||||||
isize old_buf_size = buf_size;
|
|
||||||
buf_size = 32;
|
|
||||||
buf = (char *)api->Realloc(buf, old_buf_size, buf_size);
|
|
||||||
for (auto i = 0; i < old_buf_size; i++) DQN_ASSERT(buf[i] == 'X');
|
|
||||||
DqnMem_Set(buf, '@', buf_size);
|
|
||||||
|
|
||||||
DQN_ASSERT(block_before == stack.block);
|
|
||||||
DQN_ASSERT(head_before < stack.block->head);
|
|
||||||
stack.Pop(buf);
|
|
||||||
|
|
||||||
DQN_ASSERT(block_before == stack.block);
|
|
||||||
DQN_ASSERT(head_before == stack.block->head);
|
|
||||||
DQN_ASSERT(head_before == stack.block->memory);
|
|
||||||
stack.Free();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Using push on tail
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
DqnMemStack stack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::BoundsGuard);
|
|
||||||
auto *api = &stack.myHeadAPI;
|
|
||||||
|
|
||||||
auto *block_before = stack.block;
|
|
||||||
auto *tail_before = stack.block->tail;
|
|
||||||
|
|
||||||
isize buf_size = 16;
|
|
||||||
char *buf = (char *)stack.Push_(buf_size, DqnMemStack::PushType::Tail);
|
|
||||||
DqnMem_Set(buf, 'X', buf_size);
|
|
||||||
for (auto i = 0; i < buf_size; i++) DQN_ASSERT(buf[i] == 'X');
|
|
||||||
|
|
||||||
isize old_buf_size = buf_size;
|
|
||||||
buf_size = 32;
|
|
||||||
buf = (char *)api->Realloc(buf, old_buf_size, buf_size);
|
|
||||||
for (auto i = 0; i < old_buf_size; i++) DQN_ASSERT(buf[i] == 'X');
|
|
||||||
DqnMem_Set(buf, '@', buf_size);
|
|
||||||
|
|
||||||
DQN_ASSERT(block_before == stack.block);
|
|
||||||
DQN_ASSERT(tail_before > stack.block->tail);
|
|
||||||
stack.Pop(buf);
|
|
||||||
|
|
||||||
DQN_ASSERT(block_before == stack.block);
|
|
||||||
DQN_ASSERT(tail_before == stack.block->tail);
|
|
||||||
DQN_ASSERT(stack.block->head == stack.block->memory);
|
|
||||||
stack.Free();
|
|
||||||
}
|
|
||||||
Log(Status::Ok, "Allocator MemAPI callback, realloc grow in place");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Realloc in same block and insufficient size and expand
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
// Using push on head
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
auto stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::BoundsGuard);
|
|
||||||
auto *api = &stack.myHeadAPI;
|
|
||||||
|
|
||||||
auto *block_before = stack.block;
|
|
||||||
auto *head_before = stack.block->head;
|
|
||||||
|
|
||||||
isize buf_size = 16;
|
|
||||||
char *buf = (char *)stack.Push_(buf_size);
|
|
||||||
DqnMem_Set(buf, 'X', buf_size);
|
|
||||||
for (auto i = 0; i < buf_size; i++) DQN_ASSERT(buf[i] == 'X');
|
|
||||||
|
|
||||||
isize old_buf_size = buf_size;
|
|
||||||
buf_size = DQN_MEGABYTE(2);
|
|
||||||
buf = (char *)api->Realloc(buf, old_buf_size, buf_size);
|
|
||||||
for (auto i = 0; i < old_buf_size; i++) DQN_ASSERT(buf[i] == 'X');
|
|
||||||
DqnMem_Set(buf, '@', buf_size);
|
|
||||||
|
|
||||||
DQN_ASSERT(block_before == stack.block->prev_block);
|
|
||||||
stack.Pop(buf);
|
|
||||||
|
|
||||||
DQN_ASSERT(block_before == stack.block);
|
|
||||||
DQN_ASSERT(head_before == stack.block->head);
|
|
||||||
DQN_ASSERT(head_before == stack.block->memory);
|
|
||||||
stack.Free();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Using push on tail
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
DqnMemStack stack = DqnMemStack(DQN_MEGABYTE(1), Dqn::ZeroMem::Yes, DqnMemStack::Flag::BoundsGuard);
|
|
||||||
auto *api = &stack.myHeadAPI;
|
|
||||||
|
|
||||||
auto *block_before = stack.block;
|
|
||||||
auto *tail_before = stack.block->tail;
|
|
||||||
|
|
||||||
isize buf_size = 16;
|
|
||||||
char *buf = (char *)stack.Push_(buf_size, DqnMemStack::PushType::Tail);
|
|
||||||
DqnMem_Set(buf, 'X', buf_size);
|
|
||||||
for (auto i = 0; i < buf_size; i++) DQN_ASSERT(buf[i] == 'X');
|
|
||||||
|
|
||||||
isize old_buf_size = buf_size;
|
|
||||||
buf_size = DQN_MEGABYTE(2);
|
|
||||||
buf = (char *)api->Realloc(buf, old_buf_size, buf_size);
|
|
||||||
for (auto i = 0; i < old_buf_size; i++)
|
|
||||||
DQN_ASSERT(buf[i] == 'X');
|
|
||||||
DqnMem_Set(buf, '@', buf_size);
|
|
||||||
|
|
||||||
DQN_ASSERT(block_before != stack.block);
|
|
||||||
DQN_ASSERT(block_before == stack.block->prev_block);
|
|
||||||
stack.Pop(buf);
|
|
||||||
|
|
||||||
DQN_ASSERT(block_before == stack.block);
|
|
||||||
DQN_ASSERT(tail_before == stack.block->tail);
|
|
||||||
|
|
||||||
DQN_ASSERT(stack.block->head == stack.block->memory);
|
|
||||||
stack.Free();
|
|
||||||
}
|
|
||||||
Log(Status::Ok, "Allocator MemAPI callback, realloc insufficient size so expand");
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(doyle): Realloc to smaller size logic
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
|||||||
struct DqnProcess
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
void DqnOS_Test()
|
|
||||||
{
|
|
||||||
// pid_t pid = vfork();
|
|
||||||
// if (pid == 0)
|
|
||||||
// {
|
|
||||||
// char const *argv[] = {"jim", "jams", NULL};
|
|
||||||
// char const *envp[] = {"some", "environment", NULL};
|
|
||||||
// chdir("/home/usr/loki/");
|
|
||||||
// execve(cmd, argv, envp);
|
|
||||||
// perror("Could not execute");
|
|
||||||
// }
|
|
||||||
#if defined(DQN__IS_WIN32)
|
|
||||||
// CreateProcessW();
|
|
||||||
|
|
||||||
WSAData wsaData;
|
|
||||||
int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "WSAStartup failed: %d\n", result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
addrinfo hints = {};
|
|
||||||
hints.ai_family = AF_UNSPEC;
|
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
|
||||||
hints.ai_protocol = IPPROTO_TCP;
|
|
||||||
|
|
||||||
addrinfo *foundAddr = nullptr;
|
|
||||||
result = getaddrinfo("127.0.0.1", "38151", &hints, &foundAddr);
|
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "getaddrinfo failed: %d\n", result);
|
|
||||||
WSACleanup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SOCKET connectSocket = socket(foundAddr->ai_family, foundAddr->ai_socktype, foundAddr->ai_protocol);
|
|
||||||
if (connectSocket == INVALID_SOCKET)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "socket failed: %d\n", WSAGetLastError());
|
|
||||||
freeaddrinfo(foundAddr);
|
|
||||||
WSACleanup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
@ -1,919 +0,0 @@
|
|||||||
#ifndef DQN_REFLECT_H
|
|
||||||
#define DQN_REFLECT_H
|
|
||||||
|
|
||||||
#define DQN_REFLECT
|
|
||||||
#define DQN_REFLECT_META(...)
|
|
||||||
|
|
||||||
//
|
|
||||||
// HOW TO REFLECT ANNOTATED CODE
|
|
||||||
// Define in the preprocessor, DQN_REFLECT_IMPLEMENTATION and compile
|
|
||||||
// Dqn_Reflect.h to produce the metaprogram binary. Run the binary on the
|
|
||||||
// desired C++ source files which will generate a DqnReflect_Generated.cpp
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// DqnReflect.exe <filename>.[c|cpp|h] ...
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// HOW TO ANNOTATE CODE
|
|
||||||
// This header file should be included in all files containing information you
|
|
||||||
// wish to reflect, you may reflect C-like data structures, such as in the
|
|
||||||
// following example.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Your Source Code
|
|
||||||
//
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
DQN_REFLECT enum struct OpenGLShader
|
|
||||||
{
|
|
||||||
Invalid,
|
|
||||||
Rect DQN_REFLECT_META(VertexShaderFilePath = "Rect.vert", FragmentShaderFilePath = "Rect.frag"),
|
|
||||||
Text DQN_REFLECT_META(VertexShaderFilePath = "Text.vert", FragmentShaderFilePath = "Text.frag"),
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
|
||||||
// Generated code in DqnReflect_Generated.cpp
|
|
||||||
//
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
#ifndef DQN_REFLECT_GENERATED_H
|
|
||||||
#define DQN_REFLECT_GENERATED_H
|
|
||||||
|
|
||||||
//
|
|
||||||
// OpenGL.h
|
|
||||||
//
|
|
||||||
|
|
||||||
#if !defined(DQN_REFLECT_DISABLE_OPENGL_H)
|
|
||||||
char const *DqnReflect_OpenGLShader_Strings[] = {"Invalid", "Bitmap", "Text" };
|
|
||||||
|
|
||||||
char const *DqnReflect_EnumString(OpenGLShader val)
|
|
||||||
{
|
|
||||||
if (val == OpenGLShader::Invalid) return DqnReflect_OpenGLShader_Strings[0]; // "Invalid"
|
|
||||||
if (val == OpenGLShader::Rect) return DqnReflect_OpenGLShader_Strings[1]; // "Rect"
|
|
||||||
if (val == OpenGLShader::Bitmap) return DqnReflect_OpenGLShader_Strings[2]; // "Bitmap"
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
char const *DqnReflect_VertexFilePathMetadata(OpenGLShader val)
|
|
||||||
{
|
|
||||||
if (val == OpenGLShader::Rect) return "Rect.vert";
|
|
||||||
if (val == OpenGLShader::Bitmap) return "Bitmap.vert";
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
char const *DqnReflect_FragmentFilePathMetadata(OpenGLShader val)
|
|
||||||
{
|
|
||||||
if (val == OpenGLShader::Rect) return "Rect.frag";
|
|
||||||
if (val == OpenGLShader::Bitmap) return "Bitmap.frag";
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // DQN_REFLECT_DISABLE_OPENGL_H
|
|
||||||
|
|
||||||
#endif // DQN_REFLECT_GENERATED_H
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DQN_REFLECT_IMPLEMENTATION
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
using usize = size_t;
|
|
||||||
using isize = ptrdiff_t;
|
|
||||||
using i64 = int64_t;
|
|
||||||
using i32 = int32_t;
|
|
||||||
using b32 = int32_t;
|
|
||||||
using u8 = uint8_t;
|
|
||||||
|
|
||||||
template <typename Proc>
|
|
||||||
struct Defer
|
|
||||||
{
|
|
||||||
Proc proc;
|
|
||||||
Defer(Proc p) : proc(p) {}
|
|
||||||
~Defer() { proc(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DeferHelper
|
|
||||||
{
|
|
||||||
template <typename Lambda>
|
|
||||||
Defer<Lambda> operator+(Lambda lambda) { return Defer<Lambda>(lambda); }
|
|
||||||
};
|
|
||||||
|
|
||||||
#define STR_LITERAL(str) {str, CHAR_COUNT(str)}
|
|
||||||
struct StringLiteral
|
|
||||||
{
|
|
||||||
StringLiteral() = default;
|
|
||||||
StringLiteral(char *string, int string_len) : str(string) , len(string_len) { }
|
|
||||||
char *str;
|
|
||||||
int len;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct LinkedList
|
|
||||||
{
|
|
||||||
T data;
|
|
||||||
LinkedList *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define REFLECT_MAX(a, b) ((a) > (b)) ? (a) : (b)
|
|
||||||
#define ARRAY_COUNT(str) sizeof(str)/sizeof(str[0])
|
|
||||||
#define CHAR_COUNT(str) (ARRAY_COUNT(str) - 1)
|
|
||||||
#define TOKEN_COMBINE(x, y) x ## y
|
|
||||||
#define TOKEN_COMBINE2(x, y) TOKEN_COMBINE(x, y)
|
|
||||||
#define DEFER auto const TOKEN_COMBINE(defer_lambda_, __COUNTER__) = DeferHelper() + [&]()
|
|
||||||
|
|
||||||
#define KILOBYTE(val) (1024ULL * (val))
|
|
||||||
#define MEGABYTE(val) (1024ULL * KILOBYTE(val))
|
|
||||||
|
|
||||||
//
|
|
||||||
// Memory Utilities
|
|
||||||
//
|
|
||||||
|
|
||||||
struct MemArena
|
|
||||||
{
|
|
||||||
void *memory;
|
|
||||||
usize size;
|
|
||||||
usize used;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MemArenaScopedRegion
|
|
||||||
{
|
|
||||||
MemArenaScopedRegion (MemArena *arena_, usize used_) : arena(arena_), used(used_) {}
|
|
||||||
~MemArenaScopedRegion() { arena->used = used; }
|
|
||||||
MemArena *arena;
|
|
||||||
usize used;
|
|
||||||
};
|
|
||||||
|
|
||||||
static MemArena global_main_arena;
|
|
||||||
|
|
||||||
#define MEM_ARENA_ALLOC_ARRAY(arena, Type, num) static_cast<Type *>(MemArena_Alloc(arena, sizeof(Type) * num))
|
|
||||||
#define MEM_ARENA_ALLOC_STRUCT(arena, Type) static_cast<Type *>(MemArena_Alloc(arena, sizeof(Type)))
|
|
||||||
MemArena MemArena_Init(void *memory, usize size)
|
|
||||||
{
|
|
||||||
MemArena result = {};
|
|
||||||
result.memory = memory;
|
|
||||||
result.size = size;
|
|
||||||
result.used = 0;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemArenaScopedRegion MemArena_MakeScopedRegion(MemArena *arena)
|
|
||||||
{
|
|
||||||
return MemArenaScopedRegion(arena, arena->used);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *MemArena_Alloc(MemArena *arena, usize size)
|
|
||||||
{
|
|
||||||
assert(arena->used + size <= arena->size);
|
|
||||||
void *result = static_cast<uint8_t *>(arena->memory) + arena->used;
|
|
||||||
arena->used += size;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T> void EraseStableFromCArray(T *array, isize len, isize max, isize index);
|
|
||||||
#define FIXED_ARRAY_TEMPLATE_DECL template <typename T, int MAX_>
|
|
||||||
FIXED_ARRAY_TEMPLATE_DECL struct FixedArray
|
|
||||||
{
|
|
||||||
FixedArray() = default;
|
|
||||||
T data[MAX_];
|
|
||||||
isize len;
|
|
||||||
isize Max() const { return MAX_; }
|
|
||||||
T const &operator[] (isize i) const { assert(i >= 0 && i < len); return data[i]; }
|
|
||||||
T &operator[] (isize i) { assert(i >= 0 && i < len); return data[i]; }
|
|
||||||
T const *begin () const { return data; }
|
|
||||||
T const *end () const { return data + len; }
|
|
||||||
T *begin () { return data; }
|
|
||||||
T *end () { return data + len; }
|
|
||||||
};
|
|
||||||
FIXED_ARRAY_TEMPLATE_DECL FixedArray<T, MAX_> FixedArray_Init (T const *item, int num) { FixedArray<T, MAX_> result = {}; FixedArray_Add(&result, item, num); return result; }
|
|
||||||
FIXED_ARRAY_TEMPLATE_DECL T *FixedArray_Add (FixedArray<T, MAX_> *a, T const *items, int num) { assert(a->len + num <= MAX_); T *result = static_cast<T *>(MemCopy(a->data + a->len, items, sizeof(T) * num)); a->len += num; return result; }
|
|
||||||
FIXED_ARRAY_TEMPLATE_DECL T *FixedArray_Add (FixedArray<T, MAX_> *a, T const item) { assert(a->len < MAX_); a->data[a->len++] = item; return &a->data[a->len - 1]; }
|
|
||||||
FIXED_ARRAY_TEMPLATE_DECL T *FixedArray_Make (FixedArray<T, MAX_> *a, int num) { assert(a->len + num <= MAX_); T *result = a->data + a->len; a->len += num; return result;}
|
|
||||||
FIXED_ARRAY_TEMPLATE_DECL void FixedArray_Clear (FixedArray<T, MAX_> *a) { a->len = 0; }
|
|
||||||
FIXED_ARRAY_TEMPLATE_DECL void FixedArray_EraseStable (FixedArray<T, MAX_> *a, isize index) { EraseStableFromCArray<T>(a->data, a->len--, a.Max(), index); }
|
|
||||||
FIXED_ARRAY_TEMPLATE_DECL void FixedArray_EraseUnstable(FixedArray<T, MAX_> *a, isize index) { assert(index >= 0 && index < a->len); if (--a->len == 0) return; a->data[index] = a->data[a->len]; }
|
|
||||||
|
|
||||||
//
|
|
||||||
// String Utilities
|
|
||||||
//
|
|
||||||
|
|
||||||
b32 CharIsAlpha (char ch) { return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); }
|
|
||||||
b32 CharIsDigit (char ch) { return (ch >= '0' && ch <= '9'); }
|
|
||||||
b32 CharIsAlphaNum (char ch) { return CharIsAlpha(ch) || CharIsDigit(ch); }
|
|
||||||
b32 CharIsWhitespace(char ch) { return (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); }
|
|
||||||
|
|
||||||
char const *StrSkipToChar(char const *src, char ch)
|
|
||||||
{
|
|
||||||
char const *result = src;
|
|
||||||
while (result && result[0] && result[0] != ch) ++result;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
char const *StrSkipToNextAlphaNum(char const *src)
|
|
||||||
{
|
|
||||||
char const *result = src;
|
|
||||||
while (result && result[0] && !CharIsAlphaNum(result[0])) ++result;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
char const *StrSkipToNextDigit(char const *src)
|
|
||||||
{
|
|
||||||
char const *result = src;
|
|
||||||
while (result && result[0] && !CharIsDigit(result[0])) ++result;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
char const *StrSkipToNextChar(char const *src)
|
|
||||||
{
|
|
||||||
char const *result = src;
|
|
||||||
while (result && result[0] && !CharIsAlpha(result[0])) ++result;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
char const *StrSkipToNextWord(char const *src)
|
|
||||||
{
|
|
||||||
char const *result = src;
|
|
||||||
while (result && result[0] && !CharIsWhitespace(result[0])) ++result;
|
|
||||||
while (result && result[0] && CharIsWhitespace(result[0])) ++result;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
char const *StrSkipToNextWhitespace(char const *src)
|
|
||||||
{
|
|
||||||
char const *result = src;
|
|
||||||
while (result && result[0] && !CharIsWhitespace(result[0])) ++result;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
char const *StrSkipWhitespace(char const *src)
|
|
||||||
{
|
|
||||||
char const *result = src;
|
|
||||||
while (result && result[0] && CharIsWhitespace(result[0])) ++result;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
char const *StrSkipToNextWordInplace(char const **src) { *src = StrSkipToNextWord(*src); return *src; }
|
|
||||||
char const *StrSkipWhitespaceInplace(char const **src) { *src = StrSkipWhitespace(*src); return *src; }
|
|
||||||
|
|
||||||
char *StrFind(StringLiteral src, StringLiteral find)
|
|
||||||
{
|
|
||||||
char *buf_ptr = src.str;
|
|
||||||
char *buf_end = buf_ptr + src.len;
|
|
||||||
char *result = nullptr;
|
|
||||||
|
|
||||||
for (;*buf_ptr; ++buf_ptr)
|
|
||||||
{
|
|
||||||
int len_remaining = static_cast<int>(buf_end - buf_ptr);
|
|
||||||
if (len_remaining < find.len) break;
|
|
||||||
|
|
||||||
if (strncmp(buf_ptr, find.str, find.len) == 0)
|
|
||||||
{
|
|
||||||
result = buf_ptr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
b32 StrCmp(StringLiteral a, StringLiteral b)
|
|
||||||
{
|
|
||||||
if (a.len != b.len)
|
|
||||||
return false;
|
|
||||||
b32 result = (memcmp(a.str, b.str, a.len) == 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// CPP Tokenisers/Tokens
|
|
||||||
//
|
|
||||||
|
|
||||||
#define CPP_TOKEN_TYPE_X_MACRO \
|
|
||||||
X(EndOfStream, "End Of Stream") \
|
|
||||||
X(LeftBrace, "{") \
|
|
||||||
X(RightBrace, "}") \
|
|
||||||
X(OpenParen, "(") \
|
|
||||||
X(CloseParen, ")") \
|
|
||||||
X(Comma, ",") \
|
|
||||||
X(Colon, ":") \
|
|
||||||
X(FwdSlash, "/") \
|
|
||||||
X(Comment, "comment") \
|
|
||||||
X(LessThan, "<") \
|
|
||||||
X(GreaterThan, ">") \
|
|
||||||
X(Equals, "=") \
|
|
||||||
X(String, "\"") \
|
|
||||||
X(SemiColon, ";") \
|
|
||||||
X(Identifier, "Identifier") \
|
|
||||||
X(Number, "[0-9]") \
|
|
||||||
X(Hash, "#")
|
|
||||||
|
|
||||||
#define X(decl, str) decl,
|
|
||||||
enum struct CPPTokenType
|
|
||||||
{
|
|
||||||
CPP_TOKEN_TYPE_X_MACRO
|
|
||||||
};
|
|
||||||
#undef X
|
|
||||||
|
|
||||||
#define X(decl, str) str,
|
|
||||||
char const *CPPTokenType_Strings[]
|
|
||||||
{
|
|
||||||
CPP_TOKEN_TYPE_X_MACRO
|
|
||||||
};
|
|
||||||
#undef X
|
|
||||||
|
|
||||||
struct CPPToken
|
|
||||||
{
|
|
||||||
CPPTokenType type;
|
|
||||||
char *str;
|
|
||||||
int len;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CPPReflectMetadataEntry
|
|
||||||
{
|
|
||||||
StringLiteral key;
|
|
||||||
StringLiteral value;
|
|
||||||
};
|
|
||||||
|
|
||||||
using CPPReflectMetadataArray = FixedArray<CPPReflectMetadataEntry, 8>;
|
|
||||||
struct CPPEnumValuesLinkedList
|
|
||||||
{
|
|
||||||
StringLiteral value;
|
|
||||||
CPPReflectMetadataArray metadata_array;
|
|
||||||
CPPEnumValuesLinkedList *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CPPTokeniser
|
|
||||||
{
|
|
||||||
CPPToken *tokens;
|
|
||||||
int tokens_index;
|
|
||||||
int tokens_len;
|
|
||||||
int tokens_max;
|
|
||||||
|
|
||||||
int spaces_per_indent;
|
|
||||||
int indent_level;
|
|
||||||
FILE *output_file;
|
|
||||||
};
|
|
||||||
|
|
||||||
void CPPTokeniser_SprintfToFile(CPPTokeniser *tokeniser, char const *fmt, ...)
|
|
||||||
{
|
|
||||||
int const num_spaces = tokeniser->spaces_per_indent * tokeniser->indent_level;
|
|
||||||
fprintf(tokeniser->output_file, "%*s", num_spaces, "");
|
|
||||||
|
|
||||||
va_list va;
|
|
||||||
va_start(va, fmt);
|
|
||||||
vfprintf(tokeniser->output_file, fmt, va);
|
|
||||||
va_end(va);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPPTokeniser_SprintfToFileNoIndenting(CPPTokeniser *tokeniser, char const *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list va;
|
|
||||||
va_start(va, fmt);
|
|
||||||
vfprintf(tokeniser->output_file, fmt, va);
|
|
||||||
va_end(va);
|
|
||||||
}
|
|
||||||
|
|
||||||
CPPToken CPPTokeniser_NextToken(CPPTokeniser *tokeniser)
|
|
||||||
{
|
|
||||||
CPPToken result = tokeniser->tokens[tokeniser->tokens_index++];
|
|
||||||
if (result.type == CPPTokenType::LeftBrace) tokeniser->indent_level++;
|
|
||||||
else if (result.type == CPPTokenType::RightBrace) tokeniser->indent_level--;
|
|
||||||
assert(tokeniser->indent_level >= 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
CPPToken CPPTokeniser_PeekToken(CPPTokeniser *tokeniser)
|
|
||||||
{
|
|
||||||
CPPToken result = tokeniser->tokens[tokeniser->tokens_index];
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPPTokeniser_RewindToken(CPPTokeniser *tokeniser)
|
|
||||||
{
|
|
||||||
tokeniser->tokens[--tokeniser->tokens_index];
|
|
||||||
}
|
|
||||||
|
|
||||||
CPPToken CPPTokeniser_PrevToken(CPPTokeniser *tokeniser)
|
|
||||||
{
|
|
||||||
CPPToken result = {};
|
|
||||||
result.type = CPPTokenType::EndOfStream;
|
|
||||||
if (tokeniser->tokens_index > 0)
|
|
||||||
result = tokeniser->tokens[tokeniser->tokens_index - 1];
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
CPPToken *CPPTokeniser_MakeToken(CPPTokeniser *tokeniser)
|
|
||||||
{
|
|
||||||
assert(tokeniser->tokens_len < tokeniser->tokens_max);
|
|
||||||
CPPToken *result = tokeniser->tokens + tokeniser->tokens_len++;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// CPP Parsing Helpers
|
|
||||||
//
|
|
||||||
|
|
||||||
b32 IsIdentifierToken(CPPToken token, StringLiteral expect_str)
|
|
||||||
{
|
|
||||||
b32 result = (token.type == CPPTokenType::Identifier) && (StrCmp(StringLiteral(token.str, token.len), expect_str));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
b32 ExpectToken(CPPToken token, CPPTokenType type)
|
|
||||||
{
|
|
||||||
b32 result = token.type == type;
|
|
||||||
if (!result)
|
|
||||||
{
|
|
||||||
fprintf(stdout, "Expected token type: %s received: %.*s\n", CPPTokenType_Strings[(int)type], token.len, token.str);
|
|
||||||
fprintf(stdout, "Context: %.*s\n\n", (token.len > 100) ? 100 : token.len, token.str);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// CPP Parsing Functions
|
|
||||||
//
|
|
||||||
|
|
||||||
CPPReflectMetadataArray ParseCPPReflectMeta(CPPTokeniser *tokeniser)
|
|
||||||
{
|
|
||||||
CPPReflectMetadataArray result = {};
|
|
||||||
CPPToken token = CPPTokeniser_NextToken(tokeniser);
|
|
||||||
if (!ExpectToken(token, CPPTokenType::OpenParen))
|
|
||||||
return result;
|
|
||||||
|
|
||||||
for (token = CPPTokeniser_NextToken(tokeniser);
|
|
||||||
token.type != CPPTokenType::EndOfStream && token.type != CPPTokenType::CloseParen;
|
|
||||||
token = CPPTokeniser_NextToken(tokeniser))
|
|
||||||
{
|
|
||||||
if (token.type == CPPTokenType::Identifier)
|
|
||||||
{
|
|
||||||
auto metadata_key = StringLiteral(token.str, token.len);
|
|
||||||
CPPToken peek_token = CPPTokeniser_PeekToken(tokeniser);
|
|
||||||
if (!ExpectToken(peek_token, CPPTokenType::Equals))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
token = CPPTokeniser_NextToken(tokeniser);
|
|
||||||
peek_token = CPPTokeniser_PeekToken(tokeniser);
|
|
||||||
|
|
||||||
if (peek_token.type == CPPTokenType::String || peek_token.type == CPPTokenType::Identifier)
|
|
||||||
{
|
|
||||||
token = CPPTokeniser_NextToken(tokeniser);
|
|
||||||
if (IsIdentifierToken(token, STR_LITERAL("nullptr"))) continue;
|
|
||||||
|
|
||||||
CPPReflectMetadataEntry *entry = FixedArray_Make(&result, 1);
|
|
||||||
entry->key = metadata_key;
|
|
||||||
entry->value = StringLiteral(token.str, token.len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (token.type != CPPTokenType::EndOfStream && token.type != CPPTokenType::Comma)
|
|
||||||
token = CPPTokeniser_NextToken(tokeniser);
|
|
||||||
|
|
||||||
if (token.type == CPPTokenType::EndOfStream)
|
|
||||||
CPPTokeniser_RewindToken(tokeniser);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ParseCPPEnum(CPPTokeniser *tokeniser)
|
|
||||||
{
|
|
||||||
CPPToken token = CPPTokeniser_NextToken(tokeniser);
|
|
||||||
b32 enum_is_struct_or_class = false;
|
|
||||||
|
|
||||||
if (IsIdentifierToken(token, STR_LITERAL("class")) ||
|
|
||||||
IsIdentifierToken(token, STR_LITERAL("struct")))
|
|
||||||
{
|
|
||||||
enum_is_struct_or_class = true;
|
|
||||||
token = CPPTokeniser_NextToken(tokeniser);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ExpectToken(token, CPPTokenType::Identifier))
|
|
||||||
return;
|
|
||||||
|
|
||||||
CPPToken const enum_name = token;
|
|
||||||
token = CPPTokeniser_NextToken(tokeniser);
|
|
||||||
|
|
||||||
if (!ExpectToken(token, CPPTokenType::LeftBrace))
|
|
||||||
return;
|
|
||||||
|
|
||||||
b32 has_metadata = false;
|
|
||||||
CPPEnumValuesLinkedList *start_enum_value_token = nullptr, *enum_value_token = nullptr;
|
|
||||||
MemArenaScopedRegion mem_region = MemArena_MakeScopedRegion(&global_main_arena);
|
|
||||||
for (token = CPPTokeniser_NextToken(tokeniser);
|
|
||||||
token.type != CPPTokenType::EndOfStream && token.type != CPPTokenType::SemiColon;
|
|
||||||
token = CPPTokeniser_NextToken(tokeniser))
|
|
||||||
{
|
|
||||||
if (token.type == CPPTokenType::Identifier)
|
|
||||||
{
|
|
||||||
CPPToken enum_value = token;
|
|
||||||
token = CPPTokeniser_NextToken(tokeniser);
|
|
||||||
CPPReflectMetadataArray metadata_array = {};
|
|
||||||
if (IsIdentifierToken(token, STR_LITERAL("DQN_REFLECT_META")))
|
|
||||||
{
|
|
||||||
has_metadata = true;
|
|
||||||
metadata_array = ParseCPPReflectMeta(tokeniser);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!start_enum_value_token)
|
|
||||||
{
|
|
||||||
start_enum_value_token = MEM_ARENA_ALLOC_STRUCT(&global_main_arena, CPPEnumValuesLinkedList);
|
|
||||||
enum_value_token = start_enum_value_token;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
enum_value_token->next = MEM_ARENA_ALLOC_STRUCT(&global_main_arena, CPPEnumValuesLinkedList);
|
|
||||||
enum_value_token = enum_value_token->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
(*enum_value_token) = {};
|
|
||||||
enum_value_token->metadata_array = metadata_array;
|
|
||||||
enum_value_token->value = StringLiteral(enum_value.str, enum_value.len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Write Stringified Enum Array
|
|
||||||
//
|
|
||||||
{
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "char const *DqnReflect_%.*s_Strings[] = {", enum_name.len, enum_name.str);
|
|
||||||
tokeniser->indent_level++;
|
|
||||||
for (CPPEnumValuesLinkedList *link = start_enum_value_token; link; link = link->next)
|
|
||||||
{
|
|
||||||
StringLiteral enum_value = link->value;
|
|
||||||
CPPTokeniser_SprintfToFileNoIndenting(tokeniser, "\"%.*s\", ", enum_value.len, enum_value.str);
|
|
||||||
}
|
|
||||||
|
|
||||||
tokeniser->indent_level--;
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "};\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Write ReflectEnumString Function
|
|
||||||
//
|
|
||||||
{
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "char const *DqnReflect_EnumString(%.*s val)\n{\n", enum_name.len, enum_name.str);
|
|
||||||
tokeniser->indent_level++;
|
|
||||||
DEFER
|
|
||||||
{
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "return nullptr;\n");
|
|
||||||
tokeniser->indent_level--;
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "}\n\n");
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SourceCode
|
|
||||||
{
|
|
||||||
StringLiteral decl;
|
|
||||||
StringLiteral enum_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
LinkedList<SourceCode> src_code = {};
|
|
||||||
int longest_decl_len = 0;
|
|
||||||
{
|
|
||||||
LinkedList<SourceCode> *curr_src_code = nullptr;
|
|
||||||
char const *fmt = (enum_is_struct_or_class) ? "if (val == %.*s::%.*s) " : "if (val == %.*s) ";
|
|
||||||
for (CPPEnumValuesLinkedList *link = start_enum_value_token; link; link = link->next)
|
|
||||||
{
|
|
||||||
if (!curr_src_code) curr_src_code = &src_code;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
curr_src_code->next = static_cast<LinkedList<SourceCode> *>( MemArena_Alloc(&global_main_arena, sizeof(*curr_src_code)));
|
|
||||||
curr_src_code = curr_src_code->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringLiteral enum_value = link->value;
|
|
||||||
int required_len = 0;
|
|
||||||
|
|
||||||
if (enum_is_struct_or_class) required_len = snprintf(nullptr, 0, fmt, enum_name.len, enum_name.str, enum_value.len, enum_value.str) + 1;
|
|
||||||
else required_len = snprintf(nullptr, 0, fmt, enum_value.len, enum_value.str) + 1;
|
|
||||||
|
|
||||||
longest_decl_len = REFLECT_MAX(longest_decl_len, required_len);
|
|
||||||
curr_src_code->data.decl.str = MEM_ARENA_ALLOC_ARRAY(&global_main_arena, char, required_len);
|
|
||||||
curr_src_code->data.decl.len = required_len;
|
|
||||||
curr_src_code->data.enum_value = enum_value;
|
|
||||||
|
|
||||||
if (enum_is_struct_or_class) snprintf(curr_src_code->data.decl.str, curr_src_code->data.decl.len, fmt, enum_name.len, enum_name.str, enum_value.len, enum_value.str);
|
|
||||||
else snprintf(curr_src_code->data.decl.str, curr_src_code->data.decl.len, fmt, enum_value.len, enum_value.str);
|
|
||||||
}
|
|
||||||
curr_src_code->next = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int enum_index = 0;
|
|
||||||
for (LinkedList<SourceCode> *src_code_ptr = &src_code;
|
|
||||||
src_code_ptr;
|
|
||||||
src_code_ptr = src_code_ptr->next, ++enum_index)
|
|
||||||
{
|
|
||||||
StringLiteral enum_value = src_code_ptr->data.enum_value;
|
|
||||||
int padding = longest_decl_len - src_code_ptr->data.decl.len;
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "%.*s%*s", src_code_ptr->data.decl.len, src_code_ptr->data.decl.str, padding, "");
|
|
||||||
CPPTokeniser_SprintfToFileNoIndenting(tokeniser,
|
|
||||||
"return DqnReflect_%.*s_Strings[%d]; // \"%.*s\"\n",
|
|
||||||
enum_name.len, enum_name.str,
|
|
||||||
enum_index,
|
|
||||||
enum_value.len, enum_value.str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Write User Annotated Metadata Getter Functions
|
|
||||||
//
|
|
||||||
if (has_metadata)
|
|
||||||
{
|
|
||||||
struct CPPDeclToValue
|
|
||||||
{
|
|
||||||
StringLiteral cpp_decl;
|
|
||||||
StringLiteral value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MetadataEntry
|
|
||||||
{
|
|
||||||
StringLiteral key;
|
|
||||||
FixedArray<CPPDeclToValue, 32> cpp_decl_to_val;
|
|
||||||
};
|
|
||||||
|
|
||||||
FixedArray<MetadataEntry, 32> metadata_entries = {};
|
|
||||||
for (CPPEnumValuesLinkedList *link = start_enum_value_token;
|
|
||||||
link;
|
|
||||||
link = link->next)
|
|
||||||
{
|
|
||||||
for (CPPReflectMetadataEntry const &reflect_entry : link->metadata_array)
|
|
||||||
{
|
|
||||||
MetadataEntry *metadata_entry_to_append_to = nullptr;
|
|
||||||
for (MetadataEntry &check_metadata_entry : metadata_entries)
|
|
||||||
{
|
|
||||||
if (StrCmp(check_metadata_entry.key, reflect_entry.key))
|
|
||||||
{
|
|
||||||
metadata_entry_to_append_to = &check_metadata_entry;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!metadata_entry_to_append_to)
|
|
||||||
{
|
|
||||||
metadata_entry_to_append_to = FixedArray_Make(&metadata_entries, 1);
|
|
||||||
metadata_entry_to_append_to->key = reflect_entry.key;
|
|
||||||
}
|
|
||||||
|
|
||||||
CPPDeclToValue decl_to_val = {};
|
|
||||||
decl_to_val.cpp_decl = StringLiteral(link->value.str, link->value.len);
|
|
||||||
decl_to_val.value = reflect_entry.value;
|
|
||||||
FixedArray_Add(&metadata_entry_to_append_to->cpp_decl_to_val, decl_to_val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (MetadataEntry const &metadata : metadata_entries)
|
|
||||||
{
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser,
|
|
||||||
"char const *DqnReflect_%.*sMetadata(%.*s val)\n{\n",
|
|
||||||
metadata.key.len, metadata.key.str,
|
|
||||||
enum_name.len, enum_name.str);
|
|
||||||
|
|
||||||
tokeniser->indent_level++;
|
|
||||||
DEFER
|
|
||||||
{
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "return nullptr;\n");
|
|
||||||
tokeniser->indent_level--;
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser, "}\n\n");
|
|
||||||
};
|
|
||||||
|
|
||||||
int enum_index = 0;
|
|
||||||
for (CPPDeclToValue const &decl_to_val : metadata.cpp_decl_to_val)
|
|
||||||
{
|
|
||||||
StringLiteral const *cpp_decl = &decl_to_val.cpp_decl;
|
|
||||||
StringLiteral const *value = &decl_to_val.value;
|
|
||||||
|
|
||||||
if (enum_is_struct_or_class)
|
|
||||||
{
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser,
|
|
||||||
"if (val == %.*s::%.*s) ",
|
|
||||||
enum_name.len, enum_name.str,
|
|
||||||
cpp_decl->len, cpp_decl->str);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CPPTokeniser_SprintfToFile(tokeniser,
|
|
||||||
"if (val == %.*s) ",
|
|
||||||
cpp_decl->len, cpp_decl->str);
|
|
||||||
}
|
|
||||||
CPPTokeniser_SprintfToFileNoIndenting(tokeniser, "return \"%.*s\";\n", value->len, value->str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
if (argc < 1)
|
|
||||||
{
|
|
||||||
fprintf(stdout, "Usage: %s [<filename>, ...]", argv[0]);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
usize main_arena_mem_size = MEGABYTE(2);
|
|
||||||
void *main_arena_mem = malloc(main_arena_mem_size);
|
|
||||||
global_main_arena = MemArena_Init(main_arena_mem, main_arena_mem_size);
|
|
||||||
FILE *output_file = fopen("DqnReflect_Generated.cpp", "w");
|
|
||||||
|
|
||||||
fprintf(output_file,
|
|
||||||
"#ifndef DQN_REFLECT_GENERATED_H\n"
|
|
||||||
"#define DQN_REFLECT_GENERATED_H\n\n"
|
|
||||||
"// This is an auto generated file using Dqn_Reflect\n"
|
|
||||||
"\n");
|
|
||||||
|
|
||||||
for (usize arg_index = 1; arg_index < argc; ++arg_index)
|
|
||||||
{
|
|
||||||
MemArenaScopedRegion mem_region = MemArena_MakeScopedRegion(&global_main_arena);
|
|
||||||
char *file_name = argv[arg_index];
|
|
||||||
FILE *file = fopen(file_name, "rb");
|
|
||||||
fseek(file, 0, SEEK_END);
|
|
||||||
usize file_size = ftell(file);
|
|
||||||
rewind(file);
|
|
||||||
|
|
||||||
char *file_buf = (char *)MemArena_Alloc(&global_main_arena, file_size + 1);
|
|
||||||
file_buf[file_size] = 0;
|
|
||||||
|
|
||||||
if (fread(file_buf, file_size, 1, file) != 1)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Failed to fread: %zu bytes into buffer from file: %s\n", file_size, file_name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int const file_name_len = (int)strlen(file_name);
|
|
||||||
int file_include_contents_hash_define_len = 0;
|
|
||||||
char *file_include_contents_hash_define = nullptr;
|
|
||||||
{
|
|
||||||
char *extracted_file_name_buf = static_cast<char *>(MemArena_Alloc(&global_main_arena, file_name_len));
|
|
||||||
int extracted_file_name_len = 0;
|
|
||||||
|
|
||||||
for (int i = file_name_len - 1; i >= 0; i--, extracted_file_name_len++)
|
|
||||||
{
|
|
||||||
char ch = file_name[i];
|
|
||||||
if (ch == '.')
|
|
||||||
ch = '_';
|
|
||||||
|
|
||||||
if (ch >= 'a' && ch <= 'z') ch -= 'a' - 'A';
|
|
||||||
|
|
||||||
if (ch == '\\' || ch == '/')
|
|
||||||
break;
|
|
||||||
|
|
||||||
extracted_file_name_buf[i] = ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
file_include_contents_hash_define = extracted_file_name_buf + file_name_len - extracted_file_name_len;
|
|
||||||
file_include_contents_hash_define_len = extracted_file_name_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(output_file,
|
|
||||||
"//\n"
|
|
||||||
"// %s\n"
|
|
||||||
"//\n"
|
|
||||||
"\n"
|
|
||||||
"#if !defined(DQN_REFLECT_DISABLE_%.*s)\n",
|
|
||||||
file_name,
|
|
||||||
file_include_contents_hash_define_len,
|
|
||||||
file_include_contents_hash_define);
|
|
||||||
|
|
||||||
CPPTokeniser tokeniser = {};
|
|
||||||
tokeniser.spaces_per_indent = 4;
|
|
||||||
tokeniser.output_file = output_file;
|
|
||||||
tokeniser.tokens_max = 16384;
|
|
||||||
tokeniser.tokens = MEM_ARENA_ALLOC_ARRAY(&global_main_arena, CPPToken, tokeniser.tokens_max);
|
|
||||||
|
|
||||||
StringLiteral const REFLECT_MARKER = STR_LITERAL("DQN_REFLECT");
|
|
||||||
char *file_buf_end = file_buf + file_size;
|
|
||||||
StringLiteral buffer = StringLiteral(file_buf, file_size);
|
|
||||||
|
|
||||||
for (char *ptr = StrFind(buffer, REFLECT_MARKER);
|
|
||||||
ptr;
|
|
||||||
ptr = StrFind(buffer, REFLECT_MARKER))
|
|
||||||
{
|
|
||||||
ptr += REFLECT_MARKER.len;
|
|
||||||
for (; ptr;)
|
|
||||||
{
|
|
||||||
while (CharIsWhitespace(ptr[0])) ptr++;
|
|
||||||
if (!ptr[0]) break;
|
|
||||||
|
|
||||||
CPPToken *token = CPPTokeniser_MakeToken(&tokeniser);
|
|
||||||
token->str = ptr++;
|
|
||||||
token->len = 1;
|
|
||||||
switch(token->str[0])
|
|
||||||
{
|
|
||||||
case '{': { token->type = CPPTokenType::LeftBrace; } break;
|
|
||||||
case '}': { token->type = CPPTokenType::RightBrace; } break;
|
|
||||||
case '(': { token->type = CPPTokenType::OpenParen; } break;
|
|
||||||
case ')': { token->type = CPPTokenType::CloseParen; } break;
|
|
||||||
case ',': { token->type = CPPTokenType::Comma; } break;
|
|
||||||
case ';': { token->type = CPPTokenType::SemiColon; } break;
|
|
||||||
case '=': { token->type = CPPTokenType::Equals; } break;
|
|
||||||
case '<': { token->type = CPPTokenType::LessThan; } break;
|
|
||||||
case '>': { token->type = CPPTokenType::GreaterThan; } break;
|
|
||||||
case ':': { token->type = CPPTokenType::Colon; } break;
|
|
||||||
case '/':
|
|
||||||
{
|
|
||||||
token->type = CPPTokenType::FwdSlash;
|
|
||||||
if (ptr[0] == '/')
|
|
||||||
{
|
|
||||||
while (ptr[0] == ' ' || ptr[0] == '\t') ptr++;
|
|
||||||
token->str = ptr;
|
|
||||||
while (ptr[0] != '\n') ptr++;
|
|
||||||
token->type = CPPTokenType::Comment;
|
|
||||||
token->len = ptr - token->str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
ptr--;
|
|
||||||
if (ptr[0] == '"')
|
|
||||||
{
|
|
||||||
token->type = CPPTokenType::String;
|
|
||||||
for (token->str = ++ptr;;)
|
|
||||||
{
|
|
||||||
while (ptr[0] != '"') ptr++;
|
|
||||||
token->len = ptr - token->str;
|
|
||||||
if (ptr[-1] != '\\')
|
|
||||||
{
|
|
||||||
ptr++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (CharIsDigit(ptr[0]))
|
|
||||||
{
|
|
||||||
while (CharIsDigit(ptr[0]) || ptr[0] == 'x' || ptr[0] == 'b' || ptr[0] == 'e' || ptr[0] == '.' || ptr[0] == 'f')
|
|
||||||
ptr++;
|
|
||||||
|
|
||||||
token->type = CPPTokenType::Number;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
token->type = CPPTokenType::Identifier;
|
|
||||||
if (CharIsAlpha(ptr[0]) || ptr[0] == '_')
|
|
||||||
{
|
|
||||||
ptr++;
|
|
||||||
while (CharIsAlphaNum(ptr[0]) || ptr[0] == '_') ptr++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
token->len = ptr - token->str;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (token->len == 0)
|
|
||||||
{
|
|
||||||
*token = {};
|
|
||||||
tokeniser.tokens_len--;
|
|
||||||
}
|
|
||||||
else if (token->type == CPPTokenType::SemiColon)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.str = ptr;
|
|
||||||
buffer.len = static_cast<int>(file_buf_end - ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
CPPToken *sentinel = CPPTokeniser_MakeToken(&tokeniser);
|
|
||||||
sentinel->type = CPPTokenType::EndOfStream;
|
|
||||||
|
|
||||||
for (CPPToken token = CPPTokeniser_NextToken(&tokeniser);
|
|
||||||
token.type != CPPTokenType::EndOfStream;
|
|
||||||
token = CPPTokeniser_NextToken(&tokeniser))
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
Token const *token = tokens + index;
|
|
||||||
fprintf(stdout, "%.*s", token->len, token->str);
|
|
||||||
if (index < (tokens_index - 1)) fprintf(stdout, " -> ");
|
|
||||||
#endif
|
|
||||||
if (token.type == CPPTokenType::Identifier)
|
|
||||||
{
|
|
||||||
if (StrCmp(StringLiteral(token.str, token.len), STR_LITERAL("enum")))
|
|
||||||
ParseCPPEnum(&tokeniser);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(output_file, "#endif // DQN_REFLECT_DISABLE_%.*s\n\n",
|
|
||||||
file_include_contents_hash_define_len,
|
|
||||||
file_include_contents_hash_define);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(output_file, "#endif // DQN_REFLECT_GENERATED_H\n");
|
|
||||||
fclose(output_file);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // DQN_REFLECT_IMPLEMENTATION
|
|
||||||
#endif // DQN_REFLECT_H
|
|
File diff suppressed because it is too large
Load Diff
@ -1,32 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio 15
|
|
||||||
VisualStudioVersion = 15.0.27428.2037
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{911E67C6-3D85-4FCE-B560-20A9C3E3FF48}") = "DqnUnitTest", "bin\DqnUnitTest.exe", "{F1606403-E704-4C35-8354-8E33DE4F5CCF}"
|
|
||||||
ProjectSection(DebuggerProjectSystem) = preProject
|
|
||||||
PortSupplier = 00000000-0000-0000-0000-000000000000
|
|
||||||
Executable = F:\dev\dqn\bin\DqnUnitTest.exe
|
|
||||||
RemoteMachine = THAI-XPS13
|
|
||||||
StartingDirectory = F:\dev\dqn\
|
|
||||||
Environment = Default
|
|
||||||
LaunchingEngine = 00000000-0000-0000-0000-000000000000
|
|
||||||
UseLegacyDebugEngines = No
|
|
||||||
LaunchSQLEngine = No
|
|
||||||
AttachLaunchAction = No
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Release|x64 = Release|x64
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{F1606403-E704-4C35-8354-8E33DE4F5CCF}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
SolutionGuid = {8DD71C86-534C-4A9C-A217-CBA13DE8DA5A}
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
@ -1,88 +0,0 @@
|
|||||||
void DqnVHashTable_Test()
|
|
||||||
{
|
|
||||||
LOG_HEADER();
|
|
||||||
struct Block
|
|
||||||
{
|
|
||||||
int x;
|
|
||||||
};
|
|
||||||
using Height = u32;
|
|
||||||
|
|
||||||
{
|
|
||||||
Block block = {};
|
|
||||||
|
|
||||||
DqnVHashTable<Height, Block> table = {};
|
|
||||||
DQN_DEFER { table.Free(); };
|
|
||||||
table.Set(12, block);
|
|
||||||
|
|
||||||
Block *getResult = table.Get(12);
|
|
||||||
Block *operatorResult = table[12];
|
|
||||||
DQN_ASSERT(operatorResult == getResult);
|
|
||||||
DQN_ASSERT(operatorResult != nullptr);
|
|
||||||
Log(Status::Ok, "Set and get element using key");
|
|
||||||
|
|
||||||
table.Erase(12);
|
|
||||||
getResult = table.Get(12);
|
|
||||||
operatorResult = table[12];
|
|
||||||
|
|
||||||
DQN_ASSERT(operatorResult == getResult);
|
|
||||||
DQN_ASSERT(operatorResult == nullptr);
|
|
||||||
Log(Status::Ok, "Erase element using key");
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
Block blocks[] = {{0}, {1}, {2}, {3}, {4}};
|
|
||||||
DqnVHashTable<Height, Block> table = {};
|
|
||||||
DQN_DEFER { table.Free(); };
|
|
||||||
|
|
||||||
table.Set(1, blocks[0]);
|
|
||||||
table.Set(2, blocks[1]);
|
|
||||||
table.Set(3, blocks[2]);
|
|
||||||
table.Set(4, blocks[3]);
|
|
||||||
table.Set(5, blocks[4]);
|
|
||||||
|
|
||||||
{
|
|
||||||
bool blockSeen[DQN_ARRAY_COUNT(blocks)] = {};
|
|
||||||
isize blocksSeen = 0;
|
|
||||||
for (auto const &entry : table)
|
|
||||||
{
|
|
||||||
Block const *block = &entry.item;
|
|
||||||
DQN_ASSERT(blockSeen[block->x] == false);
|
|
||||||
blockSeen[block->x] = true;
|
|
||||||
blocksSeen++;
|
|
||||||
}
|
|
||||||
DQN_ASSERT(blocksSeen == DQN_ARRAY_COUNT(blockSeen));
|
|
||||||
Log(Status::Ok, "Auto iterator using prefix operator++");
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
bool blockSeen[DQN_ARRAY_COUNT(blocks)] = {};
|
|
||||||
isize blocksSeen = 0;
|
|
||||||
for (auto it = table.begin(); it != table.end();)
|
|
||||||
{
|
|
||||||
Block *block = &it.entry->item;
|
|
||||||
|
|
||||||
DQN_ASSERT(blockSeen[block->x] == false);
|
|
||||||
blockSeen[block->x] = true;
|
|
||||||
blocksSeen++;
|
|
||||||
it = it + 1;
|
|
||||||
}
|
|
||||||
DQN_ASSERT(blocksSeen == DQN_ARRAY_COUNT(blockSeen));
|
|
||||||
Log(Status::Ok, "Auto iterator using operator+");
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
bool blockSeen[DQN_ARRAY_COUNT(blocks)] = {};
|
|
||||||
isize blocksSeen = 0;
|
|
||||||
for (auto it = table.begin(); it != table.end(); it++)
|
|
||||||
{
|
|
||||||
Block *block = &it.entry->item;
|
|
||||||
|
|
||||||
DQN_ASSERT(blockSeen[block->x] == false);
|
|
||||||
blockSeen[block->x] = true;
|
|
||||||
blocksSeen++;
|
|
||||||
}
|
|
||||||
DQN_ASSERT(blocksSeen == DQN_ARRAY_COUNT(blockSeen));
|
|
||||||
Log(Status::Ok, "Auto iterator using postfix operator++");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,71 +0,0 @@
|
|||||||
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or
|
|
||||||
@REM vcvarsall.bat to setup command-line compiler.
|
|
||||||
|
|
||||||
@echo OFF
|
|
||||||
set ProjectName=DqnUnitTest
|
|
||||||
set CompileEntryPoint=..\DqnUnitTest.cpp
|
|
||||||
|
|
||||||
REM Build tags file if you have ctags in path
|
|
||||||
where /q ctags
|
|
||||||
if %errorlevel%==0 (
|
|
||||||
REM When parsing a C++ member function definition (e.g. "className::function"),
|
|
||||||
REM ctags cannot determine whether the scope specifier is a class name or
|
|
||||||
REM a namespace specifier and always lists it as a class name in the scope
|
|
||||||
REM portion of the extension fields. Also, if a C++ function is defined outside
|
|
||||||
REM of the class declaration (the usual case), the access specification (i.e.
|
|
||||||
REM public, protected, or private) and implementation information (e.g. virtual,
|
|
||||||
REM pure virtual) contained in the function declaration are not known when the
|
|
||||||
REM tag is generated for the function definition. -c++-kinds=+p fixes that
|
|
||||||
|
|
||||||
REM The --fields=+iaS option:
|
|
||||||
REM a Access (or export) of class members
|
|
||||||
REM i Inheritance information
|
|
||||||
REM S Signature of routine (e.g. prototype or parameter list)
|
|
||||||
REM
|
|
||||||
REM The --extra=+q option:
|
|
||||||
REM By default, ctags only generates tags for separate identifiers found in
|
|
||||||
REM the source files. With --extras=+q option, then ctags will also generate
|
|
||||||
REM a second, class-qualified tag for each class member
|
|
||||||
ctags -R --c++-kinds=+p --fields=+iaS --extras=+q
|
|
||||||
)
|
|
||||||
|
|
||||||
REM Check if build tool is on path
|
|
||||||
REM >nul, 2>nul will remove the output text from the where command
|
|
||||||
where cl.exe >nul 2>nul
|
|
||||||
if %errorlevel%==1 call msvc86.bat
|
|
||||||
|
|
||||||
REM Drop compilation files into build folder
|
|
||||||
IF NOT EXIST bin mkdir bin
|
|
||||||
pushd bin
|
|
||||||
|
|
||||||
REM EHa- disable exception handling (but we use for algorithms so /EHsc)
|
|
||||||
REM GR- disable c runtime type information (we don't use)
|
|
||||||
|
|
||||||
REM MD use dynamic runtime library
|
|
||||||
REM MT use static runtime library, so build and link it into exe
|
|
||||||
|
|
||||||
REM Oi enable intrinsics optimisation, let us use CPU intrinsics if there is one
|
|
||||||
REM instead of generating a call to external library (i.e. CRT).
|
|
||||||
|
|
||||||
REM Zi enables debug data, Z7 combines the debug files into one.
|
|
||||||
|
|
||||||
REM W4 warning level 4
|
|
||||||
REM WX treat warnings as errors
|
|
||||||
REM wd4201 ignore: nonstandard extension used: nameless struct/union
|
|
||||||
set CompileFlags=-EHsc -GR- -Oi -MT -Z7 -W4 -WX -wd4201 -FC -Od -wd4127 /P
|
|
||||||
|
|
||||||
REM Include directories
|
|
||||||
set IncludeFlags=
|
|
||||||
|
|
||||||
REM Link libraries
|
|
||||||
set LinkLibraries=user32.lib ws2_32.lib
|
|
||||||
|
|
||||||
REM incrmenetal:no, turn incremental builds off
|
|
||||||
REM opt:ref, try to remove functions from libs that are referenced at all
|
|
||||||
set LinkFlags=-incremental:no -opt:ref -machine:x64
|
|
||||||
|
|
||||||
cl %CompileFlags% %CompileEntryPoint% %IncludeFlags% /link %LinkLibraries% %LinkFlags% /nologo /OUT:"%ProjectName%.exe"
|
|
||||||
REM cl /P /c %CompileFlags% %CompileEntryPoint%
|
|
||||||
|
|
||||||
popd
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,3 +0,0 @@
|
|||||||
all: DqnUnitTest.cpp
|
|
||||||
mkdir -p bin
|
|
||||||
g++ -std=c++14 -o bin/DqnUnitTest DqnUnitTest.cpp -lm -Wall -pthread -ggdb
|
|
Loading…
Reference in New Issue
Block a user