blob: c8e794fd389602ebcbaabb7739a38857aaa2d96a [file] [log] [blame]
willy tarreau12350152005-12-18 01:03:27 +01001/*
2 This File is copied from
3
4 http://www.oreilly.com/catalog/masteralgoc/index.html
5 Mastering Algorithms with C
6 By Kyle Loudon
7 ISBN: 1-56592-453-3
8 Publishd by O'Reilly
9
10 */
11
12/*****************************************************************************
13 * *
14 * ------------------------------- chtbl.c -------------------------------- *
15 * *
16 *****************************************************************************/
17
18#include <stdlib.h>
19#include <string.h>
20
Willy Tarreaubaaee002006-06-26 02:48:02 +020021#include <haproxy/list.h>
22#include <haproxy/chtbl.h>
willy tarreau12350152005-12-18 01:03:27 +010023
24/*****************************************************************************
25 * *
26 * ------------------------------ chtbl_init ------------------------------ *
27 * *
28 *****************************************************************************/
29
30int chtbl_init(CHTbl *htbl, int buckets, int (*h)(const void *key), int
31 (*match)(const void *key1, const void *key2), void (*destroy)(void*data)) {
32
Willy Tarreaubaaee002006-06-26 02:48:02 +020033 int i;
willy tarreau12350152005-12-18 01:03:27 +010034
Willy Tarreaubaaee002006-06-26 02:48:02 +020035 /*****************************************************************************
36 * *
37 * Allocate space for the hash table. *
38 * *
39 *****************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +010040
Willy Tarreaubaaee002006-06-26 02:48:02 +020041 if ((htbl->table = (List *)malloc(buckets * sizeof(List))) == NULL)
42 return -1;
willy tarreau12350152005-12-18 01:03:27 +010043
Willy Tarreaubaaee002006-06-26 02:48:02 +020044 /*****************************************************************************
45 * *
46 * Initialize the buckets. *
47 * *
48 *****************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +010049
Willy Tarreaubaaee002006-06-26 02:48:02 +020050 htbl->buckets = buckets;
willy tarreau12350152005-12-18 01:03:27 +010051
Willy Tarreaubaaee002006-06-26 02:48:02 +020052 for (i = 0; i < htbl->buckets; i++)
53 list_init(&htbl->table[i], destroy);
willy tarreau12350152005-12-18 01:03:27 +010054
Willy Tarreaubaaee002006-06-26 02:48:02 +020055 /*****************************************************************************
56 * *
57 * Encapsulate the functions. *
58 * *
59 *****************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +010060
Willy Tarreaubaaee002006-06-26 02:48:02 +020061 htbl->h = h;
62 htbl->match = match;
63 htbl->destroy = destroy;
willy tarreau12350152005-12-18 01:03:27 +010064
Willy Tarreaubaaee002006-06-26 02:48:02 +020065 /*****************************************************************************
66 * *
67 * Initialize the number of elements in the table. *
68 * *
69 *****************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +010070
Willy Tarreaubaaee002006-06-26 02:48:02 +020071 htbl->size = 0;
willy tarreau12350152005-12-18 01:03:27 +010072
Willy Tarreaubaaee002006-06-26 02:48:02 +020073 return 0;
willy tarreau12350152005-12-18 01:03:27 +010074} /* end chtbl_init () */
75
76/*****************************************************************************
77 * *
78 * ---------------------------- chtbl_destroy ----------------------------- *
79 * *
80 *****************************************************************************/
81
82void chtbl_destroy(CHTbl *htbl) {
83
Willy Tarreaubaaee002006-06-26 02:48:02 +020084 int i;
willy tarreau12350152005-12-18 01:03:27 +010085
Willy Tarreaubaaee002006-06-26 02:48:02 +020086 /*****************************************************************************
87 * *
88 * Destroy each bucket. *
89 * *
90 *****************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +010091
Willy Tarreaubaaee002006-06-26 02:48:02 +020092 for (i = 0; i < htbl->buckets; i++) {
93 list_destroy(&htbl->table[i]);
94 } /* end for () */
willy tarreau12350152005-12-18 01:03:27 +010095
Willy Tarreaubaaee002006-06-26 02:48:02 +020096 /*****************************************************************************
97 * *
98 * Free the storage allocated for the hash table. *
99 * *
100 *****************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100101
Willy Tarreaubaaee002006-06-26 02:48:02 +0200102 free(htbl->table);
willy tarreau12350152005-12-18 01:03:27 +0100103
Willy Tarreaubaaee002006-06-26 02:48:02 +0200104 /*****************************************************************************
105 * *
106 * No operations are allowed now, but clear the structure as a precaution. *
107 * *
108 *****************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100109
Willy Tarreaubaaee002006-06-26 02:48:02 +0200110 memset(htbl, 0, sizeof(CHTbl));
willy tarreau12350152005-12-18 01:03:27 +0100111
Willy Tarreaubaaee002006-06-26 02:48:02 +0200112 return;
willy tarreau12350152005-12-18 01:03:27 +0100113} /* end chtbl_destroy() */
114
115/*****************************************************************************
116 * *
117 * ----------------------------- chtbl_insert ----------------------------- *
118 * *
119 *****************************************************************************/
120
121int chtbl_insert(CHTbl *htbl, const void *data) {
122
Willy Tarreaubaaee002006-06-26 02:48:02 +0200123 void *temp;
124 int bucket,retval;
willy tarreau12350152005-12-18 01:03:27 +0100125
Willy Tarreaubaaee002006-06-26 02:48:02 +0200126 /*****************************************************************************
127 * *
128 * Do nothing if the data is already in the table. *
129 * *
130 *****************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100131
Willy Tarreaubaaee002006-06-26 02:48:02 +0200132 temp = (void *)data;
willy tarreau12350152005-12-18 01:03:27 +0100133
Willy Tarreaubaaee002006-06-26 02:48:02 +0200134 if (chtbl_lookup(htbl, &temp) == 0)
135 return 1;
willy tarreau12350152005-12-18 01:03:27 +0100136
Willy Tarreaubaaee002006-06-26 02:48:02 +0200137 /*****************************************************************************
138 * *
139 * Hash the key. *
140 * *
141 *****************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100142
Willy Tarreaubaaee002006-06-26 02:48:02 +0200143 bucket = htbl->h(data) % htbl->buckets;
willy tarreau12350152005-12-18 01:03:27 +0100144
Willy Tarreaubaaee002006-06-26 02:48:02 +0200145 /*****************************************************************************
146 * *
147 * Insert the data into the bucket. *
148 * *
149 *****************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100150
Willy Tarreaubaaee002006-06-26 02:48:02 +0200151 if ((retval = list_ins_next(&htbl->table[bucket], NULL, data)) == 0)
152 htbl->size++;
willy tarreau12350152005-12-18 01:03:27 +0100153
Willy Tarreaubaaee002006-06-26 02:48:02 +0200154 return retval;
willy tarreau12350152005-12-18 01:03:27 +0100155} /* end chtbl_insert() */
156
157/*****************************************************************************
158 * *
159 * ----------------------------- chtbl_remove ----------------------------- *
160 * *
161 *****************************************************************************/
162
163int chtbl_remove(CHTbl *htbl, void **data) {
164
Willy Tarreaubaaee002006-06-26 02:48:02 +0200165 ListElmt *element, *prev;
166 int bucket;
willy tarreau12350152005-12-18 01:03:27 +0100167
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168 /*********************************************************************
169 * *
170 * Hash the key. *
171 * *
172 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100173
Willy Tarreaubaaee002006-06-26 02:48:02 +0200174 bucket = htbl->h(*data) % htbl->buckets;
willy tarreau12350152005-12-18 01:03:27 +0100175
Willy Tarreaubaaee002006-06-26 02:48:02 +0200176 /*********************************************************************
177 * *
178 * Search for the data in the bucket. *
179 * *
180 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100181
Willy Tarreaubaaee002006-06-26 02:48:02 +0200182 prev = NULL;
willy tarreau12350152005-12-18 01:03:27 +0100183
Willy Tarreaubaaee002006-06-26 02:48:02 +0200184 for (element = list_head(&htbl->table[bucket]);
185 element != NULL; element = list_next(element)) {
186 if (htbl->match(*data, list_data(element))) {
willy tarreau12350152005-12-18 01:03:27 +0100187
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188 /*****************************************************
189 * *
190 * Remove the data from the bucket. *
191 * *
192 *****************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100193
Willy Tarreaubaaee002006-06-26 02:48:02 +0200194 if (list_rem_next(&htbl->table[bucket], prev, data) == 0) {
195 htbl->size--;
196 return 0;
197 } /* end if() */
198 else {
199 return -1;
200 }/* end else */
201 }/* end if (htbl->match(*data, list_data(element))) */
willy tarreau12350152005-12-18 01:03:27 +0100202
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203 prev = element;
204 }/* end for() */
willy tarreau12350152005-12-18 01:03:27 +0100205
Willy Tarreaubaaee002006-06-26 02:48:02 +0200206 /*********************************************************************
207 * *
208 * Return that the data was not found. *
209 * *
210 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100211
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212 return -1;
willy tarreau12350152005-12-18 01:03:27 +0100213} /* end int chtbl_remove(CHTbl *htbl, void **data) */
214
215/*****************************************************************************
216 * *
217 * ----------------------------- chtbl_lookup ----------------------------- *
218 * *
219 *****************************************************************************/
220
221int chtbl_lookup(const CHTbl *htbl, void **data) {
222
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 ListElmt *element;
224 int bucket;
willy tarreau12350152005-12-18 01:03:27 +0100225
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 /*********************************************************************
227 * *
228 * Hash the key. *
229 * *
230 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100231
Willy Tarreaubaaee002006-06-26 02:48:02 +0200232 bucket = htbl->h(*data) % htbl->buckets;
willy tarreau12350152005-12-18 01:03:27 +0100233
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234 /*********************************************************************
235 * *
236 * Search for the data in the bucket. *
237 * *
238 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100239
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240 for (element = list_head(&htbl->table[bucket]);
241 element != NULL; element = list_next(element)) {
242 if (htbl->match(*data, list_data(element))) {
willy tarreau12350152005-12-18 01:03:27 +0100243
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244 /*****************************************************
245 * *
246 * Pass back the data from the table. *
247 * *
248 *****************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100249
Willy Tarreaubaaee002006-06-26 02:48:02 +0200250 *data = list_data(element);
251 return 0;
252 }/* end if() */
253 }/* end for() */
willy tarreau12350152005-12-18 01:03:27 +0100254
Willy Tarreaubaaee002006-06-26 02:48:02 +0200255 /*********************************************************************
256 * *
257 * Return that the data was not found. *
258 * *
259 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100260
Willy Tarreaubaaee002006-06-26 02:48:02 +0200261 return -1;
willy tarreau12350152005-12-18 01:03:27 +0100262} /* end chtbl_lookup() */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263
264/*
265 * Local variables:
266 * c-indent-level: 8
267 * c-basic-offset: 8
268 * End:
269 */