-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhash_table.c
95 lines (86 loc) · 2.58 KB
/
hash_table.c
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
#include "hash_table.h"
// Allocates a new hash table with the given number of buckets and
// assigns the space to the hashtable** ht parameter for later use.
// In case sufficient memory cannot be allocated, returns a HT_ENOMEM
// (see hash_table.h)
ht_status_code
new_hash_table(int num_buckets, hashtable **ht)
{
hashtable *h = *ht; // One less indirection, easier to grok
int i;
h = malloc(sizeof *h);
if(! h)
goto bad;
h->size = num_buckets;
h->table = malloc(num_buckets * sizeof *h->table);
if(! h->table)
goto bad;
for(i = 0; i < num_buckets; i++){
h->table[i] = NULL;
}
*ht = h;
return HT_CREATE_OK;
bad:
if(h){ // Couldn't allocate memory for the buckets
free(h);
}
return HT_ENOMEM;
}
// This function is used internally to compute the number of the bucket
// where a given key/value pair should be stored.
// FIXME: Find better implementation
static unsigned int
hash(char *key, int size)
{
unsigned int r = 0u, hash = 0u;
while((r = *key++)){
hash += r;
}
return (hash % size);
}
// This function can either:
// - CREATE a key/value pair in the given hash table
// - UPDATE/PATCH a pre-existing key/value pair with a new value
// It delegates to hash and linked_list_put and returns one of the status
// codes defined in hash_table.h
ht_status_code
put(hashtable *ht, key_value kv)
{
char *key = kv.key;
unsigned int hashed_value = hash(key, ht->size);
ll_status_code sc = linked_list_put(&(ht->table[hashed_value]), kv);
// GOD, THAT IS ONE UGLY-ASS PATTERN :/
switch(sc){
case LL_PUT_OK:
return HT_PUT_OK;
case LL_ENOMEM:
return HT_ENOMEM;
default:
return HT_UNKNOWN_ERROR;
}
}
// This function tries to find the key/value pair identified by "key"
// (by delegating to linked_list_get) and returns either:
// - HT_VALUE_FOUND if the key was found in the hash table ht, in which case
// it also assigns the associated value to "result" before returning
// - HT_VALUE_NOT_FOUND if the "key" parameter can not be found in
// the hash table "ht", in which case NULL is assigned to "value"
ht_status_code
get(hashtable *ht, char *key, char **result)
{
unsigned int hashed_value = hash(key, ht->size);
ll_status_code sc = linked_list_get(ht->table[hashed_value], key, result);
switch(sc){
case LL_VALUE_FOUND:
return HT_VALUE_FOUND;
case LL_VALUE_NOT_FOUND:
return HT_VALUE_NOT_FOUND;
}
}
ht_status_code
destroy(hashtable *ht, char *key)
{
unsigned int hashed_value = hash(key, ht->size);
linked_list_delete(&(ht->table[hashed_value]), key);
return HT_DELETE_OK;
}