Blender V2.61 - r43446

listbase.c

Go to the documentation of this file.
00001 /* util.c
00002  *
00003  * various string, file, list operations.
00004  *
00005  *
00006  *
00007  * ***** BEGIN GPL LICENSE BLOCK *****
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU General Public License
00011  * as published by the Free Software Foundation; either version 2
00012  * of the License, or (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software Foundation,
00021  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00022  *
00023  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00024  * All rights reserved.
00025  *
00026  * The Original Code is: all of this file.
00027  *
00028  * Contributor(s): none yet.
00029  *
00030  * ***** END GPL LICENSE BLOCK *****
00031  * 
00032  */
00033 
00039 #include <string.h>
00040 #include <stdlib.h>
00041 
00042 
00043 #include "MEM_guardedalloc.h"
00044 
00045 #include "DNA_listBase.h"
00046 
00047 #include "BLI_listbase.h"
00048 
00049 
00050 /* implementation */
00051 
00052 /* Ripped this from blender.c */
00053 void BLI_movelisttolist(ListBase *dst, ListBase *src)
00054 {
00055     if (src->first==NULL) return;
00056 
00057     if (dst->first==NULL) {
00058         dst->first= src->first;
00059         dst->last= src->last;
00060     }
00061     else {
00062         ((Link *)dst->last)->next= src->first;
00063         ((Link *)src->first)->prev= dst->last;
00064         dst->last= src->last;
00065     }
00066     src->first= src->last= NULL;
00067 }
00068 
00069 void BLI_addhead(ListBase *listbase, void *vlink)
00070 {
00071     Link *link= vlink;
00072 
00073     if (link == NULL) return;
00074     if (listbase == NULL) return;
00075 
00076     link->next = listbase->first;
00077     link->prev = NULL;
00078 
00079     if (listbase->first) ((Link *)listbase->first)->prev = link;
00080     if (listbase->last == NULL) listbase->last = link;
00081     listbase->first = link;
00082 }
00083 
00084 
00085 void BLI_addtail(ListBase *listbase, void *vlink)
00086 {
00087     Link *link= vlink;
00088 
00089     if (link == NULL) return;
00090     if (listbase == NULL) return;
00091 
00092     link->next = NULL;
00093     link->prev = listbase->last;
00094 
00095     if (listbase->last) ((Link *)listbase->last)->next = link;
00096     if (listbase->first == NULL) listbase->first = link;
00097     listbase->last = link;
00098 }
00099 
00100 
00101 void BLI_remlink(ListBase *listbase, void *vlink)
00102 {
00103     Link *link= vlink;
00104 
00105     if (link == NULL) return;
00106     if (listbase == NULL) return;
00107 
00108     if (link->next) link->next->prev = link->prev;
00109     if (link->prev) link->prev->next = link->next;
00110 
00111     if (listbase->last == link) listbase->last = link->prev;
00112     if (listbase->first == link) listbase->first = link->next;
00113 }
00114 
00115 int BLI_remlink_safe(ListBase *listbase, void *vlink)
00116 {
00117     if(BLI_findindex(listbase, vlink) != -1) {
00118         BLI_remlink(listbase, vlink);
00119         return 1;
00120     }
00121     else {
00122         return 0;
00123     }
00124 }
00125 
00126 
00127 void BLI_freelinkN(ListBase *listbase, void *vlink)
00128 {
00129     Link *link= vlink;
00130 
00131     if (link == NULL) return;
00132     if (listbase == NULL) return;
00133 
00134     BLI_remlink(listbase,link);
00135     MEM_freeN(link);
00136 }
00137 
00138 
00139 void BLI_insertlink(ListBase *listbase, void *vprevlink, void *vnewlink)
00140 {
00141     Link *prevlink= vprevlink;
00142     Link *newlink= vnewlink;
00143 
00144     /* newlink comes after prevlink */
00145     if (newlink == NULL) return;
00146     if (listbase == NULL) return;
00147     
00148     /* empty list */
00149     if (listbase->first == NULL) { 
00150         
00151         listbase->first= newlink;
00152         listbase->last= newlink;
00153         return;
00154     }
00155     
00156     /* insert before first element */
00157     if (prevlink == NULL) { 
00158         newlink->next= listbase->first;
00159         newlink->prev= NULL;
00160         newlink->next->prev= newlink;
00161         listbase->first= newlink;
00162         return;
00163     }
00164 
00165     /* at end of list */
00166     if (listbase->last== prevlink) 
00167         listbase->last = newlink;
00168 
00169     newlink->next= prevlink->next;
00170     prevlink->next= newlink;
00171     if (newlink->next) newlink->next->prev= newlink;
00172     newlink->prev= prevlink;
00173 }
00174 
00175 /* This uses insertion sort, so NOT ok for large list */
00176 void BLI_sortlist(ListBase *listbase, int (*cmp)(void *, void *))
00177 {
00178     Link *current = NULL;
00179     Link *previous = NULL;
00180     Link *next = NULL;
00181     
00182     if (cmp == NULL) return;
00183     if (listbase == NULL) return;
00184 
00185     if (listbase->first != listbase->last)
00186     {
00187         for( previous = listbase->first, current = previous->next; current; current = next )
00188         {
00189             next = current->next;
00190             previous = current->prev;
00191             
00192             BLI_remlink(listbase, current);
00193             
00194             while(previous && cmp(previous, current) == 1)
00195             {
00196                 previous = previous->prev;
00197             }
00198             
00199             BLI_insertlinkafter(listbase, previous, current);
00200         }
00201     }
00202 }
00203 
00204 void BLI_insertlinkafter(ListBase *listbase, void *vprevlink, void *vnewlink)
00205 {
00206     Link *prevlink= vprevlink;
00207     Link *newlink= vnewlink;
00208 
00209     /* newlink before nextlink */
00210     if (newlink == NULL) return;
00211     if (listbase == NULL) return;
00212 
00213     /* empty list */
00214     if (listbase->first == NULL) { 
00215         listbase->first= newlink;
00216         listbase->last= newlink;
00217         return;
00218     }
00219     
00220     /* insert at head of list */
00221     if (prevlink == NULL) { 
00222         newlink->prev = NULL;
00223         newlink->next = listbase->first;
00224         ((Link *)listbase->first)->prev = newlink;
00225         listbase->first = newlink;
00226         return;
00227     }
00228 
00229     /* at end of list */
00230     if (listbase->last == prevlink) 
00231         listbase->last = newlink;
00232 
00233     newlink->next = prevlink->next;
00234     newlink->prev = prevlink;
00235     prevlink->next = newlink;
00236     if (newlink->next) newlink->next->prev = newlink;
00237 }
00238 
00239 void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink)
00240 {
00241     Link *nextlink= vnextlink;
00242     Link *newlink= vnewlink;
00243 
00244     /* newlink before nextlink */
00245     if (newlink == NULL) return;
00246     if (listbase == NULL) return;
00247 
00248     /* empty list */
00249     if (listbase->first == NULL) { 
00250         listbase->first= newlink;
00251         listbase->last= newlink;
00252         return;
00253     }
00254     
00255     /* insert at end of list */
00256     if (nextlink == NULL) { 
00257         newlink->prev= listbase->last;
00258         newlink->next= NULL;
00259         ((Link *)listbase->last)->next= newlink;
00260         listbase->last= newlink;
00261         return;
00262     }
00263 
00264     /* at beginning of list */
00265     if (listbase->first== nextlink) 
00266         listbase->first = newlink;
00267 
00268     newlink->next= nextlink;
00269     newlink->prev= nextlink->prev;
00270     nextlink->prev= newlink;
00271     if (newlink->prev) newlink->prev->next= newlink;
00272 }
00273 
00274 
00275 void BLI_freelist(ListBase *listbase)
00276 {
00277     Link *link, *next;
00278 
00279     if (listbase == NULL) 
00280         return;
00281     
00282     link= listbase->first;
00283     while (link) {
00284         next= link->next;
00285         free(link);
00286         link= next;
00287     }
00288     
00289     listbase->first= NULL;
00290     listbase->last= NULL;
00291 }
00292 
00293 void BLI_freelistN(ListBase *listbase)
00294 {
00295     Link *link, *next;
00296 
00297     if (listbase == NULL) return;
00298     
00299     link= listbase->first;
00300     while (link) {
00301         next= link->next;
00302         MEM_freeN(link);
00303         link= next;
00304     }
00305     
00306     listbase->first= NULL;
00307     listbase->last= NULL;
00308 }
00309 
00310 
00311 int BLI_countlist(const ListBase *listbase)
00312 {
00313     Link *link;
00314     int count = 0;
00315     
00316     if (listbase) {
00317         link = listbase->first;
00318         while (link) {
00319             count++;
00320             link= link->next;
00321         }
00322     }
00323     return count;
00324 }
00325 
00326 void *BLI_findlink(const ListBase *listbase, int number)
00327 {
00328     Link *link = NULL;
00329 
00330     if (number >= 0) {
00331         link = listbase->first;
00332         while (link != NULL && number != 0) {
00333             number--;
00334             link = link->next;
00335         }
00336     }
00337 
00338     return link;
00339 }
00340 
00341 int BLI_findindex(const ListBase *listbase, void *vlink)
00342 {
00343     Link *link= NULL;
00344     int number= 0;
00345     
00346     if (listbase == NULL) return -1;
00347     if (vlink == NULL) return -1;
00348     
00349     link= listbase->first;
00350     while (link) {
00351         if (link == vlink)
00352             return number;
00353         
00354         number++;
00355         link= link->next;
00356     }
00357     
00358     return -1;
00359 }
00360 
00361 void *BLI_findstring(const ListBase *listbase, const char *id, const int offset)
00362 {
00363     Link *link= NULL;
00364     const char *id_iter;
00365 
00366     if (listbase == NULL) return NULL;
00367 
00368     for (link= listbase->first; link; link= link->next) {
00369         id_iter= ((const char *)link) + offset;
00370 
00371         if (id[0] == id_iter[0] && strcmp(id, id_iter)==0) {
00372             return link;
00373         }
00374     }
00375 
00376     return NULL;
00377 }
00378 /* same as above but find reverse */
00379 void *BLI_rfindstring(const ListBase *listbase, const char *id, const int offset)
00380 {
00381     Link *link= NULL;
00382     const char *id_iter;
00383 
00384     if (listbase == NULL) return NULL;
00385 
00386     for (link= listbase->last; link; link= link->prev) {
00387         id_iter= ((const char *)link) + offset;
00388 
00389         if (id[0] == id_iter[0] && strcmp(id, id_iter)==0) {
00390             return link;
00391         }
00392     }
00393 
00394     return NULL;
00395 }
00396 
00397 void *BLI_findstring_ptr(const ListBase *listbase, const char *id, const int offset)
00398 {
00399     Link *link= NULL;
00400     const char *id_iter;
00401 
00402     if (listbase == NULL) return NULL;
00403 
00404     for (link= listbase->first; link; link= link->next) {
00405         /* exact copy of BLI_findstring(), except for this line */
00406         id_iter= *((const char **)(((const char *)link) + offset));
00407 
00408         if (id[0] == id_iter[0] && strcmp(id, id_iter)==0) {
00409             return link;
00410         }
00411     }
00412 
00413     return NULL;
00414 }
00415 /* same as above but find reverse */
00416 void *BLI_rfindstring_ptr(const ListBase *listbase, const char *id, const int offset)
00417 {
00418     Link *link= NULL;
00419     const char *id_iter;
00420 
00421     if (listbase == NULL) return NULL;
00422 
00423     for (link= listbase->last; link; link= link->prev) {
00424         /* exact copy of BLI_rfindstring(), except for this line */
00425         id_iter= *((const char **)(((const char *)link) + offset));
00426 
00427         if (id[0] == id_iter[0] && strcmp(id, id_iter)==0) {
00428             return link;
00429         }
00430     }
00431 
00432     return NULL;
00433 }
00434 
00435 int BLI_findstringindex(const ListBase *listbase, const char *id, const int offset)
00436 {
00437     Link *link= NULL;
00438     const char *id_iter;
00439     int i= 0;
00440 
00441     if (listbase == NULL) return -1;
00442 
00443     link= listbase->first;
00444     while (link) {
00445         id_iter= ((const char *)link) + offset;
00446 
00447         if(id[0] == id_iter[0] && strcmp(id, id_iter)==0)
00448             return i;
00449         i++;
00450         link= link->next;
00451     }
00452 
00453     return -1;
00454 }
00455 
00456 void BLI_duplicatelist(ListBase *dst, const ListBase *src)
00457 {
00458     struct Link *dst_link, *src_link;
00459 
00460     /* in this order, to ensure it works if dst == src */
00461     src_link= src->first;
00462     dst->first= dst->last= NULL;
00463 
00464     while(src_link) {
00465         dst_link= MEM_dupallocN(src_link);
00466         BLI_addtail(dst, dst_link);
00467 
00468         src_link= src_link->next;
00469     }
00470 }
00471 
00472 /* create a generic list node containing link to provided data */
00473 LinkData *BLI_genericNodeN (void *data)
00474 {
00475     LinkData *ld;
00476     
00477     if (data == NULL)
00478         return NULL;
00479         
00480     /* create new link, and make it hold the given data */
00481     ld= MEM_callocN(sizeof(LinkData), "BLI_genericNodeN()");
00482     ld->data= data;
00483     
00484     return ld;
00485 }