00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <string.h>
00004 #include <assert.h>
00005 #include "hash_table.h"
00006 #include "hcontainer.h"
00007 #include "util.h"
00008 #include "xassert.h"
00009 #include "xmem.h"
00010 #include "timer.h"
00011
00012 #define TABLESIZE (0)
00013 #define HASH_PRIME (47)
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 void hcon_init(HContainer_t *hc, int datasize, int keysize,
00027 void (*deep_free)(const void *value),
00028 void (*deep_copy)(const void *dst, const void *src))
00029 {
00030 hc->num_total = 0;
00031 hc->datasize = datasize;
00032 hc->keysize = keysize;
00033 hc->deep_free = deep_free;
00034 hc->deep_copy = deep_copy;
00035 hash_init(&hc->hash, HASH_PRIME, TABLESIZE,
00036 (int (*)(const void *, const void *))strcmp, hash_universal_hash);
00037 }
00038
00039 void hcon_init_ext(HContainer_t *hc, unsigned int hashprime, int datasize, int keysize,
00040 void (*deep_free)(const void *value),
00041 void (*deep_copy)(const void *dst, const void *src))
00042 {
00043 hc->num_total = 0;
00044 hc->datasize = datasize;
00045 hc->keysize = keysize;
00046 hc->deep_free = deep_free;
00047 hc->deep_copy = deep_copy;
00048 hash_init(&hc->hash, hashprime, TABLESIZE,
00049 (int (*)(const void *, const void *))strcmp, hash_universal_hash);
00050 }
00051
00052 void *hcon_allocslot_lower(HContainer_t *hc, const char *key)
00053 {
00054 char *tmp = strdup(key);
00055 strtolower(tmp);
00056 void *slot = hcon_allocslot(hc, tmp);
00057 free(tmp);
00058 return slot;
00059 }
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 void *hcon_allocslot(HContainer_t *hc, const char *key)
00070 {
00071 void *slot = NULL;
00072 HContainerElement_t *elem = NULL;
00073
00074 elem = (HContainerElement_t *)hash_lookup(&hc->hash, key);
00075
00076 if (elem == NULL)
00077 {
00078
00079 elem = malloc(sizeof(HContainerElement_t));
00080
00081 if (elem)
00082 {
00083 memset(elem, 0, sizeof(HContainerElement_t));
00084 elem->key = strdup(key);
00085 elem->val = malloc(hc->datasize);
00086 memset(elem->val, 0, hc->datasize);
00087
00088
00089
00090
00091
00092
00093
00094 hash_insert(&hc->hash, elem->key, (void *)(elem));
00095 ++hc->num_total;
00096 }
00097 }
00098
00099 if (elem)
00100 {
00101 slot = elem->val;
00102 }
00103
00104 return slot;
00105 }
00106
00107 void *hcon_lookup_lower(HContainer_t *hc, const char *key)
00108 {
00109 char *tmp = strdup(key);
00110 strtolower(tmp);
00111 void *slot = hcon_lookup(hc, tmp);
00112 free(tmp);
00113 return slot;
00114 }
00115
00116
00117
00118
00119
00120 void *hcon_lookup(HContainer_t *hc, const char *key)
00121 {
00122 HContainerElement_t *elem = NULL;
00123
00124 elem = (HContainerElement_t *)hash_lookup(&hc->hash, key);
00125 if (elem == NULL)
00126 return NULL;
00127 else
00128 return elem->val;
00129 }
00130
00131
00132 void *hcon_lookup_ext(HContainer_t *hc, const char *keyin, const char **keyout)
00133 {
00134 HContainerElement_t *elem = NULL;
00135 void *ret = NULL;
00136
00137 elem = (HContainerElement_t *)hash_lookup(&hc->hash, keyin);
00138 if (elem == NULL)
00139 return NULL;
00140 else
00141 {
00142 ret = elem->val;
00143 *keyout = elem->key;
00144 return ret;
00145 }
00146 }
00147
00148 void *hcon_getn(HContainer_t *hcon, unsigned int n)
00149 {
00150 HContainerElement_t *elem = NULL;
00151 HIterator_t *hit = hiter_create(hcon);
00152
00153 if (hit && n < hit->nelems)
00154 {
00155 elem = hit->elems[n];
00156 hiter_destroy(&hit);
00157 }
00158
00159 if (elem)
00160 {
00161 return elem->val;
00162 }
00163 else
00164 {
00165 return NULL;
00166 }
00167 }
00168
00169
00170
00171
00172
00173 int hcon_member_lower(HContainer_t *hc, const char *key)
00174 {
00175 int exists = 0;
00176 char *tmp = strdup(key);
00177 strtolower(tmp);
00178 exists = (hash_lookup(&hc->hash, tmp) != NULL);
00179 free(tmp);
00180 return exists;
00181 }
00182
00183 int hcon_member(HContainer_t *hc, const char *key)
00184 {
00185 return (hash_lookup(&hc->hash, key) != NULL);
00186 }
00187
00188 static void hconfreemap(const void *key, const void *value, const void *data)
00189 {
00190 HContainer_t *hcon = (HContainer_t *)data;
00191 HContainerElement_t *elem = NULL;
00192
00193
00194
00195
00196 if (value)
00197 {
00198 elem = (HContainerElement_t *)value;
00199 XASSERT(elem && elem->val);
00200
00201 if (hcon->deep_free && elem->val)
00202 {
00203 (*hcon->deep_free)(elem->val);
00204 }
00205
00206
00207 if (elem->key)
00208 {
00209 free(elem->key);
00210 }
00211
00212 if (elem->val)
00213 {
00214 free(elem->val);
00215 }
00216
00217
00218 free((void *)value);
00219 }
00220 }
00221
00222
00223 void hcon_free(HContainer_t *hc)
00224 {
00225
00226
00227 if (hc->num_total > 0)
00228 {
00229 hash_map_data(&hc->hash, hconfreemap, hc);
00230 }
00231
00232 hc->num_total = 0;
00233 hc->datasize = 0;
00234 hc->keysize = 0;
00235 hc->deep_free = NULL;
00236 hc->deep_copy = NULL;
00237
00238
00239
00240 hash_free(&hc->hash);
00241 }
00242
00243
00244
00245
00246
00247 void hcon_remove(HContainer_t *hc, const char *key)
00248 {
00249 HContainerElement_t *elem = NULL;
00250
00251 elem = (HContainerElement_t *)hash_lookup(&hc->hash, key);
00252 if (elem != NULL)
00253 {
00254
00255
00256
00257
00258
00259
00260 hash_remove(&hc->hash, key);
00261
00262 if (elem->key)
00263 {
00264 free(elem->key);
00265 elem->key = NULL;
00266 }
00267
00268 if (elem->val)
00269 {
00270 if (hc->deep_free)
00271 {
00272 (*hc->deep_free)(elem->val);
00273 }
00274
00275 free(elem->val);
00276 elem->val = NULL;
00277 }
00278
00279 free(elem);
00280
00281 --hc->num_total;
00282 }
00283 }
00284
00285 void hcon_print(HContainer_t *hc)
00286 {
00287 const char *key;
00288 void *data = NULL;
00289
00290 HIterator_t *hit = hiter_create(hc);
00291 while((data = hiter_extgetnext(hit, &key)) != NULL)
00292 {
00293 fprintf(stdout, "%s\n", key);
00294 }
00295 }
00296
00297 void hcon_printf(FILE *fp, HContainer_t *hc)
00298 {
00299 const char *key;
00300 void *data = NULL;
00301
00302 HIterator_t *hit = hiter_create(hc);
00303 while((data = hiter_extgetnext(hit, &key)) != NULL)
00304 {
00305 fprintf(fp, "%s\n", key);
00306 }
00307 }
00308
00309
00310
00311
00312 static void hconmapmap(const void *key, const void *value, const void *data)
00313 {
00314 void (*fmap)(const void *value) = (void (*)(const void *value))data;
00315
00316 if (value)
00317 {
00318 (*fmap)(((HContainerElement_t *)value)->val);
00319 }
00320 }
00321
00322 static void hconmapmap_ext(const void *key, const void *value, const void *bundle)
00323 {
00324 HContainerBundle_t *bundlearg = (HContainerBundle_t *)bundle;
00325 void (*fmap)(const void *value, void *data) = bundlearg->fmap;
00326 void *data = bundlearg->data;
00327
00328
00329 if (value)
00330 {
00331 (*fmap)(((HContainerElement_t *)value)->val, data);
00332
00333
00334 }
00335 }
00336
00337 void hcon_map(HContainer_t *hc, void (*fmap)(const void *value))
00338 {
00339 hash_map_data(&hc->hash, hconmapmap, fmap);
00340 }
00341
00342 void hcon_map_ext(HContainer_t *hc, void (*fmap)(const void *value, void *data), void *data)
00343 {
00344 HContainerBundle_t bundle;
00345
00346 bundle.fmap = fmap;
00347 bundle.data = data;
00348
00349 hash_map_data(&hc->hash, hconmapmap_ext, &bundle);
00350 }
00351
00352
00353
00354
00355 static void hconcopymap(const void *key, const void *value, const void *data)
00356 {
00357 HContainer_t *dst = (HContainer_t *)(data);
00358 HContainerElement_t *elem = (HContainerElement_t *)value;
00359
00360
00361
00362
00363
00364
00365 hcon_insert(dst, key, elem->val);
00366 }
00367
00368 void hcon_copy(HContainer_t *dst, HContainer_t *src)
00369 {
00370 hcon_init(dst, src->datasize, src->keysize, src->deep_free, src->deep_copy);
00371
00372
00373
00374 if (src->num_total > 0)
00375 {
00376 hash_map_data(&src->hash, hconcopymap, dst);
00377 }
00378 }
00379
00380
00381
00382
00383 void hcon_stat(HContainer_t *hc)
00384 {
00385 printf("=========================================================================\n");
00386 printf("Data size = %8d\n",hc->datasize);
00387 printf("Key size = %8d\n",hc->keysize);
00388 printf("Total number of items = %8d\n",hc->num_total);
00389 printf("=========================================================================\n");
00390 }
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404 static void hconelemmap(const void *key, const void *value, const void *data)
00405 {
00406 HIterator_t *hit = (HIterator_t *)(data);
00407
00408
00409 if (hit->nelems + 1 > hit->szelems)
00410 {
00411
00412 int origsz = hit->szelems;
00413
00414 hit->szelems *= 2;
00415 hit->elems = realloc(hit->elems, hit->szelems * sizeof(HContainerElement_t *));
00416 memset(&hit->elems[origsz], 0, (hit->szelems - origsz) * sizeof(HContainerElement_t *));
00417 }
00418
00419 hit->elems[hit->nelems++] = (HContainerElement_t *)value;
00420 }
00421
00422 void hiter_new(HIterator_t *hit, HContainer_t *hc)
00423 {
00424 hit->hc = hc;
00425 hit->curr = -1;
00426 hit->nelems = 0;
00427 hit->szelems = 16;
00428 hit->elems = (HContainerElement_t **)malloc(hit->szelems * sizeof(HContainerElement_t *));
00429 memset(hit->elems, 0, hit->szelems * sizeof(HContainerElement_t *));
00430
00431
00432 hash_map_data(&hit->hc->hash, hconelemmap, hit);
00433 }
00434
00435 void hiter_free(HIterator_t *hit)
00436 {
00437 if (hit && hit->elems)
00438 {
00439 free(hit->elems);
00440 }
00441 }
00442
00443 void hiter_new_sort(HIterator_t *hit, HContainer_t *hc, int (*comp)(const void *, const void *))
00444 {
00445 hiter_new(hit, hc);
00446
00447
00448 qsort(hit->elems, hit->nelems, sizeof(HContainerElement_t *), comp);
00449 }
00450
00451 void hiter_rewind(HIterator_t *hit)
00452 {
00453 hit->curr = -1;
00454 }
00455
00456 HContainer_t *hcon_create(int datasize,
00457 int keysize,
00458 void (*deep_free)(const void *value),
00459 void (*deep_copy)(const void *dst, const void *src),
00460 void **valArr,
00461 char **nameArr,
00462 int valArrSize)
00463 {
00464 HContainer_t *cont = (HContainer_t *)malloc(sizeof(HContainer_t));
00465 if (cont != NULL)
00466 {
00467 hcon_init(cont, datasize, keysize, deep_free, deep_copy);
00468 int iArr = 0;
00469
00470 while (valArr && nameArr && iArr < valArrSize)
00471 {
00472 void *slot = hcon_allocslot(cont, nameArr[iArr]);
00473 if (slot != NULL)
00474 {
00475 void *src = valArr[iArr];
00476 memcpy(slot, src, datasize);
00477
00478 if (deep_copy != NULL)
00479 {
00480 (*deep_copy)(slot, src);
00481 }
00482 }
00483
00484 iArr++;
00485 }
00486 }
00487
00488 return cont;
00489 }
00490
00491 void hcon_destroy(HContainer_t **cont)
00492 {
00493 if (*cont != NULL)
00494 {
00495 hcon_free(*cont);
00496 free(*cont);
00497 *cont = NULL;
00498 }
00499 }
00500
00501 int hcon_insert_lower(HContainer_t *hcon, const char *key, const void *value)
00502 {
00503 char *tmp = strdup(key);
00504 strtolower(tmp);
00505 int ret = hcon_insert(hcon, tmp, value);
00506 free(tmp);
00507 return ret;
00508 }
00509
00510 int hcon_insert(HContainer_t *hcon, const char *key, const void *value)
00511 {
00512 int err = 1;
00513
00514 if (hcon)
00515 {
00516 if (!hcon_lookup(hcon, key))
00517 {
00518 void *slot = hcon_allocslot(hcon, key);
00519 if (slot)
00520 {
00521 memcpy(slot, value, hcon->datasize);
00522 if (hcon->deep_copy != NULL)
00523 {
00524 (*(hcon->deep_copy))(slot, value);
00525 }
00526
00527 err = 0;
00528 }
00529 }
00530 }
00531
00532 return err;
00533 }
00534
00535 HIterator_t *hiter_create(HContainer_t *cont)
00536 {
00537 HIterator_t *iter = NULL;
00538
00539 if (cont != NULL)
00540 {
00541 iter = (HIterator_t *)malloc(sizeof(HIterator_t));
00542 if (iter != NULL)
00543 {
00544 hiter_new(iter, cont);
00545 }
00546 }
00547
00548 return iter;
00549 }
00550
00551 void hiter_destroy(HIterator_t **iter)
00552 {
00553 if (*iter != NULL)
00554 {
00555
00556 if ((*iter)->elems)
00557 {
00558 free((*iter)->elems);
00559 }
00560
00561 free(*iter);
00562 *iter = NULL;
00563 }
00564 }