#pragma once #include "BeefySysLib/Common.h" #include "BeefySysLib/util/BumpAllocator.h" NS_BF_BEGIN template class BumpList { public: struct Node { T mValue; Node* mNext; }; struct Iterator { public: Node* mNode; public: Iterator(Node* node) { mNode = node; } Iterator& operator++() { mNode = mNode->mNext; return *this; } bool operator!=(const Iterator& itr) const { return mNode != itr.mNode; } bool operator==(const Iterator& itr) const { return mNode == itr.mNode; } T operator*() { return mNode->mValue; } }; struct RemovableIterator { public: Node** mPrevNextPtr; public: RemovableIterator(Node** headPtr) { mPrevNextPtr = headPtr; } RemovableIterator& operator++() { Node* newNode = *mPrevNextPtr; if (newNode != NULL) mPrevNextPtr = &newNode->mNext; return *this; } bool operator!=(const RemovableIterator& itr) const { if (itr.mPrevNextPtr == NULL) return *mPrevNextPtr != NULL; return *itr.mPrevNextPtr != *mPrevNextPtr; } bool operator==(const RemovableIterator& itr) const { if (itr.mPrevNextPtr == NULL) return *mPrevNextPtr == NULL; return *itr.mPrevNextPtr == *mPrevNextPtr; } T operator*() { return (*mPrevNextPtr)->mValue; } }; public: Node* mHead; BumpList() { mHead = NULL; } void PushFront(T value, BumpAllocator* bumpAllocator) { auto newHead = bumpAllocator->Alloc(); newHead->mValue = value; newHead->mNext = mHead; mHead = newHead; } bool IsEmpty() { return mHead == NULL; } T front() { return mHead->mValue; } RemovableIterator begin() { return RemovableIterator(&mHead); } RemovableIterator end() { return RemovableIterator(NULL); } RemovableIterator erase(RemovableIterator itr) { T removedVal = *itr; (*itr.mPrevNextPtr) = (*itr.mPrevNextPtr)->mNext; return itr; } }; // This is a simple construct that acts as a push-only stack. // The 'NodeBlock' is designed to take advantage of being exactly 16-byte aligned when storing // Ts of 32-bit pointers. template class BlockBumpList { public: struct NodeBlock { static const int NodeCount = 3; T mVals[NodeCount]; NodeBlock* mNextBlock; NodeBlock() { mVals[0] = NULL; mVals[1] = NULL; mVals[2] = NULL; mNextBlock = NULL; } }; struct Iterator { public: NodeBlock* mNodeBlock; int mMemberIdx; public: Iterator(NodeBlock* nodeBlock) { SetNodeBlock(nodeBlock); } void SetNodeBlock(NodeBlock* nodeBlock) { mNodeBlock = nodeBlock; if (mNodeBlock != NULL) { mMemberIdx = NodeBlock::NodeCount - 1; while ((mMemberIdx >= 0) && (!mNodeBlock->mVals[mMemberIdx])) mMemberIdx--; } else mMemberIdx = -1; } Iterator& operator++() { mMemberIdx--; if (mMemberIdx < 0) SetNodeBlock(mNodeBlock->mNextBlock); return *this; } bool operator!=(const Iterator& itr) const { return (mNodeBlock != itr.mNodeBlock) || (mMemberIdx != itr.mMemberIdx); } bool operator==(const Iterator& itr) const { return (mNodeBlock == itr.mNodeBlock) && (mMemberIdx == itr.mMemberIdx); } T operator*() { return mNodeBlock->mVals[mMemberIdx]; } }; public: NodeBlock* mHeadBlock; BlockBumpList() { mHeadBlock = NULL; } void Add(T value, BumpAllocator* bumpAllocator) { if (mHeadBlock == NULL) mHeadBlock = bumpAllocator->Alloc(); else if (mHeadBlock->mVals[NodeBlock::NodeCount - 1]) { auto newHeadBlock = bumpAllocator->Alloc(); newHeadBlock->mNextBlock = mHeadBlock; mHeadBlock = newHeadBlock; } for (int i = 0; i < NodeBlock::NodeCount; i++) { if (!mHeadBlock->mVals[i]) { mHeadBlock->mVals[i] = value; break; } } } Iterator begin() { return Iterator(mHeadBlock); } Iterator end() { return Iterator(NULL); } }; NS_BF_END