blob: 08eebb819535071497e7b09a7c4903abe13e2339 [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 Tarreaue3ba5f02006-06-29 18:54:54 +020021#include <common/config.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020022#include <common/list.h>
23#include <common/chtbl.h>
willy tarreau12350152005-12-18 01:03:27 +010024
25/*****************************************************************************
26 * *
27 * ------------------------------ chtbl_init ------------------------------ *
28 * *
29 *****************************************************************************/
30
31int chtbl_init(CHTbl *htbl, int buckets, int (*h)(const void *key), int
32 (*match)(const void *key1, const void *key2), void (*destroy)(void*data)) {
33
Willy Tarreaubaaee002006-06-26 02:48:02 +020034 int i;
willy tarreau12350152005-12-18 01:03:27 +010035
Willy Tarreaubaaee002006-06-26 02:48:02 +020036 /*****************************************************************************
37 * *
38 * Allocate space for the hash table. *
39 * *
40 *****************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +010041
Willy Tarreaubaaee002006-06-26 02:48:02 +020042 if ((htbl->table = (List *)malloc(buckets * sizeof(List))) == NULL)
43 return -1;
willy tarreau12350152005-12-18 01:03:27 +010044
Willy Tarreaubaaee002006-06-26 02:48:02 +020045 /*****************************************************************************
46 * *
47 * Initialize the buckets. *
48 * *
49 *****************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +010050
Willy Tarreaubaaee002006-06-26 02:48:02 +020051 htbl->buckets = buckets;
willy tarreau12350152005-12-18 01:03:27 +010052
Willy Tarreaubaaee002006-06-26 02:48:02 +020053 for (i = 0; i < htbl->buckets; i++)
54 list_init(&htbl->table[i], destroy);
willy tarreau12350152005-12-18 01:03:27 +010055
Willy Tarreaubaaee002006-06-26 02:48:02 +020056 /*****************************************************************************
57 * *
58 * Encapsulate the functions. *
59 * *
60 *****************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +010061
Willy Tarreaubaaee002006-06-26 02:48:02 +020062 htbl->h = h;
63 htbl->match = match;
64 htbl->destroy = destroy;
willy tarreau12350152005-12-18 01:03:27 +010065
Willy Tarreaubaaee002006-06-26 02:48:02 +020066 /*****************************************************************************
67 * *
68 * Initialize the number of elements in the table. *
69 * *
70 *****************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +010071
Willy Tarreaubaaee002006-06-26 02:48:02 +020072 htbl->size = 0;
willy tarreau12350152005-12-18 01:03:27 +010073
Willy Tarreaubaaee002006-06-26 02:48:02 +020074 return 0;
willy tarreau12350152005-12-18 01:03:27 +010075} /* end chtbl_init () */
76
77/*****************************************************************************
78 * *
79 * ---------------------------- chtbl_destroy ----------------------------- *
80 * *
81 *****************************************************************************/
82
83void chtbl_destroy(CHTbl *htbl) {
84
Willy Tarreaubaaee002006-06-26 02:48:02 +020085 int i;
willy tarreau12350152005-12-18 01:03:27 +010086
Willy Tarreaubaaee002006-06-26 02:48:02 +020087 /*****************************************************************************
88 * *
89 * Destroy each bucket. *
90 * *
91 *****************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +010092
Willy Tarreaubaaee002006-06-26 02:48:02 +020093 for (i = 0; i < htbl->buckets; i++) {
94 list_destroy(&htbl->table[i]);
95 } /* end for () */
willy tarreau12350152005-12-18 01:03:27 +010096
Willy Tarreaubaaee002006-06-26 02:48:02 +020097 /*****************************************************************************
98 * *
99 * Free the storage allocated for the hash table. *
100 * *
101 *****************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100102
Willy Tarreaubaaee002006-06-26 02:48:02 +0200103 free(htbl->table);
willy tarreau12350152005-12-18 01:03:27 +0100104
Willy Tarreaubaaee002006-06-26 02:48:02 +0200105 /*****************************************************************************
106 * *
107 * No operations are allowed now, but clear the structure as a precaution. *
108 * *
109 *****************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100110
Willy Tarreaubaaee002006-06-26 02:48:02 +0200111 memset(htbl, 0, sizeof(CHTbl));
willy tarreau12350152005-12-18 01:03:27 +0100112
Willy Tarreaubaaee002006-06-26 02:48:02 +0200113 return;
willy tarreau12350152005-12-18 01:03:27 +0100114} /* end chtbl_destroy() */
115
116/*****************************************************************************
117 * *
118 * ----------------------------- chtbl_insert ----------------------------- *
119 * *
120 *****************************************************************************/
121
122int chtbl_insert(CHTbl *htbl, const void *data) {
123
Willy Tarreaubaaee002006-06-26 02:48:02 +0200124 void *temp;
125 int bucket,retval;
willy tarreau12350152005-12-18 01:03:27 +0100126
Willy Tarreaubaaee002006-06-26 02:48:02 +0200127 /*****************************************************************************
128 * *
129 * Do nothing if the data is already in the table. *
130 * *
131 *****************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100132
Willy Tarreaubaaee002006-06-26 02:48:02 +0200133 temp = (void *)data;
willy tarreau12350152005-12-18 01:03:27 +0100134
Willy Tarreaubaaee002006-06-26 02:48:02 +0200135 if (chtbl_lookup(htbl, &temp) == 0)
136 return 1;
willy tarreau12350152005-12-18 01:03:27 +0100137
Willy Tarreaubaaee002006-06-26 02:48:02 +0200138 /*****************************************************************************
139 * *
140 * Hash the key. *
141 * *
142 *****************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100143
Willy Tarreaubaaee002006-06-26 02:48:02 +0200144 bucket = htbl->h(data) % htbl->buckets;
willy tarreau12350152005-12-18 01:03:27 +0100145
Willy Tarreaubaaee002006-06-26 02:48:02 +0200146 /*****************************************************************************
147 * *
148 * Insert the data into the bucket. *
149 * *
150 *****************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100151
Willy Tarreaubaaee002006-06-26 02:48:02 +0200152 if ((retval = list_ins_next(&htbl->table[bucket], NULL, data)) == 0)
153 htbl->size++;
willy tarreau12350152005-12-18 01:03:27 +0100154
Willy Tarreaubaaee002006-06-26 02:48:02 +0200155 return retval;
willy tarreau12350152005-12-18 01:03:27 +0100156} /* end chtbl_insert() */
157
158/*****************************************************************************
159 * *
160 * ----------------------------- chtbl_remove ----------------------------- *
161 * *
162 *****************************************************************************/
163
164int chtbl_remove(CHTbl *htbl, void **data) {
165
Willy Tarreaubaaee002006-06-26 02:48:02 +0200166 ListElmt *element, *prev;
167 int bucket;
willy tarreau12350152005-12-18 01:03:27 +0100168
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169 /*********************************************************************
170 * *
171 * Hash the key. *
172 * *
173 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100174
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175 bucket = htbl->h(*data) % htbl->buckets;
willy tarreau12350152005-12-18 01:03:27 +0100176
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177 /*********************************************************************
178 * *
179 * Search for the data in the bucket. *
180 * *
181 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100182
Willy Tarreaubaaee002006-06-26 02:48:02 +0200183 prev = NULL;
willy tarreau12350152005-12-18 01:03:27 +0100184
Willy Tarreaubaaee002006-06-26 02:48:02 +0200185 for (element = list_head(&htbl->table[bucket]);
186 element != NULL; element = list_next(element)) {
187 if (htbl->match(*data, list_data(element))) {
willy tarreau12350152005-12-18 01:03:27 +0100188
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189 /*****************************************************
190 * *
191 * Remove the data from the bucket. *
192 * *
193 *****************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100194
Willy Tarreaubaaee002006-06-26 02:48:02 +0200195 if (list_rem_next(&htbl->table[bucket], prev, data) == 0) {
196 htbl->size--;
197 return 0;
198 } /* end if() */
199 else {
200 return -1;
201 }/* end else */
202 }/* end if (htbl->match(*data, list_data(element))) */
willy tarreau12350152005-12-18 01:03:27 +0100203
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204 prev = element;
205 }/* end for() */
willy tarreau12350152005-12-18 01:03:27 +0100206
Willy Tarreaubaaee002006-06-26 02:48:02 +0200207 /*********************************************************************
208 * *
209 * Return that the data was not found. *
210 * *
211 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100212
Willy Tarreaubaaee002006-06-26 02:48:02 +0200213 return -1;
willy tarreau12350152005-12-18 01:03:27 +0100214} /* end int chtbl_remove(CHTbl *htbl, void **data) */
215
216/*****************************************************************************
217 * *
218 * ----------------------------- chtbl_lookup ----------------------------- *
219 * *
220 *****************************************************************************/
221
222int chtbl_lookup(const CHTbl *htbl, void **data) {
223
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 ListElmt *element;
225 int bucket;
willy tarreau12350152005-12-18 01:03:27 +0100226
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 /*********************************************************************
228 * *
229 * Hash the key. *
230 * *
231 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100232
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 bucket = htbl->h(*data) % htbl->buckets;
willy tarreau12350152005-12-18 01:03:27 +0100234
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235 /*********************************************************************
236 * *
237 * Search for the data in the bucket. *
238 * *
239 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100240
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241 for (element = list_head(&htbl->table[bucket]);
242 element != NULL; element = list_next(element)) {
243 if (htbl->match(*data, list_data(element))) {
willy tarreau12350152005-12-18 01:03:27 +0100244
Willy Tarreaubaaee002006-06-26 02:48:02 +0200245 /*****************************************************
246 * *
247 * Pass back the data from the table. *
248 * *
249 *****************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100250
Willy Tarreaubaaee002006-06-26 02:48:02 +0200251 *data = list_data(element);
252 return 0;
253 }/* end if() */
254 }/* end for() */
willy tarreau12350152005-12-18 01:03:27 +0100255
Willy Tarreaubaaee002006-06-26 02:48:02 +0200256 /*********************************************************************
257 * *
258 * Return that the data was not found. *
259 * *
260 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100261
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262 return -1;
willy tarreau12350152005-12-18 01:03:27 +0100263} /* end chtbl_lookup() */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200264
265/*
266 * Local variables:
267 * c-indent-level: 8
268 * c-basic-offset: 8
269 * End:
270 */