SuperMarioOdysseyOnline/include/sead/container/seadTList.h
2022-06-16 14:33:18 -07:00

206 lines
5.4 KiB
C++

#ifndef SEAD_TLIST_H_
#define SEAD_TLIST_H_
#include <container/seadListImpl.h>
namespace sead
{
template <typename T>
class TListNode;
template <typename T>
class TList : public ListImpl
{
public:
using CompareCallback = int (*)(const T*, const T*);
TList() : ListImpl() {}
void pushBack(TListNode<T>* item)
{
item->erase();
item->mList = this;
ListImpl::pushBack(item);
}
void pushFront(TListNode<T>* item)
{
item->erase();
item->mList = this;
ListImpl::pushFront(item);
}
TListNode<T>* popBack() { return static_cast<TListNode<T>*>(ListImpl::popBack()); }
TListNode<T>* popFront() { return static_cast<TListNode<T>*>(ListImpl::popFront()); }
void insertBefore(TListNode<T>* node, TListNode<T>* node_to_insert)
{
ListImpl::insertBefore(node, node_to_insert);
}
void insertAfter(TListNode<T>* node, TListNode<T>* node_to_insert)
{
ListImpl::insertAfter(node, node_to_insert);
}
void erase(TListNode<T>* item)
{
if (!item->mList)
return;
item->mList = nullptr;
ListImpl::erase(item);
}
TListNode<T>* front() const { return static_cast<TListNode<T>*>(ListImpl::front()); }
TListNode<T>* back() const { return static_cast<TListNode<T>*>(ListImpl::back()); }
TListNode<T>* nth(int n) const { return static_cast<TListNode<T>*>(ListImpl::nth(n)); }
s32 indexOf(const TListNode<T>* node) const { return ListImpl::indexOf(node); }
void swap(TListNode<T>* n1, TListNode<T>* n2) { ListImpl::swap(n1, n2); }
void moveAfter(TListNode<T>* basis, TListNode<T>* n) { ListImpl::moveAfter(basis, n); }
void moveBefore(TListNode<T>* basis, TListNode<T>* n) { ListImpl::moveBefore(basis, n); }
void sort(s32 offset, CompareCallback cmp) { ListImpl::sort<T>(offset, cmp); }
void mergeSort(s32 offset, CompareCallback cmp) { ListImpl::mergeSort<T>(offset, cmp); }
TListNode<T>* find(const void* ptr, s32 offset, CompareCallback cmp) const
{
return static_cast<TListNode<T>*>(ListImpl::find(ptr, offset, cmp));
}
void uniq(s32 offset, CompareCallback cmp) { ListImpl::uniq(offset, cmp); }
void clear() { ListImpl::clear(); }
TListNode<T>* prev(const TListNode<T>* node) const
{
auto prev_node = static_cast<TListNode<T>*>(node->prev());
if (prev_node == &mStartEnd)
return nullptr;
return prev_node;
}
TListNode<T>* next(const TListNode<T>* node) const
{
auto next_node = static_cast<TListNode<T>*>(node->next());
if (next_node == &mStartEnd)
return nullptr;
return next_node;
}
class iterator
{
public:
iterator(TListNode<T>* ptr) : mPtr(ptr) {}
iterator& operator++()
{
mPtr = static_cast<TListNode<T>*>(mPtr->next());
return *this;
}
iterator& operator--()
{
mPtr = static_cast<TListNode<T>*>(mPtr->prev());
return *this;
}
T& operator*() const { return mPtr->mData; }
T* operator->() const { return &mPtr->mData; }
friend bool operator==(iterator it1, iterator it2) { return it1.mPtr == it2.mPtr; }
friend bool operator!=(iterator it1, iterator it2) { return !(it1 == it2); }
private:
TListNode<T>* mPtr;
};
iterator begin() const { return iterator(static_cast<TListNode<T>*>(mStartEnd.next())); }
iterator end() const
{
return iterator(static_cast<TListNode<T>*>(const_cast<ListNode*>(&mStartEnd)));
}
class robustIterator
{
public:
robustIterator(TListNode<T>* ptr) : mPtr(ptr)
{
mPtrNext = static_cast<TListNode<T>*>(mPtr->next());
}
robustIterator& operator++()
{
mPtr = mPtrNext;
mPtrNext = static_cast<TListNode<T>*>(mPtrNext->next());
return *this;
}
T& operator*() const { return mPtr->mData; }
T* operator->() const { return &mPtr->mData; }
friend bool operator==(robustIterator it1, robustIterator it2)
{
return it1.mPtr == it2.mPtr;
}
friend bool operator!=(robustIterator it1, robustIterator it2) { return !(it1 == it2); }
private:
TListNode<T>* mPtr;
TListNode<T>* mPtrNext;
};
robustIterator robustBegin() const
{
return robustIterator(static_cast<TListNode<T>*>(mStartEnd.next()));
}
robustIterator robustEnd() const
{
return robustIterator(static_cast<TListNode<T>*>(const_cast<ListNode*>(&mStartEnd)));
}
struct RobustRange
{
auto begin() const { return mList.robustBegin(); }
auto end() const { return mList.robustEnd(); }
const TList& mList;
};
RobustRange robustRange() const { return {*this}; }
private:
static int compareT(const T* a, const T* b)
{
if (*a < *b)
return -1;
if (*a > *b)
return 1;
return 0;
}
};
template <typename T>
class TListNode : public ListNode
{
public:
TListNode() : ListNode()
{
mData = nullptr;
mList = NULL;
}
TListNode(T data) : ListNode(), mData(data), mList(nullptr) {}
void erase()
{
TList<T>* list = mList;
if (list != NULL)
list->erase(this);
}
T mData;
TList<T>* mList;
};
} // namespace sead
#endif // SEAD_TLIST_H_