Fix comment in previous commit
[eleutheria.git] / genstructs / htable / htable.c
blob380638a05811b0fc2655c4d4dbf4504d253b2918
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/queue.h>
6 #include "htable.h"
8 void htable_init(htable_t *htable, size_t size)
10 u_int i;
12 /* Allocate memory for `size' tailq headers */
13 if ((htable->ht_table = malloc(size * sizeof *htable->ht_table)) == NULL) {
14 perror("malloc");
15 exit(EXIT_FAILURE);
18 /* Initialize tailqs */
19 for (i = 0; i < size; i++)
20 TAILQ_INIT(&htable->ht_table[i]);
22 htable->ht_size = size; /* size must be a power of 2 */
23 htable->ht_used = 0;
26 void htable_insert(htable_t *htable, const void *key, void *data)
28 struct htablehead *phead;
29 hnode_t *pnode;
30 u_int hash;
32 /* Calculate hash */
33 hash = htable->ht_hashf(key);
35 /* Search across chain if there is already an entry
36 with the same key. If there is, replace it. */
37 phead = &htable->ht_table[hash & (htable->ht_size - 1)];
38 TAILQ_FOREACH(pnode, phead, hn_next)
39 if (htable->ht_cmpf(pnode->hn_key, key) == 0) {
40 pnode->hn_data = data;
41 return;
44 /* Allocate memory for new entry */
45 if ((pnode = malloc(sizeof *pnode)) == NULL)
46 return;
47 pnode->hn_key = key;
48 pnode->hn_data = data;
50 TAILQ_INSERT_TAIL(phead, pnode, hn_next);
51 htable->ht_used++;
54 void htable_delete(htable_t *htable, const void *key)
56 struct htablehead *phead;
57 hnode_t *pnode;
58 u_int hash;
60 /* Calculate hash */
61 hash = htable->ht_hashf(key);
63 /* Search across chain if there is an entry with the
64 key we are looking. If there is, delete it. */
65 phead = &htable->ht_table[hash & (htable->ht_size - 1)];
67 TAILQ_FOREACH(pnode, phead, hn_next)
68 if (htabl->ht_cmpf(pnode->hn_key, key) == 0) {
69 TAILQ_REMOVE(phead, pnode, hn_next);
70 return;
74 void *htable_search(const htable_t *htable, const void *key)
76 hnode_t *pnode;
77 u_int hash;
79 /* Calculate hash */
80 hash = htable->ht_hashf(key);
82 TAILQ_FOREACH(pnode, &htable->ht_table[hash & (htable->ht_size - 1)], hn_next)
83 if (htable->ht_cmpf(pnode->hn_key, key) == 0)
84 return pnode->hn_data;
86 return NULL;
89 void htable_print(const htable_t *htable)
91 const hnode_t *pnode;
92 u_int i;
94 for (i = 0; i < htable->ht_size; i++) {
95 TAILQ_FOREACH(pnode, &htable->ht_table[i], hn_next)
96 htable->ht_printf(pnode->hn_key, pnode->hn_data);
97 if (TAILQ_FIRST(&htable->ht_table[i]) != NULL)
98 printf("\n");
102 u_int djb_hash(const void *key)
104 /* DJB hashing */
105 u_int i, hash = 5381;
107 for (i = 0; i < strlen((char*)key); i++)
108 hash = ((hash << 5) + hash) + ((char*)key)[i];
110 return (hash & 0x7FFFFFFF);
113 int mycmp(const void *arg1, const void *arg2)
115 return (strcmp((char *) arg1, (char *) arg2));
118 void myprintf(const void *key, const void *data)
120 printf("%s(%s) ", (char *)key, (char *)data);
123 int main(void)
125 htable_t ptable;
127 /* Initialize table */
128 htable_init(&ptable, 10);
130 /* Setup callback functions */
131 ptable.ht_hashf = djb_hash;
132 ptable.ht_cmpf = mycmp;
133 ptable.ht_printf = myprintf;
135 htable_insert(&ptable, "stathis", "stathis");
136 htable_insert(&ptable, "maria", "maria");
137 htable_insert(&ptable, "kostas", "kostas");
138 htable_insert(&ptable, "panagiotopoulos", "panagiotopoulos");
139 htable_insert(&ptable, "eleni", "eleni");
141 htable_print(&ptable);
143 return EXIT_SUCCESS;