2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 * Copyright (C) 1998-1999 The Jabber Team http://jabber.org/
21 /*****************************************************************************
22 * Internal type definitions
25 typedef struct tagHNODE
27 struct tagHNODE
*next
; /* next node in list */
28 const void *key
; /* key pointer */
29 void *value
; /* value pointer */
32 #define SLAB_NUM_NODES 64 /* allocate this many nodes per slab */
34 typedef struct tagHSLAB
36 struct tagHSLAB
*next
; /* next slab pointer */
37 HNODE nodes
[SLAB_NUM_NODES
]; /* the actual nodes */
40 #define HASH_NUM_BUCKETS 509 /* should be a prime number; see Knuth */
42 typedef struct tagHASHTABLE_INTERNAL
44 unsigned long sig1
; /* first signature word */
45 KEYHASHFUNC hash
; /* hash function */
46 KEYCOMPAREFUNC cmp
; /* comparison function */
47 int count
; /* table entry count */
48 int bcount
; /* bucket count */
49 HNODE
**buckets
; /* the hash buckets */
50 unsigned long sig2
; /* second signature word */
54 #define HASH_SIG1 0x68736148UL /* "Hash" */
55 #define HASH_SIG2 0x6F627245UL /* "Erbo" */
57 #define do_hash(tb,key) ((*((tb)->hash))(key) % ((tb)->bcount))
59 static HNODE
*s_free_nodes
= NULL
; /* free nodes list */
60 static HSLAB
*s_slabs
= NULL
; /* node slabs list */
62 /*****************************************************************************
66 static HNODE
*allocate_node(
67 const void *key
, /* key pointer for this node */
68 void *value
) /* value pointer for this node */
70 allocate_node allocates a new hash node and fills it. Returns NULL if the
71 node could not be allocated.
74 HNODE
*rc
; /* return from this function */
77 { /* allocate a new slabful of nodes and chain them to make a new free list */
78 register int i
; /* loop counter */
79 HSLAB
*slab
= (HSLAB
*)malloc(sizeof(HSLAB
));
82 memset(slab
,0,sizeof(HSLAB
));
84 for (i
=0; i
<(SLAB_NUM_NODES
-1); i
++)
85 slab
->nodes
[i
].next
= &(slab
->nodes
[i
+1]);
86 s_free_nodes
= &(slab
->nodes
[0]);
91 /* grab a node off the fron of the free list and fill it */
93 s_free_nodes
= rc
->next
;
99 } /* end allocate_node */
101 static void free_node(
102 HNODE
*node
) /* node to be freed */
104 free_node returns a hash node to the list.
107 /* zap the node contents to avoid problems later */
108 memset(node
,0,sizeof(HNODE
));
110 /* chain it onto the free list */
111 node
->next
= s_free_nodes
;
114 } /* end free_node */
116 static HNODE
*find_node(
117 HASHTABLE_INTERNAL
*tab
, /* pointer to hash table */
118 const void *key
, /* key value to look up */
119 int bucket
) /* bucket number (-1 to have function compute it) */
121 find_node walks a hash bucket to find a node whose key matches the named key value.
122 Returns the node pointer, or NULL if it's not found.
125 register HNODE
*p
; /* search pointer/return from this function */
127 if (bucket
<0) /* compute hash value if we don't know it already */
128 bucket
= do_hash(tab
,key
);
130 /* search through the bucket contents */
131 for (p
=tab
->buckets
[bucket
]; p
; p
=p
->next
)
132 if ((*(tab
->cmp
))(key
,p
->key
)==0)
133 return p
; /* found! */
135 return NULL
; /* not found */
137 } /* end find_node */
139 static HASHTABLE_INTERNAL
*handle2ptr(
140 HASHTABLE tbl
) /* hash table handle */
142 handle2ptr converts a hash table handle into a pointer and checks its signatures
143 to make sure someone's not trying to pull a whizzer on this module.
146 register HASHTABLE_INTERNAL
*rc
= (HASHTABLE_INTERNAL
*)tbl
;
147 if ((rc
->sig1
==HASH_SIG1
) && (rc
->sig2
==HASH_SIG2
))
148 return rc
; /* signatures match */
150 return NULL
; /* yIkes! */
153 /*****************************************************************************
157 HASHTABLE
ghash_create(int buckets
, KEYHASHFUNC hash
, KEYCOMPAREFUNC cmp
)
160 Creates a new hash table.
164 buckets - Number of buckets to allocate for the hash table; this value
165 should be a prime number for maximum efficiency.
166 hash - Key hash code function to use.
167 cmp - Key comparison function to use.
171 NULL - Table could not be allocated.
172 Other - Handle to the new hashtable.
175 HASHTABLE_INTERNAL
*tab
; /* new table structure */
179 return NULL
; /* bogus! */
182 buckets
= HASH_NUM_BUCKETS
;
184 /* allocate a hash table structure */
185 allocated
= malloc(sizeof(HASHTABLE_INTERNAL
) + (buckets
* sizeof(HNODE
*)));
187 return NULL
; /* memory error */
189 /* fill the fields of the hash table */
190 tab
= (HASHTABLE_INTERNAL
*)allocated
;
191 allocated
+= sizeof(HASHTABLE_INTERNAL
);
192 memset(tab
,0,sizeof(HASHTABLE_INTERNAL
));
193 memset(allocated
,0,buckets
* sizeof(HNODE
*));
194 tab
->sig1
= HASH_SIG1
;
197 tab
->bcount
= buckets
;
198 tab
->buckets
= (HNODE
**)allocated
;
199 tab
->sig2
= HASH_SIG2
;
201 return (HASHTABLE
)tab
; /* Qa'pla! */
203 } /* end ghash_create */
205 void ghash_destroy(HASHTABLE tbl
)
208 Destroys a hash table.
212 tbl - Table to be destroyed.
219 HASHTABLE_INTERNAL
*tab
; /* new table structure */
220 int i
; /* loop counter */
221 HNODE
*p
, *p2
; /* temporary pointers */
226 /* Convert the handle to a table pointer. */
227 tab
= handle2ptr(tbl
);
231 /* Nuke the nodes it contains. */
232 for (i
=0; i
<tab
->bcount
; i
++)
233 { /* free the contents of each bucket */
236 { /* free each node in turn */
245 free(tab
); /* bye bye now! */
247 } /* end ghash_destroy */
249 void *ghash_get(HASHTABLE tbl
, const void *key
)
252 Retrieves a value stored in the hash table.
256 tbl - The hash table to look in.
257 key - The key value to search on.
261 NULL - Value not found.
262 Other - Value corresponding to the specified key.
265 HASHTABLE_INTERNAL
*tab
; /* internal table pointer */
266 HNODE
*node
; /* hash node */
267 void *rc
= NULL
; /* return from this function */
270 return NULL
; /* bogus! */
272 /* Convert the handle to a table pointer. */
273 tab
= handle2ptr(tbl
);
275 return NULL
; /* error */
277 /* Attempt to find the node. */
278 node
= find_node(tab
,key
,-1);
280 rc
= node
->value
; /* found it! */
284 } /* end ghash_get */
286 int ghash_put(HASHTABLE tbl
, const void *key
, void *value
)
289 Associates a key with a value in this hash table.
293 tbl - Hash table to add.
294 key - Key to use for the value in the table.
295 value - Value to add for this key.
303 If the specified key is already in the hashtable, its value will be replaced.
306 HASHTABLE_INTERNAL
*tab
; /* internal table pointer */
307 int bucket
; /* bucket value goes into */
308 HNODE
*node
; /* hash node */
309 int rc
= 1; /* return from this function */
311 if (!tbl
|| !key
|| !value
)
312 return 0; /* bogus! */
314 /* Convert the handle to a table pointer. */
315 tab
= handle2ptr(tbl
);
317 return 0; /* error */
320 /* Compute the hash bucket and try to find an existing node. */
321 bucket
= do_hash(tab
,key
);
322 node
= find_node(tab
,key
,bucket
);
324 { /* OK, try to allocate a new node. */
325 node
= allocate_node(key
,value
);
327 { /* Chain the new node into the hash table. */
328 node
->next
= tab
->buckets
[bucket
];
329 tab
->buckets
[bucket
] = node
;
333 else /* allocation error */
337 else /* already in table - just reassign value */
342 } /* end ghash_put */
344 int ghash_remove(HASHTABLE tbl
, const void *key
)
347 Removes an entry from a hash table, given its key.
351 tbl - Hash table to remove from.
352 key - Key of value to remove.
357 0 - Failure; key not present in hash table.
360 HASHTABLE_INTERNAL
*tab
; /* internal table pointer */
361 int bucket
; /* bucket value goes into */
362 HNODE
*node
; /* hash node */
363 register HNODE
*p
; /* removal pointer */
364 int rc
= 1; /* return from this function */
367 return 0; /* bogus! */
369 /* Convert the handle to a table pointer. */
370 tab
= handle2ptr(tbl
);
372 return 0; /* error */
375 /* Compute the hash bucket and try to find an existing node. */
376 bucket
= do_hash(tab
,key
);
377 node
= find_node(tab
,key
,bucket
);
379 { /* look to unchain it from the bucket it's in */
380 if (node
==tab
->buckets
[bucket
])
381 tab
->buckets
[bucket
] = node
->next
; /* unchain at head */
383 { /* unchain in middle of list */
384 for (p
=tab
->buckets
[bucket
]; p
->next
!=node
; p
=p
->next
) ;
385 p
->next
= node
->next
;
389 free_node(node
); /* bye bye now! */
393 else /* node not found */
398 } /* end ghash_remove */
400 int ghash_walk(HASHTABLE tbl
, TABLEWALKFUNC func
, void *user_data
)
403 "Walks" through a hash table, calling a callback function for each element
408 tbl - Hash table to walk.
409 func - Function to be called for each node. It takes three parameters,
410 a user data pointer, a key value pointer, and a data value pointer.
411 It returns 0 to stop the enumeration or 1 to keep it going.
412 user_data - Value to use as the first parameter for the callback
418 Other - Number of nodes visited up to and including the one for which
419 the callback function returned 0, if it did; ranges from 1
420 to the number of nodes in the hashtable.
423 HASHTABLE_INTERNAL
*tab
; /* internal table pointer */
424 int i
; /* loop counter */
425 int running
= 1; /* we're still running */
426 int count
= 0; /* number of nodes visited before stop node */
427 register HNODE
*p
, *p2
; /* loop pointer */
430 return -1; /* bogus values! */
432 /* Convert the handle to a table pointer. */
433 tab
= handle2ptr(tbl
);
435 return -1; /* error */
438 for (i
=0; running
&& (i
<tab
->bcount
); i
++)
439 { /* visit the contents of each bucket */
442 { /* visit each node in turn */
445 running
= (*func
)(user_data
,p
->key
,p
->value
);
454 } /* end ghash_walk */
456 int str_hash_code(const char *s
)
459 Generates a hash code for a string. This function uses the ELF hashing
460 algorithm as reprinted in Andrew Binstock, "Hashing Rehashed," _Dr.
461 Dobb's Journal_, April 1996.
465 s - The string to be hashed.
469 A hash code for the string.
472 /* ELF hash uses unsigned chars and unsigned arithmetic for portability */
473 const unsigned char *name
= (const unsigned char *)s
;
474 unsigned long h
= 0, g
;
477 return 0; /* anti-NULL guard not in the original */
480 { /* do some fancy bitwanking on the string */
481 h
= (h
<< 4) + (unsigned long)(*name
++);
482 if ((g
= (h
& 0xF0000000UL
))!=0)