haproxy/src/chtbl.c

261 lines
12 KiB
C

/*
This File is copied from
http://www.oreilly.com/catalog/masteralgoc/index.html
Mastering Algorithms with C
By Kyle Loudon
ISBN: 1-56592-453-3
Publishd by O'Reilly
*/
/*****************************************************************************
* *
* ------------------------------- chtbl.c -------------------------------- *
* *
*****************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <include/list.h>
#include <include/chtbl.h>
/*****************************************************************************
* *
* ------------------------------ chtbl_init ------------------------------ *
* *
*****************************************************************************/
int chtbl_init(CHTbl *htbl, int buckets, int (*h)(const void *key), int
(*match)(const void *key1, const void *key2), void (*destroy)(void*data)) {
int i;
/*****************************************************************************
* *
* Allocate space for the hash table. *
* *
*****************************************************************************/
if ((htbl->table = (List *)malloc(buckets * sizeof(List))) == NULL)
return -1;
/*****************************************************************************
* *
* Initialize the buckets. *
* *
*****************************************************************************/
htbl->buckets = buckets;
for (i = 0; i < htbl->buckets; i++)
list_init(&htbl->table[i], destroy);
/*****************************************************************************
* *
* Encapsulate the functions. *
* *
*****************************************************************************/
htbl->h = h;
htbl->match = match;
htbl->destroy = destroy;
/*****************************************************************************
* *
* Initialize the number of elements in the table. *
* *
*****************************************************************************/
htbl->size = 0;
return 0;
} /* end chtbl_init () */
/*****************************************************************************
* *
* ---------------------------- chtbl_destroy ----------------------------- *
* *
*****************************************************************************/
void chtbl_destroy(CHTbl *htbl) {
int i;
/*****************************************************************************
* *
* Destroy each bucket. *
* *
*****************************************************************************/
for (i = 0; i < htbl->buckets; i++) {
list_destroy(&htbl->table[i]);
} /* end for () */
/*****************************************************************************
* *
* Free the storage allocated for the hash table. *
* *
*****************************************************************************/
free(htbl->table);
/*****************************************************************************
* *
* No operations are allowed now, but clear the structure as a precaution. *
* *
*****************************************************************************/
memset(htbl, 0, sizeof(CHTbl));
return;
} /* end chtbl_destroy() */
/*****************************************************************************
* *
* ----------------------------- chtbl_insert ----------------------------- *
* *
*****************************************************************************/
int chtbl_insert(CHTbl *htbl, const void *data) {
void *temp;
int bucket,retval;
/*****************************************************************************
* *
* Do nothing if the data is already in the table. *
* *
*****************************************************************************/
temp = (void *)data;
if (chtbl_lookup(htbl, &temp) == 0)
return 1;
/*****************************************************************************
* *
* Hash the key. *
* *
*****************************************************************************/
bucket = htbl->h(data) % htbl->buckets;
/*****************************************************************************
* *
* Insert the data into the bucket. *
* *
*****************************************************************************/
if ((retval = list_ins_next(&htbl->table[bucket], NULL, data)) == 0)
htbl->size++;
return retval;
} /* end chtbl_insert() */
/*****************************************************************************
* *
* ----------------------------- chtbl_remove ----------------------------- *
* *
*****************************************************************************/
int chtbl_remove(CHTbl *htbl, void **data) {
ListElmt *element, *prev;
int bucket;
/*****************************************************************************
* *
* Hash the key. *
* *
*****************************************************************************/
bucket = htbl->h(*data) % htbl->buckets;
/*****************************************************************************
* *
* Search for the data in the bucket. *
* *
*****************************************************************************/
prev = NULL;
for (element = list_head(&htbl->table[bucket]); element != NULL; element = list_next(element)) {
if (htbl->match(*data, list_data(element))) {
/***********************************************************************
* *
* Remove the data from the bucket. *
* *
***********************************************************************/
if (list_rem_next(&htbl->table[bucket], prev, data) == 0) {
htbl->size--;
return 0;
} /* end if() */
else {
return -1;
}/* end else */
}/* end if (htbl->match(*data, list_data(element))) */
prev = element;
}/* end for() */
/*****************************************************************************
* *
* Return that the data was not found. *
* *
*****************************************************************************/
return -1;
} /* end int chtbl_remove(CHTbl *htbl, void **data) */
/*****************************************************************************
* *
* ----------------------------- chtbl_lookup ----------------------------- *
* *
*****************************************************************************/
int chtbl_lookup(const CHTbl *htbl, void **data) {
ListElmt *element;
int bucket;
/*****************************************************************************
* *
* Hash the key. *
* *
*****************************************************************************/
bucket = htbl->h(*data) % htbl->buckets;
/*****************************************************************************
* *
* Search for the data in the bucket. *
* *
*****************************************************************************/
for (element = list_head(&htbl->table[bucket]); element != NULL; element = list_next(element)) {
if (htbl->match(*data, list_data(element))) {
/***********************************************************************
* *
* Pass back the data from the table. *
* *
***********************************************************************/
*data = list_data(element);
return 0;
}/* end if() */
}/* end for() */
/*****************************************************************************
* *
* Return that the data was not found. *
* *
*****************************************************************************/
return -1;
} /* end chtbl_lookup() */