00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifdef HAVE_CONFIG_H
00027 # include <config.h>
00028 #endif
00029
00030
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <glib.h>
00035 #include "mntd_volume_hash.h"
00036 #include "errmanager.h"
00037
00038
00039
00040 PHASHMAPELEMENT new_HashMapElement(PHASHMAP phm, void (*func_free)(void *data),
00041 const char *key, void *userdata);
00042 void hashmapelement_destroy(PHASHMAPELEMENT phme);
00043 int hashmap_init(PHASHMAP phm);
00044 void hashmap_destroy(PHASHMAP phm);
00045 int hashmap_hash_element(const void *obj);
00046 int hashmap_compare_element(const void *obj1, const void *obj2);
00047 void hashmap_free_element(void *userdata);
00048
00049
00050 int hashmap_add(PHASHMAP phm, const char *key, void *data);
00051 int hashmap_remove(PHASHMAP phm, const char *key);
00052 int hashmap_size(PHASHMAP phm);
00053 int hashmap_contains(PHASHMAP phm, const char *key);
00054 int hashmap_get(PHASHMAP phm, const char *key, void **userdata);
00055 int hashmap_update(PHASHMAP phm, const char *key, void *userdata);
00056 int hashmap_foreach_call_function(PHASHMAP phm, int (*func)(void *data, void *userdata), void *userdata);
00057
00058
00070 PHASHMAPELEMENT
00071 new_HashMapElement(PHASHMAP phm, void (*func_free)(void *userdata), const char *key, void *userdata)
00072 {
00073 PHASHMAPELEMENT phme = NULL;
00074
00075 g_assert(phm!=NULL);
00076 g_assert(func_free!=NULL);
00077 g_assert(key!=NULL);
00078
00079
00080
00081 phme = (PHASHMAPELEMENT) malloc(sizeof(HASHMAPELEMENT));
00082 if (phme == NULL) {
00083 MSG_ERR("Out of memory");
00084 return NULL;
00085 }
00086
00087
00088 memset(phme, 0, sizeof(HASHMAPELEMENT));
00089
00090
00091 phme->phm = phm;
00092 phme->key = strdup(key);
00093 phme->userdata = userdata;
00094
00095
00096 phme->destroy = hashmapelement_destroy;
00097 phme->free = func_free;
00098
00099
00100
00101
00102 return phme;
00103 }
00104
00105
00111 void
00112 hashmapelement_destroy(PHASHMAPELEMENT phme)
00113 {
00114 g_assert(phme!=NULL);
00115
00116
00117
00118
00119 if (phme->key != NULL) {
00120 free(phme->key);
00121 phme->key = NULL;
00122 }
00123
00124
00125 if ((phme->free != NULL) && (phme->userdata != NULL)) {
00126 phme->free(phme->userdata);
00127 phme->free = NULL;
00128 phme->userdata = NULL;
00129 }
00130
00131
00132 memset(phme, 0, sizeof(HASHMAPELEMENT));
00133 free(phme);
00134 phme = NULL;
00135
00136 return;
00137 }
00138
00139
00140 PHASHMAP
00141 new_HashMap(unsigned int bucket,
00142 void (*func_free)(void *userdata)
00143 )
00144 {
00145 PHASHMAP phm = NULL;
00146
00147 phm = (PHASHMAP) malloc(sizeof(HASHMAP));
00148 if (phm == NULL) {
00149 MSG_ERR("Out of memory");
00150 return NULL;
00151 }
00152
00153
00154 memset(phm, 0, sizeof(HASHMAP));
00155
00156
00157 if (bucket>0) {
00158 phm->bucket = bucket;
00159 } else {
00160 MSG_INF("bucket not correctly setup. Using %d as default.", DEFAULT_BUCKETS);
00161 phm->bucket = DEFAULT_BUCKETS;
00162 }
00163
00164
00165 phm->init = hashmap_init;
00166 phm->destroy = hashmap_destroy;
00167
00168 phm->hash = hashmap_hash_element;
00169 phm->compare = hashmap_compare_element;
00170 if (func_free != NULL) {
00171 phm->free = func_free;
00172 } else {
00173 phm->free = hashmap_free_element;
00174 }
00175
00176 phm->add = hashmap_add;
00177 phm->remove = hashmap_remove;
00178 phm->size = hashmap_size;
00179 phm->contains = hashmap_contains;
00180 phm->get = hashmap_get;
00181 phm->update = hashmap_update;
00182 phm->foreach = hashmap_foreach_call_function;
00183
00184
00185 if(phm->init(phm) == -1) {
00186 free(phm);
00187 phm = NULL;
00188 }
00189
00190
00191 return phm;
00192 }
00193
00194
00201 int
00202 hashmap_init(PHASHMAP phm)
00203 {
00204 CHTbl *htbl = NULL;
00205
00206 if (phm==NULL) {
00207 return -1;
00208 }
00209
00210
00211 htbl = (CHTbl *) malloc(sizeof(CHTbl));
00212 if (htbl == NULL) {
00213 MSG_ERR("not enough mem for hash table");
00214 return -1;
00215 }
00216
00217
00218 if (chtbl_init(htbl, phm->bucket, phm->hash, phm->compare, phm->free) != 0) {
00219 MSG_ERR("could not initialize hash table");
00220 if (htbl!=NULL) free(htbl);
00221 return -1;
00222 }
00223
00224
00225 phm->hm = htbl;
00226
00227
00228 return 0;
00229 }
00230
00231
00238 void
00239 hashmap_destroy(PHASHMAP phm)
00240 {
00241 if ((phm==NULL) || ((phm->hm)==NULL)) {
00242 return;
00243 }
00244
00245 chtbl_destroy(phm->hm);
00246 free(phm->hm);
00247 phm->hm = NULL;
00248 return;
00249 }
00250
00251
00258 int
00259 hashmap_hash_element(const void *obj)
00260 {
00261 char *key = NULL;
00262 unsigned int crc = 0;
00263
00264 if (obj==NULL) {
00265 MSG_EMERG("Hashmap HASH function called with wrong parameter ! (obj=0x%08x)", obj);
00266 return 0;
00267 }
00268
00269 key = ((PHASHMAPELEMENT)obj)->key;
00270 while(*key!='\0') {
00271 crc += *key++;
00272 }
00273
00274 return crc;
00275 }
00276
00277
00285 int
00286 hashmap_compare_element(const void *obj1, const void *obj2)
00287 {
00288 char *key1 = NULL;
00289 char *key2 = NULL;
00290 int res = 0;
00291
00292 if ((obj1==NULL) || (obj2==NULL)) {
00293 MSG_EMERG("Hashmap MATCH function called with wrong parameters ! (obj1=0x%08x, obj2=0x%08x)", obj1, obj2);
00294 return 0;
00295 }
00296
00297 if (obj1==obj2) {
00298 MSG_EMERG("Hashmap MATCH function called with identical parameters ! (obj1=obj2=0x%08x)", obj1);
00299 return 0;
00300 }
00301
00302 key1 = ((PHASHMAPELEMENT)obj1)->key;
00303 key2 = ((PHASHMAPELEMENT)obj2)->key;
00304
00305 res = strcmp(key1, key2);
00306
00307 return res == 0 ? 1 : 0;
00308 }
00309
00310
00316 void
00317 hashmap_free_element(void *userdata)
00318 {
00319 if (userdata != NULL) {
00320 MSG_WARNING("You really should set the 'free()' method !");
00321 }
00322 return;
00323 }
00324
00325
00335 int
00336 hashmap_add(PHASHMAP phm, const char *key, void *data)
00337 {
00338 PHASHMAPELEMENT phme = NULL;
00339 int retval;
00340
00341 if ((phm==NULL) || (key==NULL)) {
00342 return -1;
00343 }
00344
00345 phme = new_HashMapElement(phm, phm->free, key, data);
00346 if (phme == NULL) {
00347 return -1;
00348 }
00349
00350 retval = chtbl_insert(phm->hm, phme);
00351
00352 return retval;
00353 }
00354
00355
00362 int
00363 hashmap_remove(PHASHMAP phm, const char *key)
00364 {
00365 PHASHMAPELEMENT tmp = NULL;
00366 PHASHMAPELEMENT phme = NULL;
00367 void *chtbl_data = NULL;
00368 int retval;
00369
00370 if ((phm==NULL) || ((phm->hm)==NULL) || (key==NULL)) {
00371 return -1;
00372 }
00373
00374 tmp = new_HashMapElement(phm, phm->free, key, NULL);
00375 if (tmp == NULL) {
00376 return -1;
00377 }
00378
00379 chtbl_data = (void *)tmp;
00380 retval = chtbl_remove(phm->hm, &chtbl_data);
00381 if (retval == 0) {
00382 if (chtbl_data != NULL) {
00383 phme = (PHASHMAPELEMENT)chtbl_data;
00384 if (phme != tmp) {
00385 if (phme != NULL) {
00386 phme->destroy(phme);
00387 }
00388 }
00389 }
00390 }
00391 tmp->destroy(tmp); tmp=NULL;
00392
00393 return retval;
00394 }
00395
00396
00402 int
00403 hashmap_size(PHASHMAP phm)
00404 {
00405 if ((phm==NULL) || ((phm->hm)==NULL)) {
00406 return -1;
00407 }
00408
00409 return chtbl_size(phm->hm);
00410 }
00411
00412
00419 int
00420 hashmap_contains(PHASHMAP phm, const char *key)
00421 {
00422 PHASHMAPELEMENT tmp = NULL;
00423 void *data = NULL;
00424 int retval;
00425
00426 if ((phm==NULL) || ((phm->hm)==NULL)) {
00427 return 0;
00428 }
00429
00430 tmp = new_HashMapElement(phm, phm->free, key, NULL);
00431 if (tmp == NULL) {
00432 return 0;
00433 }
00434
00435 data = (void *)tmp;
00436 retval = chtbl_lookup(phm->hm, &data);
00437 tmp->destroy(tmp); tmp=NULL;
00438
00439 return (retval==0) ? 1 : 0;
00440 }
00441
00442
00450 int
00451 hashmap_get(PHASHMAP phm, const char *key, void **userdata)
00452 {
00453 PHASHMAPELEMENT tmp = NULL;
00454 void *data = NULL;
00455 int retval;
00456
00457 if ((phm==NULL) || ((phm->hm)==NULL)) {
00458 return -1;
00459 }
00460
00461 tmp = new_HashMapElement(phm, phm->free, key, NULL);
00462 if (tmp == NULL) {
00463 return -1;
00464 }
00465
00466 data = (void *)tmp;
00467 retval = chtbl_lookup(phm->hm, &data);
00468 tmp->destroy(tmp); tmp=NULL;
00469
00470 if (retval != 0) {
00471 *userdata = NULL;
00472 return -1;
00473 }
00474
00475
00476 *userdata = ((PHASHMAPELEMENT)data)->userdata;
00477 return 0;
00478 }
00479
00480
00488 int
00489 hashmap_update(PHASHMAP phm, const char *key, void *userdata)
00490 {
00491 PHASHMAPELEMENT tmp = NULL;
00492 PHASHMAPELEMENT phme = NULL;
00493 void *data = NULL;
00494 int retval;
00495
00496 if ((phm==NULL) || (key==NULL)) {
00497 return -1;
00498 }
00499
00500 if (phm->contains(phm, key)) {
00501 tmp = new_HashMapElement(phm, phm->free, key, NULL);
00502 if (tmp == NULL) {
00503 return -1;
00504 }
00505
00506 data = (void *)tmp;
00507 retval = chtbl_lookup(phm->hm, &data);
00508 tmp->destroy(tmp); tmp=NULL;
00509
00510 if (retval == 0) {
00511 phme = (PHASHMAPELEMENT)data;
00512 if (phme != NULL) {
00513 phme->free(phme->userdata);
00514 phme->userdata = userdata;
00515 }
00516 }
00517 }
00518
00519 return -1;
00520 }
00521
00522
00530 int
00531 hashmap_foreach_call_function(PHASHMAP phm,
00532 int (*func)(void *data, void *userdata),
00533 void *userdata)
00534 {
00535 int i=0;
00536
00537 if ((phm==NULL) || (func==NULL) || (phm->hm==NULL)) {
00538 return -1;
00539 }
00540
00541 for (i=0; i<phm->hm->buckets; i++) {
00542 list_for_each_call(&phm->hm->table[i], func, userdata);
00543 }
00544
00545 return 0;
00546 }