diff options
| author | Benedict <benedict@0xb8000.de> | 2017-02-02 00:32:26 +0100 |
|---|---|---|
| committer | Benedict <benedict@0xb8000.de> | 2017-02-21 13:00:27 +0100 |
| commit | 1fd84c7dc70a0a6e6d8651fafa50c51dd697ae77 (patch) | |
| tree | af5de3c7952e071c8e27800c41d9f945fa86c9e7 /lib/util/hashtable.h | |
| parent | 9dcc7348ad53cab8fd9396699de0177bac6729d5 (diff) | |
added random stuff which hasn't beend added because yeah
Diffstat (limited to 'lib/util/hashtable.h')
| -rw-r--r-- | lib/util/hashtable.h | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/lib/util/hashtable.h b/lib/util/hashtable.h new file mode 100644 index 0000000..57ac495 --- /dev/null +++ b/lib/util/hashtable.h @@ -0,0 +1,159 @@ +#ifndef __HASHMAP__ +#define __HASHMAP__ + +#include <openssl/sha.h> +#include <string.h> +#include "circulardoublelinkedlist.h" +#include "util.h" + +struct ht_item { + char *hash; + void *data; + unsigned int data_length; + struct list list; +}; + +struct hashtable { + struct ht_item **begin; + unsigned int length; + unsigned int hash_length; + void (*hash_function)(void *data, unsigned int data_length, char *res); +}; + + +int __ht_init(struct hashtable *ht, unsigned int number_elem, + unsigned int hash_length, void (*func)(void *data, + unsigned int data_length, char *res)) +{ + ht->begin = xmalloc(sizeof(struct ht_item)*number_elem); + ht->length = number_elem; + ht->hash_length = hash_length; + ht->hash_function = func; +} + +int ht_destroy(struct hashtable *ht) +{ + free(ht->begin); +} + +void compute_hash_sha1(void *data, unsigned int data_length, char *res) +{ + SHA_CTX sha1; + + SHA1_Init(&sha1); + SHA1_Update(&sha1, data, data_length); + SHA1_Final(res, &sha1); + +} + +int ht_init_sha1(struct hashtable *ht) +{ + __ht_init(ht, 300, 20, compute_hash_sha1); +} + +void *ht_is_in_list(struct list *list, char *hash, int hash_length) +{ + struct list *head, *iter; + struct ht_item *res = NULL; + + head = list; + res = CONTAINER_OF(head, struct ht_item, list); + if(memcmp(res->hash, hash, hash_length) == 0) + return res->data; + + CIRCULARLIST_FOR_EACH(iter,head) { + res = CONTAINER_OF(iter, struct ht_item, list); + if(memcmp(res->hash, hash, hash_length) == 0) + return res->data; + } + + return NULL; +} + +void ht_add(struct hashtable *ht, void *data, unsigned int data_length, + void *key, unsigned int key_length) +{ + unsigned long index; + struct ht_item *new_elem = xmalloc(sizeof(struct ht_item)); + new_elem->hash = xmalloc(ht->hash_length); + new_elem->data = xmalloc(data_length); + + memcpy(new_elem->data, data, data_length); + new_elem->data_length = data_length; + CIRCULARLIST_INIT(&new_elem->list); + + ht->hash_function(key, key_length, new_elem->hash); + memcpy(&index, new_elem->hash, sizeof(unsigned long)); + index = index % ht->length; + + if(ht->begin[index] == NULL) { + ht->begin[index] = new_elem; + return; + } + + if(ht_is_in_list(&(ht->begin[index]->list), new_elem->hash, + ht->hash_length) == NULL) { + list_insert_after(&(ht->begin[index]->list), &new_elem->list); + return; + } +} + +void *ht_get(struct hashtable *ht, void *key, unsigned int key_length) +{ + char *hash = xmalloc(ht->hash_length); + unsigned long index; + + ht->hash_function(key, key_length, hash); + memcpy(&index, hash, sizeof(unsigned long)); + index = index % ht->length; + + struct ht_item *res = ht_is_in_list(&(ht->begin[index]->list), hash, ht->hash_length); + free(hash); + return res; +} + +void __ht_delete_item(struct ht_item *delete) +{ + free(delete->hash); + free(delete->data); + free(delete); +} + +void ht_list_delete(struct list *list, unsigned long index, char *hash, + unsigned int hash_length) +{ + struct list *head, *iter; + struct ht_item *res; + + head = list; + res = CONTAINER_OF(head, struct ht_item, list); + if (memcmp(res->hash, hash, hash_length) == 0) { + list_delete(head); + __ht_delete_item(res); + return; + } + + CIRCULARLIST_FOR_EACH(iter, head) { + res = CONTAINER_OF(iter, struct ht_item, list); + if (memcmp(res->hash, hash, hash_length) == 0) { + list_delete(iter); + __ht_delete_item(res); + return; + } + } +} + +void ht_delete(struct hashtable *ht, void *key, unsigned int key_length) +{ + char *hash = xmalloc(ht->hash_length); + unsigned long index; + + ht->hash_function(key, key_length, hash); + memcpy(&index, hash, sizeof(unsigned long)); + index = index % ht->length; + + ht_list_delete(&ht->begin[index]->list, index, hash, ht->hash_length); + free(hash); +} + +#endif |
