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 ...
随机推荐
- 【C语言】C语言局部变量和全局变量
目录: [局部变量] · 定义 · 作用域 · 生命周期 · 用static修饰局部变量 [全局变量] · 定义 · 作用域 · 生命周期 1.局部变量 · 定义 在函数(代码块)内部定义的变量称为局 ...
- Android Studio Gradle Build Running 特别慢的问题探讨
本文的本本win7 64bit 6G android studio2.1 在运行程序的时候Gradle Build Running 特别慢,一个helloworld都快2min了 1.开启gradle ...
- (20160602)开源第三方学习之SDWebImage
这个类库提供一个UIImageView类别以支持加载来自网络的远程图片.具有缓存管理.异步下载.同一个URL下载次数控制和优化等特征. 地址:https://github.com/rs/SDWebIm ...
- C#反序化json字符串,不用区分大小写
最近在做第三方对接的项目,接口返回的数据是json格式,并且每个字段都是小写的,而我们程序类中的属性是要求大写的:刚开始想到的是用JavaScriptSerializer,但是这个并不满足需求 就换了 ...
- Eclipse中jsp、js文件编辑时,卡死现象解决汇总
使用Eclipse编辑jsp.js文件时,经常出现卡死现象,在网上百度了N次,经过N次优化调整后,卡死现象逐步好转,具体那个方法起到作用,不太好讲.将所有用过的方法罗列如下: 1.取消验证 windo ...
- Asp.net MVC中提交集合对象,实现Model绑定
Asp.net MVC中的Model自动绑定功能,方便了我们对于request中的数据的处理, 从客户端的请求数据,自动地以Action方法参数的形式呈现.有时候我们的Action方法中想要接收数组类 ...
- android + red5 + rtmp
背景:在已有的red5服务器环境下实现android客户端的视频直播 要实现客户端视频直播就先先对服务器端有所了解 Red5流媒体服务器是Adboe的产品,免费并且是开源的,与Flash搭配的时候可谓 ...
- Mongodb Manual阅读笔记:CH9 Sharding
9.分片(Sharding) Mongodb Manual阅读笔记:CH2 Mongodb CRUD 操作Mongodb Manual阅读笔记:CH3 数据模型(Data Models)Mongodb ...
- Access 2003 中自定义菜单栏
在Access中如何用自定义的菜单代替Access自带的菜单,现在做一个简单的介绍: 1.打开您做的Access数据库: 2.单击工具栏,选择“自定义…”: 3.在“自定义”窗口,单击“工具栏”选项卡 ...
- linux线程同步(1)-互斥量
一.概述 互斥量是线程同步的一种机制,用来保护多线程的共享资源.同一时刻,只允许一个线程对临界区进行 ...