vsftpd 2.0.7 - initial checkin.
[tomato.git] / release / src / router / vsftpd / hash.c
bloba1ea29d530181b3c6a1f6bd294c00133787f067f
1 /*
2 * Part of Very Secure FTPd
3 * Licence: GPL v2
4 * Author: Chris Evans
5 * hash.c
7 * Routines to handle simple hash table lookups and modifications.
8 */
10 #include "hash.h"
11 #include "sysutil.h"
12 #include "utility.h"
14 struct hash_node
16 void* p_key;
17 void* p_value;
18 struct hash_node* p_prev;
19 struct hash_node* p_next;
22 struct hash
24 unsigned int buckets;
25 unsigned int key_size;
26 unsigned int value_size;
27 hashfunc_t hash_func;
28 struct hash_node** p_nodes;
31 /* Internal functions */
32 struct hash_node** hash_get_bucket(struct hash* p_hash, void* p_key);
33 struct hash_node* hash_get_node_by_key(struct hash* p_hash, void* p_key);
35 struct hash*
36 hash_alloc(unsigned int buckets, unsigned int key_size,
37 unsigned int value_size, hashfunc_t hash_func)
39 unsigned int size;
40 struct hash* p_hash = vsf_sysutil_malloc(sizeof(*p_hash));
41 p_hash->buckets = buckets;
42 p_hash->key_size = key_size;
43 p_hash->value_size = value_size;
44 p_hash->hash_func = hash_func;
45 size = sizeof(struct hash_node*) * buckets;
46 p_hash->p_nodes = vsf_sysutil_malloc(size);
47 vsf_sysutil_memclr(p_hash->p_nodes, size);
48 return p_hash;
51 void*
52 hash_lookup_entry(struct hash* p_hash, void* p_key)
54 struct hash_node* p_node = hash_get_node_by_key(p_hash, p_key);
55 if (!p_node)
57 return p_node;
59 return p_node->p_value;
62 void
63 hash_add_entry(struct hash* p_hash, void* p_key, void* p_value)
65 struct hash_node** p_bucket;
66 struct hash_node* p_new_node;
67 if (hash_lookup_entry(p_hash, p_key))
69 bug("duplicate hash key");
71 p_bucket = hash_get_bucket(p_hash, p_key);
72 p_new_node = vsf_sysutil_malloc(sizeof(*p_new_node));
73 p_new_node->p_prev = 0;
74 p_new_node->p_next = 0;
75 p_new_node->p_key = vsf_sysutil_malloc(p_hash->key_size);
76 vsf_sysutil_memcpy(p_new_node->p_key, p_key, p_hash->key_size);
77 p_new_node->p_value = vsf_sysutil_malloc(p_hash->value_size);
78 vsf_sysutil_memcpy(p_new_node->p_value, p_value, p_hash->value_size);
80 if (!*p_bucket)
82 *p_bucket = p_new_node;
84 else
86 p_new_node->p_next = *p_bucket;
87 (*p_bucket)->p_prev = p_new_node;
88 *p_bucket = p_new_node;
92 void
93 hash_free_entry(struct hash* p_hash, void* p_key)
95 struct hash_node* p_node = hash_get_node_by_key(p_hash, p_key);
96 if (!p_node)
98 bug("hash node not found");
100 vsf_sysutil_free(p_node->p_key);
101 vsf_sysutil_free(p_node->p_value);
103 if (p_node->p_prev)
105 p_node->p_prev->p_next = p_node->p_next;
107 else
109 struct hash_node** p_bucket = hash_get_bucket(p_hash, p_key);
110 *p_bucket = p_node->p_next;
112 if (p_node->p_next)
114 p_node->p_next->p_prev = p_node->p_prev;
117 vsf_sysutil_free(p_node);
120 struct hash_node**
121 hash_get_bucket(struct hash* p_hash, void* p_key)
123 unsigned int bucket = (*p_hash->hash_func)(p_hash->buckets, p_key);
124 if (bucket >= p_hash->buckets)
126 bug("bad bucket lookup");
128 return &(p_hash->p_nodes[bucket]);
131 struct hash_node*
132 hash_get_node_by_key(struct hash* p_hash, void* p_key)
134 struct hash_node** p_bucket = hash_get_bucket(p_hash, p_key);
135 struct hash_node* p_node = *p_bucket;
136 if (!p_node)
138 return p_node;
140 while (p_node != 0 &&
141 vsf_sysutil_memcmp(p_key, p_node->p_key, p_hash->key_size) != 0)
143 p_node = p_node->p_next;
145 return p_node;