123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- #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;
- }
- }
|