00001
00007 #include <string.h>
00008 #include "dynlist.h"
00009
00010 dynlist createlist(int itemsize) {
00011 dynlist newlist;
00012 newlist.itemsize=itemsize;
00013 newlist.lasti=0;
00014 newlist.endi=-1;
00015 newlist.end=0;
00016 newlist.last=0;
00017 newlist.start=0;
00018
00019 #ifdef THREADSAFE
00020 sem_init(&(newlist.lock), 0, 0);
00021 sem_post(&(newlist.lock));
00022 #endif
00023
00024 return newlist;
00025 }
00026
00027 void *newitem(dynlist *list) {
00028 dynlistitem *temp;
00029
00030 #ifdef THREADSAFE
00031 sem_wait(&(list->lock));
00032 #endif
00033
00034 temp=(void*)malloc(sizeof(dynlistitem));
00035 if(!temp) {
00036 #ifdef THREADSAFE
00037 sem_post(&(list->lock));
00038 #endif
00039 return NULL;
00040 }
00041 temp->prev=list->end;
00042 temp->next=0;
00043 temp->refer=(void*)malloc(list->itemsize);
00044 memset(temp->refer, 0, list->itemsize);
00045
00046 if(!list->start)
00047 list->start=temp;
00048
00049 list->end=temp;
00050 if(temp->prev)
00051 temp->prev->next=temp;
00052
00053 list->endi++;
00054
00055 if(!list->last)
00056 list->last=temp;
00057
00058
00059 #ifdef THREADSAFE
00060 sem_post(&(list->lock));
00061 #endif
00062
00063 return temp->refer;
00064 }
00065
00066 void additem(dynlist *list, void *item, int i) {
00067 dynlistitem *temp, *prev, *next;
00068
00069 #ifdef THREADSAFE
00070 sem_wait(&(list->lock));
00071 #endif
00072
00073 prev=getdl(list, i-1);
00074 if(i==0)
00075 prev=NULL;
00076
00077 next=getdl(list, i);
00078 if(list->endi<0)
00079 next=NULL;
00080
00081 temp=malloc(sizeof(dynlistitem));
00082 temp->prev=prev;
00083 temp->next=next;
00084 temp->refer=(void*)malloc(list->itemsize);
00085 memcpy(temp->refer, item, list->itemsize);
00086
00087 if(!prev)
00088 list->start=temp;
00089 else
00090 prev->next=temp;
00091
00092 if(next)
00093 next->prev=temp;
00094 else
00095 list->end=temp;
00096
00097 list->endi++;
00098 list->last=temp;
00099
00100 #ifdef THREADSAFE
00101 sem_post(&(list->lock));
00102 #endif
00103 }
00104
00105 void appenditem(dynlist *list, void *item) {
00106 void *target;
00107 #ifdef THREADSAFE
00108 sem_wait(&(list->lock));
00109 #endif
00110
00111 target=newitem(list);
00112 memcpy(target, item, list->itemsize);
00113
00114 #ifdef THREADSAFE
00115 sem_post(&(list->lock));
00116 #endif
00117 }
00118
00119 void catlists(dynlist *list1, dynlist *list2) {
00120 dynlistitem *temp;
00121 int i;
00122
00123 #ifdef THREADSAFE
00124 sem_wait(&(list1->lock));
00125 sem_wait(&(list2->lock));
00126 #endif
00127
00128 if(list1->itemsize!=list2->itemsize)
00129 return;
00130
00131 for(i=0;i<getlen(*list2);++i) {
00132 temp=getdl(list2, i);
00133 if(temp)
00134 appenditem(list1, temp->refer);
00135 }
00136
00137 #ifdef THREADSAFE
00138 sem_post(&(list1->lock));
00139 sem_post(&(list2->lock));
00140 #endif
00141 }
00142
00143 dynlist splitlist(dynlist *list, int i) {
00144 dynlist temp;
00145 void *item;
00146 int loopi, len=getlen(*list);
00147
00148 #ifdef THREADSAFE
00149 sem_wait(&(list->lock));
00150 #endif
00151
00152
00153 temp=createlist(list->itemsize);
00154
00155 for(loopi=i; loopi<len; ++loopi) {
00156 item=getitem(list, i);
00157 if(item) {
00158 appenditem(&temp, item);
00159 eraseitem(list, i);
00160 }
00161 }
00162
00163 #ifdef THREADSAFE
00164 sem_post(&(list->lock));
00165 #endif
00166
00167 list->last=list->start;
00168 list->lasti=0;
00169
00170 return temp;
00171 }
00172
00173 void reverse(dynlist *list) {
00174 dynlistitem *temp, *refpt;
00175
00176 #ifdef THREADSAFE
00177 sem_wait(&(list->lock));
00178 #endif
00179 temp=list->start;
00180 list->start=list->end;
00181 list->end=temp;
00182
00183 for(temp=list->start; temp; temp=temp->next) {
00184 refpt=temp->prev;
00185 temp->prev=temp->next;
00186 temp->next=refpt;
00187 }
00188 list->lasti = list->endi - list->lasti;
00189
00190 #ifdef THREADSAFE
00191 sem_post(&(list->lock));
00192 #endif
00193 }
00194
00195 void swap(dynlist *list, int i, int j) {
00196 dynlistitem *itemp, *jtemp;
00197 void *btemp;
00198
00199 #ifdef THREADSAFE
00200 sem_wait(&(list->lock));
00201 #endif
00202
00203 itemp=getdl(list, i);
00204 jtemp=getdl(list, j);
00205
00206 btemp=itemp->refer;
00207 itemp->refer=jtemp->refer;
00208 jtemp->refer=btemp;
00209
00210 #ifdef THREADSAFE
00211 sem_post(&(list->lock));
00212 #endif
00213 }
00214
00215 dynlistitem *getdl(dynlist *list, int i) {
00216 int idx, idxinit, count, difflast;
00217 dynlistitem *current;
00218
00219
00220
00221 if(i<0) {
00222 i = list->endi + i + 1;
00223 if(i<0)
00224 return NULL;
00225 }
00226
00227 if(i>list->endi)
00228 return NULL;
00229
00230 if(i==0)
00231 return list->start;
00232
00233 if(i==list->endi)
00234 return list->end;
00235
00236 if(i==list->lasti)
00237 return list->last;
00238
00239 if( (difflast=i-list->lasti) < 0) {
00240 difflast*=-1;
00241 count=-1;
00242 }
00243
00244 else
00245 count=1;
00246
00247 if(i > (list->endi/2)) {
00248 if((list->endi - i) < difflast) {
00249 current=list->end;
00250 idxinit=list->endi;
00251 count=-1;
00252 }
00253
00254 else {
00255 current=list->last;
00256 idxinit=list->lasti;
00257 }
00258 }
00259
00260 else if(i<difflast) {
00261 current=list->start;
00262 idxinit=0;
00263 count=1;
00264 }
00265
00266 else {
00267 if(list->last)
00268 current=list->last;
00269
00270 else
00271 current=list->start;
00272
00273 idxinit=list->lasti;
00274 }
00275
00276 for(idx=idxinit;current;) {
00277 if(idx==i) {
00278 list->lasti=i;
00279 list->last=current;
00280 return current;
00281 }
00282
00283 switch(count) {
00284 case 1:
00285 current=current->next;
00286 ++idx;
00287 break;
00288
00289 case -1:
00290 current=current->prev;
00291 --idx;
00292 break;
00293
00294 default:
00295 return 0;
00296 }
00297 }
00298
00299 return 0;
00300 }
00301
00302 void *getitem(dynlist *list, int i) {
00303 dynlistitem *manage;
00304
00305 #ifdef THREADSAFE
00306 sem_wait(&(list->lock));
00307 #endif
00308
00309 manage=getdl(list, i);
00310
00311 if(manage) {
00312 #ifdef THREADSAFE
00313 sem_post(&(list->lock));
00314 #endif
00315
00316 return manage->refer;
00317 }
00318
00319 else {
00320 #ifdef THREADSAFE
00321 sem_post(&(list->lock));
00322 #endif
00323
00324 return 0;
00325 }
00326 }
00327
00328 void eraseitem(dynlist *list, int i) {
00329 dynlistitem *manage;
00330
00331 #ifdef THREADSAFE
00332 sem_wait(&(list->lock));
00333 #endif
00334
00335 manage=getdl(list, i);
00336
00337 if(!manage) {
00338 #ifdef THREADSAFE
00339 sem_post(&(list->lock));
00340 #endif
00341
00342 return;
00343 }
00344
00345 if(manage->prev)
00346 manage->prev->next=manage->next;
00347 else
00348 list->start=manage->next;
00349
00350 if(manage->next)
00351 manage->next->prev=manage->prev;
00352 else
00353 list->end=manage->prev;
00354
00355 list->endi--;
00356
00357 if(manage->refer)
00358 free(manage->refer);
00359 if(manage)
00360 free(manage);
00361
00362 list->lasti=0;
00363 list->last=NULL;
00364
00365 #ifdef THREADSAFE
00366 sem_post(&(list->lock));
00367 #endif
00368 }
00369
00370 void clearlist(dynlist *list) {
00371 dynlistitem *current, *temp;
00372 #ifdef THREADSAFE
00373 sem_wait(&(list->lock));
00374 #endif
00375
00376 for(current=list->start; current; ) {
00377 temp=current->next;
00378 if(current->refer) {
00379 free(current->refer);
00380 current->refer=0;
00381 }
00382
00383 if(current)
00384 free(current);
00385
00386 current=temp;
00387 }
00388 #ifdef THREADSAFE
00389 sem_post(&(list->lock));
00390 sem_destroy(&(list->lock));
00391 #endif
00392 }
00393
00394 long getsize(dynlist list) {
00395 long temp;
00396
00397 #ifdef THREADSAFE
00398 sem_wait(&(list.lock));
00399 #endif
00400
00401 temp = (list.endi+1) * (sizeof(dynlistitem) + list.itemsize) + sizeof(dynlist);
00402
00403 #ifdef THREADSAFE
00404 sem_post(&(list.lock));
00405 #endif
00406
00407 return temp;
00408 }
00409
00410 long getlen(dynlist list) {
00411 long temp;
00412
00413 #ifdef THREADSAFE
00414 sem_wait(&(list.lock));
00415 #endif
00416
00417 temp = list.endi+1;
00418
00419 #ifdef THREADSAFE
00420 sem_post(&(list.lock));
00421 #endif
00422
00423 return temp;
00424 }
00425
00426 void *compile(dynlist list) {
00427 long total_size, itemnr;
00428 void *array;
00429 char *arrayptr;
00430 dynlistitem *item;
00431 #ifdef THREADSAFE
00432 sem_wait(&(list.lock));
00433 #endif
00434
00435 total_size=0;
00436
00437
00438 total_size = (list.endi + 1) * list.itemsize;
00439
00440 array=arrayptr=(char*)malloc(total_size);
00441
00442 for(itemnr=0; itemnr<=list.endi; ++itemnr) {
00443 item = getdl(&list, itemnr);
00444 memcpy(arrayptr, item->refer, list.itemsize);
00445 arrayptr+=list.itemsize;
00446 }
00447
00448 #ifdef THREADSAFE
00449 sem_post(&(list.lock));
00450 #endif
00451 return array;
00452 }
00453
00454 dynlist decompile(void *data, int itemsize, int num) {
00455 dynlist list;
00456 void *temp;
00457 int i;
00458
00459 char *override=data;
00460
00461 list=createlist(itemsize);
00462
00463 for(i=0;i<num;++i) {
00464 temp=newitem(&list);
00465 memcpy(temp, override, itemsize);
00466 override+=itemsize;
00467 }
00468
00469 return list;
00470 }
00471
00472 void sortlist(dynlist *list, int (*func)(void*, void*)) {
00473 int i, len;
00474 void *first, *second;
00475 int changed;
00476
00477 if((len=getlen(*list)) <= 1)
00478 return;
00479
00480 do {
00481 changed=0;
00482
00483 for(i=0; i<len-1; ++i) {
00484 first=getitem(list, i);
00485 second=getitem(list, i+1);
00486
00487 if( (*func)(first, second)) {
00488 swap(list, i, i+1);
00489 changed=1;
00490 }
00491 }
00492 }while(changed);
00493 }