mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-07 19:18:19 +02:00
245 lines
No EOL
3.8 KiB
C++
245 lines
No EOL
3.8 KiB
C++
#pragma once
|
|
|
|
#include "BeefySysLib/Common.h"
|
|
#include "BeefySysLib/util/BumpAllocator.h"
|
|
|
|
NS_BF_BEGIN
|
|
|
|
template <typename T>
|
|
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<Node>();
|
|
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 <typename T>
|
|
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<NodeBlock>();
|
|
else if (mHeadBlock->mVals[NodeBlock::NodeCount - 1])
|
|
{
|
|
auto newHeadBlock = bumpAllocator->Alloc<NodeBlock>();
|
|
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 |