#include <stdlib.h>#include <stdio.h>#include <string.h>#include "icl_hash.h"#include <limits.h>
Go to the source code of this file.
Defines | |
| #define | BITS_IN_int ( sizeof(int) * CHAR_BIT ) |
| #define | THREE_QUARTERS ((int) ((BITS_IN_int * 3) / 4)) |
| #define | ONE_EIGHTH ((int) (BITS_IN_int / 8)) |
| #define | HIGH_BITS ( ~((unsigned int)(~0) >> ONE_EIGHTH )) |
Functions | |
| static long | hash_pjw (char *datum) |
| icl_hash_t * | icl_hash_create (int nbuckets, long(*hash_function)(char *)) |
| void * | icl_hash_find (icl_hash_t *ht, char *key) |
| icl_entry_t * | icl_hash_insert (icl_hash_t *ht, char *key, void *data) |
| icl_entry_t * | icl_hash_update_insert (icl_hash_t *ht, char *key, void *data, void **olddata) |
| int | icl_hash_destroy (icl_hash_t *ht, void(*free_key)(void *), void(*free_data)(void *)) |
| int | icl_hash_dump (FILE *stream, icl_hash_t *ht) |
Dependency free hash table implementation.
This simple hash table implementation should be easy to drop into any other peice of code, it does not depend on anything else :-)
Definition in file icl_hash.c.
| #define BITS_IN_int ( sizeof(int) * CHAR_BIT ) |
Definition at line 19 of file icl_hash.c.
| #define HIGH_BITS ( ~((unsigned int)(~0) >> ONE_EIGHTH )) |
Definition at line 22 of file icl_hash.c.
| #define ONE_EIGHTH ((int) (BITS_IN_int / 8)) |
Definition at line 21 of file icl_hash.c.
| #define THREE_QUARTERS ((int) ((BITS_IN_int * 3) / 4)) |
Definition at line 20 of file icl_hash.c.
| static long hash_pjw | ( | char * | datum | ) | [static] |
A simple string hash.
An adaptation of Peter Weinberger's (PJW) generic hashing algorithm based on Allen Holub's version. Accepts a pointer to a datum to be hashed and returns an unsigned integer. From: Keith Seymour's proxy library code
| datum | -- the string to be hashed |
Definition at line 38 of file icl_hash.c.
{
long hash_value, i;
if(!datum) return 0;
for (hash_value = 0; *datum; ++datum) {
hash_value = (hash_value << ONE_EIGHTH) + *datum;
if ((i = hash_value & HIGH_BITS) != 0)
hash_value = (hash_value ^ (i >> THREE_QUARTERS)) & ~HIGH_BITS;
}
return (hash_value);
}

| icl_hash_t* icl_hash_create | ( | int | nbuckets, | |
| long(*)(char *) | hash_function | |||
| ) |
Create a new hash table.
| nbuckets | -- number of buckets to create | |
| hash_function | -- pointer to the hashing function to be used |
Definition at line 62 of file icl_hash.c.
{
icl_hash_t *ht;
int i;
ht = (icl_hash_t*) malloc(sizeof(icl_hash_t));
if(!ht) return NULL;
ht->nentries = 0;
ht->buckets = (icl_entry_t**)malloc(nbuckets * sizeof(icl_entry_t*));
if(!ht->buckets) return NULL;
ht->nbuckets = nbuckets;
for(i=0;i<ht->nbuckets;i++)
ht->buckets[i] = NULL;
ht->hash_function = hash_function ? hash_function : hash_pjw;
return ht;
}


| int icl_hash_destroy | ( | icl_hash_t * | ht, | |
| void(*)(void *) | free_key, | |||
| void(*)(void *) | free_data | |||
| ) |
Free hash table structures (key and data are freed using functions).
| ht | -- the hash table to be freed | |
| free_key | -- pointer to function that frees the key | |
| free_data | -- pointer to function that frees the data |
Definition at line 212 of file icl_hash.c.
{
icl_entry_t *bucket, *curr, *next;
int i;
if(!ht) return -1;
for (i=0; i<ht->nbuckets; i++) {
bucket = ht->buckets[i];
for (curr=bucket; curr!=NULL; ) {
next=curr->next;
if (*free_key && curr->key) (*free_key)(curr->key);
if (*free_data && curr->data) (*free_data)(curr->data);
free(curr);
curr=next;
}
}
if(ht->buckets) free(ht->buckets);
if(ht) free(ht);
return 0;
}

