Write PoC simpler header generator code
This commit is contained in:
parent
cee2573b00
commit
95272e77ee
345
Code/Dqn.h
345
Code/Dqn.h
@ -1,6 +1,7 @@
|
|||||||
#if defined(DQN_IMPLEMENTATION)
|
#if defined(DQN_IMPLEMENTATION)
|
||||||
#define STB_SPRINTF_IMPLEMENTATION
|
#define STB_SPRINTF_IMPLEMENTATION
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// NOTE: stb_sprintf
|
// NOTE: stb_sprintf
|
||||||
@ -595,6 +596,179 @@ struct Dqn_StringBuilder
|
|||||||
isize string_len;
|
isize string_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <size_t N>
|
||||||
|
FILE_SCOPE char *Dqn_StringBuilder__GetWriteBufferAndUpdateUsage(Dqn_StringBuilder<N> *builder, usize size_required)
|
||||||
|
{
|
||||||
|
char *result = builder->fixed_mem + builder->fixed_mem_used;
|
||||||
|
usize space = Dqn_ArrayCount(builder->fixed_mem) - builder->fixed_mem_used;
|
||||||
|
usize *usage = &builder->fixed_mem_used;
|
||||||
|
|
||||||
|
if (builder->last_mem_buf)
|
||||||
|
{
|
||||||
|
Dqn_StringBuilderBuffer *last_buf = builder->last_mem_buf;
|
||||||
|
result = last_buf->mem + last_buf->used;
|
||||||
|
space = last_buf->size - last_buf->used;
|
||||||
|
usage = &last_buf->used;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (space < size_required)
|
||||||
|
{
|
||||||
|
DQN_ASSERT(builder->my_malloc);
|
||||||
|
if (!builder->my_malloc)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// NOTE: Need to allocate new buf
|
||||||
|
usize allocation_size = sizeof(*builder->last_mem_buf) + DQN_MAX(size_required, DQN_STRING_BUILDER_MIN_MEM_BUF_ALLOC_SIZE);
|
||||||
|
void *memory = builder->my_malloc(allocation_size);
|
||||||
|
auto *new_buf = reinterpret_cast<Dqn_StringBuilderBuffer *>(memory);
|
||||||
|
*new_buf = {};
|
||||||
|
new_buf->mem = static_cast<char *>(memory) + sizeof(*new_buf);
|
||||||
|
new_buf->size = allocation_size;
|
||||||
|
result = new_buf->mem;
|
||||||
|
usage = &new_buf->used;
|
||||||
|
|
||||||
|
if (builder->last_mem_buf)
|
||||||
|
{
|
||||||
|
builder->last_mem_buf->next = new_buf;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
builder->next_mem_buf = new_buf;
|
||||||
|
builder->last_mem_buf = new_buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size_required > 0 && *usage > 0 && result[-1] == 0)
|
||||||
|
{
|
||||||
|
// NOTE: Not first time writing into buffer using sprintf, sprintf always writes a null terminator, so we must
|
||||||
|
// subtract one
|
||||||
|
(*usage)--;
|
||||||
|
result--;
|
||||||
|
}
|
||||||
|
|
||||||
|
*usage += size_required;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <usize N>
|
||||||
|
FILE_SCOPE void Dqn_StringBuilder__BuildOutput(Dqn_StringBuilder<N> const *builder, char *dest, isize dest_size)
|
||||||
|
{
|
||||||
|
// NOTE: No data appended to builder, just allocate am empty string. But
|
||||||
|
// always allocate, so we avoid adding making nullptr part of the possible
|
||||||
|
// return values and makes using Dqn_StringBuilder more complex.
|
||||||
|
if (dest_size == 1)
|
||||||
|
{
|
||||||
|
dest[0] = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char const *end = dest + dest_size;
|
||||||
|
char *buf_ptr = dest;
|
||||||
|
|
||||||
|
memcpy(buf_ptr, builder->fixed_mem, builder->fixed_mem_used);
|
||||||
|
buf_ptr += builder->fixed_mem_used;
|
||||||
|
|
||||||
|
isize remaining_space = end - buf_ptr;
|
||||||
|
DQN_ASSERT(remaining_space >= 0);
|
||||||
|
|
||||||
|
for (Dqn_StringBuilderBuffer *string_buf = builder->next_mem_buf;
|
||||||
|
string_buf && remaining_space > 0;
|
||||||
|
string_buf = string_buf->next)
|
||||||
|
{
|
||||||
|
buf_ptr--; // We always copy the null terminator from the buffers, so if we know we have another buffer to copy from, remove the null terminator
|
||||||
|
memcpy(buf_ptr, string_buf->mem, string_buf->used);
|
||||||
|
buf_ptr += string_buf->used;
|
||||||
|
|
||||||
|
remaining_space = end - buf_ptr;
|
||||||
|
DQN_ASSERT(remaining_space >= 0);
|
||||||
|
}
|
||||||
|
DQN_ASSERT(buf_ptr == dest + dest_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// NOTE: String Builder
|
||||||
|
//
|
||||||
|
// -------------------------------------------------------------------------------------------------
|
||||||
|
DQN_HEADER_COPY_PROTOTYPE_AND_COMMENT(
|
||||||
|
"The necessary length to build the string, it returns the length including the null-terminator",
|
||||||
|
template <usize N> isize,
|
||||||
|
Dqn_StringBuilder_BuildLen(Dqn_StringBuilder<N> const *builder))
|
||||||
|
{
|
||||||
|
isize result = builder->string_len + 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DQN_HEADER_COPY_PROTOTYPE(
|
||||||
|
template <usize N> void,
|
||||||
|
Dqn_StringBuilder_BuildInBuffer(Dqn_StringBuilder<N> const *builder, char *dest, usize dest_size))
|
||||||
|
{
|
||||||
|
Dqn_StringBuilder__BuildOutput(builder, dest, dest_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// len: Return the length of the allocated string including the null-terminator
|
||||||
|
template <usize N>
|
||||||
|
char *Dqn_StringBuilder_BuildFromMalloc(Dqn_StringBuilder<N> *builder, isize *len = nullptr)
|
||||||
|
{
|
||||||
|
isize len_w_null_terminator = Dqn_StringBuilder_BuildLen(builder);
|
||||||
|
auto *result = static_cast<char *>(malloc(len_w_null_terminator));
|
||||||
|
if (len) *len = len_w_null_terminator;
|
||||||
|
Dqn_StringBuilder__BuildOutput(builder, result, len_w_null_terminator);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <usize N>
|
||||||
|
char *Dqn_StringBuilder_BuildFromArena(Dqn_StringBuilder<N> *builder, Dqn_MemArena *arena, isize *len = nullptr)
|
||||||
|
{
|
||||||
|
isize len_w_null_terminator = Dqn_StringBuilder_BuildLen(builder);
|
||||||
|
char *result = MEM_ARENA_ALLOC_ARRAY(arena, char, len_w_null_terminator);
|
||||||
|
if (len) *len = len_w_null_terminator;
|
||||||
|
Dqn_StringBuilder__BuildOutput(builder, result, len_w_null_terminator);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <usize N>
|
||||||
|
void Dqn_StringBuilder_VFmtAppend(Dqn_StringBuilder<N> *builder, char const *fmt, va_list va)
|
||||||
|
{
|
||||||
|
if (!fmt) return;
|
||||||
|
isize require = stbsp_vsnprintf(nullptr, 0, fmt, va) + 1;
|
||||||
|
char *buf = Dqn_StringBuilder__GetWriteBufferAndUpdateUsage(builder, require);
|
||||||
|
stbsp_vsnprintf(buf, static_cast<int>(require), fmt, va);
|
||||||
|
builder->string_len += (require - 1); // -1 to exclude null terminator
|
||||||
|
}
|
||||||
|
|
||||||
|
template <usize N>
|
||||||
|
void Dqn_StringBuilder_FmtAppend(Dqn_StringBuilder<N> *builder, char const *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list va;
|
||||||
|
va_start(va, fmt);
|
||||||
|
Dqn_StringBuilder_VFmtAppend(builder, fmt, va);
|
||||||
|
va_end(va);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <usize N>
|
||||||
|
void Dqn_StringBuilder_Append(Dqn_StringBuilder<N> *builder, char const *str, isize len = -1)
|
||||||
|
{
|
||||||
|
if (!str) return;
|
||||||
|
if (len == -1) len = (isize)strlen(str);
|
||||||
|
isize len_w_null_terminator = len + 1;
|
||||||
|
char *buf = Dqn_StringBuilder__GetWriteBufferAndUpdateUsage(builder, len_w_null_terminator);
|
||||||
|
Dqn_MemCopy(buf, str, len);
|
||||||
|
builder->string_len += len;
|
||||||
|
buf[len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <usize N>
|
||||||
|
void Dqn_StringBuilder_AppendChar(Dqn_StringBuilder<N> *builder, char ch)
|
||||||
|
{
|
||||||
|
char *buf = Dqn_StringBuilder__GetWriteBufferAndUpdateUsage(builder, 1 + 1 /*null terminator*/);
|
||||||
|
*buf++ = ch;
|
||||||
|
builder->string_len++;
|
||||||
|
buf[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// NOTE: (Memory) Slices
|
// NOTE: (Memory) Slices
|
||||||
@ -1171,177 +1345,6 @@ Dqn_MemArenaScopedRegion::~Dqn_MemArenaScopedRegion()
|
|||||||
this->arena->curr_mem_block->used = this->curr_mem_block_used;
|
this->arena->curr_mem_block->used = this->curr_mem_block_used;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t N>
|
|
||||||
FILE_SCOPE char *Dqn_StringBuilder__GetWriteBufferAndUpdateUsage(Dqn_StringBuilder<N> *builder, usize size_required)
|
|
||||||
{
|
|
||||||
char *result = builder->fixed_mem + builder->fixed_mem_used;
|
|
||||||
usize space = Dqn_ArrayCount(builder->fixed_mem) - builder->fixed_mem_used;
|
|
||||||
usize *usage = &builder->fixed_mem_used;
|
|
||||||
|
|
||||||
if (builder->last_mem_buf)
|
|
||||||
{
|
|
||||||
Dqn_StringBuilderBuffer *last_buf = builder->last_mem_buf;
|
|
||||||
result = last_buf->mem + last_buf->used;
|
|
||||||
space = last_buf->size - last_buf->used;
|
|
||||||
usage = &last_buf->used;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (space < size_required)
|
|
||||||
{
|
|
||||||
DQN_ASSERT(builder->my_malloc);
|
|
||||||
if (!builder->my_malloc)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
// NOTE: Need to allocate new buf
|
|
||||||
usize allocation_size = sizeof(*builder->last_mem_buf) + DQN_MAX(size_required, DQN_STRING_BUILDER_MIN_MEM_BUF_ALLOC_SIZE);
|
|
||||||
void *memory = builder->my_malloc(allocation_size);
|
|
||||||
auto *new_buf = reinterpret_cast<Dqn_StringBuilderBuffer *>(memory);
|
|
||||||
*new_buf = {};
|
|
||||||
new_buf->mem = static_cast<char *>(memory) + sizeof(*new_buf);
|
|
||||||
new_buf->size = allocation_size;
|
|
||||||
result = new_buf->mem;
|
|
||||||
usage = &new_buf->used;
|
|
||||||
|
|
||||||
if (builder->last_mem_buf)
|
|
||||||
{
|
|
||||||
builder->last_mem_buf->next = new_buf;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
builder->next_mem_buf = new_buf;
|
|
||||||
builder->last_mem_buf = new_buf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size_required > 0 && *usage > 0 && result[-1] == 0)
|
|
||||||
{
|
|
||||||
// NOTE: Not first time writing into buffer using sprintf, sprintf always writes a null terminator, so we must
|
|
||||||
// subtract one
|
|
||||||
(*usage)--;
|
|
||||||
result--;
|
|
||||||
}
|
|
||||||
|
|
||||||
*usage += size_required;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <usize N>
|
|
||||||
FILE_SCOPE void Dqn_StringBuilder__BuildOutput(Dqn_StringBuilder<N> const *builder, char *dest, isize dest_size)
|
|
||||||
{
|
|
||||||
// NOTE: No data appended to builder, just allocate am empty string. But
|
|
||||||
// always allocate, so we avoid adding making nullptr part of the possible
|
|
||||||
// return values and makes using Dqn_StringBuilder more complex.
|
|
||||||
if (dest_size == 1)
|
|
||||||
{
|
|
||||||
dest[0] = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char const *end = dest + dest_size;
|
|
||||||
char *buf_ptr = dest;
|
|
||||||
|
|
||||||
memcpy(buf_ptr, builder->fixed_mem, builder->fixed_mem_used);
|
|
||||||
buf_ptr += builder->fixed_mem_used;
|
|
||||||
|
|
||||||
isize remaining_space = end - buf_ptr;
|
|
||||||
DQN_ASSERT(remaining_space >= 0);
|
|
||||||
|
|
||||||
for (Dqn_StringBuilderBuffer *string_buf = builder->next_mem_buf;
|
|
||||||
string_buf && remaining_space > 0;
|
|
||||||
string_buf = string_buf->next)
|
|
||||||
{
|
|
||||||
buf_ptr--; // We always copy the null terminator from the buffers, so if we know we have another buffer to copy from, remove the null terminator
|
|
||||||
memcpy(buf_ptr, string_buf->mem, string_buf->used);
|
|
||||||
buf_ptr += string_buf->used;
|
|
||||||
|
|
||||||
remaining_space = end - buf_ptr;
|
|
||||||
DQN_ASSERT(remaining_space >= 0);
|
|
||||||
}
|
|
||||||
DQN_ASSERT(buf_ptr == dest + dest_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// NOTE: String Builder
|
|
||||||
//
|
|
||||||
// -------------------------------------------------------------------------------------------------
|
|
||||||
// The necessary length to build the string, it returns the length including the null-terminator
|
|
||||||
template <usize N>
|
|
||||||
isize Dqn_StringBuilder_BuildLen(Dqn_StringBuilder<N> const *builder)
|
|
||||||
{
|
|
||||||
isize result = builder->string_len + 1;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <usize N>
|
|
||||||
void Dqn_StringBuilder_BuildInBuffer(Dqn_StringBuilder<N> const *builder, char *dest, usize dest_size)
|
|
||||||
{
|
|
||||||
Dqn_StringBuilder__BuildOutput(builder, dest, dest_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// len: Return the length of the allocated string including the null-terminator
|
|
||||||
template <usize N>
|
|
||||||
char *Dqn_StringBuilder_BuildFromMalloc(Dqn_StringBuilder<N> *builder, isize *len = nullptr)
|
|
||||||
{
|
|
||||||
isize len_w_null_terminator = Dqn_StringBuilder_BuildLen(builder);
|
|
||||||
auto *result = static_cast<char *>(malloc(len_w_null_terminator));
|
|
||||||
if (len) *len = len_w_null_terminator;
|
|
||||||
Dqn_StringBuilder__BuildOutput(builder, result, len_w_null_terminator);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <usize N>
|
|
||||||
char *Dqn_StringBuilder_BuildFromArena(Dqn_StringBuilder<N> *builder, Dqn_MemArena *arena, isize *len = nullptr)
|
|
||||||
{
|
|
||||||
isize len_w_null_terminator = Dqn_StringBuilder_BuildLen(builder);
|
|
||||||
char *result = MEM_ARENA_ALLOC_ARRAY(arena, char, len_w_null_terminator);
|
|
||||||
if (len) *len = len_w_null_terminator;
|
|
||||||
Dqn_StringBuilder__BuildOutput(builder, result, len_w_null_terminator);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <usize N>
|
|
||||||
void Dqn_StringBuilder_VFmtAppend(Dqn_StringBuilder<N> *builder, char const *fmt, va_list va)
|
|
||||||
{
|
|
||||||
if (!fmt) return;
|
|
||||||
isize require = stbsp_vsnprintf(nullptr, 0, fmt, va) + 1;
|
|
||||||
char *buf = Dqn_StringBuilder__GetWriteBufferAndUpdateUsage(builder, require);
|
|
||||||
stbsp_vsnprintf(buf, static_cast<int>(require), fmt, va);
|
|
||||||
builder->string_len += (require - 1); // -1 to exclude null terminator
|
|
||||||
}
|
|
||||||
|
|
||||||
template <usize N>
|
|
||||||
void Dqn_StringBuilder_FmtAppend(Dqn_StringBuilder<N> *builder, char const *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list va;
|
|
||||||
va_start(va, fmt);
|
|
||||||
Dqn_StringBuilder_VFmtAppend(builder, fmt, va);
|
|
||||||
va_end(va);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <usize N>
|
|
||||||
void Dqn_StringBuilder_Append(Dqn_StringBuilder<N> *builder, char const *str, isize len = -1)
|
|
||||||
{
|
|
||||||
if (!str) return;
|
|
||||||
if (len == -1) len = (isize)strlen(str);
|
|
||||||
isize len_w_null_terminator = len + 1;
|
|
||||||
char *buf = Dqn_StringBuilder__GetWriteBufferAndUpdateUsage(builder, len_w_null_terminator);
|
|
||||||
Dqn_MemCopy(buf, str, len);
|
|
||||||
builder->string_len += len;
|
|
||||||
buf[len] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <usize N>
|
|
||||||
void Dqn_StringBuilder_AppendChar(Dqn_StringBuilder<N> *builder, char ch)
|
|
||||||
{
|
|
||||||
char *buf = Dqn_StringBuilder__GetWriteBufferAndUpdateUsage(builder, 1 + 1 /*null terminator*/);
|
|
||||||
*buf++ = ch;
|
|
||||||
builder->string_len++;
|
|
||||||
buf[1] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// NOTE: Vectors
|
// NOTE: Vectors
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
#define DQN_HEADER_COPY_PROTOTYPE_AND_COMMENT(func_comment, func_return, func_name_and_types) func_return func_name_and_types
|
||||||
|
#define DQN_HEADER_COPY_PROTOTYPE(func_return, func_name_and_types) func_return func_name_and_types
|
||||||
|
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
#include "Dqn.h"
|
#include "Dqn.h"
|
||||||
|
|
||||||
struct TestState
|
struct TestState
|
||||||
@ -417,10 +421,175 @@ FILE_SCOPE void UnitTests()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *Dqn_ReadFileWithArena(Dqn_MemArena *arena, char const *file, isize *file_size)
|
||||||
|
{
|
||||||
|
FILE *file_handle = fopen(file, "rb");
|
||||||
|
fseek(file_handle, 0, SEEK_END);
|
||||||
|
usize file_size_ = ftell(file_handle);
|
||||||
|
rewind(file_handle);
|
||||||
|
|
||||||
|
auto *result = (char *)MEM_ARENA_ALLOC(arena, file_size_ + 1);
|
||||||
|
DQN_ASSERT(result);
|
||||||
|
result[file_size_] = 0;
|
||||||
|
|
||||||
|
if (fread(result, file_size_, 1, file_handle) != 1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to fread: %zu bytes into buffer from file: %s\n", file_size_, file);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_size) *file_size = file_size_;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *Dqn_StrFind(char *buf, char const *find, isize buf_len = -1, isize find_len = -1)
|
||||||
|
{
|
||||||
|
if (find_len == 0) return nullptr;
|
||||||
|
if (buf_len < 0) buf_len = (isize)strlen(buf);
|
||||||
|
if (find_len < 0) find_len = (isize)strlen(find);
|
||||||
|
|
||||||
|
char *buf_end = buf + buf_len;
|
||||||
|
char *result = nullptr;
|
||||||
|
for (; *buf; ++buf)
|
||||||
|
{
|
||||||
|
isize remaining = static_cast<isize>(buf_end - buf);
|
||||||
|
if (remaining < find_len) break;
|
||||||
|
|
||||||
|
if (strncmp(buf, find, find_len) == 0)
|
||||||
|
{
|
||||||
|
result = buf;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *Dqn_StrSkipWhitespace(char *buf)
|
||||||
|
{
|
||||||
|
while (buf && (buf[0] == '\r' || buf[0] == '\t' || buf[0] == '\n' || buf[0] == ' '))
|
||||||
|
buf++;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *ParseFunctionReturnType(char *ptr, isize *len)
|
||||||
|
{
|
||||||
|
char *result = ptr;
|
||||||
|
isize result_len = 0;
|
||||||
|
for (int scope = 0; ptr; ptr++) // NOTE: Parse the function return type
|
||||||
|
{
|
||||||
|
if (ptr[0] == '<' || ptr[0] == '>')
|
||||||
|
{
|
||||||
|
if (ptr[0] == '<') scope++;
|
||||||
|
else scope--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (ptr[0] == ',')
|
||||||
|
{
|
||||||
|
if (scope != 0) continue;
|
||||||
|
result_len = static_cast<int>(ptr - result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len) *len = result_len;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *ParseFunctionNameAndParameters(char *ptr, isize *len)
|
||||||
|
{
|
||||||
|
char *result = ptr;
|
||||||
|
int result_len = 0;
|
||||||
|
for (int scope = 0; ptr; ptr++) // NOTE: Parse the function name and parameters
|
||||||
|
{
|
||||||
|
if (ptr[0] == '(') scope++;
|
||||||
|
else if (ptr[0] == ')')
|
||||||
|
{
|
||||||
|
if (scope-- != 0) continue;
|
||||||
|
result_len = static_cast<int>(ptr - result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*len = result_len;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *ParseFunctionComment(char *ptr, isize *len)
|
||||||
|
{
|
||||||
|
while (ptr[0] != '"') ptr++;
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
char *result = ptr;
|
||||||
|
isize result_len = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
while (ptr[0] != '"')
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
if (ptr[-1] != '\\')
|
||||||
|
{
|
||||||
|
result_len = ptr - result;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*len = result_len;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int main(char *argv[], int argc)
|
int main(char *argv[], int argc)
|
||||||
{
|
{
|
||||||
(void)argv; (void)argc;
|
(void)argv; (void)argc;
|
||||||
UnitTests();
|
UnitTests();
|
||||||
|
|
||||||
|
Dqn_MemArena arena = {};
|
||||||
|
isize buf_size = 0;
|
||||||
|
char *buf = Dqn_ReadFileWithArena(&arena, "../Code/Dqn.h", &buf_size);
|
||||||
|
if (!buf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
char constexpr HEADER_COPY_PROTOTYPE[] = "DQN_HEADER_COPY_PROTOTYPE";
|
||||||
|
char constexpr HEADER_COPY_PROTOTYPE_AND_COMMENT[] = "DQN_HEADER_COPY_PROTOTYPE_AND_COMMENT";
|
||||||
|
|
||||||
|
char *ptr = buf;
|
||||||
|
char *ptr_end = buf + buf_size;
|
||||||
|
isize ptr_len = buf_size;
|
||||||
|
for (char *token = Dqn_StrFind(ptr, HEADER_COPY_PROTOTYPE, ptr_len, Dqn_CharCountI(HEADER_COPY_PROTOTYPE));
|
||||||
|
token;
|
||||||
|
ptr_len = ptr_end - ptr, token = Dqn_StrFind(ptr, HEADER_COPY_PROTOTYPE, ptr_len))
|
||||||
|
{
|
||||||
|
ptr = token;
|
||||||
|
bool prototype_and_comment = (strncmp(token, HEADER_COPY_PROTOTYPE_AND_COMMENT, Dqn_CharCountI(HEADER_COPY_PROTOTYPE_AND_COMMENT)) == 0);
|
||||||
|
if (prototype_and_comment)
|
||||||
|
{
|
||||||
|
ptr += Dqn_CharCount(HEADER_COPY_PROTOTYPE_AND_COMMENT) + 1 /*macro start parenthesis*/;
|
||||||
|
|
||||||
|
isize comment_len = 0;
|
||||||
|
char *comment = ParseFunctionComment(ptr, &comment_len);
|
||||||
|
ptr = comment + comment_len;
|
||||||
|
while (ptr[0] != ',') ptr++;
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
fprintf(stdout, "%.*s", (int)comment_len, comment);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ptr += Dqn_CharCount(HEADER_COPY_PROTOTYPE) + 1 /*macro start parenthesis*/;
|
||||||
|
}
|
||||||
|
|
||||||
|
isize func_type_len = 0;
|
||||||
|
char *func_type = ParseFunctionReturnType(ptr, &func_type_len);
|
||||||
|
|
||||||
|
ptr = func_type + func_type_len + 1; // Ptr is at macro comma, skip the comma
|
||||||
|
ptr = Dqn_StrSkipWhitespace(ptr);
|
||||||
|
isize func_name_len = 0;
|
||||||
|
char *func_name = ParseFunctionNameAndParameters(ptr, &func_name_len);
|
||||||
|
|
||||||
|
ptr = func_name + func_name_len + 1; // Ptr is at macro closing paren, skip the paren
|
||||||
|
fprintf(stdout, "%.*s %.*s", (int)func_type_len, func_type, (int)func_name_len, func_name);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user