-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdictionary.c
More file actions
153 lines (114 loc) · 3.71 KB
/
Copy pathdictionary.c
File metadata and controls
153 lines (114 loc) · 3.71 KB
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include "dictionary.h"
#include "list.h"
#include <limits.h>
#include <stdlib.h>
#include <string.h>
typedef struct dictionary_entry {
char *key;
int element_size;
deallocator dealloc;
void *value;
} dictionary_entry;
dictionary_entry *dictionary_entry_create(char *key, void *value, int element_size, deallocator dealloc) {
dictionary_entry *entry = malloc(sizeof(dictionary_entry));
entry->key = strdup(key);
entry->value = malloc(element_size);
entry->element_size = element_size;
entry->dealloc = dealloc;
memcpy(entry->value, value, element_size);
return entry;
}
void dictionary_entry_free(dictionary_entry *entry) {
if (entry->dealloc && entry->value) {
entry->dealloc(entry->value);
}
free(entry->key);
free(entry->value);
free(entry);
}
/* dbj2: http://www.cse.yorku.ca/~oz/hash.html
*/
int dictionary_default_hash_function(dictionary *d, char *key) {
unsigned long int hash = 5381;
int c;
while ((c = *key++)) {
hash = ((hash << 5) + hash) + c;
}
return hash % d->array->capacity;
}
void dictionary_entry_deallocator(void *item) {
dictionary_entry_free(*(dictionary_entry **)item);
}
void dictionary_array_deallocator(void *item) {
list_free(*(list **)item);
}
dictionary *dictionary_create(int size) {
dictionary *d = malloc(sizeof(dictionary));
d->array = array_create(size, sizeof(list *), dictionary_array_deallocator);
dictionary_change_hash_function(d, dictionary_default_hash_function);
return d;
}
void dictionary_free(dictionary *d) {
array_free(d->array);
free(d);
}
int dictionary_set(dictionary *d, char *key, void *value, int element_size, deallocator dealloc) {
if (key) {
int hash = (int)(d->hash_function)(d, key);
list *l = *(list **)array_get(d->array, hash);
if (!l) {
l = list_create();
array_set(d->array, hash, &l);
}
int index = -1;
for (list_iterator i = list_get_iterator(l, 0); i.index >= 0; list_iterator_next(&i)) {
dictionary_entry *existing_entry = *(dictionary_entry **)i.value;
if (strcmp(key, existing_entry->key) == 0) {
index = i.index;
break;
}
}
if (index >= 0) {
list_remove(l, index);
}
dictionary_entry *entry = dictionary_entry_create(key, value, element_size, dealloc);
list_add(l, -1, &entry, sizeof(dictionary_entry *), dictionary_entry_deallocator);
}
return 0;
}
void *dictionary_get(dictionary *d, char *key) {
int hash = (int)(d->hash_function)(d, key);
list *l = *(list **)array_get(d->array, hash);
if (l) {
for (list_iterator i = list_get_iterator(l, 0); i.index >= 0; list_iterator_next(&i)) {
dictionary_entry *entry = *(dictionary_entry **)i.value;
if (strcmp(key, entry->key) == 0) {
return entry->value;
}
}
}
return 0;
}
int dictionary_remove(dictionary *d, char *key) {
int hash = (int)(d->hash_function)(d, key);
list *l = *(list **)array_get(d->array, hash);
if (l) {
int index = -1;
for (list_iterator i = list_get_iterator(l, 0); i.index >= 0; list_iterator_next(&i)) {
dictionary_entry *entry = *(dictionary_entry **)i.value;
if (strcmp(key, entry->key) == 0) {
index = i.index;
break;
}
}
if (index >= 0) {
return list_remove(l, index);
}
}
return 0;
}
void dictionary_change_hash_function(dictionary *d, int (*hash_function)(dictionary *,char *)) {
if (hash_function) {
d->hash_function = hash_function;
}
}