351 lines
11 KiB
C++
351 lines
11 KiB
C++
#ifndef TIER1_UTL_BUFFER_H
|
|
#define TIER1_UTL_BUFFER_H
|
|
|
|
|
|
#include "tier0/mem.h"
|
|
#include "tier0/platform.h"
|
|
#include "tier0/lib.h"
|
|
|
|
template <typename T>
|
|
class CUtlBuffer;
|
|
template <typename T>
|
|
class CUtlResizableBuffer;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// This buffer contains static data allocated on heap.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
class CUtlBuffer
|
|
{
|
|
public:
|
|
CUtlBuffer( void );
|
|
CUtlBuffer( size_t nSize );
|
|
CUtlBuffer( const CUtlBuffer<T>& buffer );
|
|
CUtlBuffer( const CUtlResizableBuffer<T>& buffer );
|
|
|
|
size_t GetSize( void ) const;
|
|
T* GetMemory(void) const;
|
|
|
|
operator T*( void ) const;
|
|
T& operator []( const size_t nIndex );
|
|
T operator []( const size_t nIndex ) const;
|
|
CUtlBuffer<T>& operator=(const CUtlBuffer<T>& other);
|
|
private:
|
|
T* m_pData;
|
|
size_t m_nSize;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Constructor.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
CUtlBuffer<T>::CUtlBuffer() : m_nSize(0)
|
|
{
|
|
m_pData = 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Constructor.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
CUtlBuffer<T>::CUtlBuffer( size_t nSize ) : m_nSize(nSize)
|
|
{
|
|
if ( nSize == 0 )
|
|
nSize = 1;
|
|
m_pData = (T*)V_malloc(sizeof(T)*nSize);
|
|
V_memset(m_pData, 0, sizeof(T)*nSize);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Constructor.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
CUtlBuffer<T>::CUtlBuffer( const CUtlBuffer<T>& buffer ) : m_nSize(buffer.m_nSize)
|
|
{
|
|
m_pData = (T*)V_malloc(sizeof(T)*buffer.m_nSize);
|
|
V_memcpy(m_pData,buffer.m_pData,sizeof(T)*buffer.m_nSize);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Constructor.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
CUtlBuffer<T>::CUtlBuffer( const CUtlResizableBuffer<T>& buffer ) : m_nSize(buffer.m_nSize)
|
|
{
|
|
m_pData = (T*)V_malloc(sizeof(T)*buffer.nSize);
|
|
V_memcpy(m_pData,buffer.pData,sizeof(T)*buffer.nSize);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Gets memory size.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
size_t CUtlBuffer<T>::GetSize( void ) const
|
|
{
|
|
return m_nSize;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Gets memory address.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
T* CUtlBuffer<T>::GetMemory( void ) const
|
|
{
|
|
return m_pData;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Gets memory address using casting.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
CUtlBuffer<T>::operator T*( void ) const
|
|
{
|
|
return m_pData;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Indexes buffer for writing.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
T& CUtlBuffer<T>::operator []( const size_t nIndex )
|
|
{
|
|
if ( m_pData == 0)
|
|
Plat_FatalErrorFunc("Buffer was not initialized\n");
|
|
|
|
if ( nIndex >= m_nSize )
|
|
Plat_FatalErrorFunc("Out of bounds indexing: size is %lu and index is %lu\n", m_nSize/sizeof(T), nIndex);
|
|
|
|
return m_pData[nIndex];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Indexes buffer for reading.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
T CUtlBuffer<T>::operator []( const size_t nIndex ) const
|
|
{
|
|
if ( nIndex >= m_nSize )
|
|
Plat_FatalErrorFunc("Out of bounds indexing: size is %lu and index is %lu\n",m_nSize, nIndex);
|
|
return m_pData[nIndex];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Assigns buffer.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
CUtlBuffer<T>& CUtlBuffer<T>::operator=(const CUtlBuffer<T>& other)
|
|
{
|
|
if ( this != &other )
|
|
{
|
|
if ( m_pData != 0)
|
|
V_free(m_pData);
|
|
m_pData = (T*)V_malloc(sizeof(T)*other.m_nSize);
|
|
V_memcpy(m_pData, other.m_pData, sizeof(T)*other.m_nSize);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// This buffer contains static data allocated on heap which can be resized.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
class CUtlResizableBuffer
|
|
{
|
|
public:
|
|
CUtlResizableBuffer( void );
|
|
CUtlResizableBuffer( size_t nSize );
|
|
CUtlResizableBuffer( const CUtlBuffer<T>& buffer );
|
|
CUtlResizableBuffer( const CUtlResizableBuffer<T>& buffer );
|
|
|
|
size_t GetSize() const;
|
|
size_t GetRealSize() const;
|
|
void Resize( size_t nSize );
|
|
void* GetMemory(void) const;
|
|
|
|
operator T*( void ) const;
|
|
T& operator []( const size_t nIndex );
|
|
T operator []( const size_t nIndex ) const;
|
|
CUtlResizableBuffer<T>& operator=(const CUtlResizableBuffer<T>& other);
|
|
private:
|
|
size_t CalculateMemorySize(size_t nSize);
|
|
T* m_pData;
|
|
size_t m_nSize;
|
|
size_t m_nAllocatedSize;
|
|
};
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Constructor.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
CUtlResizableBuffer<T>::CUtlResizableBuffer() : m_nSize(1)
|
|
{
|
|
m_pData = (T*)V_malloc(1);
|
|
m_nAllocatedSize = 1;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Constructor.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
CUtlResizableBuffer<T>::CUtlResizableBuffer( size_t nSize ) : m_nSize(nSize)
|
|
{
|
|
if ( nSize == 0 )
|
|
nSize = 1;
|
|
size_t nAllocSize = CalculateMemorySize(sizeof(T)*nSize);
|
|
m_pData = (T*)V_malloc(nAllocSize);
|
|
m_nAllocatedSize = nAllocSize;
|
|
V_memset(m_pData, 0, sizeof(T)*nSize);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Constructor.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
CUtlResizableBuffer<T>::CUtlResizableBuffer( const CUtlBuffer<T>& buffer ) : m_nSize(buffer.nSize)
|
|
{
|
|
size_t nAllocSize = CalculateMemorySize(sizeof(T)*buffer.nSize);
|
|
m_pData = (T*)V_malloc(nAllocSize);
|
|
m_nAllocatedSize = nAllocSize;
|
|
V_memcpy(m_pData,buffer.m_pData,sizeof(T)*buffer.nSize);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Constructor.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
CUtlResizableBuffer<T>::CUtlResizableBuffer( const CUtlResizableBuffer<T>& buffer ) : m_nSize(buffer.m_nSize)
|
|
{
|
|
m_pData = (T*)V_malloc(sizeof(T)*buffer.m_nAllocatedSize);
|
|
m_nAllocatedSize = buffer.m_nAllocatedSize;
|
|
V_memcpy(m_pData,buffer.m_pData,sizeof(T)*buffer.m_nSize);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Gets memory size.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
size_t CUtlResizableBuffer<T>::GetSize( void ) const
|
|
{
|
|
return m_nSize;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Gets memory size.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
size_t CUtlResizableBuffer<T>::GetRealSize( void ) const
|
|
{
|
|
return m_nAllocatedSize;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Resizes memory.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
void CUtlResizableBuffer<T>::Resize( size_t nSize )
|
|
{
|
|
if ( nSize == 0 )
|
|
nSize = 1;
|
|
|
|
|
|
if ( m_pData == 0 )
|
|
m_pData = (T*)V_malloc(CalculateMemorySize(sizeof(T)*nSize));
|
|
else
|
|
{
|
|
size_t nAllocSize = CalculateMemorySize(sizeof(T)*nSize);
|
|
if (nAllocSize!=m_nAllocatedSize)
|
|
{
|
|
// not ideal
|
|
T* pData = (T*)V_malloc(nAllocSize);
|
|
V_memcpy(pData, m_pData, m_nAllocatedSize>nAllocSize ? nAllocSize : m_nAllocatedSize );
|
|
m_nAllocatedSize = nAllocSize;
|
|
V_free(m_pData);
|
|
m_pData = pData;
|
|
}
|
|
}
|
|
m_nSize = nSize;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Gets memory address.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
void* CUtlResizableBuffer<T>::GetMemory( void ) const
|
|
{
|
|
return m_pData;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Gets memory address using casting.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
CUtlResizableBuffer<T>::operator T*( void ) const
|
|
{
|
|
return m_pData;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Indexes buffer for writing.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
T& CUtlResizableBuffer<T>::operator []( const size_t nIndex )
|
|
{
|
|
if ( m_pData == 0)
|
|
Plat_FatalErrorFunc("Buffer was not initialized\n");
|
|
|
|
if ( nIndex >= m_nSize )
|
|
Plat_FatalErrorFunc("Out of bounds indexing: size is %lu and index is %lu\n",m_nSize, nIndex);
|
|
|
|
return m_pData[nIndex];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Indexes buffer for reading.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
T CUtlResizableBuffer<T>::operator []( const size_t nIndex ) const
|
|
{
|
|
if ( nIndex >= m_nSize )
|
|
Plat_FatalErrorFunc("Out of bounds indexing: size is %lu and index is %lu\n",m_nSize, nIndex);
|
|
return m_pData[nIndex];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Assigns buffer.
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
CUtlResizableBuffer<T>& CUtlResizableBuffer<T>::operator=(const CUtlResizableBuffer<T>& other)
|
|
{
|
|
if ( this != &other )
|
|
{
|
|
V_free(m_pData);
|
|
m_pData = (T*)V_malloc(other.m_nAllocatedSize);
|
|
V_memcpy(m_pData, other.m_pData, sizeof(T)*other.m_nSize);
|
|
m_nAllocatedSize = other.m_nAllocatedSize;
|
|
m_nSize = other.m_nSize;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Calculates memory size that is
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
size_t CUtlResizableBuffer<T>::CalculateMemorySize(size_t nSize)
|
|
{
|
|
size_t x = nSize;
|
|
if (x == 0) return 1;
|
|
x--;
|
|
x |= x >> 1;
|
|
x |= x >> 2;
|
|
x |= x >> 4;
|
|
x |= x >> 8;
|
|
x |= x >> 16;
|
|
x |= x >> 32;
|
|
return x + 1;
|
|
}
|
|
|
|
#endif
|