acl  3.5.3.0
acl_htable.h
浏览该文件的文档.
1 #ifndef ACL_HTABLE_INCLUDE_H
2 #define ACL_HTABLE_INCLUDE_H
3 
4 #ifdef __cplusplus
5 extern "C" {
6 #endif
7 
8 #include "acl_define.h"
9 #include "../thread/acl_thread.h"
10 #include "acl_hash.h" /* just for ACL_HASH_FN */
11 #include "acl_slice.h"
12 #include "acl_iterator.h"
13 
14 /*--------------------------------------------------------------------------*/
15 typedef struct ACL_HTABLE ACL_HTABLE;
17 
18 /**
19  * 哈希表对象结构句柄
20  */
21 struct ACL_HTABLE {
22  int size; /* length of entries array */
23  int init_size; /* length of initial entryies array */
24  int used; /* number of entries in table */
25  ACL_HTABLE_INFO **data; /* entries array, auto-resized */
26  unsigned int flag; /* properties flag */
27  int status; /* the operator's status on the htable */
28 
29  ACL_HASH_FN hash_fn; /* hash function */
32 
33  /* for acl_iterator */
34 
35  /* 取迭代器头函数 */
36  void *(*iter_head)(ACL_ITER*, struct ACL_HTABLE*);
37  /* 取迭代器下一个函数 */
38  void *(*iter_next)(ACL_ITER*, struct ACL_HTABLE*);
39  /* 取迭代器尾函数 */
40  void *(*iter_tail)(ACL_ITER*, struct ACL_HTABLE*);
41  /* 取迭代器上一个函数 */
42  void *(*iter_prev)(ACL_ITER*, struct ACL_HTABLE*);
43  /* 取迭代器关联的当前容器成员结构对象 */
44  ACL_HTABLE_INFO *(*iter_info)(ACL_ITER*, struct ACL_HTABLE*);
45 };
46 
47 /**
48  * 哈希表中每一个哈希项的存储信息类型
49  */
51  /**
52  * 哈希键, 只所以如此声明,是因为当创建哈希表的标志位为
53  * ACL_BINHASH_FLAG_KEY_REUSE 时需要复用输入的键空间
54  */
55  union {
56  char *key;
57  const char *c_key;
58  } key;
59  void *value; /**< associated value */
60  unsigned hash; /**< store the key's hash value */
61  struct ACL_HTABLE_INFO *next; /**< colliding entry */
62  struct ACL_HTABLE_INFO *prev; /**< colliding entry */
63 };
64 
65 /**
66  * ACL_HTABLE 遍历用类型
67  */
68 typedef struct ACL_HTABLE_ITER {
69  /* public */
71 
72  /* private */
73  int i;
74  int size;
77 
78 /**
79  * 建立哈希表
80  * @param size 哈希表长度
81  * @param flag {unsigned int} 哈希表属性标志位, ACL_BINHASH_FLAG_xxx
82  * @return 所建哈希表的头指针或为空(这时表示出了严重的错误, 主要是内存分配问题)
83  */
84 ACL_API ACL_HTABLE *acl_htable_create(int size, unsigned int flag);
85 /* 添加新的对象时是否直接复用键地址 */
86 #define ACL_HTABLE_FLAG_KEY_REUSE (1 << 0)
87 
88 /* 是否针对启用多线程互斥方式 */
89 #define ACL_HTABLE_FLAG_USE_LOCK (1 << 1)
90 
91 /* 每次查询时是否将查询结果对象放在链头 */
92 #define ACL_HTABLE_FLAG_MSLOOK (1 << 2)
93 
94 /* 统一将键转换为小写,从而实现键查询不区分大小写的功能 */
95 #define ACL_HTABLE_FLAG_KEY_LOWER (1 << 3)
96 
97 ACL_API ACL_HTABLE *acl_htable_create3(int size, unsigned int flag,
98  ACL_SLICE_POOL *slice);
99 
100 /**
101  * 设置哈希表的控制参数
102  * @param table 哈希表对象句柄
103  * @param name 控制参数的变参初始值, name 及以后的控制参数如下定义
104  * ACL_HTABLE_CTL_END: 变参表结束标志
105  * ACL_HTABLE_CTL_RWLOCK: 是否启用读写锁机制
106  * ACL_HTABLE_CTL_HASH_FN: 用户自定义的哈希值计算函数
107  */
108 ACL_API void acl_htable_ctl(ACL_HTABLE *table, int name, ...);
109 #define ACL_HTABLE_CTL_END 0 /**< 控制结束标志 */
110 #define ACL_HTABLE_CTL_RWLOCK 1 /**< 是否加锁 */
111 #define ACL_HTABLE_CTL_HASH_FN 2 /**< 设置私有哈希函数 */
112 
113 /**
114  * 检查上一次哈希表操作后哈希表的状态
115  * @param table 哈希表指针
116  * @return {int} 操作哈希表后的状态, 参见如下的 ACL_HTABLE_STAT_XXX
117  */
118 ACL_API int acl_htable_errno(ACL_HTABLE *table);
119 #define ACL_HTABLE_STAT_OK 0 /**< 状态正常 */
120 #define ACL_HTABLE_STAT_INVAL 1 /**< 无效参数 */
121 #define ACL_HTABLE_STAT_DUPLEX_KEY 2 /**< 重复键 */
122 
123 /**
124  * 设置哈希表的当前状态, error 取值 ACL_HTABLE_STAT_XXX
125  * @param table 哈希表指针
126  * @param error 设置哈希表的错误状态
127  */
128 ACL_API void acl_htable_set_errno(ACL_HTABLE *table, int error);
129 
130 /**
131  * 往哈希表里添加新的项
132  * @param table 哈希表指针
133  * @param key 键, 在函数内部会复制此 key 键
134  * @param value 用户自己的特定数据项(可以由类型硬转化而来, 但是此数据项必须
135  * 不能堆栈变量)
136  * @return 所分配的哈希表项的指针, == NULL: 表示内部分配内存出错, 为严重的错误
137  * 注:如果在添加时该哈希争键存在,则返回已经存在的哈希项,使用者应该通过调用
138  * acl_htable_last_errno() 来查看是否重复添加同一个键值(ACL_HTABLE_STAT_DUPLEX_KEY)
139  */
141  const char *key, void *value);
142 
143 /**
144  * 往哈希表里添加新的项,当多个线程同时进行此操作时,函数内部会自动保证互斥操作
145  * @param table 哈希表指针
146  * @param key 键, 在函数内部会复制此 key 键
147  * @param value 用户自己的特定数据项(可以由类型硬转化而来, 但是此数据项必须
148  * 不能堆栈变量)
149  * @param callback 如果该函数指针不为空,则当添加成功后便调用该函数
150  * @param arg callback 的参数之一
151  * @return {int} 0 表示 添加成功,-1 表示添加失败
152  * 注:如果在添加时该哈希争键存在,则返回已经存在的哈希项,使用者应该通过调用
153  * acl_htable_last_errno() 来查看是否重复添加同一个键值(ACL_HTABLE_STAT_DUPLEX_KEY)
154  */
155 ACL_API int acl_htable_enter_r(ACL_HTABLE *table, const char *key, void *value,
156  void (*callback)(ACL_HTABLE_INFO *ht, void *arg), void *arg);
157 
158 /**
159  * 由所给的 key 键查寻某一特定哈希项
160  * @param table 哈希表指针
161  * @param key 键
162  * @return 不为空指针: 表示查到了对应于 key 键的哈希项
163  * 为空: 表示未查到对应于 key 键的哈希项
164  */
165 ACL_API ACL_HTABLE_INFO *acl_htable_locate(ACL_HTABLE *table, const char *key);
166 
167 /**
168  * 由所给的 key 键查寻某一特定哈希项,当多个线程同时进行此操作时,
169  * 函数内部会自动保证互斥操作
170  * @param table 哈希表指针
171  * @param key 键
172  * @param callback 查到所要求的键值后如果该指针非空则调用之
173  * @param arg callback 参数之一
174  * @return 不为空指针: 表示查到了对应于 key 键的哈希项
175  * 为空: 表示未查到对应于 key 键的哈希项
176  */
177 ACL_API int acl_htable_locate_r(ACL_HTABLE *table, const char *key,
178  void (*callback)(ACL_HTABLE_INFO *ht, void *arg), void *arg);
179 
180 /**
181  * 由所给的 key 键查寻用户的数据项
182  * @param table 哈希表指针
183  * @param key 键
184  * @return 不为空: 表示查到了对应于 key 键的数据项, 用户可以根据用户自己的
185  * 数据类型进行转换; 为空: 表示未查到对应于 key 键的数据项
186  */
187 ACL_API void *acl_htable_find(ACL_HTABLE *table, const char *key);
188 
189 /**
190  * 由所给的 key 键查寻用户的数据项, 当多个线程同时进行此操作时,
191  * 函数内部会自动保证互斥操作
192  * @param table 哈希表指针
193  * @param key 键
194  * @param callback 当查到所要求的键值后,如果该函数指针不为空则调用之
195  * @param arg callback 的参数之一
196  * @return 不为空: 表示查到了对应于 key 键的数据项, 用户可以根据用户自己的
197  * 数据类型进行转换; 为空: 表示未查到对应于 key 键的数据项
198  */
199 ACL_API int acl_htable_find_r(ACL_HTABLE *table, const char *key,
200  void (*callback)(void *value, void *arg), void *arg);
201 
202 /**
203  * 根据所给的 key 键删除某一哈希项
204  * @param table 哈希表指针
205  * @param key 键
206  * @param free_fn 如果该函数指针不为空并且找到了对应于 key 键的数据项, 则先
207  * 调用用户所提供的析构函数做一些清尾工作, 然后再释放该哈希项
208  * @return 0: 成功; -1: 未找到该 key 键
209  */
210 ACL_API int acl_htable_delete(ACL_HTABLE *table, const char *key,
211  void (*free_fn) (void *));
212 #define acl_htable_delete_r acl_htable_delete
213 
214 /**
215  * 直接根据 acl_htable_locate 返回的非空对象从哈希表中删除该对象
216  * @param table 哈希表指针
217  * @param ht {ACL_HTABLE_INFO*} 存储于哈希表中的内部结构对象
218  * @param free_fn 如果该函数指针不为空并且找到了对应于 key 键的数据项, 则先
219  * 调用用户所提供的析构函数做一些清尾工作, 然后再释放该哈希项
220  */
221 ACL_API void acl_htable_delete_entry(ACL_HTABLE *table, ACL_HTABLE_INFO *ht,
222  void (*free_fn) (void *));
223 
224 /**
225  * 释放整个哈希表
226  * @param table 哈希表指针
227  * @param free_fn 如果该指针不为空则对哈希表中的每一项哈希项先用该函数做
228  * 清尾工作, 然后再释放
229  */
230 ACL_API void acl_htable_free(ACL_HTABLE *table, void (*free_fn) (void *));
231 
232 /**
233  * 重置哈希表, 该函数会释放哈希表中的所有内容项, 并重新初始化
234  * @param table 哈希表指针
235  * @param free_fn 如果该指针不为空则对哈希表中的每一项哈希项先用该函数做
236  * 清尾工作, 然后再释放
237  * @return 是否重置成功. 0: OK; < 0: error.
238  */
239 ACL_API int acl_htable_reset(ACL_HTABLE *table, void (*free_fn) (void *));
240 #define acl_htable_reset_r acl_htable_reset
241 
242 /**
243  * 对哈希表中的每一项哈希项进行处理
244  * @param table 哈希表指针
245  * @param walk_fn 处理每一项哈希项的函数指针, 不能为空
246  * @param arg 用户自己类型的数据
247  */
248 ACL_API void acl_htable_walk(ACL_HTABLE *table,
249  void (*walk_fn) (ACL_HTABLE_INFO *, void *), void *arg);
250 #define acl_htable_walk_r acl_htable_walk
251 
252 /**
253  * 返回哈希表当前的容器空间大小
254  * @param table 哈希表指针
255  * @return 哈希表的容器空间大小
256  */
257 ACL_API int acl_htable_size(const ACL_HTABLE *table);
258 
259 /**
260  * 返回哈希表当前的窗口中所含元素个数
261  * @param table 哈希表指针
262  * @return 哈希表中元素个数
263  */
264 ACL_API int acl_htable_used(const ACL_HTABLE *table);
265 
266 /**
267  * 将哈希表里的所有项组合成一个链表
268  * @param table 哈希表
269  * @return 不为空: 链表指针; 为空: 表示该哈希表里没有哈希项
270  */
271 ACL_API ACL_HTABLE_INFO **acl_htable_list(const ACL_HTABLE *table);
272 
273 /**
274  * 显示哈希表中 key 键的分布状态
275  * @param table 哈希表指针
276  */
277 ACL_API void acl_htable_stat(const ACL_HTABLE *table);
278 #define acl_htable_stat_r acl_htable_stat
279 
280 ACL_API ACL_HTABLE_INFO **acl_htable_data(ACL_HTABLE *table);
282  ACL_HTABLE *table, ACL_HTABLE_ITER *iter);
285  ACL_HTABLE *table, ACL_HTABLE_ITER *iter);
287 
288 /*-------------------- 一些方便快捷的宏操作 --------------------------------*/
289 
290 #define ACL_HTABLE_ITER_KEY(iter) ((iter).ptr->key.c_key)
291 #define acl_htable_iter_key ACL_HTABLE_ITER_KEY
292 
293 #define ACL_HTABLE_ITER_VALUE(iter) ((iter).ptr->value)
294 #define acl_htable_iter_value ACL_HTABLE_ITER_VALUE
295 
296 /**
297  * 遍历 ACL_HTABLE
298  * @param iter {ACL_HTABLE_ITER}
299  * @param table_ptr {ACL_HTABLE *}
300  * @example:
301  void test()
302  {
303  ACL_HTABLE *table = acl_htable_create(10, 0);
304  ACL_HTABLE_ITER iter;
305  char *value, key[32];
306  int i;
307 
308  for (i = 0; i < 100; i++) {
309  value = (char*) acl_mystrdup("value");
310  snprintf(key, sizeof(key), "key:%d", i);
311  (void) acl_htable_enter(table, key, value);
312  }
313 
314  acl_htable_foreach(iter, table) {
315  printf("%s=%s\n", acl_htable_iter_key(iter),
316  acl_htable_iter_value(iter));
317  if (i == 50)
318  break;
319  }
320  acl_htable_free(table, acl_myfree_fn);
321  }
322  */
323 
324 #if 0
325 #define ACL_HTABLE_FOREACH(iter, table_ptr) \
326  if (table_ptr) \
327  for((iter).size = acl_htable_size((table_ptr)), (iter).i = 0, \
328  (iter).h = acl_htable_data((table_ptr)); (iter).i < (iter).size; (iter).i++) \
329  for ((iter).ptr = *(iter).h++; (iter).ptr; (iter).ptr = (iter).ptr->next)
330 #define ACL_HTABLE_FOREACH_REVERSE(iter, table_ptr) \
331  if (table_ptr) \
332  for((iter).size = acl_htable_size((table_ptr)), (iter).i = (iter).size - 1, \
333  (iter).h = acl_htable_data((table_ptr)) + (iter).i; (iter).i >= 0; (iter).i--) \
334  for ((iter).ptr = *(iter).h--; (iter).ptr; (iter).ptr = (iter).ptr->next)
335 #else
336 #define ACL_HTABLE_FOREACH(iter, table_ptr) \
337  if (table_ptr) \
338  for((void) acl_htable_iter_head((table_ptr), &iter); \
339  (iter).ptr; \
340  (void) acl_htable_iter_next(&iter))
341 #define ACL_HTABLE_FOREACH_REVERSE(iter, table_ptr) \
342  if (table_ptr) \
343  for((void) acl_htable_iter_tail((table_ptr), &iter); \
344  (iter).ptr; \
345  (void) acl_htable_iter_prev(&iter))
346 #endif
347 
348 #define acl_htable_foreach ACL_HTABLE_FOREACH
349 #define acl_htable_foreach_reverse ACL_HTABLE_FOREACH_REVERSE
350 
351 #ifdef __cplusplus
352 }
353 #endif
354 
355 #endif
356 
ACL_API int acl_htable_delete(ACL_HTABLE *table, const char *key, void(*free_fn)(void *))
ACL_API int acl_htable_reset(ACL_HTABLE *table, void(*free_fn)(void *))
int status
Definition: acl_htable.h:27
ACL_API ACL_HTABLE_INFO * acl_htable_locate(ACL_HTABLE *table, const char *key)
ACL_API ACL_HTABLE_INFO * acl_htable_enter(ACL_HTABLE *table, const char *key, void *value)
ACL_API const ACL_HTABLE_INFO * acl_htable_iter_prev(ACL_HTABLE_ITER *iter)
ACL_API const ACL_HTABLE_INFO * acl_htable_iter_head(ACL_HTABLE *table, ACL_HTABLE_ITER *iter)
HTTP_API void const char * name
Definition: lib_http.h:620
unsigned hash
Definition: acl_htable.h:60
ACL_API const ACL_HTABLE_INFO * acl_htable_iter_next(ACL_HTABLE_ITER *iter)
unsigned(* ACL_HASH_FN)(const void *buf, size_t len)
Definition: acl_hash.h:16
ACL_API int acl_htable_errno(ACL_HTABLE *table)
ACL_HTABLE_INFO ** data
Definition: acl_htable.h:25
int init_size
Definition: acl_htable.h:23
ACL_API ACL_HTABLE_INFO ** acl_htable_list(const ACL_HTABLE *table)
ACL_API void acl_htable_free(ACL_HTABLE *table, void(*free_fn)(void *))
ACL_API ACL_HTABLE_INFO ** acl_htable_data(ACL_HTABLE *table)
ACL_API void acl_htable_delete_entry(ACL_HTABLE *table, ACL_HTABLE_INFO *ht, void(*free_fn)(void *))
unsigned int flag
Definition: acl_htable.h:26
ACL_HTABLE_INFO ** h
Definition: acl_htable.h:75
struct ACL_HTABLE_INFO * prev
Definition: acl_htable.h:62
ACL_API int acl_htable_locate_r(ACL_HTABLE *table, const char *key, void(*callback)(ACL_HTABLE_INFO *ht, void *arg), void *arg)
ACL_HTABLE_INFO * ptr
Definition: acl_htable.h:70
const char * c_key
Definition: acl_htable.h:57
ACL_API int acl_htable_used(const ACL_HTABLE *table)
ACL_API void acl_htable_stat(const ACL_HTABLE *table)
ACL_HASH_FN hash_fn
Definition: acl_htable.h:29
ACL_API void acl_htable_walk(ACL_HTABLE *table, void(*walk_fn)(ACL_HTABLE_INFO *, void *), void *arg)
ACL_API const ACL_HTABLE_INFO * acl_htable_iter_tail(ACL_HTABLE *table, ACL_HTABLE_ITER *iter)
ACL_API void * acl_htable_find(ACL_HTABLE *table, const char *key)
struct ACL_HTABLE_ITER ACL_HTABLE_ITER
ACL_API ACL_HTABLE * acl_htable_create3(int size, unsigned int flag, ACL_SLICE_POOL *slice)
acl_pthread_mutex_t * rwlock
Definition: acl_htable.h:31
ACL_API int acl_htable_find_r(ACL_HTABLE *table, const char *key, void(*callback)(void *value, void *arg), void *arg)
ACL_API void acl_htable_ctl(ACL_HTABLE *table, int name,...)
ACL_API int acl_htable_enter_r(ACL_HTABLE *table, const char *key, void *value, void(*callback)(ACL_HTABLE_INFO *ht, void *arg), void *arg)
struct ACL_HTABLE_INFO * next
Definition: acl_htable.h:61
ACL_API void acl_htable_set_errno(ACL_HTABLE *table, int error)
ACL_SLICE_POOL * slice
Definition: acl_htable.h:30
ACL_API ACL_HTABLE * acl_htable_create(int size, unsigned int flag)
ACL_API int acl_htable_size(const ACL_HTABLE *table)