| int icl_hash_dump | ( | FILE * | stream, | |
| icl_hash_t * | ht | |||
| ) |
Dump the hash table's contents to the given file pointer.
| stream | -- the file to which the hash table should be dumped | |
| ht | -- the hash table to be dumped |
Definition at line 246 of file icl_hash.c.
{
icl_entry_t *bucket, *curr;
int i;
if(!ht) return -1;
for(i=0; i<ht->nbuckets; i++) {
bucket = ht->buckets[i];
for(curr=bucket; curr!=NULL; ) {
if(curr->key)
fprintf(stream, "icl_hash_dump: %s: %p\n", curr->key, curr->data);
curr=curr->next;
}
}
return 0;
}


| void* icl_hash_find | ( | icl_hash_t * | ht, | |
| char * | key | |||
| ) |
Search for an entry in a hash table.
| ht | -- the hash table to be searched | |
| key | -- the key of the item to search for |
Definition at line 94 of file icl_hash.c.
{
icl_entry_t* curr;
long hash_val;
if(!ht || !key) return NULL;
hash_val = (* ht->hash_function)(key) % ht->nbuckets;
for (curr=ht->buckets[hash_val]; curr != NULL; curr=curr->next)
if (strcmp(curr->key, key) == 0)
return(curr->data);
return NULL;
}

| icl_entry_t* icl_hash_insert | ( | icl_hash_t * | ht, | |
| char * | key, | |||
| void * | data | |||
| ) |
Insert an item into the hash table.
| ht | -- the hash table | |
| key | -- the key of the new item | |
| data | -- pointer to the new item's data |
Definition at line 121 of file icl_hash.c.
{
icl_entry_t *curr, *prev;
long hash_val;
if(!ht || !key) return NULL;
hash_val = (* ht->hash_function)(key) % ht->nbuckets;
for (prev=NULL,curr=ht->buckets[hash_val]; curr != NULL; prev=curr, curr=curr->next)
if (strcmp(curr->key, key) == 0)
return(NULL); /* key already exists */
/* if key was not found */
curr = (icl_entry_t*)malloc(sizeof(icl_entry_t));
if(!curr) return NULL;
curr->key = key;
curr->data = data;
curr->next = ht->buckets[hash_val]; /* add at start */
ht->buckets[hash_val] = curr;
ht->nentries++;
return curr;
}

| icl_entry_t* icl_hash_update_insert | ( | icl_hash_t * | ht, | |
| char * | key, | |||
| void * | data, | |||
| void ** | olddata | |||
| ) |
Replace entry in hash table with the given entry.
| ht | -- the hash table | |
| key | -- the key of the new item | |
| data | -- pointer to the new item's data | |
| olddata | -- pointer to the old item's data (set upon return) |
Definition at line 160 of file icl_hash.c.
{
icl_entry_t *curr, *prev;
long hash_val;
if(!ht || !key) return NULL;
hash_val = (* ht->hash_function)(key) % ht->nbuckets;
/* Scan bucket[hash_val] for key */
for (prev=NULL,curr=ht->buckets[hash_val]; curr != NULL; prev=curr, curr=curr->next)
/* If key found, remove node from list, free old key, and setup olddata for the return */
if (strcmp(curr->key, key) == 0) {
if (olddata != NULL) {
*olddata = curr->data;
free(curr->key);
}
if (prev == NULL)
ht->buckets[hash_val] = curr->next;
else
prev->next = curr->next;
}
/* Since key was either not found, or found-and-removed, create and prepend new node */
curr = (icl_entry_t*)malloc(sizeof(icl_entry_t));
if(curr == NULL) return NULL; /* out of memory */
curr->key = key;
curr->data = data;
curr->next = ht->buckets[hash_val]; /* add at start */
ht->buckets[hash_val] = curr;
ht->nentries++;
if(olddata!=NULL && *olddata!=NULL)
*olddata = NULL;
return curr;
}

1.6.3-20100507