This commit is contained in:
FluorescentCIAAfricanAmerican
2020-04-22 12:56:21 -04:00
commit 3bf9df6b27
15370 changed files with 5489726 additions and 0 deletions
+268
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+975
View File
@@ -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
+53
View File
@@ -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
View File
@@ -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
+179
View File
@@ -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
+920
View File
@@ -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
View File
@@ -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 */
+121
View File
@@ -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
View File
@@ -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
View File
@@ -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
+649
View File
@@ -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
+348
View File
@@ -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
+73
View File
@@ -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
+384
View File
@@ -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
View File
@@ -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
+589
View File
@@ -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 &nbsp; and calls through to the library function for everything else.
int isbreakablewspace( wchar_t ch );
#endif // TIER1_STRTOOLS_H
+85
View File
@@ -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
View File
@@ -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
File diff suppressed because it is too large Load Diff
+338
View File
@@ -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
View File
@@ -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
View File
@@ -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
+658
View File
@@ -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
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+248
View File
@@ -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
File diff suppressed because it is too large Load Diff
+769
View File
@@ -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
+176
View File
@@ -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
File diff suppressed because it is too large Load Diff
+354
View File
@@ -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
+331
View File
@@ -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
View File
@@ -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
View File
@@ -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
File diff suppressed because it is too large Load Diff