mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-17 22:11:58 +00:00
1
This commit is contained in:
Vendored
+268
@@ -0,0 +1,268 @@
|
||||
//========= Copyright © 1996-2006, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose: Low level byte swapping routines.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
#ifndef BYTESWAP_H
|
||||
#define BYTESWAP_H
|
||||
#if defined(_WIN32)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "tier0/dbg.h"
|
||||
#include "datamap.h" // needed for typedescription_t. note datamap.h is tier1 as well.
|
||||
|
||||
class CByteswap
|
||||
{
|
||||
public:
|
||||
CByteswap()
|
||||
{
|
||||
// Default behavior sets the target endian to match the machine native endian (no swap).
|
||||
SetTargetBigEndian( IsMachineBigEndian() );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Write a single field.
|
||||
//-----------------------------------------------------------------------------
|
||||
void SwapFieldToTargetEndian( void* pOutputBuffer, void *pData, typedescription_t *pField );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Write a block of fields. Works a bit like the saverestore code.
|
||||
//-----------------------------------------------------------------------------
|
||||
void SwapFieldsToTargetEndian( void *pOutputBuffer, void *pBaseData, datamap_t *pDataMap );
|
||||
|
||||
// Swaps fields for the templated type to the output buffer.
|
||||
template<typename T> inline void SwapFieldsToTargetEndian( T* pOutputBuffer, void *pBaseData, unsigned int objectCount = 1 )
|
||||
{
|
||||
for ( unsigned int i = 0; i < objectCount; ++i, ++pOutputBuffer )
|
||||
{
|
||||
SwapFieldsToTargetEndian( (void*)pOutputBuffer, pBaseData, &T::m_DataMap );
|
||||
pBaseData = (byte*)pBaseData + sizeof(T);
|
||||
}
|
||||
}
|
||||
|
||||
// Swaps fields for the templated type in place.
|
||||
template<typename T> inline void SwapFieldsToTargetEndian( T* pOutputBuffer, unsigned int objectCount = 1 )
|
||||
{
|
||||
SwapFieldsToTargetEndian<T>( pOutputBuffer, (void*)pOutputBuffer, objectCount );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// True if the current machine is detected as big endian.
|
||||
// (Endienness is effectively detected at compile time when optimizations are
|
||||
// enabled)
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool IsMachineBigEndian()
|
||||
{
|
||||
short nIsBigEndian = 1;
|
||||
|
||||
// if we are big endian, the first byte will be a 0, if little endian, it will be a one.
|
||||
return (bool)(0 == *(char *)&nIsBigEndian );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sets the target byte ordering we are swapping to or from.
|
||||
//
|
||||
// Braindead Endian Reference:
|
||||
// x86 is LITTLE Endian
|
||||
// PowerPC is BIG Endian
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void SetTargetBigEndian( bool bigEndian )
|
||||
{
|
||||
m_bBigEndian = bigEndian;
|
||||
m_bSwapBytes = IsMachineBigEndian() != bigEndian;
|
||||
}
|
||||
|
||||
// Changes target endian
|
||||
inline void FlipTargetEndian( void )
|
||||
{
|
||||
m_bSwapBytes = !m_bSwapBytes;
|
||||
m_bBigEndian = !m_bBigEndian;
|
||||
}
|
||||
|
||||
// Forces byte swapping state, regardless of endianess
|
||||
inline void ActivateByteSwapping( bool bActivate )
|
||||
{
|
||||
SetTargetBigEndian( IsMachineBigEndian() != bActivate );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns true if the target machine is the same as this one in endianness.
|
||||
//
|
||||
// Used to determine when a byteswap needs to take place.
|
||||
//-----------------------------------------------------------------------------
|
||||
inline bool IsSwappingBytes( void ) // Are bytes being swapped?
|
||||
{
|
||||
return m_bSwapBytes;
|
||||
}
|
||||
|
||||
inline bool IsTargetBigEndian( void ) // What is the current target endian?
|
||||
{
|
||||
return m_bBigEndian;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// IsByteSwapped()
|
||||
//
|
||||
// When supplied with a chunk of input data and a constant or magic number
|
||||
// (in native format) determines the endienness of the current machine in
|
||||
// relation to the given input data.
|
||||
//
|
||||
// Returns:
|
||||
// 1 if input is the same as nativeConstant.
|
||||
// 0 if input is byteswapped relative to nativeConstant.
|
||||
// -1 if input is not the same as nativeConstant and not byteswapped either.
|
||||
//
|
||||
// ( This is useful for detecting byteswapping in magic numbers in structure
|
||||
// headers for example. )
|
||||
//-----------------------------------------------------------------------------
|
||||
template<typename T> inline int SourceIsNativeEndian( T input, T nativeConstant )
|
||||
{
|
||||
// If it's the same, it isn't byteswapped:
|
||||
if( input == nativeConstant )
|
||||
return 1;
|
||||
|
||||
int output;
|
||||
LowLevelByteSwap<T>( &output, &input );
|
||||
if( output == nativeConstant )
|
||||
return 0;
|
||||
|
||||
Assert( 0 ); // if we get here, input is neither a swapped nor unswapped version of nativeConstant.
|
||||
return -1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Swaps an input buffer full of type T into the given output buffer.
|
||||
//
|
||||
// Swaps [count] items from the inputBuffer to the outputBuffer.
|
||||
// If inputBuffer is omitted or NULL, then it is assumed to be the same as
|
||||
// outputBuffer - effectively swapping the contents of the buffer in place.
|
||||
//-----------------------------------------------------------------------------
|
||||
template<typename T> inline void SwapBuffer( T* outputBuffer, T* inputBuffer = NULL, int count = 1 )
|
||||
{
|
||||
Assert( count >= 0 );
|
||||
Assert( outputBuffer );
|
||||
|
||||
// Fail gracefully in release:
|
||||
if( count <=0 || !outputBuffer )
|
||||
return;
|
||||
|
||||
// Optimization for the case when we are swapping in place.
|
||||
if( inputBuffer == NULL )
|
||||
{
|
||||
inputBuffer = outputBuffer;
|
||||
}
|
||||
|
||||
// Swap everything in the buffer:
|
||||
for( int i = 0; i < count; i++ )
|
||||
{
|
||||
LowLevelByteSwap<T>( &outputBuffer[i], &inputBuffer[i] );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Swaps an input buffer full of type T into the given output buffer.
|
||||
//
|
||||
// Swaps [count] items from the inputBuffer to the outputBuffer.
|
||||
// If inputBuffer is omitted or NULL, then it is assumed to be the same as
|
||||
// outputBuffer - effectively swapping the contents of the buffer in place.
|
||||
//-----------------------------------------------------------------------------
|
||||
template<typename T> inline void SwapBufferToTargetEndian( T* outputBuffer, T* inputBuffer = NULL, int count = 1 )
|
||||
{
|
||||
Assert( count >= 0 );
|
||||
Assert( outputBuffer );
|
||||
|
||||
// Fail gracefully in release:
|
||||
if( count <=0 || !outputBuffer )
|
||||
return;
|
||||
|
||||
// Optimization for the case when we are swapping in place.
|
||||
if( inputBuffer == NULL )
|
||||
{
|
||||
inputBuffer = outputBuffer;
|
||||
}
|
||||
|
||||
// Are we already the correct endienness? ( or are we swapping 1 byte items? )
|
||||
if( !m_bSwapBytes || ( sizeof(T) == 1 ) )
|
||||
{
|
||||
// If we were just going to swap in place then return.
|
||||
if( !inputBuffer )
|
||||
return;
|
||||
|
||||
// Otherwise copy the inputBuffer to the outputBuffer:
|
||||
if ( outputBuffer != inputBuffer )
|
||||
memcpy( outputBuffer, inputBuffer, count * sizeof( T ) );
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Swap everything in the buffer:
|
||||
for( int i = 0; i < count; i++ )
|
||||
{
|
||||
LowLevelByteSwap<T>( &outputBuffer[i], &inputBuffer[i] );
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//-----------------------------------------------------------------------------
|
||||
// The lowest level byte swapping workhorse of doom. output always contains the
|
||||
// swapped version of input. ( Doesn't compare machine to target endianness )
|
||||
//-----------------------------------------------------------------------------
|
||||
template<typename T> static void LowLevelByteSwap( T *output, T *input )
|
||||
{
|
||||
T temp = *output;
|
||||
#if defined( _X360 )
|
||||
// Intrinsics need the source type to be fixed-point
|
||||
DWORD* word = (DWORD*)input;
|
||||
switch( sizeof(T) )
|
||||
{
|
||||
case 8:
|
||||
{
|
||||
__storewordbytereverse( *(word+1), 0, &temp );
|
||||
__storewordbytereverse( *(word+0), 4, &temp );
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
__storewordbytereverse( *word, 0, &temp );
|
||||
break;
|
||||
|
||||
case 2:
|
||||
__storeshortbytereverse( *input, 0, &temp );
|
||||
break;
|
||||
|
||||
case 1:
|
||||
V_memcpy( &temp, input, 1 );
|
||||
break;
|
||||
|
||||
default:
|
||||
Assert( "Invalid size in CByteswap::LowLevelByteSwap" && 0 );
|
||||
}
|
||||
#else
|
||||
for( unsigned int i = 0; i < sizeof(T); i++ )
|
||||
{
|
||||
((unsigned char* )&temp)[i] = ((unsigned char*)input)[sizeof(T)-(i+1)];
|
||||
}
|
||||
#endif
|
||||
V_memcpy( output, &temp, sizeof(T) );
|
||||
}
|
||||
|
||||
#if defined( _X360 )
|
||||
// specialized for void * to get 360 XDK compile working despite changelist 281331
|
||||
//-----------------------------------------------------------------------------
|
||||
// The lowest level byte swapping workhorse of doom. output always contains the
|
||||
// swapped version of input. ( Doesn't compare machine to target endianness )
|
||||
//-----------------------------------------------------------------------------
|
||||
template<> static void LowLevelByteSwap( void **output, void **input )
|
||||
{
|
||||
AssertMsgOnce( sizeof(void *) == sizeof(unsigned int) , "void *'s on this platform are not four bytes!" );
|
||||
__storewordbytereverse( *reinterpret_cast<unsigned int *>(input), 0, output );
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned int m_bSwapBytes : 1;
|
||||
unsigned int m_bBigEndian : 1;
|
||||
};
|
||||
|
||||
#endif /* !BYTESWAP_H */
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose: Shared code for parsing / searching for characters in a string
|
||||
// using lookup tables
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef CHARACTERSET_H
|
||||
#define CHARACTERSET_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
struct characterset_t
|
||||
{
|
||||
char set[256];
|
||||
};
|
||||
|
||||
|
||||
// This is essentially a strpbrk() using a precalculated lookup table
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: builds a simple lookup table of a group of important characters
|
||||
// Input : *pSetBuffer - pointer to the buffer for the group
|
||||
// *pSetString - list of characters to flag
|
||||
//-----------------------------------------------------------------------------
|
||||
extern void CharacterSetBuild( characterset_t *pSetBuffer, const char *pSetString );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pSetBuffer - pre-build group buffer
|
||||
// character - character to lookup
|
||||
// Output : int - 1 if the character was in the set
|
||||
//-----------------------------------------------------------------------------
|
||||
#define IN_CHARACTERSET( SetBuffer, character ) ((SetBuffer).set[(unsigned char)(character)])
|
||||
|
||||
|
||||
#endif // CHARACTERSET_H
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Generic CRC functions
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#ifndef CHECKSUM_CRC_H
|
||||
#define CHECKSUM_CRC_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
typedef uint32 CRC32_t;
|
||||
|
||||
void CRC32_Init( CRC32_t *pulCRC );
|
||||
void CRC32_ProcessBuffer( CRC32_t *pulCRC, const void *p, int len );
|
||||
void CRC32_Final( CRC32_t *pulCRC );
|
||||
CRC32_t CRC32_GetTableEntry( unsigned int slot );
|
||||
|
||||
inline CRC32_t CRC32_ProcessSingleBuffer( const void *p, int len )
|
||||
{
|
||||
CRC32_t crc;
|
||||
|
||||
CRC32_Init( &crc );
|
||||
CRC32_ProcessBuffer( &crc, p, len );
|
||||
CRC32_Final( &crc );
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
#endif // CHECKSUM_CRC_H
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Generic MD5 hashing algo
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef CHECKSUM_MD5_H
|
||||
#define CHECKSUM_MD5_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
// 16 bytes == 128 bit digest
|
||||
#define MD5_DIGEST_LENGTH 16
|
||||
|
||||
// MD5 Hash
|
||||
typedef struct
|
||||
{
|
||||
unsigned int buf[4];
|
||||
unsigned int bits[2];
|
||||
unsigned char in[64];
|
||||
} MD5Context_t;
|
||||
|
||||
void MD5Init( MD5Context_t *context );
|
||||
void MD5Update( MD5Context_t *context, unsigned char const *buf, unsigned int len );
|
||||
void MD5Final( unsigned char digest[ MD5_DIGEST_LENGTH ], MD5Context_t *context );
|
||||
|
||||
char *MD5_Print(unsigned char *digest, int hashlen );
|
||||
|
||||
unsigned int MD5_PseudoRandom(unsigned int nSeed);
|
||||
|
||||
#endif // CHECKSUM_MD5_H
|
||||
Vendored
+975
@@ -0,0 +1,975 @@
|
||||
//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef CONVAR_H
|
||||
#define CONVAR_H
|
||||
|
||||
#if _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "tier0/dbg.h"
|
||||
#include "tier1/iconvar.h"
|
||||
#include "tier1/utlvector.h"
|
||||
#include "tier1/utlstring.h"
|
||||
#include "color.h"
|
||||
#include "icvar.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define FORCEINLINE_CVAR FORCEINLINE
|
||||
#elif POSIX
|
||||
#define FORCEINLINE_CVAR inline
|
||||
#elif defined(_PS3)
|
||||
#define FORCEINLINE_CVAR __attribute__((always_inline)) FORCEINLINE
|
||||
#else
|
||||
#error "implement me"
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Uncomment me to test for threading issues for material system convars
|
||||
// NOTE: You want to disable all threading when you do this
|
||||
// +host_thread_mode 0 +r_threaded_particles 0 +sv_parallel_packentities 0 +sv_disable_querycache 0
|
||||
//-----------------------------------------------------------------------------
|
||||
//#define CONVAR_TEST_MATERIAL_THREAD_CONVARS 1
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Forward declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
class ConVar;
|
||||
class CCommand;
|
||||
class ConCommand;
|
||||
class ConCommandBase;
|
||||
struct characterset_t;
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Any executable that wants to use ConVars need to implement one of
|
||||
// these to hook up access to console variables.
|
||||
//-----------------------------------------------------------------------------
|
||||
class IConCommandBaseAccessor
|
||||
{
|
||||
public:
|
||||
// Flags is a combination of FCVAR flags in cvar.h.
|
||||
// hOut is filled in with a handle to the variable.
|
||||
virtual bool RegisterConCommandBase( ConCommandBase *pVar ) = 0;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helper method for console development
|
||||
//-----------------------------------------------------------------------------
|
||||
#if defined( USE_VXCONSOLE )
|
||||
void ConVar_PublishToVXConsole();
|
||||
#else
|
||||
inline void ConVar_PublishToVXConsole() {}
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Called when a ConCommand needs to execute
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef void ( *FnCommandCallbackV1_t )( void );
|
||||
typedef void ( *FnCommandCallback_t )( const CCommand &command );
|
||||
|
||||
#define COMMAND_COMPLETION_MAXITEMS 64
|
||||
#define COMMAND_COMPLETION_ITEM_LENGTH 64
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef int ( *FnCommandCompletionCallback )( const char *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Interface version
|
||||
//-----------------------------------------------------------------------------
|
||||
class ICommandCallback
|
||||
{
|
||||
public:
|
||||
virtual void CommandCallback( const CCommand &command ) = 0;
|
||||
};
|
||||
|
||||
class ICommandCompletionCallback
|
||||
{
|
||||
public:
|
||||
virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) = 0;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: The base console invoked command/cvar interface
|
||||
//-----------------------------------------------------------------------------
|
||||
class ConCommandBase
|
||||
{
|
||||
friend class CCvar;
|
||||
friend class ConVar;
|
||||
friend class ConCommand;
|
||||
friend void ConVar_Register( int nCVarFlag, IConCommandBaseAccessor *pAccessor );
|
||||
friend void ConVar_PublishToVXConsole();
|
||||
|
||||
// FIXME: Remove when ConVar changes are done
|
||||
friend class CDefaultCvar;
|
||||
|
||||
public:
|
||||
ConCommandBase( void );
|
||||
ConCommandBase( const char *pName, const char *pHelpString = 0,
|
||||
int flags = 0 );
|
||||
|
||||
virtual ~ConCommandBase( void );
|
||||
|
||||
virtual bool IsCommand( void ) const;
|
||||
|
||||
// Check flag
|
||||
virtual bool IsFlagSet( int flag ) const;
|
||||
// Set flag
|
||||
virtual void AddFlags( int flags );
|
||||
// Clear flag
|
||||
virtual void RemoveFlags( int flags );
|
||||
|
||||
virtual int GetFlags() const;
|
||||
|
||||
// Return name of cvar
|
||||
virtual const char *GetName( void ) const;
|
||||
|
||||
// Return help text for cvar
|
||||
virtual const char *GetHelpText( void ) const;
|
||||
|
||||
// Deal with next pointer
|
||||
const ConCommandBase *GetNext( void ) const;
|
||||
ConCommandBase *GetNext( void );
|
||||
|
||||
virtual bool IsRegistered( void ) const;
|
||||
|
||||
// Returns the DLL identifier
|
||||
virtual CVarDLLIdentifier_t GetDLLIdentifier() const;
|
||||
|
||||
protected:
|
||||
virtual void Create( const char *pName, const char *pHelpString = 0,
|
||||
int flags = 0 );
|
||||
|
||||
// Used internally by OneTimeInit to initialize/shutdown
|
||||
virtual void Init();
|
||||
void Shutdown();
|
||||
|
||||
// Internal copy routine ( uses new operator from correct module )
|
||||
char *CopyString( const char *from );
|
||||
|
||||
private:
|
||||
// Next ConVar in chain
|
||||
// Prior to register, it points to the next convar in the DLL.
|
||||
// Once registered, though, m_pNext is reset to point to the next
|
||||
// convar in the global list
|
||||
ConCommandBase *m_pNext;
|
||||
|
||||
// Has the cvar been added to the global list?
|
||||
bool m_bRegistered;
|
||||
|
||||
// Static data
|
||||
const char *m_pszName;
|
||||
const char *m_pszHelpString;
|
||||
|
||||
// ConVar flags
|
||||
int m_nFlags;
|
||||
|
||||
protected:
|
||||
// ConVars add themselves to this list for the executable.
|
||||
// Then ConVar_Register runs through all the console variables
|
||||
// and registers them into a global list stored in vstdlib.dll
|
||||
static ConCommandBase *s_pConCommandBases;
|
||||
|
||||
// ConVars in this executable use this 'global' to access values.
|
||||
static IConCommandBaseAccessor *s_pAccessor;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Command tokenizer
|
||||
//-----------------------------------------------------------------------------
|
||||
class CCommand
|
||||
{
|
||||
public:
|
||||
CCommand();
|
||||
CCommand( int nArgC, const char **ppArgV );
|
||||
bool Tokenize( const char *pCommand, characterset_t *pBreakSet = NULL );
|
||||
void Reset();
|
||||
|
||||
int ArgC() const;
|
||||
const char **ArgV() const;
|
||||
const char *ArgS() const; // All args that occur after the 0th arg, in string form
|
||||
const char *GetCommandString() const; // The entire command in string form, including the 0th arg
|
||||
const char *operator[]( int nIndex ) const; // Gets at arguments
|
||||
const char *Arg( int nIndex ) const; // Gets at arguments
|
||||
|
||||
// Helper functions to parse arguments to commands.
|
||||
const char* FindArg( const char *pName ) const;
|
||||
int FindArgInt( const char *pName, int nDefaultVal ) const;
|
||||
|
||||
static int MaxCommandLength();
|
||||
static characterset_t* DefaultBreakSet();
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
COMMAND_MAX_ARGC = 64,
|
||||
COMMAND_MAX_LENGTH = 512,
|
||||
};
|
||||
|
||||
int m_nArgc;
|
||||
int m_nArgv0Size;
|
||||
char m_pArgSBuffer[ COMMAND_MAX_LENGTH ];
|
||||
char m_pArgvBuffer[ COMMAND_MAX_LENGTH ];
|
||||
const char* m_ppArgv[ COMMAND_MAX_ARGC ];
|
||||
};
|
||||
|
||||
inline int CCommand::MaxCommandLength()
|
||||
{
|
||||
return COMMAND_MAX_LENGTH - 1;
|
||||
}
|
||||
|
||||
inline int CCommand::ArgC() const
|
||||
{
|
||||
return m_nArgc;
|
||||
}
|
||||
|
||||
inline const char **CCommand::ArgV() const
|
||||
{
|
||||
return m_nArgc ? (const char**)m_ppArgv : NULL;
|
||||
}
|
||||
|
||||
inline const char *CCommand::ArgS() const
|
||||
{
|
||||
return m_nArgv0Size ? &m_pArgSBuffer[m_nArgv0Size] : "";
|
||||
}
|
||||
|
||||
inline const char *CCommand::GetCommandString() const
|
||||
{
|
||||
return m_nArgc ? m_pArgSBuffer : "";
|
||||
}
|
||||
|
||||
inline const char *CCommand::Arg( int nIndex ) const
|
||||
{
|
||||
// FIXME: Many command handlers appear to not be particularly careful
|
||||
// about checking for valid argc range. For now, we're going to
|
||||
// do the extra check and return an empty string if it's out of range
|
||||
if ( nIndex < 0 || nIndex >= m_nArgc )
|
||||
return "";
|
||||
return m_ppArgv[nIndex];
|
||||
}
|
||||
|
||||
inline const char *CCommand::operator[]( int nIndex ) const
|
||||
{
|
||||
return Arg( nIndex );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: The console invoked command
|
||||
//-----------------------------------------------------------------------------
|
||||
class ConCommand : public ConCommandBase
|
||||
{
|
||||
friend class CCvar;
|
||||
|
||||
public:
|
||||
typedef ConCommandBase BaseClass;
|
||||
|
||||
ConCommand( const char *pName, FnCommandCallbackV1_t callback,
|
||||
const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
|
||||
ConCommand( const char *pName, FnCommandCallback_t callback,
|
||||
const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
|
||||
ConCommand( const char *pName, ICommandCallback *pCallback,
|
||||
const char *pHelpString = 0, int flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 );
|
||||
|
||||
virtual ~ConCommand( void );
|
||||
|
||||
virtual bool IsCommand( void ) const;
|
||||
|
||||
virtual int AutoCompleteSuggest( const char *partial, CUtlVector< CUtlString > &commands );
|
||||
|
||||
virtual bool CanAutoComplete( void );
|
||||
|
||||
// Invoke the function
|
||||
virtual void Dispatch( const CCommand &command );
|
||||
|
||||
private:
|
||||
// NOTE: To maintain backward compat, we have to be very careful:
|
||||
// All public virtual methods must appear in the same order always
|
||||
// since engine code will be calling into this code, which *does not match*
|
||||
// in the mod code; it's using slightly different, but compatible versions
|
||||
// of this class. Also: Be very careful about adding new fields to this class.
|
||||
// Those fields will not exist in the version of this class that is instanced
|
||||
// in mod code.
|
||||
|
||||
// Call this function when executing the command
|
||||
union
|
||||
{
|
||||
FnCommandCallbackV1_t m_fnCommandCallbackV1;
|
||||
FnCommandCallback_t m_fnCommandCallback;
|
||||
ICommandCallback *m_pCommandCallback;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
FnCommandCompletionCallback m_fnCompletionCallback;
|
||||
ICommandCompletionCallback *m_pCommandCompletionCallback;
|
||||
};
|
||||
|
||||
bool m_bHasCompletionCallback : 1;
|
||||
bool m_bUsingNewCommandCallback : 1;
|
||||
bool m_bUsingCommandCallbackInterface : 1;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: A console variable
|
||||
//-----------------------------------------------------------------------------
|
||||
class ConVar : public ConCommandBase, public IConVar
|
||||
{
|
||||
friend class CCvar;
|
||||
friend class ConVarRef;
|
||||
friend class SplitScreenConVarRef;
|
||||
|
||||
public:
|
||||
typedef ConCommandBase BaseClass;
|
||||
|
||||
ConVar( const char *pName, const char *pDefaultValue, int flags = 0);
|
||||
|
||||
ConVar( const char *pName, const char *pDefaultValue, int flags,
|
||||
const char *pHelpString );
|
||||
ConVar( const char *pName, const char *pDefaultValue, int flags,
|
||||
const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax );
|
||||
ConVar( const char *pName, const char *pDefaultValue, int flags,
|
||||
const char *pHelpString, FnChangeCallback_t callback );
|
||||
ConVar( const char *pName, const char *pDefaultValue, int flags,
|
||||
const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax,
|
||||
FnChangeCallback_t callback );
|
||||
|
||||
virtual ~ConVar( void );
|
||||
|
||||
virtual bool IsFlagSet( int flag ) const;
|
||||
virtual const char* GetHelpText( void ) const;
|
||||
virtual bool IsRegistered( void ) const;
|
||||
virtual const char *GetName( void ) const;
|
||||
// Return name of command (usually == GetName(), except in case of FCVAR_SS_ADDED vars
|
||||
virtual const char *GetBaseName( void ) const;
|
||||
virtual int GetSplitScreenPlayerSlot() const;
|
||||
|
||||
virtual void AddFlags( int flags );
|
||||
virtual int GetFlags() const;
|
||||
virtual bool IsCommand( void ) const;
|
||||
|
||||
// Install a change callback (there shouldn't already be one....)
|
||||
void InstallChangeCallback( FnChangeCallback_t callback, bool bInvoke = true );
|
||||
void RemoveChangeCallback( FnChangeCallback_t callbackToRemove );
|
||||
|
||||
int GetChangeCallbackCount() const { return m_pParent->m_fnChangeCallbacks.Count(); }
|
||||
FnChangeCallback_t GetChangeCallback( int slot ) const { return m_pParent->m_fnChangeCallbacks[ slot ]; }
|
||||
|
||||
// Retrieve value
|
||||
FORCEINLINE_CVAR float GetFloat( void ) const;
|
||||
FORCEINLINE_CVAR int GetInt( void ) const;
|
||||
FORCEINLINE_CVAR Color GetColor( void ) const;
|
||||
FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); }
|
||||
FORCEINLINE_CVAR char const *GetString( void ) const;
|
||||
|
||||
// Compiler driven selection for template use
|
||||
template <typename T> T Get( void ) const;
|
||||
template <typename T> T Get( T * ) const;
|
||||
|
||||
// Any function that allocates/frees memory needs to be virtual or else you'll have crashes
|
||||
// from alloc/free across dll/exe boundaries.
|
||||
|
||||
// These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue).
|
||||
virtual void SetValue( const char *value );
|
||||
virtual void SetValue( float value );
|
||||
virtual void SetValue( int value );
|
||||
virtual void SetValue( Color value );
|
||||
|
||||
// Reset to default value
|
||||
void Revert( void );
|
||||
|
||||
// True if it has a min/max setting
|
||||
bool HasMin() const;
|
||||
bool HasMax() const;
|
||||
|
||||
bool GetMin( float& minVal ) const;
|
||||
bool GetMax( float& maxVal ) const;
|
||||
|
||||
float GetMinValue() const;
|
||||
float GetMaxValue() const;
|
||||
|
||||
const char *GetDefault( void ) const;
|
||||
void SetDefault( const char *pszDefault );
|
||||
|
||||
// Value
|
||||
struct CVValue_t
|
||||
{
|
||||
char *m_pszString;
|
||||
int m_StringLength;
|
||||
|
||||
// Values
|
||||
float m_fValue;
|
||||
int m_nValue;
|
||||
};
|
||||
|
||||
FORCEINLINE_CVAR CVValue_t &GetRawValue()
|
||||
{
|
||||
return m_Value;
|
||||
}
|
||||
FORCEINLINE_CVAR const CVValue_t &GetRawValue() const
|
||||
{
|
||||
return m_Value;
|
||||
}
|
||||
|
||||
private:
|
||||
bool InternalSetColorFromString( const char *value );
|
||||
// Called by CCvar when the value of a var is changing.
|
||||
virtual void InternalSetValue(const char *value);
|
||||
// For CVARs marked FCVAR_NEVER_AS_STRING
|
||||
virtual void InternalSetFloatValue( float fNewValue );
|
||||
virtual void InternalSetIntValue( int nValue );
|
||||
virtual void InternalSetColorValue( Color value );
|
||||
|
||||
virtual bool ClampValue( float& value );
|
||||
virtual void ChangeStringValue( const char *tempVal, float flOldValue );
|
||||
|
||||
virtual void Create( const char *pName, const char *pDefaultValue, int flags = 0,
|
||||
const char *pHelpString = 0, bool bMin = false, float fMin = 0.0,
|
||||
bool bMax = false, float fMax = false, FnChangeCallback_t callback = 0 );
|
||||
|
||||
// Used internally by OneTimeInit to initialize.
|
||||
virtual void Init();
|
||||
|
||||
protected:
|
||||
|
||||
// This either points to "this" or it points to the original declaration of a ConVar.
|
||||
// This allows ConVars to exist in separate modules, and they all use the first one to be declared.
|
||||
// m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar).
|
||||
ConVar *m_pParent;
|
||||
|
||||
// Static data
|
||||
const char *m_pszDefaultValue;
|
||||
|
||||
CVValue_t m_Value;
|
||||
|
||||
// Min/Max values
|
||||
bool m_bHasMin;
|
||||
float m_fMinVal;
|
||||
bool m_bHasMax;
|
||||
float m_fMaxVal;
|
||||
|
||||
// Call this function when ConVar changes
|
||||
CUtlVector< FnChangeCallback_t > m_fnChangeCallbacks;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as a float
|
||||
// Output : float
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE_CVAR float ConVar::GetFloat( void ) const
|
||||
{
|
||||
#ifdef CONVAR_TEST_MATERIAL_THREAD_CONVARS
|
||||
Assert( ThreadInMainThread() || IsFlagSet( FCVAR_MATERIAL_THREAD_MASK | FCVAR_ACCESSIBLE_FROM_THREADS ) );
|
||||
#endif
|
||||
return m_pParent->m_Value.m_fValue;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as an int
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE_CVAR int ConVar::GetInt( void ) const
|
||||
{
|
||||
#ifdef CONVAR_TEST_MATERIAL_THREAD_CONVARS
|
||||
Assert( ThreadInMainThread() || IsFlagSet( FCVAR_MATERIAL_THREAD_MASK | FCVAR_ACCESSIBLE_FROM_THREADS ) );
|
||||
#endif
|
||||
return m_pParent->m_Value.m_nValue;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as a color
|
||||
// Output : Color
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE_CVAR Color ConVar::GetColor( void ) const
|
||||
{
|
||||
#ifdef CONVAR_TEST_MATERIAL_THREAD_CONVARS
|
||||
Assert( ThreadInMainThread() || IsFlagSet( FCVAR_MATERIAL_THREAD_MASK | FCVAR_ACCESSIBLE_FROM_THREADS ) );
|
||||
#endif
|
||||
unsigned char *pColorElement = ((unsigned char *)&m_pParent->m_Value.m_nValue);
|
||||
return Color( pColorElement[0], pColorElement[1], pColorElement[2], pColorElement[3] );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <> FORCEINLINE_CVAR float ConVar::Get<float>( void ) const { return GetFloat(); }
|
||||
template <> FORCEINLINE_CVAR int ConVar::Get<int>( void ) const { return GetInt(); }
|
||||
template <> FORCEINLINE_CVAR bool ConVar::Get<bool>( void ) const { return GetBool(); }
|
||||
template <> FORCEINLINE_CVAR const char * ConVar::Get<const char *>( void ) const { return GetString(); }
|
||||
template <> FORCEINLINE_CVAR float ConVar::Get<float>( float *p ) const { return ( *p = GetFloat() ); }
|
||||
template <> FORCEINLINE_CVAR int ConVar::Get<int>( int *p ) const { return ( *p = GetInt() ); }
|
||||
template <> FORCEINLINE_CVAR bool ConVar::Get<bool>( bool *p ) const { return ( *p = GetBool() ); }
|
||||
template <> FORCEINLINE_CVAR const char * ConVar::Get<const char *>( char const **p ) const { return ( *p = GetString() ); }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
|
||||
// Output : const char *
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE_CVAR const char *ConVar::GetString( void ) const
|
||||
{
|
||||
#ifdef CONVAR_TEST_MATERIAL_THREAD_CONVARS
|
||||
Assert( ThreadInMainThread() || IsFlagSet( FCVAR_MATERIAL_THREAD_MASK | FCVAR_ACCESSIBLE_FROM_THREADS ) );
|
||||
#endif
|
||||
if ( m_nFlags & FCVAR_NEVER_AS_STRING )
|
||||
return "FCVAR_NEVER_AS_STRING";
|
||||
|
||||
char const *str = m_pParent->m_Value.m_pszString;
|
||||
return str ? str : "";
|
||||
}
|
||||
|
||||
class CSplitScreenAddedConVar : public ConVar
|
||||
{
|
||||
typedef ConVar BaseClass;
|
||||
public:
|
||||
CSplitScreenAddedConVar( int nSplitScreenSlot, const char *pName, const ConVar *pBaseVar ) :
|
||||
BaseClass
|
||||
(
|
||||
pName,
|
||||
pBaseVar->GetDefault(),
|
||||
// Keep basevar flags, except remove _SS and add _SS_ADDED instead
|
||||
( pBaseVar->GetFlags() & ~FCVAR_SS ) | FCVAR_SS_ADDED,
|
||||
pBaseVar->GetHelpText(),
|
||||
pBaseVar->HasMin(),
|
||||
pBaseVar->GetMinValue(),
|
||||
pBaseVar->HasMax(),
|
||||
pBaseVar->GetMaxValue()
|
||||
),
|
||||
m_pBaseVar( pBaseVar ),
|
||||
m_nSplitScreenSlot( nSplitScreenSlot )
|
||||
{
|
||||
for ( int i = 0; i < pBaseVar->GetChangeCallbackCount(); ++i )
|
||||
{
|
||||
InstallChangeCallback( pBaseVar->GetChangeCallback( i ), false );
|
||||
}
|
||||
Assert( nSplitScreenSlot >= 1 );
|
||||
Assert( nSplitScreenSlot < MAX_SPLITSCREEN_CLIENTS );
|
||||
Assert( m_pBaseVar );
|
||||
Assert( IsFlagSet( FCVAR_SS_ADDED ) );
|
||||
Assert( !IsFlagSet( FCVAR_SS ) );
|
||||
}
|
||||
|
||||
const ConVar *GetBaseVar() const;
|
||||
virtual const char *GetBaseName() const;
|
||||
void SetSplitScreenPlayerSlot( int nSlot );
|
||||
virtual int GetSplitScreenPlayerSlot() const;
|
||||
|
||||
protected:
|
||||
|
||||
const ConVar *m_pBaseVar;
|
||||
int m_nSplitScreenSlot;
|
||||
};
|
||||
|
||||
FORCEINLINE_CVAR const ConVar *CSplitScreenAddedConVar::GetBaseVar() const
|
||||
{
|
||||
Assert( m_pBaseVar );
|
||||
return m_pBaseVar;
|
||||
}
|
||||
|
||||
FORCEINLINE_CVAR const char *CSplitScreenAddedConVar::GetBaseName() const
|
||||
{
|
||||
Assert( m_pBaseVar );
|
||||
return m_pBaseVar->GetName();
|
||||
}
|
||||
|
||||
FORCEINLINE_CVAR void CSplitScreenAddedConVar::SetSplitScreenPlayerSlot( int nSlot )
|
||||
{
|
||||
m_nSplitScreenSlot = nSlot;
|
||||
}
|
||||
|
||||
FORCEINLINE_CVAR int CSplitScreenAddedConVar::GetSplitScreenPlayerSlot() const
|
||||
{
|
||||
return m_nSplitScreenSlot;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Used to read/write convars that already exist (replaces the FindVar method)
|
||||
//-----------------------------------------------------------------------------
|
||||
class ConVarRef
|
||||
{
|
||||
public:
|
||||
ConVarRef( const char *pName );
|
||||
ConVarRef( const char *pName, bool bIgnoreMissing );
|
||||
ConVarRef( IConVar *pConVar );
|
||||
|
||||
void Init( const char *pName, bool bIgnoreMissing );
|
||||
bool IsValid() const;
|
||||
bool IsFlagSet( int nFlags ) const;
|
||||
IConVar *GetLinkedConVar();
|
||||
|
||||
// Get/Set value
|
||||
float GetFloat( void ) const;
|
||||
int GetInt( void ) const;
|
||||
Color GetColor( void ) const;
|
||||
bool GetBool() const { return !!GetInt(); }
|
||||
const char *GetString( void ) const;
|
||||
|
||||
void SetValue( const char *pValue );
|
||||
void SetValue( float flValue );
|
||||
void SetValue( int nValue );
|
||||
void SetValue( Color value );
|
||||
void SetValue( bool bValue );
|
||||
|
||||
const char *GetName() const;
|
||||
|
||||
const char *GetDefault() const;
|
||||
|
||||
const char *GetBaseName() const;
|
||||
|
||||
int GetSplitScreenPlayerSlot() const;
|
||||
|
||||
private:
|
||||
// High-speed method to read convar data
|
||||
IConVar *m_pConVar;
|
||||
ConVar *m_pConVarState;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Did we find an existing convar of that name?
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE_CVAR bool ConVarRef::IsFlagSet( int nFlags ) const
|
||||
{
|
||||
return ( m_pConVar->IsFlagSet( nFlags ) != 0 );
|
||||
}
|
||||
|
||||
FORCEINLINE_CVAR IConVar *ConVarRef::GetLinkedConVar()
|
||||
{
|
||||
return m_pConVar;
|
||||
}
|
||||
|
||||
FORCEINLINE_CVAR const char *ConVarRef::GetName() const
|
||||
{
|
||||
return m_pConVar->GetName();
|
||||
}
|
||||
|
||||
FORCEINLINE_CVAR const char *ConVarRef::GetBaseName() const
|
||||
{
|
||||
return m_pConVar->GetBaseName();
|
||||
}
|
||||
|
||||
FORCEINLINE_CVAR int ConVarRef::GetSplitScreenPlayerSlot() const
|
||||
{
|
||||
return m_pConVar->GetSplitScreenPlayerSlot();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as a float
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE_CVAR float ConVarRef::GetFloat( void ) const
|
||||
{
|
||||
return m_pConVarState->m_Value.m_fValue;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as an int
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE_CVAR int ConVarRef::GetInt( void ) const
|
||||
{
|
||||
return m_pConVarState->m_Value.m_nValue;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as a color
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE_CVAR Color ConVarRef::GetColor( void ) const
|
||||
{
|
||||
return m_pConVarState->GetColor();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE_CVAR const char *ConVarRef::GetString( void ) const
|
||||
{
|
||||
Assert( !IsFlagSet( FCVAR_NEVER_AS_STRING ) );
|
||||
return m_pConVarState->m_Value.m_pszString;
|
||||
}
|
||||
|
||||
|
||||
FORCEINLINE_CVAR void ConVarRef::SetValue( const char *pValue )
|
||||
{
|
||||
m_pConVar->SetValue( pValue );
|
||||
}
|
||||
|
||||
FORCEINLINE_CVAR void ConVarRef::SetValue( float flValue )
|
||||
{
|
||||
m_pConVar->SetValue( flValue );
|
||||
}
|
||||
|
||||
FORCEINLINE_CVAR void ConVarRef::SetValue( int nValue )
|
||||
{
|
||||
m_pConVar->SetValue( nValue );
|
||||
}
|
||||
|
||||
FORCEINLINE_CVAR void ConVarRef::SetValue( Color value )
|
||||
{
|
||||
m_pConVar->SetValue( value );
|
||||
}
|
||||
|
||||
FORCEINLINE_CVAR void ConVarRef::SetValue( bool bValue )
|
||||
{
|
||||
m_pConVar->SetValue( bValue ? 1 : 0 );
|
||||
}
|
||||
|
||||
FORCEINLINE_CVAR const char *ConVarRef::GetDefault() const
|
||||
{
|
||||
return m_pConVarState->m_pszDefaultValue;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helper for referencing splitscreen convars (i.e., "name" and "name2")
|
||||
//-----------------------------------------------------------------------------
|
||||
class SplitScreenConVarRef
|
||||
{
|
||||
public:
|
||||
SplitScreenConVarRef( const char *pName );
|
||||
SplitScreenConVarRef( const char *pName, bool bIgnoreMissing );
|
||||
SplitScreenConVarRef( IConVar *pConVar );
|
||||
|
||||
void Init( const char *pName, bool bIgnoreMissing );
|
||||
bool IsValid() const;
|
||||
bool IsFlagSet( int nFlags ) const;
|
||||
|
||||
// Get/Set value
|
||||
float GetFloat( int nSlot ) const;
|
||||
int GetInt( int nSlot ) const;
|
||||
Color GetColor( int nSlot ) const;
|
||||
bool GetBool( int nSlot ) const { return !!GetInt( nSlot ); }
|
||||
const char *GetString( int nSlot ) const;
|
||||
|
||||
void SetValue( int nSlot, const char *pValue );
|
||||
void SetValue( int nSlot, float flValue );
|
||||
void SetValue( int nSlot, int nValue );
|
||||
void SetValue( int nSlot, Color value );
|
||||
void SetValue( int nSlot, bool bValue );
|
||||
|
||||
const char *GetName( int nSlot ) const;
|
||||
|
||||
const char *GetDefault() const;
|
||||
|
||||
const char *GetBaseName() const;
|
||||
|
||||
private:
|
||||
struct cv_t
|
||||
{
|
||||
IConVar *m_pConVar;
|
||||
ConVar *m_pConVarState;
|
||||
};
|
||||
|
||||
cv_t m_Info[ MAX_SPLITSCREEN_CLIENTS ];
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Did we find an existing convar of that name?
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE_CVAR bool SplitScreenConVarRef::IsFlagSet( int nFlags ) const
|
||||
{
|
||||
return ( m_Info[ 0 ].m_pConVar->IsFlagSet( nFlags ) != 0 );
|
||||
}
|
||||
|
||||
FORCEINLINE_CVAR const char *SplitScreenConVarRef::GetName( int nSlot ) const
|
||||
{
|
||||
return m_Info[ nSlot ].m_pConVar->GetName();
|
||||
}
|
||||
|
||||
FORCEINLINE_CVAR const char *SplitScreenConVarRef::GetBaseName() const
|
||||
{
|
||||
return m_Info[ 0 ].m_pConVar->GetBaseName();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as a float
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE_CVAR float SplitScreenConVarRef::GetFloat( int nSlot ) const
|
||||
{
|
||||
return m_Info[ nSlot ].m_pConVarState->m_Value.m_fValue;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as an int
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE_CVAR int SplitScreenConVarRef::GetInt( int nSlot ) const
|
||||
{
|
||||
return m_Info[ nSlot ].m_pConVarState->m_Value.m_nValue;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as an int
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE_CVAR Color SplitScreenConVarRef::GetColor( int nSlot ) const
|
||||
{
|
||||
return m_Info[ nSlot ].m_pConVarState->GetColor();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE_CVAR const char *SplitScreenConVarRef::GetString( int nSlot ) const
|
||||
{
|
||||
Assert( !IsFlagSet( FCVAR_NEVER_AS_STRING ) );
|
||||
return m_Info[ nSlot ].m_pConVarState->m_Value.m_pszString;
|
||||
}
|
||||
|
||||
|
||||
FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, const char *pValue )
|
||||
{
|
||||
m_Info[ nSlot ].m_pConVar->SetValue( pValue );
|
||||
}
|
||||
|
||||
FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, float flValue )
|
||||
{
|
||||
m_Info[ nSlot ].m_pConVar->SetValue( flValue );
|
||||
}
|
||||
|
||||
FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, int nValue )
|
||||
{
|
||||
m_Info[ nSlot ].m_pConVar->SetValue( nValue );
|
||||
}
|
||||
|
||||
FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, Color value )
|
||||
{
|
||||
m_Info[ nSlot ].m_pConVar->SetValue( value );
|
||||
}
|
||||
|
||||
FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, bool bValue )
|
||||
{
|
||||
m_Info[ nSlot ].m_pConVar->SetValue( bValue ? 1 : 0 );
|
||||
}
|
||||
|
||||
FORCEINLINE_CVAR const char *SplitScreenConVarRef::GetDefault() const
|
||||
{
|
||||
return m_Info[ 0 ].m_pConVarState->m_pszDefaultValue;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Called by the framework to register ConCommands with the ICVar
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar_Register( int nCVarFlag = 0, IConCommandBaseAccessor *pAccessor = NULL );
|
||||
void ConVar_Unregister( );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Utility methods
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar_PrintDescription( const ConCommandBase *pVar );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Utility class to quickly allow ConCommands to call member methods
|
||||
//-----------------------------------------------------------------------------
|
||||
#pragma warning (disable : 4355 )
|
||||
|
||||
template< class T >
|
||||
class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, public ICommandCompletionCallback
|
||||
{
|
||||
typedef ConCommand BaseClass;
|
||||
typedef void ( T::*FnMemberCommandCallback_t )( const CCommand &command );
|
||||
typedef int ( T::*FnMemberCommandCompletionCallback_t )( const char *pPartial, CUtlVector< CUtlString > &commands );
|
||||
|
||||
public:
|
||||
CConCommandMemberAccessor( T* pOwner, const char *pName, FnMemberCommandCallback_t callback, const char *pHelpString = 0,
|
||||
int flags = 0, FnMemberCommandCompletionCallback_t completionFunc = 0 ) :
|
||||
BaseClass( pName, this, pHelpString, flags, ( completionFunc != 0 ) ? this : NULL )
|
||||
{
|
||||
m_pOwner = pOwner;
|
||||
m_Func = callback;
|
||||
m_CompletionFunc = completionFunc;
|
||||
}
|
||||
|
||||
~CConCommandMemberAccessor()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void SetOwner( T* pOwner )
|
||||
{
|
||||
m_pOwner = pOwner;
|
||||
}
|
||||
|
||||
virtual void CommandCallback( const CCommand &command )
|
||||
{
|
||||
Assert( m_pOwner && m_Func );
|
||||
(m_pOwner->*m_Func)( command );
|
||||
}
|
||||
|
||||
virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands )
|
||||
{
|
||||
Assert( m_pOwner && m_CompletionFunc );
|
||||
return (m_pOwner->*m_CompletionFunc)( pPartial, commands );
|
||||
}
|
||||
|
||||
private:
|
||||
T* m_pOwner;
|
||||
FnMemberCommandCallback_t m_Func;
|
||||
FnMemberCommandCompletionCallback_t m_CompletionFunc;
|
||||
};
|
||||
|
||||
#pragma warning ( default : 4355 )
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Utility macros to quicky generate a simple console command
|
||||
//-----------------------------------------------------------------------------
|
||||
#define CON_COMMAND( name, description ) \
|
||||
static void name( const CCommand &args ); \
|
||||
static ConCommand name##_command( #name, name, description ); \
|
||||
static void name( const CCommand &args )
|
||||
|
||||
#define CON_COMMAND_F( name, description, flags ) \
|
||||
static void name( const CCommand &args ); \
|
||||
static ConCommand name##_command( #name, name, description, flags ); \
|
||||
static void name( const CCommand &args )
|
||||
|
||||
#define CON_COMMAND_F_COMPLETION( name, description, flags, completion ) \
|
||||
static void name( const CCommand &args ); \
|
||||
static ConCommand name##_command( #name, name, description, flags, completion ); \
|
||||
static void name( const CCommand &args )
|
||||
|
||||
#define CON_COMMAND_EXTERN( name, _funcname, description ) \
|
||||
void _funcname( const CCommand &args ); \
|
||||
static ConCommand name##_command( #name, _funcname, description ); \
|
||||
void _funcname( const CCommand &args )
|
||||
|
||||
#define CON_COMMAND_EXTERN_F( name, _funcname, description, flags ) \
|
||||
void _funcname( const CCommand &args ); \
|
||||
static ConCommand name##_command( #name, _funcname, description, flags ); \
|
||||
void _funcname( const CCommand &args )
|
||||
|
||||
#define CON_COMMAND_MEMBER_F( _thisclass, name, _funcname, description, flags ) \
|
||||
void _funcname( const CCommand &args ); \
|
||||
friend class CCommandMemberInitializer_##_funcname; \
|
||||
class CCommandMemberInitializer_##_funcname \
|
||||
{ \
|
||||
public: \
|
||||
CCommandMemberInitializer_##_funcname() : m_ConCommandAccessor( NULL, name, &_thisclass::_funcname, description, flags ) \
|
||||
{ \
|
||||
m_ConCommandAccessor.SetOwner( GET_OUTER( _thisclass, m_##_funcname##_register ) ); \
|
||||
} \
|
||||
private: \
|
||||
CConCommandMemberAccessor< _thisclass > m_ConCommandAccessor; \
|
||||
}; \
|
||||
\
|
||||
CCommandMemberInitializer_##_funcname m_##_funcname##_register; \
|
||||
|
||||
|
||||
#endif // CONVAR_H
|
||||
@@ -0,0 +1,53 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Helper class for cvars that have restrictions on their value.
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef CONVAR_SERVERBOUNDED_H
|
||||
#define CONVAR_SERVERBOUNDED_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
// This class is used to virtualize a ConVar's value, so the client can restrict its
|
||||
// value while connected to a server. When using this across modules, it's important
|
||||
// to dynamic_cast it to a ConVar_ServerBounded or you won't get the restricted value.
|
||||
//
|
||||
// NOTE: FCVAR_USERINFO vars are not virtualized before they are sent to the server
|
||||
// (we have no way to detect if the virtualized value would change), so
|
||||
// if you want to use a bounded cvar's value on the server, you must rebound it
|
||||
// the same way the client does.
|
||||
class ConVar_ServerBounded : public ConVar
|
||||
{
|
||||
public:
|
||||
ConVar_ServerBounded( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString )
|
||||
: ConVar( pName, pDefaultValue, flags, pHelpString )
|
||||
{
|
||||
}
|
||||
|
||||
ConVar_ServerBounded( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, FnChangeCallback_t callback )
|
||||
: ConVar( pName, pDefaultValue, flags, pHelpString, callback )
|
||||
{
|
||||
}
|
||||
|
||||
ConVar_ServerBounded( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax )
|
||||
: ConVar( pName, pDefaultValue, flags, pHelpString, bMin, fMin, bMax, fMax ) {}
|
||||
|
||||
// You must implement GetFloat.
|
||||
virtual float GetFloat() const = 0;
|
||||
|
||||
// You can optionally implement these.
|
||||
virtual int GetInt() const { return (int)GetFloat(); }
|
||||
virtual bool GetBool() const { return ( GetInt() != 0 ); }
|
||||
|
||||
// Use this to get the underlying cvar's value.
|
||||
float GetBaseFloatValue() const
|
||||
{
|
||||
return ConVar::GetFloat();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // CONVAR_SERVERBOUNDED_H
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
//===== Copyright © 1996-2006, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose: ExprSimplifier builds a binary tree from an infix expression (in the
|
||||
// form of a character array).
|
||||
//
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef EXPREVALUATOR_H
|
||||
#define EXPREVALUATOR_H
|
||||
|
||||
#if defined( _WIN32 )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
static const char OR_OP = '|';
|
||||
static const char AND_OP = '&';
|
||||
static const char NOT_OP = '!';
|
||||
|
||||
#define MAX_IDENTIFIER_LEN 128
|
||||
enum Kind {CONDITIONAL, NOT, LITERAL};
|
||||
|
||||
struct ExprNode
|
||||
{
|
||||
ExprNode *left; // left sub-expression
|
||||
ExprNode *right; // right sub-expression
|
||||
Kind kind; // kind of node this is
|
||||
union
|
||||
{
|
||||
char cond; // the conditional
|
||||
bool value; // the value
|
||||
} data;
|
||||
};
|
||||
|
||||
typedef ExprNode *ExprTree;
|
||||
|
||||
// callback to evaluate a $<symbol> during evaluation, return true or false
|
||||
typedef bool (*GetSymbolProc_t)( const char *pKey );
|
||||
typedef void (*SyntaxErrorProc_t)( const char *pReason );
|
||||
|
||||
class CExpressionEvaluator
|
||||
{
|
||||
public:
|
||||
CExpressionEvaluator();
|
||||
~CExpressionEvaluator();
|
||||
bool Evaluate( bool &result, const char *pInfixExpression, GetSymbolProc_t pGetSymbolProc = 0, SyntaxErrorProc_t pSyntaxErrorProc = 0 );
|
||||
|
||||
private:
|
||||
CExpressionEvaluator( CExpressionEvaluator& ); // prevent copy constructor being used
|
||||
|
||||
char GetNextToken( void );
|
||||
void FreeNode( ExprNode *pNode );
|
||||
ExprNode *AllocateNode( void );
|
||||
void FreeTree( ExprTree &node );
|
||||
bool IsConditional( bool &bCondition, const char token );
|
||||
bool IsNotOp( const char token );
|
||||
bool IsIdentifierOrConstant( const char token );
|
||||
bool MakeExprNode( ExprTree &tree, char token, Kind kind, ExprTree left, ExprTree right );
|
||||
bool MakeFactor( ExprTree &tree );
|
||||
bool MakeTerm( ExprTree &tree );
|
||||
bool MakeExpression( ExprTree &tree );
|
||||
bool BuildExpression( void );
|
||||
bool SimplifyNode( ExprTree &node );
|
||||
|
||||
ExprTree m_ExprTree; // Tree representation of the expression
|
||||
char m_CurToken; // Current token read from the input expression
|
||||
const char *m_pExpression; // Array of the expression characters
|
||||
int m_CurPosition; // Current position in the input expression
|
||||
char m_Identifier[MAX_IDENTIFIER_LEN]; // Stores the identifier string
|
||||
GetSymbolProc_t m_pGetSymbolProc;
|
||||
SyntaxErrorProc_t m_pSyntaxErrorProc;
|
||||
bool m_bSetup;
|
||||
};
|
||||
|
||||
#endif
|
||||
Vendored
+179
@@ -0,0 +1,179 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: A simple class for performing safe and in-expression sprintf-style
|
||||
// string formatting
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef FMTSTR_H
|
||||
#define FMTSTR_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include "tier0/platform.h"
|
||||
#include "tier0/dbg.h"
|
||||
#include "tier1/strtools.h"
|
||||
|
||||
#if defined( _WIN32 )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// using macro to be compatable with GCC
|
||||
#define FmtStrVSNPrintf( szBuf, nBufSize, bQuietTruncation, ppszFormat ) \
|
||||
do \
|
||||
{ \
|
||||
int result; \
|
||||
va_list arg_ptr; \
|
||||
bool bTruncated = false; \
|
||||
static int scAsserted = 0; \
|
||||
\
|
||||
va_start(arg_ptr, (*(ppszFormat))); \
|
||||
result = V_vsnprintfRet( (szBuf), (nBufSize)-1, (*(ppszFormat)), arg_ptr, &bTruncated ); \
|
||||
va_end(arg_ptr); \
|
||||
\
|
||||
(szBuf)[(nBufSize)-1] = 0; \
|
||||
if ( bTruncated && !(bQuietTruncation) && scAsserted < 5 ) \
|
||||
{ \
|
||||
Assert( !bTruncated ); \
|
||||
scAsserted++; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Purpose: String formatter with specified size
|
||||
//
|
||||
|
||||
template <int SIZE_BUF>
|
||||
class CFmtStrN
|
||||
{
|
||||
public:
|
||||
CFmtStrN()
|
||||
{
|
||||
InitQuietTruncation();
|
||||
m_szBuf[0] = 0;
|
||||
m_nLength = 0;
|
||||
}
|
||||
|
||||
// Standard C formatting
|
||||
CFmtStrN(const char *pszFormat, ...) FMTFUNCTION( 2, 3 )
|
||||
{
|
||||
InitQuietTruncation();
|
||||
FmtStrVSNPrintf(m_szBuf, SIZE_BUF, m_bQuietTruncation, &pszFormat);
|
||||
FixLength();
|
||||
}
|
||||
|
||||
// Use this for pass-through formatting
|
||||
CFmtStrN(const char ** ppszFormat, ...)
|
||||
{
|
||||
InitQuietTruncation();
|
||||
FmtStrVSNPrintf(m_szBuf, SIZE_BUF, m_bQuietTruncation, ppszFormat);
|
||||
FixLength();
|
||||
}
|
||||
|
||||
// Explicit reformat
|
||||
const char *sprintf(const char *pszFormat, ...) FMTFUNCTION( 2, 3 )
|
||||
{
|
||||
InitQuietTruncation();
|
||||
FmtStrVSNPrintf(m_szBuf, SIZE_BUF, m_bQuietTruncation, &pszFormat);
|
||||
FixLength();
|
||||
return m_szBuf;
|
||||
}
|
||||
|
||||
// Use this for pass-through formatting
|
||||
void VSprintf(const char **ppszFormat, ...)
|
||||
{
|
||||
InitQuietTruncation();
|
||||
FmtStrVSNPrintf(m_szBuf, SIZE_BUF, m_bQuietTruncation, ppszFormat);
|
||||
FixLength();
|
||||
}
|
||||
|
||||
// Use for access
|
||||
operator const char *() const { return m_szBuf; }
|
||||
char *Access() { return m_szBuf; }
|
||||
CFmtStrN<SIZE_BUF> & operator=( const char *pchValue ) { sprintf( pchValue ); return *this; }
|
||||
CFmtStrN<SIZE_BUF> & operator+=( const char *pchValue ) { Append( pchValue ); return *this; }
|
||||
int Length() const { return m_nLength; }
|
||||
|
||||
void Clear() { m_szBuf[0] = 0; m_nLength = 0; }
|
||||
|
||||
void AppendFormat( const char *pchFormat, ... ) { char *pchEnd = m_szBuf + m_nLength; FmtStrVSNPrintf( pchEnd, SIZE_BUF - m_nLength, m_bQuietTruncation, &pchFormat ); FixLength(); }
|
||||
void AppendFormatV( const char *pchFormat, va_list args );
|
||||
void Append( const char *pchValue ) { AppendFormat( pchValue ); }
|
||||
|
||||
void AppendIndent( uint32 unCount, char chIndent = '\t' );
|
||||
protected:
|
||||
virtual void InitQuietTruncation()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
m_bQuietTruncation = false;
|
||||
#else
|
||||
m_bQuietTruncation = true; // Force quiet for release builds
|
||||
#endif
|
||||
}
|
||||
|
||||
bool m_bQuietTruncation;
|
||||
|
||||
void FixLength() { m_nLength = V_strlen(m_szBuf); }
|
||||
private:
|
||||
char m_szBuf[SIZE_BUF];
|
||||
int m_nLength;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// Version which will not assert if strings are truncated
|
||||
|
||||
template <int SIZE_BUF>
|
||||
class CFmtStrQuietTruncationN : public CFmtStrN<SIZE_BUF>
|
||||
{
|
||||
protected:
|
||||
virtual void InitQuietTruncation() { this->m_bQuietTruncation = true; }
|
||||
};
|
||||
|
||||
|
||||
template< int SIZE_BUF >
|
||||
void CFmtStrN<SIZE_BUF>::AppendIndent( uint32 unCount, char chIndent )
|
||||
{
|
||||
Assert( Length() + unCount < SIZE_BUF );
|
||||
if( Length() + unCount >= SIZE_BUF )
|
||||
unCount = SIZE_BUF - (1+Length());
|
||||
for ( uint32 x = 0; x < unCount; x++ )
|
||||
{
|
||||
m_szBuf[ m_nLength++ ] = chIndent;
|
||||
}
|
||||
m_szBuf[ m_nLength ] = '\0';
|
||||
}
|
||||
|
||||
template< int SIZE_BUF >
|
||||
void CFmtStrN<SIZE_BUF>::AppendFormatV( const char *pchFormat, va_list args )
|
||||
{
|
||||
int cubPrinted = V_vsnprintf( m_szBuf+Length(), SIZE_BUF - Length(), pchFormat, args );
|
||||
m_nLength += cubPrinted;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Purpose: Default-sized string formatter
|
||||
//
|
||||
|
||||
#define FMTSTR_STD_LEN 1024
|
||||
|
||||
typedef CFmtStrN<FMTSTR_STD_LEN> CFmtStr;
|
||||
typedef CFmtStrQuietTruncationN<FMTSTR_STD_LEN> CFmtStrQuietTruncation;
|
||||
typedef CFmtStrN<1024> CFmtStr1024;
|
||||
typedef CFmtStrN<8192> CFmtStrMax;
|
||||
|
||||
//=============================================================================
|
||||
|
||||
const int k_cchFormattedDate = 64;
|
||||
const int k_cchFormattedTime = 32;
|
||||
bool BGetLocalFormattedTime( time_t timeVal, char *pchDate, int cubDate, char *pchTime, int cubTime );
|
||||
|
||||
#endif // FMTSTR_H
|
||||
Vendored
+920
@@ -0,0 +1,920 @@
|
||||
//========== Copyright © 2006, Valve Corporation, All rights reserved. ========
|
||||
//
|
||||
// Purpose: Implements a generic infrastucture for functors combining
|
||||
// a number of techniques to provide transparent parameter type
|
||||
// deduction and packaging. Supports both member and non-member functions.
|
||||
//
|
||||
// See also: http://en.wikipedia.org/wiki/Function_object
|
||||
//
|
||||
// Note that getting into the guts of this file is not for the
|
||||
// feint of heart. The core concept here is that the compiler can
|
||||
// figure out all the parameter types.
|
||||
//
|
||||
// E.g.:
|
||||
//
|
||||
// struct CMyClass
|
||||
// {
|
||||
// void foo( int i) {}
|
||||
// };
|
||||
//
|
||||
// int bar(int i) { return i; }
|
||||
//
|
||||
// CMyClass myInstance;
|
||||
//
|
||||
// CFunctor *pFunctor = CreateFunctor( &myInstance, CMyClass::foo, 8675 );
|
||||
// CFunctor *pFunctor2 = CreateFunctor( &bar, 309 );
|
||||
//
|
||||
// void CallEm()
|
||||
// {
|
||||
// (*pFunctor)();
|
||||
// (*pFunctor2)();
|
||||
// }
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef FUNCTORS_H
|
||||
#define FUNCTORS_H
|
||||
|
||||
#if defined( _WIN32 )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "tier0/platform.h"
|
||||
#include "tier1/refcount.h"
|
||||
#include "tier1/utlenvelope.h"
|
||||
#include <typeinfo>
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Macros used as basis for template generation. Just ignore the man behind the
|
||||
// curtain
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_0
|
||||
#define FUNC_TEMPLATE_ARG_PARAMS_0
|
||||
#define FUNC_BASE_TEMPLATE_ARG_PARAMS_0
|
||||
#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_0
|
||||
#define FUNC_ARG_MEMBERS_0
|
||||
#define FUNC_ARG_FORMAL_PARAMS_0
|
||||
#define FUNC_PROXY_ARG_FORMAL_PARAMS_0
|
||||
#define FUNC_CALL_ARGS_INIT_0
|
||||
#define FUNC_SOLO_CALL_ARGS_INIT_0
|
||||
#define FUNC_CALL_MEMBER_ARGS_0
|
||||
#define FUNC_CALL_ARGS_0
|
||||
#define FUNC_CALL_DATA_ARGS_0( _var )
|
||||
#define FUNC_FUNCTOR_CALL_ARGS_0
|
||||
#define FUNC_TEMPLATE_FUNC_PARAMS_0
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_0
|
||||
#define FUNC_VALIDATION_STRING_0 V_snprintf( pString, nBufLen, "method( void )" );
|
||||
#define FUNC_SEPARATOR_0
|
||||
|
||||
#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_1 typename ARG_TYPE_1
|
||||
#define FUNC_TEMPLATE_ARG_PARAMS_1 , typename ARG_TYPE_1
|
||||
#define FUNC_BASE_TEMPLATE_ARG_PARAMS_1 , ARG_TYPE_1
|
||||
#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_1 ARG_TYPE_1
|
||||
#define FUNC_ARG_MEMBERS_1 ARG_TYPE_1 m_arg1
|
||||
#define FUNC_ARG_FORMAL_PARAMS_1 , const ARG_TYPE_1 &arg1
|
||||
#define FUNC_PROXY_ARG_FORMAL_PARAMS_1 const ARG_TYPE_1 &arg1
|
||||
#define FUNC_CALL_ARGS_INIT_1 , m_arg1( arg1 )
|
||||
#define FUNC_SOLO_CALL_ARGS_INIT_1 : m_arg1( arg1 )
|
||||
#define FUNC_CALL_MEMBER_ARGS_1 m_arg1
|
||||
#define FUNC_CALL_ARGS_1 arg1
|
||||
#define FUNC_CALL_DATA_ARGS_1( _var ) _var->m_arg1
|
||||
#define FUNC_FUNCTOR_CALL_ARGS_1 , arg1
|
||||
#define FUNC_TEMPLATE_FUNC_PARAMS_1 , typename FUNC_ARG_TYPE_1
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_1 FUNC_ARG_TYPE_1
|
||||
#define FUNC_VALIDATION_STRING_1 V_snprintf( pString, nBufLen, "method( %s )", typeid( ARG_TYPE_1 ).name() );
|
||||
#define FUNC_SEPARATOR_1 ,
|
||||
|
||||
#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_2 typename ARG_TYPE_1, typename ARG_TYPE_2
|
||||
#define FUNC_TEMPLATE_ARG_PARAMS_2 , typename ARG_TYPE_1, typename ARG_TYPE_2
|
||||
#define FUNC_BASE_TEMPLATE_ARG_PARAMS_2 , ARG_TYPE_1, ARG_TYPE_2
|
||||
#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_2 ARG_TYPE_1, ARG_TYPE_2
|
||||
#define FUNC_ARG_MEMBERS_2 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2
|
||||
#define FUNC_ARG_FORMAL_PARAMS_2 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2
|
||||
#define FUNC_PROXY_ARG_FORMAL_PARAMS_2 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2
|
||||
#define FUNC_CALL_ARGS_INIT_2 , m_arg1( arg1 ), m_arg2( arg2 )
|
||||
#define FUNC_SOLO_CALL_ARGS_INIT_2 : m_arg1( arg1 ), m_arg2( arg2 )
|
||||
#define FUNC_CALL_MEMBER_ARGS_2 m_arg1, m_arg2
|
||||
#define FUNC_CALL_ARGS_2 arg1, arg2
|
||||
#define FUNC_CALL_DATA_ARGS_2( _var ) _var->m_arg1, _var->m_arg2
|
||||
#define FUNC_FUNCTOR_CALL_ARGS_2 , arg1, arg2
|
||||
#define FUNC_TEMPLATE_FUNC_PARAMS_2 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_2 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2
|
||||
#define FUNC_VALIDATION_STRING_2 V_snprintf( pString, nBufLen, "method( %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name() );
|
||||
#define FUNC_SEPARATOR_2 ,
|
||||
|
||||
#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_3 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3
|
||||
#define FUNC_TEMPLATE_ARG_PARAMS_3 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3
|
||||
#define FUNC_BASE_TEMPLATE_ARG_PARAMS_3 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3
|
||||
#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_3 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3
|
||||
#define FUNC_ARG_MEMBERS_3 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3
|
||||
#define FUNC_ARG_FORMAL_PARAMS_3 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3
|
||||
#define FUNC_PROXY_ARG_FORMAL_PARAMS_3 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3
|
||||
#define FUNC_CALL_ARGS_INIT_3 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 )
|
||||
#define FUNC_SOLO_CALL_ARGS_INIT_3 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 )
|
||||
#define FUNC_CALL_MEMBER_ARGS_3 m_arg1, m_arg2, m_arg3
|
||||
#define FUNC_CALL_ARGS_3 arg1, arg2, arg3
|
||||
#define FUNC_CALL_DATA_ARGS_3( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3
|
||||
#define FUNC_FUNCTOR_CALL_ARGS_3 , arg1, arg2, arg3
|
||||
#define FUNC_TEMPLATE_FUNC_PARAMS_3 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_3 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3
|
||||
#define FUNC_VALIDATION_STRING_3 V_snprintf( pString, nBufLen, "method( %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name() );
|
||||
#define FUNC_SEPARATOR_3 ,
|
||||
|
||||
#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_4 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4
|
||||
#define FUNC_TEMPLATE_ARG_PARAMS_4 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4
|
||||
#define FUNC_BASE_TEMPLATE_ARG_PARAMS_4 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4
|
||||
#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_4 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4
|
||||
#define FUNC_ARG_MEMBERS_4 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4
|
||||
#define FUNC_ARG_FORMAL_PARAMS_4 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4
|
||||
#define FUNC_PROXY_ARG_FORMAL_PARAMS_4 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4
|
||||
#define FUNC_CALL_ARGS_INIT_4 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 )
|
||||
#define FUNC_SOLO_CALL_ARGS_INIT_4 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 )
|
||||
#define FUNC_CALL_MEMBER_ARGS_4 m_arg1, m_arg2, m_arg3, m_arg4
|
||||
#define FUNC_CALL_ARGS_4 arg1, arg2, arg3, arg4
|
||||
#define FUNC_CALL_DATA_ARGS_4( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4
|
||||
#define FUNC_FUNCTOR_CALL_ARGS_4 , arg1, arg2, arg3, arg4
|
||||
#define FUNC_TEMPLATE_FUNC_PARAMS_4 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_4 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4
|
||||
#define FUNC_VALIDATION_STRING_4 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name() );
|
||||
#define FUNC_SEPARATOR_4 ,
|
||||
|
||||
#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_5 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5
|
||||
#define FUNC_TEMPLATE_ARG_PARAMS_5 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5
|
||||
#define FUNC_BASE_TEMPLATE_ARG_PARAMS_5 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5
|
||||
#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_5 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5
|
||||
#define FUNC_ARG_MEMBERS_5 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5
|
||||
#define FUNC_ARG_FORMAL_PARAMS_5 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5
|
||||
#define FUNC_PROXY_ARG_FORMAL_PARAMS_5 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5
|
||||
#define FUNC_CALL_ARGS_INIT_5 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 )
|
||||
#define FUNC_SOLO_CALL_ARGS_INIT_5 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 )
|
||||
#define FUNC_CALL_MEMBER_ARGS_5 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5
|
||||
#define FUNC_CALL_ARGS_5 arg1, arg2, arg3, arg4, arg5
|
||||
#define FUNC_CALL_DATA_ARGS_5( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4, _var->m_arg5
|
||||
#define FUNC_FUNCTOR_CALL_ARGS_5 , arg1, arg2, arg3, arg4, arg5
|
||||
#define FUNC_TEMPLATE_FUNC_PARAMS_5 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_5 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5
|
||||
#define FUNC_VALIDATION_STRING_5 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name(), typeid( ARG_TYPE_5 ).name() );
|
||||
#define FUNC_SEPARATOR_5 ,
|
||||
|
||||
|
||||
#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_6 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6
|
||||
#define FUNC_TEMPLATE_ARG_PARAMS_6 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6
|
||||
#define FUNC_BASE_TEMPLATE_ARG_PARAMS_6 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6
|
||||
#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_6 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6
|
||||
#define FUNC_ARG_MEMBERS_6 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6
|
||||
#define FUNC_ARG_FORMAL_PARAMS_6 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6
|
||||
#define FUNC_PROXY_ARG_FORMAL_PARAMS_6 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6
|
||||
#define FUNC_CALL_ARGS_INIT_6 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 )
|
||||
#define FUNC_SOLO_CALL_ARGS_INIT_6 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 )
|
||||
#define FUNC_CALL_MEMBER_ARGS_6 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6
|
||||
#define FUNC_CALL_ARGS_6 arg1, arg2, arg3, arg4, arg5, arg6
|
||||
#define FUNC_CALL_DATA_ARGS_6( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4, _var->m_arg5, _var->m_arg6
|
||||
#define FUNC_FUNCTOR_CALL_ARGS_6 , arg1, arg2, arg3, arg4, arg5, arg6
|
||||
#define FUNC_TEMPLATE_FUNC_PARAMS_6 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_6 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6
|
||||
#define FUNC_VALIDATION_STRING_6 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name(), typeid( ARG_TYPE_5 ).name(), typeid( ARG_TYPE_6 ).name() );
|
||||
#define FUNC_SEPARATOR_6 ,
|
||||
|
||||
#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_7 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7
|
||||
#define FUNC_TEMPLATE_ARG_PARAMS_7 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7
|
||||
#define FUNC_BASE_TEMPLATE_ARG_PARAMS_7 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7
|
||||
#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_7 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7
|
||||
#define FUNC_ARG_MEMBERS_7 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7;
|
||||
#define FUNC_ARG_FORMAL_PARAMS_7 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7
|
||||
#define FUNC_PROXY_ARG_FORMAL_PARAMS_7 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7
|
||||
#define FUNC_CALL_ARGS_INIT_7 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 )
|
||||
#define FUNC_SOLO_CALL_ARGS_INIT_7 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 )
|
||||
#define FUNC_CALL_MEMBER_ARGS_7 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7
|
||||
#define FUNC_CALL_ARGS_7 arg1, arg2, arg3, arg4, arg5, arg6, arg7
|
||||
#define FUNC_CALL_DATA_ARGS_7( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4, _var->m_arg5, _var->m_arg6, _var->m_arg7
|
||||
#define FUNC_FUNCTOR_CALL_ARGS_7 , arg1, arg2, arg3, arg4, arg5, arg6, arg7
|
||||
#define FUNC_TEMPLATE_FUNC_PARAMS_7 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_7 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7
|
||||
#define FUNC_VALIDATION_STRING_7 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name(), typeid( ARG_TYPE_5 ).name(), typeid( ARG_TYPE_6 ).name(), typeid( ARG_TYPE_7 ).name() );
|
||||
#define FUNC_SEPARATOR_7 ,
|
||||
|
||||
#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_8 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8
|
||||
#define FUNC_TEMPLATE_ARG_PARAMS_8 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8
|
||||
#define FUNC_BASE_TEMPLATE_ARG_PARAMS_8 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8
|
||||
#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_8 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8
|
||||
#define FUNC_ARG_MEMBERS_8 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; ARG_TYPE_8 m_arg8;
|
||||
#define FUNC_ARG_FORMAL_PARAMS_8 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8
|
||||
#define FUNC_PROXY_ARG_FORMAL_PARAMS_8 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8
|
||||
#define FUNC_CALL_ARGS_INIT_8 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 )
|
||||
#define FUNC_SOLO_CALL_ARGS_INIT_8 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 )
|
||||
#define FUNC_CALL_MEMBER_ARGS_8 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8
|
||||
#define FUNC_CALL_ARGS_8 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8
|
||||
#define FUNC_CALL_DATA_ARGS_8( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4, _var->m_arg5, _var->m_arg6, _var->m_arg7, _var->m_arg8
|
||||
#define FUNC_FUNCTOR_CALL_ARGS_8 , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8
|
||||
#define FUNC_TEMPLATE_FUNC_PARAMS_8 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7, typename FUNC_ARG_TYPE_8
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_8 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7, FUNC_ARG_TYPE_8
|
||||
#define FUNC_VALIDATION_STRING_8 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s, %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name(), typeid( ARG_TYPE_5 ).name(), typeid( ARG_TYPE_6 ).name(), typeid( ARG_TYPE_7 ).name(), typeid( ARG_TYPE_8 ).name() );
|
||||
#define FUNC_SEPARATOR_8 ,
|
||||
|
||||
#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_9 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9
|
||||
#define FUNC_TEMPLATE_ARG_PARAMS_9 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9
|
||||
#define FUNC_BASE_TEMPLATE_ARG_PARAMS_9 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9
|
||||
#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_9 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9
|
||||
#define FUNC_ARG_MEMBERS_9 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; ARG_TYPE_8 m_arg8; ARG_TYPE_9 m_arg9;
|
||||
#define FUNC_ARG_FORMAL_PARAMS_9 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9
|
||||
#define FUNC_PROXY_ARG_FORMAL_PARAMS_9 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9
|
||||
#define FUNC_CALL_ARGS_INIT_9 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 )
|
||||
#define FUNC_SOLO_CALL_ARGS_INIT_9 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 )
|
||||
#define FUNC_CALL_MEMBER_ARGS_9 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9
|
||||
#define FUNC_CALL_ARGS_9 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9
|
||||
#define FUNC_CALL_DATA_ARGS_9( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4, _var->m_arg5, _var->m_arg6, _var->m_arg7, _var->m_arg8, _var->m_arg9
|
||||
#define FUNC_FUNCTOR_CALL_ARGS_9 , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9
|
||||
#define FUNC_TEMPLATE_FUNC_PARAMS_9 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7, typename FUNC_ARG_TYPE_8, typename FUNC_ARG_TYPE_9
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_9 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7, FUNC_ARG_TYPE_8, FUNC_ARG_TYPE_9
|
||||
#define FUNC_VALIDATION_STRING_9 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s, %s, %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name(), typeid( ARG_TYPE_5 ).name(), typeid( ARG_TYPE_6 ).name(), typeid( ARG_TYPE_7 ).name(), typeid( ARG_TYPE_8 ).name(), typeid( ARG_TYPE_9 ).name() );
|
||||
#define FUNC_SEPARATOR_9 ,
|
||||
|
||||
#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_10 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10
|
||||
#define FUNC_TEMPLATE_ARG_PARAMS_10 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10
|
||||
#define FUNC_BASE_TEMPLATE_ARG_PARAMS_10 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10
|
||||
#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_10 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10
|
||||
#define FUNC_ARG_MEMBERS_10 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; ARG_TYPE_8 m_arg8; ARG_TYPE_9 m_arg9; ARG_TYPE_10 m_arg10;
|
||||
#define FUNC_ARG_FORMAL_PARAMS_10 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10
|
||||
#define FUNC_PROXY_ARG_FORMAL_PARAMS_10 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10
|
||||
#define FUNC_CALL_ARGS_INIT_10 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 )
|
||||
#define FUNC_SOLO_CALL_ARGS_INIT_10 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 )
|
||||
#define FUNC_CALL_MEMBER_ARGS_10 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10
|
||||
#define FUNC_CALL_ARGS_10 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10
|
||||
#define FUNC_CALL_DATA_ARGS_10( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4, _var->m_arg5, _var->m_arg6, _var->m_arg7, _var->m_arg8, _var->m_arg9, _var->m_arg10
|
||||
#define FUNC_FUNCTOR_CALL_ARGS_10 , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10
|
||||
#define FUNC_TEMPLATE_FUNC_PARAMS_10 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7, typename FUNC_ARG_TYPE_8, typename FUNC_ARG_TYPE_9, typename FUNC_ARG_TYPE_10
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_10 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7, FUNC_ARG_TYPE_8, FUNC_ARG_TYPE_9, FUNC_ARG_TYPE_10
|
||||
#define FUNC_VALIDATION_STRING_10 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s, %s, %s, %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name(), typeid( ARG_TYPE_5 ).name(), typeid( ARG_TYPE_6 ).name(), typeid( ARG_TYPE_7 ).name(), typeid( ARG_TYPE_8 ).name(), typeid( ARG_TYPE_9 ).name(), typeid( ARG_TYPE_10 ).name() );
|
||||
#define FUNC_SEPARATOR_10 ,
|
||||
|
||||
#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_11 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10, typename ARG_TYPE_11
|
||||
#define FUNC_TEMPLATE_ARG_PARAMS_11 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10, typename ARG_TYPE_11
|
||||
#define FUNC_BASE_TEMPLATE_ARG_PARAMS_11 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10, ARG_TYPE_11
|
||||
#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_11 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10, ARG_TYPE_11
|
||||
#define FUNC_ARG_MEMBERS_11 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; ARG_TYPE_8 m_arg8; ARG_TYPE_9 m_arg9; ARG_TYPE_10 m_arg10; ARG_TYPE_11 m_arg11
|
||||
#define FUNC_ARG_FORMAL_PARAMS_11 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11
|
||||
#define FUNC_PROXY_ARG_FORMAL_PARAMS_11 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11
|
||||
#define FUNC_CALL_ARGS_INIT_11 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 ), m_arg11( arg11 )
|
||||
#define FUNC_SOLO_CALL_ARGS_INIT_11 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 ), m_arg11( arg11 )
|
||||
#define FUNC_CALL_MEMBER_ARGS_11 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11
|
||||
#define FUNC_CALL_ARGS_11 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11
|
||||
#define FUNC_CALL_DATA_ARGS_11( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4, _var->m_arg5, _var->m_arg6, _var->m_arg7, _var->m_arg8, _var->m_arg9, _var->m_arg10, _var->m_arg11
|
||||
#define FUNC_FUNCTOR_CALL_ARGS_11 , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11
|
||||
#define FUNC_TEMPLATE_FUNC_PARAMS_11 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7, typename FUNC_ARG_TYPE_8, typename FUNC_ARG_TYPE_9, typename FUNC_ARG_TYPE_10, typename FUNC_ARG_TYPE_11
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_11 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7, FUNC_ARG_TYPE_8, FUNC_ARG_TYPE_9, FUNC_ARG_TYPE_10, FUNC_ARG_TYPE_11
|
||||
#define FUNC_VALIDATION_STRING_11 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name(), typeid( ARG_TYPE_5 ).name(), typeid( ARG_TYPE_6 ).name(), typeid( ARG_TYPE_7 ).name(), typeid( ARG_TYPE_8 ).name(), typeid( ARG_TYPE_9 ).name(), typeid( ARG_TYPE_10 ).name(), typeid( ARG_TYPE_11 ).name() );
|
||||
#define FUNC_SEPARATOR_11 ,
|
||||
|
||||
#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_12 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10, typename ARG_TYPE_11, typename ARG_TYPE_12
|
||||
#define FUNC_TEMPLATE_ARG_PARAMS_12 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10, typename ARG_TYPE_11, typename ARG_TYPE_12
|
||||
#define FUNC_BASE_TEMPLATE_ARG_PARAMS_12 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10, ARG_TYPE_11, ARG_TYPE_12
|
||||
#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_12 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10, ARG_TYPE_11, ARG_TYPE_12
|
||||
#define FUNC_ARG_MEMBERS_12 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; ARG_TYPE_8 m_arg8; ARG_TYPE_9 m_arg9; ARG_TYPE_10 m_arg10; ARG_TYPE_11 m_arg11; ARG_TYPE_12 m_arg12
|
||||
#define FUNC_ARG_FORMAL_PARAMS_12 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11, const ARG_TYPE_12 &arg12
|
||||
#define FUNC_PROXY_ARG_FORMAL_PARAMS_12 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11, const ARG_TYPE_12 &arg12
|
||||
#define FUNC_CALL_ARGS_INIT_12 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 ), m_arg11( arg11 ), m_arg12( arg12 )
|
||||
#define FUNC_SOLO_CALL_ARGS_INIT_12 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 ), m_arg11( arg11 ), m_arg12( arg12 )
|
||||
#define FUNC_CALL_MEMBER_ARGS_12 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12
|
||||
#define FUNC_CALL_ARGS_12 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12
|
||||
#define FUNC_CALL_DATA_ARGS_12( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4, _var->m_arg5, _var->m_arg6, _var->m_arg7, _var->m_arg8, _var->m_arg9, _var->m_arg10, _var->m_arg11, _var->m_arg12
|
||||
#define FUNC_FUNCTOR_CALL_ARGS_12 , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12
|
||||
#define FUNC_TEMPLATE_FUNC_PARAMS_12 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7, typename FUNC_ARG_TYPE_8, typename FUNC_ARG_TYPE_9, typename FUNC_ARG_TYPE_10, typename FUNC_ARG_TYPE_11, typename FUNC_ARG_TYPE_12
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_12 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7, FUNC_ARG_TYPE_8, FUNC_ARG_TYPE_9, FUNC_ARG_TYPE_10, FUNC_ARG_TYPE_11, FUNC_ARG_TYPE_12
|
||||
#define FUNC_VALIDATION_STRING_12 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name(), typeid( ARG_TYPE_5 ).name(), typeid( ARG_TYPE_6 ).name(), typeid( ARG_TYPE_7 ).name(), typeid( ARG_TYPE_8 ).name(), typeid( ARG_TYPE_9 ).name(), typeid( ARG_TYPE_10 ).name(), typeid( ARG_TYPE_11 ).name(), typeid( ARG_TYPE_12 ).name() );
|
||||
#define FUNC_SEPARATOR_12 ,
|
||||
|
||||
#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_13 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10, typename ARG_TYPE_11, typename ARG_TYPE_12, typename ARG_TYPE_13
|
||||
#define FUNC_TEMPLATE_ARG_PARAMS_13 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10, typename ARG_TYPE_11, typename ARG_TYPE_12, typename ARG_TYPE_13
|
||||
#define FUNC_BASE_TEMPLATE_ARG_PARAMS_13 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10, ARG_TYPE_11, ARG_TYPE_12, ARG_TYPE_13
|
||||
#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_13 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10, ARG_TYPE_11, ARG_TYPE_12, ARG_TYPE_13
|
||||
#define FUNC_ARG_MEMBERS_13 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; ARG_TYPE_8 m_arg8; ARG_TYPE_9 m_arg9; ARG_TYPE_10 m_arg10; ARG_TYPE_11 m_arg11; ARG_TYPE_12 m_arg12; ARG_TYPE_13 m_arg13
|
||||
#define FUNC_ARG_FORMAL_PARAMS_13 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11, const ARG_TYPE_12 &arg12, const ARG_TYPE_13 &arg13
|
||||
#define FUNC_PROXY_ARG_FORMAL_PARAMS_13 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11, const ARG_TYPE_12 &arg12, const ARG_TYPE_13 &arg13
|
||||
#define FUNC_CALL_ARGS_INIT_13 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 ), m_arg11( arg11 ), m_arg12( arg12 ), m_arg13( arg13 )
|
||||
#define FUNC_SOLO_CALL_ARGS_INIT_13 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 ), m_arg11( arg11 ), m_arg12( arg12 ), m_arg13( arg13 )
|
||||
#define FUNC_CALL_MEMBER_ARGS_13 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12, m_arg13
|
||||
#define FUNC_CALL_ARGS_13 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13
|
||||
#define FUNC_CALL_DATA_ARGS_13( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4, _var->m_arg5, _var->m_arg6, _var->m_arg7, _var->m_arg8, _var->m_arg9, _var->m_arg10, _var->m_arg11, _var->m_arg12, _var->m_arg13
|
||||
#define FUNC_FUNCTOR_CALL_ARGS_13 , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13
|
||||
#define FUNC_TEMPLATE_FUNC_PARAMS_13 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7, typename FUNC_ARG_TYPE_8, typename FUNC_ARG_TYPE_9, typename FUNC_ARG_TYPE_10, typename FUNC_ARG_TYPE_11, typename FUNC_ARG_TYPE_12, typename FUNC_ARG_TYPE_13
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_13 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7, FUNC_ARG_TYPE_8, FUNC_ARG_TYPE_9, FUNC_ARG_TYPE_10, FUNC_ARG_TYPE_11, FUNC_ARG_TYPE_12, FUNC_ARG_TYPE_13
|
||||
#define FUNC_VALIDATION_STRING_13 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name(), typeid( ARG_TYPE_5 ).name(), typeid( ARG_TYPE_6 ).name(), typeid( ARG_TYPE_7 ).name(), typeid( ARG_TYPE_8 ).name(), typeid( ARG_TYPE_9 ).name(), typeid( ARG_TYPE_10 ).name(), typeid( ARG_TYPE_11 ).name(), typeid( ARG_TYPE_12 ).name(), typeid( ARG_TYPE_13 ).name() );
|
||||
#define FUNC_SEPARATOR_13 ,
|
||||
|
||||
#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_14 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10, typename ARG_TYPE_11, typename ARG_TYPE_12, typename ARG_TYPE_13, typename ARG_TYPE_14
|
||||
#define FUNC_TEMPLATE_ARG_PARAMS_14 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10, typename ARG_TYPE_11, typename ARG_TYPE_12, typename ARG_TYPE_13, typename ARG_TYPE_14
|
||||
#define FUNC_BASE_TEMPLATE_ARG_PARAMS_14 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10, ARG_TYPE_11, ARG_TYPE_12, ARG_TYPE_13, ARG_TYPE_14
|
||||
#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_14 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10, ARG_TYPE_11, ARG_TYPE_12, ARG_TYPE_13, ARG_TYPE_14
|
||||
#define FUNC_ARG_MEMBERS_14 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; ARG_TYPE_8 m_arg8; ARG_TYPE_9 m_arg9; ARG_TYPE_10 m_arg10; ARG_TYPE_11 m_arg11; ARG_TYPE_12 m_arg12; ARG_TYPE_13 m_arg13; ARG_TYPE_14 m_arg14
|
||||
#define FUNC_ARG_FORMAL_PARAMS_14 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11, const ARG_TYPE_12 &arg12, const ARG_TYPE_13 &arg13, const ARG_TYPE_14 &arg14
|
||||
#define FUNC_PROXY_ARG_FORMAL_PARAMS_14 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11, const ARG_TYPE_12 &arg12, const ARG_TYPE_13 &arg13, const ARG_TYPE_14 &arg14
|
||||
#define FUNC_CALL_ARGS_INIT_14 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 ), m_arg11( arg11 ), m_arg12( arg12 ), m_arg13( arg13 ), m_arg14( arg14 )
|
||||
#define FUNC_SOLO_CALL_ARGS_INIT_14 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 ), m_arg11( arg11 ), m_arg12( arg12 ), m_arg13( arg13 ), m_arg14( arg14 )
|
||||
#define FUNC_CALL_MEMBER_ARGS_14 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12, m_arg13, m_arg14
|
||||
#define FUNC_CALL_ARGS_14 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14
|
||||
#define FUNC_CALL_DATA_ARGS_14( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4, _var->m_arg5, _var->m_arg6, _var->m_arg7, _var->m_arg8, _var->m_arg9, _var->m_arg10, _var->m_arg11, _var->m_arg12, _var->m_arg13, _var->m_arg14
|
||||
#define FUNC_FUNCTOR_CALL_ARGS_14 , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14
|
||||
#define FUNC_TEMPLATE_FUNC_PARAMS_14 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7, typename FUNC_ARG_TYPE_8, typename FUNC_ARG_TYPE_9, typename FUNC_ARG_TYPE_10, typename FUNC_ARG_TYPE_11, typename FUNC_ARG_TYPE_12, typename FUNC_ARG_TYPE_13, typename FUNC_ARG_TYPE_14
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_14 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7, FUNC_ARG_TYPE_8, FUNC_ARG_TYPE_9, FUNC_ARG_TYPE_10, FUNC_ARG_TYPE_11, FUNC_ARG_TYPE_12, FUNC_ARG_TYPE_13, FUNC_ARG_TYPE_14
|
||||
#define FUNC_VALIDATION_STRING_14 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name(), typeid( ARG_TYPE_5 ).name(), typeid( ARG_TYPE_6 ).name(), typeid( ARG_TYPE_7 ).name(), typeid( ARG_TYPE_8 ).name(), typeid( ARG_TYPE_9 ).name(), typeid( ARG_TYPE_10 ).name(), typeid( ARG_TYPE_11 ).name(), typeid( ARG_TYPE_12 ).name(), typeid( ARG_TYPE_13 ).name(), typeid( ARG_TYPE_14 ).name() );
|
||||
#define FUNC_SEPARATOR_14 ,
|
||||
|
||||
#define FUNC_GENERATE_ALL_BUT0( INNERMACRONAME ) \
|
||||
INNERMACRONAME(1); \
|
||||
INNERMACRONAME(2); \
|
||||
INNERMACRONAME(3); \
|
||||
INNERMACRONAME(4); \
|
||||
INNERMACRONAME(5); \
|
||||
INNERMACRONAME(6); \
|
||||
INNERMACRONAME(7); \
|
||||
INNERMACRONAME(8); \
|
||||
INNERMACRONAME(9); \
|
||||
INNERMACRONAME(10);\
|
||||
INNERMACRONAME(11);\
|
||||
INNERMACRONAME(12);\
|
||||
INNERMACRONAME(13);\
|
||||
INNERMACRONAME(14)
|
||||
|
||||
#define FUNC_GENERATE_ALL( INNERMACRONAME ) \
|
||||
INNERMACRONAME(0); \
|
||||
FUNC_GENERATE_ALL_BUT0( INNERMACRONAME )
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Purpose: Base class of all function objects
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
abstract_class CFunctor : public IRefCounted
|
||||
{
|
||||
public:
|
||||
CFunctor()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
m_nUserID = 0;
|
||||
#endif
|
||||
}
|
||||
virtual ~CFunctor() {}
|
||||
virtual void operator()() = 0;
|
||||
|
||||
unsigned m_nUserID; // For debugging
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// NOTE: Functor data + functor callback are tied together
|
||||
// The basic idea is that someone creates the functor data. At a later point,
|
||||
// the functor data is passed to a functor callback. Validation strings
|
||||
// are compared in debug builds to ensure the data matches the callback
|
||||
//-----------------------------------------------------------------------------
|
||||
abstract_class CFunctorData : public IRefCounted
|
||||
{
|
||||
public:
|
||||
virtual void ComputeValidationString( char *pString, size_t nBufLen ) const = 0;
|
||||
};
|
||||
|
||||
abstract_class CFunctorCallback : public IRefCounted
|
||||
{
|
||||
public:
|
||||
virtual bool IsEqual( CFunctorCallback *pSrc ) const = 0;
|
||||
virtual void operator()( CFunctorData *pData ) = 0;
|
||||
virtual void ComputeValidationString( char *pString, size_t nBufLen ) const = 0;
|
||||
virtual const char *GetImplClassName() const = 0;
|
||||
virtual const void *GetTarget() const = 0;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// When calling through a functor, care needs to be taken to not pass objects that might go away.
|
||||
// Since this code determines the type to store in the functor based on the actual arguments,
|
||||
// this is achieved by changing the point of call.
|
||||
//
|
||||
// See also CUtlEnvelope
|
||||
//-----------------------------------------------------------------------------
|
||||
// convert a reference to a passable value
|
||||
template <typename T>
|
||||
inline T RefToVal(const T &item)
|
||||
{
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This class can be used to pass into a functor a proxy object for a pointer
|
||||
// to be resolved later. For example, you can execute a "call" on a resource
|
||||
// whose actual value is not known until a later time
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
class CLateBoundPtr
|
||||
{
|
||||
public:
|
||||
CLateBoundPtr( T **ppObject )
|
||||
: m_ppObject( ppObject )
|
||||
{
|
||||
}
|
||||
|
||||
T *operator->() { return *m_ppObject; }
|
||||
T &operator *() { return **m_ppObject; }
|
||||
operator T *() const { return (T*)(*m_ppObject); }
|
||||
operator void *() { return *m_ppObject; }
|
||||
|
||||
private:
|
||||
T **m_ppObject;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Purpose: Classes to define memory management policies when operating
|
||||
// on pointers to members
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
class CFuncMemPolicyNone
|
||||
{
|
||||
public:
|
||||
static void OnAcquire(void *pObject) {}
|
||||
static void OnRelease(void *pObject) {}
|
||||
};
|
||||
|
||||
template <class OBJECT_TYPE_PTR = IRefCounted *>
|
||||
class CFuncMemPolicyRefCount
|
||||
{
|
||||
public:
|
||||
static void OnAcquire(OBJECT_TYPE_PTR pObject) { pObject->AddRef(); }
|
||||
static void OnRelease(OBJECT_TYPE_PTR pObject) { pObject->Release(); }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Purpose: Function proxy is a generic facility for holding a function
|
||||
// pointer. Can be used on own, though primarily for use
|
||||
// by this file
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class OBJECT_TYPE_PTR, typename FUNCTION_TYPE, class MEM_POLICY = CFuncMemPolicyNone >
|
||||
class CMemberFuncProxyBase
|
||||
{
|
||||
public:
|
||||
bool operator==( const CMemberFuncProxyBase &src ) const
|
||||
{
|
||||
return m_pfnProxied == src.m_pfnProxied && m_pObject == src.m_pObject;
|
||||
}
|
||||
|
||||
const void *GetTarget() const
|
||||
{
|
||||
return m_pObject;
|
||||
}
|
||||
|
||||
protected:
|
||||
CMemberFuncProxyBase( OBJECT_TYPE_PTR pObject, FUNCTION_TYPE pfnProxied )
|
||||
: m_pObject( pObject ),
|
||||
m_pfnProxied( pfnProxied )
|
||||
{
|
||||
MEM_POLICY::OnAcquire(m_pObject);
|
||||
}
|
||||
|
||||
~CMemberFuncProxyBase()
|
||||
{
|
||||
MEM_POLICY::OnRelease(m_pObject);
|
||||
}
|
||||
|
||||
void Set( OBJECT_TYPE_PTR pObject, FUNCTION_TYPE pfnProxied )
|
||||
{
|
||||
m_pfnProxied = pfnProxied;
|
||||
m_pObject = pObject;
|
||||
}
|
||||
|
||||
void OnCall()
|
||||
{
|
||||
Assert( (void *)m_pObject != NULL );
|
||||
}
|
||||
|
||||
FUNCTION_TYPE m_pfnProxied;
|
||||
OBJECT_TYPE_PTR m_pObject;
|
||||
};
|
||||
|
||||
|
||||
#define DEFINE_MEMBER_FUNC_PROXY( N ) \
|
||||
template <class OBJECT_TYPE_PTR, typename FUNCTION_TYPE FUNC_TEMPLATE_ARG_PARAMS_##N, class MEM_POLICY = CFuncMemPolicyNone> \
|
||||
class CMemberFuncProxy##N : public CMemberFuncProxyBase<OBJECT_TYPE_PTR, FUNCTION_TYPE, MEM_POLICY> \
|
||||
{ \
|
||||
public: \
|
||||
CMemberFuncProxy##N( OBJECT_TYPE_PTR pObject = NULL, FUNCTION_TYPE pfnProxied = NULL ) \
|
||||
: CMemberFuncProxyBase<OBJECT_TYPE_PTR, FUNCTION_TYPE, MEM_POLICY >( pObject, pfnProxied ) \
|
||||
{ \
|
||||
} \
|
||||
\
|
||||
void operator()( FUNC_PROXY_ARG_FORMAL_PARAMS_##N ) \
|
||||
{ \
|
||||
this->OnCall(); \
|
||||
((*this->m_pObject).*this->m_pfnProxied)( FUNC_CALL_ARGS_##N ); \
|
||||
} \
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNC_PROXY );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// The actual functor implementation
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
typedef CRefCounted1<CFunctor, CRefCountServiceMT> CFunctorBase;
|
||||
|
||||
#define DEFINE_FUNCTOR_TEMPLATE(N) \
|
||||
template <typename FUNC_TYPE FUNC_TEMPLATE_ARG_PARAMS_##N, class FUNCTOR_BASE = CFunctorBase> \
|
||||
class CFunctor##N : public CFunctorBase \
|
||||
{ \
|
||||
public: \
|
||||
CFunctor##N( FUNC_TYPE pfnProxied FUNC_ARG_FORMAL_PARAMS_##N ) : m_pfnProxied( pfnProxied ) FUNC_CALL_ARGS_INIT_##N {} \
|
||||
void operator()() { m_pfnProxied(FUNC_CALL_MEMBER_ARGS_##N); } \
|
||||
\
|
||||
private: \
|
||||
FUNC_TYPE m_pfnProxied; \
|
||||
FUNC_ARG_MEMBERS_##N; \
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_FUNCTOR_TEMPLATE );
|
||||
|
||||
#define DEFINE_MEMBER_FUNCTOR( N ) \
|
||||
template <class OBJECT_TYPE_PTR, typename FUNCTION_TYPE FUNC_TEMPLATE_ARG_PARAMS_##N, class FUNCTOR_BASE = CFunctorBase, class MEM_POLICY = CFuncMemPolicyNone> \
|
||||
class CMemberFunctor##N : public FUNCTOR_BASE \
|
||||
{ \
|
||||
public: \
|
||||
CMemberFunctor##N( OBJECT_TYPE_PTR pObject, FUNCTION_TYPE pfnProxied FUNC_ARG_FORMAL_PARAMS_##N ) : m_Proxy( pObject, pfnProxied ) FUNC_CALL_ARGS_INIT_##N {} \
|
||||
void operator()() { m_Proxy(FUNC_CALL_MEMBER_ARGS_##N); } \
|
||||
\
|
||||
private: \
|
||||
CMemberFuncProxy##N<OBJECT_TYPE_PTR, FUNCTION_TYPE FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, MEM_POLICY> m_Proxy; \
|
||||
FUNC_ARG_MEMBERS_##N; \
|
||||
};
|
||||
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNCTOR );
|
||||
|
||||
typedef CRefCounted1<CFunctorData, CRefCountServiceMT> CFunctorDataBase;
|
||||
class CFunctorCallbackBase : public CRefCounted1<CFunctorCallback, CRefCountServiceMT>
|
||||
{
|
||||
protected:
|
||||
virtual void ValidateFunctorData( CFunctorData *pData )
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
char pDataString[1024];
|
||||
char pCallbackString[1024];
|
||||
ComputeValidationString( pCallbackString, sizeof(pCallbackString) );
|
||||
pData->ComputeValidationString( pDataString, sizeof(pDataString) );
|
||||
bool bMatch = !V_stricmp( pDataString, pCallbackString );
|
||||
if ( !bMatch )
|
||||
{
|
||||
Warning( "Functor doesn't match data!\n\tExpected:\t%s\n\tEncountered:\t%s\n",
|
||||
pCallbackString, pDataString );
|
||||
Assert( 0 );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#define DEFINE_FUNCTOR_DATA_TEMPLATE(N) \
|
||||
template < FUNC_SOLO_TEMPLATE_ARG_PARAMS_##N > \
|
||||
class CFunctorData##N : public CFunctorDataBase \
|
||||
{ \
|
||||
public: \
|
||||
CFunctorData##N( FUNC_PROXY_ARG_FORMAL_PARAMS_##N ) FUNC_SOLO_CALL_ARGS_INIT_##N {} \
|
||||
virtual void ComputeValidationString( char *pString, size_t nBufLen ) const { FUNC_VALIDATION_STRING_##N } \
|
||||
FUNC_ARG_MEMBERS_##N; \
|
||||
}
|
||||
|
||||
class CFunctorData0 : public CFunctorDataBase
|
||||
{
|
||||
public:
|
||||
CFunctorData0( ) {}
|
||||
virtual void ComputeValidationString( char *pString, size_t nBufLen ) const { FUNC_VALIDATION_STRING_0 }
|
||||
};
|
||||
|
||||
FUNC_GENERATE_ALL_BUT0( DEFINE_FUNCTOR_DATA_TEMPLATE );
|
||||
|
||||
#define DEFINE_FUNCTOR_CALLBACK_TEMPLATE(N) \
|
||||
template < FUNC_SOLO_TEMPLATE_ARG_PARAMS_##N > \
|
||||
class CFunctorCallback##N : public CFunctorCallbackBase \
|
||||
{ \
|
||||
typedef void (*Callback_t)( FUNC_PROXY_ARG_FORMAL_PARAMS_##N ); \
|
||||
public: \
|
||||
CFunctorCallback##N( Callback_t pfnProxied ) : m_pfnProxied( pfnProxied ) {} \
|
||||
void operator()( CFunctorData *pFunctorDataBase ) \
|
||||
{ \
|
||||
ValidateFunctorData( pFunctorDataBase ); \
|
||||
CFunctorData##N< FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_##N > *pFunctorData = static_cast< CFunctorData##N< FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_##N >* >( pFunctorDataBase ); \
|
||||
m_pfnProxied( FUNC_CALL_DATA_ARGS_##N(pFunctorData) ); \
|
||||
} \
|
||||
virtual bool IsEqual( CFunctorCallback *pSrc ) const { return !V_stricmp( GetImplClassName(), pSrc->GetImplClassName() ) && ( m_pfnProxied == static_cast< CFunctorCallback##N * >( pSrc )->m_pfnProxied ); } \
|
||||
virtual void ComputeValidationString( char *pString, size_t nBufLen ) const { FUNC_VALIDATION_STRING_##N } \
|
||||
virtual const char *GetImplClassName() const { return "CFunctorCallback" #N; } \
|
||||
virtual const void *GetTarget() const { return m_pfnProxied; } \
|
||||
private: \
|
||||
Callback_t m_pfnProxied; \
|
||||
}
|
||||
|
||||
class CFunctorCallback0 : public CFunctorCallbackBase
|
||||
{
|
||||
typedef void (*Callback_t)( );
|
||||
public:
|
||||
CFunctorCallback0( Callback_t pfnProxied ) : m_pfnProxied( pfnProxied ) {}
|
||||
void operator()( CFunctorData *pFunctorDataBase )
|
||||
{
|
||||
ValidateFunctorData( pFunctorDataBase );
|
||||
m_pfnProxied( );
|
||||
}
|
||||
virtual void ComputeValidationString( char *pString, size_t nBufLen ) const { FUNC_VALIDATION_STRING_0 }
|
||||
virtual bool IsEqual( CFunctorCallback *pSrc ) const
|
||||
{
|
||||
if ( V_stricmp( GetImplClassName(), pSrc->GetImplClassName() ) )
|
||||
return false;
|
||||
return m_pfnProxied == static_cast< CFunctorCallback0* >( pSrc )->m_pfnProxied;
|
||||
}
|
||||
virtual const char *GetImplClassName() const { return "CFunctorCallback0"; }
|
||||
virtual const void *GetTarget() const { return ( void * )m_pfnProxied; }
|
||||
private:
|
||||
Callback_t m_pfnProxied;
|
||||
};
|
||||
|
||||
FUNC_GENERATE_ALL_BUT0( DEFINE_FUNCTOR_CALLBACK_TEMPLATE );
|
||||
|
||||
#define DEFINE_MEMBER_FUNCTOR_CALLBACK_TEMPLATE( N ) \
|
||||
template < class FUNCTION_CLASS FUNC_TEMPLATE_ARG_PARAMS_##N, class MEM_POLICY = CFuncMemPolicyNone > \
|
||||
class CMemberFunctorCallback##N : public CFunctorCallbackBase \
|
||||
{ \
|
||||
typedef void (FUNCTION_CLASS::*MemberCallback_t)( FUNC_PROXY_ARG_FORMAL_PARAMS_##N ); \
|
||||
public: \
|
||||
CMemberFunctorCallback##N( FUNCTION_CLASS *pObject, MemberCallback_t pfnProxied ) : m_Proxy( pObject, pfnProxied ) {} \
|
||||
void operator()( CFunctorData *pFunctorDataBase ) \
|
||||
{ \
|
||||
ValidateFunctorData( pFunctorDataBase ); \
|
||||
CFunctorData##N< FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_##N > *pFunctorData = static_cast< CFunctorData##N< FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_##N >* >( pFunctorDataBase ); \
|
||||
m_Proxy( FUNC_CALL_DATA_ARGS_##N( pFunctorData ) ); \
|
||||
} \
|
||||
virtual void ComputeValidationString( char *pString, size_t nBufLen ) const { FUNC_VALIDATION_STRING_##N } \
|
||||
virtual bool IsEqual( CFunctorCallback *pSrc ) const { return !V_stricmp( GetImplClassName(), pSrc->GetImplClassName() ) && ( m_Proxy == static_cast< CMemberFunctorCallback##N* >( pSrc )->m_Proxy ); } \
|
||||
virtual const char *GetImplClassName() const { return "CMemberFunctorCallback" #N; } \
|
||||
virtual const void *GetTarget() const { return m_Proxy.GetTarget(); } \
|
||||
private: \
|
||||
CMemberFuncProxy##N< FUNCTION_CLASS *, MemberCallback_t FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, MEM_POLICY> m_Proxy; \
|
||||
}
|
||||
|
||||
template < class FUNCTION_CLASS, class MEM_POLICY = CFuncMemPolicyNone >
|
||||
class CMemberFunctorCallback0 : public CFunctorCallbackBase
|
||||
{
|
||||
typedef void (FUNCTION_CLASS::*MemberCallback_t)( );
|
||||
public:
|
||||
CMemberFunctorCallback0( FUNCTION_CLASS *pObject, MemberCallback_t pfnProxied ) : m_Proxy( pObject, pfnProxied ) {}
|
||||
void operator()( CFunctorData *pFunctorDataBase )
|
||||
{
|
||||
ValidateFunctorData( pFunctorDataBase );
|
||||
m_Proxy( );
|
||||
}
|
||||
virtual void ComputeValidationString( char *pString, size_t nBufLen ) const { FUNC_VALIDATION_STRING_0 }
|
||||
virtual bool IsEqual( CFunctorCallback *pSrc ) const
|
||||
{
|
||||
if ( V_stricmp( GetImplClassName(), pSrc->GetImplClassName() ) )
|
||||
return false;
|
||||
return m_Proxy == static_cast< CMemberFunctorCallback0 * >( pSrc )->m_Proxy;
|
||||
}
|
||||
virtual const char *GetImplClassName() const { return "CMemberFunctorCallback0"; }
|
||||
virtual const void *GetTarget() const { return m_Proxy.GetTarget(); }
|
||||
private:
|
||||
CMemberFuncProxy0< FUNCTION_CLASS *, MemberCallback_t, MEM_POLICY > m_Proxy;
|
||||
};
|
||||
|
||||
FUNC_GENERATE_ALL_BUT0( DEFINE_MEMBER_FUNCTOR_CALLBACK_TEMPLATE );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// The real magic, letting the compiler figure out all the right template parameters
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define DEFINE_NONMEMBER_FUNCTOR_FACTORY(N) \
|
||||
template <typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
|
||||
inline CFunctor *CreateFunctor(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
|
||||
{ \
|
||||
typedef FUNCTION_RETTYPE (*Func_t)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N); \
|
||||
return new CFunctor##N<Func_t FUNC_BASE_TEMPLATE_ARG_PARAMS_##N>( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_NONMEMBER_FUNCTOR_FACTORY );
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
#define DEFINE_MEMBER_FUNCTOR_FACTORY(N) \
|
||||
template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
|
||||
inline CFunctor *CreateFunctor(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
|
||||
{ \
|
||||
return new CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) FUNC_BASE_TEMPLATE_ARG_PARAMS_##N>(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNCTOR_FACTORY );
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
#define DEFINE_CONST_MEMBER_FUNCTOR_FACTORY(N) \
|
||||
template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
|
||||
inline CFunctor *CreateFunctor(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \
|
||||
{ \
|
||||
return new CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) const FUNC_BASE_TEMPLATE_ARG_PARAMS_##N>(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_FUNCTOR_FACTORY );
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
#define DEFINE_REF_COUNTING_MEMBER_FUNCTOR_FACTORY(N) \
|
||||
template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
|
||||
inline CFunctor *CreateRefCountingFunctor(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
|
||||
{ \
|
||||
return new CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CFuncMemPolicyRefCount<OBJECT_TYPE_PTR> >(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_MEMBER_FUNCTOR_FACTORY );
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
#define DEFINE_REF_COUNTING_CONST_MEMBER_FUNCTOR_FACTORY(N) \
|
||||
template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
|
||||
inline CFunctor *CreateRefCountingFunctor(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \
|
||||
{ \
|
||||
return new CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) const FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CFuncMemPolicyRefCount<OBJECT_TYPE_PTR> >(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_CONST_MEMBER_FUNCTOR_FACTORY );
|
||||
|
||||
#define DEFINE_FUNCTOR_DATA_FACTORY(N) \
|
||||
template < FUNC_SOLO_TEMPLATE_ARG_PARAMS_##N > \
|
||||
inline CFunctorData *CreateFunctorData( FUNC_PROXY_ARG_FORMAL_PARAMS_##N ) \
|
||||
{ \
|
||||
return new CFunctorData##N< FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_##N >( FUNC_CALL_ARGS_##N ); \
|
||||
}
|
||||
|
||||
inline CFunctorData *CreateFunctorData()
|
||||
{
|
||||
return new CFunctorData0();
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL_BUT0( DEFINE_FUNCTOR_DATA_FACTORY );
|
||||
|
||||
#define DEFINE_FUNCTOR_CALLBACK_FACTORY(N) \
|
||||
template < FUNC_SOLO_TEMPLATE_ARG_PARAMS_##N > \
|
||||
inline CFunctorCallback *CreateFunctorCallback( void (*pfnProxied)( FUNC_PROXY_ARG_FORMAL_PARAMS_##N ) ) \
|
||||
{ \
|
||||
return new CFunctorCallback##N< FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_##N >( pfnProxied ); \
|
||||
}
|
||||
|
||||
inline CFunctorCallback *CreateFunctorCallback( void (*pfnProxied)() )
|
||||
{
|
||||
return new CFunctorCallback0( pfnProxied );
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL_BUT0( DEFINE_FUNCTOR_CALLBACK_FACTORY );
|
||||
|
||||
#define DEFINE_MEMBER_FUNCTOR_CALLBACK_FACTORY(N) \
|
||||
template < typename FUNCTION_CLASS FUNC_TEMPLATE_ARG_PARAMS_##N > \
|
||||
inline CFunctorCallback *CreateFunctorCallback( FUNCTION_CLASS *pObject, void ( FUNCTION_CLASS::*pfnProxied )( FUNC_PROXY_ARG_FORMAL_PARAMS_##N ) ) \
|
||||
{ \
|
||||
return new CMemberFunctorCallback##N< FUNCTION_CLASS FUNC_BASE_TEMPLATE_ARG_PARAMS_##N >( pObject, pfnProxied ); \
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNCTOR_CALLBACK_FACTORY );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Templates to assist early-out direct call code
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define DEFINE_NONMEMBER_FUNCTOR_DIRECT(N) \
|
||||
template <typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
|
||||
inline void FunctorDirectCall(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
|
||||
{ \
|
||||
(*pfnProxied)( FUNC_CALL_ARGS_##N ); \
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_NONMEMBER_FUNCTOR_DIRECT );
|
||||
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
#define DEFINE_MEMBER_FUNCTOR_DIRECT(N) \
|
||||
template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
|
||||
inline void FunctorDirectCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
|
||||
{ \
|
||||
((*pObject).*pfnProxied)(FUNC_CALL_ARGS_##N); \
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNCTOR_DIRECT );
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
#define DEFINE_CONST_MEMBER_FUNCTOR_DIRECT(N) \
|
||||
template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
|
||||
inline void FunctorDirectCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \
|
||||
{ \
|
||||
((*pObject).*pfnProxied)(FUNC_CALL_ARGS_##N); \
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_FUNCTOR_DIRECT );
|
||||
|
||||
#include "tier0/memdbgoff.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Factory class useable as templated traits
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class CDefaultFunctorFactory
|
||||
{
|
||||
public:
|
||||
FUNC_GENERATE_ALL( DEFINE_NONMEMBER_FUNCTOR_FACTORY );
|
||||
FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNCTOR_FACTORY );
|
||||
FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_FUNCTOR_FACTORY );
|
||||
FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_MEMBER_FUNCTOR_FACTORY );
|
||||
FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_CONST_MEMBER_FUNCTOR_FACTORY );
|
||||
};
|
||||
|
||||
template <class CAllocator, class CCustomFunctorBase = CFunctorBase>
|
||||
class CCustomizedFunctorFactory
|
||||
{
|
||||
public:
|
||||
void SetAllocator( CAllocator *pAllocator )
|
||||
{
|
||||
m_pAllocator = pAllocator;
|
||||
}
|
||||
|
||||
#define DEFINE_NONMEMBER_FUNCTOR_FACTORY_CUSTOM(N) \
|
||||
template <typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
|
||||
inline CFunctor *CreateFunctor( FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
|
||||
{ \
|
||||
typedef FUNCTION_RETTYPE (*Func_t)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N); \
|
||||
return new (m_pAllocator->Alloc( sizeof(CFunctor##N<Func_t FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CCustomFunctorBase>) )) CFunctor##N<Func_t FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CCustomFunctorBase>( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_NONMEMBER_FUNCTOR_FACTORY_CUSTOM );
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
#define DEFINE_MEMBER_FUNCTOR_FACTORY_CUSTOM(N) \
|
||||
template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
|
||||
inline CFunctor *CreateFunctor(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
|
||||
{ \
|
||||
return new (m_pAllocator->Alloc( sizeof(CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CCustomFunctorBase>) )) CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CCustomFunctorBase>(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNCTOR_FACTORY_CUSTOM );
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
#define DEFINE_CONST_MEMBER_FUNCTOR_FACTORY_CUSTOM(N) \
|
||||
template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
|
||||
inline CFunctor *CreateFunctor( OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \
|
||||
{ \
|
||||
return new (m_pAllocator->Alloc( sizeof(CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) const FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CCustomFunctorBase>) )) CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) const FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CCustomFunctorBase>(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_FUNCTOR_FACTORY_CUSTOM );
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
#define DEFINE_REF_COUNTING_MEMBER_FUNCTOR_FACTORY_CUSTOM(N) \
|
||||
template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
|
||||
inline CFunctor *CreateRefCountingFunctor( OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
|
||||
{ \
|
||||
return new (m_pAllocator->Alloc( sizeof(CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CCustomFunctorBase, CFuncMemPolicyRefCount<OBJECT_TYPE_PTR> >) )) CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CCustomFunctorBase, CFuncMemPolicyRefCount<OBJECT_TYPE_PTR> >(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_MEMBER_FUNCTOR_FACTORY_CUSTOM );
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
#define DEFINE_REF_COUNTING_CONST_MEMBER_FUNCTOR_FACTORY_CUSTOM(N) \
|
||||
template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
|
||||
inline CFunctor *CreateRefCountingFunctor( OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \
|
||||
{ \
|
||||
return new (m_pAllocator->Alloc( sizeof(CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) const FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CCustomFunctorBase, CFuncMemPolicyRefCount<OBJECT_TYPE_PTR> >) )) CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) const FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CCustomFunctorBase, CFuncMemPolicyRefCount<OBJECT_TYPE_PTR> >(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_CONST_MEMBER_FUNCTOR_FACTORY_CUSTOM );
|
||||
|
||||
private:
|
||||
CAllocator *m_pAllocator;
|
||||
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // FUNCTORS_H
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
//======= Copyright © 2005, , Valve Corporation, All rights reserved. =========
|
||||
//
|
||||
// Purpose: Variant Pearson Hash general purpose hashing algorithm described
|
||||
// by Cargill in C++ Report 1994. Generates a 16-bit result.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef GENERICHASH_H
|
||||
#define GENERICHASH_H
|
||||
|
||||
#if defined(_WIN32)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
unsigned FASTCALL HashString( const char *pszKey );
|
||||
unsigned FASTCALL HashStringCaseless( const char *pszKey );
|
||||
unsigned FASTCALL HashStringCaselessConventional( const char *pszKey );
|
||||
unsigned FASTCALL Hash4( const void *pKey );
|
||||
unsigned FASTCALL Hash8( const void *pKey );
|
||||
unsigned FASTCALL Hash12( const void *pKey );
|
||||
unsigned FASTCALL Hash16( const void *pKey );
|
||||
unsigned FASTCALL HashBlock( const void *pKey, unsigned size );
|
||||
|
||||
unsigned FASTCALL HashInt( const int key );
|
||||
|
||||
// hash a uint32 into a uint32
|
||||
FORCEINLINE uint32 HashIntAlternate( uint32 n)
|
||||
{
|
||||
n = ( n + 0x7ed55d16 ) + ( n << 12 );
|
||||
n = ( n ^ 0xc761c23c ) ^ ( n >> 19 );
|
||||
n = ( n + 0x165667b1 ) + ( n << 5 );
|
||||
n = ( n + 0xd3a2646c ) ^ ( n << 9 );
|
||||
n = ( n + 0xfd7046c5 ) + ( n << 3 );
|
||||
n = ( n ^ 0xb55a4f09 ) ^ ( n >> 16 );
|
||||
return n;
|
||||
}
|
||||
|
||||
inline unsigned HashIntConventional( const int n ) // faster but less effective
|
||||
{
|
||||
// first byte
|
||||
unsigned hash = 0xAAAAAAAA + (n & 0xFF);
|
||||
// second byte
|
||||
hash = ( hash << 5 ) + hash + ( (n >> 8) & 0xFF );
|
||||
// third byte
|
||||
hash = ( hash << 5 ) + hash + ( (n >> 16) & 0xFF );
|
||||
// fourth byte
|
||||
hash = ( hash << 5 ) + hash + ( (n >> 24) & 0xFF );
|
||||
|
||||
return hash;
|
||||
|
||||
/* this is the old version, which would cause a load-hit-store on every
|
||||
line on a PowerPC, and therefore took hundreds of clocks to execute!
|
||||
|
||||
byte *p = (byte *)&n;
|
||||
unsigned hash = 0xAAAAAAAA + *p++;
|
||||
hash = ( ( hash << 5 ) + hash ) + *p++;
|
||||
hash = ( ( hash << 5 ) + hash ) + *p++;
|
||||
return ( ( hash << 5 ) + hash ) + *p;
|
||||
*/
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <typename T>
|
||||
inline unsigned HashItem( const T &item )
|
||||
{
|
||||
// TODO: Confirm comiler optimizes out unused paths
|
||||
if ( sizeof(item) == 4 )
|
||||
return Hash4( &item );
|
||||
else if ( sizeof(item) == 8 )
|
||||
return Hash8( &item );
|
||||
else if ( sizeof(item) == 12 )
|
||||
return Hash12( &item );
|
||||
else if ( sizeof(item) == 16 )
|
||||
return Hash16( &item );
|
||||
else
|
||||
return HashBlock( &item, sizeof(item) );
|
||||
}
|
||||
|
||||
template <> inline unsigned HashItem<int>(const int &key )
|
||||
{
|
||||
return HashInt( key );
|
||||
}
|
||||
|
||||
template <> inline unsigned HashItem<unsigned>(const unsigned &key )
|
||||
{
|
||||
return HashInt( (int)key );
|
||||
}
|
||||
|
||||
template<> inline unsigned HashItem<const char *>(const char * const &pszKey )
|
||||
{
|
||||
return HashString( pszKey );
|
||||
}
|
||||
|
||||
template<> inline unsigned HashItem<char *>(char * const &pszKey )
|
||||
{
|
||||
return HashString( pszKey );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Murmur hash
|
||||
//-----------------------------------------------------------------------------
|
||||
uint32 MurmurHash2( const void * key, int len, uint32 seed );
|
||||
|
||||
// return murmurhash2 of a downcased string
|
||||
uint32 MurmurHash2LowerCase( char const *pString, uint32 nSeed );
|
||||
|
||||
uint64 MurmurHash64( const void * key, int len, uint32 seed );
|
||||
|
||||
|
||||
#endif /* !GENERICHASH_H */
|
||||
Vendored
+121
@@ -0,0 +1,121 @@
|
||||
//===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef ICONVAR_H
|
||||
#define ICONVAR_H
|
||||
|
||||
#if _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "tier0/dbg.h"
|
||||
#include "tier0/platform.h"
|
||||
#include "tier1/strtools.h"
|
||||
#include "color.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Forward declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
class IConVar;
|
||||
class CCommand;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ConVar flags
|
||||
//-----------------------------------------------------------------------------
|
||||
// The default, no flags at all
|
||||
#define FCVAR_NONE 0
|
||||
|
||||
// Command to ConVars and ConCommands
|
||||
// ConVar Systems
|
||||
#define FCVAR_UNREGISTERED (1<<0) // If this is set, don't add to linked list, etc.
|
||||
#define FCVAR_DEVELOPMENTONLY (1<<1) // Hidden in released products. Flag is removed automatically if ALLOW_DEVELOPMENT_CVARS is defined.
|
||||
#define FCVAR_GAMEDLL (1<<2) // defined by the game DLL
|
||||
#define FCVAR_CLIENTDLL (1<<3) // defined by the client DLL
|
||||
#define FCVAR_HIDDEN (1<<4) // Hidden. Doesn't appear in find or auto complete. Like DEVELOPMENTONLY, but can't be compiled out.
|
||||
|
||||
// ConVar only
|
||||
#define FCVAR_PROTECTED (1<<5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value
|
||||
#define FCVAR_SPONLY (1<<6) // This cvar cannot be changed by clients connected to a multiplayer server.
|
||||
#define FCVAR_ARCHIVE (1<<7) // set to cause it to be saved to vars.rc
|
||||
#define FCVAR_NOTIFY (1<<8) // notifies players when changed
|
||||
#define FCVAR_USERINFO (1<<9) // changes the client's info string
|
||||
|
||||
#define FCVAR_PRINTABLEONLY (1<<10) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ).
|
||||
#define FCVAR_UNLOGGED (1<<11) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log
|
||||
#define FCVAR_NEVER_AS_STRING (1<<12) // never try to print that cvar
|
||||
|
||||
// It's a ConVar that's shared between the client and the server.
|
||||
// At signon, the values of all such ConVars are sent from the server to the client (skipped for local
|
||||
// client, of course )
|
||||
// If a change is requested it must come from the console (i.e., no remote client changes)
|
||||
// If a value is changed while a server is active, it's replicated to all connected clients
|
||||
#define FCVAR_REPLICATED (1<<13) // server setting enforced on clients, TODO rename to FCAR_SERVER at some time
|
||||
#define FCVAR_CHEAT (1<<14) // Only useable in singleplayer / debug / multiplayer & sv_cheats
|
||||
#define FCVAR_SS (1<<15) // causes varnameN where N == 2 through max splitscreen slots for mod to be autogenerated
|
||||
#define FCVAR_DEMO (1<<16) // record this cvar when starting a demo file
|
||||
#define FCVAR_DONTRECORD (1<<17) // don't record these command in demofiles
|
||||
#define FCVAR_SS_ADDED (1<<18) // This is one of the "added" FCVAR_SS variables for the splitscreen players
|
||||
#define FCVAR_RELEASE (1<<19) // Cvars tagged with this are the only cvars avaliable to customers
|
||||
#define FCVAR_RELOAD_MATERIALS (1<<20) // If this cvar changes, it forces a material reload
|
||||
#define FCVAR_RELOAD_TEXTURES (1<<21) // If this cvar changes, if forces a texture reload
|
||||
|
||||
#define FCVAR_NOT_CONNECTED (1<<22) // cvar cannot be changed by a client that is connected to a server
|
||||
#define FCVAR_MATERIAL_SYSTEM_THREAD (1<<23) // Indicates this cvar is read from the material system thread
|
||||
#define FCVAR_ARCHIVE_GAMECONSOLE (1<<24) // cvar written to config.cfg on the Xbox
|
||||
|
||||
#define FCVAR_SERVER_CAN_EXECUTE (1<<28)// the server is allowed to execute this command on clients via ClientCommand/NET_StringCmd/CBaseClientState::ProcessStringCmd.
|
||||
#define FCVAR_SERVER_CANNOT_QUERY (1<<29)// If this is set, then the server is not allowed to query this cvar's value (via IServerPluginHelpers::StartQueryCvarValue).
|
||||
#define FCVAR_CLIENTCMD_CAN_EXECUTE (1<<30) // IVEngineClient::ClientCmd is allowed to execute this command.
|
||||
// Note: IVEngineClient::ClientCmd_Unrestricted can run any client command.
|
||||
|
||||
#define FCVAR_ACCESSIBLE_FROM_THREADS (1<<25) // used as a debugging tool necessary to check material system thread convars
|
||||
// #define FCVAR_AVAILABLE (1<<26)
|
||||
// #define FCVAR_AVAILABLE (1<<27)
|
||||
// #define FCVAR_AVAILABLE (1<<31)
|
||||
|
||||
#define FCVAR_MATERIAL_THREAD_MASK ( FCVAR_RELOAD_MATERIALS | FCVAR_RELOAD_TEXTURES | FCVAR_MATERIAL_SYSTEM_THREAD )
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Called when a ConVar changes value
|
||||
// NOTE: For FCVAR_NEVER_AS_STRING ConVars, pOldValue == NULL
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef void ( *FnChangeCallback_t )( IConVar *var, const char *pOldValue, float flOldValue );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Abstract interface for ConVars
|
||||
//-----------------------------------------------------------------------------
|
||||
abstract_class IConVar
|
||||
{
|
||||
public:
|
||||
// Value set
|
||||
virtual void SetValue( const char *pValue ) = 0;
|
||||
virtual void SetValue( float flValue ) = 0;
|
||||
virtual void SetValue( int nValue ) = 0;
|
||||
virtual void SetValue( Color value ) = 0;
|
||||
|
||||
// Return name of command
|
||||
virtual const char *GetName( void ) const = 0;
|
||||
|
||||
// Return name of command (usually == GetName(), except in case of FCVAR_SS_ADDED vars
|
||||
virtual const char *GetBaseName( void ) const = 0;
|
||||
|
||||
// Accessors.. not as efficient as using GetState()/GetInfo()
|
||||
// if you call these methods multiple times on the same IConVar
|
||||
virtual bool IsFlagSet( int nFlag ) const = 0;
|
||||
|
||||
virtual int GetSplitScreenPlayerSlot() const = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif // ICONVAR_H
|
||||
+226
@@ -0,0 +1,226 @@
|
||||
//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
// This header defines the interface convention used in the valve engine.
|
||||
// To make an interface and expose it:
|
||||
// 1. The interface must be ALL pure virtuals, and have no data members.
|
||||
// 2. Define a name for it.
|
||||
// 3. In its implementation file, use EXPOSE_INTERFACE or EXPOSE_SINGLE_INTERFACE.
|
||||
|
||||
// Versioning
|
||||
// There are two versioning cases that are handled by this:
|
||||
// 1. You add functions to the end of an interface, so it is binary compatible with the previous interface. In this case,
|
||||
// you need two EXPOSE_INTERFACEs: one to expose your class as the old interface and one to expose it as the new interface.
|
||||
// 2. You update an interface so it's not compatible anymore (but you still want to be able to expose the old interface
|
||||
// for legacy code). In this case, you need to make a new version name for your new interface, and make a wrapper interface and
|
||||
// expose it for the old interface.
|
||||
|
||||
// Static Linking:
|
||||
// Must mimic unique seperate class 'InterfaceReg' constructors per subsystem.
|
||||
// Each subsystem can then import and export interfaces as expected.
|
||||
// This is achieved through unique namespacing 'InterfaceReg' via symbol _SUBSYSTEM.
|
||||
// Static Linking also needs to generate unique symbols per interface so as to
|
||||
// provide a 'stitching' method whereby these interface symbols can be referenced
|
||||
// via the lib's primary module (usually the lib's interface exposure)
|
||||
// therby stitching all of that lib's code/data together for eventual final exe link inclusion.
|
||||
|
||||
#ifndef INTERFACE_H
|
||||
#define INTERFACE_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
// TODO: move interface.cpp into tier0 library.
|
||||
// Need to include platform.h in case _PS3 and other tokens are not yet defined
|
||||
#include "tier0/platform.h"
|
||||
|
||||
#if defined( POSIX ) && !defined( _PS3 )
|
||||
|
||||
#include <dlfcn.h> // dlopen,dlclose, et al
|
||||
#include <unistd.h>
|
||||
|
||||
#define GetProcAddress dlsym
|
||||
|
||||
#ifdef _snprintf
|
||||
#undef _snprintf
|
||||
#endif
|
||||
#define _snprintf snprintf
|
||||
#endif // POSIX && !_PS3
|
||||
|
||||
// All interfaces derive from this.
|
||||
class IBaseInterface
|
||||
{
|
||||
public:
|
||||
virtual ~IBaseInterface() {}
|
||||
};
|
||||
|
||||
#if !defined( _X360 )
|
||||
#define CREATEINTERFACE_PROCNAME "CreateInterface"
|
||||
#else
|
||||
// x360 only allows ordinal exports, .def files export "CreateInterface" at 1
|
||||
#define CREATEINTERFACE_PROCNAME ((const char*)1)
|
||||
#endif
|
||||
|
||||
typedef void* (*CreateInterfaceFn)(const char *pName, int *pReturnCode);
|
||||
typedef void* (*InstantiateInterfaceFn)();
|
||||
|
||||
// Used internally to register classes.
|
||||
class InterfaceReg
|
||||
{
|
||||
public:
|
||||
InterfaceReg(InstantiateInterfaceFn fn, const char *pName);
|
||||
|
||||
public:
|
||||
InstantiateInterfaceFn m_CreateFn;
|
||||
const char *m_pName;
|
||||
|
||||
InterfaceReg *m_pNext; // For the global list.
|
||||
};
|
||||
|
||||
// Use this to expose an interface that can have multiple instances.
|
||||
// e.g.:
|
||||
// EXPOSE_INTERFACE( CInterfaceImp, IInterface, "MyInterface001" )
|
||||
// This will expose a class called CInterfaceImp that implements IInterface (a pure class)
|
||||
// clients can receive a pointer to this class by calling CreateInterface( "MyInterface001" )
|
||||
//
|
||||
// In practice, the shared header file defines the interface (IInterface) and version name ("MyInterface001")
|
||||
// so that each component can use these names/vtables to communicate
|
||||
//
|
||||
// A single class can support multiple interfaces through multiple inheritance
|
||||
//
|
||||
// Use this if you want to write the factory function.
|
||||
#if !defined(_STATIC_LINKED) || !defined(_SUBSYSTEM)
|
||||
#define EXPOSE_INTERFACE_FN(functionName, interfaceName, versionName) \
|
||||
static InterfaceReg __g_Create##interfaceName##_reg(functionName, versionName);
|
||||
#else
|
||||
#define EXPOSE_INTERFACE_FN(functionName, interfaceName, versionName) \
|
||||
namespace _SUBSYSTEM \
|
||||
{ \
|
||||
static InterfaceReg __g_Create##interfaceName##_reg(functionName, versionName); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(_STATIC_LINKED) || !defined(_SUBSYSTEM)
|
||||
#define EXPOSE_INTERFACE(className, interfaceName, versionName) \
|
||||
static void* __Create##className##_interface() {return static_cast<interfaceName *>( new className );} \
|
||||
static InterfaceReg __g_Create##className##_reg(__Create##className##_interface, versionName );
|
||||
#else
|
||||
#define EXPOSE_INTERFACE(className, interfaceName, versionName) \
|
||||
namespace _SUBSYSTEM \
|
||||
{ \
|
||||
static void* __Create##className##_interface() {return static_cast<interfaceName *>( new className );} \
|
||||
static InterfaceReg __g_Create##className##_reg(__Create##className##_interface, versionName ); \
|
||||
}
|
||||
#endif
|
||||
|
||||
// Use this to expose a singleton interface with a global variable you've created.
|
||||
#if !defined(_STATIC_LINKED) || !defined(_SUBSYSTEM)
|
||||
#define EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, globalVarName) \
|
||||
static void* __Create##className##interfaceName##_interface() {return static_cast<interfaceName *>( &globalVarName );} \
|
||||
static InterfaceReg __g_Create##className##interfaceName##_reg(__Create##className##interfaceName##_interface, versionName);
|
||||
#else
|
||||
#define EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, globalVarName) \
|
||||
namespace _SUBSYSTEM \
|
||||
{ \
|
||||
static void* __Create##className##interfaceName##_interface() {return static_cast<interfaceName *>( &globalVarName );} \
|
||||
static InterfaceReg __g_Create##className##interfaceName##_reg(__Create##className##interfaceName##_interface, versionName); \
|
||||
}
|
||||
#endif
|
||||
|
||||
// Use this to expose a singleton interface. This creates the global variable for you automatically.
|
||||
#if !defined(_STATIC_LINKED) || !defined(_SUBSYSTEM)
|
||||
#define EXPOSE_SINGLE_INTERFACE(className, interfaceName, versionName) \
|
||||
static className __g_##className##_singleton; \
|
||||
EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, __g_##className##_singleton)
|
||||
#else
|
||||
#define EXPOSE_SINGLE_INTERFACE(className, interfaceName, versionName) \
|
||||
namespace _SUBSYSTEM \
|
||||
{ \
|
||||
static className __g_##className##_singleton; \
|
||||
} \
|
||||
EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, __g_##className##_singleton)
|
||||
#endif
|
||||
|
||||
// load/unload components
|
||||
class CSysModule;
|
||||
|
||||
// interface return status
|
||||
enum
|
||||
{
|
||||
IFACE_OK = 0,
|
||||
IFACE_FAILED
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This function is automatically exported and allows you to access any interfaces exposed with the above macros.
|
||||
// if pReturnCode is set, it will return one of the following values (IFACE_OK, IFACE_FAILED)
|
||||
// extend this for other error conditions/code
|
||||
//-----------------------------------------------------------------------------
|
||||
DLL_EXPORT void* CreateInterface(const char *pName, int *pReturnCode);
|
||||
|
||||
#if defined( _X360 )
|
||||
DLL_EXPORT void *CreateInterfaceThunk( const char *pName, int *pReturnCode );
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// UNDONE: This is obsolete, use the module load/unload/get instead!!!
|
||||
//-----------------------------------------------------------------------------
|
||||
extern CreateInterfaceFn Sys_GetFactory( CSysModule *pModule );
|
||||
extern CreateInterfaceFn Sys_GetFactory( const char *pModuleName );
|
||||
extern CreateInterfaceFn Sys_GetFactoryThis( void );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Load & Unload should be called in exactly one place for each module
|
||||
// The factory for that module should be passed on to dependent components for
|
||||
// proper versioning.
|
||||
//-----------------------------------------------------------------------------
|
||||
extern CSysModule *Sys_LoadModule( const char *pModuleName );
|
||||
extern void Sys_UnloadModule( CSysModule *pModule );
|
||||
|
||||
// Determines if current process is running with any debug modules
|
||||
extern bool Sys_RunningWithDebugModules();
|
||||
|
||||
// This is a helper function to load a module, get its factory, and get a specific interface.
|
||||
// You are expected to free all of these things.
|
||||
// Returns false and cleans up if any of the steps fail.
|
||||
bool Sys_LoadInterface(
|
||||
const char *pModuleName,
|
||||
const char *pInterfaceVersionName,
|
||||
CSysModule **pOutModule,
|
||||
void **pOutInterface );
|
||||
|
||||
bool Sys_IsDebuggerPresent();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Place this as a singleton at module scope (e.g.) and use it to get the factory from the specified module name.
|
||||
//
|
||||
// When the singleton goes out of scope (.dll unload if at module scope),
|
||||
// then it'll call Sys_UnloadModule on the module so that the refcount is decremented
|
||||
// and the .dll actually can unload from memory.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CDllDemandLoader
|
||||
{
|
||||
public:
|
||||
CDllDemandLoader( char const *pchModuleName );
|
||||
virtual ~CDllDemandLoader();
|
||||
CreateInterfaceFn GetFactory();
|
||||
void Unload();
|
||||
|
||||
private:
|
||||
|
||||
char const *m_pchModuleName;
|
||||
CSysModule *m_hModule;
|
||||
bool m_bLoadAttempted;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
+519
@@ -0,0 +1,519 @@
|
||||
//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef KEYVALUES_H
|
||||
#define KEYVALUES_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#ifdef __cplusplus
|
||||
#define NULL 0
|
||||
#else
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "utlvector.h"
|
||||
#include "color.h"
|
||||
#include "exprevaluator.h"
|
||||
|
||||
|
||||
#define FOR_EACH_SUBKEY( kvRoot, kvSubKey ) \
|
||||
for ( KeyValues * kvSubKey = kvRoot->GetFirstSubKey(); kvSubKey != NULL; kvSubKey = kvSubKey->GetNextKey() )
|
||||
|
||||
#define FOR_EACH_TRUE_SUBKEY( kvRoot, kvSubKey ) \
|
||||
for ( KeyValues * kvSubKey = kvRoot->GetFirstTrueSubKey(); kvSubKey != NULL; kvSubKey = kvSubKey->GetNextTrueSubKey() )
|
||||
|
||||
#define FOR_EACH_VALUE( kvRoot, kvValue ) \
|
||||
for ( KeyValues * kvValue = kvRoot->GetFirstValue(); kvValue != NULL; kvValue = kvValue->GetNextValue() )
|
||||
|
||||
|
||||
class IBaseFileSystem;
|
||||
class CUtlBuffer;
|
||||
class Color;
|
||||
class KeyValues;
|
||||
class IKeyValuesDumpContext;
|
||||
typedef void * FileHandle_t;
|
||||
class CKeyValuesGrowableStringTable;
|
||||
|
||||
|
||||
// single byte identifies a xbox kv file in binary format
|
||||
// strings are pooled from a searchpath/zip mounted symbol table
|
||||
#define KV_BINARY_POOLED_FORMAT 0xAA
|
||||
|
||||
|
||||
#define FOR_EACH_SUBKEY( kvRoot, kvSubKey ) \
|
||||
for ( KeyValues * kvSubKey = kvRoot->GetFirstSubKey(); kvSubKey != NULL; kvSubKey = kvSubKey->GetNextKey() )
|
||||
|
||||
#define FOR_EACH_TRUE_SUBKEY( kvRoot, kvSubKey ) \
|
||||
for ( KeyValues * kvSubKey = kvRoot->GetFirstTrueSubKey(); kvSubKey != NULL; kvSubKey = kvSubKey->GetNextTrueSubKey() )
|
||||
|
||||
#define FOR_EACH_VALUE( kvRoot, kvValue ) \
|
||||
for ( KeyValues * kvValue = kvRoot->GetFirstValue(); kvValue != NULL; kvValue = kvValue->GetNextValue() )
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Simple recursive data access class
|
||||
// Used in vgui for message parameters and resource files
|
||||
// Destructor deletes all child KeyValues nodes
|
||||
// Data is stored in key (string names) - (string/int/float)value pairs called nodes.
|
||||
//
|
||||
// About KeyValues Text File Format:
|
||||
|
||||
// It has 3 control characters '{', '}' and '"'. Names and values may be quoted or
|
||||
// not. The quote '"' character must not be used within name or values, only for
|
||||
// quoting whole tokens. You may use escape sequences wile parsing and add within a
|
||||
// quoted token a \" to add quotes within your name or token. When using Escape
|
||||
// Sequence the parser must now that by setting KeyValues::UsesEscapeSequences( true ),
|
||||
// which it's off by default. Non-quoted tokens ends with a whitespace, '{', '}' and '"'.
|
||||
// So you may use '{' and '}' within quoted tokens, but not for non-quoted tokens.
|
||||
// An open bracket '{' after a key name indicates a list of subkeys which is finished
|
||||
// with a closing bracket '}'. Subkeys use the same definitions recursively.
|
||||
// Whitespaces are space, return, newline and tabulator. Allowed Escape sequences
|
||||
// are \n, \t, \\, \n and \". The number character '#' is used for macro purposes
|
||||
// (eg #include), don't use it as first character in key names.
|
||||
//-----------------------------------------------------------------------------
|
||||
class KeyValues
|
||||
{
|
||||
public:
|
||||
// By default, the KeyValues class uses a string table for the key names that is
|
||||
// limited to 4MB. The game will exit in error if this space is exhausted. In
|
||||
// general this is preferable for game code for performance and memory fragmentation
|
||||
// reasons.
|
||||
//
|
||||
// If this is not acceptable, you can use this call to switch to a table that can grow
|
||||
// arbitrarily. This call must be made before any KeyValues objects are allocated or it
|
||||
// will result in undefined behavior. If you use the growable string table, you cannot
|
||||
// share KeyValues pointers directly with any other module. You can serialize them across
|
||||
// module boundaries. These limitations are acceptable in the Steam backend code
|
||||
// this option was written for, but may not be in other situations. Make sure to
|
||||
// understand the implications before using this.
|
||||
static void SetUseGrowableStringTable( bool bUseGrowableTable );
|
||||
|
||||
explicit KeyValues( const char *setName );
|
||||
|
||||
//
|
||||
// AutoDelete class to automatically free the keyvalues.
|
||||
// Simply construct it with the keyvalues you allocated and it will free them when falls out of scope.
|
||||
// When you decide that keyvalues shouldn't be deleted call Assign(NULL) on it.
|
||||
// If you constructed AutoDelete(NULL) you can later assign the keyvalues to be deleted with Assign(pKeyValues).
|
||||
//
|
||||
class AutoDelete
|
||||
{
|
||||
public:
|
||||
explicit inline AutoDelete( KeyValues *pKeyValues ) : m_pKeyValues( pKeyValues ) {}
|
||||
explicit inline AutoDelete( const char *pchKVName ) : m_pKeyValues( new KeyValues( pchKVName ) ) {}
|
||||
inline ~AutoDelete( void ) { if( m_pKeyValues ) m_pKeyValues->deleteThis(); }
|
||||
inline void Assign( KeyValues *pKeyValues ) { m_pKeyValues = pKeyValues; }
|
||||
KeyValues *operator->() { return m_pKeyValues; }
|
||||
operator KeyValues *() { return m_pKeyValues; }
|
||||
private:
|
||||
AutoDelete( AutoDelete const &x ); // forbid
|
||||
AutoDelete & operator= ( AutoDelete const &x ); // forbid
|
||||
protected:
|
||||
KeyValues *m_pKeyValues;
|
||||
};
|
||||
|
||||
//
|
||||
// AutoDeleteInline is useful when you want to hold your keyvalues object inside
|
||||
// and delete it right after using.
|
||||
// You can also pass temporary KeyValues object as an argument to a function by wrapping it into KeyValues::AutoDeleteInline
|
||||
// instance: call_my_function( KeyValues::AutoDeleteInline( new KeyValues( "test" ) ) )
|
||||
//
|
||||
class AutoDeleteInline : public AutoDelete
|
||||
{
|
||||
public:
|
||||
explicit inline AutoDeleteInline( KeyValues *pKeyValues ) : AutoDelete( pKeyValues ) {}
|
||||
inline operator KeyValues *() const { return m_pKeyValues; }
|
||||
inline KeyValues * Get() const { return m_pKeyValues; }
|
||||
};
|
||||
|
||||
// Quick setup constructors
|
||||
KeyValues( const char *setName, const char *firstKey, const char *firstValue );
|
||||
KeyValues( const char *setName, const char *firstKey, const wchar_t *firstValue );
|
||||
KeyValues( const char *setName, const char *firstKey, int firstValue );
|
||||
KeyValues( const char *setName, const char *firstKey, const char *firstValue, const char *secondKey, const char *secondValue );
|
||||
KeyValues( const char *setName, const char *firstKey, int firstValue, const char *secondKey, int secondValue );
|
||||
|
||||
// Section name
|
||||
const char *GetName() const;
|
||||
void SetName( const char *setName);
|
||||
|
||||
// gets the name as a unique int
|
||||
int GetNameSymbol() const;
|
||||
int GetNameSymbolCaseSensitive() const;
|
||||
|
||||
// File access. Set UsesEscapeSequences true, if resource file/buffer uses Escape Sequences (eg \n, \t)
|
||||
void UsesEscapeSequences(bool state); // default false
|
||||
bool LoadFromFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL, GetSymbolProc_t pfnEvaluateSymbolProc = NULL);
|
||||
bool SaveToFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL);
|
||||
|
||||
// Read from a buffer... Note that the buffer must be null terminated
|
||||
bool LoadFromBuffer( char const *resourceName, const char *pBuffer, IBaseFileSystem* pFileSystem = NULL, const char *pPathID = NULL, GetSymbolProc_t pfnEvaluateSymbolProc = NULL );
|
||||
|
||||
// Read from a utlbuffer...
|
||||
bool LoadFromBuffer( char const *resourceName, CUtlBuffer &buf, IBaseFileSystem* pFileSystem = NULL, const char *pPathID = NULL, GetSymbolProc_t pfnEvaluateSymbolProc = NULL );
|
||||
|
||||
// Find a keyValue, create it if it is not found.
|
||||
// Set bCreate to true to create the key if it doesn't already exist (which ensures a valid pointer will be returned)
|
||||
KeyValues *FindKey(const char *keyName, bool bCreate = false);
|
||||
KeyValues *FindKey(int keySymbol) const;
|
||||
KeyValues *CreateNewKey(); // creates a new key, with an autogenerated name. name is guaranteed to be an integer, of value 1 higher than the highest other integer key name
|
||||
void AddSubKey( KeyValues *pSubkey ); // Adds a subkey. Make sure the subkey isn't a child of some other keyvalues
|
||||
void RemoveSubKey(KeyValues *subKey); // removes a subkey from the list, DOES NOT DELETE IT
|
||||
void InsertSubKey( int nIndex, KeyValues *pSubKey ); // Inserts the given sub-key before the Nth child location
|
||||
bool ContainsSubKey( KeyValues *pSubKey ); // Returns true if this key values contains the specified sub key, false otherwise.
|
||||
void SwapSubKey( KeyValues *pExistingSubKey, KeyValues *pNewSubKey ); // Swaps an existing subkey for a new one, DOES NOT DELETE THE OLD ONE but takes ownership of the new one
|
||||
void ElideSubKey( KeyValues *pSubKey ); // Removes a subkey but inserts all of its children in its place, in-order (flattens a tree, like firing a manager!)
|
||||
|
||||
// Key iteration.
|
||||
//
|
||||
// NOTE: GetFirstSubKey/GetNextKey will iterate keys AND values. Use the functions
|
||||
// below if you want to iterate over just the keys or just the values.
|
||||
//
|
||||
KeyValues *GetFirstSubKey(); // returns the first subkey in the list
|
||||
KeyValues *GetNextKey(); // returns the next subkey
|
||||
void SetNextKey( KeyValues * pDat);
|
||||
|
||||
//
|
||||
// These functions can be used to treat it like a true key/values tree instead of
|
||||
// confusing values with keys.
|
||||
//
|
||||
// So if you wanted to iterate all subkeys, then all values, it would look like this:
|
||||
// for ( KeyValues *pKey = pRoot->GetFirstTrueSubKey(); pKey; pKey = pKey->GetNextTrueSubKey() )
|
||||
// {
|
||||
// Msg( "Key name: %s\n", pKey->GetName() );
|
||||
// }
|
||||
// for ( KeyValues *pValue = pRoot->GetFirstValue(); pKey; pKey = pKey->GetNextValue() )
|
||||
// {
|
||||
// Msg( "Int value: %d\n", pValue->GetInt() ); // Assuming pValue->GetDataType() == TYPE_INT...
|
||||
// }
|
||||
KeyValues* GetFirstTrueSubKey();
|
||||
KeyValues* GetNextTrueSubKey();
|
||||
|
||||
KeyValues* GetFirstValue(); // When you get a value back, you can use GetX and pass in NULL to get the value.
|
||||
KeyValues* GetNextValue();
|
||||
|
||||
|
||||
// Data access
|
||||
int GetInt( const char *keyName = NULL, int defaultValue = 0 );
|
||||
uint64 GetUint64( const char *keyName = NULL, uint64 defaultValue = 0 );
|
||||
float GetFloat( const char *keyName = NULL, float defaultValue = 0.0f );
|
||||
const char *GetString( const char *keyName = NULL, const char *defaultValue = "" );
|
||||
const wchar_t *GetWString( const char *keyName = NULL, const wchar_t *defaultValue = L"" );
|
||||
void *GetPtr( const char *keyName = NULL, void *defaultValue = (void*)0 );
|
||||
Color GetColor( const char *keyName = NULL , const Color &defaultColor = Color( 0, 0, 0, 0 ) );
|
||||
bool GetBool( const char *keyName = NULL, bool defaultValue = false ) { return GetInt( keyName, defaultValue ? 1 : 0 ) ? true : false; }
|
||||
bool IsEmpty(const char *keyName = NULL);
|
||||
|
||||
// Data access
|
||||
int GetInt( int keySymbol, int defaultValue = 0 );
|
||||
uint64 GetUint64( int keySymbol, uint64 defaultValue = 0 );
|
||||
float GetFloat( int keySymbol, float defaultValue = 0.0f );
|
||||
const char *GetString( int keySymbol, const char *defaultValue = "" );
|
||||
const wchar_t *GetWString( int keySymbol, const wchar_t *defaultValue = L"" );
|
||||
void *GetPtr( int keySymbol, void *defaultValue = (void*)0 );
|
||||
Color GetColor( int keySymbol /* default value is all black */);
|
||||
bool GetBool( int keySymbol, bool defaultValue = false ) { return GetInt( keySymbol, defaultValue ? 1 : 0 ) ? true : false; }
|
||||
bool IsEmpty( int keySymbol );
|
||||
|
||||
// Key writing
|
||||
void SetWString( const char *keyName, const wchar_t *value );
|
||||
void SetString( const char *keyName, const char *value );
|
||||
void SetInt( const char *keyName, int value );
|
||||
void SetUint64( const char *keyName, uint64 value );
|
||||
void SetFloat( const char *keyName, float value );
|
||||
void SetPtr( const char *keyName, void *value );
|
||||
void SetColor( const char *keyName, Color value);
|
||||
void SetBool( const char *keyName, bool value ) { SetInt( keyName, value ? 1 : 0 ); }
|
||||
|
||||
// Memory allocation (optimized)
|
||||
void *operator new( size_t iAllocSize );
|
||||
void *operator new( size_t iAllocSize, int nBlockUse, const char *pFileName, int nLine );
|
||||
void operator delete( void *pMem );
|
||||
void operator delete( void *pMem, int nBlockUse, const char *pFileName, int nLine );
|
||||
|
||||
KeyValues& operator=( KeyValues& src );
|
||||
|
||||
// Adds a chain... if we don't find stuff in this keyvalue, we'll look
|
||||
// in the one we're chained to.
|
||||
void ChainKeyValue( KeyValues* pChain );
|
||||
|
||||
void RecursiveSaveToFile( CUtlBuffer& buf, int indentLevel );
|
||||
|
||||
bool WriteAsBinary( CUtlBuffer &buffer ) const;
|
||||
bool ReadAsBinary( CUtlBuffer &buffer );
|
||||
|
||||
// Allocate & create a new copy of the keys
|
||||
KeyValues *MakeCopy( void ) const;
|
||||
|
||||
// Make a new copy of all subkeys, add them all to the passed-in keyvalues
|
||||
void CopySubkeys( KeyValues *pParent ) const;
|
||||
|
||||
// Clear out all subkeys, and the current value
|
||||
void Clear( void );
|
||||
|
||||
// Data type
|
||||
enum types_t
|
||||
{
|
||||
TYPE_NONE = 0,
|
||||
TYPE_STRING,
|
||||
TYPE_INT,
|
||||
TYPE_FLOAT,
|
||||
TYPE_PTR,
|
||||
TYPE_WSTRING,
|
||||
TYPE_COLOR,
|
||||
TYPE_UINT64,
|
||||
TYPE_COMPILED_INT_BYTE, // hack to collapse 1 byte ints in the compiled format
|
||||
TYPE_COMPILED_INT_0, // hack to collapse 0 in the compiled format
|
||||
TYPE_COMPILED_INT_1, // hack to collapse 1 in the compiled format
|
||||
TYPE_NUMTYPES,
|
||||
};
|
||||
types_t GetDataType(const char *keyName = NULL);
|
||||
|
||||
// Virtual deletion function - ensures that KeyValues object is deleted from correct heap
|
||||
void deleteThis();
|
||||
|
||||
void SetStringValue( char const *strValue );
|
||||
|
||||
// unpack a key values list into a structure
|
||||
void UnpackIntoStructure( struct KeyValuesUnpackStructure const *pUnpackTable, void *pDest );
|
||||
|
||||
// Process conditional keys for widescreen support.
|
||||
bool ProcessResolutionKeys( const char *pResString );
|
||||
|
||||
// Dump keyvalues recursively into a dump context
|
||||
bool Dump( IKeyValuesDumpContext *pDump, int nIndentLevel = 0 );
|
||||
|
||||
// Merge operations describing how two keyvalues can be combined
|
||||
enum MergeKeyValuesOp_t
|
||||
{
|
||||
MERGE_KV_ALL,
|
||||
MERGE_KV_UPDATE, // update values are copied into storage, adding new keys to storage or updating existing ones
|
||||
MERGE_KV_DELETE, // update values specify keys that get deleted from storage
|
||||
MERGE_KV_BORROW, // update values only update existing keys in storage, keys in update that do not exist in storage are discarded
|
||||
};
|
||||
void MergeFrom( KeyValues *kvMerge, MergeKeyValuesOp_t eOp = MERGE_KV_ALL );
|
||||
|
||||
// Assign keyvalues from a string
|
||||
static KeyValues * FromString( char const *szName, char const *szStringVal, char const **ppEndOfParse = NULL );
|
||||
|
||||
protected:
|
||||
KeyValues( KeyValues& ); // prevent copy constructor being used
|
||||
|
||||
// prevent delete being called except through deleteThis()
|
||||
~KeyValues();
|
||||
|
||||
KeyValues* CreateKey( const char *keyName );
|
||||
|
||||
void RecursiveCopyKeyValues( KeyValues& src );
|
||||
void RemoveEverything();
|
||||
// void RecursiveSaveToFile( IBaseFileSystem *filesystem, CUtlBuffer &buffer, int indentLevel );
|
||||
// void WriteConvertedString( CUtlBuffer &buffer, const char *pszString );
|
||||
|
||||
// NOTE: If both filesystem and pBuf are non-null, it'll save to both of them.
|
||||
// If filesystem is null, it'll ignore f.
|
||||
void RecursiveSaveToFile( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, int indentLevel );
|
||||
void WriteConvertedString( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, const char *pszString );
|
||||
|
||||
void RecursiveLoadFromBuffer( char const *resourceName, CUtlBuffer &buf, GetSymbolProc_t pfnEvaluateSymbolProc );
|
||||
|
||||
// for handling #include "filename"
|
||||
void AppendIncludedKeys( CUtlVector< KeyValues * >& includedKeys );
|
||||
void ParseIncludedKeys( char const *resourceName, const char *filetoinclude,
|
||||
IBaseFileSystem* pFileSystem, const char *pPathID, CUtlVector< KeyValues * >& includedKeys, GetSymbolProc_t pfnEvaluateSymbolProc );
|
||||
|
||||
// For handling #base "filename"
|
||||
void MergeBaseKeys( CUtlVector< KeyValues * >& baseKeys );
|
||||
void RecursiveMergeKeyValues( KeyValues *baseKV );
|
||||
|
||||
// NOTE: If both filesystem and pBuf are non-null, it'll save to both of them.
|
||||
// If filesystem is null, it'll ignore f.
|
||||
void InternalWrite( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, const void *pData, int len );
|
||||
|
||||
void Init();
|
||||
const char * ReadToken( CUtlBuffer &buf, bool &wasQuoted, bool &wasConditional );
|
||||
void WriteIndents( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, int indentLevel );
|
||||
|
||||
void FreeAllocatedValue();
|
||||
void AllocateValueBlock(int size);
|
||||
|
||||
bool ReadAsBinaryPooledFormat( CUtlBuffer &buf, IBaseFileSystem *pFileSystem, unsigned int poolKey, GetSymbolProc_t pfnEvaluateSymbolProc );
|
||||
|
||||
bool EvaluateConditional( const char *pExpressionString, GetSymbolProc_t pfnEvaluateSymbolProc );
|
||||
|
||||
uint32 m_iKeyName : 24; // keyname is a symbol defined in KeyValuesSystem
|
||||
uint32 m_iKeyNameCaseSensitive1 : 8; // 1st part of case sensitive symbol defined in KeyValueSystem
|
||||
|
||||
// These are needed out of the union because the API returns string pointers
|
||||
char *m_sValue;
|
||||
wchar_t *m_wsValue;
|
||||
|
||||
// we don't delete these
|
||||
union
|
||||
{
|
||||
int m_iValue;
|
||||
float m_flValue;
|
||||
void *m_pValue;
|
||||
unsigned char m_Color[4];
|
||||
};
|
||||
|
||||
char m_iDataType;
|
||||
char m_bHasEscapeSequences; // true, if while parsing this KeyValue, Escape Sequences are used (default false)
|
||||
uint16 m_iKeyNameCaseSensitive2; // 2nd part of case sensitive symbol defined in KeyValueSystem;
|
||||
|
||||
KeyValues *m_pPeer; // pointer to next key in list
|
||||
KeyValues *m_pSub; // pointer to Start of a new sub key list
|
||||
KeyValues *m_pChain;// Search here if it's not in our list
|
||||
|
||||
GetSymbolProc_t m_pExpressionGetSymbolProc;
|
||||
|
||||
private:
|
||||
// Statics to implement the optional growable string table
|
||||
// Function pointers that will determine which mode we are in
|
||||
static int (*s_pfGetSymbolForString)( const char *name, bool bCreate );
|
||||
static const char *(*s_pfGetStringForSymbol)( int symbol );
|
||||
static CKeyValuesGrowableStringTable *s_pGrowableStringTable;
|
||||
|
||||
public:
|
||||
// Functions that invoke the default behavior
|
||||
static int GetSymbolForStringClassic( const char *name, bool bCreate = true );
|
||||
static const char *GetStringForSymbolClassic( int symbol );
|
||||
|
||||
// Functions that use the growable string table
|
||||
static int GetSymbolForStringGrowable( const char *name, bool bCreate = true );
|
||||
static const char *GetStringForSymbolGrowable( int symbol );
|
||||
};
|
||||
|
||||
typedef KeyValues::AutoDelete KeyValuesAD;
|
||||
|
||||
enum KeyValuesUnpackDestinationTypes_t
|
||||
{
|
||||
UNPACK_TYPE_FLOAT, // dest is a float
|
||||
UNPACK_TYPE_VECTOR, // dest is a Vector
|
||||
UNPACK_TYPE_VECTOR_COLOR, // dest is a vector, src is a color
|
||||
UNPACK_TYPE_STRING, // dest is a char *. unpacker will allocate.
|
||||
UNPACK_TYPE_INT, // dest is an int
|
||||
UNPACK_TYPE_FOUR_FLOATS, // dest is an array of 4 floats. source is a string like "1 2 3 4"
|
||||
UNPACK_TYPE_TWO_FLOATS, // dest is an array of 2 floats. source is a string like "1 2"
|
||||
};
|
||||
|
||||
#define UNPACK_FIXED( kname, kdefault, dtype, ofs ) { kname, kdefault, dtype, ofs, 0 }
|
||||
#define UNPACK_VARIABLE( kname, kdefault, dtype, ofs, sz ) { kname, kdefault, dtype, ofs, sz }
|
||||
#define UNPACK_END_MARKER { NULL, NULL, UNPACK_TYPE_FLOAT, 0 }
|
||||
|
||||
struct KeyValuesUnpackStructure
|
||||
{
|
||||
char const *m_pKeyName; // null to terminate tbl
|
||||
char const *m_pKeyDefault; // null ok
|
||||
KeyValuesUnpackDestinationTypes_t m_eDataType; // UNPACK_TYPE_INT, ..
|
||||
size_t m_nFieldOffset; // use offsetof to set
|
||||
size_t m_nFieldSize; // for strings or other variable length
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// inline methods
|
||||
//-----------------------------------------------------------------------------
|
||||
inline int KeyValues::GetInt( int keySymbol, int defaultValue )
|
||||
{
|
||||
KeyValues *dat = FindKey( keySymbol );
|
||||
return dat ? dat->GetInt( (const char *)NULL, defaultValue ) : defaultValue;
|
||||
}
|
||||
|
||||
inline uint64 KeyValues::GetUint64( int keySymbol, uint64 defaultValue )
|
||||
{
|
||||
KeyValues *dat = FindKey( keySymbol );
|
||||
return dat ? dat->GetUint64( (const char *)NULL, defaultValue ) : defaultValue;
|
||||
}
|
||||
|
||||
inline float KeyValues::GetFloat( int keySymbol, float defaultValue )
|
||||
{
|
||||
KeyValues *dat = FindKey( keySymbol );
|
||||
return dat ? dat->GetFloat( (const char *)NULL, defaultValue ) : defaultValue;
|
||||
}
|
||||
|
||||
inline const char *KeyValues::GetString( int keySymbol, const char *defaultValue )
|
||||
{
|
||||
KeyValues *dat = FindKey( keySymbol );
|
||||
return dat ? dat->GetString( (const char *)NULL, defaultValue ) : defaultValue;
|
||||
}
|
||||
|
||||
inline const wchar_t *KeyValues::GetWString( int keySymbol, const wchar_t *defaultValue )
|
||||
{
|
||||
KeyValues *dat = FindKey( keySymbol );
|
||||
return dat ? dat->GetWString( (const char *)NULL, defaultValue ) : defaultValue;
|
||||
}
|
||||
|
||||
inline void *KeyValues::GetPtr( int keySymbol, void *defaultValue )
|
||||
{
|
||||
KeyValues *dat = FindKey( keySymbol );
|
||||
return dat ? dat->GetPtr( (const char *)NULL, defaultValue ) : defaultValue;
|
||||
}
|
||||
|
||||
inline Color KeyValues::GetColor( int keySymbol )
|
||||
{
|
||||
Color defaultValue( 0, 0, 0, 0 );
|
||||
KeyValues *dat = FindKey( keySymbol );
|
||||
return dat ? dat->GetColor( ) : defaultValue;
|
||||
}
|
||||
|
||||
inline bool KeyValues::IsEmpty( int keySymbol )
|
||||
{
|
||||
KeyValues *dat = FindKey( keySymbol );
|
||||
return dat ? dat->IsEmpty( ) : true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// KeyValuesDumpContext and generic implementations
|
||||
//
|
||||
|
||||
class IKeyValuesDumpContext
|
||||
{
|
||||
public:
|
||||
virtual bool KvBeginKey( KeyValues *pKey, int nIndentLevel ) = 0;
|
||||
virtual bool KvWriteValue( KeyValues *pValue, int nIndentLevel ) = 0;
|
||||
virtual bool KvEndKey( KeyValues *pKey, int nIndentLevel ) = 0;
|
||||
};
|
||||
|
||||
class IKeyValuesDumpContextAsText : public IKeyValuesDumpContext
|
||||
{
|
||||
public:
|
||||
virtual bool KvBeginKey( KeyValues *pKey, int nIndentLevel );
|
||||
virtual bool KvWriteValue( KeyValues *pValue, int nIndentLevel );
|
||||
virtual bool KvEndKey( KeyValues *pKey, int nIndentLevel );
|
||||
|
||||
public:
|
||||
virtual bool KvWriteIndent( int nIndentLevel );
|
||||
virtual bool KvWriteText( char const *szText ) = 0;
|
||||
};
|
||||
|
||||
class CKeyValuesDumpContextAsDevMsg : public IKeyValuesDumpContextAsText
|
||||
{
|
||||
public:
|
||||
// Overrides developer level to dump in DevMsg, zero to dump as Msg
|
||||
CKeyValuesDumpContextAsDevMsg( int nDeveloperLevel = 1 ) : m_nDeveloperLevel( nDeveloperLevel ) {}
|
||||
|
||||
public:
|
||||
virtual bool KvBeginKey( KeyValues *pKey, int nIndentLevel );
|
||||
virtual bool KvWriteText( char const *szText );
|
||||
|
||||
protected:
|
||||
int m_nDeveloperLevel;
|
||||
};
|
||||
|
||||
inline bool KeyValuesDumpAsDevMsg( KeyValues *pKeyValues, int nIndentLevel = 0, int nDeveloperLevel = 1 )
|
||||
{
|
||||
CKeyValuesDumpContextAsDevMsg ctx( nDeveloperLevel );
|
||||
return pKeyValues->Dump( &ctx, nIndentLevel );
|
||||
}
|
||||
|
||||
|
||||
#endif // KEYVALUES_H
|
||||
Vendored
+649
@@ -0,0 +1,649 @@
|
||||
//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// $Log: $
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef MEMPOOL_H
|
||||
#define MEMPOOL_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "tier0/memalloc.h"
|
||||
#include "tier0/tslist.h"
|
||||
#include "tier0/platform.h"
|
||||
#include "tier1/utlvector.h"
|
||||
#include "tier1/utlrbtree.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Optimized pool memory allocator
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
typedef void (*MemoryPoolReportFunc_t)( char const* pMsg, ... );
|
||||
|
||||
class CUtlMemoryPool
|
||||
{
|
||||
public:
|
||||
// Ways the memory pool can grow when it needs to make a new blob.
|
||||
enum MemoryPoolGrowType_t
|
||||
{
|
||||
GROW_NONE=0, // Don't allow new blobs.
|
||||
GROW_FAST=1, // New blob size is numElements * (i+1) (ie: the blocks it allocates
|
||||
// get larger and larger each time it allocates one).
|
||||
GROW_SLOW=2 // New blob size is numElements.
|
||||
};
|
||||
|
||||
CUtlMemoryPool( int blockSize, int numElements, int growMode = GROW_FAST, const char *pszAllocOwner = NULL, int nAlignment = 0 );
|
||||
~CUtlMemoryPool();
|
||||
|
||||
void* Alloc(); // Allocate the element size you specified in the constructor.
|
||||
void* Alloc( size_t amount );
|
||||
void* AllocZero(); // Allocate the element size you specified in the constructor, zero the memory before construction
|
||||
void* AllocZero( size_t amount );
|
||||
void Free(void *pMem);
|
||||
|
||||
// Frees everything
|
||||
void Clear();
|
||||
|
||||
// Error reporting...
|
||||
static void SetErrorReportFunc( MemoryPoolReportFunc_t func );
|
||||
|
||||
// returns number of allocated blocks
|
||||
int Count() const { return m_BlocksAllocated; }
|
||||
int PeakCount() const { return m_PeakAlloc; }
|
||||
int BlockSize() const { return m_BlockSize; }
|
||||
int Size() const { return m_NumBlobs * m_BlocksPerBlob * m_BlockSize; }
|
||||
|
||||
bool IsAllocationWithinPool( void *pMem ) const;
|
||||
|
||||
protected:
|
||||
class CBlob
|
||||
{
|
||||
public:
|
||||
CBlob *m_pPrev, *m_pNext;
|
||||
int m_NumBytes; // Number of bytes in this blob.
|
||||
char m_Data[1];
|
||||
char m_Padding[3]; // to int align the struct
|
||||
};
|
||||
|
||||
// Resets the pool
|
||||
void Init();
|
||||
void AddNewBlob();
|
||||
void ReportLeaks();
|
||||
|
||||
int m_BlockSize;
|
||||
int m_BlocksPerBlob;
|
||||
|
||||
int m_GrowMode; // GROW_ enum.
|
||||
|
||||
// FIXME: Change m_ppMemBlob into a growable array?
|
||||
void *m_pHeadOfFreeList;
|
||||
int m_BlocksAllocated;
|
||||
int m_PeakAlloc;
|
||||
unsigned short m_nAlignment;
|
||||
unsigned short m_NumBlobs;
|
||||
const char * m_pszAllocOwner;
|
||||
// CBlob could be not a multiple of 4 bytes so stuff it at the end here to keep us otherwise aligned
|
||||
CBlob m_BlobHead;
|
||||
|
||||
static MemoryPoolReportFunc_t g_ReportFunc;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Multi-thread/Thread Safe Memory Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class CMemoryPoolMT : public CUtlMemoryPool
|
||||
{
|
||||
public:
|
||||
CMemoryPoolMT( int blockSize, int numElements, int growMode = GROW_FAST, const char *pszAllocOwner = NULL, int nAlignment = 0) : CUtlMemoryPool( blockSize, numElements, growMode, pszAllocOwner, nAlignment ) {}
|
||||
|
||||
|
||||
void* Alloc() { AUTO_LOCK( m_mutex ); return CUtlMemoryPool::Alloc(); }
|
||||
void* Alloc( size_t amount ) { AUTO_LOCK( m_mutex ); return CUtlMemoryPool::Alloc( amount ); }
|
||||
void* AllocZero() { AUTO_LOCK( m_mutex ); return CUtlMemoryPool::AllocZero(); }
|
||||
void* AllocZero( size_t amount ) { AUTO_LOCK( m_mutex ); return CUtlMemoryPool::AllocZero( amount ); }
|
||||
void Free(void *pMem) { AUTO_LOCK( m_mutex ); CUtlMemoryPool::Free( pMem ); }
|
||||
|
||||
// Frees everything
|
||||
void Clear() { AUTO_LOCK( m_mutex ); return CUtlMemoryPool::Clear(); }
|
||||
private:
|
||||
CThreadFastMutex m_mutex; // @TODO: Rework to use tslist (toml 7/6/2007)
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Wrapper macro to make an allocator that returns particular typed allocations
|
||||
// and construction and destruction of objects.
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T >
|
||||
class CClassMemoryPool : public CUtlMemoryPool
|
||||
{
|
||||
public:
|
||||
CClassMemoryPool(int numElements, int growMode = GROW_FAST, int nAlignment = 0 ) :
|
||||
CUtlMemoryPool( sizeof(T), numElements, growMode, MEM_ALLOC_CLASSNAME(T), nAlignment ) {}
|
||||
|
||||
T* Alloc();
|
||||
T* AllocZero();
|
||||
void Free( T *pMem );
|
||||
|
||||
void Clear();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Specialized pool for aligned data management (e.g., Xbox textures)
|
||||
//-----------------------------------------------------------------------------
|
||||
template <int ITEM_SIZE, int ALIGNMENT, int CHUNK_SIZE, class CAllocator, bool GROWMODE = false, int COMPACT_THRESHOLD = 4 >
|
||||
class CAlignedMemPool
|
||||
{
|
||||
enum
|
||||
{
|
||||
BLOCK_SIZE = COMPILETIME_MAX( ALIGN_VALUE( ITEM_SIZE, ALIGNMENT ), 8 ),
|
||||
};
|
||||
|
||||
public:
|
||||
CAlignedMemPool();
|
||||
|
||||
void *Alloc();
|
||||
void Free( void *p );
|
||||
|
||||
static int __cdecl CompareChunk( void * const *ppLeft, void * const *ppRight );
|
||||
void Compact();
|
||||
|
||||
int NumTotal() { AUTO_LOCK( m_mutex ); return m_Chunks.Count() * ( CHUNK_SIZE / BLOCK_SIZE ); }
|
||||
int NumAllocated() { AUTO_LOCK( m_mutex ); return NumTotal() - m_nFree; }
|
||||
int NumFree() { AUTO_LOCK( m_mutex ); return m_nFree; }
|
||||
|
||||
int BytesTotal() { AUTO_LOCK( m_mutex ); return NumTotal() * BLOCK_SIZE; }
|
||||
int BytesAllocated() { AUTO_LOCK( m_mutex ); return NumAllocated() * BLOCK_SIZE; }
|
||||
int BytesFree() { AUTO_LOCK( m_mutex ); return NumFree() * BLOCK_SIZE; }
|
||||
|
||||
int ItemSize() { return ITEM_SIZE; }
|
||||
int BlockSize() { return BLOCK_SIZE; }
|
||||
int ChunkSize() { return CHUNK_SIZE; }
|
||||
|
||||
private:
|
||||
struct FreeBlock_t
|
||||
{
|
||||
FreeBlock_t *pNext;
|
||||
byte reserved[ BLOCK_SIZE - sizeof( FreeBlock_t *) ];
|
||||
};
|
||||
|
||||
CUtlVector<void *> m_Chunks; // Chunks are tracked outside blocks (unlike CUtlMemoryPool) to simplify alignment issues
|
||||
FreeBlock_t * m_pFirstFree;
|
||||
int m_nFree;
|
||||
CAllocator m_Allocator;
|
||||
double m_TimeLastCompact;
|
||||
|
||||
CThreadFastMutex m_mutex;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Pool variant using standard allocation
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T, int nInitialCount = 0, bool bDefCreateNewIfEmpty = true >
|
||||
class CObjectPool
|
||||
{
|
||||
public:
|
||||
CObjectPool()
|
||||
{
|
||||
int i = nInitialCount;
|
||||
while ( i-- > 0 )
|
||||
{
|
||||
m_AvailableObjects.PushItem( new T );
|
||||
}
|
||||
}
|
||||
|
||||
~CObjectPool()
|
||||
{
|
||||
Purge();
|
||||
}
|
||||
|
||||
int NumAvailable()
|
||||
{
|
||||
return m_AvailableObjects.Count();
|
||||
}
|
||||
|
||||
void Purge()
|
||||
{
|
||||
T *p = NULL;
|
||||
while ( m_AvailableObjects.PopItem( &p ) )
|
||||
{
|
||||
delete p;
|
||||
}
|
||||
}
|
||||
|
||||
T *GetObject( bool bCreateNewIfEmpty = bDefCreateNewIfEmpty )
|
||||
{
|
||||
T *p = NULL;
|
||||
if ( !m_AvailableObjects.PopItem( &p ) )
|
||||
{
|
||||
p = ( bCreateNewIfEmpty ) ? new T : NULL;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void PutObject( T *p )
|
||||
{
|
||||
m_AvailableObjects.PushItem( p );
|
||||
}
|
||||
|
||||
private:
|
||||
CTSList<T *> m_AvailableObjects;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Fixed budget pool with overflow to malloc
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t PROVIDED_ITEM_SIZE, int ITEM_COUNT>
|
||||
class CFixedBudgetMemoryPool
|
||||
{
|
||||
public:
|
||||
CFixedBudgetMemoryPool()
|
||||
{
|
||||
m_pBase = m_pLimit = 0;
|
||||
COMPILE_TIME_ASSERT( ITEM_SIZE % 4 == 0 );
|
||||
}
|
||||
|
||||
bool Owns( void *p )
|
||||
{
|
||||
return ( p >= m_pBase && p < m_pLimit );
|
||||
}
|
||||
|
||||
void *Alloc()
|
||||
{
|
||||
MEM_ALLOC_CREDIT_CLASS();
|
||||
#ifndef USE_MEM_DEBUG
|
||||
if ( !m_pBase )
|
||||
{
|
||||
LOCAL_THREAD_LOCK();
|
||||
if ( !m_pBase )
|
||||
{
|
||||
byte *pMemory = m_pBase = (byte *)malloc( ITEM_COUNT * ITEM_SIZE );
|
||||
m_pLimit = m_pBase + ( ITEM_COUNT * ITEM_SIZE );
|
||||
|
||||
for ( int i = 0; i < ITEM_COUNT; i++ )
|
||||
{
|
||||
m_freeList.Push( (TSLNodeBase_t *)pMemory );
|
||||
pMemory += ITEM_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *p = m_freeList.Pop();
|
||||
if ( p )
|
||||
return p;
|
||||
#endif
|
||||
return malloc( ITEM_SIZE );
|
||||
}
|
||||
|
||||
void Free( void *p )
|
||||
{
|
||||
#ifndef USE_MEM_DEBUG
|
||||
if ( Owns( p ) )
|
||||
m_freeList.Push( (TSLNodeBase_t *)p );
|
||||
else
|
||||
#endif
|
||||
free( p );
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
#ifndef USE_MEM_DEBUG
|
||||
if ( m_pBase )
|
||||
{
|
||||
free( m_pBase );
|
||||
}
|
||||
m_pBase = m_pLimit = 0;
|
||||
Construct( &m_freeList );
|
||||
#endif
|
||||
}
|
||||
|
||||
bool IsEmpty()
|
||||
{
|
||||
#ifndef USE_MEM_DEBUG
|
||||
if ( m_pBase && m_freeList.Count() != ITEM_COUNT )
|
||||
return false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
ITEM_SIZE = ALIGN_VALUE( PROVIDED_ITEM_SIZE, TSLIST_NODE_ALIGNMENT )
|
||||
};
|
||||
|
||||
CTSListBase m_freeList;
|
||||
byte *m_pBase;
|
||||
byte *m_pLimit;
|
||||
};
|
||||
|
||||
#define BIND_TO_FIXED_BUDGET_POOL( poolName ) \
|
||||
inline void* operator new( size_t size ) { return poolName.Alloc(); } \
|
||||
inline void* operator new( size_t size, int nBlockUse, const char *pFileName, int nLine ) { return poolName.Alloc(); } \
|
||||
inline void operator delete( void* p ) { poolName.Free(p); } \
|
||||
inline void operator delete( void* p, int nBlockUse, const char *pFileName, int nLine ) { poolName.Free(p); }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
template< class T >
|
||||
inline T* CClassMemoryPool<T>::Alloc()
|
||||
{
|
||||
T *pRet;
|
||||
|
||||
{
|
||||
MEM_ALLOC_CREDIT_CLASS();
|
||||
pRet = (T*)CUtlMemoryPool::Alloc();
|
||||
}
|
||||
|
||||
if ( pRet )
|
||||
{
|
||||
Construct( pRet );
|
||||
}
|
||||
return pRet;
|
||||
}
|
||||
|
||||
template< class T >
|
||||
inline T* CClassMemoryPool<T>::AllocZero()
|
||||
{
|
||||
T *pRet;
|
||||
|
||||
{
|
||||
MEM_ALLOC_CREDIT_CLASS();
|
||||
pRet = (T*)CUtlMemoryPool::AllocZero();
|
||||
}
|
||||
|
||||
if ( pRet )
|
||||
{
|
||||
Construct( pRet );
|
||||
}
|
||||
return pRet;
|
||||
}
|
||||
|
||||
template< class T >
|
||||
inline void CClassMemoryPool<T>::Free(T *pMem)
|
||||
{
|
||||
if ( pMem )
|
||||
{
|
||||
Destruct( pMem );
|
||||
}
|
||||
|
||||
CUtlMemoryPool::Free( pMem );
|
||||
}
|
||||
|
||||
template< class T >
|
||||
inline void CClassMemoryPool<T>::Clear()
|
||||
{
|
||||
CUtlRBTree<void *> freeBlocks;
|
||||
SetDefLessFunc( freeBlocks );
|
||||
|
||||
void *pCurFree = m_pHeadOfFreeList;
|
||||
while ( pCurFree != NULL )
|
||||
{
|
||||
freeBlocks.Insert( pCurFree );
|
||||
pCurFree = *((void**)pCurFree);
|
||||
}
|
||||
|
||||
for( CBlob *pCur=m_BlobHead.m_pNext; pCur != &m_BlobHead; pCur=pCur->m_pNext )
|
||||
{
|
||||
T *p = (T *)pCur->m_Data;
|
||||
T *pLimit = (T *)(pCur->m_Data + pCur->m_NumBytes);
|
||||
while ( p < pLimit )
|
||||
{
|
||||
if ( freeBlocks.Find( p ) == freeBlocks.InvalidIndex() )
|
||||
{
|
||||
Destruct( p );
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
CUtlMemoryPool::Clear();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Macros that make it simple to make a class use a fixed-size allocator
|
||||
// Put DECLARE_FIXEDSIZE_ALLOCATOR in the private section of a class,
|
||||
// Put DEFINE_FIXEDSIZE_ALLOCATOR in the CPP file
|
||||
//-----------------------------------------------------------------------------
|
||||
#define DECLARE_FIXEDSIZE_ALLOCATOR( _class ) \
|
||||
public: \
|
||||
inline void* operator new( size_t size ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_Allocator.Alloc(size); } \
|
||||
inline void* operator new( size_t size, int nBlockUse, const char *pFileName, int nLine ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_Allocator.Alloc(size); } \
|
||||
inline void operator delete( void* p ) { s_Allocator.Free(p); } \
|
||||
inline void operator delete( void* p, int nBlockUse, const char *pFileName, int nLine ) { s_Allocator.Free(p); } \
|
||||
private: \
|
||||
static CUtlMemoryPool s_Allocator
|
||||
|
||||
#define DEFINE_FIXEDSIZE_ALLOCATOR( _class, _initsize, _grow ) \
|
||||
CUtlMemoryPool _class::s_Allocator(sizeof(_class), _initsize, _grow, #_class " pool")
|
||||
|
||||
#define DEFINE_FIXEDSIZE_ALLOCATOR_ALIGNED( _class, _initsize, _grow, _alignment ) \
|
||||
CUtlMemoryPool _class::s_Allocator(sizeof(_class), _initsize, _grow, #_class " pool", _alignment )
|
||||
|
||||
#define DECLARE_FIXEDSIZE_ALLOCATOR_MT( _class ) \
|
||||
public: \
|
||||
inline void* operator new( size_t size ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_Allocator.Alloc(size); } \
|
||||
inline void* operator new( size_t size, int nBlockUse, const char *pFileName, int nLine ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_Allocator.Alloc(size); } \
|
||||
inline void operator delete( void* p ) { s_Allocator.Free(p); } \
|
||||
inline void operator delete( void* p, int nBlockUse, const char *pFileName, int nLine ) { s_Allocator.Free(p); } \
|
||||
private: \
|
||||
static CMemoryPoolMT s_Allocator
|
||||
|
||||
#define DEFINE_FIXEDSIZE_ALLOCATOR_MT( _class, _initsize, _grow ) \
|
||||
CMemoryPoolMT _class::s_Allocator(sizeof(_class), _initsize, _grow, #_class " pool")
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Macros that make it simple to make a class use a fixed-size allocator
|
||||
// This version allows us to use a memory pool which is externally defined...
|
||||
// Put DECLARE_FIXEDSIZE_ALLOCATOR_EXTERNAL in the private section of a class,
|
||||
// Put DEFINE_FIXEDSIZE_ALLOCATOR_EXTERNAL in the CPP file
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define DECLARE_FIXEDSIZE_ALLOCATOR_EXTERNAL( _class ) \
|
||||
public: \
|
||||
inline void* operator new( size_t size ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_pAllocator->Alloc(size); } \
|
||||
inline void* operator new( size_t size, int nBlockUse, const char *pFileName, int nLine ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_pAllocator->Alloc(size); } \
|
||||
inline void operator delete( void* p ) { s_pAllocator->Free(p); } \
|
||||
private: \
|
||||
static CUtlMemoryPool* s_pAllocator
|
||||
|
||||
#define DEFINE_FIXEDSIZE_ALLOCATOR_EXTERNAL( _class, _allocator ) \
|
||||
CUtlMemoryPool* _class::s_pAllocator = _allocator
|
||||
|
||||
|
||||
template <int ITEM_SIZE, int ALIGNMENT, int CHUNK_SIZE, class CAllocator, bool GROWMODE, int COMPACT_THRESHOLD >
|
||||
inline CAlignedMemPool<ITEM_SIZE, ALIGNMENT, CHUNK_SIZE, CAllocator, GROWMODE, COMPACT_THRESHOLD>::CAlignedMemPool()
|
||||
: m_pFirstFree( 0 ),
|
||||
m_nFree( 0 ),
|
||||
m_TimeLastCompact( 0 )
|
||||
{
|
||||
COMPILE_TIME_ASSERT( sizeof( FreeBlock_t ) >= BLOCK_SIZE );
|
||||
COMPILE_TIME_ASSERT( ALIGN_VALUE( sizeof( FreeBlock_t ), ALIGNMENT ) == sizeof( FreeBlock_t ) );
|
||||
}
|
||||
|
||||
template <int ITEM_SIZE, int ALIGNMENT, int CHUNK_SIZE, class CAllocator, bool GROWMODE, int COMPACT_THRESHOLD >
|
||||
inline void *CAlignedMemPool<ITEM_SIZE, ALIGNMENT, CHUNK_SIZE, CAllocator, GROWMODE, COMPACT_THRESHOLD>::Alloc()
|
||||
{
|
||||
AUTO_LOCK( m_mutex );
|
||||
|
||||
if ( !m_pFirstFree )
|
||||
{
|
||||
if ( !GROWMODE && m_Chunks.Count() )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FreeBlock_t *pNew = (FreeBlock_t *)m_Allocator.Alloc( CHUNK_SIZE );
|
||||
Assert( (unsigned)pNew % ALIGNMENT == 0 );
|
||||
m_Chunks.AddToTail( pNew );
|
||||
m_nFree = CHUNK_SIZE / BLOCK_SIZE;
|
||||
m_pFirstFree = pNew;
|
||||
for ( int i = 0; i < m_nFree - 1; i++ )
|
||||
{
|
||||
pNew->pNext = pNew + 1;
|
||||
pNew++;
|
||||
}
|
||||
pNew->pNext = NULL;
|
||||
}
|
||||
|
||||
void *p = m_pFirstFree;
|
||||
m_pFirstFree = m_pFirstFree->pNext;
|
||||
m_nFree--;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
template <int ITEM_SIZE, int ALIGNMENT, int CHUNK_SIZE, class CAllocator, bool GROWMODE, int COMPACT_THRESHOLD >
|
||||
inline void CAlignedMemPool<ITEM_SIZE, ALIGNMENT, CHUNK_SIZE, CAllocator, GROWMODE, COMPACT_THRESHOLD>::Free( void *p )
|
||||
{
|
||||
AUTO_LOCK( m_mutex );
|
||||
|
||||
// Insertion sort to encourage allocation clusters in chunks
|
||||
FreeBlock_t *pFree = ((FreeBlock_t *)p);
|
||||
FreeBlock_t *pCur = m_pFirstFree;
|
||||
FreeBlock_t *pPrev = NULL;
|
||||
|
||||
while ( pCur && pFree > pCur )
|
||||
{
|
||||
pPrev = pCur;
|
||||
pCur = pCur->pNext;
|
||||
}
|
||||
|
||||
pFree->pNext = pCur;
|
||||
|
||||
if ( pPrev )
|
||||
{
|
||||
pPrev->pNext = pFree;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pFirstFree = pFree;
|
||||
}
|
||||
m_nFree++;
|
||||
|
||||
if ( m_nFree >= ( CHUNK_SIZE / BLOCK_SIZE ) * COMPACT_THRESHOLD )
|
||||
{
|
||||
double time = Plat_FloatTime();
|
||||
double compactTime = ( m_nFree >= ( CHUNK_SIZE / BLOCK_SIZE ) * COMPACT_THRESHOLD * 4 ) ? 15.0 : 30.0;
|
||||
if ( m_TimeLastCompact > time || m_TimeLastCompact + compactTime < time )
|
||||
{
|
||||
Compact();
|
||||
m_TimeLastCompact = time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <int ITEM_SIZE, int ALIGNMENT, int CHUNK_SIZE, class CAllocator, bool GROWMODE, int COMPACT_THRESHOLD >
|
||||
inline int __cdecl CAlignedMemPool<ITEM_SIZE, ALIGNMENT, CHUNK_SIZE, CAllocator, GROWMODE, COMPACT_THRESHOLD>::CompareChunk( void * const *ppLeft, void * const *ppRight )
|
||||
{
|
||||
return ((unsigned)*ppLeft) - ((unsigned)*ppRight);
|
||||
}
|
||||
|
||||
template <int ITEM_SIZE, int ALIGNMENT, int CHUNK_SIZE, class CAllocator, bool GROWMODE, int COMPACT_THRESHOLD >
|
||||
inline void CAlignedMemPool<ITEM_SIZE, ALIGNMENT, CHUNK_SIZE, CAllocator, GROWMODE, COMPACT_THRESHOLD>::Compact()
|
||||
{
|
||||
FreeBlock_t *pCur = m_pFirstFree;
|
||||
FreeBlock_t *pPrev = NULL;
|
||||
|
||||
m_Chunks.Sort( CompareChunk );
|
||||
|
||||
#ifdef VALIDATE_ALIGNED_MEM_POOL
|
||||
{
|
||||
FreeBlock_t *p = m_pFirstFree;
|
||||
while ( p )
|
||||
{
|
||||
if ( p->pNext && p > p->pNext )
|
||||
{
|
||||
__asm { int 3 }
|
||||
}
|
||||
p = p->pNext;
|
||||
}
|
||||
|
||||
for ( int i = 0; i < m_Chunks.Count(); i++ )
|
||||
{
|
||||
if ( i + 1 < m_Chunks.Count() )
|
||||
{
|
||||
if ( m_Chunks[i] > m_Chunks[i + 1] )
|
||||
{
|
||||
__asm { int 3 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < m_Chunks.Count(); i++ )
|
||||
{
|
||||
int nBlocksPerChunk = CHUNK_SIZE / BLOCK_SIZE;
|
||||
FreeBlock_t *pChunkLimit = ((FreeBlock_t *)m_Chunks[i]) + nBlocksPerChunk;
|
||||
int nFromChunk = 0;
|
||||
if ( pCur == m_Chunks[i] )
|
||||
{
|
||||
FreeBlock_t *pFirst = pCur;
|
||||
while ( pCur && pCur >= m_Chunks[i] && pCur < pChunkLimit )
|
||||
{
|
||||
pCur = pCur->pNext;
|
||||
nFromChunk++;
|
||||
}
|
||||
pCur = pFirst;
|
||||
|
||||
}
|
||||
|
||||
while ( pCur && pCur >= m_Chunks[i] && pCur < pChunkLimit )
|
||||
{
|
||||
if ( nFromChunk != nBlocksPerChunk )
|
||||
{
|
||||
if ( pPrev )
|
||||
{
|
||||
pPrev->pNext = pCur;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pFirstFree = pCur;
|
||||
}
|
||||
pPrev = pCur;
|
||||
}
|
||||
else if ( pPrev )
|
||||
{
|
||||
pPrev->pNext = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pFirstFree = NULL;
|
||||
}
|
||||
|
||||
pCur = pCur->pNext;
|
||||
}
|
||||
|
||||
if ( nFromChunk == nBlocksPerChunk )
|
||||
{
|
||||
m_Allocator.Free( m_Chunks[i] );
|
||||
m_nFree -= nBlocksPerChunk;
|
||||
m_Chunks[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = m_Chunks.Count() - 1; i >= 0 ; i-- )
|
||||
{
|
||||
if ( !m_Chunks[i] )
|
||||
{
|
||||
m_Chunks.FastRemove( i );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MEMPOOL_H
|
||||
Vendored
+348
@@ -0,0 +1,348 @@
|
||||
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose: A fast stack memory allocator that uses virtual memory if available
|
||||
//
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef MEMSTACK_H
|
||||
#define MEMSTACK_H
|
||||
|
||||
#if defined( _WIN32 )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "tier1/utlvector.h"
|
||||
|
||||
#if defined( _WIN32 ) || defined( _PS3 )
|
||||
#define MEMSTACK_VIRTUAL_MEMORY_AVAILABLE
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
typedef unsigned MemoryStackMark_t;
|
||||
|
||||
class CMemoryStack
|
||||
{
|
||||
public:
|
||||
CMemoryStack();
|
||||
~CMemoryStack();
|
||||
|
||||
bool Init( const char *pszAllocOwner, unsigned maxSize = 0, unsigned commitSize = 0, unsigned initialCommit = 0, unsigned alignment = 16 );
|
||||
#ifdef _GAMECONSOLE
|
||||
bool InitPhysical( const char *pszAllocOwner, uint size, uint nBaseAddrAlignment, uint alignment = 16, uint32 nAdditionalFlags = 0 );
|
||||
#endif
|
||||
void Term();
|
||||
|
||||
int GetSize();
|
||||
int GetMaxSize();
|
||||
int GetUsed();
|
||||
|
||||
void *Alloc( unsigned bytes, bool bClear = false ) RESTRICT;
|
||||
|
||||
MemoryStackMark_t GetCurrentAllocPoint();
|
||||
void FreeToAllocPoint( MemoryStackMark_t mark, bool bDecommit = true );
|
||||
void FreeAll( bool bDecommit = true );
|
||||
|
||||
void Access( void **ppRegion, unsigned *pBytes );
|
||||
|
||||
void PrintContents();
|
||||
|
||||
void *GetBase();
|
||||
const void *GetBase() const { return const_cast<CMemoryStack *>(this)->GetBase(); }
|
||||
|
||||
bool CommitSize( int );
|
||||
|
||||
void SetAllocOwner( const char *pszAllocOwner );
|
||||
|
||||
private:
|
||||
bool CommitTo( byte * ) RESTRICT;
|
||||
void RegisterAllocation();
|
||||
void RegisterDeallocation( bool bShouldSpew );
|
||||
|
||||
byte *m_pNextAlloc;
|
||||
byte *m_pCommitLimit;
|
||||
byte *m_pAllocLimit;
|
||||
|
||||
byte *m_pBase;
|
||||
bool m_bRegisteredAllocation;
|
||||
bool m_bPhysical;
|
||||
char *m_pszAllocOwner;
|
||||
|
||||
unsigned m_maxSize;
|
||||
unsigned m_alignment;
|
||||
#ifdef MEMSTACK_VIRTUAL_MEMORY_AVAILABLE
|
||||
unsigned m_commitSize;
|
||||
unsigned m_minCommit;
|
||||
#endif
|
||||
#if defined( MEMSTACK_VIRTUAL_MEMORY_AVAILABLE ) && defined( _PS3 )
|
||||
IVirtualMemorySection *m_pVirtualMemorySection;
|
||||
#endif
|
||||
};
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
FORCEINLINE void *CMemoryStack::Alloc( unsigned bytes, bool bClear ) RESTRICT
|
||||
{
|
||||
Assert( m_pBase );
|
||||
|
||||
bytes = MAX( bytes, m_alignment );
|
||||
bytes = AlignValue( bytes, m_alignment );
|
||||
|
||||
void *pResult = m_pNextAlloc;
|
||||
byte *pNextAlloc = m_pNextAlloc + bytes;
|
||||
|
||||
if ( pNextAlloc > m_pCommitLimit )
|
||||
{
|
||||
if ( !CommitTo( pNextAlloc ) )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ( bClear )
|
||||
{
|
||||
memset( pResult, 0, bytes );
|
||||
}
|
||||
|
||||
m_pNextAlloc = pNextAlloc;
|
||||
|
||||
return pResult;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
inline bool CMemoryStack::CommitSize( int nBytes )
|
||||
{
|
||||
if ( GetSize() != nBytes )
|
||||
{
|
||||
return CommitTo( m_pBase + nBytes );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
inline int CMemoryStack::GetMaxSize()
|
||||
{
|
||||
return m_maxSize;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
inline int CMemoryStack::GetUsed()
|
||||
{
|
||||
return ( m_pNextAlloc - m_pBase );
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
inline void *CMemoryStack::GetBase()
|
||||
{
|
||||
return m_pBase;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
inline MemoryStackMark_t CMemoryStack::GetCurrentAllocPoint()
|
||||
{
|
||||
return ( m_pNextAlloc - m_pBase );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The CUtlMemoryStack class:
|
||||
// A fixed memory class
|
||||
//-----------------------------------------------------------------------------
|
||||
template< typename T, typename I, size_t MAX_SIZE, size_t COMMIT_SIZE = 0, size_t INITIAL_COMMIT = 0 >
|
||||
class CUtlMemoryStack
|
||||
{
|
||||
public:
|
||||
// constructor, destructor
|
||||
CUtlMemoryStack( int nGrowSize = 0, int nInitSize = 0 ) { m_MemoryStack.Init( "CUtlMemoryStack", MAX_SIZE * sizeof(T), COMMIT_SIZE * sizeof(T), INITIAL_COMMIT * sizeof(T), 4 ); COMPILE_TIME_ASSERT( sizeof(T) % 4 == 0 ); }
|
||||
CUtlMemoryStack( T* pMemory, int numElements ) { Assert( 0 ); }
|
||||
|
||||
// Can we use this index?
|
||||
bool IsIdxValid( I i ) const { long x=i; return (x >= 0) && (x < m_nAllocated); }
|
||||
|
||||
// Specify the invalid ('null') index that we'll only return on failure
|
||||
static const I INVALID_INDEX = ( I )-1; // For use with COMPILE_TIME_ASSERT
|
||||
static I InvalidIndex() { return INVALID_INDEX; }
|
||||
|
||||
class Iterator_t
|
||||
{
|
||||
Iterator_t( I i ) : index( i ) {}
|
||||
I index;
|
||||
friend class CUtlMemoryStack<T,I,MAX_SIZE, COMMIT_SIZE, INITIAL_COMMIT>;
|
||||
public:
|
||||
bool operator==( const Iterator_t it ) const { return index == it.index; }
|
||||
bool operator!=( const Iterator_t it ) const { return index != it.index; }
|
||||
};
|
||||
Iterator_t First() const { return Iterator_t( m_nAllocated ? 0 : InvalidIndex() ); }
|
||||
Iterator_t Next( const Iterator_t &it ) const { return Iterator_t( it.index < m_nAllocated ? it.index + 1 : InvalidIndex() ); }
|
||||
I GetIndex( const Iterator_t &it ) const { return it.index; }
|
||||
bool IsIdxAfter( I i, const Iterator_t &it ) const { return i > it.index; }
|
||||
bool IsValidIterator( const Iterator_t &it ) const { long x=it.index; return x >= 0 && x < m_nAllocated; }
|
||||
Iterator_t InvalidIterator() const { return Iterator_t( InvalidIndex() ); }
|
||||
|
||||
// Gets the base address
|
||||
T* Base() { return (T*)m_MemoryStack.GetBase(); }
|
||||
const T* Base() const { return (const T*)m_MemoryStack.GetBase(); }
|
||||
|
||||
// element access
|
||||
T& operator[]( I i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
|
||||
const T& operator[]( I i ) const { Assert( IsIdxValid(i) ); return Base()[i]; }
|
||||
T& Element( I i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
|
||||
const T& Element( I i ) const { Assert( IsIdxValid(i) ); return Base()[i]; }
|
||||
|
||||
// Attaches the buffer to external memory....
|
||||
void SetExternalBuffer( T* pMemory, int numElements ) { Assert( 0 ); }
|
||||
|
||||
// Size
|
||||
int NumAllocated() const { return m_nAllocated; }
|
||||
int Count() const { return m_nAllocated; }
|
||||
|
||||
// Grows the memory, so that at least allocated + num elements are allocated
|
||||
void Grow( int num = 1 ) { Assert( num > 0 ); m_nAllocated += num; m_MemoryStack.Alloc( num * sizeof(T) ); }
|
||||
|
||||
// Makes sure we've got at least this much memory
|
||||
void EnsureCapacity( int num ) { Assert( num <= MAX_SIZE ); if ( m_nAllocated < num ) Grow( num - m_nAllocated ); }
|
||||
|
||||
// Memory deallocation
|
||||
void Purge() { m_MemoryStack.FreeAll(); m_nAllocated = 0; }
|
||||
|
||||
// is the memory externally allocated?
|
||||
bool IsExternallyAllocated() const { return false; }
|
||||
|
||||
// Set the size by which the memory grows
|
||||
void SetGrowSize( int size ) { Assert( 0 ); }
|
||||
|
||||
// Identify the owner of this memory stack's memory
|
||||
void SetAllocOwner( const char *pszAllocOwner ) { m_MemoryStack.SetAllocOwner( pszAllocOwner ); }
|
||||
|
||||
private:
|
||||
CMemoryStack m_MemoryStack;
|
||||
int m_nAllocated;
|
||||
};
|
||||
|
||||
|
||||
#ifdef _X360
|
||||
//-----------------------------------------------------------------------------
|
||||
// A memory stack used for allocating physical memory on the 360
|
||||
// Usage pattern anticipates we usually never go over the initial allocation
|
||||
// When we do so, we're ok with slightly slower allocation
|
||||
//-----------------------------------------------------------------------------
|
||||
class CPhysicalMemoryStack
|
||||
{
|
||||
public:
|
||||
CPhysicalMemoryStack();
|
||||
~CPhysicalMemoryStack();
|
||||
|
||||
// The physical memory stack is allocated in chunks. We will initially
|
||||
// allocate nInitChunkCount chunks, which will always be in memory.
|
||||
// When FreeAll() is called, it will free down to the initial chunk count
|
||||
// but not below it.
|
||||
bool Init( size_t nChunkSizeInBytes, size_t nAlignment, int nInitialChunkCount, uint32 nAdditionalFlags );
|
||||
void Term();
|
||||
|
||||
size_t GetSize() const;
|
||||
size_t GetPeakUsed() const;
|
||||
size_t GetUsed() const;
|
||||
size_t GetFramePeakUsed() const;
|
||||
|
||||
MemoryStackMark_t GetCurrentAllocPoint() const;
|
||||
void FreeToAllocPoint( MemoryStackMark_t mark, bool bUnused = true ); // bUnused is for interface compat with CMemoryStack
|
||||
void *Alloc( size_t nSizeInBytes, bool bClear = false ) RESTRICT;
|
||||
void FreeAll( bool bUnused = true ); // bUnused is for interface compat with CMemoryStack
|
||||
|
||||
void PrintContents();
|
||||
|
||||
private:
|
||||
void *AllocFromOverflow( size_t nSizeInBytes );
|
||||
|
||||
struct PhysicalChunk_t
|
||||
{
|
||||
uint8 *m_pBase;
|
||||
uint8 *m_pNextAlloc;
|
||||
uint8 *m_pAllocLimit;
|
||||
};
|
||||
|
||||
PhysicalChunk_t m_InitialChunk;
|
||||
CUtlVector< PhysicalChunk_t > m_ExtraChunks;
|
||||
size_t m_nUsage;
|
||||
size_t m_nFramePeakUsage;
|
||||
size_t m_nPeakUsage;
|
||||
size_t m_nAlignment;
|
||||
size_t m_nChunkSizeInBytes;
|
||||
int m_nFirstAvailableChunk;
|
||||
int m_nAdditionalFlags;
|
||||
PhysicalChunk_t *m_pLastAllocedChunk;
|
||||
};
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
FORCEINLINE void *CPhysicalMemoryStack::Alloc( size_t nSizeInBytes, bool bClear ) RESTRICT
|
||||
{
|
||||
if ( nSizeInBytes )
|
||||
{
|
||||
nSizeInBytes = AlignValue( nSizeInBytes, m_nAlignment );
|
||||
}
|
||||
else
|
||||
{
|
||||
nSizeInBytes = m_nAlignment;
|
||||
}
|
||||
|
||||
// Can't do an allocation bigger than the chunk size
|
||||
Assert( nSizeInBytes <= m_nChunkSizeInBytes );
|
||||
|
||||
void *pResult = m_InitialChunk.m_pNextAlloc;
|
||||
uint8 *pNextAlloc = m_InitialChunk.m_pNextAlloc + nSizeInBytes;
|
||||
if ( pNextAlloc <= m_InitialChunk.m_pAllocLimit )
|
||||
{
|
||||
m_InitialChunk.m_pNextAlloc = pNextAlloc;
|
||||
m_pLastAllocedChunk = &m_InitialChunk;
|
||||
}
|
||||
else
|
||||
{
|
||||
pResult = AllocFromOverflow( nSizeInBytes );
|
||||
}
|
||||
|
||||
m_nUsage += nSizeInBytes;
|
||||
m_nFramePeakUsage = MAX( m_nUsage, m_nFramePeakUsage );
|
||||
m_nPeakUsage = MAX( m_nUsage, m_nPeakUsage );
|
||||
|
||||
if ( bClear )
|
||||
{
|
||||
memset( pResult, 0, nSizeInBytes );
|
||||
}
|
||||
|
||||
return pResult;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
inline size_t CPhysicalMemoryStack::GetPeakUsed() const
|
||||
{
|
||||
return m_nPeakUsage;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
inline size_t CPhysicalMemoryStack::GetUsed() const
|
||||
{
|
||||
return m_nUsage;
|
||||
}
|
||||
|
||||
inline size_t CPhysicalMemoryStack::GetFramePeakUsed() const
|
||||
{
|
||||
return m_nFramePeakUsage;
|
||||
}
|
||||
|
||||
inline MemoryStackMark_t CPhysicalMemoryStack::GetCurrentAllocPoint() const
|
||||
{
|
||||
Assert( m_pLastAllocedChunk );
|
||||
return ( m_pLastAllocedChunk->m_pNextAlloc - m_pLastAllocedChunk->m_pBase );
|
||||
}
|
||||
|
||||
#endif // _X360
|
||||
|
||||
#endif // MEMSTACK_H
|
||||
Vendored
+73
@@ -0,0 +1,73 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// netadr.h
|
||||
#ifndef NETADR_H
|
||||
#define NETADR_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "tier0/platform.h"
|
||||
#undef SetPort
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NA_NULL = 0,
|
||||
NA_LOOPBACK,
|
||||
NA_BROADCAST,
|
||||
NA_IP,
|
||||
} netadrtype_t;
|
||||
|
||||
struct netadr_t
|
||||
{
|
||||
public:
|
||||
netadr_t() { SetIP( 0 ); SetPort( 0 ); SetType( NA_IP ); }
|
||||
netadr_t( uint unIP, uint16 usPort ) { SetIP( unIP ); SetPort( usPort ); SetType( NA_IP ); }
|
||||
netadr_t( const char *pch ) { SetFromString( pch ); }
|
||||
void Clear(); // invalids Address
|
||||
|
||||
void SetType( netadrtype_t type );
|
||||
void SetPort( unsigned short port );
|
||||
bool SetFromSockadr(const struct sockaddr *s);
|
||||
void SetIP(uint8 b1, uint8 b2, uint8 b3, uint8 b4);
|
||||
void SetIP(uint unIP); // Sets IP. unIP is in host order (little-endian)
|
||||
void SetIPAndPort( uint unIP, unsigned short usPort ) { SetIP( unIP ); SetPort( usPort ); }
|
||||
void SetFromString(const char *pch, bool bUseDNS = false ); // if bUseDNS is true then do a DNS lookup if needed
|
||||
|
||||
bool CompareAdr (const netadr_t &a, bool onlyBase = false) const;
|
||||
bool CompareClassBAdr (const netadr_t &a) const;
|
||||
bool CompareClassCAdr (const netadr_t &a) const;
|
||||
|
||||
netadrtype_t GetType() const;
|
||||
unsigned short GetPort() const;
|
||||
const char* ToString( bool onlyBase = false ) const; // returns xxx.xxx.xxx.xxx:ppppp
|
||||
void ToSockadr(struct sockaddr *s) const;
|
||||
unsigned int GetIP() const;
|
||||
|
||||
bool IsLocalhost() const; // true, if this is the localhost IP
|
||||
bool IsLoopback() const; // true if engine loopback buffers are used
|
||||
bool IsReservedAdr() const; // true, if this is a private LAN IP
|
||||
bool IsValid() const; // ip & port != 0
|
||||
bool IsBaseAdrValid() const; // ip != 0
|
||||
|
||||
void SetFromSocket( int hSocket );
|
||||
|
||||
// These function names are decorated because the Xbox360 defines macros for ntohl and htonl
|
||||
unsigned long addr_ntohl() const;
|
||||
unsigned long addr_htonl() const;
|
||||
bool operator==(const netadr_t &netadr) const {return ( CompareAdr( netadr ) );}
|
||||
bool operator<(const netadr_t &netadr) const;
|
||||
|
||||
public: // members are public to avoid to much changes
|
||||
|
||||
netadrtype_t type;
|
||||
unsigned char ip[4];
|
||||
unsigned short port;
|
||||
};
|
||||
|
||||
#endif // NETADR_H
|
||||
Vendored
+384
@@ -0,0 +1,384 @@
|
||||
//========== Copyright � 2005, Valve Corporation, All rights reserved. ========
|
||||
//
|
||||
// Purpose: Tools for correctly implementing & handling reference counted
|
||||
// objects
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef REFCOUNT_H
|
||||
#define REFCOUNT_H
|
||||
|
||||
#include "tier0/threadtools.h"
|
||||
|
||||
#if defined( _WIN32 )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Implement a standard reference counted interface. Use of this
|
||||
// is optional insofar as all the concrete tools only require
|
||||
// at compile time that the function signatures match.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class IRefCounted
|
||||
{
|
||||
public:
|
||||
virtual int AddRef() = 0;
|
||||
virtual int Release() = 0;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Release a pointer and mark it NULL
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <class REFCOUNTED_ITEM_PTR>
|
||||
inline int SafeRelease( REFCOUNTED_ITEM_PTR &pRef )
|
||||
{
|
||||
// Use funny syntax so that this works on "auto pointers"
|
||||
REFCOUNTED_ITEM_PTR *ppRef = &pRef;
|
||||
if ( *ppRef )
|
||||
{
|
||||
int result = (*ppRef)->Release();
|
||||
*ppRef = NULL;
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Maintain a reference across a scope
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <class T = IRefCounted>
|
||||
class CAutoRef
|
||||
{
|
||||
public:
|
||||
CAutoRef( T *pRef )
|
||||
: m_pRef( pRef )
|
||||
{
|
||||
if ( m_pRef )
|
||||
m_pRef->AddRef();
|
||||
}
|
||||
|
||||
~CAutoRef()
|
||||
{
|
||||
if (m_pRef)
|
||||
m_pRef->Release();
|
||||
}
|
||||
|
||||
private:
|
||||
T *m_pRef;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Do a an inline AddRef then return the pointer, useful when
|
||||
// returning an object from a function
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define RetAddRef( p ) ( (p)->AddRef(), (p) )
|
||||
#define InlineAddRef( p ) ( (p)->AddRef(), (p) )
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: A class to both hold a pointer to an object and its reference.
|
||||
// Base exists to support other cleanup models
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <class T>
|
||||
class CBaseAutoPtr
|
||||
{
|
||||
public:
|
||||
CBaseAutoPtr() : m_pObject(0) {}
|
||||
CBaseAutoPtr(T *pFrom) : m_pObject(pFrom) {}
|
||||
|
||||
operator const void *() const { return m_pObject; }
|
||||
operator void *() { return m_pObject; }
|
||||
|
||||
operator const T *() const { return m_pObject; }
|
||||
operator const T *() { return m_pObject; }
|
||||
operator T *() { return m_pObject; }
|
||||
|
||||
int operator=( int i ) { AssertMsg( i == 0, "Only NULL allowed on integer assign" ); m_pObject = 0; return 0; }
|
||||
T * operator=( T *p ) { m_pObject = p; return p; }
|
||||
|
||||
bool operator !() const { return ( !m_pObject ); }
|
||||
bool operator!=( int i ) const { AssertMsg( i == 0, "Only NULL allowed on integer compare" ); return (m_pObject != NULL); }
|
||||
bool operator==( const void *p ) const { return ( m_pObject == p ); }
|
||||
bool operator!=( const void *p ) const { return ( m_pObject != p ); }
|
||||
bool operator==( T *p ) const { return operator==( (void *)p ); }
|
||||
bool operator!=( T *p ) const { return operator!=( (void *)p ); }
|
||||
bool operator==( const CBaseAutoPtr<T> &p ) const { return operator==( (const void *)p ); }
|
||||
bool operator!=( const CBaseAutoPtr<T> &p ) const { return operator!=( (const void *)p ); }
|
||||
|
||||
T * operator->() { return m_pObject; }
|
||||
T & operator *() { return *m_pObject; }
|
||||
T ** operator &() { return &m_pObject; }
|
||||
|
||||
const T * operator->() const { return m_pObject; }
|
||||
const T & operator *() const { return *m_pObject; }
|
||||
T * const * operator &() const { return &m_pObject; }
|
||||
|
||||
protected:
|
||||
CBaseAutoPtr( const CBaseAutoPtr<T> &from ) : m_pObject( from.m_pObject ) {}
|
||||
void operator=( const CBaseAutoPtr<T> &from ) { m_pObject = from.m_pObject; }
|
||||
|
||||
T *m_pObject;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
template <class T>
|
||||
class CRefPtr : public CBaseAutoPtr<T>
|
||||
{
|
||||
typedef CBaseAutoPtr<T> BaseClass;
|
||||
public:
|
||||
CRefPtr() {}
|
||||
CRefPtr( T *pInit ) : BaseClass( pInit ) {}
|
||||
CRefPtr( const CRefPtr<T> &from ) : BaseClass( from ) {}
|
||||
~CRefPtr() { if ( BaseClass::m_pObject ) BaseClass::m_pObject->Release(); }
|
||||
|
||||
void operator=( const CRefPtr<T> &from ) { BaseClass::operator=( from ); }
|
||||
|
||||
int operator=( int i ) { return BaseClass::operator=( i ); }
|
||||
T *operator=( T *p ) { return BaseClass::operator=( p ); }
|
||||
|
||||
operator bool() const { return !BaseClass::operator!(); }
|
||||
operator bool() { return !BaseClass::operator!(); }
|
||||
|
||||
void SafeRelease() { if ( BaseClass::m_pObject ) BaseClass::m_pObject->Release(); BaseClass::m_pObject = 0; }
|
||||
void AssignAddRef( T *pFrom ) { SafeRelease(); if (pFrom) pFrom->AddRef(); BaseClass::m_pObject = pFrom; }
|
||||
void AddRefAssignTo( T *&pTo ) { ::SafeRelease( pTo ); if ( BaseClass::m_pObject ) BaseClass::m_pObject->AddRef(); pTo = BaseClass::m_pObject; }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Traits classes defining reference count threading model
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class CRefMT
|
||||
{
|
||||
public:
|
||||
static int Increment( int *p) { return ThreadInterlockedIncrement( (int32 *)p ); }
|
||||
static int Decrement( int *p) { return ThreadInterlockedDecrement( (int32 *)p ); }
|
||||
};
|
||||
|
||||
class CRefST
|
||||
{
|
||||
public:
|
||||
static int Increment( int *p) { return ++(*p); }
|
||||
static int Decrement( int *p) { return --(*p); }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Actual reference counting implementation. Pulled out to reduce
|
||||
// code bloat.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <const bool bSelfDelete, typename CRefThreading = CRefMT>
|
||||
class NO_VTABLE CRefCountServiceBase
|
||||
{
|
||||
protected:
|
||||
CRefCountServiceBase()
|
||||
: m_iRefs( 1 )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~CRefCountServiceBase()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool OnFinalRelease()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int GetRefCount() const
|
||||
{
|
||||
return m_iRefs;
|
||||
}
|
||||
|
||||
int DoAddRef()
|
||||
{
|
||||
return CRefThreading::Increment( &m_iRefs );
|
||||
}
|
||||
|
||||
int DoRelease()
|
||||
{
|
||||
int result = CRefThreading::Decrement( &m_iRefs );
|
||||
if ( result )
|
||||
return result;
|
||||
if ( OnFinalRelease() && bSelfDelete )
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_iRefs;
|
||||
};
|
||||
|
||||
class CRefCountServiceNull
|
||||
{
|
||||
protected:
|
||||
static int DoAddRef() { return 1; }
|
||||
static int DoRelease() { return 1; }
|
||||
};
|
||||
|
||||
template <typename CRefThreading = CRefMT>
|
||||
class NO_VTABLE CRefCountServiceDestruct
|
||||
{
|
||||
protected:
|
||||
CRefCountServiceDestruct()
|
||||
: m_iRefs( 1 )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~CRefCountServiceDestruct()
|
||||
{
|
||||
}
|
||||
|
||||
int GetRefCount() const
|
||||
{
|
||||
return m_iRefs;
|
||||
}
|
||||
|
||||
int DoAddRef()
|
||||
{
|
||||
return CRefThreading::Increment( &m_iRefs );
|
||||
}
|
||||
|
||||
int DoRelease()
|
||||
{
|
||||
int result = CRefThreading::Decrement( &m_iRefs );
|
||||
if ( result )
|
||||
return result;
|
||||
this->~CRefCountServiceDestruct();
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_iRefs;
|
||||
};
|
||||
|
||||
|
||||
typedef CRefCountServiceBase<true, CRefST> CRefCountServiceST;
|
||||
typedef CRefCountServiceBase<false, CRefST> CRefCountServiceNoDeleteST;
|
||||
|
||||
typedef CRefCountServiceBase<true, CRefMT> CRefCountServiceMT;
|
||||
typedef CRefCountServiceBase<false, CRefMT> CRefCountServiceNoDeleteMT;
|
||||
|
||||
// Default to threadsafe
|
||||
typedef CRefCountServiceNoDeleteMT CRefCountServiceNoDelete;
|
||||
typedef CRefCountServiceMT CRefCountService;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Base classes to implement reference counting
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template < class REFCOUNT_SERVICE = CRefCountService >
|
||||
class NO_VTABLE CRefCounted : public REFCOUNT_SERVICE
|
||||
{
|
||||
public:
|
||||
virtual ~CRefCounted() {}
|
||||
int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); }
|
||||
int Release() { return REFCOUNT_SERVICE::DoRelease(); }
|
||||
};
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
template < class BASE1, class REFCOUNT_SERVICE = CRefCountService >
|
||||
class NO_VTABLE CRefCounted1 : public BASE1,
|
||||
public REFCOUNT_SERVICE
|
||||
{
|
||||
public:
|
||||
virtual ~CRefCounted1() {}
|
||||
int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); }
|
||||
int Release() { return REFCOUNT_SERVICE::DoRelease(); }
|
||||
};
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
template < class BASE1, class BASE2, class REFCOUNT_SERVICE = CRefCountService >
|
||||
class NO_VTABLE CRefCounted2 : public BASE1, public BASE2,
|
||||
public REFCOUNT_SERVICE
|
||||
{
|
||||
public:
|
||||
virtual ~CRefCounted2() {}
|
||||
int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); }
|
||||
int Release() { return REFCOUNT_SERVICE::DoRelease(); }
|
||||
};
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
template < class BASE1, class BASE2, class BASE3, class REFCOUNT_SERVICE = CRefCountService >
|
||||
class NO_VTABLE CRefCounted3 : public BASE1, public BASE2, public BASE3,
|
||||
public REFCOUNT_SERVICE
|
||||
{
|
||||
virtual ~CRefCounted3() {}
|
||||
int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); }
|
||||
int Release() { return REFCOUNT_SERVICE::DoRelease(); }
|
||||
};
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
template < class BASE1, class BASE2, class BASE3, class BASE4, class REFCOUNT_SERVICE = CRefCountService >
|
||||
class NO_VTABLE CRefCounted4 : public BASE1, public BASE2, public BASE3, public BASE4,
|
||||
public REFCOUNT_SERVICE
|
||||
{
|
||||
public:
|
||||
virtual ~CRefCounted4() {}
|
||||
int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); }
|
||||
int Release() { return REFCOUNT_SERVICE::DoRelease(); }
|
||||
};
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
template < class BASE1, class BASE2, class BASE3, class BASE4, class BASE5, class REFCOUNT_SERVICE = CRefCountService >
|
||||
class NO_VTABLE CRefCounted5 : public BASE1, public BASE2, public BASE3, public BASE4, public BASE5,
|
||||
public REFCOUNT_SERVICE
|
||||
{
|
||||
public:
|
||||
virtual ~CRefCounted5() {}
|
||||
int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); }
|
||||
int Release() { return REFCOUNT_SERVICE::DoRelease(); }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Class to throw around a reference counted item to debug
|
||||
// referencing problems
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifdef _DEBUG
|
||||
template <class BASE_REFCOUNTED, int FINAL_REFS = 0, const char *pszName = (const char *)NULL >
|
||||
class CRefDebug : public BASE_REFCOUNTED
|
||||
{
|
||||
public:
|
||||
CRefDebug()
|
||||
{
|
||||
AssertMsg( this->GetRefCount() == 1, "Expected initial ref count of 1" );
|
||||
DevMsg( "%s:create 0x%x\n", ( pszName ) ? pszName : "", this );
|
||||
}
|
||||
|
||||
virtual ~CRefDebug()
|
||||
{
|
||||
AssertDevMsg( this->GetRefCount() == FINAL_REFS, "Object still referenced on destroy?" );
|
||||
DevMsg( "%s:destroy 0x%x\n", ( pszName ) ? pszName : "", this );
|
||||
}
|
||||
|
||||
int AddRef()
|
||||
{
|
||||
DevMsg( "%s:(0x%x)->AddRef() --> %d\n", ( pszName ) ? pszName : "", this, this->GetRefCount() + 1 );
|
||||
return BASE_REFCOUNTED::AddRef();
|
||||
}
|
||||
|
||||
int Release()
|
||||
{
|
||||
DevMsg( "%s:(0x%x)->Release() --> %d\n", ( pszName ) ? pszName : "", this, this->GetRefCount() - 1 );
|
||||
Assert( this->GetRefCount() > 0 );
|
||||
return BASE_REFCOUNTED::Release();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // REFCOUNT_H
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef STRINGPOOL_H
|
||||
#define STRINGPOOL_H
|
||||
|
||||
#if defined( _WIN32 )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "utlrbtree.h"
|
||||
#include "utlvector.h"
|
||||
#include "utlbuffer.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Allocates memory for strings, checking for duplicates first,
|
||||
// reusing exising strings if duplicate found.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
enum StringPoolCase_t
|
||||
{
|
||||
StringPoolCaseInsensitive,
|
||||
StringPoolCaseSensitive
|
||||
};
|
||||
|
||||
class CStringPool
|
||||
{
|
||||
public:
|
||||
CStringPool( StringPoolCase_t caseSensitivity = StringPoolCaseInsensitive );
|
||||
~CStringPool();
|
||||
|
||||
unsigned int Count() const;
|
||||
|
||||
const char * Allocate( const char *pszValue );
|
||||
// This feature is deliberately not supported because it's pretty dangerous
|
||||
// given current uses of CStringPool, which assume they can copy string pointers without
|
||||
// any refcounts.
|
||||
//void Free( const char *pszValue );
|
||||
void FreeAll();
|
||||
|
||||
// searches for a string already in the pool
|
||||
const char * Find( const char *pszValue );
|
||||
|
||||
protected:
|
||||
typedef CUtlRBTree<const char *, unsigned short> CStrSet;
|
||||
|
||||
CStrSet m_Strings;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: A reference counted string pool.
|
||||
//
|
||||
// Elements are stored more efficiently than in the conventional string pool,
|
||||
// quicker to look up, and storage is tracked via reference counts.
|
||||
//
|
||||
// At some point this should replace CStringPool
|
||||
//-----------------------------------------------------------------------------
|
||||
class CCountedStringPool
|
||||
{
|
||||
public: // HACK, hash_item_t structure should not be public.
|
||||
|
||||
struct hash_item_t
|
||||
{
|
||||
char* pString;
|
||||
unsigned short nNextElement;
|
||||
unsigned char nReferenceCount;
|
||||
unsigned char pad;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
INVALID_ELEMENT = 0,
|
||||
MAX_REFERENCE = 0xFF,
|
||||
HASH_TABLE_SIZE = 1024
|
||||
};
|
||||
|
||||
CUtlVector<unsigned short> m_HashTable; // Points to each element
|
||||
CUtlVector<hash_item_t> m_Elements;
|
||||
unsigned short m_FreeListStart;
|
||||
StringPoolCase_t m_caseSensitivity;
|
||||
|
||||
public:
|
||||
CCountedStringPool( StringPoolCase_t caseSensitivity = StringPoolCaseInsensitive );
|
||||
virtual ~CCountedStringPool();
|
||||
|
||||
void FreeAll();
|
||||
|
||||
char *FindString( const char* pIntrinsic );
|
||||
char *ReferenceString( const char* pIntrinsic );
|
||||
void DereferenceString( const char* pIntrinsic );
|
||||
|
||||
// These are only reliable if there are less than 64k strings in your string pool
|
||||
unsigned short FindStringHandle( const char* pIntrinsic );
|
||||
unsigned short ReferenceStringHandle( const char* pIntrinsic );
|
||||
char *HandleToString( unsigned short handle );
|
||||
void SpewStrings();
|
||||
unsigned Hash( const char *pszKey );
|
||||
|
||||
bool SaveToBuffer( CUtlBuffer &buffer );
|
||||
bool RestoreFromBuffer( CUtlBuffer &buffer );};
|
||||
|
||||
#endif // STRINGPOOL_H
|
||||
Vendored
+589
@@ -0,0 +1,589 @@
|
||||
//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef TIER1_STRTOOLS_H
|
||||
#define TIER1_STRTOOLS_H
|
||||
|
||||
#include "tier0/basetypes.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#elif POSIX
|
||||
#include <ctype.h>
|
||||
#include <wchar.h>
|
||||
#include <math.h>
|
||||
#include <wctype.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
// 3d memcpy. Copy (up-to) 3 dimensional data with arbitrary source and destination
|
||||
// strides. Optimizes to just a single memcpy when possible. For 2d data, set numslices to 1.
|
||||
void CopyMemory3D( void *pDestAdr, void const *pSrcAdr,
|
||||
int nNumCols, int nNumRows, int nNumSlices, // dimensions of copy
|
||||
int nSrcBytesPerRow, int nSrcBytesPerSlice, // strides for source.
|
||||
int nDestBytesPerRow, int nDestBytesPerSlice // strides for dest
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
template< class T, class I > class CUtlMemory;
|
||||
template< class T, class A > class CUtlVector;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Portable versions of standard string functions
|
||||
//-----------------------------------------------------------------------------
|
||||
void _V_memset ( void *dest, int fill, int count );
|
||||
void _V_memcpy ( void *dest, const void *src, int count );
|
||||
void _V_memmove ( void *dest, const void *src, int count );
|
||||
int _V_memcmp ( const void *m1, const void *m2, int count );
|
||||
int _V_strlen ( const char *str );
|
||||
void _V_strcpy ( char *dest, const char *src );
|
||||
char* _V_strrchr ( const char *s, char c );
|
||||
int _V_strcmp ( const char *s1, const char *s2 );
|
||||
int _V_wcscmp ( const wchar_t *s1, const wchar_t *s2 );
|
||||
int _V_stricmp ( const char *s1, const char *s2 );
|
||||
char* _V_strstr ( const char *s1, const char *search );
|
||||
char* _V_strupr ( char *start );
|
||||
char* _V_strlower ( char *start );
|
||||
int _V_wcslen ( const wchar_t *pwch );
|
||||
|
||||
wchar_t* _V_wcslower (const char* file, int line, wchar_t *start);
|
||||
wchar_t* _V_wcsupr (const char* file, int line, wchar_t *start);
|
||||
|
||||
#ifdef POSIX
|
||||
inline char *strupr( char *start )
|
||||
{
|
||||
char *str = start;
|
||||
while( str && *str )
|
||||
{
|
||||
*str = (char)toupper(*str);
|
||||
str++;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
inline char *strlwr( char *start )
|
||||
{
|
||||
char *str = start;
|
||||
while( str && *str )
|
||||
{
|
||||
*str = (char)tolower(*str);
|
||||
str++;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
inline wchar_t *_wcslwr( wchar_t *start )
|
||||
{
|
||||
wchar_t *str = start;
|
||||
while( str && *str )
|
||||
{
|
||||
*str = (wchar_t)towlower(static_cast<wint_t>(*str));
|
||||
str++;
|
||||
}
|
||||
return start;
|
||||
};
|
||||
|
||||
inline wchar_t *_wcsupr( wchar_t *start )
|
||||
{
|
||||
wchar_t *str = start;
|
||||
while( str && *str )
|
||||
{
|
||||
*str = (wchar_t)towupper(static_cast<wint_t>(*str));
|
||||
str++;
|
||||
}
|
||||
return start;
|
||||
};
|
||||
|
||||
#endif // POSIX
|
||||
|
||||
// there are some users of these via tier1 templates in used in tier0. but tier0 can't depend on vstdlib which means in tier0 we always need the inlined ones
|
||||
#if ( !defined( TIER0_DLL_EXPORT ) )
|
||||
|
||||
#if !defined( _DEBUG ) && defined( _PS3 )
|
||||
|
||||
#include "tier1/strtools_inlines.h"
|
||||
|
||||
// To avoid cross-prx calls, making the V_* fucntions that don't do anything but debug checks and call through to the non V_* function
|
||||
// go ahead and call the non-V_* functions directly.
|
||||
#define V_memset(dest, fill, count) memset ((dest), (fill), (count))
|
||||
#define V_memcpy(dest, src, count) memcpy ((dest), (src), (count))
|
||||
#define V_memmove(dest, src, count) memmove ((dest), (src), (count))
|
||||
#define V_memcmp(m1, m2, count) memcmp ((m1), (m2), (count))
|
||||
#define V_strcpy(dest, src) strcpy ((dest), (src))
|
||||
#define V_strcmp(s1, s2) strcmp ((s1), (s2))
|
||||
#define V_strupr(start) strupr ((start))
|
||||
#define V_strlower(start) strlwr ((start))
|
||||
#define V_wcslen(pwch) wcslen ((pwch))
|
||||
// To avoid cross-prx calls, using inline versions of these custom functions:
|
||||
#define V_strlen(str) _V_strlen_inline ((str))
|
||||
#define V_strrchr(s, c) _V_strrchr_inline ((s), (c))
|
||||
#define V_wcscmp(s1, s2) _V_wcscmp_inline ((s1), (s2))
|
||||
#define V_stricmp(s1, s2 ) _V_stricmp_inline ((s1), (s2) )
|
||||
#define V_strstr(s1, search ) _V_strstr_inline ((s1), (search) )
|
||||
|
||||
#else
|
||||
|
||||
#define V_memset(dest, fill, count) _V_memset ((dest), (fill), (count))
|
||||
#define V_memcpy(dest, src, count) _V_memcpy ((dest), (src), (count))
|
||||
#define V_memmove(dest, src, count) _V_memmove ((dest), (src), (count))
|
||||
#define V_memcmp(m1, m2, count) _V_memcmp ((m1), (m2), (count))
|
||||
#define V_strlen(str) _V_strlen ((str))
|
||||
#define V_strcpy(dest, src) _V_strcpy ((dest), (src))
|
||||
#define V_strrchr(s, c) _V_strrchr ((s), (c))
|
||||
#define V_strcmp(s1, s2) _V_strcmp ((s1), (s2))
|
||||
#define V_wcscmp(s1, s2) _V_wcscmp ((s1), (s2))
|
||||
#define V_stricmp(s1, s2 ) _V_stricmp ((s1), (s2) )
|
||||
#define V_strstr(s1, search ) _V_strstr ((s1), (search) )
|
||||
#define V_strupr(start) _V_strupr ((start))
|
||||
#define V_strlower(start) _V_strlower ((start))
|
||||
#define V_wcslen(pwch) _V_wcslen ((pwch))
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
inline void V_memset (void *dest, int fill, int count) { memset( dest, fill, count ); }
|
||||
inline void V_memcpy (void *dest, const void *src, int count) { memcpy( dest, src, count ); }
|
||||
inline void V_memmove (void *dest, const void *src, int count) { memmove( dest, src, count ); }
|
||||
inline int V_memcmp (const void *m1, const void *m2, int count){ return memcmp( m1, m2, count ); }
|
||||
inline int V_strlen (const char *str) { return (int) strlen ( str ); }
|
||||
inline void V_strcpy (char *dest, const char *src) { strcpy( dest, src ); }
|
||||
inline int V_wcslen(const wchar_t *pwch) { return (int)wcslen(pwch); }
|
||||
inline char* V_strrchr (const char *s, char c) { return (char*)strrchr( s, c ); }
|
||||
inline int V_strcmp (const char *s1, const char *s2) { return strcmp( s1, s2 ); }
|
||||
inline int V_wcscmp (const wchar_t *s1, const wchar_t *s2) { return wcscmp( s1, s2 ); }
|
||||
inline int V_stricmp( const char *s1, const char *s2 ) { return stricmp( s1, s2 ); }
|
||||
inline char* V_strstr( const char *s1, const char *search ) { return (char*)strstr( s1, search ); }
|
||||
#ifndef COMPILER_PS3
|
||||
inline char* V_strupr (char *start) { return strupr( start ); }
|
||||
inline char* V_strlower (char *start) { return strlwr( start ); }
|
||||
inline wchar_t* V_wcsupr (wchar_t *start) { return _wcsupr( start ); }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
int V_strncmp (const char *s1, const char *s2, int count);
|
||||
int V_strcasecmp (const char *s1, const char *s2);
|
||||
int V_strncasecmp (const char *s1, const char *s2, int n);
|
||||
int V_strnicmp (const char *s1, const char *s2, int n);
|
||||
int V_atoi (const char *str);
|
||||
int64 V_atoi64(const char *str);
|
||||
uint64 V_atoui64(const char *str);
|
||||
float V_atof (const char *str);
|
||||
char* V_stristr( char* pStr, const char* pSearch );
|
||||
const char* V_stristr( const char* pStr, const char* pSearch );
|
||||
const char* V_strnistr( const char* pStr, const char* pSearch, int n );
|
||||
const char* V_strnchr( const char* pStr, char c, int n );
|
||||
|
||||
// returns string immediately following prefix, (ie str+strlen(prefix)) or NULL if prefix not found
|
||||
const char *StringAfterPrefix ( const char *str, const char *prefix );
|
||||
const char *StringAfterPrefixCaseSensitive( const char *str, const char *prefix );
|
||||
inline bool StringHasPrefix ( const char *str, const char *prefix ) { return StringAfterPrefix ( str, prefix ) != NULL; }
|
||||
inline bool StringHasPrefixCaseSensitive( const char *str, const char *prefix ) { return StringAfterPrefixCaseSensitive( str, prefix ) != NULL; }
|
||||
|
||||
|
||||
// Normalizes a float string in place.
|
||||
// (removes leading zeros, trailing zeros after the decimal point, and the decimal point itself where possible)
|
||||
void V_normalizeFloatString( char* pFloat );
|
||||
|
||||
inline bool V_isspace(int c)
|
||||
{
|
||||
// The standard white-space characters are the following: space, tab, carriage-return, newline, vertical tab, and form-feed. In the C locale, V_isspace() returns true only for the standard white-space characters.
|
||||
//return c == ' ' || c == 9 /*horizontal tab*/ || c == '\r' || c == '\n' || c == 11 /*vertical tab*/ || c == '\f';
|
||||
// codes of whitespace symbols: 9 HT, 10 \n, 11 VT, 12 form feed, 13 \r, 32 space
|
||||
|
||||
// easy to understand version, validated:
|
||||
// return ((1 << (c-1)) & 0x80001F00) != 0 && ((c-1)&0xE0) == 0;
|
||||
|
||||
// 5% faster on Core i7, 35% faster on Xbox360, no branches, validated:
|
||||
#ifdef _X360
|
||||
return ((1 << (c-1)) & 0x80001F00 & ~(-int((c-1)&0xE0))) != 0;
|
||||
#else
|
||||
// this is 11% faster on Core i7 than the previous, VC2005 compiler generates a seemingly unbalanced search tree that's faster
|
||||
switch(c)
|
||||
{
|
||||
case ' ':
|
||||
case 9:
|
||||
case '\r':
|
||||
case '\n':
|
||||
case 11:
|
||||
case '\f':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// These are versions of functions that guarantee NULL termination.
|
||||
//
|
||||
// maxLen is the maximum number of bytes in the destination string.
|
||||
// pDest[maxLen-1] is always NULL terminated if pSrc's length is >= maxLen.
|
||||
//
|
||||
// This means the last parameter can usually be a sizeof() of a string.
|
||||
void V_strncpy( char *pDest, const char *pSrc, int maxLen );
|
||||
int V_snprintf( char *pDest, int destLen, const char *pFormat, ... ) FMTFUNCTION( 3, 4 );
|
||||
void V_wcsncpy( wchar_t *pDest, wchar_t const *pSrc, int maxLenInBytes );
|
||||
int V_snwprintf( wchar_t *pDest, int maxLenInNumWideCharacters, const wchar_t *pFormat, ... );
|
||||
|
||||
#define COPY_ALL_CHARACTERS -1
|
||||
char *V_strncat(char *, const char *, size_t maxLenInBytes, int max_chars_to_copy=COPY_ALL_CHARACTERS );
|
||||
wchar_t *V_wcsncat(wchar_t *, const wchar_t *, int maxLenInBytes, int max_chars_to_copy=COPY_ALL_CHARACTERS );
|
||||
char *V_strnlwr(char *, size_t);
|
||||
|
||||
|
||||
// UNDONE: Find a non-compiler-specific way to do this
|
||||
#ifdef _WIN32
|
||||
#ifndef _VA_LIST_DEFINED
|
||||
|
||||
#ifdef _M_ALPHA
|
||||
|
||||
struct va_list
|
||||
{
|
||||
char *a0; /* pointer to first homed integer argument */
|
||||
int offset; /* byte offset of next parameter */
|
||||
};
|
||||
|
||||
#else // !_M_ALPHA
|
||||
|
||||
typedef char * va_list;
|
||||
|
||||
#endif // !_M_ALPHA
|
||||
|
||||
#define _VA_LIST_DEFINED
|
||||
|
||||
#endif // _VA_LIST_DEFINED
|
||||
|
||||
#elif POSIX
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define CORRECT_PATH_SEPARATOR '\\'
|
||||
#define CORRECT_PATH_SEPARATOR_S "\\"
|
||||
#define INCORRECT_PATH_SEPARATOR '/'
|
||||
#define INCORRECT_PATH_SEPARATOR_S "/"
|
||||
#elif POSIX || defined( _PS3 )
|
||||
#define CORRECT_PATH_SEPARATOR '/'
|
||||
#define CORRECT_PATH_SEPARATOR_S "/"
|
||||
#define INCORRECT_PATH_SEPARATOR '\\'
|
||||
#define INCORRECT_PATH_SEPARATOR_S "\\"
|
||||
#endif
|
||||
|
||||
int V_vsnprintf( char *pDest, int maxLen, const char *pFormat, va_list params );
|
||||
int V_vsnprintfRet( char *pDest, int maxLen, const char *pFormat, va_list params, bool *pbTruncated );
|
||||
|
||||
// Prints out a pretified memory counter string value ( e.g., 7,233.27 Mb, 1,298.003 Kb, 127 bytes )
|
||||
char *V_pretifymem( float value, int digitsafterdecimal = 2, bool usebinaryonek = false );
|
||||
|
||||
// Prints out a pretified integer with comma separators (eg, 7,233,270,000)
|
||||
char *V_pretifynum( int64 value );
|
||||
|
||||
// Functions for converting hexidecimal character strings back into binary data etc.
|
||||
//
|
||||
// e.g.,
|
||||
// int output;
|
||||
// V_hextobinary( "ffffffff", 8, &output, sizeof( output ) );
|
||||
// would make output == 0xfffffff or -1
|
||||
// Similarly,
|
||||
// char buffer[ 9 ];
|
||||
// V_binarytohex( &output, sizeof( output ), buffer, sizeof( buffer ) );
|
||||
// would put "ffffffff" into buffer (note null terminator!!!)
|
||||
void V_hextobinary( char const *in, int numchars, byte *out, int maxoutputbytes );
|
||||
void V_binarytohex( const byte *in, int inputbytes, char *out, int outsize );
|
||||
|
||||
// Tools for working with filenames
|
||||
// Extracts the base name of a file (no path, no extension, assumes '/' or '\' as path separator)
|
||||
void V_FileBase( const char *in, char *out,int maxlen );
|
||||
// Remove the final characters of ppath if it's '\' or '/'.
|
||||
void V_StripTrailingSlash( char *ppath );
|
||||
// Remove any extension from in and return resulting string in out
|
||||
void V_StripExtension( const char *in, char *out, int outLen );
|
||||
// Make path end with extension if it doesn't already have an extension
|
||||
void V_DefaultExtension( char *path, const char *extension, int pathStringLength );
|
||||
// Strips any current extension from path and ensures that extension is the new extension.
|
||||
// NOTE: extension string MUST include the . character
|
||||
void V_SetExtension( char *path, const char *extension, int pathStringLength );
|
||||
// Removes any filename from path ( strips back to previous / or \ character )
|
||||
void V_StripFilename( char *path );
|
||||
// Remove the final directory from the path
|
||||
bool V_StripLastDir( char *dirName, int maxlen );
|
||||
// Returns a pointer to the unqualified file name (no path) of a file name
|
||||
const char * V_UnqualifiedFileName( const char * in );
|
||||
char * V_UnqualifiedFileName( char * in );
|
||||
// Given a path and a filename, composes "path\filename", inserting the (OS correct) separator if necessary
|
||||
void V_ComposeFileName( const char *path, const char *filename, char *dest, int destSize );
|
||||
|
||||
// Copy out the path except for the stuff after the final pathseparator
|
||||
bool V_ExtractFilePath( const char *path, char *dest, int destSize );
|
||||
// Copy out the file extension into dest
|
||||
void V_ExtractFileExtension( const char *path, char *dest, int destSize );
|
||||
|
||||
const char *V_GetFileExtension( const char * path );
|
||||
|
||||
// returns a pointer to just the filename part of the path
|
||||
// (everything after the last path seperator)
|
||||
const char *V_GetFileName( const char * path );
|
||||
|
||||
// This removes "./" and "../" from the pathname. pFilename should be a full pathname.
|
||||
// Returns false if it tries to ".." past the root directory in the drive (in which case
|
||||
// it is an invalid path).
|
||||
bool V_RemoveDotSlashes( char *pFilename, char separator = CORRECT_PATH_SEPARATOR );
|
||||
|
||||
// If pPath is a relative path, this function makes it into an absolute path
|
||||
// using the current working directory as the base, or pStartingDir if it's non-NULL.
|
||||
// Returns false if it runs out of room in the string, or if pPath tries to ".." past the root directory.
|
||||
void V_MakeAbsolutePath( char *pOut, int outLen, const char *pPath, const char *pStartingDir = NULL );
|
||||
|
||||
// Creates a relative path given two full paths
|
||||
// The first is the full path of the file to make a relative path for.
|
||||
// The second is the full path of the directory to make the first file relative to
|
||||
// Returns false if they can't be made relative (on separate drives, for example)
|
||||
bool V_MakeRelativePath( const char *pFullPath, const char *pDirectory, char *pRelativePath, int nBufLen );
|
||||
|
||||
// Fixes up a file name, removing dot slashes, fixing slashes, converting to lowercase, etc.
|
||||
void V_FixupPathName( char *pOut, size_t nOutLen, const char *pPath );
|
||||
|
||||
// Adds a path separator to the end of the string if there isn't one already. Returns false if it would run out of space.
|
||||
void V_AppendSlash( char *pStr, int strSize );
|
||||
|
||||
// Returns true if the path is an absolute path.
|
||||
bool V_IsAbsolutePath( const char *pPath );
|
||||
|
||||
// Scans pIn and replaces all occurences of pMatch with pReplaceWith.
|
||||
// Writes the result to pOut.
|
||||
// Returns true if it completed successfully.
|
||||
// If it would overflow pOut, it fills as much as it can and returns false.
|
||||
bool V_StrSubst( const char *pIn, const char *pMatch, const char *pReplaceWith,
|
||||
char *pOut, int outLen, bool bCaseSensitive=false );
|
||||
|
||||
|
||||
// Split the specified string on the specified separator.
|
||||
// Returns a list of strings separated by pSeparator.
|
||||
// You are responsible for freeing the contents of outStrings (call outStrings.PurgeAndDeleteElements).
|
||||
void V_SplitString( const char *pString, const char *pSeparator, CUtlVector<char*, CUtlMemory<char*, int> > &outStrings );
|
||||
|
||||
// Just like V_SplitString, but it can use multiple possible separators.
|
||||
void V_SplitString2( const char *pString, const char **pSeparators, int nSeparators, CUtlVector<char*, CUtlMemory<char*, int> > &outStrings );
|
||||
|
||||
// Returns false if the buffer is not large enough to hold the working directory name.
|
||||
bool V_GetCurrentDirectory( char *pOut, int maxLen );
|
||||
|
||||
// Set the working directory thus.
|
||||
bool V_SetCurrentDirectory( const char *pDirName );
|
||||
|
||||
|
||||
// This function takes a slice out of pStr and stores it in pOut.
|
||||
// It follows the Python slice convention:
|
||||
// Negative numbers wrap around the string (-1 references the last character).
|
||||
// Large numbers are clamped to the end of the string.
|
||||
void V_StrSlice( const char *pStr, int firstChar, int lastCharNonInclusive, char *pOut, int outSize );
|
||||
|
||||
// Chop off the left nChars of a string.
|
||||
void V_StrLeft( const char *pStr, int nChars, char *pOut, int outSize );
|
||||
|
||||
// Chop off the right nChars of a string.
|
||||
void V_StrRight( const char *pStr, int nChars, char *pOut, int outSize );
|
||||
|
||||
// change "special" characters to have their c-style backslash sequence. like \n, \r, \t, ", etc.
|
||||
// returns a pointer to a newly allocated string, which you must delete[] when finished with.
|
||||
char *V_AddBackSlashesToSpecialChars( char const *pSrc );
|
||||
|
||||
// Force slashes of either type to be = separator character
|
||||
void V_FixSlashes( char *pname, char separator = CORRECT_PATH_SEPARATOR );
|
||||
|
||||
// This function fixes cases of filenames like materials\\blah.vmt or somepath\otherpath\\ and removes the extra double slash.
|
||||
void V_FixDoubleSlashes( char *pStr );
|
||||
|
||||
// Convert multibyte to wchar + back
|
||||
// Specify -1 for nInSize for null-terminated string
|
||||
void V_strtowcs( const char *pString, int nInSize, wchar_t *pWString, int nOutSize );
|
||||
void V_wcstostr( const wchar_t *pWString, int nInSize, char *pString, int nOutSize );
|
||||
|
||||
// buffer-safe strcat
|
||||
inline void V_strcat( char *dest, const char *src, int maxLenInBytes )
|
||||
{
|
||||
V_strncat( dest, src, maxLenInBytes, COPY_ALL_CHARACTERS );
|
||||
}
|
||||
|
||||
// buffer-safe strcat
|
||||
inline void V_wcscat( wchar_t *dest, const wchar_t *src, int maxLenInBytes )
|
||||
{
|
||||
V_wcsncat( dest, src, maxLenInBytes, COPY_ALL_CHARACTERS );
|
||||
}
|
||||
|
||||
// Convert from a string to an array of integers.
|
||||
void V_StringToIntArray( int *pVector, int count, const char *pString );
|
||||
|
||||
// Convert from a string to a 4 byte color value.
|
||||
void V_StringToColor32( color32 *color, const char *pString );
|
||||
|
||||
// Convert \r\n (Windows linefeeds) to \n (Unix linefeeds).
|
||||
void V_TranslateLineFeedsToUnix( char *pStr );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// generic unique name helper functions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// returns -1 if no match, nDefault if pName==prefix, and N if pName==prefix+N
|
||||
inline int V_IndexAfterPrefix( const char *pName, const char *prefix, int nDefault = 0 )
|
||||
{
|
||||
if ( !pName || !prefix )
|
||||
return -1;
|
||||
|
||||
const char *pIndexStr = StringAfterPrefix( pName, prefix );
|
||||
if ( !pIndexStr )
|
||||
return -1;
|
||||
|
||||
if ( !*pIndexStr )
|
||||
return nDefault;
|
||||
|
||||
return atoi( pIndexStr );
|
||||
}
|
||||
|
||||
// returns startindex if none found, 2 if "prefix" found, and n+1 if "prefixn" found
|
||||
template < class NameArray >
|
||||
int V_GenerateUniqueNameIndex( const char *prefix, const NameArray &nameArray, int startindex = 0 )
|
||||
{
|
||||
if ( !prefix )
|
||||
return 0;
|
||||
|
||||
int freeindex = startindex;
|
||||
|
||||
int nNames = nameArray.Count();
|
||||
for ( int i = 0; i < nNames; ++i )
|
||||
{
|
||||
int index = V_IndexAfterPrefix( nameArray[ i ], prefix, 1 ); // returns -1 if no match, 0 for exact match, N for
|
||||
if ( index >= freeindex )
|
||||
{
|
||||
// TODO - check that there isn't more junk after the index in pElementName
|
||||
freeindex = index + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return freeindex;
|
||||
}
|
||||
|
||||
template < class NameArray >
|
||||
bool V_GenerateUniqueName( char *name, int memsize, const char *prefix, const NameArray &nameArray )
|
||||
{
|
||||
if ( name == NULL || memsize == 0 )
|
||||
return false;
|
||||
|
||||
if ( prefix == NULL )
|
||||
{
|
||||
name[ 0 ] = '\0';
|
||||
return false;
|
||||
}
|
||||
|
||||
int prefixLength = V_strlen( prefix );
|
||||
if ( prefixLength + 1 > memsize )
|
||||
{
|
||||
name[ 0 ] = '\0';
|
||||
return false;
|
||||
}
|
||||
|
||||
int i = V_GenerateUniqueNameIndex( prefix, nameArray );
|
||||
if ( i <= 0 )
|
||||
{
|
||||
V_strncpy( name, prefix, memsize );
|
||||
return true;
|
||||
}
|
||||
|
||||
int newlen = prefixLength + ( int )log10( ( float )i ) + 1;
|
||||
if ( newlen + 1 > memsize )
|
||||
{
|
||||
V_strncpy( name, prefix, memsize );
|
||||
return false;
|
||||
}
|
||||
|
||||
V_snprintf( name, memsize, "%s%d", prefix, i );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
extern bool V_StringToBin( const char*pString, void *pBin, uint nBinSize );
|
||||
extern bool V_BinToString( char*pString, void *pBin, uint nBinSize );
|
||||
|
||||
template<typename T>
|
||||
struct BinString_t
|
||||
{
|
||||
BinString_t(){}
|
||||
BinString_t( const char *pStr )
|
||||
{
|
||||
V_strncpy( m_string, pStr, sizeof(m_string) );
|
||||
ToBin();
|
||||
}
|
||||
BinString_t( const T & that )
|
||||
{
|
||||
m_bin = that;
|
||||
ToString();
|
||||
}
|
||||
bool ToBin()
|
||||
{
|
||||
return V_StringToBin( m_string, &m_bin, sizeof( m_bin ) );
|
||||
}
|
||||
void ToString()
|
||||
{
|
||||
V_BinToString( m_string, &m_bin, sizeof( m_bin ) );
|
||||
}
|
||||
T m_bin;
|
||||
char m_string[sizeof(T)*2+2]; // 0-terminated string representing the binary data in hex
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline BinString_t<T> MakeBinString( const T& that )
|
||||
{
|
||||
return BinString_t<T>( that );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined(_PS3) || defined(POSIX)
|
||||
#define PRI_WS_FOR_WS L"%ls"
|
||||
#define PRI_WS_FOR_S "%ls"
|
||||
#define PRI_S_FOR_WS L"%s"
|
||||
#define PRI_S_FOR_S "%s"
|
||||
#else
|
||||
#define PRI_WS_FOR_WS L"%s"
|
||||
#define PRI_WS_FOR_S "%S"
|
||||
#define PRI_S_FOR_WS L"%S"
|
||||
#define PRI_S_FOR_S "%s"
|
||||
#endif
|
||||
|
||||
namespace AsianWordWrap
|
||||
{
|
||||
// Functions used by Asian language line wrapping to determine if a character can end a line, begin a line, or be broken up when repeated (eg: "...")
|
||||
bool CanEndLine( wchar_t wcCandidate );
|
||||
bool CanBeginLine( wchar_t wcCandidate );
|
||||
bool CanBreakRepeated( wchar_t wcCandidate );
|
||||
|
||||
// Used to determine if we can break a line between the first two characters passed; calls the above functions on each character
|
||||
bool CanBreakAfter( const wchar_t* wsz );
|
||||
}
|
||||
|
||||
// We use this function to determine where it is permissible to break lines
|
||||
// of text while wrapping them. On most platforms, the native iswspace() function
|
||||
// returns FALSE for the "non-breaking space" characters 0x00a0 and 0x202f, and so we don't
|
||||
// break on them. On the 360, however, iswspace returns TRUE for them. So, on that
|
||||
// platform, we work around it by defining this wrapper which returns false
|
||||
// for and calls through to the library function for everything else.
|
||||
int isbreakablewspace( wchar_t ch );
|
||||
|
||||
#endif // TIER1_STRTOOLS_H
|
||||
Vendored
+85
@@ -0,0 +1,85 @@
|
||||
//===== Copyright � 2005-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose: A higher level link library for general use in the game and tools.
|
||||
//
|
||||
//===========================================================================//
|
||||
|
||||
|
||||
#ifndef TIER1_H
|
||||
#define TIER1_H
|
||||
|
||||
#if defined( _WIN32 )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "appframework/iappsystem.h"
|
||||
#include "tier1/convar.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Forward declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Call this to connect to/disconnect from all tier 1 libraries.
|
||||
// It's up to the caller to check the globals it cares about to see if ones are missing
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConnectTier1Libraries( CreateInterfaceFn *pFactoryList, int nFactoryCount );
|
||||
void DisconnectTier1Libraries();
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helper empty implementation of an IAppSystem for tier2 libraries
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class IInterface, int ConVarFlag = 0 >
|
||||
class CTier1AppSystem : public CTier0AppSystem< IInterface >
|
||||
{
|
||||
typedef CTier0AppSystem< IInterface > BaseClass;
|
||||
|
||||
public:
|
||||
virtual bool Connect( CreateInterfaceFn factory )
|
||||
{
|
||||
if ( !BaseClass::Connect( factory ) )
|
||||
return false;
|
||||
|
||||
ConnectTier1Libraries( &factory, 1 );
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void Disconnect()
|
||||
{
|
||||
DisconnectTier1Libraries();
|
||||
BaseClass::Disconnect();
|
||||
}
|
||||
|
||||
virtual InitReturnVal_t Init()
|
||||
{
|
||||
InitReturnVal_t nRetVal = BaseClass::Init();
|
||||
if ( nRetVal != INIT_OK )
|
||||
return nRetVal;
|
||||
|
||||
if ( g_pCVar )
|
||||
{
|
||||
ConVar_Register( ConVarFlag );
|
||||
}
|
||||
return INIT_OK;
|
||||
}
|
||||
|
||||
virtual void Shutdown()
|
||||
{
|
||||
if ( g_pCVar )
|
||||
{
|
||||
ConVar_Unregister( );
|
||||
}
|
||||
BaseClass::Shutdown( );
|
||||
}
|
||||
|
||||
virtual AppSystemTier_t GetTier()
|
||||
{
|
||||
return APP_SYSTEM_TIER1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // TIER1_H
|
||||
|
||||
+349
@@ -0,0 +1,349 @@
|
||||
//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
// A growable memory class.
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef UTLBLOCKMEMORY_H
|
||||
#define UTLBLOCKMEMORY_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "tier0/dbg.h"
|
||||
#include "tier0/platform.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
|
||||
#include "tier0/memalloc.h"
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#pragma warning (disable:4100)
|
||||
#pragma warning (disable:4514)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef UTBLOCKLMEMORY_TRACK
|
||||
#define UTLBLOCKMEMORY_TRACK_ALLOC() MemAlloc_RegisterAllocation( "||Sum of all UtlBlockMemory||", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 )
|
||||
#define UTLBLOCKMEMORY_TRACK_FREE() if ( !m_pMemory ) ; else MemAlloc_RegisterDeallocation( "||Sum of all UtlBlockMemory||", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 )
|
||||
#else
|
||||
#define UTLBLOCKMEMORY_TRACK_ALLOC() ((void)0)
|
||||
#define UTLBLOCKMEMORY_TRACK_FREE() ((void)0)
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The CUtlBlockMemory class:
|
||||
// A growable memory class that allocates non-sequential blocks, but is indexed sequentially
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T, class I >
|
||||
class CUtlBlockMemory
|
||||
{
|
||||
public:
|
||||
// constructor, destructor
|
||||
CUtlBlockMemory( int nGrowSize = 0, int nInitSize = 0 );
|
||||
~CUtlBlockMemory();
|
||||
|
||||
// Set the size by which the memory grows - round up to the next power of 2
|
||||
void Init( int nGrowSize = 0, int nInitSize = 0 );
|
||||
|
||||
// here to match CUtlMemory, but only used by ResetDbgInfo, so it can just return NULL
|
||||
T* Base() { return NULL; }
|
||||
const T* Base() const { return NULL; }
|
||||
|
||||
class Iterator_t
|
||||
{
|
||||
public:
|
||||
Iterator_t( I i ) : index( i ) {}
|
||||
I index;
|
||||
|
||||
bool operator==( const Iterator_t it ) const { return index == it.index; }
|
||||
bool operator!=( const Iterator_t it ) const { return index != it.index; }
|
||||
};
|
||||
Iterator_t First() const { return Iterator_t( IsIdxValid( 0 ) ? 0 : InvalidIndex() ); }
|
||||
Iterator_t Next( const Iterator_t &it ) const { return Iterator_t( IsIdxValid( it.index + 1 ) ? it.index + 1 : InvalidIndex() ); }
|
||||
I GetIndex( const Iterator_t &it ) const { return it.index; }
|
||||
bool IsIdxAfter( I i, const Iterator_t &it ) const { return i > it.index; }
|
||||
bool IsValidIterator( const Iterator_t &it ) const { return IsIdxValid( it.index ); }
|
||||
Iterator_t InvalidIterator() const { return Iterator_t( InvalidIndex() ); }
|
||||
|
||||
// element access
|
||||
T& operator[]( I i );
|
||||
const T& operator[]( I i ) const;
|
||||
T& Element( I i );
|
||||
const T& Element( I i ) const;
|
||||
|
||||
// Can we use this index?
|
||||
bool IsIdxValid( I i ) const;
|
||||
static I InvalidIndex() { return ( I )-1; }
|
||||
|
||||
void Swap( CUtlBlockMemory< T, I > &mem );
|
||||
|
||||
// Size
|
||||
int NumAllocated() const;
|
||||
int Count() const { return NumAllocated(); }
|
||||
|
||||
// Grows memory by max(num,growsize) rounded up to the next power of 2, and returns the allocation index/ptr
|
||||
void Grow( int num = 1 );
|
||||
|
||||
// Makes sure we've got at least this much memory
|
||||
void EnsureCapacity( int num );
|
||||
|
||||
// Memory deallocation
|
||||
void Purge();
|
||||
|
||||
// Purge all but the given number of elements
|
||||
void Purge( int numElements );
|
||||
|
||||
protected:
|
||||
int Index( int major, int minor ) const { return ( major << m_nIndexShift ) | minor; }
|
||||
int MajorIndex( int i ) const { return i >> m_nIndexShift; }
|
||||
int MinorIndex( int i ) const { return i & m_nIndexMask; }
|
||||
void ChangeSize( int nBlocks );
|
||||
int NumElementsInBlock() const { return m_nIndexMask + 1; }
|
||||
|
||||
T** m_pMemory;
|
||||
int m_nBlocks;
|
||||
int m_nIndexMask : 27;
|
||||
int m_nIndexShift : 5;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// constructor, destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T, class I >
|
||||
CUtlBlockMemory<T,I>::CUtlBlockMemory( int nGrowSize, int nInitAllocationCount )
|
||||
: m_pMemory( 0 ), m_nBlocks( 0 ), m_nIndexMask( 0 ), m_nIndexShift( 0 )
|
||||
{
|
||||
Init( nGrowSize, nInitAllocationCount );
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
CUtlBlockMemory<T,I>::~CUtlBlockMemory()
|
||||
{
|
||||
Purge();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Fast swap
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T, class I >
|
||||
void CUtlBlockMemory<T,I>::Swap( CUtlBlockMemory< T, I > &mem )
|
||||
{
|
||||
V_swap( m_pMemory, mem.m_pMemory );
|
||||
V_swap( m_nBlocks, mem.m_nBlocks );
|
||||
V_swap( m_nIndexMask, mem.m_nIndexMask );
|
||||
V_swap( m_nIndexShift, mem.m_nIndexShift );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Set the size by which the memory grows - round up to the next power of 2
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T, class I >
|
||||
void CUtlBlockMemory<T,I>::Init( int nGrowSize /* = 0 */, int nInitSize /* = 0 */ )
|
||||
{
|
||||
Purge();
|
||||
|
||||
if ( nGrowSize == 0)
|
||||
{
|
||||
// default grow size is smallest size s.t. c++ allocation overhead is ~6% of block size
|
||||
nGrowSize = ( 127 + sizeof( T ) ) / sizeof( T );
|
||||
}
|
||||
nGrowSize = SmallestPowerOfTwoGreaterOrEqual( nGrowSize );
|
||||
m_nIndexMask = nGrowSize - 1;
|
||||
|
||||
m_nIndexShift = 0;
|
||||
while ( nGrowSize > 1 )
|
||||
{
|
||||
nGrowSize >>= 1;
|
||||
++m_nIndexShift;
|
||||
}
|
||||
Assert( m_nIndexMask + 1 == ( 1 << m_nIndexShift ) );
|
||||
|
||||
Grow( nInitSize );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// element access
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T, class I >
|
||||
inline T& CUtlBlockMemory<T,I>::operator[]( I i )
|
||||
{
|
||||
Assert( IsIdxValid(i) );
|
||||
T *pBlock = m_pMemory[ MajorIndex( i ) ];
|
||||
return pBlock[ MinorIndex( i ) ];
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
inline const T& CUtlBlockMemory<T,I>::operator[]( I i ) const
|
||||
{
|
||||
Assert( IsIdxValid(i) );
|
||||
const T *pBlock = m_pMemory[ MajorIndex( i ) ];
|
||||
return pBlock[ MinorIndex( i ) ];
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
inline T& CUtlBlockMemory<T,I>::Element( I i )
|
||||
{
|
||||
Assert( IsIdxValid(i) );
|
||||
T *pBlock = m_pMemory[ MajorIndex( i ) ];
|
||||
return pBlock[ MinorIndex( i ) ];
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
inline const T& CUtlBlockMemory<T,I>::Element( I i ) const
|
||||
{
|
||||
Assert( IsIdxValid(i) );
|
||||
const T *pBlock = m_pMemory[ MajorIndex( i ) ];
|
||||
return pBlock[ MinorIndex( i ) ];
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Size
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T, class I >
|
||||
inline int CUtlBlockMemory<T,I>::NumAllocated() const
|
||||
{
|
||||
return m_nBlocks * NumElementsInBlock();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Is element index valid?
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T, class I >
|
||||
inline bool CUtlBlockMemory<T,I>::IsIdxValid( I i ) const
|
||||
{
|
||||
return ( i >= 0 ) && ( MajorIndex( i ) < m_nBlocks );
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
void CUtlBlockMemory<T,I>::Grow( int num )
|
||||
{
|
||||
if ( num <= 0 )
|
||||
return;
|
||||
|
||||
int nBlockSize = NumElementsInBlock();
|
||||
int nBlocks = ( num + nBlockSize - 1 ) / nBlockSize;
|
||||
|
||||
ChangeSize( m_nBlocks + nBlocks );
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
void CUtlBlockMemory<T,I>::ChangeSize( int nBlocks )
|
||||
{
|
||||
UTLBLOCKMEMORY_TRACK_FREE(); // this must stay before the recalculation of m_nBlocks, since it implicitly uses the old value
|
||||
|
||||
int nBlocksOld = m_nBlocks;
|
||||
m_nBlocks = nBlocks;
|
||||
|
||||
UTLBLOCKMEMORY_TRACK_ALLOC(); // this must stay after the recalculation of m_nBlocks, since it implicitly uses the new value
|
||||
|
||||
// free old blocks if shrinking
|
||||
for ( int i = m_nBlocks; i < nBlocksOld; ++i )
|
||||
{
|
||||
UTLBLOCKMEMORY_TRACK_FREE();
|
||||
free( (void*)m_pMemory[ i ] );
|
||||
}
|
||||
|
||||
if ( m_pMemory )
|
||||
{
|
||||
MEM_ALLOC_CREDIT_CLASS();
|
||||
m_pMemory = (T**)realloc( m_pMemory, m_nBlocks * sizeof(T*) );
|
||||
Assert( m_pMemory );
|
||||
}
|
||||
else
|
||||
{
|
||||
MEM_ALLOC_CREDIT_CLASS();
|
||||
m_pMemory = (T**)malloc( m_nBlocks * sizeof(T*) );
|
||||
Assert( m_pMemory );
|
||||
}
|
||||
|
||||
if ( !m_pMemory )
|
||||
{
|
||||
Error( "CUtlBlockMemory overflow!\n" );
|
||||
}
|
||||
|
||||
// allocate new blocks if growing
|
||||
int nBlockSize = NumElementsInBlock();
|
||||
for ( int i = nBlocksOld; i < m_nBlocks; ++i )
|
||||
{
|
||||
MEM_ALLOC_CREDIT_CLASS();
|
||||
m_pMemory[ i ] = (T*)malloc( nBlockSize * sizeof( T ) );
|
||||
Assert( m_pMemory[ i ] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Makes sure we've got at least this much memory
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T, class I >
|
||||
inline void CUtlBlockMemory<T,I>::EnsureCapacity( int num )
|
||||
{
|
||||
Grow( num - NumAllocated() );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memory deallocation
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T, class I >
|
||||
void CUtlBlockMemory<T,I>::Purge()
|
||||
{
|
||||
if ( !m_pMemory )
|
||||
return;
|
||||
|
||||
for ( int i = 0; i < m_nBlocks; ++i )
|
||||
{
|
||||
UTLBLOCKMEMORY_TRACK_FREE();
|
||||
free( (void*)m_pMemory[ i ] );
|
||||
}
|
||||
m_nBlocks = 0;
|
||||
|
||||
UTLBLOCKMEMORY_TRACK_FREE();
|
||||
free( (void*)m_pMemory );
|
||||
m_pMemory = 0;
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
void CUtlBlockMemory<T,I>::Purge( int numElements )
|
||||
{
|
||||
Assert( numElements >= 0 );
|
||||
|
||||
int nAllocated = NumAllocated();
|
||||
if ( numElements > nAllocated )
|
||||
{
|
||||
// Ensure this isn't a grow request in disguise.
|
||||
Assert( numElements <= nAllocated );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( numElements <= 0 )
|
||||
{
|
||||
Purge();
|
||||
return;
|
||||
}
|
||||
|
||||
int nBlockSize = NumElementsInBlock();
|
||||
int nBlocksOld = m_nBlocks;
|
||||
int nBlocks = ( numElements + nBlockSize - 1 ) / nBlockSize;
|
||||
|
||||
// If the number of blocks is the same as the allocated number of blocks, we are done.
|
||||
if ( nBlocks == m_nBlocks )
|
||||
return;
|
||||
|
||||
ChangeSize( nBlocks );
|
||||
}
|
||||
|
||||
#include "tier0/memdbgoff.h"
|
||||
|
||||
#endif // UTLBLOCKMEMORY_H
|
||||
+1398
File diff suppressed because it is too large
Load Diff
Vendored
+338
@@ -0,0 +1,338 @@
|
||||
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======//
|
||||
//
|
||||
// Purpose: A dictionary mapping from symbol to structure
|
||||
//
|
||||
// $Header: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef UTLDICT_H
|
||||
#define UTLDICT_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "tier0/dbg.h"
|
||||
#include "tier1/utlmap.h"
|
||||
|
||||
// Include this because tons of code was implicitly getting utlsymbol or utlvector via utldict.h
|
||||
#include "tier1/utlsymbol.h"
|
||||
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
enum EDictCompareType
|
||||
{
|
||||
k_eDictCompareTypeCaseSensitive=0,
|
||||
k_eDictCompareTypeCaseInsensitive=1,
|
||||
k_eDictCompareTypeFilenames // Slashes and backslashes count as the same character..
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A dictionary mapping from symbol to structure
|
||||
//-----------------------------------------------------------------------------
|
||||
#define FOR_EACH_DICT( dictName, iteratorName ) \
|
||||
for( int iteratorName=dictName.First(); iteratorName != dictName.InvalidIndex(); iteratorName = dictName.Next( iteratorName ) )
|
||||
|
||||
// faster iteration, but in an unspecified order
|
||||
#define FOR_EACH_DICT_FAST( dictName, iteratorName ) \
|
||||
for ( int iteratorName = 0; iteratorName < dictName.MaxElement(); ++iteratorName ) if ( !dictName.IsValidIndex( iteratorName ) ) continue; else
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A dictionary mapping from symbol to structure
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I = int >
|
||||
class CUtlDict
|
||||
{
|
||||
public:
|
||||
// constructor, destructor
|
||||
// Left at growSize = 0, the memory will first allocate 1 element and double in size
|
||||
// at each increment.
|
||||
CUtlDict( int compareType = k_eDictCompareTypeCaseInsensitive, int growSize = 0, int initSize = 0 );
|
||||
~CUtlDict( );
|
||||
|
||||
void EnsureCapacity( int );
|
||||
|
||||
// gets particular elements
|
||||
T& Element( I i );
|
||||
const T& Element( I i ) const;
|
||||
T& operator[]( I i );
|
||||
const T& operator[]( I i ) const;
|
||||
|
||||
// gets element names
|
||||
char *GetElementName( I i );
|
||||
char const *GetElementName( I i ) const;
|
||||
|
||||
void SetElementName( I i, char const *pName );
|
||||
|
||||
// Number of elements
|
||||
unsigned int Count() const;
|
||||
|
||||
// Checks if a node is valid and in the tree
|
||||
bool IsValidIndex( I i ) const;
|
||||
|
||||
// Invalid index
|
||||
static I InvalidIndex();
|
||||
|
||||
// Insert method (inserts in order)
|
||||
I Insert( const char *pName, const T &element );
|
||||
I Insert( const char *pName );
|
||||
|
||||
// Find method
|
||||
I Find( const char *pName ) const;
|
||||
|
||||
// Remove methods
|
||||
void RemoveAt( I i );
|
||||
void Remove( const char *pName );
|
||||
void RemoveAll( );
|
||||
|
||||
// Purge memory
|
||||
void Purge();
|
||||
void PurgeAndDeleteElements(); // Call delete on each element.
|
||||
|
||||
// Iteration methods
|
||||
I First() const;
|
||||
I Next( I i ) const;
|
||||
|
||||
// Nested typedefs, for code that might need
|
||||
// to fish out the index type from a given dict
|
||||
typedef I IndexType_t;
|
||||
|
||||
protected:
|
||||
typedef CUtlMap<const char *, T, I> DictElementMap_t;
|
||||
DictElementMap_t m_Elements;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// constructor, destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
CUtlDict<T, I>::CUtlDict( int compareType, int growSize, int initSize ) : m_Elements( growSize, initSize )
|
||||
{
|
||||
if ( compareType == k_eDictCompareTypeFilenames )
|
||||
{
|
||||
m_Elements.SetLessFunc( CaselessStringLessThanIgnoreSlashes );
|
||||
}
|
||||
else if ( compareType == k_eDictCompareTypeCaseInsensitive )
|
||||
{
|
||||
m_Elements.SetLessFunc( CaselessStringLessThan );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Elements.SetLessFunc( StringLessThan );
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
CUtlDict<T, I>::~CUtlDict()
|
||||
{
|
||||
Purge();
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline void CUtlDict<T, I>::EnsureCapacity( int num )
|
||||
{
|
||||
return m_Elements.EnsureCapacity( num );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// gets particular elements
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
inline T& CUtlDict<T, I>::Element( I i )
|
||||
{
|
||||
return m_Elements[i];
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline const T& CUtlDict<T, I>::Element( I i ) const
|
||||
{
|
||||
return m_Elements[i];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// gets element names
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
inline char *CUtlDict<T, I>::GetElementName( I i )
|
||||
{
|
||||
return (char *)m_Elements.Key( i );
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline char const *CUtlDict<T, I>::GetElementName( I i ) const
|
||||
{
|
||||
return m_Elements.Key( i );
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline T& CUtlDict<T, I>::operator[]( I i )
|
||||
{
|
||||
return Element(i);
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline const T & CUtlDict<T, I>::operator[]( I i ) const
|
||||
{
|
||||
return Element(i);
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline void CUtlDict<T, I>::SetElementName( I i, char const *pName )
|
||||
{
|
||||
MEM_ALLOC_CREDIT_CLASS();
|
||||
// TODO: This makes a copy of the old element
|
||||
// TODO: This relies on the rb tree putting the most recently
|
||||
// removed element at the head of the insert list
|
||||
free( (void *)m_Elements.Key( i ) );
|
||||
m_Elements.Reinsert( strdup( pName ), i );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Num elements
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
inline unsigned int CUtlDict<T, I>::Count() const
|
||||
{
|
||||
return m_Elements.Count();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Checks if a node is valid and in the tree
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
inline bool CUtlDict<T, I>::IsValidIndex( I i ) const
|
||||
{
|
||||
return m_Elements.IsValidIndex(i);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Invalid index
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
inline I CUtlDict<T, I>::InvalidIndex()
|
||||
{
|
||||
return DictElementMap_t::InvalidIndex();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Delete a node from the tree
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
void CUtlDict<T, I>::RemoveAt(I elem)
|
||||
{
|
||||
free( (void *)m_Elements.Key( elem ) );
|
||||
m_Elements.RemoveAt(elem);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// remove a node in the tree
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I> void CUtlDict<T, I>::Remove( const char *search )
|
||||
{
|
||||
I node = Find( search );
|
||||
if (node != InvalidIndex())
|
||||
{
|
||||
RemoveAt(node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Removes all nodes from the tree
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
void CUtlDict<T, I>::RemoveAll()
|
||||
{
|
||||
typename DictElementMap_t::IndexType_t index = m_Elements.FirstInorder();
|
||||
while ( index != m_Elements.InvalidIndex() )
|
||||
{
|
||||
const char *pKey = m_Elements.Key( index );
|
||||
free( const_cast<char*>(pKey) );
|
||||
index = m_Elements.NextInorder( index );
|
||||
}
|
||||
|
||||
m_Elements.RemoveAll();
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
void CUtlDict<T, I>::Purge()
|
||||
{
|
||||
RemoveAll();
|
||||
}
|
||||
|
||||
|
||||
template <class T, class I>
|
||||
void CUtlDict<T, I>::PurgeAndDeleteElements()
|
||||
{
|
||||
// Delete all the elements.
|
||||
I index = m_Elements.FirstInorder();
|
||||
while ( index != m_Elements.InvalidIndex() )
|
||||
{
|
||||
const char* pKey = m_Elements.Key( index );
|
||||
free( const_cast<char*>(pKey) );
|
||||
delete m_Elements[index];
|
||||
index = m_Elements.NextInorder( index );
|
||||
}
|
||||
|
||||
m_Elements.RemoveAll();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// inserts a node into the tree
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
I CUtlDict<T, I>::Insert( const char *pName, const T &element )
|
||||
{
|
||||
MEM_ALLOC_CREDIT_CLASS();
|
||||
return m_Elements.Insert( strdup( pName ), element );
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
I CUtlDict<T, I>::Insert( const char *pName )
|
||||
{
|
||||
MEM_ALLOC_CREDIT_CLASS();
|
||||
return m_Elements.Insert( strdup( pName ) );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// finds a node in the tree
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
I CUtlDict<T, I>::Find( const char *pName ) const
|
||||
{
|
||||
MEM_ALLOC_CREDIT_CLASS();
|
||||
if ( pName )
|
||||
return m_Elements.Find( pName );
|
||||
else
|
||||
return InvalidIndex();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Iteration methods
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
I CUtlDict<T, I>::First() const
|
||||
{
|
||||
return m_Elements.FirstInorder();
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
I CUtlDict<T, I>::Next( I i ) const
|
||||
{
|
||||
return m_Elements.NextInorder(i);
|
||||
}
|
||||
|
||||
#include "tier0/memdbgoff.h"
|
||||
|
||||
#endif // UTLDICT_H
|
||||
+241
@@ -0,0 +1,241 @@
|
||||
//========== Copyright � 2005, Valve Corporation, All rights reserved. ========
|
||||
//
|
||||
// Purpose: A class to wrap data for transport over a boundary like a thread
|
||||
// or window.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "tier1/utlstring.h"
|
||||
#include "tier0/basetypes.h"
|
||||
|
||||
#ifndef UTLENVELOPE_H
|
||||
#define UTLENVELOPE_H
|
||||
|
||||
#if defined( _WIN32 )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class CUtlDataEnvelope
|
||||
{
|
||||
public:
|
||||
CUtlDataEnvelope( const void *pData, int nBytes );
|
||||
CUtlDataEnvelope( const CUtlDataEnvelope &from );
|
||||
~CUtlDataEnvelope();
|
||||
|
||||
CUtlDataEnvelope &operator=( const CUtlDataEnvelope &from );
|
||||
|
||||
operator void *();
|
||||
operator void *() const;
|
||||
|
||||
private:
|
||||
void Assign( const void *pData, int nBytes );
|
||||
void Assign( const CUtlDataEnvelope &from );
|
||||
void Purge();
|
||||
|
||||
// TODO: switch to a reference counted array?
|
||||
union
|
||||
{
|
||||
byte *m_pData;
|
||||
byte m_data[4];
|
||||
};
|
||||
int m_nBytes;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <typename T>
|
||||
class CUtlEnvelope : protected CUtlDataEnvelope
|
||||
{
|
||||
public:
|
||||
CUtlEnvelope( const T *pData, int nElems = 1 );
|
||||
CUtlEnvelope( const CUtlEnvelope<T> &from );
|
||||
|
||||
CUtlEnvelope<T> &operator=( const CUtlEnvelope<T> &from );
|
||||
|
||||
operator T *();
|
||||
operator T *() const;
|
||||
|
||||
operator void *();
|
||||
operator void *() const;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <>
|
||||
class CUtlEnvelope<const char *>
|
||||
{
|
||||
public:
|
||||
CUtlEnvelope( const char *pData )
|
||||
{
|
||||
m_string = pData;
|
||||
}
|
||||
|
||||
CUtlEnvelope( const CUtlEnvelope<const char *> &from )
|
||||
{
|
||||
m_string = from.m_string;
|
||||
}
|
||||
|
||||
CUtlEnvelope<const char *> &operator=( const CUtlEnvelope<const char *> &from )
|
||||
{
|
||||
m_string = from.m_string;
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator char *()
|
||||
{
|
||||
return (char *) m_string.Get();
|
||||
}
|
||||
|
||||
operator char *() const
|
||||
{
|
||||
return (char *) m_string.Get();
|
||||
}
|
||||
|
||||
operator void *()
|
||||
{
|
||||
return (void *) m_string.Get();
|
||||
}
|
||||
|
||||
operator void *() const
|
||||
{
|
||||
return (void *) m_string.Get();
|
||||
}
|
||||
|
||||
private:
|
||||
CUtlString m_string;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
inline void CUtlDataEnvelope::Assign( const void *pData, int nBytes )
|
||||
{
|
||||
if ( pData )
|
||||
{
|
||||
m_nBytes = nBytes;
|
||||
if ( m_nBytes > 4 )
|
||||
{
|
||||
m_pData = new byte[nBytes];
|
||||
memcpy( m_pData, pData, nBytes );
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy( m_data, pData, nBytes );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pData = NULL;
|
||||
m_nBytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline void CUtlDataEnvelope::Assign( const CUtlDataEnvelope &from )
|
||||
{
|
||||
Assign( from.operator void *(), from.m_nBytes );
|
||||
}
|
||||
|
||||
inline void CUtlDataEnvelope::Purge()
|
||||
{
|
||||
if (m_nBytes > 4)
|
||||
delete [] m_pData;
|
||||
m_nBytes = 0;
|
||||
}
|
||||
|
||||
inline CUtlDataEnvelope::CUtlDataEnvelope( const void *pData, int nBytes )
|
||||
{
|
||||
Assign( pData, nBytes );
|
||||
}
|
||||
|
||||
inline CUtlDataEnvelope::CUtlDataEnvelope( const CUtlDataEnvelope &from )
|
||||
{
|
||||
Assign( from );
|
||||
}
|
||||
|
||||
inline CUtlDataEnvelope::~CUtlDataEnvelope()
|
||||
{
|
||||
Purge();
|
||||
}
|
||||
|
||||
inline CUtlDataEnvelope &CUtlDataEnvelope::operator=( const CUtlDataEnvelope &from )
|
||||
{
|
||||
Purge();
|
||||
Assign( from );
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline CUtlDataEnvelope::operator void *()
|
||||
{
|
||||
if ( !m_nBytes )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ( m_nBytes > 4) ? m_pData : m_data;
|
||||
}
|
||||
|
||||
inline CUtlDataEnvelope::operator void *() const
|
||||
{
|
||||
if ( !m_nBytes )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ( m_nBytes > 4) ? (void *)m_pData : (void *)m_data;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <typename T>
|
||||
inline CUtlEnvelope<T>::CUtlEnvelope( const T *pData, int nElems )
|
||||
: CUtlDataEnvelope( pData, sizeof(T) * nElems )
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline CUtlEnvelope<T>::CUtlEnvelope( const CUtlEnvelope<T> &from )
|
||||
: CUtlDataEnvelope( from )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline CUtlEnvelope<T> &CUtlEnvelope<T>::operator=( const CUtlEnvelope<T> &from )
|
||||
{
|
||||
CUtlDataEnvelope::operator=( from );
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline CUtlEnvelope<T>::operator T *()
|
||||
{
|
||||
return (T *)CUtlDataEnvelope::operator void *();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline CUtlEnvelope<T>::operator T *() const
|
||||
{
|
||||
return (T *)( (const_cast<CUtlEnvelope<T> *>(this))->operator T *() );
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline CUtlEnvelope<T>::operator void *()
|
||||
{
|
||||
return CUtlDataEnvelope::operator void *();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline CUtlEnvelope<T>::operator void *() const
|
||||
{
|
||||
return ( (const_cast<CUtlEnvelope<T> *>(this))->operator void *() );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "tier0/memdbgoff.h"
|
||||
|
||||
#endif // UTLENVELOPE_H
|
||||
+354
@@ -0,0 +1,354 @@
|
||||
//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
// A growable memory class.
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef UTLFIXEDMEMORY_H
|
||||
#define UTLFIXEDMEMORY_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "tier0/dbg.h"
|
||||
#include "tier0/platform.h"
|
||||
|
||||
#include "tier0/memalloc.h"
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#pragma warning (disable:4100)
|
||||
#pragma warning (disable:4514)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef UTLFIXEDMEMORY_TRACK
|
||||
#define UTLFIXEDMEMORY_TRACK_ALLOC() MemAlloc_RegisterAllocation( "||Sum of all UtlFixedMemory||", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 )
|
||||
#define UTLFIXEDMEMORY_TRACK_FREE() if ( !m_pMemory ) ; else MemAlloc_RegisterDeallocation( "||Sum of all UtlFixedMemory||", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 )
|
||||
#else
|
||||
#define UTLFIXEDMEMORY_TRACK_ALLOC() ((void)0)
|
||||
#define UTLFIXEDMEMORY_TRACK_FREE() ((void)0)
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The CUtlFixedMemory class:
|
||||
// A growable memory class that allocates non-sequential blocks, but is indexed sequentially
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T >
|
||||
class CUtlFixedMemory
|
||||
{
|
||||
public:
|
||||
// constructor, destructor
|
||||
CUtlFixedMemory( int nGrowSize = 0, int nInitSize = 0 );
|
||||
~CUtlFixedMemory();
|
||||
|
||||
// Set the size by which the memory grows
|
||||
void Init( int nGrowSize = 0, int nInitSize = 0 );
|
||||
|
||||
// here to match CUtlMemory, but only used by ResetDbgInfo, so it can just return NULL
|
||||
T* Base() { return NULL; }
|
||||
const T* Base() const { return NULL; }
|
||||
|
||||
protected:
|
||||
struct BlockHeader_t;
|
||||
|
||||
public:
|
||||
class Iterator_t
|
||||
{
|
||||
public:
|
||||
Iterator_t( BlockHeader_t *p, int i ) : m_pBlockHeader( p ), m_nIndex( i ) {}
|
||||
BlockHeader_t *m_pBlockHeader;
|
||||
int m_nIndex;
|
||||
|
||||
bool operator==( const Iterator_t it ) const { return m_pBlockHeader == it.m_pBlockHeader && m_nIndex == it.m_nIndex; }
|
||||
bool operator!=( const Iterator_t it ) const { return m_pBlockHeader != it.m_pBlockHeader || m_nIndex != it.m_nIndex; }
|
||||
};
|
||||
Iterator_t First() const { return m_pBlocks ? Iterator_t( m_pBlocks, 0 ) : InvalidIterator(); }
|
||||
Iterator_t Next( const Iterator_t &it ) const
|
||||
{
|
||||
Assert( IsValidIterator( it ) );
|
||||
if ( !IsValidIterator( it ) )
|
||||
return InvalidIterator();
|
||||
|
||||
BlockHeader_t * RESTRICT pHeader = it.m_pBlockHeader;
|
||||
if ( it.m_nIndex + 1 < pHeader->m_nBlockSize )
|
||||
return Iterator_t( pHeader, it.m_nIndex + 1 );
|
||||
|
||||
return pHeader->m_pNext ? Iterator_t( pHeader->m_pNext, 0 ) : InvalidIterator();
|
||||
}
|
||||
int GetIndex( const Iterator_t &it ) const
|
||||
{
|
||||
Assert( IsValidIterator( it ) );
|
||||
if ( !IsValidIterator( it ) )
|
||||
return InvalidIndex();
|
||||
|
||||
return ( int )( HeaderToBlock( it.m_pBlockHeader ) + it.m_nIndex );
|
||||
}
|
||||
bool IsIdxAfter( int i, const Iterator_t &it ) const
|
||||
{
|
||||
Assert( IsValidIterator( it ) );
|
||||
if ( !IsValidIterator( it ) )
|
||||
return false;
|
||||
|
||||
if ( IsInBlock( i, it.m_pBlockHeader ) )
|
||||
return i > GetIndex( it );
|
||||
|
||||
for ( BlockHeader_t * RESTRICT pbh = it.m_pBlockHeader->m_pNext; pbh; pbh = pbh->m_pNext )
|
||||
{
|
||||
if ( IsInBlock( i, pbh ) )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool IsValidIterator( const Iterator_t &it ) const { return it.m_pBlockHeader && it.m_nIndex >= 0 && it.m_nIndex < it.m_pBlockHeader->m_nBlockSize; }
|
||||
Iterator_t InvalidIterator() const { return Iterator_t( NULL, -1 ); }
|
||||
|
||||
// element access
|
||||
T& operator[]( int i );
|
||||
const T& operator[]( int i ) const;
|
||||
T& Element( int i );
|
||||
const T& Element( int i ) const;
|
||||
|
||||
// Can we use this index?
|
||||
bool IsIdxValid( int i ) const;
|
||||
|
||||
// Specify the invalid ('null') index that we'll only return on failure
|
||||
static const int INVALID_INDEX = 0; // For use with COMPILE_TIME_ASSERT
|
||||
static int InvalidIndex() { return INVALID_INDEX; }
|
||||
|
||||
// Size
|
||||
int NumAllocated() const;
|
||||
int Count() const { return NumAllocated(); }
|
||||
|
||||
// Grows memory by max(num,growsize), and returns the allocation index/ptr
|
||||
void Grow( int num = 1 );
|
||||
|
||||
// Makes sure we've got at least this much memory
|
||||
void EnsureCapacity( int num );
|
||||
|
||||
// Memory deallocation
|
||||
void Purge();
|
||||
|
||||
protected:
|
||||
// Fast swap - WARNING: Swap invalidates all ptr-based indices!!!
|
||||
void Swap( CUtlFixedMemory< T > &mem );
|
||||
|
||||
bool IsInBlock( int i, BlockHeader_t *pBlockHeader ) const
|
||||
{
|
||||
T *p = ( T* )i;
|
||||
const T *p0 = HeaderToBlock( pBlockHeader );
|
||||
return p >= p0 && p < p0 + pBlockHeader->m_nBlockSize;
|
||||
}
|
||||
|
||||
struct BlockHeader_t
|
||||
{
|
||||
BlockHeader_t *m_pNext;
|
||||
int m_nBlockSize;
|
||||
};
|
||||
|
||||
const T *HeaderToBlock( const BlockHeader_t *pHeader ) const { return ( T* )( pHeader + 1 ); }
|
||||
const BlockHeader_t *BlockToHeader( const T *pBlock ) const { return ( BlockHeader_t* )( pBlock ) - 1; }
|
||||
|
||||
BlockHeader_t* m_pBlocks;
|
||||
int m_nAllocationCount;
|
||||
int m_nGrowSize;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// constructor, destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T >
|
||||
CUtlFixedMemory<T>::CUtlFixedMemory( int nGrowSize, int nInitAllocationCount )
|
||||
: m_pBlocks( 0 ), m_nAllocationCount( 0 ), m_nGrowSize( 0 )
|
||||
{
|
||||
Init( nGrowSize, nInitAllocationCount );
|
||||
}
|
||||
|
||||
template< class T >
|
||||
CUtlFixedMemory<T>::~CUtlFixedMemory()
|
||||
{
|
||||
Purge();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Fast swap - WARNING: Swap invalidates all ptr-based indices!!!
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T >
|
||||
void CUtlFixedMemory<T>::Swap( CUtlFixedMemory< T > &mem )
|
||||
{
|
||||
V_swap( m_pBlocks, mem.m_pBlocks );
|
||||
V_swap( m_nAllocationCount, mem.m_nAllocationCount );
|
||||
V_swap( m_nGrowSize, mem.m_nGrowSize );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Set the size by which the memory grows - round up to the next power of 2
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T >
|
||||
void CUtlFixedMemory<T>::Init( int nGrowSize /* = 0 */, int nInitSize /* = 0 */ )
|
||||
{
|
||||
Purge();
|
||||
|
||||
m_nGrowSize = nGrowSize;
|
||||
|
||||
Grow( nInitSize );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// element access
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T >
|
||||
inline T& CUtlFixedMemory<T>::operator[]( int i )
|
||||
{
|
||||
Assert( IsIdxValid(i) );
|
||||
return *( T* )i;
|
||||
}
|
||||
|
||||
template< class T >
|
||||
inline const T& CUtlFixedMemory<T>::operator[]( int i ) const
|
||||
{
|
||||
Assert( IsIdxValid(i) );
|
||||
return *( T* )i;
|
||||
}
|
||||
|
||||
template< class T >
|
||||
inline T& CUtlFixedMemory<T>::Element( int i )
|
||||
{
|
||||
Assert( IsIdxValid(i) );
|
||||
return *( T* )i;
|
||||
}
|
||||
|
||||
template< class T >
|
||||
inline const T& CUtlFixedMemory<T>::Element( int i ) const
|
||||
{
|
||||
Assert( IsIdxValid(i) );
|
||||
return *( T* )i;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Size
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T >
|
||||
inline int CUtlFixedMemory<T>::NumAllocated() const
|
||||
{
|
||||
return m_nAllocationCount;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Is element index valid?
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T >
|
||||
inline bool CUtlFixedMemory<T>::IsIdxValid( int i ) const
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
for ( BlockHeader_t *pbh = m_pBlocks; pbh; pbh = pbh->m_pNext )
|
||||
{
|
||||
if ( IsInBlock( i, pbh ) )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
return i != InvalidIndex();
|
||||
#endif
|
||||
}
|
||||
|
||||
template< class T >
|
||||
void CUtlFixedMemory<T>::Grow( int num )
|
||||
{
|
||||
if ( num <= 0 )
|
||||
return;
|
||||
|
||||
int nBlockSize = m_nGrowSize;
|
||||
if ( nBlockSize == 0 )
|
||||
{
|
||||
if ( m_nAllocationCount )
|
||||
{
|
||||
nBlockSize = m_nAllocationCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Compute an allocation which is at least as big as a cache line...
|
||||
nBlockSize = ( 31 + sizeof( T ) ) / sizeof( T );
|
||||
Assert( nBlockSize );
|
||||
}
|
||||
}
|
||||
if ( nBlockSize < num )
|
||||
{
|
||||
int n = ( num + nBlockSize -1 ) / nBlockSize;
|
||||
Assert( n * nBlockSize >= num );
|
||||
Assert( ( n - 1 ) * nBlockSize < num );
|
||||
nBlockSize *= n;
|
||||
}
|
||||
m_nAllocationCount += nBlockSize;
|
||||
|
||||
MEM_ALLOC_CREDIT_CLASS();
|
||||
BlockHeader_t * RESTRICT pBlockHeader = ( BlockHeader_t* )malloc( sizeof( BlockHeader_t ) + nBlockSize * sizeof( T ) );
|
||||
if ( !pBlockHeader )
|
||||
{
|
||||
Error( "CUtlFixedMemory overflow!\n" );
|
||||
}
|
||||
pBlockHeader->m_pNext = NULL;
|
||||
pBlockHeader->m_nBlockSize = nBlockSize;
|
||||
|
||||
if ( !m_pBlocks )
|
||||
{
|
||||
m_pBlocks = pBlockHeader;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 1 // IsIdxAfter assumes that newly allocated blocks are at the end
|
||||
BlockHeader_t * RESTRICT pbh = m_pBlocks;
|
||||
while ( pbh->m_pNext )
|
||||
{
|
||||
pbh = pbh->m_pNext;
|
||||
}
|
||||
pbh->m_pNext = pBlockHeader;
|
||||
#else
|
||||
pBlockHeader = m_pBlocks;
|
||||
pBlockHeader->m_pNext = m_pBlocks;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Makes sure we've got at least this much memory
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T >
|
||||
inline void CUtlFixedMemory<T>::EnsureCapacity( int num )
|
||||
{
|
||||
Grow( num - NumAllocated() );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memory deallocation
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T >
|
||||
void CUtlFixedMemory<T>::Purge()
|
||||
{
|
||||
if ( !m_pBlocks )
|
||||
return;
|
||||
|
||||
for ( BlockHeader_t *pbh = m_pBlocks; pbh; )
|
||||
{
|
||||
BlockHeader_t *pFree = pbh;
|
||||
pbh = pbh->m_pNext;
|
||||
free( pFree );
|
||||
}
|
||||
m_pBlocks = NULL;
|
||||
m_nAllocationCount = 0;
|
||||
}
|
||||
|
||||
#include "tier0/memdbgoff.h"
|
||||
|
||||
#endif // UTLFIXEDMEMORY_H
|
||||
Vendored
+658
@@ -0,0 +1,658 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Header: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef UTLGRAPH_H
|
||||
#define UTLGRAPH_H
|
||||
|
||||
#include "tier1/utlmap.h"
|
||||
#include "tier1/utlvector.h"
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A Graph class
|
||||
//
|
||||
// Nodes must have a unique Node ID.
|
||||
//
|
||||
// Edges are unidirectional, specified from the beginning node.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <class T, class C >
|
||||
class CUtlGraphVisitor;
|
||||
|
||||
template <class T, class C = int >
|
||||
class CUtlGraph
|
||||
{
|
||||
public:
|
||||
typedef int I;
|
||||
typedef I IndexType_t;
|
||||
typedef T NodeID_t;
|
||||
typedef C CostType_t;
|
||||
|
||||
typedef CUtlGraphVisitor<T,C> Visitor_t;
|
||||
|
||||
struct Edge_t
|
||||
{
|
||||
IndexType_t m_DestinationNode;
|
||||
CostType_t m_EdgeCost;
|
||||
|
||||
Edge_t( IndexType_t i = 0 )
|
||||
{
|
||||
m_DestinationNode = i;
|
||||
m_EdgeCost = 0;
|
||||
}
|
||||
|
||||
bool operator==(const Edge_t &that ) const
|
||||
{
|
||||
return m_DestinationNode == that.m_DestinationNode;
|
||||
}
|
||||
|
||||
static int SortFn( const Edge_t *plhs, const Edge_t *prhs )
|
||||
{
|
||||
if ( plhs->m_EdgeCost < prhs->m_EdgeCost )
|
||||
return -1;
|
||||
else if ( plhs->m_EdgeCost > prhs->m_EdgeCost )
|
||||
return 1;
|
||||
else return 0;
|
||||
}
|
||||
};
|
||||
|
||||
typedef CUtlVector<Edge_t> vecEdges_t;
|
||||
|
||||
// constructor, destructor
|
||||
CUtlGraph( );
|
||||
~CUtlGraph();
|
||||
|
||||
// Add an edge
|
||||
bool AddEdge( T SourceNode, T DestNode, C nCost );
|
||||
|
||||
// Remove an edge
|
||||
bool RemoveEdge( T SourceNode, T DestNode );
|
||||
|
||||
// gets particular elements
|
||||
T& Element( I i );
|
||||
T const &Element( I i ) const;
|
||||
T& operator[]( I i );
|
||||
T const &operator[]( I i ) const;
|
||||
|
||||
// Find a node
|
||||
I Find( T Node ) { return m_Nodes.Find( Node ); }
|
||||
I Find( T Node ) const { return m_Nodes.Find( Node ); }
|
||||
|
||||
// Num elements
|
||||
unsigned int Count() const { return m_Nodes.Count() ; }
|
||||
|
||||
// Max "size" of the vector
|
||||
I MaxElement() const { return m_Nodes.MaxElement(); }
|
||||
|
||||
// Checks if a node is valid and in the graph
|
||||
bool IsValidIndex( I i ) const { return m_Nodes.IsValidIndex( i ); }
|
||||
|
||||
// Checks if the graph as a whole is valid
|
||||
bool IsValid() const { return m_Nodes.IsValid(); }
|
||||
|
||||
// Invalid index
|
||||
static I InvalidIndex() { return CUtlMap< NodeID_t, vecEdges_t*>::InvalidIndex(); }
|
||||
|
||||
// Remove methods
|
||||
void RemoveAt( I i );
|
||||
void RemoveAll();
|
||||
|
||||
// Makes sure we have enough memory allocated to store a requested # of elements
|
||||
void EnsureCapacity( int num );
|
||||
|
||||
// Create Path Matrix once you've added all nodes and edges
|
||||
void CreatePathMatrix();
|
||||
|
||||
// For Visitor classes
|
||||
vecEdges_t *GetEdges( I i );
|
||||
|
||||
// shortest path costs
|
||||
vecEdges_t *GetPathCosts( I i );
|
||||
|
||||
#ifdef DBGFLAG_VALIDATE
|
||||
void Validate( CValidator &validator, const char *pchName );
|
||||
#endif // DBGFLAG_VALIDATE
|
||||
|
||||
protected:
|
||||
|
||||
struct Node_t
|
||||
{
|
||||
vecEdges_t *m_pvecEdges;
|
||||
vecEdges_t *m_pvecPaths;
|
||||
|
||||
Node_t()
|
||||
{
|
||||
m_pvecEdges = NULL;
|
||||
m_pvecPaths = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
CUtlMap< NodeID_t, Node_t > m_Nodes;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A Graph "visitor" class
|
||||
//
|
||||
// From the specified beginning point, visits each node in an expanding radius
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class C = int >
|
||||
class CUtlGraphVisitor
|
||||
{
|
||||
public:
|
||||
CUtlGraphVisitor( CUtlGraph<T, C> &graph );
|
||||
|
||||
bool Begin( T StartNode );
|
||||
bool Advance();
|
||||
|
||||
T CurrentNode();
|
||||
C AccumulatedCost();
|
||||
int CurrentRadius();
|
||||
|
||||
private:
|
||||
|
||||
typedef typename CUtlGraph<T,C>::IndexType_t IndexType_t;
|
||||
typedef typename CUtlGraph<T,C>::Edge_t Edge_t;
|
||||
typedef CUtlVector<Edge_t> vecEdges_t;
|
||||
|
||||
CUtlGraph<T, C> &m_Graph;
|
||||
|
||||
vecEdges_t m_vecVisitQueue;
|
||||
int m_iVisiting;
|
||||
int m_nCurrentRadius;
|
||||
|
||||
vecEdges_t m_vecFringeQueue;
|
||||
|
||||
CUtlVector<T> m_vecNodesVisited;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// constructor, destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <class T, class C >
|
||||
inline CUtlGraph<T, C>::CUtlGraph()
|
||||
{
|
||||
SetDefLessFunc( m_Nodes );
|
||||
}
|
||||
|
||||
template <class T, class C >
|
||||
inline CUtlGraph<T, C>::~CUtlGraph()
|
||||
{
|
||||
RemoveAll();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// gets particular elements
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <class T, class C >
|
||||
inline T &CUtlGraph<T, C>::Element( I i )
|
||||
{
|
||||
return m_Nodes.Key( i );
|
||||
}
|
||||
|
||||
template <class T, class C >
|
||||
inline T const &CUtlGraph<T, C>::Element( I i ) const
|
||||
{
|
||||
return m_Nodes.Key( i );
|
||||
}
|
||||
|
||||
template <class T, class C >
|
||||
inline T &CUtlGraph<T, C>::operator[]( I i )
|
||||
{
|
||||
return Element(i);
|
||||
}
|
||||
|
||||
template <class T, class C >
|
||||
inline T const &CUtlGraph<T, C>::operator[]( I i ) const
|
||||
{
|
||||
return Element(i);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// various accessors
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Removes all nodes from the tree
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <class T, class C >
|
||||
void CUtlGraph<T, C>::RemoveAll()
|
||||
{
|
||||
FOR_EACH_MAP_FAST( m_Nodes, iNode )
|
||||
{
|
||||
delete m_Nodes[iNode].m_pvecEdges;
|
||||
delete m_Nodes[iNode].m_pvecPaths;
|
||||
}
|
||||
|
||||
m_Nodes.RemoveAll();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Makes sure we have enough memory allocated to store a requested # of elements
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class C >
|
||||
void CUtlGraph<T, C>::EnsureCapacity( int num )
|
||||
{
|
||||
m_Nodes.EnsureCapacity(num);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Add an edge
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class C >
|
||||
bool CUtlGraph<T, C>::AddEdge( T SourceNode, T DestNode, C nCost )
|
||||
{
|
||||
I iSrcNode = m_Nodes.Find( SourceNode );
|
||||
if ( !m_Nodes.IsValidIndex( iSrcNode ) )
|
||||
{
|
||||
Node_t Node;
|
||||
Node.m_pvecEdges = new vecEdges_t();
|
||||
Node.m_pvecPaths = new vecEdges_t();
|
||||
iSrcNode = m_Nodes.Insert( SourceNode, Node );
|
||||
}
|
||||
|
||||
I iDstNode = m_Nodes.Find( DestNode );
|
||||
if ( !m_Nodes.IsValidIndex( iDstNode ) )
|
||||
{
|
||||
Node_t Node;
|
||||
Node.m_pvecEdges = new vecEdges_t();
|
||||
Node.m_pvecPaths = new vecEdges_t();
|
||||
iDstNode = m_Nodes.Insert( DestNode, Node );
|
||||
}
|
||||
|
||||
vecEdges_t &vecEdges = *m_Nodes[iSrcNode].m_pvecEdges;
|
||||
|
||||
#ifdef _DEBUG
|
||||
FOR_EACH_VEC( vecEdges, iEdge )
|
||||
{
|
||||
if ( vecEdges[iEdge].m_DestinationNode == iDstNode )
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
Edge_t newEdge;
|
||||
newEdge.m_DestinationNode = iDstNode;
|
||||
newEdge.m_EdgeCost = nCost;
|
||||
|
||||
vecEdges[ vecEdges.AddToTail() ] = newEdge;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Remove an edge
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class C >
|
||||
bool CUtlGraph<T, C>::RemoveEdge( T SourceNode, T DestNode )
|
||||
{
|
||||
I iSrcNode = m_Nodes.Find( SourceNode );
|
||||
if ( !m_Nodes.IsValidIndex( iSrcNode ) )
|
||||
return false;
|
||||
|
||||
I iDstNode = m_Nodes.Find( DestNode );
|
||||
if ( !m_Nodes.IsValidIndex( iDstNode ) )
|
||||
return false;
|
||||
|
||||
vecEdges_t &vecEdges = *m_Nodes[iSrcNode].m_pvecEdges;
|
||||
|
||||
FOR_EACH_VEC( vecEdges, iEdge )
|
||||
{
|
||||
if ( vecEdges[iEdge].m_DestinationNode == iDstNode )
|
||||
{
|
||||
// could use FastRemove, but nodes won't have that
|
||||
// many edges, and the elements are small, and
|
||||
// preserving the original ordering is nice
|
||||
vecEdges.Remove( iEdge );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Get all of a Node's edges
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class C >
|
||||
typename CUtlGraph<T, C>::vecEdges_t *CUtlGraph<T, C>::GetEdges( I i )
|
||||
{
|
||||
return m_Nodes[i].m_pvecEdges;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Get all of a Node's edges
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class C >
|
||||
typename CUtlGraph<T, C>::vecEdges_t *CUtlGraph<T, C>::GetPathCosts( I i )
|
||||
{
|
||||
return m_Nodes[i].m_pvecPaths;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Data and memory validation
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifdef DBGFLAG_VALIDATE
|
||||
template <class T, class C >
|
||||
void CUtlGraph<T, C>::Validate( CValidator &validator, const char *pchName )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
validator.Push( typeid(*this).raw_name(), this, pchName );
|
||||
#else
|
||||
validator.Push( typeid(*this).name(), this, pchName );
|
||||
#endif
|
||||
|
||||
ValidateObj( m_Nodes );
|
||||
|
||||
FOR_EACH_MAP_FAST( m_Nodes, iNode )
|
||||
{
|
||||
validator.ClaimMemory( m_Nodes[iNode].m_pvecEdges );
|
||||
ValidateObj( *m_Nodes[iNode].m_pvecEdges );
|
||||
validator.ClaimMemory( m_Nodes[iNode].m_pvecPaths );
|
||||
ValidateObj( *m_Nodes[iNode].m_pvecPaths );
|
||||
}
|
||||
|
||||
validator.Pop();
|
||||
}
|
||||
#endif // DBGFLAG_VALIDATE
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Get all of a Node's edges
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class C >
|
||||
void CUtlGraph<T, C>::CreatePathMatrix()
|
||||
{
|
||||
int n = MaxElement();
|
||||
|
||||
// Notes
|
||||
// Because CUtlMap stores its nodes in essentially a vector,
|
||||
// we know that we can use its indices in our own path matrix
|
||||
// vectors safely (they will be numbers in the range (0,N) where
|
||||
// N is largest number of nodes ever present in the graph).
|
||||
//
|
||||
// This lets us very quickly access previous best-path estimates
|
||||
// by indexing into a node's vecPaths directly.
|
||||
//
|
||||
// When we are all done, we can then compact the vector, removing
|
||||
// "null" paths, and then sorting by cost.
|
||||
|
||||
// Initialize matrix with all edges
|
||||
FOR_EACH_MAP_FAST( m_Nodes, iNode )
|
||||
{
|
||||
vecEdges_t &vecEdges = *m_Nodes.Element( iNode ).m_pvecEdges;
|
||||
vecEdges_t &vecPaths = *m_Nodes.Element( iNode ).m_pvecPaths;
|
||||
|
||||
vecPaths.RemoveAll();
|
||||
vecPaths.AddMultipleToTail( n );
|
||||
FOR_EACH_VEC( vecPaths, iPath )
|
||||
{
|
||||
vecPaths[iPath].m_DestinationNode = InvalidIndex();
|
||||
}
|
||||
|
||||
// Path to self
|
||||
vecPaths[iNode].m_DestinationNode = iNode;
|
||||
// zero cost to self
|
||||
vecPaths[iNode].m_EdgeCost = 0;
|
||||
|
||||
FOR_EACH_VEC( vecEdges, iEdge )
|
||||
{
|
||||
// Path to a neighbor node - we know exactly what the cost is
|
||||
Edge_t &edge = vecEdges[iEdge];
|
||||
vecPaths[ edge.m_DestinationNode ].m_DestinationNode = edge.m_DestinationNode;
|
||||
vecPaths[ edge.m_DestinationNode ].m_EdgeCost = edge.m_EdgeCost;
|
||||
}
|
||||
}
|
||||
|
||||
// Floyd-Warshall
|
||||
// for k:= 0 to n-1
|
||||
// for each (i,j) in (0..n-1)
|
||||
// path[i][j] = min( path[i][j], path[i][k]+path[k][j] );
|
||||
for ( int k = 0; k < n; ++ k )
|
||||
{
|
||||
if ( !m_Nodes.IsValidIndex( k ) )
|
||||
continue;
|
||||
|
||||
// All current known paths from K
|
||||
vecEdges_t &destMapFromK = *m_Nodes[k].m_pvecPaths;
|
||||
|
||||
for ( int i = 0; i < n; ++i )
|
||||
{
|
||||
if ( !m_Nodes.IsValidIndex( i ) )
|
||||
continue;
|
||||
|
||||
// All current known paths from J
|
||||
vecEdges_t &destMapFromI = *m_Nodes[i].m_pvecPaths;
|
||||
|
||||
// Path from I to K?
|
||||
int iFromIToK = k;
|
||||
bool bFromIToK = destMapFromI[iFromIToK].m_DestinationNode != InvalidIndex();
|
||||
CostType_t cIToK = ( bFromIToK ) ? destMapFromI[iFromIToK].m_EdgeCost : INT_MAX;
|
||||
|
||||
for ( int j = 0; j < n; ++ j )
|
||||
{
|
||||
if ( !m_Nodes.IsValidIndex( j ) )
|
||||
continue;
|
||||
|
||||
// Path from I to J already?
|
||||
int iFromIToJ = j;
|
||||
bool bFromIToJ = destMapFromI[iFromIToJ].m_DestinationNode != InvalidIndex();
|
||||
CostType_t cIToJ = ( bFromIToJ ) ? destMapFromI[iFromIToJ].m_EdgeCost : INT_MAX;
|
||||
|
||||
// Path from K to J?
|
||||
int iFromKToJ = j;
|
||||
bool bFromKToJ = destMapFromK[iFromKToJ].m_DestinationNode != InvalidIndex();
|
||||
CostType_t cKToJ = ( bFromKToJ ) ? destMapFromK[iFromKToJ].m_EdgeCost : INT_MAX;
|
||||
|
||||
// Is the new path valid?
|
||||
bool bNewPathFound = ( bFromIToK && bFromKToJ );
|
||||
|
||||
if ( bNewPathFound )
|
||||
{
|
||||
if ( bFromIToJ )
|
||||
{
|
||||
// Pick min of previous best and current path
|
||||
destMapFromI[iFromIToJ].m_EdgeCost = min( cIToJ, cIToK + cKToJ );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Current path is the first, hence the best so far
|
||||
destMapFromI[iFromIToJ].m_DestinationNode = iFromIToJ;
|
||||
destMapFromI[iFromIToJ].m_EdgeCost = cIToK + cKToJ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up and sort the paths
|
||||
FOR_EACH_MAP_FAST( m_Nodes, iNode )
|
||||
{
|
||||
vecEdges_t &vecPaths = *m_Nodes.Element( iNode ).m_pvecPaths;
|
||||
FOR_EACH_VEC( vecPaths, iPath )
|
||||
{
|
||||
Edge_t &edge = vecPaths[iPath];
|
||||
if ( edge.m_DestinationNode == InvalidIndex() )
|
||||
{
|
||||
// No path to this destination was found.
|
||||
// Remove this entry from the vector.
|
||||
vecPaths.FastRemove( iPath );
|
||||
--iPath; // adjust for the removal
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the vector by cost, given that it
|
||||
// is likely consumers will want to
|
||||
// iterate destinations in that order.
|
||||
vecPaths.Sort( Edge_t::SortFn );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class C >
|
||||
CUtlGraphVisitor<T, C>::CUtlGraphVisitor( CUtlGraph<T,C> &graph )
|
||||
: m_Graph( graph )
|
||||
{
|
||||
m_iVisiting = 0;
|
||||
m_nCurrentRadius = 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Begin visiting the nodes in the graph. Returns false if the start node
|
||||
// does not exist
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class C >
|
||||
bool CUtlGraphVisitor<T, C>::Begin( T StartNode )
|
||||
{
|
||||
m_vecVisitQueue.RemoveAll();
|
||||
m_vecFringeQueue.RemoveAll();
|
||||
m_vecNodesVisited.RemoveAll();
|
||||
m_iVisiting = 0;
|
||||
m_nCurrentRadius = 0;
|
||||
|
||||
IndexType_t iStartNode = m_Graph.Find( StartNode );
|
||||
|
||||
if ( !m_Graph.IsValidIndex( iStartNode ) )
|
||||
return false;
|
||||
|
||||
vecEdges_t *pvecEdges = m_Graph.GetEdges( iStartNode );
|
||||
|
||||
Edge_t edge;
|
||||
edge.m_DestinationNode = iStartNode;
|
||||
edge.m_EdgeCost = 0;
|
||||
|
||||
m_vecVisitQueue[ m_vecVisitQueue.AddToTail() ] = edge;
|
||||
|
||||
m_vecNodesVisited[ m_vecNodesVisited.AddToTail() ] = iStartNode;
|
||||
|
||||
m_vecFringeQueue = *pvecEdges;
|
||||
|
||||
// cells actually get marked as "visited" as soon as we put
|
||||
// them in the fringe queue, so we don't put them in the *next*
|
||||
// fringe queue (we build the fringe queue before we actually visit
|
||||
// the nodes in the new visit queue).
|
||||
FOR_EACH_VEC( m_vecFringeQueue, iFringe )
|
||||
{
|
||||
m_vecNodesVisited[ m_vecNodesVisited.AddToTail() ] = m_vecFringeQueue[iFringe].m_DestinationNode;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Advance to the next node. Returns false when all nodes have been visited
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class C>
|
||||
bool CUtlGraphVisitor<T, C>::Advance()
|
||||
{
|
||||
m_iVisiting++;
|
||||
|
||||
// Is the VisitQueue empty? move outward one radius if so
|
||||
|
||||
if ( m_iVisiting >= m_vecVisitQueue.Count() )
|
||||
{
|
||||
m_nCurrentRadius++;
|
||||
m_iVisiting = 0;
|
||||
m_vecVisitQueue = m_vecFringeQueue;
|
||||
m_vecFringeQueue.RemoveAll();
|
||||
|
||||
if ( !m_vecVisitQueue.Count() )
|
||||
return false;
|
||||
|
||||
// create new fringe queue
|
||||
FOR_EACH_VEC( m_vecVisitQueue, iNode )
|
||||
{
|
||||
Edge_t &node = m_vecVisitQueue[iNode];
|
||||
vecEdges_t &vecEdges = *m_Graph.GetEdges( node.m_DestinationNode );
|
||||
FOR_EACH_VEC( vecEdges, iEdge )
|
||||
{
|
||||
Edge_t &edge = vecEdges[iEdge];
|
||||
if ( m_vecNodesVisited.InvalidIndex() == m_vecNodesVisited.Find( edge.m_DestinationNode ) )
|
||||
{
|
||||
m_vecNodesVisited[ m_vecNodesVisited.AddToTail() ] = edge.m_DestinationNode;
|
||||
|
||||
int iNewFringeNode = m_vecFringeQueue.AddToTail();
|
||||
m_vecFringeQueue[ iNewFringeNode ] = edge;
|
||||
// Accumulate the cost to get to the current point
|
||||
m_vecFringeQueue[ iNewFringeNode ].m_EdgeCost += node.m_EdgeCost;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Get the current node in the visit sequence
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class C>
|
||||
T CUtlGraphVisitor<T, C>::CurrentNode()
|
||||
{
|
||||
if ( m_iVisiting >= m_vecVisitQueue.Count() )
|
||||
{
|
||||
AssertMsg( false, "Visitor invalid" );
|
||||
return T();
|
||||
}
|
||||
|
||||
return m_Graph[ m_vecVisitQueue[ m_iVisiting ].m_DestinationNode ];
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Get the accumulated cost to traverse the graph to the current node
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class C>
|
||||
C CUtlGraphVisitor<T, C>::AccumulatedCost()
|
||||
{
|
||||
if ( m_iVisiting >= m_vecVisitQueue.Count() )
|
||||
{
|
||||
AssertMsg( false, "Visitor invalid" );
|
||||
return C();
|
||||
}
|
||||
|
||||
return m_vecVisitQueue[ m_iVisiting ].m_EdgeCost;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Get the current radius from the start point to this node
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class C>
|
||||
int CUtlGraphVisitor<T, C>::CurrentRadius()
|
||||
{
|
||||
if ( m_iVisiting >= m_vecVisitQueue.Count() )
|
||||
{
|
||||
AssertMsg( false, "Visitor invalid" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m_nCurrentRadius;
|
||||
}
|
||||
|
||||
#endif // UTLGRAPH_H
|
||||
Vendored
+1299
File diff suppressed because it is too large
Load Diff
+1087
File diff suppressed because it is too large
Load Diff
Vendored
+248
@@ -0,0 +1,248 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Header: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef UTLMAP_H
|
||||
#define UTLMAP_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "tier0/dbg.h"
|
||||
#include "utlrbtree.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Purpose: An associative container. Pretty much identical to std::map.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// This is a useful macro to iterate from start to end in order in a map
|
||||
#define FOR_EACH_MAP( mapName, iteratorName ) \
|
||||
for ( int iteratorName = (mapName).FirstInorder(); (mapName).IsUtlMap && iteratorName != (mapName).InvalidIndex(); iteratorName = (mapName).NextInorder( iteratorName ) )
|
||||
|
||||
// faster iteration, but in an unspecified order
|
||||
#define FOR_EACH_MAP_FAST( mapName, iteratorName ) \
|
||||
for ( int iteratorName = 0; (mapName).IsUtlMap && iteratorName < (mapName).MaxElement(); ++iteratorName ) if ( !(mapName).IsValidIndex( iteratorName ) ) continue; else
|
||||
|
||||
struct base_utlmap_t
|
||||
{
|
||||
public:
|
||||
static const bool IsUtlMap = true; // Used to match this at compiletime
|
||||
};
|
||||
|
||||
#if defined( GNUC ) && defined( DEBUG )
|
||||
const bool base_utlmap_t::IsUtlMap SELECTANY;
|
||||
#endif
|
||||
|
||||
template <typename K, typename T, typename I = unsigned short>
|
||||
class CUtlMap : public base_utlmap_t
|
||||
{
|
||||
public:
|
||||
typedef K KeyType_t;
|
||||
typedef T ElemType_t;
|
||||
typedef I IndexType_t;
|
||||
|
||||
// Less func typedef
|
||||
// Returns true if the first parameter is "less" than the second
|
||||
typedef bool (*LessFunc_t)( const KeyType_t &, const KeyType_t & );
|
||||
|
||||
// constructor, destructor
|
||||
// Left at growSize = 0, the memory will first allocate 1 element and double in size
|
||||
// at each increment.
|
||||
// LessFunc_t is required, but may be set after the constructor using SetLessFunc() below
|
||||
CUtlMap( int growSize = 0, int initSize = 0, LessFunc_t lessfunc = 0 )
|
||||
: m_Tree( growSize, initSize, CKeyLess( lessfunc ) )
|
||||
{
|
||||
}
|
||||
|
||||
CUtlMap( LessFunc_t lessfunc )
|
||||
: m_Tree( CKeyLess( lessfunc ) )
|
||||
{
|
||||
}
|
||||
|
||||
void EnsureCapacity( int num ) { m_Tree.EnsureCapacity( num ); }
|
||||
|
||||
// gets particular elements
|
||||
ElemType_t & Element( IndexType_t i ) { return m_Tree.Element( i ).elem; }
|
||||
const ElemType_t & Element( IndexType_t i ) const { return m_Tree.Element( i ).elem; }
|
||||
ElemType_t & operator[]( IndexType_t i ) { return m_Tree.Element( i ).elem; }
|
||||
const ElemType_t & operator[]( IndexType_t i ) const { return m_Tree.Element( i ).elem; }
|
||||
KeyType_t & Key( IndexType_t i ) { return m_Tree.Element( i ).key; }
|
||||
const KeyType_t & Key( IndexType_t i ) const { return m_Tree.Element( i ).key; }
|
||||
|
||||
|
||||
// Num elements
|
||||
unsigned int Count() const { return m_Tree.Count(); }
|
||||
|
||||
// Max "size" of the vector
|
||||
IndexType_t MaxElement() const { return m_Tree.MaxElement(); }
|
||||
|
||||
// Checks if a node is valid and in the map
|
||||
bool IsValidIndex( IndexType_t i ) const { return m_Tree.IsValidIndex( i ); }
|
||||
|
||||
// Checks if the map as a whole is valid
|
||||
bool IsValid() const { return m_Tree.IsValid(); }
|
||||
|
||||
// Invalid index
|
||||
static IndexType_t InvalidIndex() { return CTree::InvalidIndex(); }
|
||||
|
||||
// Sets the less func
|
||||
void SetLessFunc( LessFunc_t func )
|
||||
{
|
||||
m_Tree.SetLessFunc( CKeyLess( func ) );
|
||||
}
|
||||
|
||||
// Insert method (inserts in order)
|
||||
IndexType_t Insert( const KeyType_t &key, const ElemType_t &insert )
|
||||
{
|
||||
Node_t node;
|
||||
node.key = key;
|
||||
node.elem = insert;
|
||||
return m_Tree.Insert( node );
|
||||
}
|
||||
|
||||
IndexType_t Insert( const KeyType_t &key )
|
||||
{
|
||||
Node_t node;
|
||||
node.key = key;
|
||||
return m_Tree.Insert( node );
|
||||
}
|
||||
|
||||
// Find method
|
||||
IndexType_t Find( const KeyType_t &key ) const
|
||||
{
|
||||
Node_t dummyNode;
|
||||
dummyNode.key = key;
|
||||
return m_Tree.Find( dummyNode );
|
||||
}
|
||||
|
||||
// Remove methods
|
||||
void RemoveAt( IndexType_t i ) { m_Tree.RemoveAt( i ); }
|
||||
bool Remove( const KeyType_t &key )
|
||||
{
|
||||
Node_t dummyNode;
|
||||
dummyNode.key = key;
|
||||
return m_Tree.Remove( dummyNode );
|
||||
}
|
||||
|
||||
void RemoveAll( ) { m_Tree.RemoveAll(); }
|
||||
void Purge( ) { m_Tree.Purge(); }
|
||||
|
||||
// Purges the list and calls delete on each element in it.
|
||||
void PurgeAndDeleteElements();
|
||||
|
||||
// Iteration
|
||||
IndexType_t FirstInorder() const { return m_Tree.FirstInorder(); }
|
||||
IndexType_t NextInorder( IndexType_t i ) const { return m_Tree.NextInorder( i ); }
|
||||
IndexType_t PrevInorder( IndexType_t i ) const { return m_Tree.PrevInorder( i ); }
|
||||
IndexType_t LastInorder() const { return m_Tree.LastInorder(); }
|
||||
|
||||
// If you change the search key, this can be used to reinsert the
|
||||
// element into the map.
|
||||
void Reinsert( const KeyType_t &key, IndexType_t i )
|
||||
{
|
||||
m_Tree[i].key = key;
|
||||
m_Tree.Reinsert(i);
|
||||
}
|
||||
|
||||
IndexType_t InsertOrReplace( const KeyType_t &key, const ElemType_t &insert )
|
||||
{
|
||||
IndexType_t i = Find( key );
|
||||
if ( i != InvalidIndex() )
|
||||
{
|
||||
Element( i ) = insert;
|
||||
return i;
|
||||
}
|
||||
|
||||
return Insert( key, insert );
|
||||
}
|
||||
|
||||
void Swap( CUtlMap< K, T, I > &that )
|
||||
{
|
||||
m_Tree.Swap( that.m_Tree );
|
||||
}
|
||||
|
||||
|
||||
struct Node_t
|
||||
{
|
||||
Node_t()
|
||||
{
|
||||
}
|
||||
|
||||
Node_t( const Node_t &from )
|
||||
: key( from.key ),
|
||||
elem( from.elem )
|
||||
{
|
||||
}
|
||||
|
||||
KeyType_t key;
|
||||
ElemType_t elem;
|
||||
};
|
||||
|
||||
class CKeyLess
|
||||
{
|
||||
public:
|
||||
CKeyLess( LessFunc_t lessFunc ) : m_LessFunc(lessFunc) {}
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
return !m_LessFunc;
|
||||
}
|
||||
|
||||
bool operator()( const Node_t &left, const Node_t &right ) const
|
||||
{
|
||||
return m_LessFunc( left.key, right.key );
|
||||
}
|
||||
|
||||
LessFunc_t m_LessFunc;
|
||||
};
|
||||
|
||||
typedef CUtlRBTree<Node_t, I, CKeyLess> CTree;
|
||||
|
||||
CTree *AccessTree() { return &m_Tree; }
|
||||
|
||||
protected:
|
||||
CTree m_Tree;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Purges the list and calls delete on each element in it.
|
||||
template< typename K, typename T, typename I >
|
||||
inline void CUtlMap<K, T, I>::PurgeAndDeleteElements()
|
||||
{
|
||||
for ( I i = 0; i < MaxElement(); ++i )
|
||||
{
|
||||
if ( !IsValidIndex( i ) )
|
||||
continue;
|
||||
|
||||
delete Element( i );
|
||||
}
|
||||
|
||||
Purge();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// This is horrible and slow and meant to be used only when you're dealing with really
|
||||
// non-time/memory-critical code and desperately want to copy a whole map element-by-element
|
||||
// for whatever reason.
|
||||
template < typename K, typename T, typename I >
|
||||
void DeepCopyMap( const CUtlMap<K,T,I>& pmapIn, CUtlMap<K,T,I> *out_pmapOut )
|
||||
{
|
||||
Assert( out_pmapOut );
|
||||
|
||||
out_pmapOut->Purge();
|
||||
FOR_EACH_MAP_FAST( pmapIn, i )
|
||||
{
|
||||
out_pmapOut->Insert( i, pmapIn[i] );
|
||||
}
|
||||
}
|
||||
|
||||
#endif // UTLMAP_H
|
||||
+1090
File diff suppressed because it is too large
Load Diff
+769
@@ -0,0 +1,769 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Multiple linked list container class
|
||||
//
|
||||
// $Revision: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef UTLMULTILIST_H
|
||||
#define UTLMULTILIST_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "utllinkedlist.h"
|
||||
|
||||
// memdbgon must be the last include file in a .h file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// class CUtlMultiList:
|
||||
// description:
|
||||
// A lovely index-based linked list! T is the class type, I is the index
|
||||
// type, which usually should be an unsigned short or smaller.
|
||||
// This list can contain multiple lists
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
class CUtlMultiList
|
||||
{
|
||||
protected:
|
||||
// What the linked list element looks like
|
||||
struct ListElem_t
|
||||
{
|
||||
T m_Element;
|
||||
I m_Previous;
|
||||
I m_Next;
|
||||
};
|
||||
|
||||
struct List_t
|
||||
{
|
||||
I m_Head;
|
||||
I m_Tail;
|
||||
I m_Count;
|
||||
};
|
||||
|
||||
typedef CUtlMemory<ListElem_t> M; // Keep naming similar to CUtlLinkedList
|
||||
public:
|
||||
typedef I ListHandle_t;
|
||||
|
||||
// constructor, destructor
|
||||
CUtlMultiList( int growSize = 0, int initSize = 0 );
|
||||
CUtlMultiList( void *pMemory, int memsize );
|
||||
~CUtlMultiList( );
|
||||
|
||||
// gets particular elements
|
||||
T& Element( I i );
|
||||
T const& Element( I i ) const;
|
||||
T& operator[]( I i );
|
||||
T const& operator[]( I i ) const;
|
||||
|
||||
// Make sure we have a particular amount of memory
|
||||
void EnsureCapacity( int num );
|
||||
|
||||
// Memory deallocation
|
||||
void Purge();
|
||||
|
||||
// List Creation/deletion
|
||||
ListHandle_t CreateList();
|
||||
void DestroyList( ListHandle_t list );
|
||||
bool IsValidList( ListHandle_t list ) const;
|
||||
|
||||
// Insertion methods (call default constructor)....
|
||||
I InsertBefore( ListHandle_t list, I before );
|
||||
I InsertAfter( ListHandle_t list, I after );
|
||||
I AddToHead( ListHandle_t list );
|
||||
I AddToTail( ListHandle_t list );
|
||||
|
||||
// Insertion methods (call copy constructor)....
|
||||
I InsertBefore( ListHandle_t list, I before, T const& src );
|
||||
I InsertAfter( ListHandle_t list, I after, T const& src );
|
||||
I AddToHead( ListHandle_t list, T const& src );
|
||||
I AddToTail( ListHandle_t list, T const& src );
|
||||
|
||||
// Removal methods
|
||||
void Remove( ListHandle_t list, I elem );
|
||||
|
||||
// Removes all items in a single list
|
||||
void RemoveAll( ListHandle_t list );
|
||||
|
||||
// Removes all items in all lists
|
||||
void RemoveAll();
|
||||
|
||||
// Allocation/deallocation methods
|
||||
// NOTE: To free, it must *not* be in a list!
|
||||
I Alloc( );
|
||||
void Free( I elem );
|
||||
|
||||
// list modification
|
||||
void LinkBefore( ListHandle_t list, I before, I elem );
|
||||
void LinkAfter( ListHandle_t list, I after, I elem );
|
||||
void Unlink( ListHandle_t list, I elem );
|
||||
void LinkToHead( ListHandle_t list, I elem );
|
||||
void LinkToTail( ListHandle_t list, I elem );
|
||||
|
||||
// invalid index
|
||||
static I InvalidIndex() { return (I)~0; }
|
||||
static bool IndexInRange( int index );
|
||||
static size_t ElementSize() { return sizeof(ListElem_t); }
|
||||
|
||||
// list statistics
|
||||
int Count( ListHandle_t list ) const;
|
||||
int TotalCount( ) const;
|
||||
I MaxElementIndex() const;
|
||||
|
||||
// Traversing the list
|
||||
I Head( ListHandle_t list ) const;
|
||||
I Tail( ListHandle_t list ) const;
|
||||
I Previous( I element ) const;
|
||||
I Next( I element ) const;
|
||||
|
||||
// Are nodes in a list or valid?
|
||||
bool IsValidIndex( I i ) const;
|
||||
bool IsInList( I i ) const;
|
||||
|
||||
protected:
|
||||
// constructs the class
|
||||
void ConstructList( );
|
||||
|
||||
// Gets at the list element....
|
||||
ListElem_t& InternalElement( I i ) { return m_Memory[i]; }
|
||||
ListElem_t const& InternalElement( I i ) const { return m_Memory[i]; }
|
||||
|
||||
// A test for debug mode only...
|
||||
bool IsElementInList( ListHandle_t list, I elem ) const;
|
||||
|
||||
// copy constructors not allowed
|
||||
CUtlMultiList( CUtlMultiList<T, I> const& list ) { Assert(0); }
|
||||
|
||||
M m_Memory;
|
||||
CUtlLinkedList<List_t, I> m_List;
|
||||
I* m_pElementList;
|
||||
|
||||
I m_FirstFree;
|
||||
I m_TotalElements;
|
||||
int m_MaxElementIndex; // The number allocated (use int so we can catch overflow)
|
||||
|
||||
void ResetDbgInfo()
|
||||
{
|
||||
m_pElements = m_Memory.Base();
|
||||
|
||||
#ifdef _DEBUG
|
||||
// Allocate space for the element list (which list is each element in)
|
||||
if (m_Memory.NumAllocated() > 0)
|
||||
{
|
||||
if (!m_pElementList)
|
||||
{
|
||||
m_pElementList = (I*)malloc( m_Memory.NumAllocated() * sizeof(I) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pElementList = (I*)realloc( m_pElementList, m_Memory.NumAllocated() * sizeof(I) );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// For debugging purposes;
|
||||
// it's in release builds so this can be used in libraries correctly
|
||||
ListElem_t *m_pElements;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// constructor, destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <class T, class I>
|
||||
CUtlMultiList<T,I>::CUtlMultiList( int growSize, int initSize ) :
|
||||
m_Memory(growSize, initSize), m_pElementList(0)
|
||||
{
|
||||
ConstructList();
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
CUtlMultiList<T,I>::CUtlMultiList( void* pMemory, int memsize ) :
|
||||
m_Memory((ListElem_t *)pMemory, memsize/sizeof(ListElem_t)), m_pElementList(0)
|
||||
{
|
||||
ConstructList();
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
CUtlMultiList<T,I>::~CUtlMultiList( )
|
||||
{
|
||||
RemoveAll();
|
||||
if (m_pElementList)
|
||||
free(m_pElementList);
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
void CUtlMultiList<T,I>::ConstructList( )
|
||||
{
|
||||
m_FirstFree = InvalidIndex();
|
||||
m_TotalElements = 0;
|
||||
m_MaxElementIndex = 0;
|
||||
ResetDbgInfo();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// gets particular elements
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
inline T& CUtlMultiList<T,I>::Element( I i )
|
||||
{
|
||||
return m_Memory[i].m_Element;
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline T const& CUtlMultiList<T,I>::Element( I i ) const
|
||||
{
|
||||
return m_Memory[i].m_Element;
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline T& CUtlMultiList<T,I>::operator[]( I i )
|
||||
{
|
||||
return m_Memory[i].m_Element;
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline T const& CUtlMultiList<T,I>::operator[]( I i ) const
|
||||
{
|
||||
return m_Memory[i].m_Element;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// list creation/destruction
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
typename CUtlMultiList<T,I>::ListHandle_t CUtlMultiList<T,I>::CreateList()
|
||||
{
|
||||
ListHandle_t l = m_List.AddToTail();
|
||||
m_List[l].m_Head = m_List[l].m_Tail = InvalidIndex();
|
||||
m_List[l].m_Count = 0;
|
||||
return l;
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
void CUtlMultiList<T,I>::DestroyList( ListHandle_t list )
|
||||
{
|
||||
Assert( IsValidList(list) );
|
||||
RemoveAll( list );
|
||||
m_List.Remove(list);
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
bool CUtlMultiList<T,I>::IsValidList( ListHandle_t list ) const
|
||||
{
|
||||
return m_List.IsValidIndex(list);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// list statistics
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
inline int CUtlMultiList<T,I>::TotalCount() const
|
||||
{
|
||||
return m_TotalElements;
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline int CUtlMultiList<T,I>::Count( ListHandle_t list ) const
|
||||
{
|
||||
Assert( IsValidList(list) );
|
||||
return m_List[list].m_Count;
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline I CUtlMultiList<T,I>::MaxElementIndex() const
|
||||
{
|
||||
return m_MaxElementIndex;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Traversing the list
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
inline I CUtlMultiList<T,I>::Head(ListHandle_t list) const
|
||||
{
|
||||
Assert( IsValidList(list) );
|
||||
return m_List[list].m_Head;
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline I CUtlMultiList<T,I>::Tail(ListHandle_t list) const
|
||||
{
|
||||
Assert( IsValidList(list) );
|
||||
return m_List[list].m_Tail;
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline I CUtlMultiList<T,I>::Previous( I i ) const
|
||||
{
|
||||
Assert( IsValidIndex(i) );
|
||||
return InternalElement(i).m_Previous;
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline I CUtlMultiList<T,I>::Next( I i ) const
|
||||
{
|
||||
Assert( IsValidIndex(i) );
|
||||
return InternalElement(i).m_Next;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Are nodes in the list or valid?
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <class T, class I>
|
||||
inline bool CUtlMultiList<T,I>::IndexInRange( int index ) // Static method
|
||||
{
|
||||
// Since I is not necessarily the type returned by M (int), we need to check that M returns
|
||||
// indices which are representable by I. A common case is 'I === unsigned short', in which case
|
||||
// case CUtlMemory will have 'InvalidIndex == (int)-1' (which casts to 65535 in I), and will
|
||||
// happily return elements at index 65535 and above.
|
||||
|
||||
// Do a couple of static checks here: the invalid index should be (I)~0 given how we use m_MaxElementIndex,
|
||||
// and 'I' should be unsigned (to avoid signed arithmetic errors for plausibly exhaustible ranges).
|
||||
COMPILE_TIME_ASSERT( (I)M::INVALID_INDEX == (I)~0 );
|
||||
COMPILE_TIME_ASSERT( ( sizeof(I) > 2 ) || ( ( (I)-1 ) > 0 ) );
|
||||
|
||||
return ( ( (I)index == index ) && ( (I)index != InvalidIndex() ) );
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline bool CUtlMultiList<T,I>::IsValidIndex( I i ) const
|
||||
{
|
||||
// GCC warns if I is an unsigned type and we do a ">= 0" against it (since the comparison is always 0).
|
||||
// We get the warning even if we cast inside the expression. It only goes away if we assign to another variable.
|
||||
long x = i;
|
||||
|
||||
return (i < m_MaxElementIndex) && (x >= 0) &&
|
||||
((m_Memory[i].m_Previous != i) || (m_Memory[i].m_Next == i));
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline bool CUtlMultiList<T,I>::IsInList( I i ) const
|
||||
{
|
||||
// GCC warns if I is an unsigned type and we do a ">= 0" against it (since the comparison is always 0).
|
||||
// We get the warning even if we cast inside the expression. It only goes away if we assign to another variable.
|
||||
long x = i;
|
||||
return (i < m_MaxElementIndex) && (x >= 0) && (Previous(i) != i);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Makes sure we have enough memory allocated to store a requested # of elements
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T, class I >
|
||||
void CUtlMultiList<T, I>::EnsureCapacity( int num )
|
||||
{
|
||||
m_Memory.EnsureCapacity(num);
|
||||
ResetDbgInfo();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Deallocate memory
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
void CUtlMultiList<T,I>::Purge()
|
||||
{
|
||||
RemoveAll();
|
||||
m_List.Purge();
|
||||
m_Memory.Purge( );
|
||||
m_List.Purge();
|
||||
m_FirstFree = InvalidIndex();
|
||||
m_TotalElements = 0;
|
||||
m_MaxElementIndex = 0;
|
||||
ResetDbgInfo();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Node allocation/deallocation
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
I CUtlMultiList<T,I>::Alloc( )
|
||||
{
|
||||
I elem;
|
||||
if (m_FirstFree == InvalidIndex())
|
||||
{
|
||||
// We can overflow before the utlmemory overflows, since we have have I != int
|
||||
if ( !IndexInRange( m_MaxElementIndex ) )
|
||||
{
|
||||
ExecuteNTimes( 10, Warning( "CUtlMultiList overflow! (exhausted index range)\n" ) );
|
||||
return InvalidIndex();
|
||||
}
|
||||
|
||||
// Nothing in the free list; add.
|
||||
// Since nothing is in the free list, m_TotalElements == total # of elements
|
||||
// the list knows about.
|
||||
if (m_MaxElementIndex == m_Memory.NumAllocated())
|
||||
{
|
||||
m_Memory.Grow();
|
||||
ResetDbgInfo();
|
||||
|
||||
if ( m_MaxElementIndex >= m_Memory.NumAllocated() )
|
||||
{
|
||||
ExecuteNTimes( 10, Warning( "CUtlMultiList overflow! (exhausted memory allocator)\n" ) );
|
||||
return InvalidIndex();
|
||||
}
|
||||
}
|
||||
|
||||
elem = (I)m_MaxElementIndex;
|
||||
++m_MaxElementIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
elem = m_FirstFree;
|
||||
m_FirstFree = InternalElement(m_FirstFree).m_Next;
|
||||
}
|
||||
|
||||
// Mark the element as not being in a list
|
||||
InternalElement(elem).m_Next = InternalElement(elem).m_Previous = elem;
|
||||
|
||||
++m_TotalElements;
|
||||
|
||||
Construct( &Element(elem) );
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
void CUtlMultiList<T,I>::Free( I elem )
|
||||
{
|
||||
Assert( IsValidIndex(elem) && !IsInList(elem) );
|
||||
Destruct( &Element(elem) );
|
||||
InternalElement(elem).m_Next = m_FirstFree;
|
||||
m_FirstFree = elem;
|
||||
--m_TotalElements;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A test for debug mode only...
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
inline bool CUtlMultiList<T,I>::IsElementInList( ListHandle_t list, I elem ) const
|
||||
{
|
||||
if (!m_pElementList)
|
||||
return true;
|
||||
|
||||
return m_pElementList[elem] == list;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// list modification
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
void CUtlMultiList<T,I>::LinkBefore( ListHandle_t list, I before, I elem )
|
||||
{
|
||||
Assert( IsValidIndex(elem) && IsValidList(list) );
|
||||
|
||||
// Unlink it if it's in the list at the moment
|
||||
Unlink(list, elem);
|
||||
|
||||
ListElem_t& newElem = InternalElement(elem);
|
||||
|
||||
// The element *after* our newly linked one is the one we linked before.
|
||||
newElem.m_Next = before;
|
||||
|
||||
if (before == InvalidIndex())
|
||||
{
|
||||
// In this case, we're linking to the end of the list, so reset the tail
|
||||
newElem.m_Previous = m_List[list].m_Tail;
|
||||
m_List[list].m_Tail = elem;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Here, we're not linking to the end. Set the prev pointer to point to
|
||||
// the element we're linking.
|
||||
Assert( IsInList(before) );
|
||||
ListElem_t& beforeElem = InternalElement(before);
|
||||
newElem.m_Previous = beforeElem.m_Previous;
|
||||
beforeElem.m_Previous = elem;
|
||||
}
|
||||
|
||||
// Reset the head if we linked to the head of the list
|
||||
if (newElem.m_Previous == InvalidIndex())
|
||||
m_List[list].m_Head = elem;
|
||||
else
|
||||
InternalElement(newElem.m_Previous).m_Next = elem;
|
||||
|
||||
// one more element baby
|
||||
++m_List[list].m_Count;
|
||||
|
||||
// Store the element into the list
|
||||
if (m_pElementList)
|
||||
m_pElementList[elem] = list;
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
void CUtlMultiList<T,I>::LinkAfter( ListHandle_t list, I after, I elem )
|
||||
{
|
||||
Assert( IsValidIndex(elem) );
|
||||
|
||||
// Unlink it if it's in the list at the moment
|
||||
Unlink(list, elem);
|
||||
|
||||
ListElem_t& newElem = InternalElement(elem);
|
||||
|
||||
// The element *before* our newly linked one is the one we linked after
|
||||
newElem.m_Previous = after;
|
||||
if (after == InvalidIndex())
|
||||
{
|
||||
// In this case, we're linking to the head of the list, reset the head
|
||||
newElem.m_Next = m_List[list].m_Head;
|
||||
m_List[list].m_Head = elem;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Here, we're not linking to the end. Set the next pointer to point to
|
||||
// the element we're linking.
|
||||
Assert( IsInList(after) );
|
||||
ListElem_t& afterElem = InternalElement(after);
|
||||
newElem.m_Next = afterElem.m_Next;
|
||||
afterElem.m_Next = elem;
|
||||
}
|
||||
|
||||
// Reset the tail if we linked to the tail of the list
|
||||
if (newElem.m_Next == InvalidIndex())
|
||||
m_List[list].m_Tail = elem;
|
||||
else
|
||||
InternalElement(newElem.m_Next).m_Previous = elem;
|
||||
|
||||
// one more element baby
|
||||
++m_List[list].m_Count;
|
||||
|
||||
// Store the element into the list
|
||||
if (m_pElementList)
|
||||
m_pElementList[elem] = list;
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
void CUtlMultiList<T,I>::Unlink( ListHandle_t list, I elem )
|
||||
{
|
||||
Assert( IsValidIndex(elem) && IsValidList(list) );
|
||||
|
||||
if (IsInList(elem))
|
||||
{
|
||||
// Make sure the element is in the right list
|
||||
Assert( IsElementInList( list, elem ) );
|
||||
ListElem_t& oldElem = InternalElement(elem);
|
||||
|
||||
// If we're the first guy, reset the head
|
||||
// otherwise, make our previous node's next pointer = our next
|
||||
if (oldElem.m_Previous != InvalidIndex())
|
||||
InternalElement(oldElem.m_Previous).m_Next = oldElem.m_Next;
|
||||
else
|
||||
m_List[list].m_Head = oldElem.m_Next;
|
||||
|
||||
// If we're the last guy, reset the tail
|
||||
// otherwise, make our next node's prev pointer = our prev
|
||||
if (oldElem.m_Next != InvalidIndex())
|
||||
InternalElement(oldElem.m_Next).m_Previous = oldElem.m_Previous;
|
||||
else
|
||||
m_List[list].m_Tail = oldElem.m_Previous;
|
||||
|
||||
// This marks this node as not in the list,
|
||||
// but not in the free list either
|
||||
oldElem.m_Previous = oldElem.m_Next = elem;
|
||||
|
||||
// One less puppy
|
||||
--m_List[list].m_Count;
|
||||
|
||||
// Store the element into the list
|
||||
if (m_pElementList)
|
||||
m_pElementList[elem] = m_List.InvalidIndex();
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline void CUtlMultiList<T,I>::LinkToHead( ListHandle_t list, I elem )
|
||||
{
|
||||
LinkAfter( list, InvalidIndex(), elem );
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline void CUtlMultiList<T,I>::LinkToTail( ListHandle_t list, I elem )
|
||||
{
|
||||
LinkBefore( list, InvalidIndex(), elem );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Insertion methods; allocates and links (uses default constructor)
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
I CUtlMultiList<T,I>::InsertBefore( ListHandle_t list, I before )
|
||||
{
|
||||
// Make a new node
|
||||
I newNode = Alloc();
|
||||
if ( newNode == InvalidIndex() )
|
||||
return newNode;
|
||||
|
||||
// Link it in
|
||||
LinkBefore( list, before, newNode );
|
||||
|
||||
// Construct the data
|
||||
Construct( &Element(newNode) );
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
I CUtlMultiList<T,I>::InsertAfter( ListHandle_t list, I after )
|
||||
{
|
||||
// Make a new node
|
||||
I newNode = Alloc();
|
||||
if ( newNode == InvalidIndex() )
|
||||
return newNode;
|
||||
|
||||
// Link it in
|
||||
LinkAfter( list, after, newNode );
|
||||
|
||||
// Construct the data
|
||||
Construct( &Element(newNode) );
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline I CUtlMultiList<T,I>::AddToHead( ListHandle_t list )
|
||||
{
|
||||
return InsertAfter( list, InvalidIndex() );
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline I CUtlMultiList<T,I>::AddToTail( ListHandle_t list )
|
||||
{
|
||||
return InsertBefore( list, InvalidIndex() );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Insertion methods; allocates and links (uses copy constructor)
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
I CUtlMultiList<T,I>::InsertBefore( ListHandle_t list, I before, T const& src )
|
||||
{
|
||||
// Make a new node
|
||||
I newNode = Alloc();
|
||||
if ( newNode == InvalidIndex() )
|
||||
return newNode;
|
||||
|
||||
// Link it in
|
||||
LinkBefore( list, before, newNode );
|
||||
|
||||
// Construct the data
|
||||
CopyConstruct( &Element(newNode), src );
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
I CUtlMultiList<T,I>::InsertAfter( ListHandle_t list, I after, T const& src )
|
||||
{
|
||||
// Make a new node
|
||||
I newNode = Alloc();
|
||||
if ( newNode == InvalidIndex() )
|
||||
return newNode;
|
||||
|
||||
// Link it in
|
||||
LinkAfter( list, after, newNode );
|
||||
|
||||
// Construct the data
|
||||
CopyConstruct( &Element(newNode), src );
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline I CUtlMultiList<T,I>::AddToHead( ListHandle_t list, T const& src )
|
||||
{
|
||||
return InsertAfter( list, InvalidIndex(), src );
|
||||
}
|
||||
|
||||
template <class T, class I>
|
||||
inline I CUtlMultiList<T,I>::AddToTail( ListHandle_t list, T const& src )
|
||||
{
|
||||
return InsertBefore( list, InvalidIndex(), src );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Removal methods
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class I>
|
||||
void CUtlMultiList<T,I>::Remove( ListHandle_t list, I elem )
|
||||
{
|
||||
if (IsInList(elem))
|
||||
Unlink(list, elem);
|
||||
Free( elem );
|
||||
}
|
||||
|
||||
// Removes all items in a single list
|
||||
template <class T, class I>
|
||||
void CUtlMultiList<T,I>::RemoveAll( ListHandle_t list )
|
||||
{
|
||||
Assert( IsValidList(list) );
|
||||
I i = Head(list);
|
||||
I next;
|
||||
while( i != InvalidIndex() )
|
||||
{
|
||||
next = Next(i);
|
||||
Remove(list, i);
|
||||
i = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class T, class I>
|
||||
void CUtlMultiList<T,I>::RemoveAll()
|
||||
{
|
||||
if (m_MaxElementIndex == 0)
|
||||
return;
|
||||
|
||||
// Put everything into the free list
|
||||
I prev = InvalidIndex();
|
||||
for (int i = (int)m_MaxElementIndex; --i >= 0; )
|
||||
{
|
||||
// Invoke the destructor
|
||||
if (IsValidIndex((I)i))
|
||||
Destruct( &Element((I)i) );
|
||||
|
||||
// next points to the next free list item
|
||||
InternalElement((I)i).m_Next = prev;
|
||||
|
||||
// Indicates it's in the free list
|
||||
InternalElement((I)i).m_Previous = (I)i;
|
||||
prev = (I)i;
|
||||
}
|
||||
|
||||
// First free points to the first element
|
||||
m_FirstFree = 0;
|
||||
|
||||
// Clear everything else out
|
||||
for (I list = m_List.Head(); list != m_List.InvalidIndex(); list = m_List.Next(list) )
|
||||
{
|
||||
m_List[list].m_Head = InvalidIndex();
|
||||
m_List[list].m_Tail = InvalidIndex();
|
||||
m_List[list].m_Count = 0;
|
||||
}
|
||||
|
||||
m_TotalElements = 0;
|
||||
}
|
||||
|
||||
|
||||
#include "tier0/memdbgoff.h"
|
||||
|
||||
#endif // UTLMULTILIST_H
|
||||
Vendored
+176
@@ -0,0 +1,176 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef UTLQUEUE_H
|
||||
#define UTLQUEUE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "utlvector.h"
|
||||
|
||||
// T is the type stored in the queue
|
||||
template< class T, class M = CUtlMemory< T > >
|
||||
class CUtlQueue
|
||||
{
|
||||
public:
|
||||
|
||||
// constructor: lessfunc is required, but may be set after the constructor with
|
||||
// SetLessFunc
|
||||
CUtlQueue( int growSize = 0, int initSize = 0 );
|
||||
CUtlQueue( T *pMemory, int numElements );
|
||||
|
||||
// element access
|
||||
T& operator[]( int i );
|
||||
T const& operator[]( int i ) const;
|
||||
T& Element( int i );
|
||||
T const& Element( int i ) const;
|
||||
|
||||
// return the item from the front of the queue and delete it
|
||||
T const& RemoveAtHead();
|
||||
// return the item from the end of the queue and delete it
|
||||
T const& RemoveAtTail();
|
||||
|
||||
// return item at the front of the queue
|
||||
T const& Head();
|
||||
// return item at the end of the queue
|
||||
T const& Tail();
|
||||
|
||||
// put a new item on the queue to the tail.
|
||||
void Insert( T const &element );
|
||||
|
||||
// checks if an element of this value already exists on the queue, returns true if it does
|
||||
bool Check( T const element );
|
||||
|
||||
// Returns the count of elements in the queue
|
||||
int Count() const { return m_heap.Count(); }
|
||||
|
||||
// Is element index valid?
|
||||
bool IsIdxValid( int i ) const;
|
||||
|
||||
// doesn't deallocate memory
|
||||
void RemoveAll() { m_heap.RemoveAll(); }
|
||||
|
||||
// Memory deallocation
|
||||
void Purge() { m_heap.Purge(); }
|
||||
|
||||
protected:
|
||||
CUtlVector<T, M> m_heap;
|
||||
T m_current;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The CUtlQueueFixed class:
|
||||
// A queue class with a fixed allocation scheme
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T, size_t MAX_SIZE >
|
||||
class CUtlQueueFixed : public CUtlQueue< T, CUtlMemoryFixed<T, MAX_SIZE > >
|
||||
{
|
||||
typedef CUtlQueue< T, CUtlMemoryFixed<T, MAX_SIZE > > BaseClass;
|
||||
public:
|
||||
|
||||
// constructor, destructor
|
||||
CUtlQueueFixed( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
|
||||
CUtlQueueFixed( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
|
||||
};
|
||||
|
||||
template< class T, class M >
|
||||
inline CUtlQueue<T, M>::CUtlQueue( int growSize, int initSize ) :
|
||||
m_heap(growSize, initSize)
|
||||
{
|
||||
}
|
||||
|
||||
template< class T, class M >
|
||||
inline CUtlQueue<T, M>::CUtlQueue( T *pMemory, int numElements ) :
|
||||
m_heap(pMemory, numElements)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// element access
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T, class M >
|
||||
inline T& CUtlQueue<T,M>::operator[]( int i )
|
||||
{
|
||||
return m_heap[i];
|
||||
}
|
||||
|
||||
template< class T, class M >
|
||||
inline T const& CUtlQueue<T,M>::operator[]( int i ) const
|
||||
{
|
||||
return m_heap[i];
|
||||
}
|
||||
|
||||
template< class T, class M >
|
||||
inline T& CUtlQueue<T,M>::Element( int i )
|
||||
{
|
||||
return m_heap[i];
|
||||
}
|
||||
|
||||
template< class T, class M >
|
||||
inline T const& CUtlQueue<T,M>::Element( int i ) const
|
||||
{
|
||||
return m_heap[i];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Is element index valid?
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T, class M >
|
||||
inline bool CUtlQueue<T,M>::IsIdxValid( int i ) const
|
||||
{
|
||||
return (i >= 0) && (i < m_heap.Count());
|
||||
}
|
||||
|
||||
template <class T, class M>
|
||||
inline T const& CUtlQueue<T, M>::RemoveAtHead()
|
||||
{
|
||||
m_current = m_heap[0];
|
||||
m_heap.Remove((int)0);
|
||||
return m_current;
|
||||
}
|
||||
|
||||
template <class T, class M>
|
||||
inline T const& CUtlQueue<T, M>::RemoveAtTail()
|
||||
{
|
||||
m_current = m_heap[ m_heap.Count() - 1 ];
|
||||
m_heap.Remove((int)(m_heap.Count() - 1));
|
||||
return m_current;
|
||||
}
|
||||
|
||||
template <class T, class M>
|
||||
inline T const& CUtlQueue<T, M>::Head()
|
||||
{
|
||||
m_current = m_heap[0];
|
||||
return m_current;
|
||||
}
|
||||
|
||||
template <class T, class M>
|
||||
inline T const& CUtlQueue<T, M>::Tail()
|
||||
{
|
||||
m_current = m_heap[ m_heap.Count() - 1 ];
|
||||
return m_current;
|
||||
}
|
||||
|
||||
template <class T, class M>
|
||||
void CUtlQueue<T, M>::Insert( T const &element )
|
||||
{
|
||||
int index = m_heap.AddToTail();
|
||||
m_heap[index] = element;
|
||||
}
|
||||
|
||||
template <class T, class M>
|
||||
bool CUtlQueue<T, M>::Check( T const element )
|
||||
{
|
||||
int index = m_heap.Find(element);
|
||||
return ( index != -1 );
|
||||
}
|
||||
|
||||
|
||||
#endif // UTLQUEUE_H
|
||||
+1581
File diff suppressed because it is too large
Load Diff
+354
@@ -0,0 +1,354 @@
|
||||
//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// $Header: $
|
||||
// $NoKeywords: $
|
||||
//
|
||||
// A growable array class that keeps all elements in order using binary search
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef UTLSORTVECTOR_H
|
||||
#define UTLSORTVECTOR_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "utlvector.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// class CUtlSortVector:
|
||||
// description:
|
||||
// This in an sorted order-preserving vector. Items may be inserted or removed
|
||||
// at any point in the vector. When an item is inserted, all elements are
|
||||
// moved down by one element using memmove. When an item is removed, all
|
||||
// elements are shifted back down. Items are searched for in the vector
|
||||
// using a binary search technique. Clients must pass in a Less() function
|
||||
// into the constructor of the vector to determine the sort order.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _WIN32
|
||||
// gcc has no qsort_s, so i need to use a static var to hold the sort context. this makes cutlsortvector _not_ thread sfae under linux
|
||||
extern void *g_pUtlSortVectorQSortContext;
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
class CUtlSortVectorDefaultLess
|
||||
{
|
||||
public:
|
||||
bool Less( const T& lhs, const T& rhs, void * )
|
||||
{
|
||||
return lhs < rhs;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class LessFunc = CUtlSortVectorDefaultLess<T>, class BaseVector = CUtlVector<T> >
|
||||
class CUtlSortVector : public BaseVector
|
||||
{
|
||||
public:
|
||||
|
||||
// constructor
|
||||
CUtlSortVector( int nGrowSize = 0, int initSize = 0 );
|
||||
CUtlSortVector( T* pMemory, int numElements );
|
||||
|
||||
// inserts (copy constructs) an element in sorted order into the list
|
||||
int Insert( const T& src );
|
||||
|
||||
// Finds an element within the list using a binary search
|
||||
int Find( const T& search ) const;
|
||||
int FindLessOrEqual( const T& search ) const;
|
||||
int FindLess( const T& search ) const;
|
||||
template <typename K>
|
||||
int FindAs( const K& key ) const;
|
||||
|
||||
// Removes a particular element
|
||||
void Remove( const T& search );
|
||||
void Remove( int i );
|
||||
|
||||
// Allows methods to set a context to be used with the less function..
|
||||
void SetLessContext( void *pCtx );
|
||||
|
||||
// Note that you can only use this index until sorting is redone!!!
|
||||
int InsertNoSort( const T& src );
|
||||
void RedoSort( bool bForceSort = false );
|
||||
|
||||
protected:
|
||||
// No copy constructor
|
||||
CUtlSortVector( const CUtlSortVector<T, LessFunc> & );
|
||||
|
||||
// never call these; illegal for this class
|
||||
int AddToHead();
|
||||
int AddToTail();
|
||||
int InsertBefore( int elem );
|
||||
int InsertAfter( int elem );
|
||||
int AddToHead( const T& src );
|
||||
int AddToTail( const T& src );
|
||||
int InsertBefore( int elem, const T& src );
|
||||
int InsertAfter( int elem, const T& src );
|
||||
int AddMultipleToHead( int num );
|
||||
int AddMultipleToTail( int num, const T *pToCopy=NULL );
|
||||
int InsertMultipleBefore( int elem, int num, const T *pToCopy=NULL );
|
||||
int InsertMultipleAfter( int elem, int num );
|
||||
int AddVectorToTail( CUtlVector<T> const &src );
|
||||
|
||||
struct QSortContext_t
|
||||
{
|
||||
void *m_pLessContext;
|
||||
LessFunc *m_pLessFunc;
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
static int CompareHelper( void *context, const T *lhs, const T *rhs )
|
||||
{
|
||||
QSortContext_t *ctx = reinterpret_cast< QSortContext_t * >( context );
|
||||
if ( ctx->m_pLessFunc->Less( *lhs, *rhs, ctx->m_pLessContext ) )
|
||||
return -1;
|
||||
if ( ctx->m_pLessFunc->Less( *rhs, *lhs, ctx->m_pLessContext ) )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int CompareHelper( const T *lhs, const T *rhs )
|
||||
{
|
||||
QSortContext_t *ctx = reinterpret_cast< QSortContext_t * >( g_pUtlSortVectorQSortContext );
|
||||
if ( ctx->m_pLessFunc->Less( *lhs, *rhs, ctx->m_pLessContext ) )
|
||||
return -1;
|
||||
if ( ctx->m_pLessFunc->Less( *rhs, *lhs, ctx->m_pLessContext ) )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void *m_pLessContext;
|
||||
bool m_bNeedsSort;
|
||||
|
||||
private:
|
||||
void QuickSort( LessFunc& less, int X, int I );
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class LessFunc, class BaseVector>
|
||||
CUtlSortVector<T, LessFunc, BaseVector>::CUtlSortVector( int nGrowSize, int initSize ) :
|
||||
m_pLessContext(NULL), BaseVector( nGrowSize, initSize ), m_bNeedsSort( false )
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, class LessFunc, class BaseVector>
|
||||
CUtlSortVector<T, LessFunc, BaseVector>::CUtlSortVector( T* pMemory, int numElements ) :
|
||||
m_pLessContext(NULL), BaseVector( pMemory, numElements ), m_bNeedsSort( false )
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Allows methods to set a context to be used with the less function..
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class LessFunc, class BaseVector>
|
||||
void CUtlSortVector<T, LessFunc, BaseVector>::SetLessContext( void *pCtx )
|
||||
{
|
||||
m_pLessContext = pCtx;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// grows the vector
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class LessFunc, class BaseVector>
|
||||
int CUtlSortVector<T, LessFunc, BaseVector>::Insert( const T& src )
|
||||
{
|
||||
AssertFatal( !m_bNeedsSort );
|
||||
|
||||
int pos = FindLessOrEqual( src ) + 1;
|
||||
this->GrowVector();
|
||||
this->ShiftElementsRight(pos);
|
||||
CopyConstruct<T>( &this->Element(pos), src );
|
||||
return pos;
|
||||
}
|
||||
|
||||
template <class T, class LessFunc, class BaseVector>
|
||||
int CUtlSortVector<T, LessFunc, BaseVector>::InsertNoSort( const T& src )
|
||||
{
|
||||
m_bNeedsSort = true;
|
||||
int lastElement = BaseVector::m_Size;
|
||||
// Just stick the new element at the end of the vector, but don't do a sort
|
||||
this->GrowVector();
|
||||
this->ShiftElementsRight(lastElement);
|
||||
CopyConstruct( &this->Element(lastElement), src );
|
||||
return lastElement;
|
||||
}
|
||||
|
||||
template <class T, class LessFunc, class BaseVector>
|
||||
void CUtlSortVector<T, LessFunc, BaseVector>::QuickSort( LessFunc& less, int nLower, int nUpper )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
typedef int (__cdecl *QSortCompareFunc_t)(void *context, const void *, const void *);
|
||||
if ( this->Count() > 1 )
|
||||
{
|
||||
QSortContext_t ctx;
|
||||
ctx.m_pLessContext = m_pLessContext;
|
||||
ctx.m_pLessFunc = &less;
|
||||
|
||||
qsort_s( Base(), Count(), sizeof(T), (QSortCompareFunc_t)&CUtlSortVector<T, LessFunc>::CompareHelper, &ctx );
|
||||
}
|
||||
#else
|
||||
typedef int (__cdecl *QSortCompareFunc_t)( const void *, const void *);
|
||||
if ( this->Count() > 1 )
|
||||
{
|
||||
QSortContext_t ctx;
|
||||
ctx.m_pLessContext = m_pLessContext;
|
||||
ctx.m_pLessFunc = &less;
|
||||
g_pUtlSortVectorQSortContext = &ctx;
|
||||
|
||||
qsort( this->Base(), this->Count(), sizeof(T), (QSortCompareFunc_t)&CUtlSortVector<T, LessFunc>::CompareHelper );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T, class LessFunc, class BaseVector>
|
||||
void CUtlSortVector<T, LessFunc, BaseVector>::RedoSort( bool bForceSort /*= false */ )
|
||||
{
|
||||
if ( !m_bNeedsSort && !bForceSort )
|
||||
return;
|
||||
|
||||
m_bNeedsSort = false;
|
||||
LessFunc less;
|
||||
QuickSort( less, 0, this->Count() - 1 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// finds a particular element
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class LessFunc, class BaseVector>
|
||||
int CUtlSortVector<T, LessFunc, BaseVector>::Find( const T& src ) const
|
||||
{
|
||||
AssertFatal( !m_bNeedsSort );
|
||||
|
||||
LessFunc less;
|
||||
|
||||
int start = 0, end = this->Count() - 1;
|
||||
while (start <= end)
|
||||
{
|
||||
int mid = (start + end) >> 1;
|
||||
if ( less.Less( this->Element(mid), src, m_pLessContext ) )
|
||||
{
|
||||
start = mid + 1;
|
||||
}
|
||||
else if ( less.Less( src, this->Element(mid), m_pLessContext ) )
|
||||
{
|
||||
end = mid - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// finds a particular element
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class LessFunc, class BaseVector>
|
||||
template <typename K>
|
||||
int CUtlSortVector<T, LessFunc, BaseVector>::FindAs( const K& key ) const
|
||||
{
|
||||
AssertFatal( !m_bNeedsSort );
|
||||
|
||||
LessFunc less;
|
||||
|
||||
int start = 0, end = this->Count() - 1;
|
||||
while (start <= end)
|
||||
{
|
||||
int mid = (start + end) >> 1;
|
||||
int nResult = less.Compare( this->Element(mid), key, m_pLessContext );
|
||||
if ( nResult < 0 )
|
||||
{
|
||||
start = mid + 1;
|
||||
}
|
||||
else if ( nResult > 0 )
|
||||
{
|
||||
end = mid - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// finds a particular element
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class LessFunc, class BaseVector>
|
||||
int CUtlSortVector<T, LessFunc, BaseVector>::FindLessOrEqual( const T& src ) const
|
||||
{
|
||||
AssertFatal( !m_bNeedsSort );
|
||||
|
||||
LessFunc less;
|
||||
int start = 0, end = this->Count() - 1;
|
||||
while (start <= end)
|
||||
{
|
||||
int mid = (start + end) >> 1;
|
||||
if ( less.Less( this->Element(mid), src, m_pLessContext ) )
|
||||
{
|
||||
start = mid + 1;
|
||||
}
|
||||
else if ( less.Less( src, this->Element(mid), m_pLessContext ) )
|
||||
{
|
||||
end = mid - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
return end;
|
||||
}
|
||||
|
||||
template <class T, class LessFunc, class BaseVector>
|
||||
int CUtlSortVector<T, LessFunc, BaseVector>::FindLess( const T& src ) const
|
||||
{
|
||||
AssertFatal( !m_bNeedsSort );
|
||||
|
||||
LessFunc less;
|
||||
int start = 0, end = this->Count() - 1;
|
||||
while (start <= end)
|
||||
{
|
||||
int mid = (start + end) >> 1;
|
||||
if ( less.Less( this->Element(mid), src, m_pLessContext ) )
|
||||
{
|
||||
start = mid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
end = mid - 1;
|
||||
}
|
||||
}
|
||||
return end;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Removes a particular element
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class LessFunc, class BaseVector>
|
||||
void CUtlSortVector<T, LessFunc, BaseVector>::Remove( const T& search )
|
||||
{
|
||||
AssertFatal( !m_bNeedsSort );
|
||||
|
||||
int pos = Find(search);
|
||||
if (pos != -1)
|
||||
{
|
||||
BaseVector::Remove(pos);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class LessFunc, class BaseVector>
|
||||
void CUtlSortVector<T, LessFunc, BaseVector>::Remove( int i )
|
||||
{
|
||||
BaseVector::Remove( i );
|
||||
}
|
||||
|
||||
#endif // UTLSORTVECTOR_H
|
||||
Vendored
+331
@@ -0,0 +1,331 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
// A stack based on a growable array
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef UTLSTACK_H
|
||||
#define UTLSTACK_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "utlmemory.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The CUtlStack class:
|
||||
// A growable stack class which doubles in size by default.
|
||||
// It will always keep all elements consecutive in memory, and may move the
|
||||
// elements around in memory (via a realloc) when elements are pushed or
|
||||
// popped. Clients should therefore refer to the elements of the stack
|
||||
// by index (they should *never* maintain pointers to elements in the stack).
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T, class M = CUtlMemory< T > >
|
||||
class CUtlStack
|
||||
{
|
||||
public:
|
||||
// constructor, destructor
|
||||
CUtlStack( int growSize = 0, int initSize = 0 );
|
||||
~CUtlStack();
|
||||
|
||||
void CopyFrom( const CUtlStack<T, M> &from );
|
||||
|
||||
// element access
|
||||
T& operator[]( int i );
|
||||
T const& operator[]( int i ) const;
|
||||
T& Element( int i );
|
||||
T const& Element( int i ) const;
|
||||
|
||||
// Gets the base address (can change when adding elements!)
|
||||
T* Base();
|
||||
T const* Base() const;
|
||||
|
||||
// Looks at the stack top
|
||||
T& Top();
|
||||
T const& Top() const;
|
||||
|
||||
// Size
|
||||
int Count() const;
|
||||
|
||||
// Is element index valid?
|
||||
bool IsIdxValid( int i ) const;
|
||||
|
||||
// Adds an element, uses default constructor
|
||||
int Push();
|
||||
|
||||
// Adds an element, uses copy constructor
|
||||
int Push( T const& src );
|
||||
|
||||
// Pops the stack
|
||||
void Pop();
|
||||
void Pop( T& oldTop );
|
||||
void PopMultiple( int num );
|
||||
|
||||
// Makes sure we have enough memory allocated to store a requested # of elements
|
||||
void EnsureCapacity( int num );
|
||||
|
||||
// Clears the stack, no deallocation
|
||||
void Clear();
|
||||
|
||||
// Memory deallocation
|
||||
void Purge();
|
||||
|
||||
private:
|
||||
// Grows the stack allocation
|
||||
void GrowStack();
|
||||
|
||||
// For easier access to the elements through the debugger
|
||||
void ResetDbgInfo();
|
||||
|
||||
M m_Memory;
|
||||
int m_Size;
|
||||
|
||||
// For easier access to the elements through the debugger
|
||||
T* m_pElements;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// For easier access to the elements through the debugger
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T, class M >
|
||||
inline void CUtlStack<T,M>::ResetDbgInfo()
|
||||
{
|
||||
m_pElements = m_Memory.Base();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// constructor, destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T, class M >
|
||||
CUtlStack<T,M>::CUtlStack( int growSize, int initSize ) :
|
||||
m_Memory(growSize, initSize), m_Size(0)
|
||||
{
|
||||
ResetDbgInfo();
|
||||
}
|
||||
|
||||
template< class T, class M >
|
||||
CUtlStack<T,M>::~CUtlStack()
|
||||
{
|
||||
Purge();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// copy into
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T, class M >
|
||||
void CUtlStack<T,M>::CopyFrom( const CUtlStack<T, M> &from )
|
||||
{
|
||||
Purge();
|
||||
EnsureCapacity( from.Count() );
|
||||
for ( int i = 0; i < from.Count(); i++ )
|
||||
{
|
||||
Push( from[i] );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// element access
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T, class M >
|
||||
inline T& CUtlStack<T,M>::operator[]( int i )
|
||||
{
|
||||
assert( IsIdxValid(i) );
|
||||
return m_Memory[i];
|
||||
}
|
||||
|
||||
template< class T, class M >
|
||||
inline T const& CUtlStack<T,M>::operator[]( int i ) const
|
||||
{
|
||||
assert( IsIdxValid(i) );
|
||||
return m_Memory[i];
|
||||
}
|
||||
|
||||
template< class T, class M >
|
||||
inline T& CUtlStack<T,M>::Element( int i )
|
||||
{
|
||||
assert( IsIdxValid(i) );
|
||||
return m_Memory[i];
|
||||
}
|
||||
|
||||
template< class T, class M >
|
||||
inline T const& CUtlStack<T,M>::Element( int i ) const
|
||||
{
|
||||
assert( IsIdxValid(i) );
|
||||
return m_Memory[i];
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gets the base address (can change when adding elements!)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T, class M >
|
||||
inline T* CUtlStack<T,M>::Base()
|
||||
{
|
||||
return m_Memory.Base();
|
||||
}
|
||||
|
||||
template< class T, class M >
|
||||
inline T const* CUtlStack<T,M>::Base() const
|
||||
{
|
||||
return m_Memory.Base();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns the top of the stack
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T, class M >
|
||||
inline T& CUtlStack<T,M>::Top()
|
||||
{
|
||||
assert( m_Size > 0 );
|
||||
return Element(m_Size-1);
|
||||
}
|
||||
|
||||
template< class T, class M >
|
||||
inline T const& CUtlStack<T,M>::Top() const
|
||||
{
|
||||
assert( m_Size > 0 );
|
||||
return Element(m_Size-1);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Size
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T, class M >
|
||||
inline int CUtlStack<T,M>::Count() const
|
||||
{
|
||||
return m_Size;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Is element index valid?
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T, class M >
|
||||
inline bool CUtlStack<T,M>::IsIdxValid( int i ) const
|
||||
{
|
||||
return (i >= 0) && (i < m_Size);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Grows the stack
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T, class M >
|
||||
void CUtlStack<T,M>::GrowStack()
|
||||
{
|
||||
if (m_Size >= m_Memory.NumAllocated())
|
||||
m_Memory.Grow();
|
||||
|
||||
++m_Size;
|
||||
|
||||
ResetDbgInfo();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Makes sure we have enough memory allocated to store a requested # of elements
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T, class M >
|
||||
void CUtlStack<T,M>::EnsureCapacity( int num )
|
||||
{
|
||||
m_Memory.EnsureCapacity(num);
|
||||
ResetDbgInfo();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Adds an element, uses default constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T, class M >
|
||||
int CUtlStack<T,M>::Push()
|
||||
{
|
||||
GrowStack();
|
||||
Construct( &Element(m_Size-1) );
|
||||
return m_Size - 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Adds an element, uses copy constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T, class M >
|
||||
int CUtlStack<T,M>::Push( T const& src )
|
||||
{
|
||||
GrowStack();
|
||||
CopyConstruct( &Element(m_Size-1), src );
|
||||
return m_Size - 1;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Pops the stack
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T, class M >
|
||||
void CUtlStack<T,M>::Pop()
|
||||
{
|
||||
assert( m_Size > 0 );
|
||||
Destruct( &Element(m_Size-1) );
|
||||
--m_Size;
|
||||
}
|
||||
|
||||
template< class T, class M >
|
||||
void CUtlStack<T,M>::Pop( T& oldTop )
|
||||
{
|
||||
assert( m_Size > 0 );
|
||||
oldTop = Top();
|
||||
Pop();
|
||||
}
|
||||
|
||||
template< class T, class M >
|
||||
void CUtlStack<T,M>::PopMultiple( int num )
|
||||
{
|
||||
assert( m_Size >= num );
|
||||
for ( int i = 0; i < num; ++i )
|
||||
Destruct( &Element( m_Size - i - 1 ) );
|
||||
m_Size -= num;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Element removal
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T, class M >
|
||||
void CUtlStack<T,M>::Clear()
|
||||
{
|
||||
for (int i = m_Size; --i >= 0; )
|
||||
Destruct(&Element(i));
|
||||
|
||||
m_Size = 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memory deallocation
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T, class M >
|
||||
void CUtlStack<T,M>::Purge()
|
||||
{
|
||||
Clear();
|
||||
m_Memory.Purge( );
|
||||
ResetDbgInfo();
|
||||
}
|
||||
|
||||
#endif // UTLSTACK_H
|
||||
+373
@@ -0,0 +1,373 @@
|
||||
//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. =======
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef UTLSTRING_H
|
||||
#define UTLSTRING_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include "tier1/utlmemory.h"
|
||||
#include "tier1/strtools.h"
|
||||
#include "limits.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Base class, containing simple memory management
|
||||
//-----------------------------------------------------------------------------
|
||||
class CUtlBinaryBlock
|
||||
{
|
||||
public:
|
||||
CUtlBinaryBlock( int growSize = 0, int initSize = 0 );
|
||||
~CUtlBinaryBlock()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
m_nActualLength = 0x7BADF00D;
|
||||
#else
|
||||
m_nActualLength = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// NOTE: nInitialLength indicates how much of the buffer starts full
|
||||
CUtlBinaryBlock( void* pMemory, int nSizeInBytes, int nInitialLength );
|
||||
CUtlBinaryBlock( const void* pMemory, int nSizeInBytes );
|
||||
CUtlBinaryBlock( const CUtlBinaryBlock& src );
|
||||
|
||||
void Get( void *pValue, int nMaxLen ) const;
|
||||
void Set( const void *pValue, int nLen );
|
||||
const void *Get( ) const;
|
||||
void *Get( );
|
||||
|
||||
unsigned char& operator[]( int i );
|
||||
const unsigned char& operator[]( int i ) const;
|
||||
|
||||
int Length() const;
|
||||
void SetLength( int nLength ); // Undefined memory will result
|
||||
bool IsEmpty() const;
|
||||
void Clear();
|
||||
void Purge();
|
||||
|
||||
bool IsReadOnly() const;
|
||||
|
||||
CUtlBinaryBlock &operator=( const CUtlBinaryBlock &src );
|
||||
|
||||
// Test for equality
|
||||
bool operator==( const CUtlBinaryBlock &src ) const;
|
||||
|
||||
private:
|
||||
CUtlMemory<unsigned char> m_Memory;
|
||||
int m_nActualLength;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// class inlines
|
||||
//-----------------------------------------------------------------------------
|
||||
inline const void *CUtlBinaryBlock::Get( ) const
|
||||
{
|
||||
return m_Memory.Base();
|
||||
}
|
||||
|
||||
inline void *CUtlBinaryBlock::Get( )
|
||||
{
|
||||
return m_Memory.Base();
|
||||
}
|
||||
|
||||
inline int CUtlBinaryBlock::Length() const
|
||||
{
|
||||
return m_nActualLength;
|
||||
}
|
||||
|
||||
inline unsigned char& CUtlBinaryBlock::operator[]( int i )
|
||||
{
|
||||
return m_Memory[i];
|
||||
}
|
||||
|
||||
inline const unsigned char& CUtlBinaryBlock::operator[]( int i ) const
|
||||
{
|
||||
return m_Memory[i];
|
||||
}
|
||||
|
||||
inline bool CUtlBinaryBlock::IsReadOnly() const
|
||||
{
|
||||
return m_Memory.IsReadOnly();
|
||||
}
|
||||
|
||||
inline bool CUtlBinaryBlock::IsEmpty() const
|
||||
{
|
||||
return Length() == 0;
|
||||
}
|
||||
|
||||
inline void CUtlBinaryBlock::Clear()
|
||||
{
|
||||
SetLength( 0 );
|
||||
}
|
||||
|
||||
inline void CUtlBinaryBlock::Purge()
|
||||
{
|
||||
SetLength( 0 );
|
||||
m_Memory.Purge();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Simple string class.
|
||||
// NOTE: This is *not* optimal! Use in tools, but not runtime code
|
||||
//-----------------------------------------------------------------------------
|
||||
class CUtlString
|
||||
{
|
||||
public:
|
||||
typedef enum
|
||||
{
|
||||
PATTERN_NONE = 0x00000000,
|
||||
PATTERN_DIRECTORY = 0x00000001
|
||||
} TUtlStringPattern;
|
||||
|
||||
public:
|
||||
CUtlString();
|
||||
CUtlString( const char *pString );
|
||||
CUtlString( const CUtlString& string );
|
||||
|
||||
// Attaches the string to external memory. Useful for avoiding a copy
|
||||
CUtlString( void* pMemory, int nSizeInBytes, int nInitialLength );
|
||||
CUtlString( const void* pMemory, int nSizeInBytes );
|
||||
|
||||
const char *Get( ) const;
|
||||
void Set( const char *pValue );
|
||||
|
||||
void Clear() { Set( NULL ); }
|
||||
|
||||
// Converts to c-strings
|
||||
operator const char*() const;
|
||||
|
||||
// for compatibility switching items from UtlSymbol
|
||||
const char *String() const { return Get(); }
|
||||
|
||||
// Returns strlen
|
||||
int Length() const;
|
||||
bool IsEmpty() const;
|
||||
|
||||
// Sets the length (used to serialize into the buffer )
|
||||
// Note: If nLen != 0, then this adds an extra byte for a null-terminator.
|
||||
void SetLength( int nLen );
|
||||
char *Get();
|
||||
void Purge();
|
||||
|
||||
// Case Change
|
||||
void ToLower( );
|
||||
|
||||
void Append( const char *pchAddition );
|
||||
|
||||
// Strips the trailing slash
|
||||
void StripTrailingSlash();
|
||||
|
||||
CUtlString &operator=( const CUtlString &src );
|
||||
CUtlString &operator=( const char *src );
|
||||
|
||||
// Test for equality
|
||||
bool operator==( const CUtlString &src ) const;
|
||||
bool operator==( const char *src ) const;
|
||||
bool operator!=( const CUtlString &src ) const { return !operator==( src ); }
|
||||
bool operator!=( const char *src ) const { return !operator==( src ); }
|
||||
|
||||
// If these are not defined, CUtlString as rhs will auto-convert
|
||||
// to const char* and do logical operations on the raw pointers. Ugh.
|
||||
inline friend bool operator==( const char *lhs, const CUtlString &rhs ) { return rhs.operator==( lhs ); }
|
||||
inline friend bool operator!=( const char *lhs, const CUtlString &rhs ) { return rhs.operator!=( lhs ); }
|
||||
|
||||
CUtlString &operator+=( const CUtlString &rhs );
|
||||
CUtlString &operator+=( const char *rhs );
|
||||
CUtlString &operator+=( char c );
|
||||
CUtlString &operator+=( int rhs );
|
||||
CUtlString &operator+=( double rhs );
|
||||
|
||||
CUtlString operator+( const char *pOther ) const;
|
||||
|
||||
bool MatchesPattern( const CUtlString &Pattern, int nFlags = 0 ) const; // case SENSITIVE, use * for wildcard in pattern string
|
||||
|
||||
int Format( const char *pFormat, ... );
|
||||
void SetDirect( const char *pValue, int nChars );
|
||||
|
||||
// Defining AltArgumentType_t hints that associative container classes should
|
||||
// also implement Find/Insert/Remove functions that take const char* params.
|
||||
typedef const char *AltArgumentType_t;
|
||||
|
||||
// Take a piece out of the string.
|
||||
// If you only specify nStart, it'll go from nStart to the end.
|
||||
// You can use negative numbers and it'll wrap around to the start.
|
||||
CUtlString Slice( int32 nStart=0, int32 nEnd=INT_MAX ) const;
|
||||
|
||||
// Grab a substring starting from the left or the right side.
|
||||
CUtlString Left( int32 nChars ) const;
|
||||
CUtlString Right( int32 nChars ) const;
|
||||
|
||||
// Replace all instances of one character with another.
|
||||
CUtlString Replace( char cFrom, char cTo ) const;
|
||||
|
||||
// Calls right through to V_MakeAbsolutePath.
|
||||
CUtlString AbsPath( const char *pStartingDir=NULL ) const;
|
||||
|
||||
// Gets the filename (everything except the path.. c:\a\b\c\somefile.txt -> somefile.txt).
|
||||
CUtlString UnqualifiedFilename() const;
|
||||
|
||||
// Strips off one directory. Uses V_StripLastDir but strips the last slash also!
|
||||
CUtlString DirName() const;
|
||||
|
||||
// Works like V_ComposeFileName.
|
||||
static CUtlString PathJoin( const char *pStr1, const char *pStr2 );
|
||||
|
||||
// These can be used for utlvector sorts.
|
||||
static int __cdecl SortCaseInsensitive( const CUtlString *pString1, const CUtlString *pString2 );
|
||||
static int __cdecl SortCaseSensitive( const CUtlString *pString1, const CUtlString *pString2 );
|
||||
|
||||
private:
|
||||
CUtlBinaryBlock m_Storage;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Inline methods
|
||||
//-----------------------------------------------------------------------------
|
||||
inline bool CUtlString::IsEmpty() const
|
||||
{
|
||||
return Length() == 0;
|
||||
}
|
||||
|
||||
inline int __cdecl CUtlString::SortCaseInsensitive( const CUtlString *pString1, const CUtlString *pString2 )
|
||||
{
|
||||
return V_stricmp( pString1->String(), pString2->String() );
|
||||
}
|
||||
|
||||
inline int __cdecl CUtlString::SortCaseSensitive( const CUtlString *pString1, const CUtlString *pString2 )
|
||||
{
|
||||
return V_strcmp( pString1->String(), pString2->String() );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Implementation of low-level string functionality for character types.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template < typename T >
|
||||
class StringFuncs
|
||||
{
|
||||
public:
|
||||
static T *Duplicate( const T *pValue );
|
||||
static void Copy( T *out_pOut, const T *pIn, int iLength );
|
||||
static int Compare( const T *pLhs, const T *pRhs );
|
||||
static int Length( const T *pValue );
|
||||
static const T *FindChar( const T *pStr, const T cSearch );
|
||||
static const T *EmptyString();
|
||||
};
|
||||
|
||||
template < >
|
||||
class StringFuncs<char>
|
||||
{
|
||||
public:
|
||||
static char *Duplicate( const char *pValue ) { return strdup( pValue ); }
|
||||
static void Copy( char *out_pOut, const char *pIn, int iLength ) { strncpy( out_pOut, pIn, iLength ); }
|
||||
static int Compare( const char *pLhs, const char *pRhs ) { return strcmp( pLhs, pRhs ); }
|
||||
static int Length( const char *pValue ) { return strlen( pValue ); }
|
||||
static const char *FindChar( const char *pStr, const char cSearch ) { return strchr( pStr, cSearch ); }
|
||||
static const char *EmptyString() { return ""; }
|
||||
};
|
||||
|
||||
template < >
|
||||
class StringFuncs<wchar_t>
|
||||
{
|
||||
public:
|
||||
static wchar_t *Duplicate( const wchar_t *pValue ) { return wcsdup( pValue ); }
|
||||
static void Copy( wchar_t *out_pOut, const wchar_t *pIn, int iLength ) { wcsncpy( out_pOut, pIn, iLength ); }
|
||||
static int Compare( const wchar_t *pLhs, const wchar_t *pRhs ) { return wcscmp( pLhs, pRhs ); }
|
||||
static int Length( const wchar_t *pValue ) { return wcslen( pValue ); }
|
||||
static const wchar_t *FindChar( const wchar_t *pStr, const wchar_t cSearch ) { return wcschr( pStr, cSearch ); }
|
||||
static const wchar_t *EmptyString() { return L""; }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Dirt-basic auto-release string class. Not intended for manipulation,
|
||||
// can be stored in a container or forwarded as a functor parameter.
|
||||
// Note the benefit over CUtlString: sizeof(CUtlConstString) == sizeof(char*).
|
||||
// Also note: null char* pointers are treated identically to empty strings.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template < typename T = char >
|
||||
class CUtlConstStringBase
|
||||
{
|
||||
public:
|
||||
CUtlConstStringBase() : m_pString( NULL ) {}
|
||||
CUtlConstStringBase( const T *pString ) : m_pString( NULL ) { Set( pString ); }
|
||||
CUtlConstStringBase( const CUtlConstStringBase& src ) : m_pString( NULL ) { Set( src.m_pString ); }
|
||||
~CUtlConstStringBase() { Set( NULL ); }
|
||||
|
||||
void Set( const T *pValue );
|
||||
void Clear() { Set( NULL ); }
|
||||
|
||||
const T *Get() const { return m_pString ? m_pString : StringFuncs<T>::EmptyString(); }
|
||||
operator const T*() const { return m_pString ? m_pString : StringFuncs<T>::EmptyString(); }
|
||||
|
||||
bool IsEmpty() const { return m_pString == NULL; } // Note: empty strings are never stored by Set
|
||||
|
||||
int Compare( const T *rhs ) const;
|
||||
|
||||
// Logical ops
|
||||
bool operator<( const T *rhs ) const { return Compare( rhs ) < 0; }
|
||||
bool operator==( const T *rhs ) const { return Compare( rhs ) == 0; }
|
||||
bool operator!=( const T *rhs ) const { return Compare( rhs ) != 0; }
|
||||
bool operator<( const CUtlConstStringBase &rhs ) const { return Compare( rhs.m_pString ) < 0; }
|
||||
bool operator==( const CUtlConstStringBase &rhs ) const { return Compare( rhs.m_pString ) == 0; }
|
||||
bool operator!=( const CUtlConstStringBase &rhs ) const { return Compare( rhs.m_pString ) != 0; }
|
||||
|
||||
// If these are not defined, CUtlConstString as rhs will auto-convert
|
||||
// to const char* and do logical operations on the raw pointers. Ugh.
|
||||
inline friend bool operator<( const T *lhs, const CUtlConstStringBase &rhs ) { return rhs.Compare( lhs ) > 0; }
|
||||
inline friend bool operator==( const T *lhs, const CUtlConstStringBase &rhs ) { return rhs.Compare( lhs ) == 0; }
|
||||
inline friend bool operator!=( const T *lhs, const CUtlConstStringBase &rhs ) { return rhs.Compare( lhs ) != 0; }
|
||||
|
||||
CUtlConstStringBase &operator=( const T *src ) { Set( src ); return *this; }
|
||||
CUtlConstStringBase &operator=( const CUtlConstStringBase &src ) { Set( src.m_pString ); return *this; }
|
||||
|
||||
// Defining AltArgumentType_t is a hint to containers that they should
|
||||
// implement Find/Insert/Remove functions that take const char* params.
|
||||
typedef const T *AltArgumentType_t;
|
||||
|
||||
protected:
|
||||
const T *m_pString;
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
void CUtlConstStringBase<T>::Set( const T *pValue )
|
||||
{
|
||||
if ( pValue != m_pString )
|
||||
{
|
||||
free( ( void* ) m_pString );
|
||||
m_pString = pValue && pValue[0] ? StringFuncs<T>::Duplicate( pValue ) : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
int CUtlConstStringBase<T>::Compare( const T *rhs ) const
|
||||
{
|
||||
if ( m_pString )
|
||||
{
|
||||
if ( rhs )
|
||||
return StringFuncs<T>::Compare( m_pString, rhs );
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( rhs )
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
typedef CUtlConstStringBase<char> CUtlConstString;
|
||||
typedef CUtlConstStringBase<wchar_t> CUtlConstWideString;
|
||||
|
||||
|
||||
#endif // UTLSTRING_H
|
||||
+345
@@ -0,0 +1,345 @@
|
||||
//===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose: Defines a symbol table
|
||||
//
|
||||
// $Header: $
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef UTLSYMBOL_H
|
||||
#define UTLSYMBOL_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "tier0/threadtools.h"
|
||||
#include "tier1/utlrbtree.h"
|
||||
#include "tier1/utlvector.h"
|
||||
#include "tier1/utlbuffer.h"
|
||||
#include "tier1/utllinkedlist.h"
|
||||
#include "tier1/stringpool.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// forward declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
class CUtlSymbolTable;
|
||||
class CUtlSymbolTableMT;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This is a symbol, which is a easier way of dealing with strings.
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef unsigned short UtlSymId_t;
|
||||
|
||||
#define UTL_INVAL_SYMBOL ((UtlSymId_t)~0)
|
||||
|
||||
class CUtlSymbol
|
||||
{
|
||||
public:
|
||||
// constructor, destructor
|
||||
CUtlSymbol() : m_Id(UTL_INVAL_SYMBOL) {}
|
||||
CUtlSymbol( UtlSymId_t id ) : m_Id(id) {}
|
||||
CUtlSymbol( const char* pStr );
|
||||
CUtlSymbol( CUtlSymbol const& sym ) : m_Id(sym.m_Id) {}
|
||||
|
||||
// operator=
|
||||
CUtlSymbol& operator=( CUtlSymbol const& src ) { m_Id = src.m_Id; return *this; }
|
||||
|
||||
// operator==
|
||||
bool operator==( CUtlSymbol const& src ) const { return m_Id == src.m_Id; }
|
||||
bool operator==( const char* pStr ) const;
|
||||
|
||||
// Is valid?
|
||||
bool IsValid() const { return m_Id != UTL_INVAL_SYMBOL; }
|
||||
|
||||
// Gets at the symbol
|
||||
operator UtlSymId_t () const { return m_Id; }
|
||||
|
||||
// Gets the string associated with the symbol
|
||||
const char* String( ) const;
|
||||
|
||||
// Modules can choose to disable the static symbol table so to prevent accidental use of them.
|
||||
static void DisableStaticSymbolTable();
|
||||
|
||||
// Methods with explicit locking mechanism. Only use for optimization reasons.
|
||||
static void LockTableForRead();
|
||||
static void UnlockTableForRead();
|
||||
const char * StringNoLock() const;
|
||||
|
||||
protected:
|
||||
UtlSymId_t m_Id;
|
||||
|
||||
// Initializes the symbol table
|
||||
static void Initialize();
|
||||
|
||||
// returns the current symbol table
|
||||
static CUtlSymbolTableMT* CurrTable();
|
||||
|
||||
// The standard global symbol table
|
||||
static CUtlSymbolTableMT* s_pSymbolTable;
|
||||
|
||||
static bool s_bAllowStaticSymbolTable;
|
||||
|
||||
friend class CCleanupUtlSymbolTable;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CUtlSymbolTable:
|
||||
// description:
|
||||
// This class defines a symbol table, which allows us to perform mappings
|
||||
// of strings to symbols and back. The symbol class itself contains
|
||||
// a static version of this class for creating global strings, but this
|
||||
// class can also be instanced to create local symbol tables.
|
||||
//
|
||||
// This class stores the strings in a series of string pools. The first
|
||||
// two bytes of each string are decorated with a hash to speed up
|
||||
// comparisons.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class CUtlSymbolTable
|
||||
{
|
||||
public:
|
||||
// constructor, destructor
|
||||
CUtlSymbolTable( int growSize = 0, int initSize = 16, bool caseInsensitive = false );
|
||||
~CUtlSymbolTable();
|
||||
|
||||
// Finds and/or creates a symbol based on the string
|
||||
CUtlSymbol AddString( const char* pString );
|
||||
|
||||
// Finds the symbol for pString
|
||||
CUtlSymbol Find( const char* pString ) const;
|
||||
|
||||
// Look up the string associated with a particular symbol
|
||||
const char* String( CUtlSymbol id ) const;
|
||||
|
||||
// Remove all symbols in the table.
|
||||
void RemoveAll();
|
||||
|
||||
int GetNumStrings( void ) const
|
||||
{
|
||||
return m_Lookup.Count();
|
||||
}
|
||||
|
||||
// We store one of these at the beginning of every string to speed
|
||||
// up comparisons.
|
||||
typedef unsigned short hashDecoration_t;
|
||||
|
||||
protected:
|
||||
class CStringPoolIndex
|
||||
{
|
||||
public:
|
||||
inline CStringPoolIndex()
|
||||
{
|
||||
}
|
||||
|
||||
inline CStringPoolIndex( unsigned short iPool, unsigned short iOffset )
|
||||
: m_iPool(iPool), m_iOffset(iOffset)
|
||||
{}
|
||||
|
||||
inline bool operator==( const CStringPoolIndex &other ) const
|
||||
{
|
||||
return m_iPool == other.m_iPool && m_iOffset == other.m_iOffset;
|
||||
}
|
||||
|
||||
unsigned short m_iPool; // Index into m_StringPools.
|
||||
unsigned short m_iOffset; // Index into the string pool.
|
||||
};
|
||||
|
||||
class CLess
|
||||
{
|
||||
public:
|
||||
CLess( int ignored = 0 ) {} // permits default initialization to NULL in CUtlRBTree
|
||||
bool operator!() const { return false; }
|
||||
bool operator()( const CStringPoolIndex &left, const CStringPoolIndex &right ) const;
|
||||
};
|
||||
|
||||
// Stores the symbol lookup
|
||||
class CTree : public CUtlRBTree<CStringPoolIndex, unsigned short, CLess>
|
||||
{
|
||||
public:
|
||||
CTree( int growSize, int initSize ) : CUtlRBTree<CStringPoolIndex, unsigned short, CLess>( growSize, initSize ) {}
|
||||
friend class CUtlSymbolTable::CLess; // Needed to allow CLess to calculate pointer to symbol table
|
||||
};
|
||||
|
||||
struct StringPool_t
|
||||
{
|
||||
int m_TotalLen; // How large is
|
||||
int m_SpaceUsed;
|
||||
char m_Data[1];
|
||||
};
|
||||
|
||||
CTree m_Lookup;
|
||||
|
||||
bool m_bInsensitive;
|
||||
mutable unsigned short m_nUserSearchStringHash;
|
||||
mutable const char* m_pUserSearchString;
|
||||
|
||||
// stores the string data
|
||||
CUtlVector<StringPool_t*> m_StringPools;
|
||||
|
||||
private:
|
||||
int FindPoolWithSpace( int len ) const;
|
||||
const char* StringFromIndex( const CStringPoolIndex &index ) const;
|
||||
const char* DecoratedStringFromIndex( const CStringPoolIndex &index ) const;
|
||||
|
||||
friend class CLess;
|
||||
friend class CSymbolHash;
|
||||
|
||||
};
|
||||
|
||||
class CUtlSymbolTableMT : public CUtlSymbolTable
|
||||
{
|
||||
public:
|
||||
CUtlSymbolTableMT( int growSize = 0, int initSize = 32, bool caseInsensitive = false )
|
||||
: CUtlSymbolTable( growSize, initSize, caseInsensitive )
|
||||
{
|
||||
}
|
||||
|
||||
CUtlSymbol AddString( const char* pString )
|
||||
{
|
||||
m_lock.LockForWrite();
|
||||
CUtlSymbol result = CUtlSymbolTable::AddString( pString );
|
||||
m_lock.UnlockWrite();
|
||||
return result;
|
||||
}
|
||||
|
||||
CUtlSymbol Find( const char* pString ) const
|
||||
{
|
||||
m_lock.LockForWrite();
|
||||
CUtlSymbol result = CUtlSymbolTable::Find( pString );
|
||||
m_lock.UnlockWrite();
|
||||
return result;
|
||||
}
|
||||
|
||||
const char* String( CUtlSymbol id ) const
|
||||
{
|
||||
m_lock.LockForRead();
|
||||
const char *pszResult = CUtlSymbolTable::String( id );
|
||||
m_lock.UnlockRead();
|
||||
return pszResult;
|
||||
}
|
||||
|
||||
const char * StringNoLock( CUtlSymbol id ) const
|
||||
{
|
||||
return CUtlSymbolTable::String( id );
|
||||
}
|
||||
|
||||
void LockForRead()
|
||||
{
|
||||
m_lock.LockForRead();
|
||||
}
|
||||
|
||||
void UnlockForRead()
|
||||
{
|
||||
m_lock.UnlockRead();
|
||||
}
|
||||
|
||||
private:
|
||||
#ifdef WIN32
|
||||
mutable CThreadSpinRWLock m_lock;
|
||||
#else
|
||||
mutable CThreadRWLock m_lock;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CUtlFilenameSymbolTable:
|
||||
// description:
|
||||
// This class defines a symbol table of individual filenames, stored more
|
||||
// efficiently than a standard symbol table. Internally filenames are broken
|
||||
// up into file and path entries, and a file handle class allows convenient
|
||||
// access to these.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// The handle is a CUtlSymbol for the dirname and the same for the filename, the accessor
|
||||
// copies them into a static char buffer for return.
|
||||
typedef void* FileNameHandle_t;
|
||||
|
||||
// Symbol table for more efficiently storing filenames by breaking paths and filenames apart.
|
||||
// Refactored from Basefilesystem.h
|
||||
class CUtlFilenameSymbolTable
|
||||
{
|
||||
// Internal representation of a FileHandle_t
|
||||
// If we get more than 64K filenames, we'll have to revisit...
|
||||
// Right now CUtlSymbol is a short, so this packs into an int/void * pointer size...
|
||||
struct FileNameHandleInternal_t
|
||||
{
|
||||
FileNameHandleInternal_t()
|
||||
{
|
||||
path = 0;
|
||||
file = 0;
|
||||
}
|
||||
|
||||
// Part before the final '/' character
|
||||
unsigned short path;
|
||||
// Part after the final '/', including extension
|
||||
unsigned short file;
|
||||
};
|
||||
|
||||
public:
|
||||
FileNameHandle_t FindOrAddFileName( const char *pFileName );
|
||||
FileNameHandle_t FindFileName( const char *pFileName );
|
||||
int PathIndex(const FileNameHandle_t &handle) { return (( const FileNameHandleInternal_t * )&handle)->path; }
|
||||
bool String( const FileNameHandle_t& handle, char *buf, int buflen );
|
||||
void RemoveAll();
|
||||
void SpewStrings();
|
||||
bool SaveToBuffer( CUtlBuffer &buffer );
|
||||
bool RestoreFromBuffer( CUtlBuffer &buffer );
|
||||
|
||||
private:
|
||||
CCountedStringPool m_StringPool;
|
||||
mutable CThreadSpinRWLock m_lock;
|
||||
};
|
||||
|
||||
// This creates a simple class that includes the underlying CUtlSymbol
|
||||
// as a private member and then instances a private symbol table to
|
||||
// manage those symbols. Avoids the possibility of the code polluting the
|
||||
// 'global'/default symbol table, while letting the code look like
|
||||
// it's just using = and .String() to look at CUtlSymbol type objects
|
||||
//
|
||||
// NOTE: You can't pass these objects between .dlls in an interface (also true of CUtlSymbol of course)
|
||||
//
|
||||
#define DECLARE_PRIVATE_SYMBOLTYPE( typename ) \
|
||||
class typename \
|
||||
{ \
|
||||
public: \
|
||||
typename(); \
|
||||
typename( const char* pStr ); \
|
||||
typename& operator=( typename const& src ); \
|
||||
bool operator==( typename const& src ) const; \
|
||||
const char* String( ) const; \
|
||||
private: \
|
||||
CUtlSymbol m_SymbolId; \
|
||||
};
|
||||
|
||||
// Put this in the .cpp file that uses the above typename
|
||||
#define IMPLEMENT_PRIVATE_SYMBOLTYPE( typename ) \
|
||||
static CUtlSymbolTable g_##typename##SymbolTable; \
|
||||
typename::typename() \
|
||||
{ \
|
||||
m_SymbolId = UTL_INVAL_SYMBOL; \
|
||||
} \
|
||||
typename::typename( const char* pStr ) \
|
||||
{ \
|
||||
m_SymbolId = g_##typename##SymbolTable.AddString( pStr ); \
|
||||
} \
|
||||
typename& typename::operator=( typename const& src ) \
|
||||
{ \
|
||||
m_SymbolId = src.m_SymbolId; \
|
||||
return *this; \
|
||||
} \
|
||||
bool typename::operator==( typename const& src ) const \
|
||||
{ \
|
||||
return ( m_SymbolId == src.m_SymbolId ); \
|
||||
} \
|
||||
const char* typename::String( ) const \
|
||||
{ \
|
||||
return g_##typename##SymbolTable.String( m_SymbolId ); \
|
||||
}
|
||||
|
||||
#endif // UTLSYMBOL_H
|
||||
+1275
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user