// // File: hzTmplStack.h // // Legal Notice: This file is part of the HadronZoo C++ Class Library. // // Copyright 2025 HadronZoo Project (http://www.hadronzoo.com) // // The HadronZoo C++ Class Library is free software: You can redistribute it, and/or modify it under the terms of the GNU Lesser General Public License, as published by the Free // Software Foundation, either version 3 of the License, or any later version. // // The HadronZoo C++ Class Library 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 Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License along with the HadronZoo C++ Class Library. If not, see http://www.gnu.org/licenses. //
#ifndef hzTmplStack_h #define hzTmplStack_h
#include "hzString.h" #include "hzLock.h" #include "hzProcess.h"
/* ** Prototypes */
void Fatal (const char* va_alist ...) ;
/* ** Definitions */
template <class OBJ> class _hz_stackitem { // Category: Collection Support // // List element containing an element and a pointer to the next element. For use in the unordered list class templates, hzList, hzQue and hzStack.
public: _hz_stackitem* next ; // Next item in list OBJ m_Obj ; // Object in list
_hz_stackitem (OBJ obj) { next = 0 ; m_Obj = obj ; } } ;
template <class OBJ> class hzStack { // Category: Object Collection // // The hzStack class template faciliates a memory resident stack of objects. A stack is characterized by PUSH and PULL operations in which new // objects are injected at the front of the stack (pushed) and objects are removed from the front of the stack (pulled). This provides a LIFO // (last-in, first-out) operation. This differs from a que (hzQue) in which new objects are placed at the back of a que and popped in order.
private: struct _stack_ca { // Struct to hold actual content (avoid hard copying)
_hz_stackitem<OBJ>* m_pList ; // Start of list of objects in stack _hz_stackitem<OBJ>* m_pLast ; // Pointer to last object in the stack
hzLocker* m_pLock ; // Locking (off by default) hzString m_Name ; // Diagnostics & reports uint32_t m_nCount ; // Population mutable int32_t m_nCopy ; // Copy count OBJ m_Default ; // Default (null) element
_stack_ca (void) { memset(&m_Default, 0, sizeof(OBJ)) ; m_pList = m_pLast = 0 ; m_pLock = 0 ; m_nCount = m_nCopy = 0 ; } ~_stack_ca (void) { delete m_pLock ; }
void SetLock (hzLockOpt eLock) { if (eLock == HZ_ATOMIC) m_pLock = new hzLockRW() ; if (eLock == HZ_MUTEX) m_pLock = new hzLockRWD() ; }
void LockRead (void) { if (m_pLock) m_pLock->LockRead() ; } void LockWrite (void) { if (m_pLock) m_pLock->LockWrite() ; } void Unlock (void) { if (m_pLock) m_pLock->Unlock() ; } } ;
_stack_ca* mx ; // Pointer to internal content
// Prevent copies hzStack<OBJ> (const hzStack<OBJ>&) ; hzStack<OBJ>& operator= (const hzStack<OBJ>&) ;
public: // Constructor hzStack (hzLockOpt eLock = HZ_NOLOCK) { mx = new _stack_ca() ; mx->SetLock(eLock) ; } hzStack (const hzString name) { mx = new _stack_ca() ; mx->m_Name = name ; mx->SetLock(HZ_MUTEX) ; }
// Destructor ~hzStack (void) { if (mx->m_nCopy > 0) mx->m_nCopy-- ; else { Clear() ; delete mx ; } }
uint32_t Count (void) { return mx->m_nCount ; }
/* const hzStack<OBJ>& operator= (const hzStack<OBJ>& op) { // If this control area is the same as that of the operand, do nothing. Otherwise decouple from or clear the control area and adopt that of the operand. if (mx == op.mx) return *this ;
if (mx->m_nCopy) mx->m_nCopy-- ; else mx->Clear() ;
mx = op.mx ; mx->m_nCopy++ ; return *this ; } */
void Clear (void) { // Delete all objects from the stack
_hz_stackitem<OBJ>* pC ; // Current object pointer _hz_stackitem<OBJ>* pN ; // Next object in series
for (pC = mx->m_pList ; pC ; pC = pN) { pN = pC->next ; delete pC ; }
mx->m_pList = mx->m_pLast = 0 ; mx->m_nCount = 0 ; }
void Push (const OBJ obj) { // Push an object onto the stack // // Argument: obj Object to push // Returns: None
_hzfunc_ct("hzStack::Push") ;
_hz_stackitem<OBJ>* pTL ; // New object pointer
if (!(pTL = new _hz_stackitem<OBJ>(obj))) Fatal("hzStack::Push. Allocaction failure") ;
if (mx->m_pList == 0) mx->m_pList = mx->m_pLast = pTL ; else { //mx->m_pLast->m_pNext = pTL ; mx->m_pLast->next = pTL ; mx->m_pLast = pTL ; }
mx->m_nCount++ ; }
// Return element OBJ& Pull (void) { // Pull an object from the stack // // Arguments: None // Returns: Referenece to last object placed on stack
_hz_stackitem<OBJ>* pTL ; // Object-link iterator
OBJ obj ; // Target object
if ((pTL = mx->m_pList)) { obj = mx->m_pList->m_Obj ; //mx->m_pList = mx->m_pList->m_pNext ; mx->m_pList = mx->m_pList->next ; delete pTL ; mx->m_nCount-- ; }
return mx->m_Default ; }
hzEcode Delete (const OBJ& obj) { // Delete the specified object from the stack // // Argument: obj Object to be deleted // // Returns: E_NOTFOUND If the object does not exist // E_OK If the object was deleted
_hz_stackitem<OBJ>* pTL ; // Current link _hz_stackitem<OBJ>* pPL ; // Previous link
hzEcode rc = E_NOTFOUND ; // Return code
// match obj pointer to one on list
pPL = 0 ; for (pTL = mx->m_pList ; pTL ; pTL = pTL->m_pNext) { if (pTL->m_Obj == obj) { // found item to delete if (pTL == mx->m_pList) //mx->m_pList = mx->m_pList->m_pNext ; mx->m_pList = mx->m_pList->next ;
// If the item is the last if (pTL == mx->m_pLast) mx->m_pLast = pPL ;
// tie adjacent items together if (pPL) //pPL->m_pNext = pTL->m_pNext; pPL->next = pTL->next;
delete pTL ; mx->m_nCount-- ; rc = E_OK ; break ; }
pPL = pTL ; }
return rc ; } } ;
#endif // hzTmplStack_h