/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2016, 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 Teigha(R) software pursuant to a license // agreement with Open Design Alliance. // Teigha(R) Copyright (C) 2002-2016 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 _ODA_UNIDIRECTIONALLISTT_H_ #define _ODA_UNIDIRECTIONALLISTT_H_ #include "OdArrayMemAlloc.h" #include "TD_PackPush.h" template, class Mm = OdrxMemoryManager> class OdUnidirectionalList; /** \details This class declares the unidirectional list. Library: TD_Db */ template class OdUnidirectionalList { struct SNode { SNode() : m_pNext(NULL) { } public: SNode* m_pNext; T m_value; }; class CmpValues { public: CmpValues(const T& value) : m_value(value) { } bool operator()(const T& value) const { return (m_value == value); } protected: const T& m_value; }; public: class ConstIterator { public: ConstIterator(SNode* pNode = NULL) : m_pNode(pNode) { } const T& operator*() const { ODA_ASSERT(m_pNode != NULL); return m_pNode->m_value; } const T* operator->() const { ODA_ASSERT(m_pNode != NULL); return &(m_pNode->m_value); } ConstIterator& operator++() { ODA_ASSERT(m_pNode != NULL); m_pNode = m_pNode->m_pNext; return *this; } ConstIterator operator++(int) { ODA_ASSERT(m_pNode != NULL); return ConstIterator(m_pNode->m_pNext); } bool operator==(const ConstIterator& it) const { return (m_pNode == it.m_pNode); } bool operator!=(const ConstIterator& it) const { return (m_pNode != it.m_pNode); } SNode* node() { return m_pNode; } void setNode(SNode* pNode) { m_pNode = pNode; } private: ConstIterator& operator--() { return *this; } ConstIterator operator--(int) { return ConstIterator(); } protected: SNode* m_pNode; }; class Iterator : public ConstIterator { public: Iterator(SNode* pNode = NULL) : ConstIterator(pNode) { } T& operator*() { ODA_ASSERT(ConstIterator::m_pNode != NULL); return ConstIterator::m_pNode->m_value; } T* operator->() { ODA_ASSERT(ConstIterator::m_pNode != NULL); return &(ConstIterator::m_pNode->m_value); } Iterator& operator++() { ODA_ASSERT(ConstIterator::m_pNode != NULL); ConstIterator::m_pNode = ConstIterator::m_pNode->m_pNext; return *this; } Iterator operator++(int) { ODA_ASSERT(ConstIterator::m_pNode != NULL); return Iterator(ConstIterator::m_pNode->m_pNext); } private: Iterator& operator--() { return *this; } Iterator operator--(int) { return Iterator(); } }; typedef typename A::size_type size_type; typedef Iterator iterator; typedef ConstIterator const_iterator; public: OdUnidirectionalList(); OdUnidirectionalList(const OdUnidirectionalList& list); ~OdUnidirectionalList(); OdUnidirectionalList& operator=(const OdUnidirectionalList& list); iterator begin(); const_iterator begin() const; iterator end(); const_iterator end() const; size_type size() const; bool isEmpty() const; iterator insertAfter(const_iterator it, const T& value = T()); iterator insertAtBegin(const T& value = T()); iterator removeAfter(const_iterator it); void clear(); bool find(iterator& it, iterator& prevIt, const T& value , const_iterator prevStartIt = const_iterator()) const; bool find(iterator& it, const T& value) const; template bool findIf(iterator& it, iterator& prevIt, P pred , const_iterator prevStartIt = const_iterator()) const; template bool findIf(iterator& it, P pred) const; bool operator==(const OdUnidirectionalList& list) const; protected: static SNode* createNode(); static SNode* createNode(const T& value); static void destroyNode(SNode* pNode); static SNode* copyList(SNode* pNode); private: SNode* m_pHead; size_type m_size; }; template inline OdUnidirectionalList::OdUnidirectionalList() : m_pHead(NULL), m_size(0) { } template inline OdUnidirectionalList::OdUnidirectionalList(const OdUnidirectionalList& list) : m_pHead(copyList(list.m_pHead)), m_size(list.m_size) { } template inline OdUnidirectionalList::~OdUnidirectionalList() { clear(); } template inline OdUnidirectionalList& OdUnidirectionalList::operator=(const OdUnidirectionalList& list) { if(this != &list) { clear(); m_pHead = copyList(list.m_pHead); m_size = list.m_size; } return *this; } template inline typename OdUnidirectionalList::SNode* OdUnidirectionalList::createNode() { SNode* pNewNode = reinterpret_cast(Mm::Alloc(sizeof(SNode))); if(pNewNode == NULL) throw OdError(eOutOfMemory); A::construct(&(pNewNode->m_value)); return pNewNode; } template inline typename OdUnidirectionalList::SNode* OdUnidirectionalList::createNode(const T& value) { SNode* pNewNode = reinterpret_cast(Mm::Alloc(sizeof(SNode))); if(pNewNode == NULL) throw OdError(eOutOfMemory); A::construct(&(pNewNode->m_value), value); return pNewNode; } template inline void OdUnidirectionalList::destroyNode(SNode* pNode) { ODA_ASSERT(pNode != NULL); A::destroy(&(pNode->m_value)); Mm::Free(pNode); } template inline typename OdUnidirectionalList::SNode* OdUnidirectionalList::copyList(SNode* pNode) { SNode* pHead = NULL; if(pNode != NULL) { SNode* pNewNode = pHead = createNode(pNode->m_value); pNewNode->m_pNext = NULL; for(pNode = pNode->m_pNext; pNode != NULL; pNode = pNode->m_pNext) { pNewNode->m_pNext = createNode(pNode->m_value); pNewNode->m_pNext->m_pNext = NULL; pNewNode = pNewNode->m_pNext; } } return pHead; } template inline typename OdUnidirectionalList::iterator OdUnidirectionalList::begin() { return iterator(m_pHead); } template inline typename OdUnidirectionalList::const_iterator OdUnidirectionalList::begin() const { return const_iterator(m_pHead); } template inline typename OdUnidirectionalList::iterator OdUnidirectionalList::end() { return iterator(); } template inline typename OdUnidirectionalList::const_iterator OdUnidirectionalList::end() const { return const_iterator(); } template inline typename OdUnidirectionalList::size_type OdUnidirectionalList::size() const { return m_size; } template inline bool OdUnidirectionalList::isEmpty() const { return (m_size == 0); } template inline typename OdUnidirectionalList::iterator OdUnidirectionalList::insertAfter(const_iterator it , const T& value) { SNode* pNode = createNode(value); if(it.node() != NULL) { pNode->m_pNext = it.node()->m_pNext; it.node()->m_pNext = pNode; } else { pNode->m_pNext = m_pHead; m_pHead = pNode; } ++m_size; return iterator(pNode); } template inline typename OdUnidirectionalList::iterator OdUnidirectionalList::insertAtBegin(const T& value) { SNode* pNode = createNode(value); pNode->m_pNext = m_pHead; m_pHead = pNode; ++m_size; return iterator(pNode); } template inline typename OdUnidirectionalList::iterator OdUnidirectionalList::removeAfter(const_iterator it) { if(it.node() != NULL) { SNode* pNode = it.node()->m_pNext; if(pNode != NULL) { it.node()->m_pNext = pNode->m_pNext; destroyNode(pNode); --m_size; } return iterator(it.node()->m_pNext); } SNode* pNode = m_pHead; m_pHead = m_pHead->m_pNext; destroyNode(pNode); --m_size; return iterator(m_pHead); } template inline void OdUnidirectionalList::clear() { SNode* pNode; SNode* pNextNode; for(pNode = m_pHead; pNode != NULL; pNode = pNextNode) { pNextNode = pNode->m_pNext; destroyNode(pNode); } m_pHead = NULL; m_size = 0; } template inline bool OdUnidirectionalList::find(iterator& it, iterator& prevIt , const T& value, const_iterator prevStartIt) const { return find(it, prevIt, CmpValues(value), prevStartIt); } template inline bool OdUnidirectionalList::find(iterator& it, const T& value) const { return find(it, CmpValues(value)); } template template inline bool OdUnidirectionalList::findIf(iterator& it, iterator& prevIt , P pred, const_iterator prevStartIt) const { if(!isEmpty()) { ODA_ASSERT(m_pHead != NULL); SNode* pPrevNode = prevStartIt.node(); SNode* pNode = ((pPrevNode != NULL) ? pPrevNode->m_pNext : m_pHead); for(; pNode != NULL; pPrevNode = pNode, pNode = pNode->m_pNext) { if(pred(pNode->m_value)) { it.setNode(pNode); prevIt.setNode(pPrevNode); return true; } } } return false; } template template inline bool OdUnidirectionalList::findIf(iterator& it, P pred) const { if(!isEmpty()) { ODA_ASSERT(m_pHead != NULL); for(SNode* pNode = m_pHead; pNode != NULL; pNode = pNode->m_pNext) { if(pred(pNode->m_value)) { it.setNode(pNode); return true; } } } return false; } template inline bool OdUnidirectionalList::operator==(const OdUnidirectionalList& list) const { if(m_size == list.m_size) { SNode* pNode1 = m_pHead; SNode* pNode2 = list.m_pHead; for(; pNode1 != NULL; pNode1 = pNode1->m_pNext, pNode2 = pNode2->m_pNext) { ODA_ASSERT(pNode2 != NULL); if(pNode1->m_value != pNode2->m_value) return false; } return true; } return false; } #include "TD_PackPop.h" #endif // _ODA_UNIDIRECTIONALLISTT_H_