#define VY_DEFINE_UIDTAB_FILE_STRUCTURES #include "uidtab.h" #include "aio.h" #include "xxhash/xxhash.h" #include #include #include #include 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; }