Add: Discovery phase added

Add: StringPool, StringView
This commit is contained in:
0x221E
2026-01-16 16:44:30 +01:00
parent 58d405b397
commit 3829703102
10 changed files with 360 additions and 28 deletions

View File

@@ -1 +1 @@
gcc -o ibuild src/main.c src/memory.c src/utils.c -fsanitize=address -g -DDEBUG
gcc -o ibuild src/main.c src/memory.c src/utils.c src/string.c src/discovery.c src/io.c -fsanitize=address -g -DDEBUG

99
src/discovery.c Normal file
View File

@@ -0,0 +1,99 @@
#include "discovery.h"
#include "memory.h"
#include "string.h"
#include "io.h"
#include "utils.h"
#include <assert.h>
#include <string.h>
Discovery discovery_create(Arena* a, StringPool* sp)
{
assert(a != NULL);
assert(sp != NULL);
Discovery d;
d.a = a;
d.sp = sp;
d.files = d.a->mem;
d.c_files = NULL;
d.h_files = NULL;
d.cpp_files = NULL;
d.file_count = 0;
d.c_count = 0;
d.h_count = 0;
d.cpp_count = 0;
LOG_DEBUG("Discovery creation completed with arena with block @ %p, with capacity %d.", a->mem, a->cap);
return d;
}
void discovery_cleanup(Discovery* d)
{
}
void discovery_discover(Discovery* d)
{
assert(d != NULL);
DirOpContext doc;
doc.a_f = d->a;
doc.sp = d->sp;
StringView path = SV(d->sp, ".");
size_t count = dir_get_recursive(&doc, &path);
d->file_count = count;
LOG_DEBUG("Discovered %d files.", count);
StringView c_ext = SV(d->sp, ".c");
ExtDiscoveryResult c_res = discovery_discover_ext(d, d->a, &c_ext);
if(c_res.mem != NULL)
{
LOG_DEBUG("Discovered %d C files.", c_res.len);
d->c_count = c_res.len;
d->c_files = c_res.mem;
}
StringView h_ext = SV(d->sp, ".h");
ExtDiscoveryResult h_res = discovery_discover_ext(d, d->a, &h_ext);
if(h_res.mem != NULL)
{
LOG_DEBUG("Discovered %d H files.", h_res.len);
d->h_count = h_res.len;
d->h_files = h_res.mem;
}
}
// TODO: Make the search logic faster, or at least search all of the wanted extension at once, uniformly.
ExtDiscoveryResult discovery_discover_ext(Discovery* d, Arena* a, StringView* ext)
{
assert(d != NULL);
assert(a != NULL);
assert(ext != NULL);
assert(ext->buf != NULL);
assert(ext->len > 0);
void* res = a->last;
size_t count = 0;
for(size_t i = 0; i < d->file_count; i++)
{
char* ptr = strrchr(d->files[i].path.buf, '.');
if(ptr == NULL)
continue;
if(strcmp(ptr, ext->buf) == 0)
{
DirEntry** entry = (DirEntry**)arena_alloc(a, sizeof(DirEntry*));
*entry = &d->files[i];
count++;
}
}
if(count > 0) return (ExtDiscoveryResult){.mem = res, .len = count};
return (ExtDiscoveryResult){.mem = NULL, .len = 0};
}

45
src/discovery.h Normal file
View File

@@ -0,0 +1,45 @@
#ifndef DISCOVERY_H
#define DISCOVERY_H
typedef struct Arena Arena;
typedef struct StringPool StringPool;
typedef struct StringView StringView;
typedef struct DirEntry DirEntry;
#include <stddef.h>
struct Discovery
{
// Memory
Arena* a;
StringPool* sp;
StringPool* sp_temp;
// Results
DirEntry* files;
DirEntry** c_files;
DirEntry** h_files;
DirEntry** cpp_files;
size_t file_count;
size_t c_count;
size_t h_count;
size_t cpp_count;
};
struct ExtDiscoveryResult
{
void* mem;
size_t len;
};
typedef struct Discovery Discovery;
typedef struct ExtDiscoveryResult ExtDiscoveryResult;
Discovery discovery_create(Arena* a, StringPool* sp);
void discovery_cleanup(Discovery* d);
void discovery_discover(Discovery* d);
ExtDiscoveryResult discovery_discover_ext(Discovery* d, Arena* a, StringView* ext);
#endif

69
src/io.c Normal file
View File

