#ifndef UTLMEMORY_H
#define UTLMEMORY_H
#ifdef _WIN32
#pragma once
#endif
#include "tier0/dbg.h"
#include <string.h>
#include "tier0/platform.h"
#include "tier0/memdbgon.h"
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning (disable:4100)
#endif
#ifdef UTLMEMORY_TRACK
#define UTLMEMORY_TRACK_ALLOC() MemAlloc_RegisterAllocation( "Sum of all UtlMemory", 0, m_nAllocationCount * sizeof(T), m_nAllocationCount * sizeof(T), 0 )
#define UTLMEMORY_TRACK_FREE() if ( !m_pMemory ) ; else MemAlloc_RegisterDeallocation( "Sum of all UtlMemory", 0, m_nAllocationCount * sizeof(T), m_nAllocationCount * sizeof(T), 0 )
#else
#define UTLMEMORY_TRACK_ALLOC() ((void)0)
#define UTLMEMORY_TRACK_FREE() ((void)0)
#endif
BEGIN_TIER1_NAMESPACE
class CUtlMemoryBase
{
public:
CUtlMemoryBase( int nSizeOfType, int nGrowSize = 0, int nInitSize = 0 );
CUtlMemoryBase( int nSizeOfType, void* pMemory, int numElements );
CUtlMemoryBase( int nSizeOfType, const void* pMemory, int numElements );
#ifdef VALVE_RVALUE_REFS
CUtlMemoryBase( CUtlMemoryBase&& src );
#endif ~CUtlMemoryBase();
bool IsIdxValid( int i ) const;
void SetExternalBuffer( void * pMemory, int numElements );
void SetExternalBuffer( const void * pMemory, int numElements );
void Swap( CUtlMemoryBase &mem );
void *Detach();
void ConvertToGrowableMemory( int nGrowSize );
int NumAllocated() const;
int Count() const;
int CubAllocated() const { return m_nAllocationCount * m_unSizeOfElements; }
void Grow( int num = 1 );
void EnsureCapacity( int num );
void Purge();
void Purge( int numElements, bool bRealloc = true );
bool IsExternallyAllocated() const;
bool IsReadOnly() const;
void SetGrowSize( int size );
protected:
CUtlMemoryBase(const CUtlMemoryBase& rhs);
const CUtlMemoryBase& operator=(const CUtlMemoryBase& rhs);
enum
{
EXTERNAL_BUFFER_MARKER = -1,
EXTERNAL_CONST_BUFFER_MARKER = -2,
};
uint32 m_unSizeOfElements;
void * m_pMemory;
int m_nAllocationCount;
int m_nGrowSize;
};
template< class T >
class CUtlMemory : public CUtlMemoryBase
{
public:
CUtlMemory( int nGrowSize = 0, int nInitSize = 0 );
CUtlMemory( T* pMemory, int numElements );
CUtlMemory( const T* pMemory, int numElements );
#ifdef VALVE_RVALUE_REFS
CUtlMemory( CUtlMemory&& src );
#endif
T& operator[]( int i );
const T& operator[]( int i ) const;
T& Element( int i );
const T& Element( int i ) const;
T* Base();
const T* Base() const;
private:
CUtlMemory(const CUtlMemory& rhs);
const CUtlMemory& operator=(const CUtlMemory& rhs);
};
template< typename T, size_t SIZE >
class CUtlMemoryFixed
{
public:
CUtlMemoryFixed( int nGrowSize = 0, int nInitSize = 0 ) { Assert( nInitSize == 0 || nInitSize == SIZE ); }
CUtlMemoryFixed( T* pMemory, int numElements ) { Assert( 0 ); }
bool IsIdxValid( int i ) const { return (i >= 0) && (i < SIZE); }
T* Base() { return (T*)(&m_Memory[0]); }
const T* Base() const { return (const T*)(&m_Memory[0]); }
T& operator[]( int i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
const T& operator[]( int i ) const { Assert( IsIdxValid(i) ); return Base()[i]; }
T& Element( int i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
const T& Element( int i ) const { Assert( IsIdxValid(i) ); return Base()[i]; }
void SetExternalBuffer( T* pMemory, int numElements ) { Assert( 0 ); }
int NumAllocated() const { return SIZE; }
int Count() const { return SIZE; }
void Grow( int num = 1 ) { Assert( 0 ); }
void EnsureCapacity( int num ) { Assert( num <= SIZE ); }
void Purge() {}
void Purge( int numElements, bool bRealloc = true ) { Assert( 0 ); }
bool IsExternallyAllocated() const { return false; }
void SetGrowSize( int size ) {}
private:
uint8 m_Memory[SIZE*sizeof(T)];
};
template< class T >
inline CUtlMemory<T>::CUtlMemory( int nGrowSize, int nInitAllocationCount ) : CUtlMemoryBase( sizeof( T ), nGrowSize, nInitAllocationCount )
{
}
template< class T >
inline CUtlMemory<T>::CUtlMemory( T* pMemory, int numElements ) : CUtlMemoryBase( sizeof( T ), (void*)pMemory, numElements )
{
}
template< class T >
inline CUtlMemory<T>::CUtlMemory( const T* pMemory, int numElements ) : CUtlMemoryBase( sizeof( T ), pMemory, numElements )
{
}
#ifdef VALVE_RVALUE_REFS
template< class T >
inline CUtlMemory<T>::CUtlMemory( CUtlMemory<T>&& src ) : CUtlMemoryBase( std::move( src ) )
{
static_assert( sizeof( CUtlMemory<T> ) == sizeof( CUtlMemoryBase ), "Move constructor needs to be updated if there are inline members in CUtlMemory." );
}
#endif
template< class T >
void SWAP( T &a, T &b )
{
#if VALVE_RVALUE_REFS
T tmp( std::move( a ) );
a = std::move( b );
b = std::move( tmp );
#else
T tmp( a );
a = b;
b = tmp;
#endif
}
template< class T >
inline T& CUtlMemory<T>::operator[]( int i )
{
DbgAssert( !IsReadOnly() );
DbgAssert( IsIdxValid(i) );
return ((T*)m_pMemory)[i];
}
template< class T >
inline const T& CUtlMemory<T>::operator[]( int i ) const
{
DbgAssert( IsIdxValid(i) );
return ((T*)m_pMemory)[i];
}
template< class T >
inline T& CUtlMemory<T>::Element( int i )
{
DbgAssert( !IsReadOnly() );
DbgAssert( IsIdxValid(i) );
return ((T*)m_pMemory)[i];
}
template< class T >
inline const T& CUtlMemory<T>::Element( int i ) const
{
DbgAssert( IsIdxValid(i) );
return ((T*)m_pMemory)[i];
}
template< class T >
inline T* CUtlMemory<T>::Base()
{
return (T*)m_pMemory;
}
template< class T >
inline const T *CUtlMemory<T>::Base() const
{
return (const T*)m_pMemory;
}
END_TIER1_NAMESPACE
#include "tier0/memdbgoff.h"
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#endif