//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #ifndef ENTITYDATAINSTANTIATOR_H #define ENTITYDATAINSTANTIATOR_H #ifdef _WIN32 #pragma once #endif #include "utlhash.h" #include "tier0/memdbgon.h" // This is the hash key type, but it could just as easily be and int or void * class CBaseEntity; //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- abstract_class IEntityDataInstantiator { public: virtual ~IEntityDataInstantiator() {}; virtual void *GetDataObject( const CBaseEntity *instance ) = 0; virtual void *CreateDataObject( const CBaseEntity *instance ) = 0; virtual void DestroyDataObject( const CBaseEntity *instance ) = 0; }; //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- template class CEntityDataInstantiator : public IEntityDataInstantiator { public: CEntityDataInstantiator() : m_HashTable( 64, 0, 0, CompareFunc, KeyFunc ) { } virtual void *GetDataObject( const CBaseEntity *instance ) { UtlHashHandle_t handle; HashEntry entry; entry.key = instance; handle = m_HashTable.Find( entry ); if ( handle != m_HashTable.InvalidHandle() ) { return (void *)m_HashTable[ handle ].data; } return NULL; } virtual void *CreateDataObject( const CBaseEntity *instance ) { UtlHashHandle_t handle; HashEntry entry; entry.key = instance; handle = m_HashTable.Find( entry ); // Create it if not already present if ( handle == m_HashTable.InvalidHandle() ) { handle = m_HashTable.Insert( entry ); Assert( handle != m_HashTable.InvalidHandle() ); m_HashTable[ handle ].data = new T; // FIXME: We'll have to remove this if any objects we instance have vtables!!! Q_memset( m_HashTable[ handle ].data, 0, sizeof( T ) ); } return (void *)m_HashTable[ handle ].data; } virtual void DestroyDataObject( const CBaseEntity *instance ) { UtlHashHandle_t handle; HashEntry entry; entry.key = instance; handle = m_HashTable.Find( entry ); if ( handle != m_HashTable.InvalidHandle() ) { delete m_HashTable[ handle ].data; m_HashTable.Remove( handle ); } } private: struct HashEntry { HashEntry() { key = NULL; data = NULL; } const CBaseEntity *key; T *data; }; static bool CompareFunc( const HashEntry &src1, const HashEntry &src2 ) { return ( src1.key == src2.key ); } static unsigned int KeyFunc( const HashEntry &src ) { // Shift right to get rid of alignment bits and border the struct on a 16 byte boundary return (unsigned int)src.key; } CUtlHash< HashEntry > m_HashTable; }; #include "tier0/memdbgoff.h" #endif // ENTITYDATAINSTANTIATOR_H