暴雪最快hash算法源码

中国有句古话"再一再二不能再三再四",看来Blizzard也深得此话的精髓,如果说两个不同的字符串经过一个哈希算法得到的入口点一致有可能,但用三个不同的哈希算法算出的入口点都一致,那几乎可以肯定是不可能的事了,这个几率是1:18889465931478580854784,大概是10的 22.3次方分之一,对一个游戏程序来说足够安全了。

  1 /*********************************StringHash.h*********************************/
  2 
  3 #pragma once
  4 
  5 #define MAXTABLELEN 1024 // 默认哈希索引表大小 
  6 ////////////////////////////////////////////////////////////////////////// 
  7 // 哈希索引表定义 
  8 typedef struct _HASHTABLE
  9 { 
 10   long nHashA; 
 11   long nHashB; 
 12   bool bExists; 
 13 }HASHTABLE, *PHASHTABLE ;
 14 
 15 class StringHash
 16 {
 17 public:
 18   StringHash(const long nTableLength = MAXTABLELEN);
 19   ~StringHash(void);
 20 private: 
 21   unsigned long cryptTable[0x500]; 
 22   unsigned long m_tablelength; // 哈希索引表长度 
 23   HASHTABLE *m_HashIndexTable; 
 24 private:
 25   void InitCryptTable(); // 对哈希索引表预处理 
 26   unsigned long HashString(const string& lpszString, unsigned long dwHashType); // 求取哈希值 
 27 public:
 28   bool Hash(string url);
 29   unsigned long Hashed(string url); // 检测url是否被hash过
 30 };
 31 
 32  
 33 
 34 /*********************************StringHash.cpp*********************************/
 35 
 36 #include "StdAfx.h"
 37 #include "StringHash.h"
 38 
 39 StringHash::StringHash(const long nTableLength /*= MAXTABLELEN*/)
 40 {
 41   InitCryptTable(); 
 42   m_tablelength = nTableLength; 
 43   //初始化hash表
 44   m_HashIndexTable = new HASHTABLE[nTableLength]; 
 45   for ( int i = 0; i < nTableLength; i++ ) 
 46   { 
 47     m_HashIndexTable[i].nHashA = -1; 
 48     m_HashIndexTable[i].nHashB = -1; 
 49     m_HashIndexTable[i].bExists = false; 
 50   } 
 51 }
 52 
 53 StringHash::~StringHash(void)
 54 {
 55   //清理内存
 56   if ( NULL != m_HashIndexTable ) 
 57   { 
 58     delete []m_HashIndexTable; 
 59     m_HashIndexTable = NULL; 
 60     m_tablelength = 0; 
 61   } 
 62 }
 63 
 64 /************************************************************************/
 65 /*函数名:InitCryptTable
 66 /*功 能:对哈希索引表预处理 
 67 /*返回值:无
 68 /************************************************************************/
 69 void StringHash::InitCryptTable() 
 70 { 
 71   unsigned long seed = 0x00100001, index1 = 0, index2 = 0, i;
 72 
 73   for( index1 = 0; index1 < 0x100; index1++ ) 
 74   { 
 75     for( index2 = index1, i = 0; i < 5; i++, index2 += 0x100 ) 
 76     { 
 77       unsigned long temp1, temp2; 
 78       seed = (seed * 125 + 3) % 0x2AAAAB; 
 79       temp1 = (seed & 0xFFFF) << 0x10; 
 80       seed = (seed * 125 + 3) % 0x2AAAAB; 
 81       temp2 = (seed & 0xFFFF); 
 82       cryptTable[index2] = ( temp1 | temp2 ); 
 83     } 
 84   } 
 85 }
 86 
 87 /************************************************************************/
 88 /*函数名:HashString
 89 /*功 能:求取哈希值 
 90 /*返回值:返回hash值
 91 /************************************************************************/
 92 unsigned long StringHash::HashString(const string& lpszString, unsigned long dwHashType) 
 93 { 
 94   unsigned char *key = (unsigned char *)(const_cast<char*>(lpszString.c_str())); 
 95   unsigned long seed1 = 0x7FED7FED, seed2 = 0xEEEEEEEE; 
 96   int ch;
 97 
 98   while(*key != 0) 
 99   { 
100     ch = toupper(*key++);
101 
102     seed1 = cryptTable[(dwHashType << 8) + ch] ^ (seed1 + seed2); 
103     seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3; 
104   } 
105   return seed1; 
106 }
107 
108 /************************************************************************/
109 /*函数名:Hashed
110 /*功 能:检测一个字符串是否被hash过
111 /*返回值:如果存在,返回位置;否则,返回-1
112 /************************************************************************/
113 unsigned long StringHash::Hashed(string lpszString)
114 
115 { 
116   const unsigned long HASH_OFFSET = 0, HASH_A = 1, HASH_B = 2; 
117   //不同的字符串三次hash还会碰撞的几率无限接近于不可能
118   unsigned long nHash = HashString(lpszString, HASH_OFFSET); 
119   unsigned long nHashA = HashString(lpszString, HASH_A); 
120   unsigned long nHashB = HashString(lpszString, HASH_B); 
121   unsigned long nHashStart = nHash % m_tablelength, 
122   nHashPos = nHashStart;
123 
124   while ( m_HashIndexTable[nHashPos].bExists) 
125   { 
126   if (m_HashIndexTable[nHashPos].nHashA == nHashA && m_HashIndexTable[nHashPos].nHashB == nHashB)
127     return nHashPos; 
128   else 
129   nHashPos = (nHashPos + 1) % m_tablelength;
130 
131   if (nHashPos == nHashStart) 
132   break; 
133   }
134 
135   return -1; //没有找到 
136 }
137 
138 /************************************************************************/
139 /*函数名:Hash
140 /*功 能:hash一个字符串 
141 /*返回值:成功,返回true;失败,返回false
142 /************************************************************************/
143 bool StringHash::Hash(string lpszString)
144 { 
145   const unsigned long HASH_OFFSET = 0, HASH_A = 1, HASH_B = 2; 
146   unsigned long nHash = HashString(lpszString, HASH_OFFSET); 
147   unsigned long nHashA = HashString(lpszString, HASH_A); 
148   unsigned long nHashB = HashString(lpszString, HASH_B); 
149   unsigned long nHashStart = nHash % m_tablelength, 
150   nHashPos = nHashStart;
151 
152   while ( m_HashIndexTable[nHashPos].bExists) 
153   { 
154     nHashPos = (nHashPos + 1) % m_tablelength; 
155     if (nHashPos == nHashStart) //一个轮回 
156     { 
157       //hash表中没有空余的位置了,无法完成hash
158       return false; 
159     } 
160   } 
161   m_HashIndexTable[nHashPos].bExists = true; 
162   m_HashIndexTable[nHashPos].nHashA = nHashA; 
163   m_HashIndexTable[nHashPos].nHashB = nHashB;
164 
165   return true; 
166 }
posted on 2012-04-13 01:02  渊蓝之蓝  阅读(6837)  评论(0编辑  收藏  举报