123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- /* Copyright (c) 2002-2012 Croteam Ltd.
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as published by
- the Free Software Foundation
- 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.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
- #ifndef SE_INCL_DYNAMICCONTAINER_CPP
- #define SE_INCL_DYNAMICCONTAINER_CPP
- #ifdef PRAGMA_ONCE
- #pragma once
- #endif
- #include <Engine/Templates/DynamicContainer.h>
- #include <Engine/Base/Memory.h>
- #include <Engine/Templates/StaticStackArray.cpp>
- /*
- * Default constructor.
- */
- template<class Type>
- CDynamicContainer<Type>::CDynamicContainer(void) {
- #if CHECKARRAYLOCKING
- // not locked
- dc_LockCt = 0;
- #endif
- }
- /*
- * Copy constructor.
- */
- template<class Type>
- CDynamicContainer<Type>::CDynamicContainer(CDynamicContainer<Type> &dcOriginal)
- {
- #if CHECKARRAYLOCKING
- // not locked
- dc_LockCt = 0;
- #endif
- // call assignment operator
- (*this) = dcOriginal;
- }
- /*
- * Destructor -- removes all objects.
- */
- template<class Type>
- CDynamicContainer<Type>::~CDynamicContainer(void) {
- Clear();
- }
- /*
- * Remove all objects, and reset the array to initial (empty) state.
- */
- template<class Type>
- void CDynamicContainer<Type>::Clear(void) {
- ASSERT(this!=NULL);
- CStaticStackArray<Type *>::Clear();
- }
- /*
- * Add a given object to container.
- */
- template<class Type>
- void CDynamicContainer<Type>::Add(Type *ptNewObject)
- {
- // set the new pointer
- Push() = ptNewObject;
- }
- /*
- * Insert a given object to container at specified index.
- */
- template<class Type>
- void CDynamicContainer<Type>::Insert(Type *ptNewObject, const INDEX iPos/*=0*/)
- {
- // get number of member that need moving and add new one
- const INDEX ctMovees = CStaticStackArray<Type*>::Count() - iPos;
- CStaticStackArray<Type*>::Push();
- // move all members after insert position one place up
- Type **pptInsertAt = this->sa_Array+iPos;
- Type **pptMoveTo = pptInsertAt +1;
- memmove( pptMoveTo, pptInsertAt, sizeof(Type*)*ctMovees);
- // store pointer to newly inserted member at specified position
- *pptInsertAt = ptNewObject;
- }
- /*
- * Remove a given object from container.
- */
- template<class Type>
- void CDynamicContainer<Type>::Remove(Type *ptOldObject)
- {
- ASSERT(this!=NULL);
- #if CHECKARRAYLOCKING
- // check that not locked for indices
- ASSERT(dc_LockCt == 0);
- #endif
- // find its index
- INDEX iMember=GetIndex(ptOldObject);
- // move last pointer here
- sa_Array[iMember]=sa_Array[Count()-1];
- Pop();
- }
- /* Test if a given object is in the container. */
- template<class Type>
- BOOL CDynamicContainer<Type>::IsMember(Type *ptOldObject)
- {
- ASSERT(this!=NULL);
- // slow !!!!
- // check all members
- for (INDEX iMember=0; iMember<Count(); iMember++) {
- if(sa_Array[iMember]==ptOldObject) {
- return TRUE;
- }
- }
- return FALSE;
- }
- /*
- * Get pointer to a member from it's index.
- */
- template<class Type>
- Type *CDynamicContainer<Type>::Pointer(INDEX iMember) {
- ASSERT(this!=NULL);
- // check that index is currently valid
- ASSERT(iMember>=0 && iMember<Count());
- #if CHECKARRAYLOCKING
- // check that locked for indices
- ASSERT(dc_LockCt>0);
- #endif
- return sa_Array[iMember];
- }
- template<class Type>
- const Type *CDynamicContainer<Type>::Pointer(INDEX iMember) const {
- ASSERT(this!=NULL);
- // check that index is currently valid
- ASSERT(iMember>=0 && iMember<Count());
- #if CHECKARRAYLOCKING
- // check that locked for indices
- ASSERT(dc_LockCt>0);
- #endif
- return sa_Array[iMember];
- }
- /*
- * Lock for getting indices.
- */
- template<class Type>
- void CDynamicContainer<Type>::Lock(void) {
- ASSERT(this!=NULL);
- #if CHECKARRAYLOCKING
- ASSERT(dc_LockCt>=0);
- // increment lock counter
- dc_LockCt++;
- #endif
- }
- /*
- * Unlock after getting indices.
- */
- template<class Type>
- void CDynamicContainer<Type>::Unlock(void) {
- ASSERT(this!=NULL);
- #if CHECKARRAYLOCKING
- dc_LockCt--;
- ASSERT(dc_LockCt>=0);
- #endif
- }
- /*
- * Get index of a member from it's pointer.
- */
- template<class Type>
- INDEX CDynamicContainer<Type>::Index(Type *ptMember) {
- ASSERT(this!=NULL);
- // check that locked for indices
- #if CHECKARRAYLOCKING
- ASSERT(dc_LockCt>0);
- #endif
- return GetIndex(ptMember);
- }
- /*
- * Get index of a member from it's pointer without locking.
- */
- template<class Type>
- INDEX CDynamicContainer<Type>::GetIndex(Type *ptMember) {
- ASSERT(this!=NULL);
- // slow !!!!
- // check all members
- for (INDEX iMember=0; iMember<Count(); iMember++) {
- if(sa_Array[iMember]==ptMember) {
- return iMember;
- }
- }
- ASSERTALWAYS("CDynamicContainer<Type><>::Index(): Not a member of this container!");
- return 0;
- }
- /* Get first object in container (there must be at least one when calling this). */
- template<class Type>
- Type &CDynamicContainer<Type>::GetFirst(void)
- {
- ASSERT(Count()>=1);
- return *sa_Array[0];
- }
- /*
- * Assignment operator.
- */
- template<class Type>
- CDynamicContainer<Type> &CDynamicContainer<Type>::operator=(CDynamicContainer<Type> &coOriginal)
- {
- CStaticStackArray<Type *>::operator=(coOriginal);
- return *this;
- }
- /*
- * Move all elements of another array into this one.
- */
- template<class Type>
- void CDynamicContainer<Type>::MoveContainer(CDynamicContainer<Type> &coOther)
- {
- ASSERT(this!=NULL && &coOther!=NULL);
- // check that not locked for indices
- #if CHECKARRAYLOCKING
- ASSERT(dc_LockCt==0 && coOther.dc_LockCt==0);
- #endif
- CStaticStackArray<Type*>::MoveArray(coOther);
- }
- /////////////////////////////////////////////////////////////////////
- // CDynamicContainerIterator<Type>
- /*
- * Template class for iterating dynamic array.
- */
- template<class Type>
- class CDynamicContainerIterator {
- private:
- INDEX dci_Index; // index of current element
- CDynamicContainer<Type> &dci_Array; // reference to array
- public:
- /* Constructor for given array. */
- inline CDynamicContainerIterator(CDynamicContainer<Type> &da);
- /* Destructor. */
- inline ~CDynamicContainerIterator(void);
- /* Move to next object. */
- inline void MoveToNext(void);
- /* Check if finished. */
- inline BOOL IsPastEnd(void);
-
- /* Get current element. */
- Type &Current(void) { return *dci_Array.Pointer(dci_Index); }
- Type &operator*(void) { return *dci_Array.Pointer(dci_Index); }
- operator Type *(void) { return dci_Array.Pointer(dci_Index); }
- Type *operator->(void) { return dci_Array.Pointer(dci_Index); }
- };
- /*
- * Constructor for given array.
- */
- template<class Type>
- inline CDynamicContainerIterator<Type>::CDynamicContainerIterator(CDynamicContainer<Type> &da) : dci_Array(da) {
- // lock indices
- dci_Array.Lock();
- dci_Index = 0;
- }
- /*
- * Destructor.
- */
- template<class Type>
- inline CDynamicContainerIterator<Type>::~CDynamicContainerIterator(void) {
- // unlock indices
- dci_Array.Unlock();
- dci_Index = -1;
- }
- /*
- * Move to next object.
- */
- template<class Type>
- inline void CDynamicContainerIterator<Type>::MoveToNext(void) {
- ASSERT(this!=NULL);
- dci_Index++;
- }
- /*
- * Check if finished.
- */
- template<class Type>
- inline BOOL CDynamicContainerIterator<Type>::IsPastEnd(void) {
- ASSERT(this!=NULL);
- return dci_Index>=dci_Array.Count();
- }
- // iterate whole dynamic container
- /* NOTE: The iterator defined by this macro must be destroyed before adding/removing
- * elements in the container. To do so, embed the for loop in additional curly braces.
- */
- #define FOREACHINDYNAMICCONTAINER(container, type, iter) \
- for(CDynamicContainerIterator<type> iter(container); !iter.IsPastEnd(); iter.MoveToNext() )
- #endif /* include-once check. */
|