dict.c
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:6k
源码类别:

手机WAP编程

开发平台:

WINDOWS

  1. /*
  2.  * dict.c - lookup data structure using octet strings as keys
  3.  *
  4.  * The Dict is implemented as a simple hash table. In the future, it 
  5.  * might be interesting to use a trie instead.
  6.  *
  7.  * Lars Wirzenius, based on code by Tuomas Luttinen
  8.  */
  9. #include "gwlib.h"
  10. /*
  11.  * The hash table stores key/value -pairs in a List.
  12.  */
  13. typedef struct Item Item;
  14. struct Item {
  15.     Octstr *key;
  16.     void *value;
  17. };
  18. static Item *item_create(Octstr *key, void *value)
  19. {
  20.     Item *item;
  21.     
  22.     item = gw_malloc(sizeof(*item));
  23.     item->key = octstr_duplicate(key);
  24.     item->value = value;
  25.     return item;
  26. }
  27. static void item_destroy(void *item)
  28. {
  29.     Item *p;
  30.     
  31.     p = item;
  32.     octstr_destroy(p->key);
  33.     gw_free(p);
  34. }
  35. static int item_has_key(void *item, void *key)
  36. {
  37.     return octstr_compare(key, ((Item *) item)->key) == 0;
  38. }
  39. /*
  40.  * The dictionary itself is a very simple hash table.
  41.  * `tab' is an array of Lists of Items, in which empty Lists may be
  42.  * represented as NULL.  `size' is the number of elements allocated
  43.  * for the array, and `key_count' is the number of Items currently
  44.  * in the table.  `key_count' is kept up to date by the put and remove
  45.  * functions, and is used to make dict_key_count() faster.
  46.  */
  47. struct Dict {
  48.     List **tab;
  49.     long size;
  50.     long key_count;
  51.     void (*destroy_value)(void *);
  52.     Mutex *lock;
  53. };
  54. static void lock(Dict *dict)
  55. {
  56.     mutex_lock(dict->lock);
  57. }
  58. static void unlock(Dict *dict)
  59. {
  60.     mutex_unlock(dict->lock);
  61. }
  62. static long key_to_index(Dict *dict, Octstr *key)
  63. {
  64.     return octstr_hash_key(key) % dict->size;
  65. }
  66. static int handle_null_value(Dict *dict, Octstr *key, void *value)
  67. {
  68.     if (value == NULL) {
  69.         value = dict_remove(dict, key);
  70. if (dict->destroy_value != NULL)
  71.     dict->destroy_value(value);
  72.         return 1;
  73.     }
  74.     return 0;
  75. }
  76. static int dict_put_true(Dict *dict, Octstr *key, void *value)
  77. {
  78.     Item *p;
  79.     long i;
  80.     int item_unique;
  81.     item_unique = 0;
  82.     lock(dict);
  83.     i = key_to_index(dict, key);
  84.     if (dict->tab[i] == NULL) {
  85. dict->tab[i] = list_create();
  86. p = NULL;
  87.     } else {
  88. p = list_search(dict->tab[i], key, item_has_key);
  89.     }
  90.     if (p == NULL) {
  91.      p = item_create(key, value);
  92. list_append(dict->tab[i], p);
  93.         dict->key_count++;
  94.         item_unique = 1;
  95.     } else {
  96.         item_unique = 0;
  97.     }
  98.     unlock(dict);
  99.     return item_unique;
  100. }
  101. /*
  102.  * And finally, the public functions.
  103.  */
  104. Dict *dict_create(long size_hint, void (*destroy_value)(void *))
  105. {
  106.     Dict *dict;
  107.     long i;
  108.     
  109.     dict = gw_malloc(sizeof(*dict));
  110.     /*
  111.      * Hash tables tend to work well until they are fill to about 50%.
  112.      */
  113.     dict->size = size_hint * 2;
  114.     dict->tab = gw_malloc(sizeof(dict->tab[0]) * dict->size);
  115.     for (i = 0; i < dict->size; ++i)
  116.      dict->tab[i] = NULL;
  117.     dict->lock = mutex_create();
  118.     dict->destroy_value = destroy_value;
  119.     dict->key_count = 0;
  120.     
  121.     return dict;
  122. }
  123. void dict_destroy(Dict *dict)
  124. {
  125.     long i;
  126.     Item *p;
  127.     
  128.     if (dict == NULL)
  129.         return;
  130.     for (i = 0; i < dict->size; ++i) {
  131.         if (dict->tab[i] == NULL)
  132.     continue;
  133. while ((p = list_extract_first(dict->tab[i])) != NULL) {
  134.     if (dict->destroy_value != NULL)
  135.      dict->destroy_value(p->value);
  136.     item_destroy(p);
  137. }
  138. list_destroy(dict->tab[i], NULL);
  139.     }
  140.     mutex_destroy(dict->lock);
  141.     gw_free(dict->tab);
  142.     gw_free(dict);
  143. }
  144. void dict_put(Dict *dict, Octstr *key, void *value)
  145. {
  146.     long i;
  147.     Item *p;
  148.     if (value == NULL) {
  149.         value = dict_remove(dict, key);
  150. if (dict->destroy_value != NULL)
  151.     dict->destroy_value(value);
  152.         return;
  153.     }
  154.     lock(dict);
  155.     i = key_to_index(dict, key);
  156.     if (dict->tab[i] == NULL) {
  157. dict->tab[i] = list_create();
  158. p = NULL;
  159.     } else
  160. p = list_search(dict->tab[i], key, item_has_key);
  161.     if (p == NULL) {
  162.      p = item_create(key, value);
  163. list_append(dict->tab[i], p);
  164.         dict->key_count++;
  165.     } else {
  166. if (dict->destroy_value != NULL)
  167.     dict->destroy_value(p->value);
  168. p->value = value;
  169.     }
  170.     unlock(dict);
  171. }
  172. int dict_put_once(Dict *dict, Octstr *key, void *value)
  173. {
  174.     int ret;
  175.     ret = 1;
  176.     if (handle_null_value(dict, key, value))
  177.         return 1;
  178.     if (dict_put_true(dict, key, value)) {
  179.         ret = 1;
  180.     } else {
  181.         ret = 0;
  182.     }
  183.     return ret;
  184. }
  185. void *dict_get(Dict *dict, Octstr *key)
  186. {
  187.     long i;
  188.     Item *p;
  189.     void *value;
  190.     lock(dict);
  191.     i = key_to_index(dict, key);
  192.     if (dict->tab[i] == NULL)
  193. p = NULL;
  194.     else
  195.         p = list_search(dict->tab[i], key, item_has_key);
  196.     if (p == NULL)
  197.      value = NULL;
  198.     else
  199.      value = p->value;
  200.     unlock(dict);
  201.     return value;
  202. }
  203. void *dict_remove(Dict *dict, Octstr *key)
  204. {
  205.     long i;
  206.     Item *p;
  207.     void *value;
  208.     List *list;
  209.     lock(dict);
  210.     i = key_to_index(dict, key);
  211.     if (dict->tab[i] == NULL)
  212.         list = NULL;
  213.     else
  214.         list = list_extract_matching(dict->tab[i], key, item_has_key);
  215.     gw_assert(list == NULL || list_len(list) == 1);
  216.     if (list == NULL)
  217.      value = NULL;
  218.     else {
  219. p = list_get(list, 0);
  220. list_destroy(list, NULL);
  221.      value = p->value;
  222. item_destroy(p);
  223. dict->key_count--;
  224.     }
  225.     unlock(dict);
  226.     return value;
  227. }
  228. long dict_key_count(Dict *dict)
  229. {
  230.     long result;
  231.     lock(dict);
  232.     result = dict->key_count;
  233.     unlock(dict);
  234.     return result;
  235. }
  236. List *dict_keys(Dict *dict)
  237. {
  238.     List *list;
  239.     Item *item;
  240.     long i, j;
  241.     
  242.     list = list_create();
  243.     lock(dict);
  244.     for (i = 0; i < dict->size; ++i) {
  245. if (dict->tab[i] == NULL)
  246.     continue;
  247. for (j = 0; j < list_len(dict->tab[i]); ++j) {
  248.     item = list_get(dict->tab[i], j);
  249.     list_append(list, octstr_duplicate(item->key));
  250. }
  251.     }
  252.     unlock(dict);
  253.     
  254.     return list;
  255. }