Blender V2.61 - r43446
|
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 }