Здравствуйте,
Для загрузки использую хэш-таблицу с прямой адресацией. Описание
здесь.
Исходник
unsigned long Array<SigT>::Hash2( const unsigned char keyMD5[MD5_DIGEST_LEN] )
{
unsigned int uHash1 = 0, uHash2 = 0;
// evaluate 2 hashes of keyMD5 string:
// uHash1 in the range [ 0 .. TOTAL_CELL_COUNT - 1 ]
// uHash2 in the range [ 1 .. TOTAL_CELL_COUNT - 1 ]
int p = 0;
do
{
uHash1 *= STRIDE_1; uHash1 += ( STRIDE_2 * keyMD5[p] );
uHash2 *= STRIDE_2; uHash2 += ( STRIDE_1 * keyMD5[p] );
} while(++p < MD5_DIGEST_LEN);
uHash1 %= this->TOTAL_CELL_COUNT;
uHash2 %= ( this->TOTAL_CELL_COUNT - 1 ); ++uHash2;
// searching
while( this->bufArIxes[ uHash1 ] != SIGDATA_IDX_BAD )
{
const SigT &hashedSignature = this->signsBuffer[ bufArIxes[ uHash1 ] ];
if( !memcmp( keyMD5, hashedSignature.MD5, MD5_DIGEST_LEN ) )
return bufArIxes[ uHash1 ];
uHash1 += uHash2; uHash1 %= this->TOTAL_CELL_COUNT;
}
// unique item, not found in signature buffer, this->bufArIxes[ uHash1 ] == SIGDATA_IDX_BAD
return uHash1;
}
// fill bufArIxes with indexes in signsBuffer. Hash by MD5 key
template <class SigT>
void Array<SigT>::Make()
{
// order by MD5, exclude duplicates
for( size_t bufIx = 0; bufIx < sigCount; bufIx++ )
{
unsigned uHash1 = Hash2( signsBuffer[bufIx].MD5 ); // SigT *signsBuffer - сплошной массив, хранит MD-5 хэши (сигнатуры)
if( bufArIxes[uHash1] == SIGDATA_IDX_BAD ) // unsigned *bufArIxes - индексы в signsBuffer, вычисленные Hash2
bufArIxes[uHash1] = bufIx;
}
}
template <typename SigT>
SigT *Array<SigT>::HashSearch(unsigned char MD5[MD5_DIGEST_LEN] )
{
unsigned uHash1 = Hash2( MD5 );
if( this->bufArIxes[uHash1] != SIGDATA_IDX_BAD )
return (SigT *)&this->signsBuffer[ bufArIxes[uHash1] ];
return NULL;
}
Алгоритм загрузки сигнатур, еще загружает vector
размеров файлов, для бинарного-поиска по нему. Поиск по этому массиву размеров делается перед вычислением мд5-хэша.
Суммируя: это достойная структура для работы с МД5-хэшами загрузка/поиск? Что можно выбрать лучше И собственно алгоритм формирования хэша из файла (буфера). Вроде GetFileSignature