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
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 #include "gwlib.h"
00068
00069
00070
00071
00072
00073
00074 typedef struct Item Item;
00075 struct Item {
00076 Octstr *key;
00077 void *value;
00078 };
00079
00080
00081 static Item *item_create(Octstr *key, void *value)
00082 {
00083 Item *item;
00084
00085 item = gw_malloc(sizeof(*item));
00086 item->key = octstr_duplicate(key);
00087 item->value = value;
00088 return item;
00089 }
00090
00091 static void item_destroy(void *item)
00092 {
00093 Item *p;
00094
00095 p = item;
00096 octstr_destroy(p->key);
00097 gw_free(p);
00098 }
00099
00100
00101 static int item_has_key(void *item, void *key)
00102 {
00103 return octstr_compare(key, ((Item *) item)->key) == 0;
00104 }
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 struct Dict {
00117 List **tab;
00118 long size;
00119 long key_count;
00120 void (*destroy_value)(void *);
00121 Mutex *lock;
00122 };
00123
00124
00125 static void lock(Dict *dict)
00126 {
00127 mutex_lock(dict->lock);
00128 }
00129
00130
00131 static void unlock(Dict *dict)
00132 {
00133 mutex_unlock(dict->lock);
00134 }
00135
00136
00137 static long key_to_index(Dict *dict, Octstr *key)
00138 {
00139 return octstr_hash_key(key) % dict->size;
00140 }
00141
00142 static int handle_null_value(Dict *dict, Octstr *key, void *value)
00143 {
00144 if (value == NULL) {
00145 value = dict_remove(dict, key);
00146 if (dict->destroy_value != NULL)
00147 dict->destroy_value(value);
00148 return 1;
00149 }
00150
00151 return 0;
00152 }
00153
00154 static int dict_put_true(Dict *dict, Octstr *key, void *value)
00155 {
00156 Item *p;
00157 long i;
00158 int item_unique;
00159
00160 item_unique = 0;
00161 lock(dict);
00162 i = key_to_index(dict, key);
00163
00164 if (dict->tab[i] == NULL) {
00165 dict->tab[i] = gwlist_create();
00166 p = NULL;
00167 } else {
00168 p = gwlist_search(dict->tab[i], key, item_has_key);
00169 }
00170
00171 if (p == NULL) {
00172 p = item_create(key, value);
00173 gwlist_append(dict->tab[i], p);
00174 dict->key_count++;
00175 item_unique = 1;
00176 } else {
00177 if (dict->destroy_value != NULL)
00178 dict->destroy_value(value);
00179 item_unique = 0;
00180 }
00181
00182 unlock(dict);
00183
00184 return item_unique;
00185 }
00186
00187
00188
00189
00190
00191
00192 Dict *dict_create(long size_hint, void (*destroy_value)(void *))
00193 {
00194 Dict *dict;
00195 long i;
00196
00197 dict = gw_malloc(sizeof(*dict));
00198
00199
00200
00201
00202 dict->size = size_hint * 2;
00203
00204 dict->tab = gw_malloc(sizeof(dict->tab[0]) * dict->size);
00205 for (i = 0; i < dict->size; ++i)
00206 dict->tab[i] = NULL;
00207 dict->lock = mutex_create();
00208 dict->destroy_value = destroy_value;
00209 dict->key_count = 0;
00210
00211 return dict;
00212 }
00213
00214
00215 void dict_destroy(Dict *dict)
00216 {
00217 long i;
00218 Item *p;
00219
00220 if (dict == NULL)
00221 return;
00222
00223 for (i = 0; i < dict->size; ++i) {
00224 if (dict->tab[i] == NULL)
00225 continue;
00226
00227 while ((p = gwlist_extract_first(dict->tab[i])) != NULL) {
00228 if (dict->destroy_value != NULL)
00229 dict->destroy_value(p->value);
00230 item_destroy(p);
00231 }
00232 gwlist_destroy(dict->tab[i], NULL);
00233 }
00234 mutex_destroy(dict->lock);
00235 gw_free(dict->tab);
00236 gw_free(dict);
00237 }
00238
00239
00240 void dict_put(Dict *dict, Octstr *key, void *value)
00241 {
00242 long i;
00243 Item *p;
00244
00245 if (value == NULL) {
00246 value = dict_remove(dict, key);
00247 if (dict->destroy_value != NULL)
00248 dict->destroy_value(value);
00249 return;
00250 }
00251
00252 lock(dict);
00253 i = key_to_index(dict, key);
00254 if (dict->tab[i] == NULL) {
00255 dict->tab[i] = gwlist_create();
00256 p = NULL;
00257 } else
00258 p = gwlist_search(dict->tab[i], key, item_has_key);
00259 if (p == NULL) {
00260 p = item_create(key, value);
00261 gwlist_append(dict->tab[i], p);
00262 dict->key_count++;
00263 } else {
00264 if (dict->destroy_value != NULL)
00265 dict->destroy_value(p->value);
00266 p->value = value;
00267 }
00268 unlock(dict);
00269 }
00270
00271 int dict_put_once(Dict *dict, Octstr *key, void *value)
00272 {
00273 int ret;
00274
00275 ret = 1;
00276 if (handle_null_value(dict, key, value))
00277 return 1;
00278 if (dict_put_true(dict, key, value)) {
00279 ret = 1;
00280 } else {
00281 ret = 0;
00282 }
00283 return ret;
00284 }
00285
00286 void *dict_get(Dict *dict, Octstr *key)
00287 {
00288 long i;
00289 Item *p;
00290 void *value;
00291
00292 lock(dict);
00293 i = key_to_index(dict, key);
00294 if (dict->tab[i] == NULL)
00295 p = NULL;
00296 else
00297 p = gwlist_search(dict->tab[i], key, item_has_key);
00298 if (p == NULL)
00299 value = NULL;
00300 else
00301 value = p->value;
00302 unlock(dict);
00303 return value;
00304 }
00305
00306
00307 void *dict_remove(Dict *dict, Octstr *key)
00308 {
00309 long i;
00310 Item *p;
00311 void *value;
00312 List *list;
00313
00314 lock(dict);
00315 i = key_to_index(dict, key);
00316 if (dict->tab[i] == NULL)
00317 list = NULL;
00318 else
00319 list = gwlist_extract_matching(dict->tab[i], key, item_has_key);
00320 gw_assert(list == NULL || gwlist_len(list) == 1);
00321 if (list == NULL)
00322 value = NULL;
00323 else {
00324 p = gwlist_get(list, 0);
00325 gwlist_destroy(list, NULL);
00326 value = p->value;
00327 item_destroy(p);
00328 dict->key_count--;
00329 }
00330 unlock(dict);
00331 return value;
00332 }
00333
00334
00335 long dict_key_count(Dict *dict)
00336 {
00337 long result;
00338
00339 lock(dict);
00340 result = dict->key_count;
00341 unlock(dict);
00342
00343 return result;
00344 }
00345
00346
00347 List *dict_keys(Dict *dict)
00348 {
00349 List *list;
00350 Item *item;
00351 long i, j;
00352
00353 list = gwlist_create();
00354
00355 lock(dict);
00356 for (i = 0; i < dict->size; ++i) {
00357 if (dict->tab[i] == NULL)
00358 continue;
00359 for (j = 0; j < gwlist_len(dict->tab[i]); ++j) {
00360 item = gwlist_get(dict->tab[i], j);
00361 gwlist_append(list, octstr_duplicate(item->key));
00362 }
00363 }
00364 unlock(dict);
00365
00366 return list;
00367 }
00368
00369
00370
00371
00372
00373
00374
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.