/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a license // agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// #ifndef _ODSTACK_H_ #define _ODSTACK_H_ #include "TD_PackPush.h" template class OdStackItem; template class OdStack; template class OdCachingStack; /** \details */ template class OdStackItem : public T { friend class OdStack; friend class OdCachingStack; protected: OdStackItem* m_pUnder; inline OdStackItem(OdStackItem* pUnder, const T& val) : T(val), m_pUnder(pUnder) { } inline OdStackItem(OdStackItem* pUnder, T&& val) : T(std::move(val)), m_pUnder(pUnder) { } inline OdStackItem(OdStackItem* pUnder) : m_pUnder(pUnder) { } }; /** \details */ template class OdStack { typedef OdStackItem TItem; public: TItem* m_pTop; inline OdStack() : m_pTop(0) { } inline void push(const T& inVal) { m_pTop = new TItem(m_pTop, inVal); } inline void push(T&& inVal) { m_pTop = new TItem(m_pTop, std::move(inVal)); } inline T* push() { m_pTop = new TItem(m_pTop); return top(); } inline void pop(T& outVal) { ODA_ASSERT(m_pTop); // pop from empty stack outVal = *m_pTop; pop(); } inline const T* top() const { return m_pTop; } inline T* top() { return m_pTop; } inline void pop() { TItem* pTop = m_pTop; ODA_ASSERT(pTop); // pop from empty stack m_pTop = pTop->m_pUnder; delete pTop; } inline ~OdStack() { while(m_pTop) { pop(); } } inline T* beforeTop() const { ODA_ASSERT(m_pTop); return m_pTop->m_pUnder; } bool empty()const { return m_pTop == 0; } size_t size() const { size_t n = 0; for ( TItem* p = m_pTop; p; p = p->m_pUnder) ++n; return n; } }; /** \details */ template class OdCachingStack : public OdStack { protected: typedef OdStack Base; typedef OdStackItem StackItem; StackItem *m_pCache; protected: StackItem *getItem(StackItem *pUnder) { if (m_pCache) { StackItem *pItem = m_pCache; m_pCache = m_pCache->m_pUnder; pItem->m_pUnder = pUnder; return pItem; } return new StackItem(pUnder); } void freeItems(StackItem *&pItems) { while (pItems) { StackItem *pItem = pItems; pItems = pItem->m_pUnder; delete pItem; } } public: inline OdCachingStack() : m_pCache(nullptr) { } inline ~OdCachingStack() { freeItems(Base::m_pTop); freeItems(m_pCache); } inline void push(const T& inVal) { *static_cast(Base::m_pTop = getItem(Base::m_pTop)) = inVal; } inline void push(T&& inVal) { *static_cast(Base::m_pTop = getItem(Base::m_pTop)) = std::move(inVal); } inline T* push() { return Base::m_pTop = getItem(Base::m_pTop); } inline void pop() { StackItem *pTop = Base::m_pTop; ODA_ASSERT(pTop); // pop from empty stack Base::m_pTop = pTop->m_pUnder; pTop->m_pUnder = m_pCache; m_pCache = pTop; } inline void pop(T& outVal) { ODA_ASSERT(Base::m_pTop); // pop from empty stack outVal = *Base::m_pTop; pop(); } inline void clearCache() { freeItems(m_pCache); } }; #include "TD_PackPop.h" #endif //#ifndef _ODSTACK_H_