[BACK]Return to pfuAutoList.C CVS log [TXT][DIR] Up to [Development] / performer / src / lib / libpfutil

File: [Development] / performer / src / lib / libpfutil / pfuAutoList.C (download)

Revision 1.1, Tue Nov 21 21:39:36 2000 UTC (16 years, 10 months ago) by flynnt
Branch: MAIN
CVS Tags: HEAD

Initial check-in based on OpenGL Performer 2.4 tree.
-flynnt

/*
 * Copyright 1997, MultiGen, Inc.
 * Copyright 1997, Paradigm Simulation, Inc.
 * ALL RIGHTS RESERVED
 *
 * UNPUBLISHED -- Rights reserved under the copyright laws of the United
 * States.   Use of a copyright notice is precautionary only and does not
 * imply publication or disclosure.
 *
 * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND:
 * Use, duplication or disclosure by the Government is subject to restrictions
 * as set forth in FAR 52.227.19(c)(2) or subparagraph (c)(1)(ii) of the Rights
 * in Technical Data and Computer Software clause at DFARS 252.227-7013 and/or
 * in similar or successor clauses in the FAR, or the DOD or NASA FAR
 * Supplement.
 */

////////////////////////////////////////////////////////////////////////
//
// $RCSfile: pfuAutoList.C,v $
// $Date: 2000/11/21 21:39:36 $
// $Revision: 1.1 $
//
// Description:
//  	Performer Utility Auto-delete List class
//
// Notes:
//  	A list for pfMemory objects that are owned by the list.
//
//  	Loaders can use this to avoid resource leaks by attaching
//  	objects of this class as pfNode::userData and adding
//  	pfMemory objects to this list. When the node is deleted the
//  	user data resources will also be deleted.
//
// 
//  	init() must be called before any use of this class!
//
// To Do:
//
////////////////////////////////////////////////////////////////////////

#define __BUILDCAPI__

#include "pfuAutoList.h"

extern "C"
{
}

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

pfType* pfuAutoList::classType = 0;

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

void
pfuAutoList::
init ()
{
    if ( ! classType )
    {
        pfObject::init();

        classType = new pfType( pfObject::getClassType(), "pfuAutoList" );
    }
}


void
pfuInitAutoListClass ()
{
    pfuAutoList::init();
}

////////////////////////////////////////////////////////////////////////

extern "C"
{

pfType*
pfuGetAutoListClassType ()
{
    return pfuAutoList::getClassType();
}

}

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

pfuAutoList::
~pfuAutoList ()
{
    destroyElements( List );
    List->checkDelete();
}

////////////////////////////////////////////////////////////////////////

pfuAutoList::
pfuAutoList ()
    : List( new ( getArena() ) pfList )
{
    setType( classType );
}

pfuAutoList::
pfuAutoList ( int howMany )
    : List( new ( getArena() ) pfList( sizeof( pfMemory* ), howMany ) )
{
    setType( classType );
}

extern "C"
{

pfuAutoList*
pfuNewAutoList ( int howMany, void* arena )
{
    return new ( arena ) pfuAutoList( howMany );
}

}

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// delete each element in the list

void
pfuAutoList::
destroyElements ( pfList* list )
{
    int howMany = list->getNum();

    for ( int which = 0; which < howMany; ++ which )
    {
	pfMemory*   elt = ( pfMemory* ) list->get( which );

	if ( elt )
	    elt->unrefDelete();
    }
}

////////////////////////////////////////////////////////////////////////
// reference count each element in the list

void
pfuAutoList::
refElements ()
{
    int howMany = getNum();

    for ( int which = 0; which < howMany; ++ which )
    {
	pfMemory*   elt = get( which );

	if ( elt )
	    elt->ref();
    }
}

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// add element to the end (tail) of the list.

void
pfuAutoList::
add( pfMemory* elt )
{
    List->add( elt );
    elt->ref();
}

extern "C"
{

void
pfuAdd ( pfuAutoList* self, void* elt )
{
    pfType* memType = pfMemory::getClassType();
    
    if ( pfMemory::isOfType( elt, memType ) )
    {
    	self->add( pfMemory::getMemory( elt ) );
    }
    else
    {
    	pfNotify( PFNFY_WARN, PFNFY_USAGE,
    	    	  "%s::add() - ( void* ) 0x%p is not a %s",
    	    	  self->getTypeName(),
    	    	  elt,
    	    	  memType->getName() );
    }
}

}

////////////////////////////////////////////////////////////////////////
// copy list according to pfList::copy()
// NOTE: pfObject::this->userData is not owned or deleted!!

