2008-12-20 10:02:00 +00:00
|
|
|
/* util.c
|
|
|
|
*
|
|
|
|
* various string, file, list operations.
|
|
|
|
*
|
|
|
|
*
|
2009-06-23 00:09:26 +00:00
|
|
|
* $Id$
|
2008-12-20 10:02:00 +00:00
|
|
|
*
|
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2008-12-20 10:02:00 +00:00
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* The Original Code is: all of this file.
|
|
|
|
*
|
|
|
|
* Contributor(s): none yet.
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#include "DNA_listBase.h"
|
|
|
|
|
|
|
|
#include "BLI_listbase.h"
|
|
|
|
|
|
|
|
|
|
|
|
/* implementation */
|
|
|
|
|
|
|
|
/* Ripped this from blender.c */
|
2010-12-21 14:49:34 +00:00
|
|
|
void BLI_movelisttolist(ListBase *dst, ListBase *src)
|
2008-12-20 10:02:00 +00:00
|
|
|
{
|
2011-02-13 10:52:18 +00:00
|
|
|
if (src->first==NULL) return;
|
2008-12-20 10:02:00 +00:00
|
|
|
|
2011-02-13 10:52:18 +00:00
|
|
|
if (dst->first==NULL) {
|
2010-12-21 14:49:34 +00:00
|
|
|
dst->first= src->first;
|
|
|
|
dst->last= src->last;
|
2008-12-20 10:02:00 +00:00
|
|
|
}
|
|
|
|
else {
|
2010-12-21 14:49:34 +00:00
|
|
|
((Link *)dst->last)->next= src->first;
|
|
|
|
((Link *)src->first)->prev= dst->last;
|
|
|
|
dst->last= src->last;
|
2008-12-20 10:02:00 +00:00
|
|
|
}
|
2011-02-13 10:52:18 +00:00
|
|
|
src->first= src->last= NULL;
|
2008-12-20 10:02:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void BLI_addhead(ListBase *listbase, void *vlink)
|
|
|
|
{
|
|
|
|
Link *link= vlink;
|
|
|
|
|
|
|
|
if (link == NULL) return;
|
|
|
|
if (listbase == NULL) return;
|
|
|
|
|
|
|
|
link->next = listbase->first;
|
|
|
|
link->prev = NULL;
|
|
|
|
|
|
|
|
if (listbase->first) ((Link *)listbase->first)->prev = link;
|
|
|
|
if (listbase->last == NULL) listbase->last = link;
|
|
|
|
listbase->first = link;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BLI_addtail(ListBase *listbase, void *vlink)
|
|
|
|
{
|
|
|
|
Link *link= vlink;
|
|
|
|
|
|
|
|
if (link == NULL) return;
|
|
|
|
if (listbase == NULL) return;
|
|
|
|
|
|
|
|
link->next = NULL;
|
|
|
|
link->prev = listbase->last;
|
|
|
|
|
|
|
|
if (listbase->last) ((Link *)listbase->last)->next = link;
|
2011-02-13 10:52:18 +00:00
|
|
|
if (listbase->first == NULL) listbase->first = link;
|
2008-12-20 10:02:00 +00:00
|
|
|
listbase->last = link;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BLI_remlink(ListBase *listbase, void *vlink)
|
|
|
|
{
|
|
|
|
Link *link= vlink;
|
|
|
|
|
|
|
|
if (link == NULL) return;
|
|
|
|
if (listbase == NULL) return;
|
|
|
|
|
|
|
|
if (link->next) link->next->prev = link->prev;
|
|
|
|
if (link->prev) link->prev->next = link->next;
|
|
|
|
|
|
|
|
if (listbase->last == link) listbase->last = link->prev;
|
|
|
|
if (listbase->first == link) listbase->first = link->next;
|
|
|
|
}
|
|
|
|
|
merge own commits into render branch into trunk since 27560
27562, 27570, 27571, 27574, 27576, 27577, 27579, 27590, 27591, 27594, 27595, 27596, 27599, 27605, 27611, 27612, 27613, 27614, 27623
2010-03-20 16:41:01 +00:00
|
|
|
int BLI_remlink_safe(ListBase *listbase, void *vlink)
|
|
|
|
{
|
|
|
|
if(BLI_findindex(listbase, vlink) != -1) {
|
|
|
|
BLI_remlink(listbase, vlink);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-20 10:02:00 +00:00
|
|
|
|
|
|
|
void BLI_freelinkN(ListBase *listbase, void *vlink)
|
|
|
|
{
|
|
|
|
Link *link= vlink;
|
|
|
|
|
|
|
|
if (link == NULL) return;
|
|
|
|
if (listbase == NULL) return;
|
|
|
|
|
|
|
|
BLI_remlink(listbase,link);
|
|
|
|
MEM_freeN(link);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BLI_insertlink(ListBase *listbase, void *vprevlink, void *vnewlink)
|
|
|
|
{
|
|
|
|
Link *prevlink= vprevlink;
|
|
|
|
Link *newlink= vnewlink;
|
|
|
|
|
|
|
|
/* newlink comes after prevlink */
|
|
|
|
if (newlink == NULL) return;
|
|
|
|
if (listbase == NULL) return;
|
|
|
|
|
|
|
|
/* empty list */
|
|
|
|
if (listbase->first == NULL) {
|
|
|
|
|
|
|
|
listbase->first= newlink;
|
|
|
|
listbase->last= newlink;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* insert before first element */
|
|
|
|
if (prevlink == NULL) {
|
|
|
|
newlink->next= listbase->first;
|
2011-02-13 10:52:18 +00:00
|
|
|
newlink->prev= NULL;
|
2008-12-20 10:02:00 +00:00
|
|
|
newlink->next->prev= newlink;
|
|
|
|
listbase->first= newlink;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* at end of list */
|
|
|
|
if (listbase->last== prevlink)
|
|
|
|
listbase->last = newlink;
|
|
|
|
|
|
|
|
newlink->next= prevlink->next;
|
|
|
|
prevlink->next= newlink;
|
|
|
|
if (newlink->next) newlink->next->prev= newlink;
|
|
|
|
newlink->prev= prevlink;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This uses insertion sort, so NOT ok for large list */
|
|
|
|
void BLI_sortlist(ListBase *listbase, int (*cmp)(void *, void *))
|
|
|
|
{
|
|
|
|
Link *current = NULL;
|
|
|
|
Link *previous = NULL;
|
|
|
|
Link *next = NULL;
|
|
|
|
|
|
|
|
if (cmp == NULL) return;
|
|
|
|
if (listbase == NULL) return;
|
|
|
|
|
|
|
|
if (listbase->first != listbase->last)
|
|
|
|
{
|
|
|
|
for( previous = listbase->first, current = previous->next; current; current = next )
|
|
|
|
{
|
|
|
|
next = current->next;
|
|
|
|
previous = current->prev;
|
|
|
|
|
|
|
|
BLI_remlink(listbase, current);
|
|
|
|
|
|
|
|
while(previous && cmp(previous, current) == 1)
|
|
|
|
{
|
|
|
|
previous = previous->prev;
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_insertlinkafter(listbase, previous, current);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BLI_insertlinkafter(ListBase *listbase, void *vprevlink, void *vnewlink)
|
|
|
|
{
|
|
|
|
Link *prevlink= vprevlink;
|
|
|
|
Link *newlink= vnewlink;
|
|
|
|
|
|
|
|
/* newlink before nextlink */
|
|
|
|
if (newlink == NULL) return;
|
|
|
|
if (listbase == NULL) return;
|
|
|
|
|
|
|
|
/* empty list */
|
|
|
|
if (listbase->first == NULL) {
|
|
|
|
listbase->first= newlink;
|
|
|
|
listbase->last= newlink;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* insert at head of list */
|
|
|
|
if (prevlink == NULL) {
|
|
|
|
newlink->prev = NULL;
|
|
|
|
newlink->next = listbase->first;
|
|
|
|
((Link *)listbase->first)->prev = newlink;
|
|
|
|
listbase->first = newlink;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* at end of list */
|
|
|
|
if (listbase->last == prevlink)
|
|
|
|
listbase->last = newlink;
|
|
|
|
|
|
|
|
newlink->next = prevlink->next;
|
|
|
|
newlink->prev = prevlink;
|
|
|
|
prevlink->next = newlink;
|
|
|
|
if (newlink->next) newlink->next->prev = newlink;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink)
|
|
|
|
{
|
|
|
|
Link *nextlink= vnextlink;
|
|
|
|
Link *newlink= vnewlink;
|
|
|
|
|
|
|
|
/* newlink before nextlink */
|
|
|
|
if (newlink == NULL) return;
|
|
|
|
if (listbase == NULL) return;
|
|
|
|
|
|
|
|
/* empty list */
|
|
|
|
if (listbase->first == NULL) {
|
|
|
|
listbase->first= newlink;
|
|
|
|
listbase->last= newlink;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* insert at end of list */
|
|
|
|
if (nextlink == NULL) {
|
|
|
|
newlink->prev= listbase->last;
|
2011-02-13 10:52:18 +00:00
|
|
|
newlink->next= NULL;
|
2008-12-20 10:02:00 +00:00
|
|
|
((Link *)listbase->last)->next= newlink;
|
|
|
|
listbase->last= newlink;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* at beginning of list */
|
|
|
|
if (listbase->first== nextlink)
|
|
|
|
listbase->first = newlink;
|
|
|
|
|
|
|
|
newlink->next= nextlink;
|
|
|
|
newlink->prev= nextlink->prev;
|
|
|
|
nextlink->prev= newlink;
|
|
|
|
if (newlink->prev) newlink->prev->next= newlink;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BLI_freelist(ListBase *listbase)
|
|
|
|
{
|
|
|
|
Link *link, *next;
|
|
|
|
|
|
|
|
if (listbase == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
link= listbase->first;
|
|
|
|
while (link) {
|
|
|
|
next= link->next;
|
|
|
|
free(link);
|
|
|
|
link= next;
|
|
|
|
}
|
|
|
|
|
|
|
|
listbase->first= NULL;
|
|
|
|
listbase->last= NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BLI_freelistN(ListBase *listbase)
|
|
|
|
{
|
|
|
|
Link *link, *next;
|
|
|
|
|
|
|
|
if (listbase == NULL) return;
|
|
|
|
|
|
|
|
link= listbase->first;
|
|
|
|
while (link) {
|
|
|
|
next= link->next;
|
|
|
|
MEM_freeN(link);
|
|
|
|
link= next;
|
|
|
|
}
|
|
|
|
|
|
|
|
listbase->first= NULL;
|
|
|
|
listbase->last= NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-12-21 14:49:34 +00:00
|
|
|
int BLI_countlist(const ListBase *listbase)
|
2008-12-20 10:02:00 +00:00
|
|
|
{
|
|
|
|
Link *link;
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
if (listbase) {
|
|
|
|
link = listbase->first;
|
|
|
|
while (link) {
|
|
|
|
count++;
|
|
|
|
link= link->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2010-12-21 14:49:34 +00:00
|
|
|
void *BLI_findlink(const ListBase *listbase, int number)
|
2008-12-20 10:02:00 +00:00
|
|
|
{
|
|
|
|
Link *link = NULL;
|
|
|
|
|
|
|
|
if (number >= 0) {
|
|
|
|
link = listbase->first;
|
|
|
|
while (link != NULL && number != 0) {
|
|
|
|
number--;
|
|
|
|
link = link->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return link;
|
|
|
|
}
|
|
|
|
|
2010-12-21 14:49:34 +00:00
|
|
|
int BLI_findindex(const ListBase *listbase, void *vlink)
|
2008-12-20 10:02:00 +00:00
|
|
|
{
|
|
|
|
Link *link= NULL;
|
|
|
|
int number= 0;
|
|
|
|
|
|
|
|
if (listbase == NULL) return -1;
|
|
|
|
if (vlink == NULL) return -1;
|
|
|
|
|
|
|
|
link= listbase->first;
|
|
|
|
while (link) {
|
|
|
|
if (link == vlink)
|
|
|
|
return number;
|
|
|
|
|
|
|
|
number++;
|
|
|
|
link= link->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-12-21 14:49:34 +00:00
|
|
|
void *BLI_findstring(const ListBase *listbase, const char *id, const int offset)
|
2009-12-29 15:40:26 +00:00
|
|
|
{
|
|
|
|
Link *link= NULL;
|
|
|
|
const char *id_iter;
|
|
|
|
|
|
|
|
if (listbase == NULL) return NULL;
|
|
|
|
|
|
|
|
link= listbase->first;
|
|
|
|
while (link) {
|
|
|
|
id_iter= ((const char *)link) + offset;
|
2009-12-29 15:47:16 +00:00
|
|
|
|
2010-08-13 06:30:04 +00:00
|
|
|
if(id[0] == id_iter[0] && strcmp(id, id_iter)==0)
|
|
|
|
return link;
|
|
|
|
|
|
|
|
link= link->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-12-21 14:49:34 +00:00
|
|
|
void *BLI_findstring_ptr(const ListBase *listbase, const char *id, const int offset)
|
2010-08-13 06:30:04 +00:00
|
|
|
{
|
|
|
|
Link *link= NULL;
|
|
|
|
const char *id_iter;
|
|
|
|
|
|
|
|
if (listbase == NULL) return NULL;
|
|
|
|
|
|
|
|
link= listbase->first;
|
|
|
|
while (link) {
|
|
|
|
/* exact copy of BLI_findstring(), except for this line */
|
|
|
|
id_iter= *((const char **)(((const char *)link) + offset));
|
|
|
|
|
2009-12-29 15:40:26 +00:00
|
|
|
if(id[0] == id_iter[0] && strcmp(id, id_iter)==0)
|
|
|
|
return link;
|
|
|
|
|
|
|
|
link= link->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-12-21 14:49:34 +00:00
|
|
|
int BLI_findstringindex(const ListBase *listbase, const char *id, const int offset)
|
2010-02-02 21:43:26 +00:00
|
|
|
{
|
|
|
|
Link *link= NULL;
|
|
|
|
const char *id_iter;
|
|
|
|
int i= 0;
|
|
|
|
|
|
|
|
if (listbase == NULL) return -1;
|
|
|
|
|
|
|
|
link= listbase->first;
|
|
|
|
while (link) {
|
|
|
|
id_iter= ((const char *)link) + offset;
|
|
|
|
|
|
|
|
if(id[0] == id_iter[0] && strcmp(id, id_iter)==0)
|
|
|
|
return i;
|
|
|
|
i++;
|
|
|
|
link= link->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-12-21 14:49:34 +00:00
|
|
|
void BLI_duplicatelist(ListBase *dst, const ListBase *src)
|
2008-12-20 10:02:00 +00:00
|
|
|
{
|
2010-12-21 14:49:34 +00:00
|
|
|
struct Link *dst_link, *src_link;
|
|
|
|
|
|
|
|
/* in this order, to ensure it works if dst == src */
|
|
|
|
src_link= src->first;
|
2011-02-13 10:52:18 +00:00
|
|
|
dst->first= dst->last= NULL;
|
2010-12-21 14:49:34 +00:00
|
|
|
|
|
|
|
while(src_link) {
|
|
|
|
dst_link= MEM_dupallocN(src_link);
|
|
|
|
BLI_addtail(dst, dst_link);
|
|
|
|
|
|
|
|
src_link= src_link->next;
|
|
|
|
}
|
2008-12-20 10:02:00 +00:00
|
|
|
}
|
|
|
|
|
2009-09-17 10:14:56 +00:00
|
|
|
/* create a generic list node containing link to provided data */
|
|
|
|
LinkData *BLI_genericNodeN (void *data)
|
|
|
|
{
|
|
|
|
LinkData *ld;
|
|
|
|
|
|
|
|
if (data == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* create new link, and make it hold the given data */
|
|
|
|
ld= MEM_callocN(sizeof(LinkData), "BLI_genericNodeN()");
|
|
|
|
ld->data= data;
|
|
|
|
|
|
|
|
return ld;
|
|
|
|
}
|