#include <cstdio>
#include <cstring>
#include "hashdict.h"
template<class KeyT,class CntT,class ValueT>
EA_COMMON::CHashDict<KeyT,CntT,ValueT>::CHashDict()
{}
template<class KeyT,class CntT,class ValueT>
EA_COMMON::CHashDict<KeyT,CntT,ValueT>::~CHashDict()
{}
template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CHashDict<KeyT,CntT,ValueT>::Create(CntT atHashNum,CntT atCnt)
{
if(atHashNum == 0)
{
return enum_op_error;
}
m_oHashDict.m_tHashNum = atHashNum;
m_oHashDict.m_tNodeNum = 0;
m_oHashDict.m_tCnt = atCnt;
m_oHashDict.m_oHashTbl.m_pHash = new STRU_HASH_DICT_NODE<KeyT,CntT,ValueT>*[m_oHashDict.m_tHashNum];
if(!m_oHashDict.m_oHashTbl.m_pHash)
{
return enum_op_error;
}
memset(m_oHashDict.m_oHashTbl.m_pHash,0,sizeof(STRU_HASH_DICT_NODE<KeyT,CntT,ValueT>*)*m_oHashDict.m_tHashNum);
m_oHashDict.m_pFirstBlock = new STRU_HASH_BLOCK<KeyT,CntT,ValueT>;
if(!m_oHashDict.m_pFirstBlock)
{
delete [] m_oHashDict.m_oHashTbl.m_pHash;
return enum_op_error;
}
memset(m_oHashDict.m_pFirstBlock->m_nHashNode,0,sizeof(STRU_HASH_DICT_NODE<KeyT,CntT,ValueT>)*HASH_DICT_BLOCK_NUM);
m_oHashDict.m_pFirstBlock->m_pNext = 0;
m_oHashDict.m_pCurBlock = m_oHashDict.m_pFirstBlock;
m_oHashDict.m_uiAvailNum = HASH_DICT_BLOCK_NUM;
m_oHashDict.m_pCurNode = m_oHashDict.m_pCurBlock->m_nHashNode;
return enum_op_ok;
}
template<class KeyT,class CntT,class ValueT>
bool EA_COMMON::CHashDict<KeyT,CntT,ValueT>::IsDelNode(STRU_DICT_NODE<KeyT,CntT,ValueT> *aoNode)
{
if(aoNode->m_tKey == 0)
{
return true;
}
return false;
}
template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CHashDict<KeyT,CntT,ValueT>::Save(const char *apPath,const char *apFile)
{
char lstrName[512];
snprintf(lstrName,512,"%s/%s.info",apPath,apFile);
//record info file
FILE *lpFileInfo = fopen(lstrName,"w");
fprintf(lpFileInfo,"hash_base=%u\nnode_num=%u\ncnt=%u\n",m_oHashDict.m_tHashNum,m_oHashDict.m_tNodeNum,m_oHashDict.m_tCnt);
fclose(lpFileInfo);
//record second level
unsigned int *lpInfoCnt = new unsigned int[2*m_oHashDict.m_tHashNum];
memset(lpInfoCnt,0,sizeof(unsigned int) * 2 * m_oHashDict.m_tHashNum);
unsigned int *lpSkipCnt = lpInfoCnt;
unsigned int *lpItemCnt = lpInfoCnt + m_oHashDict.m_tHashNum;
unsigned int luiBlockCnt = 0,luiLoopCnt=0,luiNodeCnt=0;
STRU_DICT_SAVE_NODE<KeyT,ValueT> *lpSave = new STRU_DICT_SAVE_NODE<KeyT,ValueT>[HASH_DICT_BLOCK_NUM];
snprintf(lstrName,512,"%s/%s.data2",apPath,apFile);
FILE *lpFileData2 = fopen(lstrName,"w");
for(unsigned int i = 0;i < m_oHashDict.m_tHashNum;i++)
{
STRU_HASH_DICT_NODE<KeyT,CntT,ValueT> *lpHashNode = m_oHashDict.m_oHashTbl.m_pHash[i];
lpSkipCnt[i] = luiNodeCnt;
while(lpHashNode)
{
if(IsDelNode(lpHashNode))
{
lpHashNode = lpHashNode->m_pNext;
continue;
}
lpSave[luiLoopCnt].m_tKey = lpHashNode->m_tKey;
lpSave[luiLoopCnt].m_tValue = lpHashNode->m_tValue;
lpItemCnt[i]++;
luiLoopCnt++;
luiNodeCnt++;
if(luiLoopCnt >= HASH_DICT_BLOCK_NUM)
{
fwrite(lpSave,sizeof(STRU_DICT_SAVE_NODE<KeyT,ValueT>),luiLoopCnt,lpFileData2);
luiBlockCnt++;
luiLoopCnt=0;
}
lpHashNode = lpHashNode->m_pNext;
}
}
if(luiLoopCnt != 0)
{
fwrite(lpSave,sizeof(STRU_DICT_SAVE_NODE<KeyT,ValueT>),luiLoopCnt,lpFileData2);
}
fclose(lpFileData2);
delete [] lpSave;
if((luiBlockCnt * HASH_DICT_BLOCK_NUM + luiLoopCnt != m_oHashDict.m_tNodeNum) || (luiNodeCnt != m_oHashDict.m_tNodeNum))
{
delete [] lpInfoCnt;
return enum_op_error;
}
snprintf(lstrName,512,"%s/%s.data1",apPath,apFile);
FILE *lpFileData1 = fopen(lstrName,"w");
fwrite(lpSkipCnt,sizeof(unsigned int),m_oHashDict.m_tHashNum,lpFileData1);
fwrite(lpItemCnt,sizeof(unsigned int),m_oHashDict.m_tHashNum,lpFileData1);
fclose(lpFileData1);
delete [] lpInfoCnt;
m_oHashDict.m_tCnt++;
return enum_op_ok;
}
template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CHashDict<KeyT,CntT,ValueT>::Destroy()
{
delete [] m_oHashDict.m_oHashTbl.m_pHash;
STRU_HASH_BLOCK<KeyT,CntT,ValueT> *lpBlock = m_oHashDict.m_pFirstBlock;
STRU_HASH_BLOCK<KeyT,CntT,ValueT> *lpTmp=0;;
while(lpBlock)
{
lpTmp = lpBlock;
lpBlock = lpBlock->m_pNext;
delete [] lpTmp;
}
return enum_op_ok;
}
template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CHashDict<KeyT,CntT,ValueT>::Load(const char *apPath,const char *apFile,CntT atHashNum)
{
char lstrName[512];
snprintf(lstrName,512,"%s/%s.info",apPath,apFile);
FILE *lpFileInfo = fopen(lstrName,"r");
unsigned int luiHashNum = 0,luiNodeNum = 0,luiCnt = 0;
if(fscanf(lpFileInfo,"hash_base=%u\nnode_num=%u\ncnt=%u\n",&luiHashNum,&luiNodeNum,&luiCnt) != 3)
{
fclose(lpFileInfo);
return enum_op_error;
}
fclose(lpFileInfo);
luiHashNum = atHashNum > 0 ? atHashNum:luiHashNum;
if(CHashDict<KeyT,CntT,ValueT>::Create(luiHashNum,0) != enum_op_ok)
{
return enum_op_error;
}
snprintf(lstrName,512,"%s/%s.data2",apPath,apFile);
FILE *lpFileData2 = fopen(lstrName,"r");
STRU_DICT_SAVE_NODE<KeyT,ValueT> loNodeValue[HASH_DICT_BLOCK_NUM];
unsigned int luiNodeCnt = 0,luiNodeRCnt=0;
STRU_HASH_DICT_NODE<KeyT,CntT,ValueT> loDictNode;
while((luiNodeCnt=fread(loNodeValue,sizeof(STRU_DICT_SAVE_NODE<KeyT,ValueT>),HASH_DICT_BLOCK_NUM,lpFileData2)) > 0)
{
for(int i = 0;i<luiNodeCnt;i++)
{
loDictNode.m_tKey = loNodeValue[i].m_tKey;
loDictNode.m_tValue = loNodeValue[i].m_tValue;
loDictNode.m_tCnt = -1;
loDictNode.m_pNext = 0;
Add(loDictNode,true);
}
luiNodeRCnt += luiNodeCnt;
}
fclose(lpFileData2);
if(luiNodeRCnt != luiNodeNum)
{
return enum_op_error;
}
return enum_op_ok;
}
template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CHashDict<KeyT,CntT,ValueT>::Add(STRU_DICT_NODE<KeyT,CntT,ValueT> &aoNode,bool abOverwrite)
{
if(aoNode.m_tKey == 0)
{
return enum_add_invalid;
}
unsigned int luiKey = aoNode.m_tKey % m_oHashDict.m_tHashNum;
STRU_HASH_DICT_NODE<KeyT,CntT,ValueT> *lpNode = m_oHashDict.m_oHashTbl.m_pHash[luiKey];
STRU_HASH_DICT_NODE<KeyT,CntT,ValueT> *lpInsNode=0,*lpAviNode=0;
while(lpNode)
{
if(lpNode->m_tKey == aoNode.m_tKey)
{
lpInsNode = lpNode;
break;
}
if(lpAviNode == 0 && lpNode->m_tKey == 0)
{
lpAviNode = lpNode;
}
lpNode = lpNode->m_pNext;
}
ENUM_HASHDICT_OPTYPE loOpType = enum_op_ok;
if(lpInsNode)
{
if(abOverwrite)
{
lpInsNode->m_tValue = aoNode.m_tValue;
m_oHashDict.m_tCnt++;
loOpType = enum_add_replace;
}
else
{
loOpType = enum_add_exist;
}
}
else
{
if(lpAviNode)
{
lpAviNode->m_tKey = aoNode.m_tKey;
lpAviNode->m_tValue = aoNode.m_tValue;
lpAviNode->m_tCnt = ++m_oHashDict.m_tCnt;
m_oHashDict.m_tNodeNum++;
}
else
{
if(m_oHashDict.m_uiAvailNum == 0)
{
m_oHashDict.m_pCurBlock = new STRU_HASH_BLOCK<KeyT,CntT,ValueT>;
memset(m_oHashDict.m_pCurBlock->m_nHashNode,0,sizeof(STRU_HASH_DICT_NODE<KeyT,CntT,ValueT>) * HASH_DICT_BLOCK_NUM);
m_oHashDict.m_pCurBlock->m_pNext = m_oHashDict.m_pFirstBlock;
m_oHashDict.m_pFirstBlock = m_oHashDict.m_pCurBlock;
m_oHashDict.m_uiAvailNum = HASH_DICT_BLOCK_NUM;
m_oHashDict.m_pCurNode = m_oHashDict.m_pCurBlock->m_nHashNode;
}
lpInsNode = m_oHashDict.m_pCurNode;
lpInsNode->m_pNext = 0;
lpInsNode->m_tKey = aoNode.m_tKey;
lpInsNode->m_tCnt = ++m_oHashDict.m_tCnt;
lpInsNode->m_tValue = aoNode.m_tValue;
if(m_oHashDict.m_oHashTbl.m_pHash[luiKey] == 0)
{
m_oHashDict.m_oHashTbl.m_pHash[luiKey] = lpInsNode;
}
else
{
lpInsNode->m_pNext = m_oHashDict.m_oHashTbl.m_pHash[luiKey];
m_oHashDict.m_oHashTbl.m_pHash[luiKey] = lpInsNode;
}
++m_oHashDict.m_tNodeNum;
--m_oHashDict.m_uiAvailNum;
++m_oHashDict.m_pCurNode;
}
}
return loOpType;
}
template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CHashDict<KeyT,CntT,ValueT>::Del(STRU_DICT_NODE<KeyT,CntT,ValueT> &aoNode)
{
ENUM_HASHDICT_OPTYPE loOpType = enum_op_ok;
unsigned int luiKey = aoNode.m_tKey % m_oHashDict.m_tHashNum;
STRU_HASH_DICT_NODE<KeyT,CntT,ValueT> *lpNode = m_oHashDict.m_oHashTbl.m_pHash[luiKey];
while(lpNode)
{
if(lpNode->m_tKey == aoNode.m_tKey)
{
break;
}
lpNode = lpNode->m_pNext;
}
if(lpNode)
{
lpNode->m_tKey = 0;
++m_oHashDict.m_tCnt;
--m_oHashDict.m_tNodeNum;
}
else
{
loOpType = enum_node_not_exist;
}
return loOpType;
}
template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CHashDict<KeyT,CntT,ValueT>::Modify(STRU_DICT_NODE<KeyT,CntT,ValueT> &aoNode)
{
ENUM_HASHDICT_OPTYPE loOpType = enum_op_ok;
unsigned int luiKey = aoNode.m_tKey % m_oHashDict.m_tHashNum;
STRU_HASH_DICT_NODE<KeyT,CntT,ValueT> *lpNode = m_oHashDict.m_oHashTbl.m_pHash[luiKey];
while(lpNode)
{
if(lpNode->m_tKey == aoNode.m_tKey)
{
break;
}
lpNode = lpNode->m_pNext;
}
if(lpNode)
{
lpNode->m_tValue = aoNode.m_tValue;
lpNode->m_tCnt = ++m_oHashDict.m_tCnt;
}
else
{
loOpType = enum_node_not_exist;
}
return loOpType;
}
template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CHashDict<KeyT,CntT,ValueT>::Find(STRU_DICT_NODE<KeyT,CntT,ValueT> &aoNode)
{
ENUM_HASHDICT_OPTYPE loOpType = enum_op_ok;
unsigned int luiKey = aoNode.m_tKey % m_oHashDict.m_tHashNum;
STRU_HASH_DICT_NODE<KeyT,CntT,ValueT> *lpNode = m_oHashDict.m_oHashTbl.m_pHash[luiKey];
while(lpNode)
{
if(lpNode->m_tKey == aoNode.m_tKey)
{
break;
}
lpNode = lpNode->m_pNext;
}
if(lpNode)
{
aoNode.m_tValue = lpNode->m_tValue;
aoNode.m_tCnt = lpNode->m_tCnt;
}
else
{
loOpType = enum_node_not_exist;
}
return loOpType;
}
template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CHashDict<KeyT,CntT,ValueT>::Adjust()
{
unsigned int luiHashNum = m_oHashDict.m_tNodeNum % 2 ? m_oHashDict.m_tNodeNum/2 + 1:m_oHashDict.m_tNodeNum/2;
STRU_HASH_DICT_NODE<KeyT,CntT,ValueT> **lpHashTbl = new STRU_HASH_DICT_NODE<KeyT,CntT,ValueT>*[luiHashNum];
delete [] m_oHashDict.m_oHashTbl.m_pHash;
m_oHashDict.m_oHashTbl.m_pHash = lpHashTbl;
m_oHashDict.m_tHashNum = luiHashNum;
STRU_HASH_BLOCK<KeyT,CntT,ValueT> *lpNodeBlock = m_oHashDict.m_pFirstBlock;
unsigned int luiLoopCnt = HASH_DICT_BLOCK_NUM;
unsigned int luiKey = 0;
while(lpNodeBlock)
{
if(!lpNodeBlock->m_pNext)
{
luiLoopCnt = HASH_DICT_BLOCK_NUM - m_oHashDict.m_uiAvailNum;
STRU_HASH_DICT_NODE<KeyT,CntT,ValueT> *lpNode = lpNodeBlock->m_nHashNode;
for(int i = 0;i<luiLoopCnt;i++)
{
if(lpNode[i].m_tKey)
{
luiKey = lpNode[i].m_tKey % luiHashNum;
}
else
{
luiKey = (luiKey + 1)%luiHashNum;
}
if(m_oHashDict.m_oHashTbl.m_pHash[luiKey])
{
lpNode[i].m_pNext = m_oHashDict.m_oHashTbl.m_pHash[luiKey];
m_oHashDict.m_oHashTbl.m_pHash[luiKey] = &lpNode[i];
}
else
{
lpNode[i].m_pNext = 0;
m_oHashDict.m_oHashTbl.m_pHash[luiKey] = &lpNode[i];
}
}
}
lpNodeBlock = lpNodeBlock->m_pNext;
}
return enum_op_ok;
}
template<class KeyT,class CntT,class ValueT>
EA_COMMON::CSearchDict<KeyT,CntT,ValueT>::CSearchDict()
{}
template<class KeyT,class CntT,class ValueT>
EA_COMMON::CSearchDict<KeyT,CntT,ValueT>::~CSearchDict()
{}
template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CSearchDict<KeyT,CntT,ValueT>::Load(const char *apPath,const char *apFile)
{
char lstrName[512];
snprintf(lstrName,512,"%s/%s.info",apPath,apFile);
FILE *lpFileInfo = fopen(lstrName,"r");
unsigned int luiHashNum = 0,luiNodeNum = 0,luiCurCnt=0;
if(fscanf(lpFileInfo,"hash_base=%u\nnode_num=%u\ncnt=%u\n",&luiHashNum,&luiNodeNum,&luiCurCnt) != 3)
{
fclose(lpFileInfo);
return enum_op_error;
}
fclose(lpFileInfo);
m_oSearchDict.m_tHashNum = luiHashNum;
m_oSearchDict.m_tNodeNum = luiNodeNum;
m_oSearchDict.m_ptHashSkip = new CntT[luiHashNum];
m_oSearchDict.m_ptItemNum = new CntT[luiHashNum];
FILE *lpFileData1 = 0,*lpFileData2 = 0;
snprintf(lstrName,512,"%s/%s.data1",apPath,apFile);
lpFileData1 = fopen(lstrName,"r");
if(fread(m_oSearchDict.m_ptHashSkip,sizeof(CntT),luiHashNum,lpFileData1) != luiHashNum)
{
fclose(lpFileData1);
delete [] m_oSearchDict.m_ptHashSkip;
delete [] m_oSearchDict.m_ptItemNum;
return enum_op_error;
}
if(fread(m_oSearchDict.m_ptItemNum,sizeof(CntT),luiHashNum,lpFileData1) != luiHashNum)
{
fclose(lpFileData1);
delete [] m_oSearchDict.m_ptHashSkip;
delete [] m_oSearchDict.m_ptItemNum;
return enum_op_error;
}
fclose(lpFileData1);
snprintf(lstrName,512,"%s/%s.data2",apPath,apFile);
lpFileData2 = fopen(lstrName,"r");
m_oSearchDict.m_pNodes = new STRU_DICT_SAVE_NODE<KeyT,ValueT>[luiNodeNum];
if(fread(m_oSearchDict.m_pNodes,sizeof(STRU_DICT_SAVE_NODE<KeyT,ValueT>),luiNodeNum,lpFileData2) != luiNodeNum)
{
delete [] m_oSearchDict.m_ptHashSkip;
delete [] m_oSearchDict.m_ptItemNum;
delete [] m_oSearchDict.m_pNodes;
return enum_op_error;
}
fclose(lpFileData2);
return enum_op_ok;
}
template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CSearchDict<KeyT,CntT,ValueT>::Destroy()
{
delete [] m_oSearchDict.m_ptHashSkip;
delete [] m_oSearchDict.m_ptItemNum;
delete [] m_oSearchDict.m_pNodes;
return enum_op_error;
}
template<class KeyT,class CntT,class ValueT>
EA_COMMON::ENUM_HASHDICT_OPTYPE EA_COMMON::CSearchDict<KeyT,CntT,ValueT>::Find(STRU_DICT_SAVE_NODE<KeyT,ValueT> &aoNode)
{
unsigned int luiKey = aoNode.m_tKey % m_oSearchDict.m_tHashNum;
STRU_DICT_SAVE_NODE<KeyT,ValueT> *lpNode = 0;
for(unsigned int i = 0;i < m_oSearchDict.m_ptItemNum[luiKey];i++)
{
int liIndex = m_oSearchDict.m_ptHashSkip[luiKey] + i;
lpNode = &m_oSearchDict.m_pNodes[liIndex];
if(lpNode->m_tKey == aoNode.m_tKey)
{
aoNode.m_tValue = lpNode->m_tValue;
return enum_op_ok;
}
}
return enum_op_error;
}