Reference Table¶
An index’s catalogue: which archives it holds, which files are in each of them, and the revisions and checksums of both.
It is read when the cache is opened, so what exists is known long before anything is decompressed.
ReferenceTable.Create¶
function TReferenceTable.Create(id: Integer): TReferenceTable; static;
An empty reference table for index id. TReferenceTable.Read fills it in.
ReferenceTable.Contains¶
function TReferenceTable.Contains(id: Integer): Boolean;
Whether this index holds an archive with the given id.
ReferenceTable flags¶
function TReferenceTable.HasName(): Boolean;
function TReferenceTable.HasWhirlpool(): Boolean;
function TReferenceTable.HasLengths(): Boolean;
function TReferenceTable.HasChecksums(): Boolean;
Which optional fields this table stores for each of its archives.
The table’s Mask is a bitfield that says which of the four are present, and they appear in
that order in the encoded table, so TReferenceTable.Read has to consult these to know
where each following field starts.
ReferenceTable.Read¶
procedure TReferenceTable.Read(const data: TByteArray; var offset: Integer);
Decodes an index’s reference table: which archives it holds, which files are in each of them, and the metadata the table carries about both.
The table is stored column by column rather than archive by archive - every archive’s CRC, then every archive’s revision, and so on - so this makes one pass per field over the whole archive list. Ids themselves are stored as deltas from the previous id, which is why they accumulate and why they always come out ascending.
Version 7 tables write ids as ReadBigSmart because they can exceed 16 bits; earlier ones always use 2 bytes. Anything outside versions 5 to 7 raises.
Opening a cache runs this over every index, which comes to some hundreds of thousands of ids and as many again of per-archive fields, and it is the bulk of what TCacheReader.Load costs. So the id and 32 bit reads are written out here rather than going through ReadBigSmart and Read32Bits - a call per field is worth about a third of the running time at this scale - and the version is branched on once instead of once per id.
ReferenceTable.ArchiveID¶
function TReferenceTable.ArchiveID(const name: String): Integer;
The id of the archive named name, or -1 if this index has no such archive.
The cache does not store names, only their hashes, so this compares against CacheString2Hash of the name.
Example:
id := CacheReader.Indices[ECacheIndex.SPRITES].ReferenceTable.ArchiveID('mapscene');