This section of the archives stores flipcode's complete Developer Toolbox collection,
featuring a variety of mini-articles and source code contributions from our readers.

Hash Table
Submitted by

Hello Coders at flipcode! I've recently delved into my stockpile of code
searching for a method of quickly and easily accessing information. There are
also quick methods of saving this hash table, but if you really want to make a
game worthy hash table, check out the MoPaQ format (MPQ, as in Diablo,
Starcraft, etc.) at http://www.campaigncreations.com/starcraft/inside_mopaq/
I'm using the table for a complete range of uses, from registration with a
server object (simply add the hash entry) to variations of a heirachy. (I
couldn't use STD with the heirachy implementation as well as a few others)
The method that the hash values are created is with purpose, so don't believe
that I enjoy being cryptic. Anyway, the top 16 bits of the 32 bit hash is the
'type' number. This is a unique ID generated as a verification number. The
bottom 16 bits is the actual hash; in the hash table, it is used to quickly
reference retrieve the position in the table. Once the position in the table is
found, the table progresses through a linked list, consisting of all entries
with the same lower 16 bits, searching for the entry that matches the top 16
bits.
Enjoy! Comments, Code Corrections, Weather Reports, etc. Welcome!
Chris Pergrossi

//
// I made this hash function after several months of looking around
// and I must say, the greatest resource I found was looking at the
// MPQ format used by Blizzard. The resource can be found at
// http://www.campaigncreations.com/starcraft/inside_mopaq///
// This function was made to be case - insensitive, just cause I hate
// having to worry about caps or not, so if you want it case - sensitive,
// replace the line: ch = toupper (*pKey++) with ch = *pKey++
//
long toHash (char* pString)
{
long nSeed1, nSeed2;

//
// I use this when I use the table for pointers to memory
// this will return the first entry in the table (not the
// first slot, but the first actual entry) and it's paired
// hash value
//
bool getHash (long* nHash, T* entry)
{
for (int i = 0; i < MAX_HASH_ENTRIES; i++)
if (pTable[i])
{
*entry = pTable[i]->entry;
*nHash = i | (pTable[i]->type << 16);
returntrue;
}

returnfalse;
}

//
// this will return the next hash in the list, given
// an original hash value (again, I use this for freeing memory)
//
// Watch Out: It searches for the previous entry to give the next entry.
// If you erase the previously returned entry (removeHash ()) you must
// use getHash () to return another entry, because getNext () won't find
// anymore and return false
//
bool getNext (long nHash, long* nNext, T* entry)
{
long nPos, nType;