121 lines
3.3 KiB
C
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;
|
|
} |