EAHash is a family of hashing functions. There are string hashes, binary hashes, cryptographic hashes, checksums, and CRCs; each has its applications. If you are looking for hash tables, they are present in the EASTL library, which provides a suite of hash table containers.
Hash functions are functions which take input data and produce a hash value, which is usually an integer or some short fixed-size data. This is useful for implementing hash-tables, cryptographic security, and error checking. A good hash function produces a unique hash value for the large majority of unique input. A cryptographic hash goes further and has a level of mathematical security built into it so that it is difficult or impossible to guess the original input from a given hash value output. You can read more about hash functions at Wikipedia at http://en.wikipedia.org/wiki/Hash_function.
EAStdC provides the following hash submodules:
EAHash provides these hashes in forms that read from blocks in memory.
String hashes are probably the most common hashes used in game development. There is a particular interest in having string hashes that are fast but reasonably collision-free in practice. Cryptographical security is not of interest to string hashes. However, being able to do a case-insensitive hash often is.
String hashes are different from binary hashes in that they hash characters and not bytes. Thus, the hash for the 8 bit string "hello" will be the same as the hash for a 16 bit char string L"hello" even though the latter uses twice as many bytes and would hash to a different value via a binary hash function. String hashes are also different in that they sometimes have the option to act with case insensitivity. In such cases the hash for "Hello" is the same as for "hello".
The primary string hash provided by EAHashString is the FNV1 hash, though the DJB2 hash is also provided. The FNV1 hash appears to be the best string hash for most users' needs, as it is very fast and yet generates surprisingly few collisions with typical text input.
The FNV1 hash functions provided by EAHashString are:
uint32_t FNV1 (const void* pData, size_t nLength, uint32_t nInitialValue = kFNV1InitialValue);
uint32_t FNV1_String8 (const char8_t* pData, uint32_t nInitialValue = kFNV1InitialValue, CharCase charCase = kCharCaseAny);
uint32_t FNV1_String16(const char16_t* pData, uint32_t nInitialValue = kFNV1InitialValue, CharCase charCase = kCharCaseAny);
Example usage:
const char16_t fileName[IO::kMaxFileNameLength];
const uint32_t fileNameHash = FNV1_string16(filePath, kFNV1InitialValue, kCharCaseLower);
printf("Case-insensitive hash for file %ls is 0x%08x.\n", filePath, fileNameHash);
A CRCs (cyclical redundancy check) is a form of hash which is good at detecting uniqueness of input yet is fairly simple to implement. CRCs are most often used to detect errors during data transmission in a non-security-sensitive environment. If a recieved file has a different checksum than the original file, there was a transmission error. A cryptographic hash could also be used to do what a CRC hash does, but it would have more overhead, particularly when implemented in hardware.
There are many standards and variations of CRC algorithms, and trying to understand them can be a tedious frustrating experience. EAHashCRC provides a single CRC implementation for each of various bit sizes and doesn't try to cater to the myriad of variations that exist. Unless you need a CRC function which interacts with some specific third party CRC convention, the version in EAHashCRC is probably fine. You can read more about CRCs on Wikipedia at http://en.wikipedia.org/wiki/Cyclic_redundancy_check.
The CRC functions have a 'bFinalize' parameter, which enables the inversion of the bits upon completion. This is a common practice in standardized CRC calculations. When doing iterative CRC calculations, you need to make sure you set bFinalize to false for all but the last call. See the example code below.
EAHashCRC provides the following block functions:
uint16_t CRC16(const void* pData, size_t nLength, uint16_t nInitialValue = kCRC16InitialValue, bool bFinalize = true); uint32_t CRC24(const void* pData, size_t nLength, uint32_t nInitialValue = kCRC24InitialValue, bool bFinalize = true); uint32_t CRC32(const void* pData, size_t nLength, uint32_t nInitialValue = kCRC32InitialValue, bool bFinalize = true); uint64_t CRC64(const void* pData, size_t nLength, uint64_t nInitialValue = kCRC64InitialValue, bool bFinalize = true); uint32_t CRC32Reverse(const void* pData, size_t nLength, uint32_t nInitialValue = kCRC32InitialValue, bool bFinalize = true);
Example basic usage:
char* fileData; size_t fileLength; ReadFile(pData, fileLength); uint16_t crc = CRC16(fileData, fileLength);
Example usage of incremental CRC calculation, which is useful when you don't have the data in a single block:
char pDataArray[1000];
uint64_t crc = kCRC64InitialValue;
for(int i = 0; i < 10; i++) // Calculate the CRC for the data array incrementally.
crc = EA::Hash::CRC64(pDataArray[i * 100], 100, crc, i == 9);