rtengine/src/runtime/uidtab.c
Kevin Trogant 0c89d63716 load runtime asset dependency data
removed init/shutdown functions from headers.
2023-12-21 00:19:48 +01:00

121 lines
3.3 KiB
C

#define VY_DEFINE_UIDTAB_FILE_STRUCTURES
#include "uidtab.h"
#include "aio.h"
#include "xxhash/xxhash.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef struct {
vy_uid *uids;
vy_uid_data *data;
uint32_t slots;
} vy_uidtab;
static vy_uidtab _tab;
vy_result LoadUIDTable(void) {
/* We use stdio here, because we cannot load any asset in parallel to this.
* This is because the uidtab is what tells us which assets exist.
*/
FILE *f = fopen("assets/uidtab.bin", "rb");
if (!f)
return VY_LOAD_FAILED;
vy_uidtab_header header;
if (fread(&header, sizeof(header), 1, f) != 1) {
fclose(f);
return VY_LOAD_FAILED;
}
/* TODO(Kevin): For some reason, the checksum calculation causes
* Memory access errors .
XXH3_state_t *checksum = XXH3_createState();
if (!checksum) {
fclose(f);
return VY_UNKNOWN_ERROR;
}
*/
_tab.slots = vyNextPowerOfTwo32(header.num_entries * 2);
void *mem = malloc((sizeof(vy_uid) + sizeof(vy_uid_data)) * _tab.slots);
if (!mem) {
fclose(f);
_tab.slots = 0;
return VY_BUFFER_ALLOC_FAILED;
}
_tab.uids = mem;
_tab.data = (vy_uid_data *)(_tab.uids + _tab.slots);
memset(mem, 0, (sizeof(vy_uid) + sizeof(vy_uid_data)) * _tab.slots);
uint32_t mod = _tab.slots - 1;
for (uint32_t i = 0; i < header.num_entries; ++i) {
vy_uidtab_entry entry;
if (fread(&entry, sizeof(entry), 1, f) != 1) {
free(mem);
_tab.slots = 0;
fclose(f);
return VY_LOAD_FAILED;
}
//XXH3_64bits_update(checksum, &entry, sizeof(entry));
/* Insert into hashtable */
bool inserted = false;
for (uint32_t j = 0; j < _tab.slots; ++j) {
uint32_t at = (entry.uid + j) & mod;
if (_tab.uids[at] == VY_INVALID_UID) {
_tab.uids[at] = entry.uid;
_tab.data[at].pkg_file = entry.file;
_tab.data[at].size = entry.size;
_tab.data[at].offset = entry.offset;
inserted = true;
break;
}
}
if (!inserted) {
vyReportError("core",
"Failed to insert an entry into the uid table. This should not happen.");
fclose(f);
free(mem);
_tab.slots = 0;
return VY_UNKNOWN_ERROR;
}
}
fclose(f);
/*
XXH64_hash_t checksum_hash = XXH3_64bits_digest(checksum);
XXH64_hash_t file_hash = XXH64_hashFromCanonical(&header.checksum);
XXH3_freeState(checksum);
if (checksum_hash != file_hash) {
vyLog("core",
"WARNING: uidtab.bin checksum does not match calculated checksum of loaded entries.");
}
*/
return VY_SUCCESS;
}
void ReleaseUIDTable(void) {
free(_tab.uids);
_tab.slots = 0;
}
VY_DLLEXPORT const vy_uid_data *vyGetUIDData(vy_uid uid) {
uint32_t mod = _tab.slots - 1;
for (uint32_t j = 0; j < _tab.slots; ++j) {
uint32_t at = (uid + j) & mod;
if (_tab.uids[at] == uid) {
return &_tab.data[at];
} else if (_tab.uids[at] == VY_INVALID_UID) {
break;
}
}
return NULL;
}