/*!****************************************************************************
@file PVRTHash.h
@copyright Copyright (c) Imagination Technologies Limited.
@brief A simple hash class which uses TEA to hash a string or given data
into a 32-bit unsigned int.
******************************************************************************/
#ifndef PVRTHASH_H
#define PVRTHASH_H
#include "PVRTString.h"
#include "PVRTGlobal.h"
/*!****************************************************************************
@class CPVRTHash
@brief A simple hash class which uses TEA to hash a string or other given
data into a 32-bit unsigned int.
******************************************************************************/
class CPVRTHash
{
public:
/*!***************************************************************************
@brief Constructor
*****************************************************************************/
CPVRTHash() : m_uiHash(0) {}
/*!***************************************************************************
@brief Copy Constructor
@param[in] rhs CPVRTHash to copy.
*****************************************************************************/
CPVRTHash(const CPVRTHash& rhs) : m_uiHash(rhs.m_uiHash) {}
/*!***************************************************************************
@brief Overloaded constructor
@param[in] String CPVRTString to create the CPVRTHash with.
*****************************************************************************/
CPVRTHash(const CPVRTString& String) : m_uiHash(0)
{
if(String.length() > 0) // Empty string. Don't set.
{
m_uiHash = MakeHash(String);
}
}
/*!***************************************************************************
@brief Overloaded constructor
@param[in] c_pszString String to create the CPVRTHash with.
*****************************************************************************/
CPVRTHash(const char* c_pszString) : m_uiHash(0)
{
_ASSERT(c_pszString);
if(c_pszString[0] != 0) // Empty string. Don't set.
{
m_uiHash = MakeHash(c_pszString);
}
}
/*!***************************************************************************
@brief Overloaded constructor
@param[in] pData
@param[in] dataSize
@param[in] dataCount
*****************************************************************************/
CPVRTHash(const void* pData, unsigned int dataSize, unsigned int dataCount) : m_uiHash(0)
{
_ASSERT(pData);
_ASSERT(dataSize > 0);
if(dataCount > 0)
{
m_uiHash = MakeHash(pData, dataSize, dataCount);
}
}
/*!***************************************************************************
@brief Overloaded assignment.
@param[in] rhs
@return CPVRTHash &
*****************************************************************************/
CPVRTHash& operator=(const CPVRTHash& rhs)
{
if(this != &rhs)
{
m_uiHash = rhs.m_uiHash;
}
return *this;
}
/*!***************************************************************************
@brief Converts to unsigned int.
@return int
*****************************************************************************/
operator unsigned int() const
{
return m_uiHash;
}
/*!***************************************************************************
@brief Generates a hash from a CPVRTString.
@param[in] String
@return The hash.
*****************************************************************************/
static CPVRTHash MakeHash(const CPVRTString& String)
{
if(String.length() > 0)
return MakeHash(String.c_str(), sizeof(char), (unsigned int) String.length());
return CPVRTHash();
}
/*!***************************************************************************
@brief Generates a hash from a null terminated char array.
@param[in] c_pszString
@return The hash.
*****************************************************************************/
static CPVRTHash MakeHash(const char* c_pszString)
{
_ASSERT(c_pszString);
if(c_pszString[0] == 0)
return CPVRTHash();
const char* pCursor = c_pszString;
while(*pCursor) pCursor++;
return MakeHash(c_pszString, sizeof(char), (unsigned int) (pCursor - c_pszString));
}
/*!***************************************************************************
@brief Generates a hash from generic data. This function uses the
32-bit Fowler/Noll/Vo algorithm which trades efficiency for
slightly increased risk of collisions. This algorithm is
public domain. More information can be found at:
http://www.isthe.com/chongo/tech/comp/fnv/.
@param[in] pData
@param[in] dataSize
@param[in] dataCount
@return unsigned int The hash.
*****************************************************************************/
static CPVRTHash MakeHash(const void* pData, unsigned int dataSize, unsigned int dataCount)
{
_ASSERT(pData);
_ASSERT(dataSize > 0);
#define FNV_PRIME 16777619U
#define FNV_OFFSETBIAS 2166136261U
if(dataCount == 0)
return CPVRTHash();
CPVRTHash pvrHash;
unsigned char* p = (unsigned char*)pData;
pvrHash.m_uiHash = FNV_OFFSETBIAS;
for(unsigned int i = 0; i < dataSize * dataCount; ++i)
{
pvrHash.m_uiHash = (pvrHash.m_uiHash * FNV_PRIME) ^ p[i];
}
return pvrHash;
}
private:
unsigned int m_uiHash; /// The hashed data.
};
#endif