#ifndef TIER1_UTL_BUFFER_H #define TIER1_UTL_BUFFER_H #include "tier0/mem.h" #include "tier0/platform.h" #include "tier0/lib.h" template class CUtlBuffer; template class CUtlResizableBuffer; //----------------------------------------------------------------------------- // This buffer contains static data allocated on heap. //----------------------------------------------------------------------------- template class CUtlBuffer { public: CUtlBuffer( void ); CUtlBuffer( size_t nSize ); CUtlBuffer( const CUtlBuffer& buffer ); CUtlBuffer( const CUtlResizableBuffer& buffer ); size_t GetSize( void ) const; void* GetMemory(void) const; operator T*( void ) const; T& operator []( const size_t nIndex ); T operator []( const size_t nIndex ) const; CUtlBuffer& operator=(const CUtlBuffer& other); private: T* m_pData; size_t m_nSize; }; //----------------------------------------------------------------------------- // Constructor. //----------------------------------------------------------------------------- template CUtlBuffer::CUtlBuffer() : m_nSize(0) { m_pData = 0; } //----------------------------------------------------------------------------- // Constructor. //----------------------------------------------------------------------------- template CUtlBuffer::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 CUtlBuffer::CUtlBuffer( const CUtlBuffer& 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 CUtlBuffer::CUtlBuffer( const CUtlResizableBuffer& 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 size_t CUtlBuffer::GetSize( void ) const { return m_nSize; } //----------------------------------------------------------------------------- // Gets memory address. //----------------------------------------------------------------------------- template void* CUtlBuffer::GetMemory( void ) const { return m_pData; } //----------------------------------------------------------------------------- // Gets memory address using casting. //----------------------------------------------------------------------------- template CUtlBuffer::operator T*( void ) const { return m_pData; } //----------------------------------------------------------------------------- // Indexes buffer for writing. //----------------------------------------------------------------------------- template T& CUtlBuffer::operator []( const size_t nIndex ) { if ( m_pData == 0) Plat_FatalErrorFunc("Buffer was not initialized"); if ( nIndex >= m_nSize ) Plat_FatalErrorFunc("Out of bounds indexing: size is %lu and index is %lu", m_nSize/sizeof(T), nIndex); return m_pData[nIndex]; } //----------------------------------------------------------------------------- // Indexes buffer for reading. //----------------------------------------------------------------------------- template T CUtlBuffer::operator []( const size_t nIndex ) const { if ( nIndex >= m_nSize ) Plat_FatalErrorFunc("Out of bounds indexing: size is %lu and index is %lu",m_nSize, nIndex); return m_pData[nIndex]; } //----------------------------------------------------------------------------- // Assigns buffer. //----------------------------------------------------------------------------- template CUtlBuffer& CUtlBuffer::operator=(const CUtlBuffer& 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 class CUtlResizableBuffer { public: CUtlResizableBuffer( void ); CUtlResizableBuffer( size_t nSize ); CUtlResizableBuffer( const CUtlBuffer& buffer ); CUtlResizableBuffer( const CUtlResizableBuffer& 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& operator=(const CUtlResizableBuffer& other); private: size_t CalculateMemorySize(size_t nSize); T* m_pData; size_t m_nSize; size_t m_nAllocatedSize; }; //----------------------------------------------------------------------------- // Constructor. //----------------------------------------------------------------------------- template CUtlResizableBuffer::CUtlResizableBuffer() : m_nSize(1) { m_pData = (T*)V_malloc(1); m_nAllocatedSize = 1; } //----------------------------------------------------------------------------- // Constructor. //----------------------------------------------------------------------------- template CUtlResizableBuffer::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 CUtlResizableBuffer::CUtlResizableBuffer( const CUtlBuffer& 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 CUtlResizableBuffer::CUtlResizableBuffer( const CUtlResizableBuffer& 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 size_t CUtlResizableBuffer::GetSize( void ) const { return m_nSize; } //----------------------------------------------------------------------------- // Gets memory size. //----------------------------------------------------------------------------- template size_t CUtlResizableBuffer::GetRealSize( void ) const { return m_nAllocatedSize; } //----------------------------------------------------------------------------- // Resizes memory. //----------------------------------------------------------------------------- template void CUtlResizableBuffer::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 void* CUtlResizableBuffer::GetMemory( void ) const { return m_pData; } //----------------------------------------------------------------------------- // Gets memory address using casting. //----------------------------------------------------------------------------- template CUtlResizableBuffer::operator T*( void ) const { return m_pData; } //----------------------------------------------------------------------------- // Indexes buffer for writing. //----------------------------------------------------------------------------- template T& CUtlResizableBuffer::operator []( const size_t nIndex ) { if ( m_pData == 0) Plat_FatalErrorFunc("Buffer was not initialized"); if ( nIndex >= m_nSize ) Plat_FatalErrorFunc("Out of bounds indexing: size is %lu and index is %lu",m_nSize, nIndex); return m_pData[nIndex]; } //----------------------------------------------------------------------------- // Indexes buffer for reading. //----------------------------------------------------------------------------- template T CUtlResizableBuffer::operator []( const size_t nIndex ) const { if ( nIndex >= m_nSize ) Plat_FatalErrorFunc("Out of bounds indexing: size is %lu and index is %lu",m_nSize, nIndex); return m_pData[nIndex]; } //----------------------------------------------------------------------------- // Assigns buffer. //----------------------------------------------------------------------------- template CUtlResizableBuffer& CUtlResizableBuffer::operator=(const CUtlResizableBuffer& 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 size_t CUtlResizableBuffer::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