00001 #include "linklist.h"
00002 #include "dbug_mem.h"
00003
00004
00005
00006
00007
00008
00009
00010 void
00011 list_init(List *list, int (*match)(const void *key1, const void *key2),
00012 void (*destroy)(void *data))
00013 {
00014
00015
00016 T_RDWR_INIT(&(list->rwlock), NULL);
00017
00018
00019 list->size = 0;
00020
00021 if (destroy != NULL) {
00022 list->destroy = destroy;
00023 } else {
00024 list->destroy = stringFreeFunction;
00025 }
00026
00027 if (match != NULL) {
00028 list->match = match;
00029 } else {
00030 list->match = stringMatchFunction;
00031 }
00032
00033 list->head = NULL;
00034 list->tail = NULL;
00035 }
00036
00037
00038 void
00039 list_destroy(List *list)
00040 {
00041 void *data = NULL;
00042
00043
00044
00045 T_RDWR_WLOCK(&(list->rwlock));
00046
00047
00048 while (list_size(list) > 0) {
00049 if (list_rem_next(list, NULL, (void **)&data) == 0 &&
00050 list->destroy != NULL) {
00051
00052 list->destroy(data);
00053 }
00054 }
00055
00056
00057 memset(list, 0, sizeof(List));
00058
00059 T_RDWR_WUNLOCK(&(list->rwlock));
00060
00061 return;
00062 }
00063
00064
00065 int
00066 list_getsize(List *list)
00067 {
00068 int retval = 0;
00069
00070
00071
00072 T_RDWR_RLOCK(&(list->rwlock));
00073
00074 retval = list_size(list);
00075
00076 T_RDWR_RUNLOCK(&(list->rwlock));
00077
00078 return retval;
00079 }
00080
00081
00082 int
00083 list_insert(List *list, void *data)
00084 {
00085 int retval = -1;
00086 void *temp = data;
00087
00088
00089
00090 T_RDWR_WLOCK(&(list->rwlock));
00091
00092
00093 if(list_internal_lookup(list, &temp)==0) {
00094
00095 retval = 1;
00096 } else {
00097
00098 retval = list_ins_next(list, NULL, data);
00099 }
00100
00101 T_RDWR_WUNLOCK(&(list->rwlock));
00102
00103 return retval;
00104 }
00105
00106
00107 int
00108 list_lookup(List *list, void **data)
00109 {
00110 int retval = -1;
00111
00112
00113
00114 T_RDWR_RLOCK(&(list->rwlock));
00115
00116 retval = list_internal_lookup(list, data);
00117
00118 T_RDWR_RUNLOCK(&(list->rwlock));
00119
00120 return retval;
00121 }
00122
00123
00124 int
00125 list_for_each_call(List *list, int (*func)(void *data, void *userdata),
00126 void *userdata)
00127 {
00128 ListElmt *element;
00129 int retval = 0;
00130 void *data=NULL;
00131
00132
00133
00134 T_RDWR_RLOCK(&(list->rwlock));
00135
00136
00137 for (element = list_head(list); element != NULL && retval==0; element =
00138 list_next(element)) {
00139 data = (void *)element->data;
00140 retval = func(data, userdata);
00141 }
00142
00143 T_RDWR_RUNLOCK(&(list->rwlock));
00144
00145 return retval;
00146 }
00147
00148
00149 int
00150 list_remove_each_if_func_eq_1(List *list, int (*func)(void *data, void *userdata),
00151 void *userdata)
00152 {
00153 ListElmt *element, *prev, *next;
00154 void *data = NULL;
00155
00156
00157
00158 T_RDWR_WLOCK(&(list->rwlock));
00159
00160
00161 prev = NULL;
00162
00163 for (element = list_head(list); element != NULL;) {
00164 next = list_next(element);
00165 if (func(list_data(element), userdata) == 1) {
00166
00167 if (list_rem_next(list, prev, &data) == 0 &&
00168 list->destroy != NULL) {
00169
00170 list->destroy(data);
00171 }
00172 } else {
00173 prev = element;
00174 }
00175 element = next;
00176 }
00177
00178 T_RDWR_WUNLOCK(&(list->rwlock));
00179
00180 return 0;
00181 }
00182
00183 int
00184 list_foreach_match(List *list, int (*matchfunc)(const void *key1, const void *key2), void (*callbackfunc)(const void *data), void **data)
00185 {
00186 ListElmt *element;
00187 int retval = -1;
00188
00189
00190
00191 T_RDWR_RLOCK(&(list->rwlock));
00192
00193
00194 for (element = list_head(list); element != NULL ; element = list_next(element)) {
00195 if (matchfunc(*data, list_data(element))) {
00196 callbackfunc(list_data(element));
00197 retval = 0;
00198 }
00199 }
00200
00201 T_RDWR_RUNLOCK(&(list->rwlock));
00202
00203 return retval;
00204 }
00205
00206
00207 int
00208 list_remove(List *list, void **data)
00209 {
00210 ListElmt *element, *prev;
00211
00212
00213
00214 T_RDWR_WLOCK(&(list->rwlock));
00215
00216
00217 prev = NULL;
00218
00219 for (element = list_head(list); element != NULL; element =
00220 list_next(element)) {
00221 if (list->match(*data, list_data(element))) {
00222
00223 if (list_rem_next(list, prev, data) == 0) {
00224 T_RDWR_WUNLOCK(&(list->rwlock));
00225 return 0;
00226 } else {
00227 T_RDWR_WUNLOCK(&(list->rwlock));
00228 return -1;
00229 }
00230 }
00231 prev = element;
00232 }
00233
00234 T_RDWR_WUNLOCK(&(list->rwlock));
00235
00236
00237 return -1;
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247 int
00248 list_ins_next(List *list, ListElmt *element, const void *data)
00249 {
00250 ListElmt *new_element = NULL;
00251
00252
00253
00254
00255 if ((new_element = (ListElmt *)malloc(sizeof(ListElmt))) == NULL) {
00256 return -1;
00257 }
00258
00259
00260 new_element->data = (void *)data;
00261
00262 if (element == NULL) {
00263
00264 if (list_size(list) == 0) {
00265 list->tail = new_element;
00266 }
00267
00268 new_element->next = list->head;
00269 list->head = new_element;
00270 } else {
00271
00272 if (element->next == NULL) {
00273 list->tail = new_element;
00274 }
00275
00276 new_element->next = element->next;
00277 element->next = new_element;
00278 }
00279
00280
00281 list->size++;
00282
00283 return 0;
00284 }
00285
00286
00287
00288 int
00289 list_rem_next(List *list, ListElmt *element, void **data)
00290 {
00291 ListElmt *old_element = NULL;
00292
00293
00294
00295
00296 if (list_size(list) == 0) {
00297 return -1;
00298 }
00299
00300
00301 if (element == NULL) {
00302
00303 *data = list->head->data;
00304 old_element = list->head;
00305 list->head = list->head->next;
00306
00307 if (list_size(list) == 1) {
00308 list->tail = NULL;
00309 }
00310 } else {
00311
00312 if (element->next == NULL) {
00313 return -1;
00314 }
00315
00316 *data = element->next->data;
00317 old_element = element->next;
00318 element->next = element->next->next;
00319
00320 if (element->next == NULL) {
00321 list->tail = element;
00322 }
00323 }
00324
00325
00326 free(old_element);
00327
00328
00329 list->size--;
00330
00331 return 0;
00332 }
00333
00334
00335
00336 int
00337 stringMatchFunction(const void *key1, const void *key2)
00338 {
00339 int res = 0;
00340
00341 res = strcmp(key1, key2);
00342
00343 return res == 0 ? 1 : 0;
00344 }
00345
00346
00347
00348 void
00349 stringFreeFunction(void *ptr)
00350 {
00351 if (ptr != NULL) free(ptr);
00352 }
00353
00354
00355
00356 int
00357 list_internal_lookup(List *list, void **data)
00358 {
00359 ListElmt *element;
00360 int retval = -1;
00361
00362
00363
00364
00365 for (element = list_head(list); element != NULL && retval!=0; element =
00366 list_next(element)) {
00367 if (list->match(*data, list_data(element))) {
00368
00369 *data = list_data(element);
00370 retval = 0;
00371 }
00372 }
00373
00374
00375 return retval;
00376 }