1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-07 19:18:19 +02:00
Beef/IDEHelper/BumpList.h
2022-07-30 09:11:38 -04:00

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