134 lines
3.7 KiB
C
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;
|
|
}
|