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