#ifndef MXLIST_H #define MXLIST_H #include "mxtypes.h" #include "mxcore.h" 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; } friend class MxList; friend class MxListCursor; private: T m_obj; MxListEntry *m_prev; MxListEntry *m_next; }; // SIZE 0x10 template class MxListParent : public MxCore { public: MxListParent() { m_count = 0; m_customDestructor = Destroy; } virtual ~MxListParent() {} virtual MxS8 Compare(T, T) { return 0; }; static void Destroy(T) {}; protected: MxU32 m_count; // +0x8 void (*m_customDestructor)(T); // +0xc }; // SIZE 0x18 template class MxList : protected MxListParent { public: MxList() { m_last = NULL; m_first = NULL; } virtual ~MxList(); void Append(T); void OtherAppend(T p_obj) { _InsertEntry(p_obj, this->m_last, NULL); }; void DeleteAll(); MxU32 GetCount() { return 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 private: void _DeleteEntry(MxListEntry *match); void _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(); MxBool Next(T& p_obj); void SetValue(T p_obj); void Head() { m_match = m_list->m_first; } void Reset() { m_match = NULL; } 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->m_next; m_customDestructor(t->GetValue()); delete t; t = next; } m_count = 0; m_last = NULL; m_first = NULL; } template inline void MxList::Append(T p_newobj) { MxListEntry *currentLast = this->m_last; MxListEntry *newEntry = new MxListEntry(p_newobj, currentLast); if (currentLast) currentLast->m_next = newEntry; else this->m_first = newEntry; this->m_last = newEntry; this->m_count++; } template inline void 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->m_next = newEntry; else this->m_first = newEntry; if (p_next) p_next->m_prev = newEntry; else this->m_last = newEntry; this->m_count++; } template inline void MxList::_DeleteEntry(MxListEntry *match) { MxListEntry **pPrev = &match->m_prev; MxListEntry **pNext = &match->m_next; if (match->m_prev) match->m_prev->m_next = *pNext; else m_first = *pNext; if (*pNext) (*pNext)->m_prev = *pPrev; else m_last = *pPrev; delete match; m_count--; } template inline MxBool MxListCursor::Find(T p_obj) { for (m_match = m_list->m_first; m_match && m_list->Compare(m_match->m_obj, p_obj); m_match = m_match->m_next); return m_match != NULL; } template inline void MxListCursor::Detach() { m_list->_DeleteEntry(m_match); m_match = NULL; } template inline MxBool MxListCursor::Next(T& p_obj) { if (!m_match) m_match = m_list->m_first; else m_match = m_match->m_next; if (m_match) p_obj = m_match->GetValue(); return m_match != NULL; } template inline void MxListCursor::SetValue(T p_obj) { if (m_match) m_match->m_obj = p_obj; } #endif // MXLIST_H