diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /gcsdk/directory.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'gcsdk/directory.cpp')
| -rw-r--r-- | gcsdk/directory.cpp | 526 |
1 files changed, 526 insertions, 0 deletions
diff --git a/gcsdk/directory.cpp b/gcsdk/directory.cpp new file mode 100644 index 0000000..e4c809b --- /dev/null +++ b/gcsdk/directory.cpp @@ -0,0 +1,526 @@ +//====== Copyright �, Valve Corporation, All rights reserved. ================= +// +// Purpose: Defines a directory for all the GC processes for an app +// +//============================================================================= + + +#include "stdafx.h" +#include "gcsdk/directory.h" + + +namespace GCSDK +{ + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CGCDirTypeInstance::CGCDirTypeInstance( const char* pszTypeName, uint32 nType, uint32 nInstance, const KeyValues *pKVConfig, const CGCDirProcess* pProcess ) + : m_nType( nType ) + , m_sTypeName( pszTypeName ) + , m_nInstance( nInstance ) + , m_pProcess( pProcess ) +{ + m_pConfig = pKVConfig->MakeCopy(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +CGCDirTypeInstance::~CGCDirTypeInstance() +{ + m_pConfig->deleteThis(); +} + +//----------------------------------------------------------------------------- +// Purpose: Returns the type for this GC +//----------------------------------------------------------------------------- +uint32 CGCDirTypeInstance::GetType() const +{ + return m_nType; +} + +//----------------------------------------------------------------------------- +const char* CGCDirTypeInstance::GetTypeName() const +{ + return m_sTypeName; +} + +//----------------------------------------------------------------------------- +// Purpose: Returns the instance index for GCs of this type +//----------------------------------------------------------------------------- +uint32 CGCDirTypeInstance::GetInstance() const +{ + return m_nInstance; +} + + +//----------------------------------------------------------------------------- +// Purpose: Gets any additional configuration data for this GC +//----------------------------------------------------------------------------- +KeyValues * CGCDirTypeInstance::GetConfig() const +{ + return m_pConfig; +} + +//----------------------------------------------------------------------------- +// Purpose: Gets the box that this GC was associated with +//----------------------------------------------------------------------------- +const CGCDirProcess* CGCDirTypeInstance::GetProcess( ) const +{ + return m_pProcess; +} + + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CGCDirProcess::CGCDirProcess( uint32 nGCDirIndex, const char *pchName, const char* pchProcessType, const KeyValues *pKVConfig ) : + m_iDirGC( nGCDirIndex ), + m_sName( pchName ), + m_sType( pchProcessType ), + m_nTypeMask( 0 ) +{ + m_pConfig = pKVConfig->MakeCopy(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +CGCDirProcess::~CGCDirProcess() +{ + // Don't need to delete our pointers. They were allocated by the directory + // and will be cleaned up by the directory. +} + +//----------------------------------------------------------------------------- +// Purpose: Gets any additional configuration data for this GC +//----------------------------------------------------------------------------- +KeyValues * CGCDirProcess::GetConfig() const +{ + return m_pConfig; +} + +//----------------------------------------------------------------------------- +// Purpose: Gets the name for this box +//----------------------------------------------------------------------------- +const char *CGCDirProcess::GetName() const +{ + return m_sName.Get(); +} + +const char *CGCDirProcess::GetProcessType() const +{ + return m_sType.Get(); +} + +//----------------------------------------------------------------------------- +// Purpose: Gets the number of GCs assigned to this box +//----------------------------------------------------------------------------- +uint32 CGCDirProcess::GetTypeInstanceCount() const +{ + return m_vecGCs.Count(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Gets the specified GC definition +//----------------------------------------------------------------------------- +const CGCDirTypeInstance *CGCDirProcess::GetTypeInstance( uint32 nGCIndex ) const +{ + bool bValidIndex = m_vecGCs.IsValidIndex( nGCIndex ); + Assert( bValidIndex ); + if ( !bValidIndex ) + return NULL; + + return m_vecGCs[ nGCIndex ]; +} + + +//----------------------------------------------------------------------------- +// Purpose: Adds a GC to this box +//----------------------------------------------------------------------------- +void CGCDirProcess::AddGC( CGCDirTypeInstance *pGC ) +{ + if ( !pGC ) + { + Assert( false ); + return; + } + + //set this within our type mask + Assert( pGC->GetType() < 64 ); + m_nTypeMask |= ( uint64 )1 << pGC->GetType(); + + m_vecGCs.AddToTail( pGC ); + if( !m_vecUniqueTypeList.HasElement( pGC->GetType() ) ) + { + m_vecUniqueTypeList.Insert( pGC->GetType() ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +uint32 CGCDirProcess::GetGCDirIndex() const +{ + return m_iDirGC; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CGCDirProcess::HasInstanceOfType( uint32 nType ) const +{ + return ( m_nTypeMask & ( ( uint64 )1 << nType ) ) != 0; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +const CUtlSortVector< uint32 >& CGCDirProcess::GetUniqueTypeList() const +{ + return m_vecUniqueTypeList; +} + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CDirectory::CDirectory() + : m_bInitialized( false ) + , m_mapGCsByType( DefLessFunc( int32 ) ) + , m_mapRegisteredGCTypes( DefLessFunc( int32 ) ) +{ +} + + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +CDirectory::~CDirectory() +{ + m_vecProcesses.PurgeAndDeleteElements(); + m_vecTypeInstances.PurgeAndDeleteElements(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Initializes the directory +//----------------------------------------------------------------------------- +bool CDirectory::BInit( KeyValues *pKVDirectory ) +{ + Assert( !m_bInitialized ); + if ( m_bInitialized ) + return false; + + if ( NULL == pKVDirectory ) + { + AssertMsg( false, "Null KV passed to CDirectory::BInit()" ); + return false; + } + + CUtlSymbolTable processNamesTable( 0, 16, true ); + FOR_EACH_TRUE_SUBKEY( pKVDirectory, pkvProcess ) + { + if( 0 != Q_stricmp( pkvProcess->GetName( ), "process" ) ) + continue; + + //get the name of this process and ensure that it is unique + const char *pchProcessName = pkvProcess->GetString( "name" ); + if( !pchProcessName || !pchProcessName[ 0 ] ) + { + AssertMsg( false, "Process defined in the config with no name" ); + return false; + } + if( processNamesTable.Find( pchProcessName ).IsValid() ) + { + AssertMsg( false, "Duplicate box \"%s\" encountered while parsing the config", pchProcessName ); + return false; + } + processNamesTable.AddString( pchProcessName ); + + //get the type associated with this process + const char *pchProcessType = pkvProcess->GetString( "type" ); + if( !pchProcessType || !pchProcessType[ 0 ] ) + { + AssertMsg( false, "Process %s defined in the config with no process type associated with it", pchProcessName ); + return false; + } + + //create our new process info + CGCDirProcess *pProcess = new CGCDirProcess( m_vecProcesses.Count( ), pchProcessName, pchProcessType, pkvProcess ); + m_vecProcesses.AddToTail( pProcess ); + + FOR_EACH_SUBKEY( pkvProcess, pkvType ) + { + if( 0 != Q_stricmp( pkvType->GetName(), "gc" ) ) + continue; + + const char *pchGCType = NULL; + if( pkvType->GetFirstSubKey() ) + { + pchGCType = pkvType->GetString( "gc" ); + } + else + { + pchGCType = pkvType->GetString( ); + } + + if ( !pchGCType || !pchGCType[0] ) + { + AssertMsg( false, "GC defined on box \"%s\" in the config with no type", pchProcessName ); + return false; + } + + int32 nGCType = GetGCTypeForName( pchGCType ); + if ( s_nInvalidGCType == nGCType ) + { + AssertMsg( false, "GC defined on box \"%s\" with unknown type \"%s\" encountered while parsing the config", pchProcessName, pchGCType ); + return false; + } + + //note that to get the count we can't call GetGCCountForType until after we register since otherwise we don't have a type entry + int nGCTypeIndex = m_mapGCsByType.Find( nGCType ); + if ( !m_mapGCsByType.IsValidIndex( nGCType ) ) + { + nGCTypeIndex = m_mapGCsByType.Insert( nGCType ); + } + + CGCDirTypeInstance *pGC = new CGCDirTypeInstance( pchGCType, nGCType, m_mapGCsByType[ nGCTypeIndex ].Count(), pkvType, pProcess ); + pProcess->AddGC( pGC ); + m_vecTypeInstances.AddToTail( pGC ); + m_mapGCsByType[ nGCTypeIndex ].AddToTail( pGC ); + } + } + + // There must be exactly one master GC defined. Make sure it exists + int32 nMasterType = GetGCTypeForName( "master" ); + if ( s_nInvalidGCType == nMasterType ) + { + AssertMsg( false, "Master GC type is not registered" ); + return false; + } + + if ( 1 != GetGCCountForType( nMasterType ) ) + { + AssertMsg( false, "Incorrect number of master GCs in the config. Expected: 1 Actual: %d", GetGCCountForType( nMasterType ) ); + return false; + } + + const CGCDirTypeInstance *pGC = GetGCInstanceForType( nMasterType, 0 ); + if ( 0 != pGC->GetProcess()->GetGCDirIndex() ) + { + AssertMsg( false, "The master GC must be contained within the first GC defined." ); + return false; + } + + m_bInitialized = true; + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Registers a type of GC +//----------------------------------------------------------------------------- +void CDirectory::RegisterGCType( int32 nTypeID, const char *pchName ) +{ + Assert( s_nInvalidGCType != nTypeID ); + if ( s_nInvalidGCType == nTypeID ) + return; + + bool bHasElement = m_mapRegisteredGCTypes.IsValidIndex( m_mapRegisteredGCTypes.Find( nTypeID ) ); + AssertMsg( !bHasElement, "A GC of type %d has already been registered", nTypeID ); + if ( bHasElement ) + return; + + bHasElement = m_dictRegisteredGCNameToType.HasElement( pchName ); + AssertMsg( !bHasElement, "A GC type with name \"%s\" has already been registered", pchName ); + if ( bHasElement ) + return; + + RegisteredGCType_t &gcReg = m_mapRegisteredGCTypes[ m_mapRegisteredGCTypes.Insert( nTypeID ) ]; + gcReg.m_strName = pchName; + + m_dictRegisteredGCNameToType.Insert( pchName, nTypeID ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Gets the number of boxes hosting GCs in the universe +//----------------------------------------------------------------------------- +uint32 CDirectory::GetProcessCount() const +{ + return m_vecProcesses.Count(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Gets the definition for a particular box +//----------------------------------------------------------------------------- +const CGCDirProcess *CDirectory::GetProcess( int32 nIndex ) const +{ + if( !m_vecProcesses.IsValidIndex( nIndex ) ) + { + Assert( false ); + return NULL; + } + + return m_vecProcesses[ nIndex ]; +} + + +//----------------------------------------------------------------------------- +// Purpose: Gets the number of GCs in the universe +//----------------------------------------------------------------------------- +uint32 CDirectory::GetGCTypeInstanceCount() const +{ + return m_vecTypeInstances.Count(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +const CGCDirTypeInstance *CDirectory::GetGCTypeInstance( uint32 iDirGC ) const +{ + if( iDirGC >= ( uint32 )m_vecTypeInstances.Count() ) + { + Assert( false ); + return NULL; + } + + return m_vecTypeInstances[ iDirGC ]; +} + + +//----------------------------------------------------------------------------- +// Purpose: Gets the number of GCs in the universe of the given type +//----------------------------------------------------------------------------- +int32 CDirectory::GetGCCountForType( int32 nTypeID ) const +{ + int nIndex = m_mapGCsByType.Find( nTypeID ); + if ( !m_mapGCsByType.IsValidIndex( nIndex ) ) + { + EmitWarning( SPEW_GC, 2, "CDirectory::GetGCCountForType() called with unregistered type %d (%s)\n", nTypeID, GetNameForGCType( nTypeID ) ); + return 0; + } + + return m_mapGCsByType[nIndex].Count(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +const CGCDirTypeInstance *CDirectory::GetGCInstanceForType( int32 nTypeID, int32 nInstance ) const +{ + int nIndex = m_mapGCsByType.Find( nTypeID ); + if ( !m_mapGCsByType.IsValidIndex( nIndex ) ) + { + EmitWarning( SPEW_GC, 2, "CDirectory::GetGCInstanceForType() called with unregistered type %d (%s)\n", nTypeID, GetNameForGCType( nTypeID ) ); + return NULL; + } + + const CCopyableUtlVector<CGCDirTypeInstance *> &vecGCs = m_mapGCsByType[ nIndex ]; + bool bValidIndex = vecGCs.IsValidIndex( nInstance ); + Assert( bValidIndex ); + if ( !bValidIndex ) + return NULL; + + return vecGCs[ nInstance ]; +} + + +//----------------------------------------------------------------------------- +// Purpose: Given a type and index, this will hash it to be a valid in-range index for that type and return the directory index +//----------------------------------------------------------------------------- +int32 CDirectory::GetGCDirIndexForInstance( int32 nTypeID, uint32 nInstanceIndex ) const +{ + int nIndex = m_mapGCsByType.Find( nTypeID ); + if ( !m_mapGCsByType.IsValidIndex( nIndex ) ) + { + EmitWarning( SPEW_GC, 2, "CDirectory::GetGCDirIndexForInstance() called with unregistered type %d (%s)\n", nTypeID, GetNameForGCType( nTypeID ) ); + return -1; + } + + const CCopyableUtlVector<CGCDirTypeInstance *> &vecGCs = m_mapGCsByType[ nIndex ]; + uint32 nWrappedIndex = nInstanceIndex % vecGCs.Count(); + return vecGCs[ nWrappedIndex ]->GetProcess()->GetGCDirIndex(); +} + +//----------------------------------------------------------------------------- +// Purpose: given a GC type, this will add all of the GC indices associated with that type onto the provided vector +//----------------------------------------------------------------------------- +void CDirectory::GetGCDirIndicesForType( int32 nTypeID, CUtlVector< uint32 >& vecIndices ) const +{ + int nIndex = m_mapGCsByType.Find( nTypeID ); + if ( m_mapGCsByType.IsValidIndex( nIndex ) ) + { + const CCopyableUtlVector<CGCDirTypeInstance *> &vecGCs = m_mapGCsByType[ nIndex ]; + FOR_EACH_VEC( vecGCs, nGC ) + { + vecIndices.AddToTail( vecGCs[ nGC ]->GetProcess()->GetGCDirIndex() ); + } + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Gets a name for a registered GC type +//----------------------------------------------------------------------------- +const char *CDirectory::GetNameForGCType( int32 nTypeID ) const +{ + int nIndex = m_mapRegisteredGCTypes.Find( nTypeID ); + if ( !m_mapRegisteredGCTypes.IsValidIndex( nIndex ) ) + return "unknown"; + + return m_mapRegisteredGCTypes[nIndex].m_strName.Get(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Gets the creation factory for a registered GC types +//----------------------------------------------------------------------------- +CDirectory::GCFactory_t CDirectory::GetFactoryForProcessType( const char* pszProcessType ) const +{ + int nIndex = m_dictProcessTypeToFactory.Find( pszProcessType ); + if( nIndex == m_dictProcessTypeToFactory.InvalidIndex() ) + return NULL; + return m_dictProcessTypeToFactory[ nIndex ]; +} + +//----------------------------------------------------------------------------- +// Purpose: Registers a factory for a specific process type +//----------------------------------------------------------------------------- +void CDirectory::RegisterProcessTypeFactory( const char* pszProcessType, GCFactory_t pfnFactory ) +{ + m_dictProcessTypeToFactory.Insert( pszProcessType, pfnFactory ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Gets the type for a GC given a name +//----------------------------------------------------------------------------- +int32 CDirectory::GetGCTypeForName( const char *pchName ) const +{ + int nIndex = m_dictRegisteredGCNameToType.Find( pchName ); + if ( !m_dictRegisteredGCNameToType.IsValidIndex( nIndex ) ) + return s_nInvalidGCType; + + return m_dictRegisteredGCNameToType[nIndex]; +} + + +//----------------------------------------------------------------------------- +// Purpose: Gets the global directory singleton +//----------------------------------------------------------------------------- +CDirectory *GDirectory() +{ + static CDirectory g_directory; + return &g_directory; +} + + +} // namespace GCSDK |