rtengine/src/runtime/file_tab.c
Kevin Trogant 3254af3786 Make progress towards the new builtin asset compiler
Attempts to compile HLSL shaders (with includes)
2024-01-25 09:45:23 +01:00

134 lines
3.7 KiB
C

#include "file_tab.h"
#include "threading.h"
#include "config.h"
#include "hashing.h"
#define NAME_CAP(cap) ((cap)*128)
typedef struct {
rt_file_id *ids;
unsigned int *name_offsets;
char *names;
unsigned int capacity;
unsigned int name_head;
rt_mutex *mutex;
} rt_file_tab;
static rt_file_tab _file_tab;
RT_CVAR_I(rt_FileTabCapacity, "Maximum number of filetab entries. Default: 1024", 1024);
rt_result InitFileTab(void) {
unsigned int max_files = (unsigned int)rt_FileTabCapacity.i;
_file_tab.ids = calloc(max_files, sizeof(rt_file_id));
if (!_file_tab.ids)
return 1;
_file_tab.name_offsets = calloc(max_files, sizeof(unsigned int));
if (!_file_tab.name_offsets)
return 1;
_file_tab.names = malloc(NAME_CAP(max_files));
if (!_file_tab.names)
return 1;
_file_tab.capacity = max_files;
_file_tab.name_head = 0;
_file_tab.mutex = rtCreateMutex();
return RT_SUCCESS;
}
void ShutdownFileTab(void) {
free(_file_tab.ids);
free(_file_tab.names);
free(_file_tab.name_offsets);
rtDestroyMutex(_file_tab.mutex);
}
RT_DLLEXPORT rt_file_id rtGetFileId(const char *path) {
rt_text_span span;
span.start = path;
span.length = (unsigned int)strlen(path);
return rtGetFileIdFromSpan(span);
}
RT_DLLEXPORT rt_file_id rtGetFileIdFromSpan(rt_text_span path) {
/* Randomly choosen, aka finger smash keyboard */
rt_file_id fid = (rt_file_id)rtHashBytes(path.start, path.length);
if (fid == 0)
fid = ~fid;
return fid;
}
RT_DLLEXPORT rt_file_id rtAddFileFromSpan(rt_text_span path) {
rt_file_id fid = rtGetFileIdFromSpan(path);
if (!rtLockMutex(_file_tab.mutex)) {
rtReportError("fio", "Failed to lock the guard mutex.");
return 0;
}
/* Hash Insert */
unsigned int i = 0;
unsigned int base = (unsigned int)(fid % _file_tab.capacity);
while (i < _file_tab.capacity) {
unsigned int at = (base + i) % _file_tab.capacity;
if (_file_tab.ids[at] == 0) {
/* Insert */
unsigned int slen = (unsigned int)path.length + 1;
if ((_file_tab.name_head + slen) >= NAME_CAP(_file_tab.capacity)) {
/* Out of name storage */
fid = 0;
break;
}
memcpy(_file_tab.names + _file_tab.name_head, path.start, slen);
_file_tab.names[_file_tab.name_head + slen - 1] = '\0';
_file_tab.name_offsets[at] = _file_tab.name_head;
_file_tab.ids[at] = fid;
_file_tab.name_head += slen;
break;
} else if (_file_tab.ids[at] == fid) {
break;
}
++i;
}
/* Out of space */
if (i == _file_tab.capacity)
fid = 0;
rtUnlockMutex(_file_tab.mutex);
return fid;
}
RT_DLLEXPORT rt_file_id rtAddFile(const char *path) {
rt_text_span span;
span.start = path;
span.length = (unsigned int)strlen(path);
return rtAddFileFromSpan(span);
}
RT_DLLEXPORT const char *rtGetFilePath(rt_file_id fid) {
/* Hash Lookup */
if (fid == 0)
return NULL;
if (!rtLockMutex(_file_tab.mutex)) {
rtReportError("fio", "Failed to lock the guard mutex.");
return 0;
}
const char *result = NULL;
unsigned int i = 0;
unsigned int base = (unsigned int)(fid % _file_tab.capacity);
while (i < _file_tab.capacity) {
unsigned int at = (base + i) % _file_tab.capacity;
if (_file_tab.ids[at] == fid) {
result = _file_tab.names + _file_tab.name_offsets[at];
break;
} else if (_file_tab.ids[at] == 0) {
break;
}
++i;
}
rtUnlockMutex(_file_tab.mutex);
return result;
}