int
pfuAutoList::
copy( pfMemory const* rhs )
{
    int ok = parentCopy( rhs, 0 );

    if ( ok )
    {
	pfuAutoList const*  other = ( pfuAutoList* ) rhs;

    	pfList* tmp = new ( getArena() ) pfList( other->List->getEltSize(),
    	    	    	    	    	    	 other->List->getNum() );

	ok = tmp->copy( other->List );

	if ( ok )
	{
    	    pfList* old = List;
    	    
     	    List = tmp;
	    refElements();

    	    destroyElements( old ); // exception safe now
    	    old->checkDelete();
	}
	else
	{
	    tmp->checkDelete();
	}
    }
    return ok;
}

extern "C"
{

//  works with pfCopy()

}

////////////////////////////////////////////////////////////////////////
// insert element into list at position given.

void
pfuAutoList::
insert ( int which, pfMemory* elt )
{
    List->insert( which, elt );
    elt->ref();
}

extern "C"
{

void
pfuInsert ( pfuAutoList* self, int which, void* elt )
{
    pfType* memType = pfMemory::getClassType();
    
    if ( pfMemory::isOfType( elt, memType ) )
    {
    	self->insert( which, pfMemory::getMemory( elt ) );
    }
    else
    {
    	pfNotify( PFNFY_WARN, PFNFY_USAGE,
    	    	  "%s::insert() - ( void* ) 0x%p is not a %s",
    	    	  self->getTypeName(),
    	    	  elt,
    	    	  memType->getName() );
    }
}

}

////////////////////////////////////////////////////////////////////////
// move (insert) first occurance of element to position given.

extern "C"
{

int
pfuMove ( pfuAutoList* self, int which, void* elt )
{
    pfType* memType = pfMemory::getClassType();
    
    if ( pfMemory::isOfType( elt, memType ) )
    {
    	return self->move( which, pfMemory::getMemory( elt ) );
    }
    else
    {
    	pfNotify( PFNFY_WARN, PFNFY_USAGE,
    	    	  "%s::move() - ( void* ) 0x%p is not a %s",
    	    	  self->getTypeName(),
    	    	  elt,
    	    	  memType->getName() );
    }
    return -1;
}

}

////////////////////////////////////////////////////////////////////////
// print list ... as well as pfList::print() does at least.

int
pfuAutoList::
print ( uint, uint, char* prefix, FILE* file )
{
    return fprintf( file ? file : stderr,
    		    "%s%s: 0x%p %d elts of %d bytes\n",
    		    prefix ? prefix : "",
    		    getTypeName(),
    		    this,
    		    getNum(),
    		    sizeof( pfMemory* ) );
}

extern "C"
{

// works with pfPrint()

}

////////////////////////////////////////////////////////////////////////
// remove element from tail of list. return element if any.

pfMemory*
pfuAutoList::
rem ()
{
    int     	which = getNum() - 1;
    pfMemory*	elt = get( which );

    if ( elt )
    {
    	List->removeIndex( which );
    	elt->unref();
    }
    return elt;
}

extern "C"
{

void*
pfuRem ( pfuAutoList* self )
{
    pfMemory*	elt = self->rem();

    // NOTE: return getData when dealing with pfMemory
    return elt && elt->isExactType( pfMemory::getClassType() )
    	?  elt->getData()
    	:  elt;
}

}

////////////////////////////////////////////////////////////////////////
// remove element from list if present.

int
pfuAutoList::
remove ( pfMemory* elt )
{
    int ok = List->remove( elt );

    if ( ok >= 0 )
    	elt->unref();

    return ok;
}

extern "C"
{

int
pfuRemove ( pfuAutoList* self, void* elt )
{
    pfType* memType = pfMemory::getClassType();
    
    if ( pfMemory::isOfType( elt, memType ) )
    {
    	return self->remove( pfMemory::getMemory( elt ) );
    }
    else
    {
    	pfNotify( PFNFY_WARN, PFNFY_USAGE,
    	    	  "%s::remove() - ( void* ) 0x%p is not a %s",
    	    	  self->getTypeName(),
    	    	  elt,
    	    	  memType->getName() );
    }
    return -1;
}

}

////////////////////////////////////////////////////////////////////////
// remove element at position given from list if present.

void
pfuAutoList::
removeIndex ( int which )
{
    pfMemory*	elt = get( which );

    if ( elt )
    {
    	List->removeIndex( which );
    	elt->unref();
    }
}

extern "C"
{

void
pfuRemoveIndex ( pfuAutoList* self, int which )
{
    self->removeIndex( which );
}

}

////////////////////////////////////////////////////////////////////////
// replace first instance of old element with new element.

