#ifndef MXLIST_H #define MXLIST_H #include "mxcollection.h" #include "mxcore.h" #include "mxtypes.h" template class MxList; template class MxListCursor; template class MxPtrList : public MxList { public: MxPtrList(void (*p_destroy)(T*) = Destroy) { m_customDestructor = p_destroy; } }; template class MxListEntry { public: MxListEntry() {} MxListEntry(T p_obj, MxListEntry* p_prev) { m_obj = p_obj; m_prev = p_prev; m_next = NULL; } MxListEntry(T p_obj, MxListEntry* p_prev, MxListEntry* p_next) { m_obj = p_obj; m_prev = p_prev; m_next = p_next; } T GetValue() { return this->m_obj; } MxListEntry* GetNext() { return m_next; } MxListEntry* GetPrev() { return m_prev; } void SetValue(T p_obj) { m_obj = p_obj; } void SetNext(MxListEntry* p_next) { m_next = p_next; } void SetPrev(MxListEntry* p_prev) { m_prev = p_prev; } private: T m_obj; MxListEntry* m_prev; MxListEntry* m_next; }; // SIZE 0x18 template class MxList : protected MxCollection { public: MxList() { m_last = NULL; m_first = NULL; } virtual ~MxList() override; void Append(T p_obj) { _InsertEntry(p_obj, this->m_last, NULL); }; void DeleteAll(); MxU32 GetCount() { return this->m_count; } void SetDestroy(void (*p_customDestructor)(T)) { this->m_customDestructor = p_customDestructor; } friend class MxListCursor; protected: MxListEntry* m_first; // 0x10 MxListEntry* m_last; // 0x14 void _DeleteEntry(MxListEntry* match); MxListEntry* _InsertEntry(T, MxListEntry*, MxListEntry*); }; template class MxListCursor : public MxCore { public: MxListCursor(MxList* p_list) { m_list = p_list; m_match = NULL; } MxBool Find(T p_obj); void Detach(); void Destroy(); MxBool Next(T& p_obj); MxBool Current(T& p_obj); MxBool Advance(); MxBool HasMatch() { return m_match != NULL; } void SetValue(T p_obj); void Head() { m_match = m_list->m_first; } void Reset() { m_match = NULL; } void Prepend(T p_newobj); private: MxList* m_list; MxListEntry* m_match; }; // Unclear purpose template class MxListCursorChild : public MxListCursor { public: MxListCursorChild(MxList* p_list) : MxListCursor(p_list) {} }; // Unclear purpose template class MxListCursorChildChild : public MxListCursorChild { public: MxListCursorChildChild(MxList* p_list) : MxListCursorChild(p_list) {} }; template MxList::~MxList() { DeleteAll(); } template inline void MxList::DeleteAll() { for (MxListEntry* t = m_first;;) { if (!t) break; MxListEntry* next = t->GetNext(); this->m_customDestructor(t->GetValue()); delete t; t = next; } this->m_count = 0; m_last = NULL; m_first = NULL; } template inline MxListEntry* MxList::_InsertEntry(T p_newobj, MxListEntry* p_prev, MxListEntry* p_next) { MxListEntry* newEntry = new MxListEntry(p_newobj, p_prev, p_next); if (p_prev) p_prev->SetNext(newEntry); else this->m_first = newEntry; if (p_next) p_next->SetPrev(newEntry); else this->m_last = newEntry; this->m_count++; return newEntry; } template inline void MxList::_DeleteEntry(MxListEntry* match) { if (match->GetPrev()) match->GetPrev()->SetNext(match->GetNext()); else m_first = match->GetNext(); if (match->GetNext()) match->GetNext()->SetPrev(match->GetPrev()); else m_last = match->GetPrev(); delete match; this->m_count--; } template inline MxBool MxListCursor::Find(T p_obj) { for (m_match = m_list->m_first; m_match && m_list->Compare(m_match->GetValue(), p_obj); m_match = m_match->GetNext()) ; return m_match != NULL; } template inline void MxListCursor::Detach() { m_list->_DeleteEntry(m_match); m_match = NULL; } template inline void MxListCursor::Destroy() { if (m_match) { m_list->m_customDestructor(m_match->GetValue()); Detach(); } } template inline MxBool MxListCursor::Next(T& p_obj) { if (!m_match) m_match = m_list->m_first; else m_match = m_match->GetNext(); if (m_match) p_obj = m_match->GetValue(); return m_match != NULL; } template inline MxBool MxListCursor::Current(T& p_obj) { if (m_match) p_obj = m_match->GetValue(); return m_match != NULL; } template inline MxBool MxListCursor::Advance() { if (!m_match) m_match = m_list->m_first; else m_match = m_match->GetNext(); return m_match != NULL; } template inline void MxListCursor::SetValue(T p_obj) { if (m_match) m_match->SetValue(p_obj); } template inline void MxListCursor::Prepend(T p_newobj) { if (m_match) m_list->_InsertEntry(p_newobj, m_match->GetPrev(), m_match); } #endif // MXLIST_H