/*!**************************************************************************** @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