@@ -0,0 +1,69 @@
#include "io.h"
#include "utils.h"
#include "memory.h"
#include <errno.h>
#include <assert.h>
#include <dirent.h>
#include <string.h>
StringView path_concat_ss(StringPool *sp, StringView* a, StringView* b)
{
if(a == NULL) DIE("a must be a valid string!");
if(b == NULL) DIE("b must be a valid string!");
if(a->len <= 0 || b->len <= 0) DIE("a and b must not be empty! (a:%d, b:%d)", a->len, b->len);
if(a->buf[a->len - 1] == '/')
return string_createcat_ss(sp, a, b);
StringView slash = (StringView){.buf = "/", .len = 1};
StringView ts = string_createcat_ss(sp, a, &slash);
return string_createcat_ss(sp, &ts, b);
}
// Utilize DFS for recursive directory search.
size_t dir_get_recursive(DirOpContext* doc, StringView* p)
{
assert(doc != NULL);
if(p == NULL) DIE("p cannot be null!");
if(p->len <= 0) DIE("p must not be empty!");
DIR* d = opendir(p->buf);
if(d == NULL) DIE("could not open directory!");
size_t count = 0;
while(d)
{
errno = 0;
struct dirent* de = readdir(d);
if(de == NULL && errno != 0) DIE("failed to read directory: \"%s\"", p);
if(de == NULL) break;
if(de->d_type != DT_DIR && de->d_type != DT_REG) continue;
if(strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0 || strcmp(de->d_name, ".git") == 0) continue;
StringView res = (StringView){.buf = de->d_name, strlen(de->d_name)};
StringView fpath = path_concat_ss(doc->sp, p, &res);
DirEntry* file = (DirEntry*)arena_alloc(doc->a_f, sizeof(DirEntry));
file->path = fpath;
file->type = de->d_type;
count++;
switch(de->d_type)
{
case DT_REG:
LOG_DEBUG("Added entry: \"%.*s\" to memory location @ %p.", fpath.len, fpath.buf, file);
break;
case DT_DIR:
LOG_DEBUG("Added directory directory entry \"%.*s\" to memory location @ %p. Entering directory...", fpath.len, fpath.buf, file);
count += dir_get_recursive(doc, &fpath);
break;
default:
continue;
}
}
LOG_DEBUG("Directory complete: %s", p->buf);
closedir(d);
return count;
}

28
src/io.h Normal file
View File

@@ -0,0 +1,28 @@
#ifndef IO_H
#define IO_H
#include "string.h"
typedef struct Arena Arena;
struct DirEntry
{
StringView path;
unsigned char type;
};
struct DirOpContext
{
Arena* a_f;
StringPool* sp;
};
typedef struct DirEntry DirEntry;
typedef struct DirOpContext DirOpContext;
// a should not contain a trailing slash
StringView path_concat_ss(StringPool* sp, StringView* a, StringView* b);
size_t dir_get_recursive(DirOpContext* doc, StringView* p);
#endif

View File

@@ -5,22 +5,22 @@
#include <stdlib.h>
#include "utils.h"
#include "string.h"
#include "discovery.h"
int main(void) {
Backend b = {NULL, 0};
backend_initialize(&b);
Arena a_sp = arena_create(&b, MEM_ARENA_MAX_CAP);
StringPool sp = string_pool_create(&a_sp);
Arena a_sptemp = arena_create(&b, MEM_ARENA_MAX_CAP);
StringPool sp_temp = string_pool_create(&a_sptemp);
Arena a;
a.b = &b;
char* test = (char*)arena_alloc(&a, 6);
char* test2 = "Noice";
memcpy(test, test2, 5);
test[5] = '\0';
Arena a_d = arena_create(&b, 1024*1024*5); // 5MB for Discovery
Discovery d = discovery_create(&a_d, &sp);
discovery_discover(&d);
printf("That's right. %s\n", test);
return 0;
}

View File

