mirror of https://github.com/F-Stack/f-stack.git
291 lines
6.6 KiB
C
291 lines
6.6 KiB
C
|
|
|||
|
/**
|
|||
|
* Tencent is pleased to support the open source community by making MSEC available.
|
|||
|
*
|
|||
|
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
|
|||
|
*
|
|||
|
* Licensed under the GNU General Public License, Version 2.0 (the "License");
|
|||
|
* you may not use this file except in compliance with the License. You may
|
|||
|
* obtain a copy of the License at
|
|||
|
*
|
|||
|
* https://opensource.org/licenses/GPL-2.0
|
|||
|
*
|
|||
|
* Unless required by applicable law or agreed to in writing, software distributed under the
|
|||
|
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
|||
|
* either express or implied. See the License for the specific language governing permissions
|
|||
|
* and limitations under the License.
|
|||
|
*/
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* @filename hash_list.h
|
|||
|
* @info <EFBFBD><EFBFBD><EFBFBD><EFBFBD>hash<EFBFBD><EFBFBD>, <EFBFBD><EFBFBD><EFBFBD><EFBFBD>hash<EFBFBD>洢ʵ<EFBFBD><EFBFBD>; <EFBFBD>̳<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>hashӳ<EFBFBD><EFBFBD>, ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>ص<EFBFBD>
|
|||
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD>, <EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>, <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ỵ<EFBFBD><EFBFBD>
|
|||
|
* @time 2013-06-11
|
|||
|
*/
|
|||
|
|
|||
|
#ifndef __HASH_LIST_FILE__
|
|||
|
#define __HASH_LIST_FILE__
|
|||
|
|
|||
|
#include <stdlib.h>
|
|||
|
#include <math.h>
|
|||
|
#include <string.h>
|
|||
|
#include <stdint.h>
|
|||
|
#include <assert.h>
|
|||
|
|
|||
|
namespace NS_MICRO_THREAD {
|
|||
|
|
|||
|
/**
|
|||
|
* @brief Hash<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>صĻ<EFBFBD><EFBFBD><EFBFBD>, <EFBFBD>̳и<EFBFBD>Ԫ<EFBFBD>ؼ<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ
|
|||
|
*/
|
|||
|
class HashKey
|
|||
|
{
|
|||
|
private:
|
|||
|
HashKey* _next_entry; ///< <20><><EFBFBD><EFBFBD>hash<73><68><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA>
|
|||
|
uint32_t _hash_value; ///< hash value<75><65>Ϣ, <20><>Լ<EFBFBD>Ƚϵ<C8BD>ʱ<EFBFBD><CAB1>
|
|||
|
void* _data_ptr; ///< hash data<74><61><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>, <20><>key - value <20>ۺϴ洢
|
|||
|
|
|||
|
public:
|
|||
|
|
|||
|
friend class HashList; ///< hash<73><68><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD>nextָ<74><D6B8>
|
|||
|
|
|||
|
/**
|
|||
|
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
*/
|
|||
|
HashKey():_next_entry(NULL), _hash_value(0), _data_ptr(NULL) {};
|
|||
|
virtual ~HashKey(){};
|
|||
|
|
|||
|
/**
|
|||
|
* @brief <EFBFBD>ڵ<EFBFBD>Ԫ<EFBFBD>ص<EFBFBD>hash<EFBFBD>㷨, <EFBFBD><EFBFBD>ȡkey<EFBFBD><EFBFBD>hashֵ
|
|||
|
* @return <EFBFBD>ڵ<EFBFBD>Ԫ<EFBFBD>ص<EFBFBD>hashֵ
|
|||
|
*/
|
|||
|
virtual uint32_t HashValue() = 0;
|
|||
|
|
|||
|
/**
|
|||
|
* @brief <EFBFBD>ڵ<EFBFBD>Ԫ<EFBFBD>ص<EFBFBD>cmp<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, ͬһͰID<EFBFBD><EFBFBD>, <EFBFBD><EFBFBD>key<EFBFBD>Ƚ<EFBFBD>
|
|||
|
* @return <EFBFBD>ڵ<EFBFBD>Ԫ<EFBFBD>ص<EFBFBD>hashֵ
|
|||
|
*/
|
|||
|
virtual int HashCmp(HashKey* rhs) = 0;
|
|||
|
|
|||
|
/**
|
|||
|
* @brief <EFBFBD>ѱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӿ<EFBFBD>, <EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD>, <EFBFBD>ڱ<EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD>ѡʵ<EFBFBD><EFBFBD>
|
|||
|
*/
|
|||
|
virtual void HashIterate() {
|
|||
|
return;
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* @brief <EFBFBD>ڵ<EFBFBD>Ԫ<EFBFBD>ص<EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ
|
|||
|
*/
|
|||
|
void* GetDataPtr() {
|
|||
|
return _data_ptr;
|
|||
|
};
|
|||
|
void SetDataPtr(void* data) {
|
|||
|
_data_ptr = data;
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* @brief Hash<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽhash, ע<EFBFBD><EFBFBD>ѡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>hash<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
*/
|
|||
|
class HashList
|
|||
|
{
|
|||
|
public:
|
|||
|
|
|||
|
/**
|
|||
|
* @brief <EFBFBD><EFBFBD><EFBFBD>캯<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
*/
|
|||
|
explicit HashList(int max = 100000) {
|
|||
|
_max = GetMaxPrimeNum((max > 2) ? max : 100000);
|
|||
|
_buckets = (HashKey**)calloc(_max, sizeof(HashKey*));
|
|||
|
_count = 0;
|
|||
|
};
|
|||
|
virtual ~HashList() {
|
|||
|
if (_buckets) {
|
|||
|
free(_buckets);
|
|||
|
_buckets = NULL;
|
|||
|
}
|
|||
|
_count = 0;
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* @brief <EFBFBD><EFBFBD>ȡhash<EFBFBD><EFBFBD>Ԫ<EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD>
|
|||
|
* @return <EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
|
|||
|
*/
|
|||
|
int HashSize() {
|
|||
|
return _count;
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* @brief hash<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD>, Ҫ<EFBFBD>ڸ<EFBFBD>Ԫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ, <EFBFBD><EFBFBD><EFBFBD><EFBFBD>remove
|
|||
|
* @param key <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>, ע<EFBFBD><EFBFBD>Ԫ<EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
* @return 0 <EFBFBD>ɹ<EFBFBD>, -1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>, -2 <EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
*/
|
|||
|
int HashInsert(HashKey* key) {
|
|||
|
if (!key || !_buckets) {
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
if ((key->_hash_value != 0) || (key->_next_entry != NULL)) {
|
|||
|
return -2;
|
|||
|
}
|
|||
|
|
|||
|
key->_hash_value = key->HashValue();
|
|||
|
int idx = (key->_hash_value) % _max;
|
|||
|
|
|||
|
HashKey* next_item = _buckets[idx];
|
|||
|
_buckets[idx] = key;
|
|||
|
key->_next_entry = next_item;
|
|||
|
_count++;
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @brief hash<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD>
|
|||
|
* @param key <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD>keyָ<EFBFBD><EFBFBD>
|
|||
|
* @return <EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>, NULL<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
*/
|
|||
|
HashKey* HashFind(HashKey* key) {
|
|||
|
if (!key || !_buckets) {
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
uint32_t hash = key->HashValue();
|
|||
|
int idx = hash % _max;
|
|||
|
HashKey* item = _buckets[idx];
|
|||
|
|
|||
|
for (; item != NULL; item = item->_next_entry) {
|
|||
|
if (item->_hash_value != hash) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if (item->HashCmp(key) == 0) {
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return item;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @brief hash<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD>
|
|||
|
* @param key <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD>keyָ<EFBFBD><EFBFBD>
|
|||
|
* @return <EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>, NULL<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
*/
|
|||
|
void* HashFindData(HashKey* key) {
|
|||
|
HashKey* item = HashFind(key);
|
|||
|
if (!item) {
|
|||
|
return NULL;
|
|||
|
} else {
|
|||
|
return item->_data_ptr;
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* @brief hashɾ<EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD>
|
|||
|
* @param key <EFBFBD><EFBFBD>ɾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>keyָ<EFBFBD><EFBFBD>
|
|||
|
*/
|
|||
|
void HashRemove(HashKey* key) {
|
|||
|
if (!key || !_buckets) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
uint32_t hash = key->HashValue();
|
|||
|
int idx = hash % _max;
|
|||
|
HashKey* item = _buckets[idx];
|
|||
|
HashKey* prev = NULL;
|
|||
|
|
|||
|
for (; item != NULL; prev = item, item = item->_next_entry) {
|
|||
|
if ((item->_hash_value == hash) && (item->HashCmp(key) == 0)){
|
|||
|
if (prev == NULL) {
|
|||
|
_buckets[idx] = item->_next_entry;
|
|||
|
} else {
|
|||
|
prev->_next_entry = item->_next_entry;
|
|||
|
}
|
|||
|
item->_hash_value = 0;
|
|||
|
item->_next_entry = NULL;
|
|||
|
_count--;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @brief hash<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD>, <EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
*/
|
|||
|
void HashForeach() {
|
|||
|
if (!_buckets) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
for (int i = 0; i < _max; i++) {
|
|||
|
HashKey* item = _buckets[i];
|
|||
|
for (; item != NULL; item = item->_next_entry) {
|
|||
|
item->HashIterate();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @brief hash<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD><EFBFBD><EFBFBD>, ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ձ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
*/
|
|||
|
HashKey* HashGetFirst() {
|
|||
|
if (!_buckets) {
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
for (int i = 0; i < _max; i++) {
|
|||
|
if (_buckets[i]) {
|
|||
|
return _buckets[i];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
private:
|
|||
|
|
|||
|
/**
|
|||
|
* @brief <EFBFBD><EFBFBD>ȡͰ<EFBFBD><EFBFBD><EFBFBD>ȵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
*/
|
|||
|
int GetMaxPrimeNum(int num)
|
|||
|
{
|
|||
|
int sqrt_value = (int)sqrt(num);
|
|||
|
for (int i = num; i > 0; i--)
|
|||
|
{
|
|||
|
int flag = 1;
|
|||
|
for (int k = 2; k <= sqrt_value; k++)
|
|||
|
{
|
|||
|
if (i % k == 0)
|
|||
|
{
|
|||
|
flag = 0;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (flag == 1)
|
|||
|
{
|
|||
|
return i;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return 0;
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
private:
|
|||
|
HashKey** _buckets; ///< Ͱָ<CDB0><D6B8>
|
|||
|
int _count; ///< <20><>ЧԪ<D0A7>ظ<EFBFBD><D8B8><EFBFBD>
|
|||
|
int _max; ///< <20><><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
};
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#endif
|
|||
|
|