mirror of
https://github.com/0x221E/ibuild.git
synced 2026-01-18 02:42:20 +00:00
Add: Discovery phase added
Add: StringPool, StringView
This commit is contained in:
2
build.sh
2
build.sh
@@ -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
99
src/discovery.c
Normal 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
45
src/discovery.h
Normal 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
69
src/io.c
Normal 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
28
src/io.h
Normal 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
|
||||||
18
src/main.c
18
src/main.c
@@ -5,22 +5,22 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "discovery.h"
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
Backend b = {NULL, 0};
|
Backend b = {NULL, 0};
|
||||||
backend_initialize(&b);
|
backend_initialize(&b);
|
||||||
|
|
||||||
Arena a;
|
Arena a_sp = arena_create(&b, MEM_ARENA_MAX_CAP);
|
||||||
a.b = &b;
|
StringPool sp = string_pool_create(&a_sp);
|
||||||
|
|
||||||
char* test = (char*)arena_alloc(&a, 6);
|
Arena a_sptemp = arena_create(&b, MEM_ARENA_MAX_CAP);
|
||||||
char* test2 = "Noice";
|
StringPool sp_temp = string_pool_create(&a_sptemp);
|
||||||
|
|
||||||
memcpy(test, test2, 5);
|
Arena a_d = arena_create(&b, 1024*1024*5); // 5MB for Discovery
|
||||||
|
Discovery d = discovery_create(&a_d, &sp);
|
||||||
test[5] = '\0';
|
discovery_discover(&d);
|
||||||
|
|
||||||
printf("That's right. %s\n", test);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
27
src/memory.c
27
src/memory.c
@@ -23,24 +23,33 @@ void backend_free(Backend* b)
|
|||||||
if(munmap(b->mem, b->cap) == -1) DIE("munmap failed!");
|
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);
|
assert(b != NULL);
|
||||||
void* ptr = b->last;
|
void* ptr = b->last;
|
||||||
if(b->len + MEM_ARENA_MAX_CAP >= MEM_BACKEND_MAX_CAP)
|
if(b->len + 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);
|
DIE("Process out of memory, requested %d (current usage %d out of %d).", cap, b->len, b->cap);
|
||||||
b->last = (char*)b->last + (int)MEM_ARENA_MAX_CAP;
|
b->last = (char*)b->last + (int)cap;
|
||||||
b->len += MEM_ARENA_MAX_CAP;
|
b->len += cap;
|
||||||
return ptr;
|
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 != NULL);
|
||||||
assert(a->b != NULL);
|
assert(a->b != NULL);
|
||||||
void* mem = backend_reserve(a->b);
|
void* mem = backend_reserve(a->b, cap);
|
||||||
a->mem = mem;
|
a->mem = mem;
|
||||||
a->cap = MEM_ARENA_MAX_CAP;
|
a->cap = cap;
|
||||||
a->len = 0;
|
a->len = 0;
|
||||||
a->last = a->mem;
|
a->last = a->mem;
|
||||||
a->next = NULL;
|
a->next = NULL;
|
||||||
@@ -51,7 +60,7 @@ void* arena_alloc(Arena* a, size_t len)
|
|||||||
{
|
{
|
||||||
assert(a != NULL);
|
assert(a != NULL);
|
||||||
assert(a->b != 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;
|
int len_aligned = (len + 7) & ~7;
|
||||||
|
|
||||||
|
|||||||
18
src/memory.h
18
src/memory.h
@@ -12,30 +12,34 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
typedef struct
|
struct Backend
|
||||||
{
|
{
|
||||||
void* mem;
|
void* mem;
|
||||||
void* last;
|
void* last;
|
||||||
size_t len;
|
size_t len;
|
||||||
size_t cap;
|
size_t cap;
|
||||||
} Backend;
|
};
|
||||||
|
|
||||||
typedef struct
|
struct Arena
|
||||||
{
|
{
|
||||||
void* mem;
|
void* mem;
|
||||||
void* last;
|
void* last;
|
||||||
size_t len;
|
size_t len;
|
||||||
size_t cap;
|
size_t cap;
|
||||||
void* next;
|
void* next;
|
||||||
Backend* b;
|
struct Backend* b;
|
||||||
} Arena;
|
};
|
||||||
|
|
||||||
|
typedef struct Backend Backend;
|
||||||
|
typedef struct Arena Arena;
|
||||||
|
|
||||||
void backend_initialize(Backend* b);
|
void backend_initialize(Backend* b);
|
||||||
void backend_free(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_reset(Arena* a);
|
||||||
void* arena_alloc(Arena* a, size_t len);
|
void* arena_alloc(Arena* a, size_t len);
|
||||||
|
|
||||||
|
|||||||
46
src/string.c
Normal file
46
src/string.c
Normal 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
32
src/string.h
Normal 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
|
||||||
Reference in New Issue
Block a user