dynlist.c

Go to the documentation of this file.
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; /*TODO: return val?*/
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         /*TODO:test*/
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         /*experimental: add support for python-style negative indexing
00220          *-1 equals len-1*/
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)) { /*i is over half*/
00248                 if((list->endi - i) < difflast) {/*i is closest to endi*/
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 }

Generated on Wed Mar 19 12:08:08 2008 for dynlist by  doxygen 1.5.3