sqwarmed/sdk_src/game/server/generic_classmap.h

172 lines
3.9 KiB
C
Raw Normal View History

2024-08-29 19:18:30 -04:00
//========= Copyright <20> 1996-2009, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef ASW_GENERIC_CLASSMAP_H
#define ASW_GENERIC_CLASSMAP_H
#ifdef _WIN32
#pragma once
#endif
template <class T>
class CGenericClassmap
{
public:
typedef T *( *DISPATCHFUNCTION )( void );
CGenericClassmap() { }
~CGenericClassmap() { }
void Add( const char *mapname, const char *classname, int size, DISPATCHFUNCTION factory = 0 );
char const *Lookup( const char *classname );
T *CreateInstance( const char *mapname );
int GetClassSize( const char *classname );
private:
class classentry_t
{
public:
classentry_t()
{
mapname[ 0 ] = 0;
factory = 0;
size = -1;
}
char const *GetMapName() const
{
return mapname;
}
void SetMapName( char const *newname )
{
Q_strncpy( mapname, newname, sizeof( mapname ) );
}
DISPATCHFUNCTION factory;
int size;
private:
char mapname[ 40 ];
};
CUtlDict< classentry_t, unsigned short > m_ClassDict;
};
template <class T>
void CGenericClassmap< T >::Add( const char *mapname, const char *classname, int size, DISPATCHFUNCTION factory )
{
const char *map = Lookup( classname );
if ( map && !Q_strcasecmp( mapname, map ) )
return;
if ( map )
{
int index = m_ClassDict.Find( classname );
Assert( index != m_ClassDict.InvalidIndex() );
m_ClassDict.RemoveAt( index );
}
classentry_t element;
element.SetMapName( mapname );
element.factory = factory;
element.size = size;
m_ClassDict.Insert( classname, element );
}
template <class T>
const char *CGenericClassmap< T >::Lookup( const char *classname )
{
unsigned short index;
static classentry_t lookup;
index = m_ClassDict.Find( classname );
if ( index == m_ClassDict.InvalidIndex() )
return NULL;
lookup = m_ClassDict.Element( index );
return lookup.GetMapName();
}
template <class T>
T *CGenericClassmap< T >::CreateInstance( const char *mapname )
{
int c = m_ClassDict.Count();
int i;
for ( i = 0; i < c; i++ )
{
classentry_t *lookup = &m_ClassDict[ i ];
if ( !lookup )
continue;
if ( Q_stricmp( lookup->GetMapName(), mapname ) )
continue;
if ( !lookup->factory )
{
#if defined( _DEBUG )
Msg( "No factory for %s/%s\n", lookup->GetMapName(), m_ClassDict.GetElementName( i ) );
#endif
continue;
}
return ( *lookup->factory )();
}
return NULL;
}
template <class T>
int CGenericClassmap< T >::GetClassSize( const char *classname )
{
int c = m_ClassDict.Count();
int i;
for ( i = 0; i < c; i++ )
{
classentry_t *lookup = &m_ClassDict[ i ];
if ( !lookup )
continue;
if ( Q_strcmp( lookup->GetMapName(), classname ) )
continue;
return lookup->size;
}
return -1;
}
#if 0
// example
// to hold the database:
static CGenericClassmap< CAI_BehaviorBase > m_BehaviorClasses;
// macro for easy factory creation / use:
#define LINK_BEHAVIOR_TO_CLASS( localName, className ) \
static CAI_BehaviorBase *C##className##Factory( void ) \
{ \
return static_cast< CAI_BehaviorBase * >( new className ); \
}; \
class C##localName##Foo \
{ \
public: \
C##localName##Foo( void ) \
{ \
CAI_BehaviorBase::m_BehaviorClasses.Add( #localName, #className, \
sizeof( className ),&C##className##Factory ); \
} \
}; \
static C##localName##Foo g_C##localName##Foo;
// example of macro use:
LINK_BEHAVIOR_TO_CLASSNAME( CAI_ASW_ScuttleBehavior );
#endif
#endif // ASW_GENERIC_CLASSMAP_H