400 lines
8.5 KiB
C++
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
|
|
|