#ifndef STORM_LIST_TS_LIST_HPP #define STORM_LIST_TS_LIST_HPP #include "storm/Memory.hpp" #include "storm/list/TSGetLink.hpp" #include "storm/list/TSLink.hpp" #include #include #include #include #define STORM_LIST(T) TSList> template class TSList { public: // Member variables ptrdiff_t m_linkoffset = 0; TSLink m_terminator; // Member functions TSList(); ~TSList(); void ChangeLinkOffset(ptrdiff_t linkoffset); void Clear(); T* DeleteNode(T* ptr); T* Head(); void InitializeTerminator(); bool IsLinked(T* ptr); TSLink* Link(const T* ptr); void LinkNode(T* ptr, uint32_t linktype, T* existingptr); void LinkToHead(T* ptr); void LinkToTail(T* ptr); const char* MemFileName() const; int32_t MemLineNo() const; T* NewNode(uint32_t location, size_t extrabytes, uint32_t flags); T* Next(const T* ptr); T* RawNext(const T* ptr); void SetLinkOffset(ptrdiff_t linkoffset); T* Tail(); void UnlinkAll(); void UnlinkNode(T* node); }; template TSList::TSList() { this->InitializeTerminator(); } template TSList::~TSList() { this->UnlinkAll(); } template void TSList::ChangeLinkOffset(ptrdiff_t linkoffset) { if (linkoffset != this->m_linkoffset) { this->UnlinkAll(); this->SetLinkOffset(linkoffset); } } template void TSList::Clear() { T* node; while ((node = this->Head())) { this->DeleteNode(node); } } template T* TSList::DeleteNode(T* ptr) { T* next = this->Next(ptr); ptr->~T(); SMemFree(ptr, __FILE__, __LINE__, 0); return next; } template T* TSList::Head() { return this->m_terminator.Next(); } template void TSList::InitializeTerminator() { this->m_terminator.m_prevlink = &this->m_terminator; // Set sentinel node (indicates list end) this->m_terminator.m_next = reinterpret_cast(~reinterpret_cast(&this->m_terminator)); } template bool TSList::IsLinked(T* ptr) { return TGetLink::Link(ptr, this->m_linkoffset)->IsLinked(); } template TSLink* TSList::Link(const T* ptr) { if (ptr) { return TGetLink::Link(ptr, this->m_linkoffset); } else { return &this->m_terminator; } } template void TSList::LinkNode(T* ptr, uint32_t linktype, T* existingptr) { TSLink* v5 = this->Link(ptr); if (v5->m_prevlink) { v5->Unlink(); } TSLink* v7; if (existingptr) { v7 = this->Link(existingptr); } else { v7 = &this->m_terminator; } TSLink* v8; switch (linktype) { case 1: // After existingptr v5->m_prevlink = v7; v5->m_next = v7->m_next; v7->NextLink(this->m_linkoffset)->m_prevlink = v5; v7->m_next = ptr; break; case 2: // Before existingptr v8 = v7->m_prevlink; v5->m_prevlink = v7->m_prevlink; v5->m_next = v8->m_next; v8->m_next = ptr; v7->m_prevlink = v5; break; default: // TODO error break; } } template void TSList::LinkToHead(T* ptr) { this->LinkNode(ptr, 1, nullptr); } template void TSList::LinkToTail(T* ptr) { this->LinkNode(ptr, 2, nullptr); } template const char* TSList::MemFileName() const { return typeid(T).name(); } template int32_t TSList::MemLineNo() const { return -2; } template T* TSList::NewNode(uint32_t location, size_t extrabytes, uint32_t flags) { void* m = SMemAlloc(sizeof(T) + extrabytes, this->MemFileName(), this->MemLineNo(), flags | 0x8); T* node; if (m) { node = new (m) T(); } else { node = nullptr; } if (location) { this->LinkNode(node, location, nullptr); } return node; } template T* TSList::Next(const T* ptr) { return this->Link(ptr)->Next(); } template T* TSList::RawNext(const T* ptr) { TSLink* link = this->Link(ptr); return link->RawNext(); } template void TSList::SetLinkOffset(ptrdiff_t linkoffset) { this->m_linkoffset = linkoffset; this->InitializeTerminator(); } template T* TSList::Tail() { return this->m_terminator.Prev(); } template void TSList::UnlinkAll() { T* node; while ((node = this->Head())) { this->UnlinkNode(node); } } template void TSList::UnlinkNode(T* node) { TSLink* link = this->Link(node); link->Unlink(); } #endif