Commit 9e428935f7874cea1c1d4c5367d040aa38eb8626

  • avatar
  • Sean Lynch <seanl @lite…ti.org>
  • Fri Jan 15 17:52:59 GMT 2010
Add key length and the ability to set dup and free to NULL
genhash.c
(93 / 47)
  
1818 1610612741
1919};
2020
21static inline void*
22dup_key(genhash_t *h, const void *key, size_t klen)
23{
24 if (h->ops.dupKey != NULL) {
25 return h->ops.dupKey(key, klen);
26 } else {
27 return (void*)key;
28 }
29}
30
31static inline void*
32dup_value(genhash_t *h, const void *value, size_t vlen)
33{
34 if (h->ops.dupValue != NULL) {
35 return h->ops.dupValue(value, vlen);
36 } else {
37 return (void*)value;
38 }
39}
40
41static inline void
42free_key(genhash_t *h, void *key)
43{
44 if (h->ops.freeKey != NULL) {
45 h->ops.freeKey(key);
46 }
47}
48
49static inline void
50free_value(genhash_t *h, void *value)
51{
52 if (h->ops.freeValue != NULL) {
53 h->ops.freeValue(value);
54 }
55}
56
2157static int
2258estimate_table_size(int est)
2359{
7878
7979 assert(ops.hashfunc != NULL);
8080 assert(ops.hasheq != NULL);
81 assert(ops.dupKey != NULL);
82 assert(ops.dupValue != NULL);
83 assert(ops.freeKey != NULL);
84 assert(ops.freeValue != NULL);
81 assert((ops.dupKey != NULL && ops.freeKey != NULL) || ops.freeKey == NULL);
82 assert((ops.dupValue != NULL && ops.freeValue != NULL) || ops.freeValue == NULL);
8583
8684 size=estimate_table_size(est);
8785 rv=calloc(1, sizeof(genhash_t)
101101}
102102
103103void
104genhash_store(genhash_t *h, const void* k, const void* v)
104genhash_store(genhash_t *h, const void* k, size_t klen,
105 const void* v, size_t vlen)
105106{
106107 int n=0;
107108 struct genhash_entry_t *p;
108109
109110 assert(h != NULL);
110111
111 n=h->ops.hashfunc(k) % h->size;
112 n=h->ops.hashfunc(k, klen) % h->size;
112113 assert(n >= 0);
113114 assert(n < h->size);
114115
115116 p=calloc(1, sizeof(struct genhash_entry_t));
116117 assert(p);
117118
118 p->key=h->ops.dupKey(k);
119 p->value=h->ops.dupValue(v);
119 p->key=dup_key(h, k, klen);
120 p->nkey = klen;
121 p->value=dup_value(h, v, vlen);
122 p->nvalue = vlen;
120123
121124 p->next=h->buckets[n];
122125 h->buckets[n]=p;
123126}
124127
125128static struct genhash_entry_t *
126genhash_find_entry(genhash_t *h, const void* k)
129genhash_find_entry(genhash_t *h, const void* k, size_t klen)
127130{
128131 int n=0;
129132 struct genhash_entry_t *p;
130133
131134 assert(h != NULL);
132 n=h->ops.hashfunc(k) % h->size;
135 n=h->ops.hashfunc(k, klen) % h->size;
133136 assert(n >= 0);
134137 assert(n < h->size);
135138
136139 p=h->buckets[n];
137 for(p=h->buckets[n]; p && !h->ops.hasheq(k, p->key); p=p->next);
140 for(p=h->buckets[n]; p && !h->ops.hasheq(k, klen, p->key, p->nkey); p=p->next);
138141 return p;
139142}
140143
141144void*
142genhash_find(genhash_t *h, const void* k)
145genhash_find(genhash_t *h, const void* k, size_t klen)
143146{
144147 struct genhash_entry_t *p;
145148 void *rv=NULL;
146149
147 p=genhash_find_entry(h, k);
150 p=genhash_find_entry(h, k, klen);
148151
149152 if(p) {
150153 rv=p->value;
156156}
157157
158158enum update_type
159genhash_update(genhash_t* h, const void* k, const void* v)
159genhash_update(genhash_t* h, const void* k, size_t klen,
160 const void* v, size_t vlen)
160161{
161162 struct genhash_entry_t *p;
162163 enum update_type rv=0;
163164
164 p=genhash_find_entry(h, k);
165 p=genhash_find_entry(h, k, klen);
165166
166167 if(p) {
167 h->ops.freeValue(p->value);
168 p->value=h->ops.dupValue(v);
168 free_value(h, p->value);
169 p->value=dup_value(h, v, vlen);
169170 rv=MODIFICATION;
170171 } else {
171 genhash_store(h, k, v);
172 genhash_store(h, k, klen, v, vlen);
172173 rv=NEW;
173174 }
174175
177177}
178178
179179enum update_type
180genhash_fun_update(genhash_t* h, const void* k,
181 void *(*upd)(const void *, const void *),
180genhash_fun_update(genhash_t* h, const void* k, size_t klen,
181 void *(*upd)(const void *, const void *, size_t *, void *),
182182 void (*fr)(void*),
183 const void *def)
183 void *arg,
184 const void *def, size_t deflen)
184185{
185186 struct genhash_entry_t *p;
186187 enum update_type rv=0;
188 size_t newSize = 0;
187189
188 p=genhash_find_entry(h, k);
190 p=genhash_find_entry(h, k, klen);
189191
190192 if(p) {
191 void *newValue=upd(k, p->value);
192 h->ops.freeValue(p->value);
193 p->value=h->ops.dupValue(newValue);
193 void *newValue=upd(k, p->value, &newSize, arg);
194 free_value(h, p->value);
195 p->value=dup_value(h, newValue, newSize);
194196 fr(newValue);
195197 rv=MODIFICATION;
196198 } else {
197 void *newValue=upd(k, def);
198 genhash_store(h, k, newValue);
199 void *newValue=upd(k, def, &newSize, arg);
200 genhash_store(h, k, klen, newValue, newSize);
199201 fr(newValue);
200202 rv=NEW;
201203 }
209209free_item(genhash_t *h, struct genhash_entry_t *i)
210210{
211211 assert(i);
212 h->ops.freeKey(i->key);
213 h->ops.freeValue(i->value);
212 free_key(h, i->key);
213 free_value(h, i->value);
214214 free(i);
215215}
216216
217217int
218genhash_delete(genhash_t* h, const void* k)
218genhash_delete(genhash_t* h, const void* k, size_t klen)
219219{
220220 struct genhash_entry_t *deleteme=NULL;
221221 int n=0;
222222 int rv=0;
223223
224224 assert(h != NULL);
225 n=h->ops.hashfunc(k) % h->size;
225 n=h->ops.hashfunc(k, klen) % h->size;
226226 assert(n >= 0);
227227 assert(n < h->size);
228228
229229 if(h->buckets[n] != NULL) {
230230 /* Special case the first one */
231 if(h->ops.hasheq(h->buckets[n]->key, k)) {
231 if(h->ops.hasheq(h->buckets[n]->key, h->buckets[n]->nkey, k, klen)) {
232232 deleteme=h->buckets[n];
233233 h->buckets[n]=deleteme->next;
234234 } else {
235235 struct genhash_entry_t *p=NULL;
236236 for(p=h->buckets[n]; deleteme==NULL && p->next != NULL; p=p->next) {
237 if(h->ops.hasheq(p->next->key, k)) {
237 if(h->ops.hasheq(p->next->key, p->next->nkey, k, klen)) {
238238 deleteme=p->next;
239239 p->next=deleteme->next;
240240 }
250250}
251251
252252int
253genhash_delete_all(genhash_t* h, const void* k)
253genhash_delete_all(genhash_t* h, const void* k, size_t klen)
254254{
255255 int rv=0;
256 while(genhash_delete(h, k) == 1) {
256 while(genhash_delete(h, k, klen) == 1) {
257257 rv++;
258258 }
259259 return rv;
261261
262262void
263263genhash_iter(genhash_t* h,
264 void (*iterfunc)(const void* key, const void* val, void *arg), void *arg)
264 void (*iterfunc)(const void* key, size_t nkey,
265 const void* val, size_t nval,
266 void *arg), void *arg)
265267{
266268 int i=0;
267269 struct genhash_entry_t *p=NULL;
271271
272272 for(i=0; i<h->size; i++) {
273273 for(p=h->buckets[i]; p!=NULL; p=p->next) {
274 iterfunc(p->key, p->value, arg);
274 iterfunc(p->key, p->nkey, p->value, p->nvalue, arg);
275275 }
276276 }
277277}
295295}
296296
297297static void
298count_entries(const void *key, const void *val, void *arg)
298count_entries(const void *key, size_t klen,
299 const void *val, size_t vlen, void *arg)
299300{
300301 int *count=(int *)arg;
301302 (*count)++;
311311}
312312
313313int
314genhash_size_for_key(genhash_t* h, const void* k)
314genhash_size_for_key(genhash_t* h, const void* k, size_t klen)
315315{
316316 int rv=0;
317317 assert(h != NULL);
318 genhash_iter_key(h, k, count_entries, &rv);
318 genhash_iter_key(h, k, klen, count_entries, &rv);
319319 return rv;
320320}
321321
322322void
323genhash_iter_key(genhash_t* h, const void* key,
324 void (*iterfunc)(const void* key, const void* val, void *arg), void *arg)
323genhash_iter_key(genhash_t* h, const void* key, size_t klen,
324 void (*iterfunc)(const void* key, size_t klen,
325 const void* val, size_t vlen,
326 void *arg), void *arg)
325327{
326328 int n=0;
327329 struct genhash_entry_t *p=NULL;
328330
329331 assert(h != NULL);
330 n=h->ops.hashfunc(key) % h->size;
332 n=h->ops.hashfunc(key, klen) % h->size;
331333 assert(n >= 0);
332334 assert(n < h->size);
333335
334336 for(p=h->buckets[n]; p!=NULL; p=p->next) {
335 if(h->ops.hasheq(key, p->key)) {
336 iterfunc(p->key, p->value, arg);
337 if(h->ops.hasheq(key, klen, p->key, p->nkey)) {
338 iterfunc(p->key, p->nkey, p->value, p->nvalue, arg);
337339 }
338340 }
339341}
340342
341343int
342genhash_string_hash(const void* p)
344genhash_string_hash(const void* p, size_t nkey)
343345{
344346 int rv=5381;
345347 int i=0;
346348 char *str=(char *)p;
347349
348 for(i=0; str[i] != 0x00; i++) {
350 for(i=0; i < nkey; i++) {
351 assert(str[i]);
349352 rv = ((rv << 5) + rv) ^ str[i];
350353 }
351354
genhash.h
(25 / 17)
  
3535 /**
3636 * Function to compute a hash for the given value.
3737 */
38 int (*hashfunc)(const void *);
38 int (*hashfunc)(const void *, size_t);
3939 /**
4040 * Function that returns true if the given keys are equal.
4141 */
42 int (*hasheq)(const void *, const void *);
42 int (*hasheq)(const void *, size_t, const void *, size_t);
4343 /**
4444 * Function to duplicate a key for storage.
4545 */
46 void* (*dupKey)(const void *);
46 void* (*dupKey)(const void *, size_t);
4747 /**
4848 * Function to duplicate a value for storage.
4949 */
50 void* (*dupValue)(const void *);
50 void* (*dupValue)(const void *, size_t);
5151 /**
5252 * Function to free a key.
5353 */
9595 * @param k the key
9696 * @param v the value
9797 */
98void genhash_store(genhash_t *h, const void *k, const void *v);
98void genhash_store(genhash_t *h, const void *k, size_t klen,
99 const void *v, size_t vlen);
99100
100101/**
101102 * Get the most recent value stored for the given key.
106106 *
107107 * @return the value, or NULL if one cannot be found
108108 */
109void* genhash_find(genhash_t *h, const void *k);
109void* genhash_find(genhash_t *h, const void *k, size_t klen);
110110
111111/**
112112 * Delete the most recent value stored for a key.
116116 *
117117 * @return the number of items deleted
118118 */
119int genhash_delete(genhash_t *h, const void *k);
119int genhash_delete(genhash_t *h, const void *k, size_t klen);
120120
121121/**
122122 * Delete all mappings of a given key.
126126 *
127127 * @return the number of items deleted
128128 */
129int genhash_delete_all(genhash_t *h, const void *k);
129int genhash_delete_all(genhash_t *h, const void *k, size_t klen);
130130
131131/**
132132 * Create or update an item in-place.
138138 * @return an indicator of whether this created a new item or updated
139139 * an existing one
140140 */
141enum update_type genhash_update(genhash_t *h, const void *k, const void *v);
141enum update_type genhash_update(genhash_t *h, const void *k, size_t klen,
142 const void *v, size_t vlen);
142143
143144/**
144145 * Create or update an item in-place with a function.
155155 * @return an indicator of whether this created a new item or updated
156156 * an existing one
157157 */
158enum update_type genhash_fun_update(genhash_t *h, const void *key,
159 void *(*upd)(const void *k, const void *oldv),
158enum update_type genhash_fun_update(genhash_t *h, const void *key, size_t klen,
159 void *(*upd)(const void *k, const void *oldv,
160 size_t *ns, void *a),
160161 void (*fr)(void*),
161 const void *def);
162 void *arg,
163 const void *def, size_t deflen);
162164
163165/**
164166 * Iterate all keys and values in a hash table.
170170 * @param arg an argument to be passed to the iterfunc on each iteration
171171 */
172172void genhash_iter(genhash_t *h,
173 void (*iterfunc)(const void* key, const void* val, void *arg),
173 void (*iterfunc)(const void* key, size_t nkey,
174 const void* val, size_t nval,
175 void *arg),
174176 void *arg);
175177
176178/**
183183 * @param iterfunc a function that will be called once for every k/v pair
184184 * @param arg an argument to be passed to the iterfunc on each iteration
185185 */
186void genhash_iter_key(genhash_t *h, const void* key,
187 void (*iterfunc)(const void* key, const void* val, void *arg),
186void genhash_iter_key(genhash_t *h, const void* key, size_t nkey,
187 void (*iterfunc)(const void* key, size_t inkey,
188 const void* val, size_t inval,
189 void *arg),
188190 void *arg);
189191
190192/**
216216 *
217217 * @return the number of entries keyed with the given key
218218 */
219int genhash_size_for_key(genhash_t *h, const void *k);
219int genhash_size_for_key(genhash_t *h, const void *k, size_t nkey);
220220
221221/**
222222 * Convenient hash function for strings.
225225 *
226226 * @return a hash value for this string.
227227 */
228int genhash_string_hash(const void *k);
228int genhash_string_hash(const void *k, size_t nkey);
229229
230230/**
231231 * @}
genhash_int.h
(4 / 0)
  
44struct genhash_entry_t {
55 /** The key for this entry */
66 void *key;
7 /** Size of the key */
8 size_t nkey;
79 /** The value for this entry */
810 void *value;
11 /** Size of the value */
12 size_t nvalue;
913 /** Pointer to the next entry */
1014 struct genhash_entry_t *next;
1115};

Comments

Add a new comment:

Login or create an account to post a comment

Add your comment