266 lines
6.9 KiB
C
266 lines
6.9 KiB
C
/* util.c
|
|
*
|
|
* various string, file, list operations.
|
|
*
|
|
*
|
|
* $Id$
|
|
*
|
|
* ***** 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,
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* 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 "MEM_guardedalloc.h"
|
|
|
|
#include "DNA_listBase.h"
|
|
|
|
#include "BLI_listbase.h"
|
|
#include "BLI_dynamiclist.h"
|
|
|
|
#define PAGE_SIZE 4
|
|
|
|
/*=====================================================================================*/
|
|
/* Methods for access array (realloc) */
|
|
/*=====================================================================================*/
|
|
|
|
/* remove item with index */
|
|
static void rem_array_item(struct DynamicArray *da, unsigned int index)
|
|
{
|
|
da->items[index]=NULL;
|
|
da->count--;
|
|
if(index==da->last_item_index){
|
|
while((!da->items[da->last_item_index]) && (da->last_item_index>0)){
|
|
da->last_item_index--;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* add array (if needed, then realloc) */
|
|
static void add_array_item(struct DynamicArray *da, void *item, unsigned int index)
|
|
{
|
|
/* realloc of access array */
|
|
if(da->max_item_index < index){
|
|
unsigned int i, max = da->max_item_index;
|
|
void **nitems;
|
|
|
|
do {
|
|
da->max_item_index += PAGE_SIZE; /* OS can allocate only PAGE_SIZE Bytes */
|
|
} while(da->max_item_index<=index);
|
|
|
|
nitems = (void**)MEM_mallocN(sizeof(void*)*(da->max_item_index+1), "dlist access array");
|
|
for(i=0;i<=max;i++)
|
|
nitems[i] = da->items[i];
|
|
|
|
/* set rest pointers to the NULL */
|
|
for(i=max+1; i<=da->max_item_index; i++)
|
|
nitems[i]=NULL;
|
|
|
|
MEM_freeN(da->items); /* free old access array */
|
|
da->items = nitems;
|
|
}
|
|
|
|
da->items[index] = item;
|
|
da->count++;
|
|
if(index > da->last_item_index) da->last_item_index = index;
|
|
}
|
|
|
|
/* free access array */
|
|
static void destroy_array(DynamicArray *da)
|
|
{
|
|
da->count=0;
|
|
da->last_item_index=0;
|
|
da->max_item_index=0;
|
|
MEM_freeN(da->items);
|
|
da->items = NULL;
|
|
}
|
|
|
|
/* initialize dynamic array */
|
|
static void init_array(DynamicArray *da)
|
|
{
|
|
unsigned int i;
|
|
|
|
da->count=0;
|
|
da->last_item_index=0;
|
|
da->max_item_index = PAGE_SIZE-1;
|
|
da->items = (void*)MEM_mallocN(sizeof(void*)*(da->max_item_index+1), "dlist access array");
|
|
for(i=0; i<=da->max_item_index; i++) da->items[i]=NULL;
|
|
}
|
|
|
|
/* reinitialize dynamic array */
|
|
static void reinit_array(DynamicArray *da)
|
|
{
|
|
destroy_array(da);
|
|
init_array(da);
|
|
}
|
|
|
|
/*=====================================================================================*/
|
|
/* Methods for two way dynamic list with access array */
|
|
/*=====================================================================================*/
|
|
|
|
/* create new two way dynamic list with access array from two way dynamic list
|
|
* it doesn't copy any items to new array or something like this It is strongly
|
|
* recomended to use BLI_dlist_ methods for adding/removing items from dynamic list
|
|
* unless you can end with inconsistence system !!! */
|
|
DynamicList *BLI_dlist_from_listbase(ListBase *lb)
|
|
{
|
|
DynamicList *dlist;
|
|
Link *item;
|
|
int i=0, count;
|
|
|
|
if(!lb) return NULL;
|
|
|
|
count = BLI_countlist(lb);
|
|
|
|
dlist = MEM_mallocN(sizeof(DynamicList), "temp dynamic list");
|
|
/* ListBase stuff */
|
|
dlist->lb.first = lb->first;
|
|
dlist->lb.last = lb->last;
|
|
/* access array stuff */
|
|
dlist->da.count=count;
|
|
dlist->da.max_item_index = count-1;
|
|
dlist->da.last_item_index = count -1;
|
|
dlist->da.items = (void*)MEM_mallocN(sizeof(void*)*count, "temp dlist access array");
|
|
|
|
item = (Link*)lb->first;
|
|
while(item){
|
|
dlist->da.items[i] = (void*)item;
|
|
item = item->next;
|
|
i++;
|
|
}
|
|
|
|
/* to prevent you of using original ListBase :-) */
|
|
lb->first = lb->last = NULL;
|
|
|
|
return dlist;
|
|
}
|
|
|
|
/* take out ListBase from DynamicList and destroy all temporary structures of DynamicList */
|
|
ListBase *BLI_listbase_from_dlist(DynamicList *dlist, ListBase *lb)
|
|
{
|
|
if(!dlist) return NULL;
|
|
|
|
if(!lb) lb = (ListBase*)MEM_mallocN(sizeof(ListBase), "ListBase");
|
|
|
|
lb->first = dlist->lb.first;
|
|
lb->last = dlist->lb.last;
|
|
|
|
/* free all items of access array */
|
|
MEM_freeN(dlist->da.items);
|
|
/* free DynamicList*/
|
|
MEM_freeN(dlist);
|
|
|
|
return lb;
|
|
}
|
|
|
|
/* return pointer at item from th dynamic list with access array */
|
|
void *BLI_dlist_find_link(DynamicList *dlist, unsigned int index)
|
|
{
|
|
if(!dlist || !dlist->da.items) return NULL;
|
|
|
|
if((index <= dlist->da.last_item_index) && (index >= 0) && (dlist->da.count>0)){
|
|
return dlist->da.items[index];
|
|
}
|
|
else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/* return count of items in the dynamic list with access array */
|
|
unsigned int BLI_count_items(DynamicList *dlist)
|
|
{
|
|
if(!dlist) return 0;
|
|
|
|
return dlist->da.count;
|
|
}
|
|
|
|
/* free item from the dynamic list with access array */
|
|
void BLI_dlist_free_item(DynamicList *dlist, unsigned int index)
|
|
{
|
|
if(!dlist || !dlist->da.items) return;
|
|
|
|
if((index <= dlist->da.last_item_index) && (dlist->da.items[index])){
|
|
BLI_freelinkN(&(dlist->lb), dlist->da.items[index]);
|
|
rem_array_item(&(dlist->da), index);
|
|
}
|
|
}
|
|
|
|
/* remove item from the dynamic list with access array */
|
|
void BLI_dlist_rem_item(DynamicList *dlist, unsigned int index)
|
|
{
|
|
if(!dlist || !dlist->da.items) return;
|
|
|
|
if((index <= dlist->da.last_item_index) && (dlist->da.items[index])){
|
|
BLI_remlink(&(dlist->lb), dlist->da.items[index]);
|
|
rem_array_item(&(dlist->da), index);
|
|
}
|
|
}
|
|
|
|
/* add item to the dynamic list with access array (index) */
|
|
void* BLI_dlist_add_item_index(DynamicList *dlist, void *item, unsigned int index)
|
|
{
|
|
if(!dlist || !dlist->da.items) return NULL;
|
|
|
|
if((index <= dlist->da.max_item_index) && (dlist->da.items[index])) {
|
|
/* you can't place item at used index */
|
|
return NULL;
|
|
}
|
|
else {
|
|
add_array_item(&(dlist->da), item, index);
|
|
BLI_addtail(&(dlist->lb), item);
|
|
return item;
|
|
}
|
|
}
|
|
|
|
/* destroy dynamic list with access array */
|
|
void BLI_dlist_destroy(DynamicList *dlist)
|
|
{
|
|
if(!dlist) return;
|
|
|
|
BLI_freelistN(&(dlist->lb));
|
|
destroy_array(&(dlist->da));
|
|
}
|
|
|
|
/* initialize dynamic list with access array */
|
|
void BLI_dlist_init(DynamicList *dlist)
|
|
{
|
|
if(!dlist) return;
|
|
|
|
dlist->lb.first = NULL;
|
|
dlist->lb.last = NULL;
|
|
|
|
init_array(&(dlist->da));
|
|
}
|
|
|
|
/* reinitialize dynamic list with acces array */
|
|
void BLI_dlist_reinit(DynamicList *dlist)
|
|
{
|
|
if(!dlist) return;
|
|
|
|
BLI_freelistN(&(dlist->lb));
|
|
reinit_array(&(dlist->da));
|
|
}
|
|
|
|
/*=====================================================================================*/
|