int
pfuAutoList::
replace ( pfMemory* oldElt, pfMemory* newElt )
{
    int ok = List->replace( oldElt, newElt );
    
    if ( ok >= 0 )
    {
    	oldElt->unref();
    	newElt->ref();
    }
    return ok;
}

extern "C"
{

int
pfuReplace ( pfuAutoList* self, void* oldElt, void* newElt )
{
    pfType* memType = pfMemory::getClassType();
    
    if ( pfMemory::isOfType( oldElt, memType ) )
    {
    	if ( pfMemory::isOfType( newElt, memType ) )
	{
	    return self->replace( pfMemory::getMemory( oldElt ),
    	    	    		  pfMemory::getMemory( newElt ) );
	}
	else
	{
    	    pfNotify( PFNFY_WARN, PFNFY_USAGE,
    	    	      "%s::replace() - ( void* ) 0x%p is not a %s",
    	    	      self->getTypeName(),
    	    	      newElt,
    	    	      memType->getName() );
	}
    }
    else
    {
    	pfNotify( PFNFY_WARN, PFNFY_USAGE,
    	    	  "%s::replace() - ( void* ) 0x%p is not a %s",
    	    	  self->getTypeName(),
    	    	  oldElt,
    	    	  memType->getName() );
    }
    return -1;
}

}

////////////////////////////////////////////////////////////////////////
// reset list to empty state.

void
pfuAutoList::
reset ()
{
    destroyElements( List );
    List->reset();
}

extern "C"
{

void
pfuResetList ( pfuAutoList* self )
{
    self->reset();
}

}

////////////////////////////////////////////////////////////////////////
// set indicated element in list with given element.
// release existing element if any.

void
pfuAutoList::
set ( int which, pfMemory* elt )
{
    pfMemory*	oldElt = get( which );

    if ( oldElt )
    	oldElt->unref();

    List->set( which, elt );
    elt->ref();
}

extern "C"
{

void
pfuSet ( pfuAutoList* self, int which, void* elt )
{
    pfType* memType = pfMemory::getClassType();
    
    if ( pfMemory::isOfType( elt, memType ) )
    {
    	self->set( which, pfMemory::getMemory( elt ) );
    }
    else
    {
    	pfNotify( PFNFY_WARN, PFNFY_USAGE,
    	    	  "%s::set() - ( void* ) 0x%p is not a %s",
    	    	  self->getTypeName(),
    	    	  elt,
    	    	  memType->getName() );
    }
}

}

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// compare two lists for recursive, bit-wise equality
// NOTE: consistant with pfCopy(), but not a proper element-wise compare

int
pfuAutoList::
compare ( pfMemory const* rhs ) const
{
    int ok = parentCompare( rhs );

    if ( ok == 0 )
    {
	pfuAutoList const*  other = ( pfuAutoList* ) rhs;

	ok = List->compare( other->List );
	if ( ok == 0 )
	{
	    // compare other data members
	}
    }
    return ok;
}

extern "C"
{

// works with pfCompare()

}

////////////////////////////////////////////////////////////////////////
// get indicated element from list. return element if any.

extern "C"
{

void*
pfuGet( pfuAutoList const* self, int which )
{
    pfMemory*	elt = self->get( which );

    // NOTE: return getData when dealing with pfMemory
    return elt && elt->isExactType( pfMemory::getClassType() )
    	?  elt->getData()
    	:  elt;
}

}

////////////////////////////////////////////////////////////////////////
// get number of elements in list.

extern "C"
{

int
pfuGetNum ( pfuAutoList const* self )
{
    return self->getNum();
}

}

////////////////////////////////////////////////////////////////////////
// search for first instance of indicated element.
// return index if found.

extern "C"
{

int
pfuSearch ( pfuAutoList const* self, void* elt )
{
    pfType* memType = pfMemory::getClassType();
    
    if ( pfMemory::isOfType( elt, memType ) )
    {
    	return self->search( pfMemory::getMemory( elt ) );
    }
    else
    {
    	pfNotify( PFNFY_WARN, PFNFY_USAGE,
    	    	  "%s::search() - ( void* ) 0x%p is not a %s",
    	    	  self->getTypeName(),
    	    	  elt,
    	    	  memType->getName() );
    }
    return -1;
}

}

////////////////////////////////////////////////////////////////////////
// search for first instance of indicated type.
// return index if found.

int
pfuAutoList::
search ( pfType* type ) const
{
    int howMany = getNum();

    for ( int which = 0; which < howMany; ++ which )
    {
	pfMemory*   elt = get( which );

	if ( elt->isOfType( type ) )
	{
	    return which;
	}
    }
    return -1;
}

extern "C"
{

int
pfuSearchForType ( pfuAutoList const* self, pfType* type )
{
    return self->search( type );
}

}