1 //
2 // anyRemote
3 // a wi-fi or bluetooth remote for your PC.
4 //
5 // Copyright (C) 2006-2016 Mikhail Fedotov <anyremote@mail.ru>
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 //
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25
26 #include "common.h"
27 #include "hash.h"
28 #include "list.h"
29
30 //
31 // Hash related wrappers
32 //
33
34 #ifdef USE_GLIB
35
36 #include <glib.h>
37
hashNew(DestroyCallback valueDestroyFunc)38 HashTable* hashNew(DestroyCallback valueDestroyFunc)
39 {
40 return g_hash_table_new_full(g_str_hash, g_str_equal, free, valueDestroyFunc);
41 }
42
hashFind(HashTable * hash,const char * key)43 void* hashFind(HashTable* hash, const char *key)
44 {
45 if (hash && key) {
46 return g_hash_table_lookup(hash, key);
47 }
48 return NULL;
49 }
50
hashReplace(HashTable * hash,const char * key,void * value)51 void hashReplace(HashTable* hash, const char* key, void *value)
52 {
53 if (hash && key) {
54 g_hash_table_replace(hash, strdup(key), value);
55 }
56 }
57
hashRemove(HashTable * hash,const char * key)58 int hashRemove(HashTable* hash, const char* key)
59 {
60 if (hash && key) {
61 if (g_hash_table_remove(hash, key)) {
62 return RC_OK;
63 }
64 }
65 return RC_NOK;
66 }
67
hashDestroy(HashTable * hash)68 void hashDestroy(HashTable* hash)
69 {
70 if (hash) {
71 g_hash_table_destroy(hash);
72 }
73 }
74
hashForeach(HashTable * hash,HashForeachFunc func,void * data)75 void hashForeach(HashTable* hash, HashForeachFunc func, void *data)
76 {
77 if (hash) {
78 g_hash_table_foreach(hash, func, data);
79 }
80 }
81
82 #else
83
str2hash(const char * str)84 static unsigned int str2hash(const char *str)
85 {
86 unsigned int hash = 0;
87 for(; *str; str++) {
88 hash = 31*hash + *str;
89 }
90 return hash;
91 }
92
get(struct StrHashTable * table,const char * key)93 static void* get(struct StrHashTable *table, const char *key)
94 {
95 unsigned int bucket = str2hash(key)%NR_BUCKETS;
96 struct StrHashNode *node = table->buckets[bucket];
97
98 while (node) {
99 if (strcmp(key,node->key) == 0) {
100 return node->value;
101 }
102 node = node->next;
103 }
104 return NULL;
105 }
106
insert(struct StrHashTable * table,char * key,void * value)107 static int insert(struct StrHashTable *table, char *key, void *value)
108 {
109
110 unsigned int bucket = str2hash(key)%NR_BUCKETS;
111 //printf("insert %s to %d\n", key, bucket);
112
113 struct StrHashNode **tmp = &(table->buckets[bucket]);
114 while (*tmp) {
115 if (strcmp(key,(*tmp)->key) == 0) {
116 break;
117 }
118 tmp = &((*tmp)->next);
119 }
120
121 struct StrHashNode *node = NULL;
122
123 if (*tmp) {
124 //printf("insert %s remove old\n", key);
125 free((*tmp)->key);
126
127 if(table->free_value != NULL) {
128 table->free_value((*tmp)->value);
129 }
130 node = *tmp;
131 } else {
132 node = malloc(sizeof(struct StrHashNode));
133 if(node == NULL) {
134 return -1;
135 }
136 node->next = NULL;
137 *tmp = node;
138 }
139 node->key = key;
140 node->value = value;
141
142 return 0;
143 }
144
removeNode(struct StrHashTable * table,const char * key)145 static int removeNode(struct StrHashTable *table, const char *key)
146 {
147 unsigned int bucket = str2hash(key)%NR_BUCKETS;
148
149 struct StrHashNode *tmp;
150 struct StrHashNode *tmp_prev;
151
152 tmp_prev = NULL;
153 tmp = table->buckets[bucket];
154 while (tmp) {
155 if (strcmp(key,tmp->key) == 0) {
156 break;
157 }
158 tmp_prev = tmp;
159 tmp = tmp->next;
160 }
161
162 if(tmp) {
163
164 free(tmp->key);
165
166 if(table->free_value != NULL) {
167 table->free_value(tmp->value);
168 }
169
170 if (tmp_prev) {
171 tmp_prev->next = tmp->next;
172 } else { // remove first
173 table->buckets[bucket] = tmp->next;
174 }
175
176 free(tmp);
177
178 return RC_OK;
179 }
180
181 return RC_NOK;
182 }
183
destroyData(struct StrHashTable * table)184 static void destroyData(struct StrHashTable *table)
185 {
186 int i = 0;
187 for (;i<NR_BUCKETS;i++) {
188
189 struct StrHashNode *tmp = table->buckets[i];
190
191 while (tmp) {
192
193 free(tmp->key);
194
195 if(table->free_value != NULL) {
196 table->free_value(tmp->value);
197 }
198
199 struct StrHashNode *t = tmp;
200
201 tmp = tmp->next;
202
203 free(t);
204 }
205 }
206 }
207
foreach(struct StrHashTable * table,HashForeachFunc func,void * data)208 static void foreach(struct StrHashTable *table, HashForeachFunc func, void *data)
209 {
210 int i = 0;
211 for (;i<NR_BUCKETS;i++) {
212
213 struct StrHashNode *tmp = table->buckets[i];
214 if (!tmp) continue;
215
216 //printf("foreach %d\n", i);
217
218 while (tmp) {
219 if (tmp->key && tmp->value) {
220 func(tmp->key, tmp->value, data);
221 //} else {
222 // printf("foreach %d corrupted hash data\n", i);
223 }
224 tmp = tmp->next;
225 }
226 }
227 }
228
hashNew(DestroyCallback valueDestroyFunc)229 HashTable * hashNew(DestroyCallback valueDestroyFunc)
230 {
231 HashTable * hash = malloc(sizeof(struct StrHashTable));
232
233 int i = 0;
234 for (;i<NR_BUCKETS;i++) {
235 hash->buckets[i] = NULL;
236 }
237 hash->free_value = valueDestroyFunc;
238
239 return hash;
240 }
241
hashFind(HashTable * hash,const char * key)242 void* hashFind(HashTable* hash, const char *key)
243 {
244 if (hash && key) {
245 return get(hash, key);
246 }
247 return NULL;
248 }
249
hashReplace(HashTable * hash,const char * key,void * value)250 void hashReplace(HashTable* hash, const char* key, void *value)
251 {
252 if (hash && key) {
253 insert(hash, strdup(key), value);
254 }
255 }
256
hashRemove(HashTable * hash,const char * key)257 int hashRemove(HashTable* hash, const char* key)
258 {
259 if (hash && key) {
260 return removeNode(hash, key);
261 }
262 return RC_NOK;
263 }
264
hashDestroy(HashTable * hash)265 void hashDestroy(HashTable* hash)
266 {
267 if (hash) {
268 destroyData(hash);
269 free(hash);
270 hash = NULL;
271 }
272 }
273
hashForeach(HashTable * hash,HashForeachFunc func,void * data)274 void hashForeach(HashTable* hash, HashForeachFunc func, void *data)
275 {
276 if (hash) {
277 foreach(hash, func, data);
278 }
279 }
280
281 #endif
282