zoukankan      html  css  js  c++  java
  • 暴雪最快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 }
  • 相关阅读:
    Jersey初始化配置
    Jersey框架简介
    警告: [SetContextPropertiesRule]{Context} Setting property 'source' to 'org.eclipse.jst.jee.server:esignmanage' did not find a matching property.解决
    HIbernate基于外键的查询
    Apache Maven 入门篇(下)
    Apache Maven 入门篇 ( 上 )
    DetachedCriteria用法
    SQL Excel导入到sqlserver表
    轮番图片js
    Js Tab页(二)
  • 原文地址:https://www.cnblogs.com/ylan2009/p/2445101.html
Copyright © 2011-2022 走看看