哈希表是一种数据结构,通过在记录的存储位置和它的关键字之间建立确定的对应关系,来快速查询表中的数据;
openssl lhash.h 为我们提供了哈希表OPENSSL_LHASH 的相关接口,我们可以直接使用,用来存放各种数据;
哈希表类似前面提到的栈,但是哈希表的优势是查询速度快。
1. lhash.h 提供的哈希表主要接口有
//创建哈希表,参数为两个回调函数,分别可自定义哈希值计算方法,排序方法
OPENSSL_LHASH *OPENSSL_LH_new(OPENSSL_LH_HASHFUNC h, OPENSSL_LH_COMPFUNC c); //释放哈希表内存,但是不释放表中数据的内存,需要调用下面的doall方法遍历表中数据去释放
void OPENSSL_LH_free(OPENSSL_LHASH *lh); //在表中插入一条记录,当表中有该数据时,会进行替换,成功返回插入的数据地址
void *OPENSSL_LH_insert(OPENSSL_LHASH *lh, void *data); //从表中删除一条记录,成功返回删除的该数据地址
void *OPENSSL_LH_delete(OPENSSL_LHASH *lh, const void *data); //从表中查询一条记录,参数为要查询数据的地址,成功返回表中该数据的地址
void *OPENSSL_LH_retrieve(OPENSSL_LHASH *lh, const void *data); //遍历表中的数据记录,回调函数可处理遍历每条记录
void OPENSSL_LH_doall(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNC func); //遍历表中的数据记录,多了一个arg参数,可看下面的测试
void OPENSSL_LH_doall_arg(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNCARG func, void *arg); //计算一条数据的哈希值
unsigned long OPENSSL_LH_strhash(const char *c); //哈希表中元素个数
unsigned long OPENSSL_LH_num_items(const OPENSSL_LHASH *lh); //查看哈希表的状态,输出到FILE
void OPENSSL_LH_stats(const OPENSSL_LHASH *lh, FILE *fp); //查看哈希表节点的状态,输出到FILE
void OPENSSL_LH_node_stats(const OPENSSL_LHASH *lh, FILE *fp); //查看哈希表节点的使用状态,输出到FILE
void OPENSSL_LH_node_usage_stats(const OPENSSL_LHASH *lh, FILE *fp);
//以下接口为哈希表状态,输出到BIO
void OPENSSL_LH_stats_bio(const OPENSSL_LHASH *lh, BIO *out);
void OPENSSL_LH_node_stats_bio(const OPENSSL_LHASH *lh, BIO *out);
void OPENSSL_LH_node_usage_stats_bio(const OPENSSL_LHASH *lh, BIO *out);
2. 测试代码
unsigned long hashff(void *hf)
{
printf("%s\n",hf);
return ;
} int hashfCmp(int *a,int *b)
{
return *a > *b; } void printArg(int *a,char *b)
{
printf("doall_arg: %d %s\n",*a,b);
} void printValue(int *value)
{
printf("doall: %d\n",*value);
} int main(int argc, const char * argv[]) { OPENSSL_LHASH *lh = OPENSSL_LH_new(NULL, NULL); int item = ;
OPENSSL_LH_insert(lh, &item); int item2 = ;
OPENSSL_LH_insert(lh, &item2); int item3 = ;
OPENSSL_LH_insert(lh, &item3); //因为表中已经存在数据5,如果再插入,将会替换之前的数据5
int item4 = ;
int *ret=;
ret = OPENSSL_LH_insert(lh, &item4);
if (*ret==item4) {
printf("insert replace PASS\n");
} int *fd = ;
fd = OPENSSL_LH_retrieve(lh,&item2);
if (*fd == item2) {
printf("find value PASS\n");
} OPENSSL_LH_doall(lh, printValue);
OPENSSL_LH_doall_arg(lh, printArg, "arg"); int *delRet = ;
delRet = OPENSSL_LH_delete(lh, &item4);
if (*delRet==item4) {
printf("delete value PASS\n");
} int numLen = OPENSSL_LH_num_items(lh);
printf("len=%d\n"); OPENSSL_LH_stats(lh, stdout); OPENSSL_LH_free(lh); return ;
}
输出日志
insert replace PASS
find value PASS
doall:
doall:
doall:
doall_arg: arg
doall_arg: arg
doall_arg: arg
delete value PASS
len=
num_items =
num_nodes =
num_alloc_nodes =
num_expands =
num_expand_reallocs =
num_contracts =
num_contract_reallocs =
num_hash_calls =
num_comp_calls =
num_insert =
num_replace =
num_delete =
num_no_delete =
num_retrieve =
num_retrieve_miss =
num_hash_comps =
Program ended with exit code:
测试使用 openssl 1.1.0c
参考:https://www.openssl.org/docs/man1.0.2/crypto/lhash.html