Files
libsst/Include/ZUtil/ZReferenceBuffer.hpp
2026-04-03 00:22:39 -05:00

400 lines
8.5 KiB
C++

/*
ZReferenceBuffer.hpp
Author: James Russell
Purpose : Acts as a means of storing arbitrary types of values in an array which gives back index-based references to
pointers of those types of values. Handles, internally, the Buffer overflowing and looping back around
the end of the storage array.
Changelog :
2/11/10 - Creation (jcr2)
2/13/10 - Should be working as advertised (jcr)
3/04/10 - NOW working as advertised (jcr)
*/
#ifndef _ZREFERENCEBUFFER_H
#define _ZREFERENCEBUFFER_H
#include <ZUtil/ZAlloc.hpp>
#include <ZUtil/ZAssert.hpp>
#include <ZSTL/ZArray.hpp>
#include <ZSTL/ZList.hpp>
#define ZRB_DEFAULT_BUFFER_SIZE (10)
#define ZRB_INVALID_HANDLE (-1)
typedef int ZReferenceBufferHandle;
template <typename T>
class ZReferenceBuffer
{
protected:
//The Current Index Value (next value to be assigned)
int CurrentIndex;
//The Current Size of the Buffer (Storage Capacity)
int BufferSize;
//The Current Number of Items contained in the Buffer
int ItemCount;
//Indicator array used to indicate which indices of the Buffer are valid
ZArray<int> Indicator;
//Buffer of T* Values
ZArray<T*> Buffer;
//Checks if a given reference is valid
inline bool IsValid(int index);
//Checks if a given reference is invalid
inline bool IsInvalid(int index);
//Sets the Indicator of an index to valid
inline void SetValid(int index);
//Sets the Indicator of an index to invalid
inline void SetInvalid(int index);
public:
/*
Default constructor.
*/
ZReferenceBuffer();
/*
Constructor.
@param _size - The starting size of the reference buffer.
*/
ZReferenceBuffer(int _size);
/*
Constructor.
@param _allocator - the allocator to use for allocations / deallocations in the reference buffer
*/
ZReferenceBuffer(ZArrayAllocator<T> *_allocator);
/*
Constructor.
@param _size - The starting size of the reference buffer.
@param _allocator - the allocator to use for allocations / deallocations in the reference buffer
*/
ZReferenceBuffer( int _size, ZArrayAllocator<T> *_allocator);
/*
Destructor.
*/
~ZReferenceBuffer();
/*
public ZReferenceBuffer::AddItem
Adds the item to the reference Buffer, returning a handle. Resizes the Buffer automatically to
increase the size of the buffer if full.
@param _item - the item to add to the buffer
@return (ZReferenceBufferHandle) - a ZReferenceBufferHandle which can be used to reference item, Will never return NULL.
*/
ZReferenceBufferHandle AddItem(T _item);
/*
public ZReferenceBuffer::GetItem
Gets an item in the Buffer given a reference handle.
@param _ref - the reference handle to the item you wish to get
@return (T&) - the item the handle refers to
*/
T& GetItem(ZReferenceBufferHandle _ref);
/*
public ZReferenceBuffer::SetItem
Attempts to set the reference to map to the provided item. Used for updating references.
@param _ref - a valid reference handle to update. If NULL, will set the null handle, allowing a NULL reference to be valid.
@param _item - the item to update the reference to
@return (T) - the overwritten value that ref pointed to
*/
T SetItem(ZReferenceBufferHandle _ref, T _item);
/*
public ZReferenceBuffer::RemoveItem
Removes an item from the Buffer given a reference handle and invalidates the handle (until reassigned).
@param _ref - the reference handle to the item you wish to remove
@return (T) - the item removed
*/
T RemoveItem(ZReferenceBufferHandle _ref);
/*
public ZReferenceBuffer::Remove
Removes all occurrences of an item from the Buffer given a pointer to the item.
@param _item - the item you wish to remove
@return (void)
*/
void Remove(T _item);
/*
public ZReferenceBuffer::Size
Gets the current size of the buffer.
@return (int) - the size (capacity) of the buffer
*/
int Size();
/*
public ZReferenceBuffer::Count
Returns the number of elements currently stored in the Buffer
@return (int) - the count (number of items) in the buffer
*/
int Count();
/*
public ZReferenceBuffer::Items
Returns a ZList containing the elements of the reference Buffer.
@return (ZList<T>) - a list containing all the values currently in the buffer
*/
ZList<T> Items();
/*
inline public ZReferenceBuffer::IsFull
Returns true if the Buffer is full, false otherwise.
@return (bool) - boolean indicating the buffer is full
*/
inline bool IsFull();
/*
public ZReferenceBuffer::Resize
Resizes the Buffer to store _newSize number of elements. Already existing references remain valid. Returns true
on success, false otherwise. Newsize must be greater than the current size of the reference Buffer.
@param _newSize - the ZNew capacity of the buffer
@return (bool) - boolean indicating success or failure
*/
bool Resize( int _newSize);
};
template <typename T>
ZReferenceBuffer<T>::ZReferenceBuffer( int _size, ZArrayAllocator<T>* _allocator)
: CurrentIndex(1), BufferSize(_size+1), ItemCount(0), Allocator(_allocator)
{
this->Buffer.Resize(BufferSize);
this->Indicator.Resize(this->BufferSize, false);
}
template <typename T>
ZReferenceBuffer<T>::ZReferenceBuffer( int _size)
: CurrentIndex(1), BufferSize(_size+1), ItemCount(0)
{
this->Buffer.Resize(BufferSize);
this->Indicator.Resize(this->BufferSize, false);
}
template <typename T>
ZReferenceBuffer<T>::ZReferenceBuffer(ZArrayAllocator<T>* _allocator)
: CurrentIndex(1), BufferSize(ZRB_DEFAULT_BUFFER_SIZE+1), ItemCount(0), Allocator(_allocator)
{
this->Buffer.Resize(BufferSize);
this->Indicator.Resize(this->BufferSize, false);
}
template <typename T>
ZReferenceBuffer<T>::ZReferenceBuffer()
: CurrentIndex(1), BufferSize(ZRB_DEFAULT_BUFFER_SIZE+1), ItemCount(0)
{
this->Buffer.Resize(BufferSize);
this->Indicator.Resize(this->BufferSize, false);
}
template <typename T>
ZReferenceBuffer<T>::~ZReferenceBuffer()
{
}
template <typename T>
bool ZReferenceBuffer<T>::IsValid(int _index)
{
if (_index >= 0)
return this->Indicator[_index] != 0;
return false;
}
template <typename T>
bool ZReferenceBuffer<T>::IsInvalid(int _index)
{
return !IsValid(_index);
}
template <typename T>
void ZReferenceBuffer<T>::SetValid( int _index)
{
this->Indicator[_index] = 1;
}
template <typename T>
void ZReferenceBuffer<T>::SetInvalid( int _index)
{
this->Indicator[_index] = 0;
}
template <typename T>
ZReferenceBufferHandle ZReferenceBuffer<T>::AddItem(T _item)
{
int startIndex;
int ref;
//CurrentIndex should only be zero if Buffer is full
if (this->CurrentIndex == 0)
return this->CurrentIndex;
ref = startIndex = this->CurrentIndex;
while (this->IsValid(this->CurrentIndex))
{
this->CurrentIndex++;
ref = this->CurrentIndex;
if (this->CurrentIndex == startIndex)
this->Resize(this->BufferSize * 2);
if (this->CurrentIndex >= this->BufferSize)
ref = this->CurrentIndex = 1;
}
if (ref != -1)
{
this->Buffer[ref] = _item;
this->SetValid(ref);
this->ItemCount++;
}
return ref;
}
template <typename T>
T& ZReferenceBuffer<T>::GetItem(ZReferenceBufferHandle _ref)
{
ZASSERT(this->IsValid(_ref), "ERROR: ZReferenceBuffer::GetItemRef passed invalid reference!");
return this->Buffer[_ref];
}
template <typename T>
T ZReferenceBuffer<T>::RemoveItem(ZReferenceBufferHandle _ref)
{
T item;
ZASSERT( this->IsValid(_ref) , "ERROR: ZReferenceBuffer::RemoveItem passed invalid reference!" );
this->ItemCount--;
this->SetInvalid(_ref);
item = this->Buffer[_ref];
return item;
}
template <typename T>
void ZReferenceBuffer<T>::Remove(T _item)
{
for ( int i = 0; i < this->BufferSize; i++)
if (this->Buffer[i] == _item)
this->RemoveItem(i);
}
template <typename T>
T ZReferenceBuffer<T>::SetItem(int _ref, T _item)
{
T ret;
ret = this->Buffer[_ref];
this->Buffer[_ref] = _item;
this->SetValid(_ref);
this->ItemCount++;
return ret;
}
template <typename T>
int ZReferenceBuffer<T>::Size()
{
return this->BufferSize;
}
template <typename T>
int ZReferenceBuffer<T>::Count()
{
return this->ItemCount;
}
template <typename T>
bool ZReferenceBuffer<T>::IsFull()
{
return (!this->CurrentIndex);
}
template <typename T>
bool ZReferenceBuffer<T>::Resize( int _newSize)
{
if (_newSize < this->BufferSize)
return false;
this->BufferSize = _newSize + 1;
ZArray<T*> newBuffer;
newBuffer.Resize(this->BufferSize);
for ( int i = 0; i < this->BufferSize; i++)
newBuffer[i] = this->Buffer[i];
this->Indicator.Resize(this->BufferSize, false);
this->Buffer = newBuffer;
return true;
}
template <typename T>
ZList<T> ZReferenceBuffer<T>::Items()
{
int i;
ZList<T> items;
for (i = 1; i < this->BufferSize; i++)
{
if (this->IsValid(i))
items.PushBack(this->Buffer[i]);
}
return items;
}
#endif