zlog学习笔记(zc_hashtable)
zc_hashtable.h
/**
* hashtable
*/ #ifndef __zc_hashtable_h
#define __zc_hashtable_h typedef struct zc_hashtable_entry_s {
unsigned int hash_key;
void *key;
void *value;
struct zc_hashtable_entry_s *prev;
struct zc_hashtable_entry_s *next;
} zc_hashtable_entry_t; typedef struct zc_hashtable_s zc_hashtable_t; typedef unsigned int (*zc_hashtable_hash_fn) (const void *key);
typedef int (*zc_hashtable_equal_fn) (const void *key1, const void *key2);
typedef void(*zc_hashtable_del_fn) (void *kv); zc_hashtable_t *zc_hashtable_new(size_t a_size,
zc_hashtable_hash_fn hash_fn,
zc_hashtable_equal_fn equal_fn,
zc_hashtable_del_fn key_del_fn,
zc_hashtable_del_fn value_del_fn); void zc_hashtable_del(zc_hashtable_t *a_table);
void zc_hashtable_clean(zc_hashtable_t *a_table);
int zc_hashtable_put(zc_hashtable_t *a_table, void *a_key, void *a_value); zc_hashtable_entry_t *zc_hashtable_get_entry(zc_hashtable_t *a_table, const void *a_key); void *zc_hashtable_get(zc_hashtable_t *a_table, const void *a_key);
void zc_hashtable_remove(zc_hashtable_t *a_table, const void *a_key); zc_hashtable_entry_t *zc_hashtable_begin(zc_hashtable_t *a_table);
zc_hashtable_entry_t *zc_hashtable_next(zc_hashtable_t *a_table, zc_hashtable_entry_t *a_entry); struct zc_hashtable_s {
//记录当前element的个数
size_t nelem; zc_hashtable_entry_t **tab;
size_t tab_size; zc_hashtable_hash_fn hash;
zc_hashtable_equal_fn equal;
zc_hashtable_del_fn key_del;
zc_hashtable_del_fn value_del;
}; #define zc_hashtable_foreach(a_table, a_entry)\
for(a_entry = zc_hashtable_begin(a_table); a_entry; a_entry = zc_hashtable_next(a_table, a_entry)) unsigned int zc_hashtable_str_hash(const void *str);
int zc_hashtable_str_equal(const void *key1, const void *key2); #endif
zc_hashtable.c
#include <stdlib.h>
#include <errno.h>
#include <pthread.h> #include "zc_defs.h"
#include "zc_hashtable.h" //struct zc_hashtable_s {
// //记录当前element的个数
// size_t nelem;
//
// zc_hashtable_entry_t **tab;
// size_t tab_size;
//
// zc_hashtable_hash_fn hash;
// zc_hashtable_equal_fn equal;
// zc_hashtable_del_fn key_del;
// zc_hashtable_del_fn value_del;
//}; zc_hashtable_t *zc_hashtable_new(size_t a_size,
zc_hashtable_hash_fn hash,
zc_hashtable_equal_fn equal,
zc_hashtable_del_fn key_del,
zc_hashtable_del_fn value_del){ zc_hashtable_t *a_table;
a_table = (zc_hashtable_t *)calloc(, sizeof(zc_hashtable_t));
if(!a_table){
zc_error("calloc fail, errno[%d]", errno);
return NULL;
} a_table->tab = (zc_hashtable_entry_t **)calloc(a_size, sizeof(zc_hashtable_entry_t *));
if(!a_table->tab){
zc_error("calloc fail, errno[%d]", errno);
free(a_table);
return NULL;
}
a_table->tab_size = a_size; a_table->nelem = ;
a_table->hash = hash;
a_table->equal = equal; //these two could be NULL
a_table->key_del = key_del;
a_table->value_del = value_del; return a_table;
} void zc_hashtable_del(zc_hashtable_t *a_table){
size_t i;
zc_hashtable_entry_t *p;
zc_hashtable_entry_t *q; if(!a_table){
zc_error("a_table[%p] is NULL, just do nothing", a_table);
return ;
} for(i = ; i < a_table->tab_size; i++){
//hash conflic
for(p = (a_table->tab)[i]; p; p = q){
q = p->next;
if(a_table->key_del){
a_table->key_del(p->key);
}
if(a_table->value_del){
a_table->value_del(p->value);
}
free(p);
}
}
if(a_table->tab){
free(a_table->tab);
}
free(a_table); return;
} void zc_hashtable_clean(zc_hashtable_t *a_table){
size_t i;
zc_hashtable_entry_t *p, *q; for(i = ; i < a_table->tab_size; i++){
for(p = (a_table->tab)[i]; p; p = q){
q = p->next;
if(a_table->key_del){
a_table->key_del(p->key);
}
if(a_table->value_del){
a_table->value_del(p->value);
}
free(p);
}
(a_table->tab)[i] = NULL;
}
a_table->nelem = ; return;
} static int zc_hashtable_rehash(zc_hashtable_t *a_table){
size_t i, j, tab_size;
zc_hashtable_entry_t **tab;
zc_hashtable_entry_t *p;
zc_hashtable_entry_t *q; tab_size = * a_table->tab_size;
tab = calloc(tab_size, sizeof(zc_hashtable_t *));
if(!tab){
zc_error("calloc fail, errno[%d]", errno);
return -;
} for(i = ; i < a_table->tab_size; i++){
//优化
for(p = a_table->tab[i]; p; p = q){
q = p->next; p->prev = NULL;
p->next = NULL;
j = p->hash_key % tab_size;
if(tab[j]){
tab[j]->prev = p;
p->next = tab[j];
}
tab[j] = p;
}
}
free(a_table->tab);
a_table->tab = tab;
a_table->tab_size = tab_size; return ;
} void *zc_hashtable_get(zc_hashtable_t *a_table, const void *a_key){
size_t i;
zc_hashtable_entry_t *p = NULL; i = a_table->hash(a_key) % a_table->tab_size;
for(p = a_table->tab[i]; p; p = p->next){
if(a_table->equal(a_key, p->key)){
return p->value;
}
}
return NULL;
} int zc_hashtable_put(zc_hashtable_t *a_table, void *a_key, void *a_value){
int rc;
size_t i;
zc_hashtable_entry_t *p = NULL; i = a_table->hash(a_key) % a_table->tab_size;
for(p = a_table->tab[i]; p; p = p->next){
if(a_table->equal(a_key, p->key)){
break;
}
} //a_table->tab[i] have value
if(p){
if(a_table->key_del){
a_table->key_del(p->key);
}
if(a_table->value_del){
a_table->value_del(p->value);
}
p->key = a_key;
p->value = a_value;
return ;
}else{
if(a_table->nelem > a_table->tab_size * 1.3){
rc = zc_hashtable_rehash(a_table);
if(rc){
zc_error("rehash fail");
return -;
}
}
//如果sizeof(zc_hashtable_entry_t *) 会造成free失败
p = calloc(, sizeof(zc_hashtable_entry_t));
if(!p){
zc_error("calloc fail, errno[%d]", errno);
return -;
} p->hash_key = a_table->hash(a_key);
p->key = a_key;
p->value = a_value;
p->next = NULL;
p->prev = NULL; i = p->hash_key % a_table->tab_size;
//has value
if(a_table->tab[i]){
a_table->tab[i]->prev = p;
p->next = a_table->tab[i];
}
a_table->tab[i] = p;
a_table->nelem++;
} return ;
} void zc_hashtable_remove(zc_hashtable_t *a_table, const void *a_key){
size_t i;
zc_hashtable_entry_t *p; if(!a_table || !a_key){
zc_error("a_table[%p] or a_key[%p] is NULL, just do nothing", a_table, a_key);
return ;
}
i = a_table->hash(a_key) % a_table->tab_size;
for(p = a_table->tab[i]; p; p = p->next){
if(a_table->equal(a_key, p->key)){
break;
}
} if(!p){
zc_error("p[%p] is not found in hashtable", p);
return;
} if(a_table->key_del){
a_table->key_del(p->key);
}
if(a_table->value_del){
a_table->value_del(p->value);
} if(p->next){
p->next->prev = p->prev;
}
if(p->prev){
p->prev->next = p->next;
}else{
//notice
a_table->tab[i] = p->next;
} free(p);
a_table->nelem--; return;
} zc_hashtable_entry_t *zc_hashtable_begin(zc_hashtable_t *a_table){
size_t i;
zc_hashtable_entry_t *p;
for(i= ; i < a_table->tab_size; i++){
for(p = a_table->tab[i]; p; p->next){
if(p){
return p;
}
}
}
printf("%d\n", i);
return NULL;
} zc_hashtable_entry_t *zc_hashtable_next(zc_hashtable_t *a_table, zc_hashtable_entry_t *a_entry){
size_t i, j; if(a_entry->next){
return a_entry->next;
} i = a_entry->hash_key % a_table->tab_size; for(j = i + ; j < a_table->tab_size; j++){
if(a_table->tab[j]){
return a_table->tab[j];
}
} return NULL;
} /**************************************************hash、equal**********************************************/ int zc_hashtable_str_equal(const void *key1, const void *key2){
return (STRCMP((const char *)key1, ==, (const char *)key2));
} unsigned int zc_hashtable_str_hash(const void *str){
size_t h = ;
const char *p = (const char *)str; while(*p != '\0'){
h = ((h << ) + h) + (*p++); /* hash * 33 + c*/
} return h;
}
测试
#include <stdio.h> #include "zc_defs.h"
#include "zc_hashtable.c"
#include "zc_profile.c" void myfree(void *kv){ } int main(){
zc_hashtable_t *a_table;
zc_hashtable_entry_t *a_entry; a_table = zc_hashtable_new(,
zc_hashtable_str_hash,
zc_hashtable_str_equal,
myfree,myfree
); zc_hashtable_put(a_table, "aaa", "");
zc_hashtable_put(a_table, "bbb", "");
zc_hashtable_put(a_table, "ccc", ""); zc_hashtable_foreach(a_table, a_entry){
printf("k[%s], v[%s]\n", a_entry->key, a_entry->value);
} printf("getv[%s]\n", (char *)zc_hashtable_get(a_table, "ccc")); zc_hashtable_remove(a_table, "ccc"); zc_hashtable_foreach(a_table, a_entry){
printf("k[%s], v[%s]\n", a_entry->key, a_entry->value);
} zc_hashtable_remove(a_table, NULL);
zc_hashtable_del(NULL); zc_hashtable_del(a_table); return ;
}
zlog学习笔记(zc_hashtable)的更多相关文章
- zlog学习笔记(mdc)
mdc.h #ifndef __zlog_mdc_h #define __zlog_mdc_h #include "zc_defs.h" typedef struct zlog_m ...
- zlog学习笔记(level_list)
level_list.h /** * */ #ifndef __zlog_level_list_h #define __zlog_level_list_h zc_arraylist_t *zlog_l ...
- zlog学习笔记(level)
level.h /** * */ #ifndef __zlog_level_h #define __zlog_level_h #include "stdio.h" #include ...
- zlog学习笔记(zc_arraylist)
zc_arraylist.h /** * 实现类似列表的功能 * */ #ifndef __zc_arraylist_h #define __zc_arraylist_h #define ARRAY_ ...
- zlog学习笔记(zc_profile)
zc_profile.h #ifndef __zlog_profile_h #define __zlog_profile_h #define EMPTY() #define zc_assert(exp ...
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- PHP-自定义模板-学习笔记
1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ...
- PHP-会员登录与注册例子解析-学习笔记
1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...
- 2014年暑假c#学习笔记目录
2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...
随机推荐
- PULL解析XML的运行机制详解
PULL解析简单易上手,基本上看一遍,基本上就会解析啦,但总是感觉对PULL解析的运行机制不是很了解,就总结了以下事件驱动到底是怎么执行的.. PULL: Android内置了PULL解析器.PULL ...
- iOS通讯录开发
场景一:直接选择一个联系人的电话号码 这里不需要先获取所有的联系人自己做联系人列表,直接使用系统自带的AddressBookUI/ABPeoplePickerNavigationController. ...
- vs合并压缩css,js插件——Bundler & Minifier
之前做了一个大转盘的抽奖活动,因为比较火,部分用户反馈看不到页面的情况,我怀疑js加载请求过慢导致,所以今天针对之前的一个页面进行调试优化. 首先想到的是对页面的js和css进行压缩优化,百度了下vs ...
- 教你怎么检测Heartbleed OpenSSL漏洞
Heartbleed错误是一个严重的漏洞.这个弱点可以窃取信息,在正常情况下,由SSL / TLS加密保护互联网.Heartbleed错误允许任何人在互联网上阅读系统的内存保护脆弱的OpenSSL的软 ...
- C#复习⑧
C#复习⑧ 2016年6月22日 13:50 Main Attribute & Threads 属性与线程 1.Conditional Attribute 条件属性 #define debug ...
- WPF学习之路(四)路由
路由事件概述 功能定义:路由事件是一种可以针对元素树中的多个侦听器(而不是仅针对引发该事件的对象)调用处理程序的事件. 实现定义:路由事件是一个 CLR 事件,可以由RouteEvent 类的实例提供 ...
- Asp.Net Web Form 前后台传值
1,后台往前台传值----单个变量直接传递到页面元素 前台代码 <b><%=strCompanyName%>费用明细</b> 后台代码 public partial ...
- MYSQL的JOB
要让JOB顺利运行,必须要打开MYSQL的定时器. -- 查看是否开启定时器 SHOW VARIABLES LIKE '%sche%'; -- 开启定时器 0:off 1:on -- 这个需要最高权限 ...
- C#调用自定义表类型参数
-SQL SERVER生成测试环境: --创建测试DB CREATE database Sales; go USE Sales GO --创建表类型 IF TYPE_ID('LocalDT') IS ...
- nginx参数说明
一.nginx的核心配置: >>> 正常运行的必备配置: 1. user username [groupname]; #指定运行worker子进程的用户或组 2. pid /path ...