@@ -23,24 +23,33 @@ void backend_free(Backend* b)
if(munmap(b->mem, b->cap) == -1) DIE("munmap failed!");
}
void* backend_reserve(Backend* b)
void* backend_reserve(Backend* b, size_t cap)
{
assert(b != NULL);
void* ptr = b->last;
if(b->len + MEM_ARENA_MAX_CAP >= MEM_BACKEND_MAX_CAP)
DIE("Out of memory, requested %d (current usage %d out of %d).", MEM_ARENA_MAX_CAP, b->len, b->cap);
b->last = (char*)b->last + (int)MEM_ARENA_MAX_CAP;
b->len += MEM_ARENA_MAX_CAP;
if(b->len + cap >= MEM_BACKEND_MAX_CAP)
DIE("Process out of memory, requested %d (current usage %d out of %d).", cap, b->len, b->cap);
b->last = (char*)b->last + (int)cap;
b->len += cap;
return ptr;
}
void arena_init(Arena* a)
Arena arena_create(Backend* b, size_t cap)
{
assert(b != NULL);
Arena a;
a.b = b;
arena_init(&a, cap);
return a;
}
void arena_init(Arena* a, size_t cap)
{
assert(a != NULL);
assert(a->b != NULL);
void* mem = backend_reserve(a->b);
void* mem = backend_reserve(a->b, cap);
a->mem = mem;
a->cap = MEM_ARENA_MAX_CAP;
a->cap = cap;
a->len = 0;
a->last = a->mem;
a->next = NULL;
@@ -51,7 +60,7 @@ void* arena_alloc(Arena* a, size_t len)
{
assert(a != NULL);
assert(a->b != NULL);
if(a->mem == NULL || a->last == NULL) arena_init(a);
if(a->mem == NULL || a->last == NULL) arena_init(a, MEM_ARENA_MAX_CAP);
int len_aligned = (len + 7) & ~7;

View File

@@ -12,30 +12,34 @@
#include <stddef.h>
typedef struct
struct Backend
{
void* mem;
void* last;
size_t len;
size_t cap;
} Backend;
};
typedef struct
struct Arena
{
void* mem;
void* last;
size_t len;
size_t cap;
void* next;
Backend* b;
} Arena;
struct Backend* b;
};
typedef struct Backend Backend;
typedef struct Arena Arena;
void backend_initialize(Backend* b);
void backend_free(Backend* b);
void* backend_reserve(Backend* b);
void* backend_reserve(Backend* b, size_t cap);
void arena_init(Arena* a);
Arena arena_create(Backend* b, size_t cap);
void arena_init(Arena* a, size_t cap);
//void arena_reset(Arena* a);
void* arena_alloc(Arena* a, size_t len);

46
src/string.c Normal file
View File

@@ -0,0 +1,46 @@
#include "string.h"
#include <assert.h>
#include "utils.h"
#include <string.h>
StringPool string_pool_create(Arena* a)
{
assert(a != NULL);
assert(a->mem != NULL);
StringPool sp;
sp.a = a;
LOG_DEBUG("String pool initialized on arena with block @ %p.", sp.a->mem);
return sp;
}
void string_pool_reset(StringPool* ps)
{
// arena_reset(&ps->a);
}
StringView string_create(StringPool* sp, const char* s, size_t len)
{
assert(sp != NULL);
if(s == NULL) DIE("Invalid string supplied!");
char* buf = (char*)arena_alloc(sp->a, len + 1);
memcpy(buf, s, len);
buf[len] = '\0';
LOG_DEBUG("A string was created @ %p with data: \"%s\"", buf, buf);
return (StringView){.buf = buf, .len=len};
}
StringView string_createcat_ss(StringPool* sp, StringView* a, StringView* b)
{
if(a == NULL) DIE("a must be a valid C-style string!");
if(b == NULL) DIE("b must be a valid C-style string!");
if(a->len <= 0 || b->len <= 0) DIE("size must be valid! a: %d, b: %d", a->len, b->len);
size_t len = a->len + b->len;
char* buf = (char*)arena_alloc(sp->a, len + 1);
memcpy(buf, a->buf, a->len);
char* bbuf_off = buf + a->len;
memcpy(bbuf_off, b->buf, b->len);
buf[len] = '\0';
LOG_DEBUG("A string was created @ %p with data: \"%s\"", buf, buf);
return (StringView){.buf = buf, .len = len};
}

32
src/string.h Normal file
View File

@@ -0,0 +1,32 @@
#ifndef STRING_H
#define STRING_H
#include "memory.h"
#include <stddef.h>
#define SV(sp, s) string_create(sp, s, sizeof(s) - 1)
struct StringPool
{
Arena* a;
};
struct StringView
{
const char* buf;
size_t len;
};
typedef struct StringPool StringPool;
typedef struct StringView StringView;
StringPool string_pool_create(Arena* a);
void string_pool_reset(StringPool* sp);
StringView string_create(StringPool* sp, const char* s, size_t len);
// Ensure that lengths do not contain null term
StringView string_createcat_ss(StringPool* sp, StringView* a, StringView* b);
#endif