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