Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
330
Src/Wasabi/bfc/ptrlist.cpp
Normal file
330
Src/Wasabi/bfc/ptrlist.cpp
Normal file
|
@ -0,0 +1,330 @@
|
|||
#include "ptrlist.h"
|
||||
#include <bfc/bfc_assert.h>
|
||||
|
||||
// if this symbol is enabled, do sanity checking in a bunch of methods
|
||||
//#define DO_VERIFY_PTRLIST
|
||||
|
||||
#if defined(ASSERTS_ENABLED) && defined(DO_VERIFY_PTRLIST)
|
||||
#define VERIFY_PTRLIST verify()
|
||||
#else
|
||||
#define VERIFY_PTRLIST
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
int ptrlist_totalnitems = 0;
|
||||
#endif
|
||||
|
||||
PtrListRoot::PtrListRoot( int initial_size )
|
||||
{
|
||||
nitems = nslots = 0;
|
||||
items = NULL;
|
||||
//FG>why? we might as well save initial_size*4 bytes if nobody inserts anything in the list, no?
|
||||
//BU No. initial_size defaults to 0 and therefore no memory is actually
|
||||
//allocated in a typical construction. But, sometimes you want to start with
|
||||
//a specific size, generally when you know the exact size you want,
|
||||
//so that you can avoid REALLOCs when you initially populate the list.
|
||||
//FG>Ah, makes sense.
|
||||
setMinimumSize( initial_size );
|
||||
}
|
||||
|
||||
PtrListRoot::PtrListRoot( const PtrListRoot *from )
|
||||
{
|
||||
nitems = nslots = 0;
|
||||
items = NULL;
|
||||
copyFrom( from );
|
||||
}
|
||||
|
||||
PtrListRoot::~PtrListRoot()
|
||||
{
|
||||
removeAll();
|
||||
}
|
||||
|
||||
void PtrListRoot::copyFrom( const PtrListRoot *from )
|
||||
{
|
||||
ASSERT( from != NULL );
|
||||
|
||||
removeAll();
|
||||
appendFrom( from );
|
||||
VERIFY_PTRLIST;
|
||||
}
|
||||
|
||||
void PtrListRoot::appendFrom( const PtrListRoot *from )
|
||||
{
|
||||
ASSERT( from != NULL );
|
||||
|
||||
int n = from->getNumItems();
|
||||
|
||||
if ( n <= 0 )
|
||||
return;
|
||||
|
||||
void **mem = from->getItemList();
|
||||
|
||||
ASSERT( mem != NULL ); // can't be NULL if getNumItems() >= 1
|
||||
|
||||
setMinimumSize( getNumItems() + n );
|
||||
MEMCPY( items + getNumItems(), from->getItemList(), sizeof( void * ) * n );
|
||||
nitems += n;
|
||||
#ifdef _DEBUG
|
||||
ptrlist_totalnitems += n;
|
||||
#endif
|
||||
VERIFY_PTRLIST;
|
||||
}
|
||||
|
||||
void PtrListRoot::setMinimumSize( int _nslots )
|
||||
{
|
||||
ASSERT( _nslots >= 0 );
|
||||
#ifdef DECREASE_PTRLISTS_SIZE
|
||||
if ( _nslots + 2 * DEF_PTRLIST_INCREMENT < nslots )
|
||||
{
|
||||
nslots = ( ( _nslots / DEF_PTRLIST_INCREMENT ) + 2 ) * DEF_PTRLIST_INCREMENT;
|
||||
items = (void **) REALLOC( items, sizeof( void * ) * nslots );
|
||||
}
|
||||
#endif
|
||||
if ( _nslots == 0 || _nslots <= nslots )
|
||||
return;
|
||||
|
||||
nslots = _nslots;
|
||||
|
||||
if ( items )
|
||||
items = (void **) REALLOC( items, sizeof( void * ) * nslots );
|
||||
else
|
||||
items = (void **) MALLOC( sizeof( void * ) * nslots );
|
||||
|
||||
VERIFY_PTRLIST;
|
||||
}
|
||||
|
||||
int PtrListRoot::getNumItems() const
|
||||
{
|
||||
return nitems;
|
||||
}
|
||||
|
||||
void *PtrListRoot::enumItem( int n ) const
|
||||
{
|
||||
if ( items == NULL || n < 0 || n >= nitems )
|
||||
return NULL;
|
||||
|
||||
return items[ n ];
|
||||
}
|
||||
|
||||
void *PtrListRoot::addItem( void *item, int pos, int increment )
|
||||
{
|
||||
ASSERT( increment > 0 );
|
||||
ASSERTPR( item != NULL, "can't put NULLs into ptrlists" );
|
||||
ASSERT( nitems <= nslots );
|
||||
|
||||
#ifdef DECREASE_PTRLISTS_SIZE
|
||||
// expand or shrink as necessary
|
||||
if ( items == NULL || nslots == nitems )
|
||||
setMinimumSize( nslots + increment );
|
||||
else
|
||||
setMinimumSize( nitems );
|
||||
#else
|
||||
// expand if necessary
|
||||
if ( items == NULL || nslots == nitems )
|
||||
setMinimumSize( nslots + increment );
|
||||
#endif
|
||||
|
||||
items[ nitems++ ] = item;
|
||||
|
||||
if ( pos != PTRLIST_POS_LAST )
|
||||
moveItem( nitems - 1, pos );
|
||||
|
||||
VERIFY_PTRLIST;
|
||||
|
||||
#ifdef _DEBUG
|
||||
ptrlist_totalnitems++;
|
||||
#endif
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
// replace what's in the slot with the new value
|
||||
void *PtrListRoot::setItem( void *item, int pos )
|
||||
{
|
||||
ASSERT( nitems >= pos );
|
||||
items[ pos ] = item;
|
||||
VERIFY_PTRLIST;
|
||||
return item;
|
||||
}
|
||||
|
||||
void PtrListRoot::reverse()
|
||||
{
|
||||
if ( nitems <= 1 )
|
||||
return;
|
||||
|
||||
MemBlock<void *> block( nitems, items );
|
||||
void **blockmem = block.getMemory();
|
||||
|
||||
for ( int i = 0, j = nitems - 1; j >= 0; i++, j-- )
|
||||
{
|
||||
items[ i ] = blockmem[ j ];
|
||||
}
|
||||
}
|
||||
|
||||
void PtrListRoot::moveItem( int from, int to )
|
||||
{
|
||||
if ( from == to )
|
||||
return;
|
||||
|
||||
void *ptr = items[ from ];
|
||||
|
||||
if ( nitems > from + 1 ) // if moving from the end, there is nothing to shift behind our src position
|
||||
{
|
||||
//IMPORTANT note for future ports: This assumes MEMCPY accepts overlapping segments.
|
||||
MEMCPY( &items[ from ], &items[ from + 1 ], ( nitems - from ) * sizeof( void * ) );
|
||||
}
|
||||
|
||||
if ( to > from )
|
||||
to--;
|
||||
|
||||
if ( nitems > to ) // if moving to the end, there is nothing to shift behind our target position
|
||||
MEMCPY( &items[ to + 1 ], &items[ to ], ( nitems - to - 1 ) * sizeof( void * ) );
|
||||
|
||||
items[ to ] = ptr;
|
||||
VERIFY_PTRLIST;
|
||||
}
|
||||
|
||||
int PtrListRoot::removeItem( void *item )
|
||||
{
|
||||
int c = 0;
|
||||
|
||||
if ( item == NULL || items == NULL || nitems <= 0 )
|
||||
return 0;
|
||||
|
||||
// count occurences of item in items, remember the first one
|
||||
void **p = items;
|
||||
int first = -1;
|
||||
|
||||
for ( int i = 0; i < nitems; i++, p++ )
|
||||
{
|
||||
if ( *p == item )
|
||||
{
|
||||
if ( c++ == 0 )
|
||||
first = i;
|
||||
}
|
||||
}
|
||||
|
||||
// if we found one, remove it
|
||||
if ( c > 0 )
|
||||
{
|
||||
removeByPos( first ); // delByPos is faaast
|
||||
c--; // decrease count
|
||||
}
|
||||
|
||||
VERIFY_PTRLIST;
|
||||
|
||||
return c; // returns how many occurences of this item left
|
||||
}
|
||||
|
||||
void PtrListRoot::removeEveryItem( void *item )
|
||||
{
|
||||
while ( removeItem( item ) );
|
||||
VERIFY_PTRLIST;
|
||||
}
|
||||
|
||||
void PtrListRoot::removeByPos( int pos )
|
||||
{
|
||||
if ( pos < 0 || pos >= nitems )
|
||||
return; //JC
|
||||
|
||||
--nitems;
|
||||
#ifdef _DEBUG
|
||||
ptrlist_totalnitems--;
|
||||
#endif
|
||||
|
||||
if ( pos == nitems )
|
||||
return; // last one? nothing to copy over
|
||||
|
||||
MEMCPY( items + pos, items + ( pos + 1 ), sizeof( void * ) * ( nitems - pos ) ); // CT:not (nitems-(pos+1)) as nitems has been decremented earlier
|
||||
#ifdef DECREASE_PTRLISTS_SIZE
|
||||
// shrink if necessary
|
||||
setMinimumSize( nitems );
|
||||
#endif
|
||||
VERIFY_PTRLIST;
|
||||
}
|
||||
|
||||
void PtrListRoot::removeLastItem()
|
||||
{
|
||||
if ( nitems == 0 || items == NULL ) return;
|
||||
nitems--; // hee hee
|
||||
#ifdef _DEBUG
|
||||
ptrlist_totalnitems--;
|
||||
#endif
|
||||
#ifdef DECREASE_PTRLISTS_SIZE
|
||||
// shrink if necessary
|
||||
setMinimumSize( nitems );
|
||||
#endif
|
||||
VERIFY_PTRLIST;
|
||||
}
|
||||
|
||||
void PtrListRoot::removeAll()
|
||||
{
|
||||
FREE( items ); items = NULL;
|
||||
#ifdef _DEBUG
|
||||
ptrlist_totalnitems -= nitems;
|
||||
#endif
|
||||
#ifdef DECREASE_PTRLISTS_SIZE
|
||||
// shrink if necessary
|
||||
setMinimumSize( nitems );
|
||||
#endif
|
||||
nitems = 0;
|
||||
nslots = 0;
|
||||
VERIFY_PTRLIST;
|
||||
}
|
||||
|
||||
void PtrListRoot::freeAll()
|
||||
{
|
||||
for ( int i = 0; i < nitems; i++ ) //JC
|
||||
if ( items ) FREE( items[ i ] );
|
||||
|
||||
removeAll();
|
||||
VERIFY_PTRLIST;
|
||||
}
|
||||
|
||||
int PtrListRoot::searchItem( void *item ) const
|
||||
{
|
||||
for ( int i = 0; i < nitems; i++ )
|
||||
if ( items[ i ] == item )
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void PtrListRoot::verify()
|
||||
{
|
||||
#ifdef DO_VERIFY_PTRLIST
|
||||
ASSERT( nitems >= 0 );
|
||||
ASSERT( nslots >= 0 );
|
||||
ASSERT( nitems <= nslots );
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
int PtrListRoot::bsearchItem( void *item ) const
|
||||
{
|
||||
// do binary search
|
||||
if ( nitems == 0 || items == NULL ) return -1;
|
||||
|
||||
int bot = 0, top = nitems - 1, mid;
|
||||
|
||||
for ( int c = 0; c < nitems + 16; c++ )
|
||||
{
|
||||
if ( bot > top ) return -1;
|
||||
mid = ( bot + top ) / 2;
|
||||
if ( item == items[ mid ] ) return mid;
|
||||
if ( item < items[ mid ] ) top = mid - 1;
|
||||
else bot = mid + 1;
|
||||
}
|
||||
ASSERTPR( 0, "binary search fucked up" );
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
void PtrListRoot::purge()
|
||||
{
|
||||
ASSERT( nitems == 0 );
|
||||
if ( items != NULL )
|
||||
{
|
||||
FREE( items );
|
||||
items = NULL;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue