summaryrefslogtreecommitdiff
path: root/lib/hashtable.h
blob: ff501cce9437daf26e91841cc4add94eae299ee5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#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;
}

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;

	LIST_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;
	LIST_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);
		printf("kollision\n");
		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;

	return ht_is_in_list(&(ht->begin[index]->list), hash, ht->hash_length);
}

#endif