Diffstat (limited to 'kmicromail/libetpan/tools/cinthash.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | kmicromail/libetpan/tools/cinthash.c | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/kmicromail/libetpan/tools/cinthash.c b/kmicromail/libetpan/tools/cinthash.c new file mode 100644 index 0000000..02ee727 --- a/dev/null +++ b/kmicromail/libetpan/tools/cinthash.c @@ -0,0 +1,248 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include <stdlib.h> +#include "cinthash.h" + +struct cinthash_list { + unsigned long hash; + void * data; + struct cinthash_list * next; +}; + +static struct cinthash_list HASH_LISTHEAD_NEW = { 0, NULL, NULL }; + +static inline int hash_list_add(cinthash_t * table, + unsigned long hash, void * data) +{ + struct cinthash_list * ht; + int index; + + index = hash % table->hashtable_size; + + ht = malloc(sizeof(struct cinthash_list)); + if (ht == NULL) + return -1; + + ht->hash = hash; + ht->data = data; + ht->next = table->table[index].next; + + table->table[index].next = ht; + + return 0; +} + +static inline void hash_list_free(struct cinthash_list * list) +{ + struct cinthash_list * cur; + struct cinthash_list * next; + + next = list; + while (next != NULL) { + cur = next; + next = cur->next; + free(cur); + } +} + +static inline int hash_list_remove(cinthash_t * table, unsigned long hash) +{ + struct cinthash_list * cur; + int index; + + index = hash % table->hashtable_size; + + for(cur = &table->table[index] ; cur->next != NULL ; cur = cur->next) { + if (cur->next->hash == hash) { + struct cinthash_list * hash_data; + + hash_data = cur->next; + cur->next = cur->next->next; + + free(hash_data); + + return 0; + } + } + + return -1; +} + +static inline void * hash_list_find(cinthash_t * table, unsigned long hash) +{ + struct cinthash_list * cur; + int index; + + index = hash % table->hashtable_size; + + for(cur = table->table[index].next ; cur != NULL ; cur = cur->next) { + if (cur->hash == hash) + return cur->data; + } + + return NULL; +} + +cinthash_t * cinthash_new(unsigned long hashtable_size) +{ + cinthash_t * ht; + unsigned long i; + + ht = malloc(sizeof(cinthash_t)); + if (ht == NULL) + return NULL; + + ht->table = malloc(sizeof(struct cinthash_list) * hashtable_size); + if (ht->table == NULL) + return NULL; + + ht->hashtable_size = hashtable_size; + ht->count = 0; + + for(i = 0 ; i < hashtable_size ; i++) + ht->table[i] = HASH_LISTHEAD_NEW; + + return ht; +} + +void cinthash_free(cinthash_t * table) +{ + unsigned long i; + + for(i = 0 ; i < table->hashtable_size ; i++) + hash_list_free(table->table[i].next); + + free(table->table); + + free(table); +} + +int cinthash_add(cinthash_t * table, unsigned long hash, void * data) +{ + int index; + + index = hash % table->hashtable_size; + + if (table->table[index].data == NULL) { + table->table[index].hash = hash; + table->table[index].data = data; + table->table[index].next = NULL; + + table->count ++; + + return 0; + } + else { + int r; + + r = hash_list_add(table, hash, data); + if (r == -1) + return -1; + + table->count ++; + + return 0; + } +} + +int cinthash_remove(cinthash_t * table, unsigned long hash) +{ + int index; + + index = hash % table->hashtable_size; + + if (table->table[index].hash == hash) { + table->table[index].hash = 0; + table->table[index].data = NULL; + + table->count --; + + return 0; + } + else { + int r; + + r = hash_list_remove(table, hash); + + table->count --; + + return 0; + } +} + +void * cinthash_find(cinthash_t * table, unsigned long hash) +{ + int index; + + index = hash % table->hashtable_size; + + if (table->table[index].hash == hash) + return table->table[index].data; + + return hash_list_find(table, hash); +} + +void cinthash_foreach_key(cinthash_t * table, + void (* func)(unsigned long, void *), + void * data) +{ + unsigned long index; + struct cinthash_list * cur; + + for(index = 0 ; index < table->hashtable_size ; index ++) { + if (table->table[index].data != NULL) { + func(table->table[index].hash, data); + for(cur = table->table[index].next ; cur != NULL ; cur = cur->next) + func(cur->hash, data); + } + } +} + +void cinthash_foreach_data(cinthash_t * table, + void (* func)(void *, void *), + void * data) +{ + unsigned long index; + struct cinthash_list * cur; + + for(index = 0 ; index < table->hashtable_size ; index ++) { + if (table->table[index].data != NULL) { + func(table->table[index].data, data); + for(cur = table->table[index].next ; cur != NULL ; cur = cur->next) + func(cur->data, data); + } + } +} |