This repository was archived by the owner on Apr 26, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbasichashmap.c
More file actions
171 lines (129 loc) · 5.47 KB
/
basichashmap.c
File metadata and controls
171 lines (129 loc) · 5.47 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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include "basichashmap.h"
#include <stdlib.h>
#include <basicvector.h>
#include <string.h>
struct basichashmap_s {
struct basicvector_s *vector;
};
struct basichashmap_entry_s {
char *index;
void *value;
};
// see usage of this struct in basichashmap_free for explanation
struct deallocation_user_data_s {
void (*deallocation_function)(char *index, void *item, void *user_data);
void *user_data;
};
void basichashmap_entry_s_deallocation_function(void *vector_item, void *user_data) {
struct basichashmap_entry_s *hashmap_entry = (struct basichashmap_entry_s *) vector_item;
struct deallocation_user_data_s *deallocation_user_data = (struct deallocation_user_data_s *) user_data;
if (deallocation_user_data->deallocation_function != NULL) {
deallocation_user_data->deallocation_function(hashmap_entry->index, hashmap_entry->value, deallocation_user_data->user_data);
}
free(hashmap_entry->index);
free(hashmap_entry);
}
int basichashmap_init(struct basichashmap_s **hashmap) {
if (hashmap == NULL) return BASICHASHMAP_MEMORY_ERROR;
*hashmap = malloc(sizeof(struct basichashmap_s));
if (*hashmap == NULL) {
return BASICHASHMAP_MEMORY_ERROR;
}
if (basicvector_init(&((*hashmap)->vector)) != BASICVECTOR_SUCCESS) {
free(*hashmap);
return BASICHASHMAP_MEMORY_ERROR;
}
return BASICHASHMAP_SUCCESS;
}
int basichashmap_count(struct basichashmap_s *hashmap, int *length) {
if (hashmap == NULL) return BASICHASHMAP_MEMORY_ERROR;
if (length == NULL) return BASICHASHMAP_INVALID_ARGUMENT;
int status = basicvector_length(hashmap->vector, length);
if (status == BASICVECTOR_SUCCESS) {
return BASICHASHMAP_SUCCESS;
} else {
return BASICHASHMAP_MEMORY_ERROR;
}
}
bool basicvector_get_search_function(void *item, void *user_data) {
struct basichashmap_entry_s *entry = (struct basichashmap_entry_s *) item;
char *index = (char *) user_data;
return strcmp(index, entry->index) == 0;
}
int basichashmap_get(struct basichashmap_s *hashmap, char *index, void **result) {
if (hashmap == NULL) return BASICHASHMAP_MEMORY_ERROR;
if (index == NULL || result == NULL) return BASICHASHMAP_INVALID_ARGUMENT;
struct basichashmap_entry_s *entry_result;
int status = basicvector_find(hashmap->vector, (void **) &entry_result, basicvector_get_search_function, index);
switch (status) {
case BASICVECTOR_SUCCESS:
*result = entry_result->value;
return BASICHASHMAP_SUCCESS;
case BASICVECTOR_ITEM_NOT_FOUND:
return BASICHASHMAP_ITEM_NOT_FOUND;
default:
return BASICHASHMAP_MEMORY_ERROR;
};
}
bool basichashmap_remove_by_index_search_callback(
void *item,
void *user_data
) {
char *searched_index = (char*) user_data;
struct basichashmap_entry_s *entry = (struct basichashmap_entry_s *) item;
return strcmp(entry->index, searched_index) == 0;
}
int basichashmap_remove_by_index(
struct basichashmap_s *hashmap,
char *index,
void (*deallocation_function)(char *index, void *value, void *user_data),
void *user_data
) {
if (hashmap == NULL) return BASICHASHMAP_MEMORY_ERROR;
if (index == NULL) return BASICHASHMAP_INVALID_ARGUMENT;
int result;
int status = basicvector_find_index(hashmap->vector, &result, basichashmap_remove_by_index_search_callback, index);
if (status == BASICVECTOR_ITEM_NOT_FOUND) {
return BASICHASHMAP_ITEM_NOT_FOUND;
} else if (status != BASICVECTOR_SUCCESS) {
return BASICHASHMAP_MEMORY_ERROR;
}
struct deallocation_user_data_s deallocation_user_data = { deallocation_function, user_data };
basicvector_remove(hashmap->vector, result, basichashmap_entry_s_deallocation_function, &deallocation_user_data);
return BASICHASHMAP_SUCCESS;
}
int basichashmap_set(
struct basichashmap_s *hashmap,
char *index,
void *value,
void (*deallocation_function)(char *index, void *value, void *user_data),
void *user_data
) {
if (hashmap == NULL) {
return BASICHASHMAP_MEMORY_ERROR;
}
if (index == NULL) {
return BASICHASHMAP_INVALID_ARGUMENT;
}
int remove_status = basichashmap_remove_by_index(hashmap, index, deallocation_function, user_data);
if (remove_status != BASICHASHMAP_SUCCESS && remove_status != BASICHASHMAP_ITEM_NOT_FOUND) {
return remove_status;
}
struct basichashmap_entry_s *entry = malloc(sizeof(struct basichashmap_entry_s));
char *own_index = malloc(sizeof(char) * (strlen(index) + 1));
strcpy(own_index, index);
entry->index = own_index;
entry->value = value;
basicvector_push(hashmap->vector, entry);
return BASICHASHMAP_SUCCESS;
}
int basichashmap_free(struct basichashmap_s *hashmap, void (* deallocation_function)(char *index, void *item, void *user_data), void *user_data) {
if (hashmap == NULL) {
return BASICHASHMAP_MEMORY_ERROR;
}
// Type of deallocation function in basicvector library does not correspond to one that we have. Because of that, there is a struct that is only for passing data to compatible deallocation function and then from that data we can execute proper callback (see basichashmap_entry_s_deallocation_function).
struct deallocation_user_data_s deallocation_user_data = { deallocation_function, user_data };
basicvector_free(hashmap->vector, basichashmap_entry_s_deallocation_function, &deallocation_user_data);
free(hashmap);
return BASICHASHMAP_SUCCESS;
}