isle/LEGO1/omni/include/mxlist.h
MS 9ab3954bbb
Minor tweak to MxList template (#1083)
* Beta addrs for MxList and related functions

* MxList DeleteAll and Empty functions
2024-08-11 13:23:39 -07:00

346 lines
6 KiB
C++

#ifndef MXLIST_H
#define MXLIST_H
#include "mxcollection.h"
#include "mxcore.h"
#include "mxtypes.h"
template <class T>
class MxList;
template <class T>
class MxListCursor;
template <class T>
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 T>
class MxList : protected MxCollection<T> {
public:
MxList() { m_first = m_last = NULL; }
~MxList() override;
void Append(T p_obj) { InsertEntry(p_obj, this->m_last, NULL); }
void Prepend(T p_obj) { InsertEntry(p_obj, NULL, this->m_first); }
void DeleteAll();
void Empty();
MxU32 GetCount() { return this->m_count; }
friend class MxListCursor<T>;
using MxCollection<T>::SetDestroy;
protected:
MxListEntry<T>* m_first; // 0x10
MxListEntry<T>* m_last; // 0x14
void DeleteEntry(MxListEntry<T>*);
MxListEntry<T>* InsertEntry(T, MxListEntry<T>*, MxListEntry<T>*);
};
// SIZE 0x18
template <class T>
class MxPtrList : public MxList<T*> {
public:
MxPtrList(MxBool p_ownership) { SetOwnership(p_ownership); }
static void Destroy(T* p_obj) { delete p_obj; }
void SetOwnership(MxBool p_ownership)
{
MxCollection<T*>::SetDestroy(p_ownership ? MxPtrList<T>::Destroy : MxCollection<T*>::Destroy);
}
};
// SIZE 0x10
template <class T>
class MxListCursor : public MxCore {
public:
MxListCursor(MxList<T>* p_list)
{
m_list = p_list;
m_match = NULL;
}
MxBool Find(T p_obj);
void Detach();
void Destroy();
MxBool Next();
MxBool Next(T& p_obj);
MxBool Prev();
MxBool Prev(T& p_obj);
MxBool Current(T& p_obj);
MxBool First(T& p_obj);
MxBool Last(T& p_obj);
MxBool HasMatch() { return m_match != NULL; }
void SetValue(T p_obj);
MxBool Head()
{
m_match = m_list->m_first;
return m_match != NULL;
}
MxBool Tail()
{
m_match = m_list->m_last;
return m_match != NULL;
}
void Reset() { m_match = NULL; }
void Prepend(T p_newobj);
private:
MxList<T>* m_list; // 0x08
MxListEntry<T>* m_match; // 0x0c
};
// SIZE 0x10
template <class T>
class MxPtrListCursor : public MxListCursor<T*> {
public:
MxPtrListCursor(MxPtrList<T>* p_list) : MxListCursor<T*>(p_list) {}
};
template <class T>
MxList<T>::~MxList()
{
DeleteAll();
}
// Delete entries and values
template <class T>
inline void MxList<T>::DeleteAll()
{
MxListEntry<T>* next;
for (MxListEntry<T>* t = m_first; t; t = next) {
next = t->GetNext();
this->m_customDestructor(t->GetValue());
delete t;
}
this->m_count = 0;
m_first = m_last = NULL;
}
// Delete entries only
template <class T>
inline void MxList<T>::Empty()
{
MxListEntry<T>* next;
for (MxListEntry<T>* t = m_first; t; t = next) {
next = t->GetNext();
delete t;
}
this->m_count = 0;
m_first = m_last = NULL;
}
template <class T>
inline MxListEntry<T>* MxList<T>::InsertEntry(T p_newobj, MxListEntry<T>* p_prev, MxListEntry<T>* p_next)
{
MxListEntry<T>* newEntry = new MxListEntry<T>(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 <class T>
inline void MxList<T>::DeleteEntry(MxListEntry<T>* p_match)
{
if (p_match->GetPrev()) {
p_match->GetPrev()->SetNext(p_match->GetNext());
}
else {
m_first = p_match->GetNext();
}
if (p_match->GetNext()) {
p_match->GetNext()->SetPrev(p_match->GetPrev());
}
else {
m_last = p_match->GetPrev();
}
delete p_match;
this->m_count--;
}
template <class T>
inline MxBool MxListCursor<T>::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 <class T>
inline void MxListCursor<T>::Detach()
{
if (m_match) {
m_list->DeleteEntry(m_match);
m_match = NULL;
}
}
template <class T>
inline void MxListCursor<T>::Destroy()
{
if (m_match) {
m_list->m_customDestructor(m_match->GetValue());
m_list->DeleteEntry(m_match);
m_match = NULL;
}
}
template <class T>
inline MxBool MxListCursor<T>::Next()
{
if (!m_match) {
m_match = m_list->m_first;
}
else {
m_match = m_match->GetNext();
}
return m_match != NULL;
}
template <class T>
inline MxBool MxListCursor<T>::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 <class T>
inline MxBool MxListCursor<T>::Prev()
{
if (!m_match) {
m_match = m_list->m_last;
}
else {
m_match = m_match->GetPrev();
}
return m_match != NULL;
}
template <class T>
inline MxBool MxListCursor<T>::Prev(T& p_obj)
{
if (!m_match) {
m_match = m_list->m_last;
}
else {
m_match = m_match->GetPrev();
}
if (m_match) {
p_obj = m_match->GetValue();
}
return m_match != NULL;
}
template <class T>
inline MxBool MxListCursor<T>::Current(T& p_obj)
{
if (m_match) {
p_obj = m_match->GetValue();
}
return m_match != NULL;
}
template <class T>
inline MxBool MxListCursor<T>::First(T& p_obj)
{
m_match = m_list->m_first;
if (m_match) {
p_obj = m_match->GetValue();
}
return m_match != NULL;
}
template <class T>
inline MxBool MxListCursor<T>::Last(T& p_obj)
{
m_match = m_list->m_last;
if (m_match) {
p_obj = m_match->GetValue();
}
return m_match != NULL;
}
template <class T>
inline void MxListCursor<T>::SetValue(T p_obj)
{
if (m_match) {
m_match->SetValue(p_obj);
}
}
template <class T>
inline void MxListCursor<T>::Prepend(T p_newobj)
{
if (m_match) {
m_list->InsertEntry(p_newobj, m_match->GetPrev(), m_match);
}
}
#endif // MXLIST_H