/*************************************************************************** * Copyright (C) 2004 by Olivier Stezowski * * stezow(AT)ipnl.in2p3.fr * * * * 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. * ***************************************************************************/ /** @file PtrStack.h template header file */ #ifndef ADF_PtrStack #define ADF_PtrStack #define ADF_PTRSTACK_H ADF_PtrStack #include namespace ADF { //! PtrStack /*! Because of some problems using std containers with pointer (with memory management) this "light" class is to be used as a stack of pointers. new objects (pointers) are added via the Add method. Once added, an individual pointer cannot be removed ... but all the stack can be cleared using the Clear method. The Delete method makes a similar job but also delete the pointers if this is set to owner via the SetOwner method. \warning Don't store pointers on array of objects in this since the delete method called is without [] (delete intead of delete []). MaxSize: \n Max size (allocated) of the stack. This is not a problem since any call of Add will expand the stack if required. FilledSize: \n To get the position of the last non-null pointer CurrentSize: \n Current position in the stack. The At methods allows to get one by one the pointer stored in the stack. (At(GetSize()) checks then is the next pointer exist or not). TO BE USED only with S as UShort_t or UInt_t. */ template class PtrStack { public: // const S fDefaultCapacity = 16; private: // public: T **fStack; S fCurrentSize; S fFilledSize; S fMaxSize; Bool_t fIsOwner; protected: void Init(); void Expand(S); public: PtrStack(S max_size = 16): fStack(0x0), fCurrentSize(0), fFilledSize(0), fMaxSize(max_size), fIsOwner(true) { Init(); } ~PtrStack(); //! The object at position c is now on the top of the stack void SetBottom() { fCurrentSize = 0; } void SetOwner(Bool_t own = false) { fIsOwner = own; } T *At(S which) const { if ( which < fMaxSize ) return fStack[which]; return NULL; } //! Add a new pointer on the stack /*! The current poistion becomes the top position on the stack */ void Add(T *t) { if ( fFilledSize == fMaxSize ) Expand(fMaxSize+10); if ( fFilledSize < fMaxSize ) { fStack[fFilledSize++] = t; fCurrentSize = fFilledSize; } } // void Reserve(S size) { if ( size <= fMaxSize ) return; } //! to get the current position in the stack /*! */ S GetSize() const { return fCurrentSize; } //! /*! remove pointers from the stack without calling delete */ void Clear() { if ( fStack == NULL || fFilledSize == 0 ) return; for (S i = 0; i < fFilledSize; i++) fStack[i] = NULL ; fFilledSize = fCurrentSize = 0; } //! /*! remove pointers from the stack and delete it if this stack owns their objects */ void Delete(); }; template void PtrStack::Init() { if ( fMaxSize <= 0 ) fMaxSize = 1; if ( fStack ) { delete [] fStack; fStack = NULL; } fStack = new T*[fMaxSize]; ::memset(fStack,0,fMaxSize*sizeof(T*)); fFilledSize = 0; fCurrentSize = 0; } template void PtrStack::Expand(S new_size) { if ( new_size <= fMaxSize ) return; T **tmp = new T*[new_size]; ::memset(tmp,0,new_size*sizeof(T*)); for (S i = 0; i < fFilledSize; i++) tmp[i] = At(i); if ( fStack ) { delete [] fStack; fStack = NULL; } fStack = tmp; fMaxSize = new_size; } template PtrStack::~PtrStack() { if ( fStack ) { Delete(); delete [] fStack; } } template void PtrStack::Delete() { if ( fStack == NULL || fFilledSize == 0 ) return; for (S i = 0; i < fMaxSize; i++) { if ( fStack[i] && fIsOwner ) delete fStack[i]; fStack[i] = NULL; } fFilledSize = fCurrentSize = 0; } } #endif