summaryrefslogtreecommitdiff
path: root/external/vpc/public/tier1
diff options
context:
space:
mode:
Diffstat (limited to 'external/vpc/public/tier1')
-rw-r--r--external/vpc/public/tier1/byteswap.h268
-rw-r--r--external/vpc/public/tier1/characterset.h43
-rw-r--r--external/vpc/public/tier1/checksum_crc.h31
-rw-r--r--external/vpc/public/tier1/checksum_md5.h33
-rw-r--r--external/vpc/public/tier1/convar.h975
-rw-r--r--external/vpc/public/tier1/convar_serverbounded.h53
-rw-r--r--external/vpc/public/tier1/exprevaluator.h74
-rw-r--r--external/vpc/public/tier1/fmtstr.h179
-rw-r--r--external/vpc/public/tier1/functors.h920
-rw-r--r--external/vpc/public/tier1/generichash.h116
-rw-r--r--external/vpc/public/tier1/iconvar.h121
-rw-r--r--external/vpc/public/tier1/interface.h226
-rw-r--r--external/vpc/public/tier1/keyvalues.h519
-rw-r--r--external/vpc/public/tier1/mempool.h649
-rw-r--r--external/vpc/public/tier1/memstack.h348
-rw-r--r--external/vpc/public/tier1/netadr.h73
-rw-r--r--external/vpc/public/tier1/refcount.h384
-rw-r--r--external/vpc/public/tier1/stringpool.h106
-rw-r--r--external/vpc/public/tier1/strtools.h589
-rw-r--r--external/vpc/public/tier1/tier1.h85
-rw-r--r--external/vpc/public/tier1/utlblockmemory.h349
-rw-r--r--external/vpc/public/tier1/utlbuffer.h1398
-rw-r--r--external/vpc/public/tier1/utldict.h338
-rw-r--r--external/vpc/public/tier1/utlenvelope.h241
-rw-r--r--external/vpc/public/tier1/utlfixedmemory.h354
-rw-r--r--external/vpc/public/tier1/utlgraph.h658
-rw-r--r--external/vpc/public/tier1/utlhash.h1299
-rw-r--r--external/vpc/public/tier1/utllinkedlist.h1087
-rw-r--r--external/vpc/public/tier1/utlmap.h248
-rw-r--r--external/vpc/public/tier1/utlmemory.h1090
-rw-r--r--external/vpc/public/tier1/utlmultilist.h769
-rw-r--r--external/vpc/public/tier1/utlqueue.h176
-rw-r--r--external/vpc/public/tier1/utlrbtree.h1581
-rw-r--r--external/vpc/public/tier1/utlsortvector.h354
-rw-r--r--external/vpc/public/tier1/utlstack.h331
-rw-r--r--external/vpc/public/tier1/utlstring.h373
-rw-r--r--external/vpc/public/tier1/utlsymbol.h345
-rw-r--r--external/vpc/public/tier1/utlvector.h1275
38 files changed, 18058 insertions, 0 deletions
diff --git a/external/vpc/public/tier1/byteswap.h b/external/vpc/public/tier1/byteswap.h
new file mode 100644
index 0000000..b4dea77
--- /dev/null
+++ b/external/vpc/public/tier1/byteswap.h
@@ -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 */
diff --git a/external/vpc/public/tier1/characterset.h b/external/vpc/public/tier1/characterset.h
new file mode 100644
index 0000000..42ef2c3
--- /dev/null
+++ b/external/vpc/public/tier1/characterset.h
@@ -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
diff --git a/external/vpc/public/tier1/checksum_crc.h b/external/vpc/public/tier1/checksum_crc.h
new file mode 100644
index 0000000..4c82376
--- /dev/null
+++ b/external/vpc/public/tier1/checksum_crc.h
@@ -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
diff --git a/external/vpc/public/tier1/checksum_md5.h b/external/vpc/public/tier1/checksum_md5.h
new file mode 100644
index 0000000..3692cf1
--- /dev/null
+++ b/external/vpc/public/tier1/checksum_md5.h
@@ -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
diff --git a/external/vpc/public/tier1/convar.h b/external/vpc/public/tier1/convar.h
new file mode 100644
index 0000000..d67a5d4
--- /dev/null
+++ b/external/vpc/public/tier1/convar.h
@@ -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
diff --git a/external/vpc/public/tier1/convar_serverbounded.h b/external/vpc/public/tier1/convar_serverbounded.h
new file mode 100644
index 0000000..3616239
--- /dev/null
+++ b/external/vpc/public/tier1/convar_serverbounded.h
@@ -0,0 +1,53 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Helper class for cvars that have restrictions on their value.
+//
+//=============================================================================//
+
+#ifndef CONVAR_SERVERBOUNDED_H
+#define CONVAR_SERVERBOUNDED_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+// This class is used to virtualize a ConVar's value, so the client can restrict its
+// value while connected to a server. When using this across modules, it's important
+// to dynamic_cast it to a ConVar_ServerBounded or you won't get the restricted value.
+//
+// NOTE: FCVAR_USERINFO vars are not virtualized before they are sent to the server
+// (we have no way to detect if the virtualized value would change), so
+// if you want to use a bounded cvar's value on the server, you must rebound it
+// the same way the client does.
+class ConVar_ServerBounded : public ConVar
+{
+public:
+ ConVar_ServerBounded( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString )
+ : ConVar( pName, pDefaultValue, flags, pHelpString )
+ {
+ }
+
+ ConVar_ServerBounded( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, FnChangeCallback_t callback )
+ : ConVar( pName, pDefaultValue, flags, pHelpString, callback )
+ {
+ }
+
+ ConVar_ServerBounded( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax )
+ : ConVar( pName, pDefaultValue, flags, pHelpString, bMin, fMin, bMax, fMax ) {}
+
+ // You must implement GetFloat.
+ virtual float GetFloat() const = 0;
+
+ // You can optionally implement these.
+ virtual int GetInt() const { return (int)GetFloat(); }
+ virtual bool GetBool() const { return ( GetInt() != 0 ); }
+
+ // Use this to get the underlying cvar's value.
+ float GetBaseFloatValue() const
+ {
+ return ConVar::GetFloat();
+ }
+};
+
+
+#endif // CONVAR_SERVERBOUNDED_H
diff --git a/external/vpc/public/tier1/exprevaluator.h b/external/vpc/public/tier1/exprevaluator.h
new file mode 100644
index 0000000..89dffc6
--- /dev/null
+++ b/external/vpc/public/tier1/exprevaluator.h
@@ -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
diff --git a/external/vpc/public/tier1/fmtstr.h b/external/vpc/public/tier1/fmtstr.h
new file mode 100644
index 0000000..476f4c5
--- /dev/null
+++ b/external/vpc/public/tier1/fmtstr.h
@@ -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
diff --git a/external/vpc/public/tier1/functors.h b/external/vpc/public/tier1/functors.h
new file mode 100644
index 0000000..5b74787
--- /dev/null
+++ b/external/vpc/public/tier1/functors.h
@@ -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
diff --git a/external/vpc/public/tier1/generichash.h b/external/vpc/public/tier1/generichash.h
new file mode 100644
index 0000000..44733d6
--- /dev/null
+++ b/external/vpc/public/tier1/generichash.h
@@ -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 */
diff --git a/external/vpc/public/tier1/iconvar.h b/external/vpc/public/tier1/iconvar.h
new file mode 100644
index 0000000..397c111
--- /dev/null
+++ b/external/vpc/public/tier1/iconvar.h
@@ -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
diff --git a/external/vpc/public/tier1/interface.h b/external/vpc/public/tier1/interface.h
new file mode 100644
index 0000000..90b0f11
--- /dev/null
+++ b/external/vpc/public/tier1/interface.h
@@ -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
+
+
+
diff --git a/external/vpc/public/tier1/keyvalues.h b/external/vpc/public/tier1/keyvalues.h
new file mode 100644
index 0000000..a419dec
--- /dev/null
+++ b/external/vpc/public/tier1/keyvalues.h
@@ -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
diff --git a/external/vpc/public/tier1/mempool.h b/external/vpc/public/tier1/mempool.h
new file mode 100644
index 0000000..67da207
--- /dev/null
+++ b/external/vpc/public/tier1/mempool.h
@@ -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
diff --git a/external/vpc/public/tier1/memstack.h b/external/vpc/public/tier1/memstack.h
new file mode 100644
index 0000000..f1846d2
--- /dev/null
+++ b/external/vpc/public/tier1/memstack.h
@@ -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
diff --git a/external/vpc/public/tier1/netadr.h b/external/vpc/public/tier1/netadr.h
new file mode 100644
index 0000000..c635a33
--- /dev/null
+++ b/external/vpc/public/tier1/netadr.h
@@ -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
diff --git a/external/vpc/public/tier1/refcount.h b/external/vpc/public/tier1/refcount.h
new file mode 100644
index 0000000..58bcf65
--- /dev/null
+++ b/external/vpc/public/tier1/refcount.h
@@ -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
diff --git a/external/vpc/public/tier1/stringpool.h b/external/vpc/public/tier1/stringpool.h
new file mode 100644
index 0000000..67dfb51
--- /dev/null
+++ b/external/vpc/public/tier1/stringpool.h
@@ -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
diff --git a/external/vpc/public/tier1/strtools.h b/external/vpc/public/tier1/strtools.h
new file mode 100644
index 0000000..62d335f
--- /dev/null
+++ b/external/vpc/public/tier1/strtools.h
@@ -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
diff --git a/external/vpc/public/tier1/tier1.h b/external/vpc/public/tier1/tier1.h
new file mode 100644
index 0000000..c4d89c6
--- /dev/null
+++ b/external/vpc/public/tier1/tier1.h
@@ -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
+
diff --git a/external/vpc/public/tier1/utlblockmemory.h b/external/vpc/public/tier1/utlblockmemory.h
new file mode 100644
index 0000000..81ba5e5
--- /dev/null
+++ b/external/vpc/public/tier1/utlblockmemory.h
@@ -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
diff --git a/external/vpc/public/tier1/utlbuffer.h b/external/vpc/public/tier1/utlbuffer.h
new file mode 100644
index 0000000..5832750
--- /dev/null
+++ b/external/vpc/public/tier1/utlbuffer.h
@@ -0,0 +1,1398 @@
+//====== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. =======//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+// Serialization/unserialization buffer
+//=============================================================================//
+
+#ifndef UTLBUFFER_H
+#define UTLBUFFER_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "unitlib/unitlib.h" // just here for tests - remove before checking in!!!
+
+#include "tier1/utlmemory.h"
+#include "tier1/byteswap.h"
+#include <stdarg.h>
+
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+struct characterset_t;
+
+
+//-----------------------------------------------------------------------------
+// Description of character conversions for string output
+// Here's an example of how to use the macros to define a character conversion
+// BEGIN_CHAR_CONVERSION( CStringConversion, '\\' )
+// { '\n', "n" },
+// { '\t', "t" }
+// END_CHAR_CONVERSION( CStringConversion, '\\' )
+//-----------------------------------------------------------------------------
+class CUtlCharConversion
+{
+public:
+ struct ConversionArray_t
+ {
+ char m_nActualChar;
+ char *m_pReplacementString;
+ };
+
+ CUtlCharConversion( char nEscapeChar, const char *pDelimiter, int nCount, ConversionArray_t *pArray );
+ char GetEscapeChar() const;
+ const char *GetDelimiter() const;
+ int GetDelimiterLength() const;
+
+ const char *GetConversionString( char c ) const;
+ int GetConversionLength( char c ) const;
+ int MaxConversionLength() const;
+
+ // Finds a conversion for the passed-in string, returns length
+ virtual char FindConversion( const char *pString, int *pLength );
+
+protected:
+ struct ConversionInfo_t
+ {
+ int m_nLength;
+ char *m_pReplacementString;
+ };
+
+ char m_nEscapeChar;
+ const char *m_pDelimiter;
+ int m_nDelimiterLength;
+ int m_nCount;
+ int m_nMaxConversionLength;
+ char m_pList[256];
+ ConversionInfo_t m_pReplacements[256];
+};
+
+#define BEGIN_CHAR_CONVERSION( _name, _delimiter, _escapeChar ) \
+ static CUtlCharConversion::ConversionArray_t s_pConversionArray ## _name[] = {
+
+#define END_CHAR_CONVERSION( _name, _delimiter, _escapeChar ) \
+ }; \
+ CUtlCharConversion _name( _escapeChar, _delimiter, sizeof( s_pConversionArray ## _name ) / sizeof( CUtlCharConversion::ConversionArray_t ), s_pConversionArray ## _name );
+
+#define BEGIN_CUSTOM_CHAR_CONVERSION( _className, _name, _delimiter, _escapeChar ) \
+ static CUtlCharConversion::ConversionArray_t s_pConversionArray ## _name[] = {
+
+#define END_CUSTOM_CHAR_CONVERSION( _className, _name, _delimiter, _escapeChar ) \
+ }; \
+ _className _name( _escapeChar, _delimiter, sizeof( s_pConversionArray ## _name ) / sizeof( CUtlCharConversion::ConversionArray_t ), s_pConversionArray ## _name );
+
+//-----------------------------------------------------------------------------
+// Character conversions for C strings
+//-----------------------------------------------------------------------------
+CUtlCharConversion *GetCStringCharConversion();
+
+//-----------------------------------------------------------------------------
+// Character conversions for quoted strings, with no escape sequences
+//-----------------------------------------------------------------------------
+CUtlCharConversion *GetNoEscCharConversion();
+
+
+//-----------------------------------------------------------------------------
+// Macro to set overflow functions easily
+//-----------------------------------------------------------------------------
+#define SetUtlBufferOverflowFuncs( _get, _put ) \
+ SetOverflowFuncs( static_cast <UtlBufferOverflowFunc_t>( _get ), static_cast <UtlBufferOverflowFunc_t>( _put ) )
+
+
+#define FMSTRRETTYPE static const char *
+#ifdef LINUX
+// gcc 4.3 is techinically correct and doesn't like the storage specifier,
+// unfortunately, that makes gcc on the mac and VS wind up with multiply defined
+// symbols at link time
+#define FMSTRRETTYPE const char *
+#endif
+
+typedef unsigned short ushort;
+
+template < class A >
+static const char *GetFmtStr( int nRadix = 10, bool bPrint = true ) { Assert( 0 ); return ""; }
+
+template <> FMSTRRETTYPE GetFmtStr< short > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%hd"; }
+template <> FMSTRRETTYPE GetFmtStr< ushort > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%hu"; }
+template <> FMSTRRETTYPE GetFmtStr< int > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%d"; }
+template <> FMSTRRETTYPE GetFmtStr< uint > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 || nRadix == 16 ); return nRadix == 16 ? "%x" : "%u"; }
+template <> FMSTRRETTYPE GetFmtStr< int64 > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%lld"; }
+template <> FMSTRRETTYPE GetFmtStr< float > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%f"; }
+template <> FMSTRRETTYPE GetFmtStr< double > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return bPrint ? "%.15lf" : "%lf"; } // force Printf to print DBL_DIG=15 digits of precision for doubles - defaults to FLT_DIG=6
+
+
+//-----------------------------------------------------------------------------
+// Command parsing..
+//-----------------------------------------------------------------------------
+class CUtlBuffer
+{
+// Brian has on his todo list to revisit this as there are issues in some cases with CUtlVector using operator = instead of copy construtor in InsertMultiple, etc.
+// The unsafe case is something like this:
+// CUtlVector< CUtlBuffer > vecFoo;
+//
+// CUtlBuffer buf;
+// buf.Put( xxx );
+// vecFoo.Insert( buf );
+//
+// This will cause memory corruption when vecFoo is cleared
+//
+//private:
+// // Disallow copying
+// CUtlBuffer( const CUtlBuffer & );// { Assert( 0 ); }
+// CUtlBuffer &operator=( const CUtlBuffer & );// { Assert( 0 ); return *this; }
+
+public:
+ enum SeekType_t
+ {
+ SEEK_HEAD = 0,
+ SEEK_CURRENT,
+ SEEK_TAIL
+ };
+
+ // flags
+ enum BufferFlags_t
+ {
+ TEXT_BUFFER = 0x1, // Describes how get + put work (as strings, or binary)
+ EXTERNAL_GROWABLE = 0x2, // This is used w/ external buffers and causes the utlbuf to switch to reallocatable memory if an overflow happens when Putting.
+ CONTAINS_CRLF = 0x4, // For text buffers only, does this contain \n or \n\r?
+ READ_ONLY = 0x8, // For external buffers; prevents null termination from happening.
+ AUTO_TABS_DISABLED = 0x10, // Used to disable/enable push/pop tabs
+ };
+
+ // Overflow functions when a get or put overflows
+ typedef bool (CUtlBuffer::*UtlBufferOverflowFunc_t)( int nSize );
+
+ // Constructors for growable + external buffers for serialization/unserialization
+ CUtlBuffer( int growSize = 0, int initSize = 0, int nFlags = 0 );
+ CUtlBuffer( const void* pBuffer, int size, int nFlags = 0 );
+ // This one isn't actually defined so that we catch contructors that are trying to pass a bool in as the third param.
+ CUtlBuffer( const void *pBuffer, int size, bool crap );
+
+ unsigned char GetFlags() const;
+
+ // NOTE: This will assert if you attempt to recast it in a way that
+ // is not compatible. The only valid conversion is binary-> text w/CRLF
+ void SetBufferType( bool bIsText, bool bContainsCRLF );
+
+ // Makes sure we've got at least this much memory
+ void EnsureCapacity( int num );
+
+ // Access for direct read into buffer
+ void * AccessForDirectRead( int nBytes );
+
+ // Attaches the buffer to external memory....
+ void SetExternalBuffer( void* pMemory, int nSize, int nInitialPut, int nFlags = 0 );
+ bool IsExternallyAllocated() const;
+ void AssumeMemory( void *pMemory, int nSize, int nInitialPut, int nFlags = 0 );
+ void *Detach();
+ void* DetachMemory();
+
+ FORCEINLINE void ActivateByteSwappingIfBigEndian( void )
+ {
+ if ( ( IsX360() || IsPS3() ) )
+ ActivateByteSwapping( true );
+ }
+
+
+ // Controls endian-ness of binary utlbufs - default matches the current platform
+ void ActivateByteSwapping( bool bActivate );
+ void SetBigEndian( bool bigEndian );
+ bool IsBigEndian( void );
+
+ // Resets the buffer; but doesn't free memory
+ void Clear();
+
+ // Clears out the buffer; frees memory
+ void Purge();
+
+ // Dump the buffer to stdout
+ void Spew( );
+
+ // Read stuff out.
+ // Binary mode: it'll just read the bits directly in, and characters will be
+ // read for strings until a null character is reached.
+ // Text mode: it'll parse the file, turning text #s into real numbers.
+ // GetString will read a string until a space is reached
+ char GetChar( );
+ unsigned char GetUnsignedChar( );
+ short GetShort( );
+ unsigned short GetUnsignedShort( );
+ int GetInt( );
+ int64 GetInt64( );
+ unsigned int GetIntHex( );
+ unsigned int GetUnsignedInt( );
+ float GetFloat( );
+ double GetDouble( );
+ void * GetPtr();
+ void GetString( char* pString, int nMaxChars = 0 );
+ void Get( void* pMem, int size );
+ void GetLine( char* pLine, int nMaxChars = 0 );
+
+ // Used for getting objects that have a byteswap datadesc defined
+ template <typename T> void GetObjects( T *dest, int count = 1 );
+
+ // This will get at least 1 byte and up to nSize bytes.
+ // It will return the number of bytes actually read.
+ int GetUpTo( void *pMem, int nSize );
+
+ // This version of GetString converts \" to \\ and " to \, etc.
+ // It also reads a " at the beginning and end of the string
+ void GetDelimitedString( CUtlCharConversion *pConv, char *pString, int nMaxChars = 0 );
+ char GetDelimitedChar( CUtlCharConversion *pConv );
+
+ // This will return the # of characters of the string about to be read out
+ // NOTE: The count will *include* the terminating 0!!
+ // In binary mode, it's the number of characters until the next 0
+ // In text mode, it's the number of characters until the next space.
+ int PeekStringLength();
+
+ // This version of PeekStringLength converts \" to \\ and " to \, etc.
+ // It also reads a " at the beginning and end of the string
+ // NOTE: The count will *include* the terminating 0!!
+ // In binary mode, it's the number of characters until the next 0
+ // In text mode, it's the number of characters between "s (checking for \")
+ // Specifying false for bActualSize will return the pre-translated number of characters
+ // including the delimiters and the escape characters. So, \n counts as 2 characters when bActualSize == false
+ // and only 1 character when bActualSize == true
+ int PeekDelimitedStringLength( CUtlCharConversion *pConv, bool bActualSize = true );
+
+ // Just like scanf, but doesn't work in binary mode
+ int Scanf( const char* pFmt, ... );
+ int VaScanf( const char* pFmt, va_list list );
+
+ // Eats white space, advances Get index
+ void EatWhiteSpace();
+
+ // Eats C++ style comments
+ bool EatCPPComment();
+
+ // (For text buffers only)
+ // Parse a token from the buffer:
+ // Grab all text that lies between a starting delimiter + ending delimiter
+ // (skipping whitespace that leads + trails both delimiters).
+ // If successful, the get index is advanced and the function returns true,
+ // otherwise the index is not advanced and the function returns false.
+ bool ParseToken( const char *pStartingDelim, const char *pEndingDelim, char* pString, int nMaxLen );
+
+ // Advance the get index until after the particular string is found
+ // Do not eat whitespace before starting. Return false if it failed
+ // String test is case-insensitive.
+ bool GetToken( const char *pToken );
+
+ // Parses the next token, given a set of character breaks to stop at
+ // Returns the length of the token parsed in bytes (-1 if none parsed)
+ int ParseToken( characterset_t *pBreaks, char *pTokenBuf, int nMaxLen, bool bParseComments = true );
+
+ // Write stuff in
+ // Binary mode: it'll just write the bits directly in, and strings will be
+ // written with a null terminating character
+ // Text mode: it'll convert the numbers to text versions
+ // PutString will not write a terminating character
+ void PutChar( char c );
+ void PutUnsignedChar( unsigned char uc );
+ void PutShort( short s );
+ void PutUnsignedShort( unsigned short us );
+ void PutInt( int i );
+ void PutInt64( int64 i );
+ void PutUnsignedInt( unsigned int u );
+ void PutFloat( float f );
+ void PutDouble( double d );
+ void PutPtr( void * ); // Writes the pointer, not the pointed to
+ void PutString( const char* pString );
+ void Put( const void* pMem, int size );
+
+ // Used for putting objects that have a byteswap datadesc defined
+ template <typename T> void PutObjects( T *src, int count = 1 );
+
+ // This version of PutString converts \ to \\ and " to \", etc.
+ // It also places " at the beginning and end of the string
+ void PutDelimitedString( CUtlCharConversion *pConv, const char *pString );
+ void PutDelimitedChar( CUtlCharConversion *pConv, char c );
+
+ // Just like printf, writes a terminating zero in binary mode
+ void Printf( const char* pFmt, ... ) FMTFUNCTION( 2, 3 );
+ void VaPrintf( const char* pFmt, va_list list );
+
+ // What am I writing (put)/reading (get)?
+ void* PeekPut( int offset = 0 );
+ const void* PeekGet( int offset = 0 ) const;
+ const void* PeekGet( int nMaxSize, int nOffset );
+
+ // Where am I writing (put)/reading (get)?
+ int TellPut( ) const;
+ int TellGet( ) const;
+
+ // What's the most I've ever written?
+ int TellMaxPut( ) const;
+
+ // How many bytes remain to be read?
+ // NOTE: This is not accurate for streaming text files; it overshoots
+ int GetBytesRemaining() const;
+
+ // Change where I'm writing (put)/reading (get)
+ void SeekPut( SeekType_t type, int offset );
+ void SeekGet( SeekType_t type, int offset );
+
+ // Buffer base
+ const void* Base() const;
+ void* Base();
+
+ // memory allocation size, does *not* reflect size written or read,
+ // use TellPut or TellGet for that
+ int Size() const;
+
+ // Am I a text buffer?
+ bool IsText() const;
+
+ // Can I grow if I'm externally allocated?
+ bool IsGrowable() const;
+
+ // Am I valid? (overflow or underflow error), Once invalid it stays invalid
+ bool IsValid() const;
+
+ // Do I contain carriage return/linefeeds?
+ bool ContainsCRLF() const;
+
+ // Am I read-only
+ bool IsReadOnly() const;
+
+ // Converts a buffer from a CRLF buffer to a CR buffer (and back)
+ // Returns false if no conversion was necessary (and outBuf is left untouched)
+ // If the conversion occurs, outBuf will be cleared.
+ bool ConvertCRLF( CUtlBuffer &outBuf );
+
+ // Push/pop pretty-printing tabs
+ void PushTab();
+ void PopTab();
+
+ // Temporarily disables pretty print
+ void EnableTabs( bool bEnable );
+
+#if !defined( _GAMECONSOLE )
+ // Swap my internal memory with another buffer,
+ // and copy all of its other members
+ void SwapCopy( CUtlBuffer &other ) ;
+#endif
+
+protected:
+ // error flags
+ enum
+ {
+ PUT_OVERFLOW = 0x1,
+ GET_OVERFLOW = 0x2,
+ MAX_ERROR_FLAG = GET_OVERFLOW,
+ };
+
+ void SetOverflowFuncs( UtlBufferOverflowFunc_t getFunc, UtlBufferOverflowFunc_t putFunc );
+
+ bool OnPutOverflow( int nSize );
+ bool OnGetOverflow( int nSize );
+
+protected:
+ // Checks if a get/put is ok
+ bool CheckPut( int size );
+ bool CheckGet( int size );
+
+ // NOTE: Pass in nPut here even though it is just a copy of m_Put. This is almost always called immediately
+ // after modifying m_Put and this lets it stay in a register
+ void AddNullTermination( int nPut );
+
+ // Methods to help with pretty-printing
+ bool WasLastCharacterCR();
+ void PutTabs();
+
+ // Help with delimited stuff
+ char GetDelimitedCharInternal( CUtlCharConversion *pConv );
+ void PutDelimitedCharInternal( CUtlCharConversion *pConv, char c );
+
+ // Default overflow funcs
+ bool PutOverflow( int nSize );
+ bool GetOverflow( int nSize );
+
+ // Does the next bytes of the buffer match a pattern?
+ bool PeekStringMatch( int nOffset, const char *pString, int nLen );
+
+ // Peek size of line to come, check memory bound
+ int PeekLineLength();
+
+ // How much whitespace should I skip?
+ int PeekWhiteSpace( int nOffset );
+
+ // Checks if a peek get is ok
+ bool CheckPeekGet( int nOffset, int nSize );
+
+ // Call this to peek arbitrarily long into memory. It doesn't fail unless
+ // it can't read *anything* new
+ bool CheckArbitraryPeekGet( int nOffset, int &nIncrement );
+
+ template <typename T> void GetType( T& dest );
+ template <typename T> void GetTypeBin( T& dest );
+ template <typename T> bool GetTypeText( T &value, int nRadix = 10 );
+ template <typename T> void GetObject( T *src );
+
+ template <typename T> void PutType( T src );
+ template <typename T> void PutTypeBin( T src );
+ template <typename T> void PutObject( T *src );
+
+ // be sure to also update the copy constructor
+ // and SwapCopy() when adding members.
+ CUtlMemory<unsigned char> m_Memory;
+ int m_Get;
+ int m_Put;
+
+ unsigned char m_Error;
+ unsigned char m_Flags;
+ unsigned char m_Reserved;
+#if defined( _GAMECONSOLE )
+ unsigned char pad;
+#endif
+
+ int m_nTab;
+ int m_nMaxPut;
+ int m_nOffset;
+
+ UtlBufferOverflowFunc_t m_GetOverflowFunc;
+ UtlBufferOverflowFunc_t m_PutOverflowFunc;
+
+ CByteswap m_Byteswap;
+};
+
+
+// Stream style output operators for CUtlBuffer
+inline CUtlBuffer &operator<<( CUtlBuffer &b, char v )
+{
+ b.PutChar( v );
+ return b;
+}
+
+inline CUtlBuffer &operator<<( CUtlBuffer &b, unsigned char v )
+{
+ b.PutUnsignedChar( v );
+ return b;
+}
+
+inline CUtlBuffer &operator<<( CUtlBuffer &b, short v )
+{
+ b.PutShort( v );
+ return b;
+}
+
+inline CUtlBuffer &operator<<( CUtlBuffer &b, unsigned short v )
+{
+ b.PutUnsignedShort( v );
+ return b;
+}
+
+inline CUtlBuffer &operator<<( CUtlBuffer &b, int v )
+{
+ b.PutInt( v );
+ return b;
+}
+
+inline CUtlBuffer &operator<<( CUtlBuffer &b, unsigned int v )
+{
+ b.PutUnsignedInt( v );
+ return b;
+}
+
+inline CUtlBuffer &operator<<( CUtlBuffer &b, float v )
+{
+ b.PutFloat( v );
+ return b;
+}
+
+inline CUtlBuffer &operator<<( CUtlBuffer &b, double v )
+{
+ b.PutDouble( v );
+ return b;
+}
+
+inline CUtlBuffer &operator<<( CUtlBuffer &b, const char *pv )
+{
+ b.PutString( pv );
+ return b;
+}
+
+inline CUtlBuffer &operator<<( CUtlBuffer &b, const Vector &v )
+{
+ b << v.x << " " << v.y << " " << v.z;
+ return b;
+}
+
+inline CUtlBuffer &operator<<( CUtlBuffer &b, const Vector2D &v )
+{
+ b << v.x << " " << v.y;
+ return b;
+}
+
+
+class CUtlInplaceBuffer : public CUtlBuffer
+{
+public:
+ CUtlInplaceBuffer( int growSize = 0, int initSize = 0, int nFlags = 0 );
+
+ //
+ // Routines returning buffer-inplace-pointers
+ //
+public:
+ //
+ // Upon success, determines the line length, fills out the pointer to the
+ // beginning of the line and the line length, advances the "get" pointer
+ // offset by the line length and returns "true".
+ //
+ // If end of file is reached or upon error returns "false".
+ //
+ // Note: the returned length of the line is at least one character because the
+ // trailing newline characters are also included as part of the line.
+ //
+ // Note: the pointer returned points into the local memory of this buffer, in
+ // case the buffer gets relocated or destroyed the pointer becomes invalid.
+ //
+ // e.g.: -------------
+ //
+ // char *pszLine;
+ // int nLineLen;
+ // while ( pUtlInplaceBuffer->InplaceGetLinePtr( &pszLine, &nLineLen ) )
+ // {
+ // ...
+ // }
+ //
+ // -------------
+ //
+ // @param ppszInBufferPtr on return points into this buffer at start of line
+ // @param pnLineLength on return holds num bytes accessible via (*ppszInBufferPtr)
+ //
+ // @returns true if line was successfully read
+ // false when EOF is reached or error occurs
+ //
+ bool InplaceGetLinePtr( /* out */ char **ppszInBufferPtr, /* out */ int *pnLineLength );
+
+ //
+ // Determines the line length, advances the "get" pointer offset by the line length,
+ // replaces the newline character with null-terminator and returns the initial pointer
+ // to now null-terminated line.
+ //
+ // If end of file is reached or upon error returns NULL.
+ //
+ // Note: the pointer returned points into the local memory of this buffer, in
+ // case the buffer gets relocated or destroyed the pointer becomes invalid.
+ //
+ // e.g.: -------------
+ //
+ // while ( char *pszLine = pUtlInplaceBuffer->InplaceGetLinePtr() )
+ // {
+ // ...
+ // }
+ //
+ // -------------
+ //
+ // @returns ptr-to-zero-terminated-line if line was successfully read and buffer modified
+ // NULL when EOF is reached or error occurs
+ //
+ char * InplaceGetLinePtr( void );
+};
+
+
+//-----------------------------------------------------------------------------
+// Where am I reading?
+//-----------------------------------------------------------------------------
+inline int CUtlBuffer::TellGet( ) const
+{
+ return m_Get;
+}
+
+
+//-----------------------------------------------------------------------------
+// How many bytes remain to be read?
+//-----------------------------------------------------------------------------
+inline int CUtlBuffer::GetBytesRemaining() const
+{
+ return m_nMaxPut - TellGet();
+}
+
+
+//-----------------------------------------------------------------------------
+// What am I reading?
+//-----------------------------------------------------------------------------
+inline const void* CUtlBuffer::PeekGet( int offset ) const
+{
+ return &m_Memory[ m_Get + offset - m_nOffset ];
+}
+
+
+//-----------------------------------------------------------------------------
+// Unserialization
+//-----------------------------------------------------------------------------
+
+template <typename T>
+inline void CUtlBuffer::GetObject( T *dest )
+{
+ if ( CheckGet( sizeof(T) ) )
+ {
+ if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) )
+ {
+ *dest = *(T *)PeekGet();
+ }
+ else
+ {
+ m_Byteswap.SwapFieldsToTargetEndian<T>( dest, (T*)PeekGet() );
+ }
+ m_Get += sizeof(T);
+ }
+ else
+ {
+ V_memset( &dest, 0, sizeof(T) );
+ }
+}
+
+
+template <typename T>
+inline void CUtlBuffer::GetObjects( T *dest, int count )
+{
+ for ( int i = 0; i < count; ++i, ++dest )
+ {
+ GetObject<T>( dest );
+ }
+}
+
+
+template <typename T>
+inline void CUtlBuffer::GetTypeBin( T &dest )
+{
+ if ( CheckGet( sizeof(T) ) )
+ {
+ if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) )
+ {
+ dest = *(T *)PeekGet();
+ }
+ else
+ {
+ m_Byteswap.SwapBufferToTargetEndian<T>( &dest, (T*)PeekGet() );
+ }
+ m_Get += sizeof(T);
+ }
+ else
+ {
+ dest = 0;
+ }
+}
+
+template <>
+inline void CUtlBuffer::GetTypeBin< float >( float &dest )
+{
+ if ( CheckGet( sizeof( float ) ) )
+ {
+ uintp pData = (uintp)PeekGet();
+ if ( ( IsX360() || IsPS3() ) && ( pData & 0x03 ) )
+ {
+ // handle unaligned read
+ ((unsigned char*)&dest)[0] = ((unsigned char*)pData)[0];
+ ((unsigned char*)&dest)[1] = ((unsigned char*)pData)[1];
+ ((unsigned char*)&dest)[2] = ((unsigned char*)pData)[2];
+ ((unsigned char*)&dest)[3] = ((unsigned char*)pData)[3];
+ }
+ else
+ {
+ // aligned read
+ dest = *(float *)pData;
+ }
+ if ( m_Byteswap.IsSwappingBytes() )
+ {
+ m_Byteswap.SwapBufferToTargetEndian< float >( &dest, &dest );
+ }
+ m_Get += sizeof( float );
+ }
+ else
+ {
+ dest = 0;
+ }
+}
+
+template <>
+inline void CUtlBuffer::GetTypeBin< double >( double &dest )
+{
+ if ( CheckGet( sizeof( double ) ) )
+ {
+ uintp pData = (uintp)PeekGet();
+ if ( ( IsX360() || IsPS3() ) && ( pData & 0x07 ) )
+ {
+ // handle unaligned read
+ ((unsigned char*)&dest)[0] = ((unsigned char*)pData)[0];
+ ((unsigned char*)&dest)[1] = ((unsigned char*)pData)[1];
+ ((unsigned char*)&dest)[2] = ((unsigned char*)pData)[2];
+ ((unsigned char*)&dest)[3] = ((unsigned char*)pData)[3];
+ ((unsigned char*)&dest)[4] = ((unsigned char*)pData)[4];
+ ((unsigned char*)&dest)[5] = ((unsigned char*)pData)[5];
+ ((unsigned char*)&dest)[6] = ((unsigned char*)pData)[6];
+ ((unsigned char*)&dest)[7] = ((unsigned char*)pData)[7];
+ }
+ else
+ {
+ // aligned read
+ dest = *(double *)pData;
+ }
+ if ( m_Byteswap.IsSwappingBytes() )
+ {
+ m_Byteswap.SwapBufferToTargetEndian< double >( &dest, &dest );
+ }
+ m_Get += sizeof( double );
+ }
+ else
+ {
+ dest = 0;
+ }
+}
+
+template < class T >
+inline T StringToNumber( char *pString, char **ppEnd, int nRadix )
+{
+ Assert( 0 );
+ *ppEnd = pString;
+ return 0;
+}
+
+template <>
+inline int8 StringToNumber( char *pString, char **ppEnd, int nRadix )
+{
+ return ( int8 )strtol( pString, ppEnd, nRadix );
+}
+
+template <>
+inline uint8 StringToNumber( char *pString, char **ppEnd, int nRadix )
+{
+ return ( uint8 )strtoul( pString, ppEnd, nRadix );
+}
+
+template <>
+inline int16 StringToNumber( char *pString, char **ppEnd, int nRadix )
+{
+ return ( int16 )strtol( pString, ppEnd, nRadix );
+}
+
+template <>
+inline uint16 StringToNumber( char *pString, char **ppEnd, int nRadix )
+{
+ return ( uint16 )strtoul( pString, ppEnd, nRadix );
+}
+
+template <>
+inline int32 StringToNumber( char *pString, char **ppEnd, int nRadix )
+{
+ return ( int32 )strtol( pString, ppEnd, nRadix );
+}
+
+template <>
+inline uint32 StringToNumber( char *pString, char **ppEnd, int nRadix )
+{
+ return ( uint32 )strtoul( pString, ppEnd, nRadix );
+}
+
+template <>
+inline int64 StringToNumber( char *pString, char **ppEnd, int nRadix )
+{
+#if defined(_PS3) || defined(POSIX)
+ return ( int64 )strtoll( pString, ppEnd, nRadix );
+#else // !_PS3
+ return ( int64 )_strtoi64( pString, ppEnd, nRadix );
+#endif // _PS3
+}
+
+template <>
+inline float StringToNumber( char *pString, char **ppEnd, int nRadix )
+{
+ NOTE_UNUSED( nRadix );
+ return ( float )strtod( pString, ppEnd );
+}
+
+template <>
+inline double StringToNumber( char *pString, char **ppEnd, int nRadix )
+{
+ NOTE_UNUSED( nRadix );
+ return ( double )strtod( pString, ppEnd );
+}
+
+template <typename T>
+inline bool CUtlBuffer::GetTypeText( T &value, int nRadix /*= 10*/ )
+{
+ // NOTE: This is not bullet-proof; it assumes numbers are < 128 characters
+ int nLength = 128;
+ if ( !CheckArbitraryPeekGet( 0, nLength ) )
+ {
+ value = 0;
+ return false;
+ }
+
+ char *pStart = (char*)PeekGet();
+ char* pEnd = pStart;
+ value = StringToNumber< T >( pStart, &pEnd, nRadix );
+
+ int nBytesRead = (int)( pEnd - pStart );
+ if ( nBytesRead == 0 )
+ return false;
+
+ m_Get += nBytesRead;
+ return true;
+}
+
+template <typename T>
+inline void CUtlBuffer::GetType( T &dest )
+{
+ if (!IsText())
+ {
+ GetTypeBin( dest );
+ }
+ else
+ {
+ GetTypeText( dest );
+ }
+}
+
+inline char CUtlBuffer::GetChar( )
+{
+ // LEGACY WARNING: this behaves differently than GetUnsignedChar()
+ char c;
+ GetTypeBin( c ); // always reads as binary
+ return c;
+}
+
+inline unsigned char CUtlBuffer::GetUnsignedChar( )
+{
+ // LEGACY WARNING: this behaves differently than GetChar()
+ unsigned char c;
+ if (!IsText())
+ {
+ GetTypeBin( c );
+ }
+ else
+ {
+ c = ( unsigned char )GetUnsignedShort();
+ }
+ return c;
+}
+
+inline short CUtlBuffer::GetShort( )
+{
+ short s;
+ GetType( s );
+ return s;
+}
+
+inline unsigned short CUtlBuffer::GetUnsignedShort( )
+{
+ unsigned short s;
+ GetType( s );
+ return s;
+}
+
+inline int CUtlBuffer::GetInt( )
+{
+ int i;
+ GetType( i );
+ return i;
+}
+
+inline int64 CUtlBuffer::GetInt64( )
+{
+ int64 i;
+ GetType( i );
+ return i;
+}
+
+inline unsigned int CUtlBuffer::GetIntHex( )
+{
+ uint i;
+ if (!IsText())
+ {
+ GetTypeBin( i );
+ }
+ else
+ {
+ GetTypeText( i, 16 );
+ }
+ return i;
+}
+
+inline unsigned int CUtlBuffer::GetUnsignedInt( )
+{
+ unsigned int i;
+ GetType( i );
+ return i;
+}
+
+inline float CUtlBuffer::GetFloat( )
+{
+ float f;
+ GetType( f );
+ return f;
+}
+
+inline double CUtlBuffer::GetDouble( )
+{
+ double d;
+ GetType( d );
+ return d;
+}
+
+inline void *CUtlBuffer::GetPtr( )
+{
+ void *p;
+ // LEGACY WARNING: in text mode, PutPtr writes 32 bit pointers in hex, while GetPtr reads 32 or 64 bit pointers in decimal
+#ifndef X64BITS
+ p = ( void* )GetUnsignedInt();
+#else
+ p = ( void* )GetInt64();
+#endif
+ return p;
+}
+
+//-----------------------------------------------------------------------------
+// Where am I writing?
+//-----------------------------------------------------------------------------
+inline unsigned char CUtlBuffer::GetFlags() const
+{
+ return m_Flags;
+}
+
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+inline bool CUtlBuffer::IsExternallyAllocated() const
+{
+ return m_Memory.IsExternallyAllocated();
+}
+
+
+//-----------------------------------------------------------------------------
+// Where am I writing?
+//-----------------------------------------------------------------------------
+inline int CUtlBuffer::TellPut( ) const
+{
+ return m_Put;
+}
+
+
+//-----------------------------------------------------------------------------
+// What's the most I've ever written?
+//-----------------------------------------------------------------------------
+inline int CUtlBuffer::TellMaxPut( ) const
+{
+ return m_nMaxPut;
+}
+
+
+//-----------------------------------------------------------------------------
+// What am I reading?
+//-----------------------------------------------------------------------------
+inline void* CUtlBuffer::PeekPut( int offset )
+{
+ return &m_Memory[m_Put + offset - m_nOffset];
+}
+
+
+//-----------------------------------------------------------------------------
+// Various put methods
+//-----------------------------------------------------------------------------
+
+template <typename T>
+inline void CUtlBuffer::PutObject( T *src )
+{
+ if ( CheckPut( sizeof(T) ) )
+ {
+ if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) )
+ {
+ *(T *)PeekPut() = *src;
+ }
+ else
+ {
+ m_Byteswap.SwapFieldsToTargetEndian<T>( (T*)PeekPut(), src );
+ }
+ m_Put += sizeof(T);
+ AddNullTermination( m_Put );
+ }
+}
+
+
+template <typename T>
+inline void CUtlBuffer::PutObjects( T *src, int count )
+{
+ for ( int i = 0; i < count; ++i, ++src )
+ {
+ PutObject<T>( src );
+ }
+}
+
+
+template <typename T>
+inline void CUtlBuffer::PutTypeBin( T src )
+{
+ if ( CheckPut( sizeof(T) ) )
+ {
+ if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) )
+ {
+ *(T *)PeekPut() = src;
+ }
+ else
+ {
+ m_Byteswap.SwapBufferToTargetEndian<T>( (T*)PeekPut(), &src );
+ }
+ m_Put += sizeof(T);
+ AddNullTermination( m_Put );
+ }
+}
+
+#if defined( _GAMECONSOLE )
+template <>
+inline void CUtlBuffer::PutTypeBin< float >( float src )
+{
+ if ( CheckPut( sizeof( src ) ) )
+ {
+ if ( m_Byteswap.IsSwappingBytes() )
+ {
+ m_Byteswap.SwapBufferToTargetEndian<float>( &src, &src );
+ }
+
+ //
+ // Write the data
+ //
+ unsigned pData = (unsigned)PeekPut();
+ if ( pData & 0x03 )
+ {
+ // handle unaligned write
+ byte* dst = (byte*)pData;
+ byte* srcPtr = (byte*)&src;
+ dst[0] = srcPtr[0];
+ dst[1] = srcPtr[1];
+ dst[2] = srcPtr[2];
+ dst[3] = srcPtr[3];
+ }
+ else
+ {
+ *(float *)pData = src;
+ }
+
+ m_Put += sizeof(float);
+ AddNullTermination( m_Put );
+ }
+}
+
+template <>
+inline void CUtlBuffer::PutTypeBin< double >( double src )
+{
+ if ( CheckPut( sizeof( src ) ) )
+ {
+ if ( m_Byteswap.IsSwappingBytes() )
+ {
+ m_Byteswap.SwapBufferToTargetEndian<double>( &src, &src );
+ }
+
+ //
+ // Write the data
+ //
+ unsigned pData = (unsigned)PeekPut();
+ if ( pData & 0x07 )
+ {
+ // handle unaligned write
+ byte* dst = (byte*)pData;
+ byte* srcPtr = (byte*)&src;
+ dst[0] = srcPtr[0];
+ dst[1] = srcPtr[1];
+ dst[2] = srcPtr[2];
+ dst[3] = srcPtr[3];
+ dst[4] = srcPtr[4];
+ dst[5] = srcPtr[5];
+ dst[6] = srcPtr[6];
+ dst[7] = srcPtr[7];
+ }
+ else
+ {
+ *(double *)pData = src;
+ }
+
+ m_Put += sizeof(double);
+ AddNullTermination( m_Put );
+ }
+}
+#endif
+
+template <typename T>
+inline void CUtlBuffer::PutType( T src )
+{
+ if (!IsText())
+ {
+ PutTypeBin( src );
+ }
+ else
+ {
+ Printf( GetFmtStr< T >(), src );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Methods to help with pretty-printing
+//-----------------------------------------------------------------------------
+inline bool CUtlBuffer::WasLastCharacterCR()
+{
+ if ( !IsText() || (TellPut() == 0) )
+ return false;
+ return ( *( const char * )PeekPut( -1 ) == '\n' );
+}
+
+inline void CUtlBuffer::PutTabs()
+{
+ int nTabCount = ( m_Flags & AUTO_TABS_DISABLED ) ? 0 : m_nTab;
+ for (int i = nTabCount; --i >= 0; )
+ {
+ PutTypeBin<char>( '\t' );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Push/pop pretty-printing tabs
+//-----------------------------------------------------------------------------
+inline void CUtlBuffer::PushTab( )
+{
+ ++m_nTab;
+}
+
+inline void CUtlBuffer::PopTab()
+{
+ if ( --m_nTab < 0 )
+ {
+ m_nTab = 0;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Temporarily disables pretty print
+//-----------------------------------------------------------------------------
+inline void CUtlBuffer::EnableTabs( bool bEnable )
+{
+ if ( bEnable )
+ {
+ m_Flags &= ~AUTO_TABS_DISABLED;
+ }
+ else
+ {
+ m_Flags |= AUTO_TABS_DISABLED;
+ }
+}
+
+inline void CUtlBuffer::PutChar( char c )
+{
+ if ( WasLastCharacterCR() )
+ {
+ PutTabs();
+ }
+
+ PutTypeBin( c );
+}
+
+inline void CUtlBuffer::PutUnsignedChar( unsigned char c )
+{
+ if (!IsText())
+ {
+ PutTypeBin( c );
+ }
+ else
+ {
+ PutUnsignedShort( c );
+ }
+}
+
+inline void CUtlBuffer::PutShort( short s )
+{
+ PutType( s );
+}
+
+inline void CUtlBuffer::PutUnsignedShort( unsigned short s )
+{
+ PutType( s );
+}
+
+inline void CUtlBuffer::PutInt( int i )
+{
+ PutType( i );
+}
+
+inline void CUtlBuffer::PutInt64( int64 i )
+{
+ PutType( i );
+}
+
+inline void CUtlBuffer::PutUnsignedInt( unsigned int u )
+{
+ PutType( u );
+}
+
+inline void CUtlBuffer::PutFloat( float f )
+{
+ PutType( f );
+}
+
+inline void CUtlBuffer::PutDouble( double d )
+{
+ PutType( d );
+}
+
+inline void CUtlBuffer::PutPtr( void *p )
+{
+ // LEGACY WARNING: in text mode, PutPtr writes 32 bit pointers in hex, while GetPtr reads 32 or 64 bit pointers in decimal
+ if (!IsText())
+ {
+ PutTypeBin( p );
+ }
+ else
+ {
+ Printf( "0x%p", p );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Am I a text buffer?
+//-----------------------------------------------------------------------------
+inline bool CUtlBuffer::IsText() const
+{
+ return (m_Flags & TEXT_BUFFER) != 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Can I grow if I'm externally allocated?
+//-----------------------------------------------------------------------------
+inline bool CUtlBuffer::IsGrowable() const
+{
+ return (m_Flags & EXTERNAL_GROWABLE) != 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Am I valid? (overflow or underflow error), Once invalid it stays invalid
+//-----------------------------------------------------------------------------
+inline bool CUtlBuffer::IsValid() const
+{
+ return m_Error == 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Do I contain carriage return/linefeeds?
+//-----------------------------------------------------------------------------
+inline bool CUtlBuffer::ContainsCRLF() const
+{
+ return IsText() && ((m_Flags & CONTAINS_CRLF) != 0);
+}
+
+
+//-----------------------------------------------------------------------------
+// Am I read-only
+//-----------------------------------------------------------------------------
+inline bool CUtlBuffer::IsReadOnly() const
+{
+ return (m_Flags & READ_ONLY) != 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Buffer base and size
+//-----------------------------------------------------------------------------
+inline const void* CUtlBuffer::Base() const
+{
+ return m_Memory.Base();
+}
+
+inline void* CUtlBuffer::Base()
+{
+ return m_Memory.Base();
+}
+
+inline int CUtlBuffer::Size() const
+{
+ return m_Memory.NumAllocated();
+}
+
+
+//-----------------------------------------------------------------------------
+// Clears out the buffer; frees memory
+//-----------------------------------------------------------------------------
+inline void CUtlBuffer::Clear()
+{
+ m_Get = 0;
+ m_Put = 0;
+ m_Error = 0;
+ m_nOffset = 0;
+ m_nMaxPut = -1;
+ AddNullTermination( m_Put );
+}
+
+inline void CUtlBuffer::Purge()
+{
+ m_Get = 0;
+ m_Put = 0;
+ m_nOffset = 0;
+ m_nMaxPut = 0;
+ m_Error = 0;
+ m_Memory.Purge();
+}
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+inline void *CUtlBuffer::AccessForDirectRead( int nBytes )
+{
+ Assert( m_Get == 0 && m_Put == 0 && m_nMaxPut == 0 );
+ EnsureCapacity( nBytes );
+ m_nMaxPut = nBytes;
+ return Base();
+}
+
+inline void *CUtlBuffer::Detach()
+{
+ void *p = m_Memory.Detach();
+ Clear();
+ return p;
+}
+
+//-----------------------------------------------------------------------------
+
+inline void CUtlBuffer::Spew( )
+{
+ SeekGet( CUtlBuffer::SEEK_HEAD, 0 );
+
+ char pTmpLine[1024];
+ while( IsValid() && GetBytesRemaining() )
+ {
+ V_memset( pTmpLine, 0, sizeof(pTmpLine) );
+ Get( pTmpLine, MIN( ( size_t )GetBytesRemaining(), sizeof(pTmpLine)-1 ) );
+ Msg( _T( "%s" ), pTmpLine );
+ }
+}
+
+#if !defined(_GAMECONSOLE)
+inline void CUtlBuffer::SwapCopy( CUtlBuffer &other )
+{
+ m_Get = other.m_Get;
+ m_Put = other.m_Put;
+ m_Error = other.m_Error;
+ m_Flags = other.m_Flags;
+ m_Reserved = other.m_Reserved;
+ m_nTab = other.m_nTab;
+ m_nMaxPut = other.m_nMaxPut;
+ m_nOffset = other.m_nOffset;
+ m_GetOverflowFunc = other.m_GetOverflowFunc;
+ m_PutOverflowFunc = other.m_PutOverflowFunc;
+ m_Byteswap = other.m_Byteswap;
+
+ m_Memory.Swap( other.m_Memory );
+}
+#endif
+
+#endif // UTLBUFFER_H
+
diff --git a/external/vpc/public/tier1/utldict.h b/external/vpc/public/tier1/utldict.h
new file mode 100644
index 0000000..cb6d4f1
--- /dev/null
+++ b/external/vpc/public/tier1/utldict.h
@@ -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
diff --git a/external/vpc/public/tier1/utlenvelope.h b/external/vpc/public/tier1/utlenvelope.h
new file mode 100644
index 0000000..28e434b
--- /dev/null
+++ b/external/vpc/public/tier1/utlenvelope.h
@@ -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
diff --git a/external/vpc/public/tier1/utlfixedmemory.h b/external/vpc/public/tier1/utlfixedmemory.h
new file mode 100644
index 0000000..a124889
--- /dev/null
+++ b/external/vpc/public/tier1/utlfixedmemory.h
@@ -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
diff --git a/external/vpc/public/tier1/utlgraph.h b/external/vpc/public/tier1/utlgraph.h
new file mode 100644
index 0000000..9b9482e
--- /dev/null
+++ b/external/vpc/public/tier1/utlgraph.h
@@ -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
diff --git a/external/vpc/public/tier1/utlhash.h b/external/vpc/public/tier1/utlhash.h
new file mode 100644
index 0000000..aaddb29
--- /dev/null
+++ b/external/vpc/public/tier1/utlhash.h
@@ -0,0 +1,1299 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+// Serialization/unserialization buffer
+//=============================================================================//
+
+#ifndef UTLHASH_H
+#define UTLHASH_H
+#pragma once
+
+#include <limits.h>
+#include "utlmemory.h"
+#include "utlvector.h"
+#include "utllinkedlist.h"
+#include "utllinkedlist.h"
+#include "commonmacros.h"
+#include "generichash.h"
+
+typedef unsigned int UtlHashHandle_t;
+
+template<class Data, typename C = bool (*)( Data const&, Data const& ), typename K = unsigned int (*)( Data const& ) >
+class CUtlHash
+{
+public:
+ // compare and key functions - implemented by the
+ typedef C CompareFunc_t;
+ typedef K KeyFunc_t;
+
+ // constructor/deconstructor
+ CUtlHash( int bucketCount = 0, int growCount = 0, int initCount = 0,
+ CompareFunc_t compareFunc = 0, KeyFunc_t keyFunc = 0 );
+ ~CUtlHash();
+
+ // invalid handle
+ static UtlHashHandle_t InvalidHandle( void ) { return ( UtlHashHandle_t )~0; }
+ bool IsValidHandle( UtlHashHandle_t handle ) const;
+
+ // size
+ int Count( void ) const;
+
+ // memory
+ void Purge( void );
+
+ // insertion methods
+ UtlHashHandle_t Insert( Data const &src );
+ UtlHashHandle_t Insert( Data const &src, bool *pDidInsert );
+ UtlHashHandle_t AllocEntryFromKey( Data const &src );
+
+ // removal methods
+ void Remove( UtlHashHandle_t handle );
+ void RemoveAll();
+
+ // retrieval methods
+ UtlHashHandle_t Find( Data const &src ) const;
+
+ Data &Element( UtlHashHandle_t handle );
+ Data const &Element( UtlHashHandle_t handle ) const;
+ Data &operator[]( UtlHashHandle_t handle );
+ Data const &operator[]( UtlHashHandle_t handle ) const;
+
+ UtlHashHandle_t GetFirstHandle() const;
+ UtlHashHandle_t GetNextHandle( UtlHashHandle_t h ) const;
+
+ // debugging!!
+ void Log( const char *filename );
+ void Dump();
+
+protected:
+
+ int GetBucketIndex( UtlHashHandle_t handle ) const;
+ int GetKeyDataIndex( UtlHashHandle_t handle ) const;
+ UtlHashHandle_t BuildHandle( int ndxBucket, int ndxKeyData ) const;
+
+ bool DoFind( Data const &src, unsigned int *pBucket, int *pIndex ) const;
+
+protected:
+
+ // handle upper 16 bits = bucket index (bucket heads)
+ // handle lower 16 bits = key index (bucket list)
+ typedef CUtlVector<Data> HashBucketList_t;
+ CUtlVector<HashBucketList_t> m_Buckets;
+
+ CompareFunc_t m_CompareFunc; // function used to handle unique compares on data
+ KeyFunc_t m_KeyFunc; // function used to generate the key value
+
+ bool m_bPowerOfTwo; // if the bucket value is a power of two,
+ unsigned int m_ModMask; // use the mod mask to "mod"
+};
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+CUtlHash<Data, C, K>::CUtlHash( int bucketCount, int growCount, int initCount,
+ CompareFunc_t compareFunc, KeyFunc_t keyFunc ) :
+ m_CompareFunc( compareFunc ),
+ m_KeyFunc( keyFunc )
+{
+ bucketCount = MIN(bucketCount, 65536);
+ m_Buckets.SetSize( bucketCount );
+ for( int ndxBucket = 0; ndxBucket < bucketCount; ndxBucket++ )
+ {
+ m_Buckets[ndxBucket].SetSize( initCount );
+ m_Buckets[ndxBucket].SetGrowSize( growCount );
+ }
+
+ // check to see if the bucket count is a power of 2 and set up
+ // optimizations appropriately
+ m_bPowerOfTwo = IsPowerOfTwo( bucketCount );
+ m_ModMask = m_bPowerOfTwo ? (bucketCount-1) : 0;
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+CUtlHash<Data, C, K>::~CUtlHash()
+{
+ Purge();
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline bool CUtlHash<Data, C, K>::IsValidHandle( UtlHashHandle_t handle ) const
+{
+ int ndxBucket = GetBucketIndex( handle );
+ int ndxKeyData = GetKeyDataIndex( handle );
+
+ // ndxBucket and ndxKeyData can't possibly be less than zero -- take a
+ // look at the definition of the Get..Index functions for why. However,
+ // if you override those functions, you will need to override this one
+ // as well.
+ if( /*( ndxBucket >= 0 ) && */ ( ndxBucket < m_Buckets.Count() ) )
+ {
+ if( /*( ndxKeyData >= 0 ) && */ ( ndxKeyData < m_Buckets[ndxBucket].Count() ) )
+ return true;
+ }
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline int CUtlHash<Data, C, K>::Count( void ) const
+{
+ int count = 0;
+
+ int bucketCount = m_Buckets.Count();
+ for( int ndxBucket = 0; ndxBucket < bucketCount; ndxBucket++ )
+ {
+ count += m_Buckets[ndxBucket].Count();
+ }
+
+ return count;
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline int CUtlHash<Data, C, K>::GetBucketIndex( UtlHashHandle_t handle ) const
+{
+ return ( ( ( handle >> 16 ) & 0x0000ffff ) );
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline int CUtlHash<Data, C, K>::GetKeyDataIndex( UtlHashHandle_t handle ) const
+{
+ return ( handle & 0x0000ffff );
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline UtlHashHandle_t CUtlHash<Data, C, K>::BuildHandle( int ndxBucket, int ndxKeyData ) const
+{
+ Assert( ( ndxBucket >= 0 ) && ( ndxBucket < 65536 ) );
+ Assert( ( ndxKeyData >= 0 ) && ( ndxKeyData < 65536 ) );
+
+ UtlHashHandle_t handle = ndxKeyData;
+ handle |= ( ndxBucket << 16 );
+
+ return handle;
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline void CUtlHash<Data, C, K>::Purge( void )
+{
+ int bucketCount = m_Buckets.Count();
+ for( int ndxBucket = 0; ndxBucket < bucketCount; ndxBucket++ )
+ {
+ m_Buckets[ndxBucket].Purge();
+ }
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline bool CUtlHash<Data, C, K>::DoFind( Data const &src, unsigned int *pBucket, int *pIndex ) const
+{
+ // generate the data "key"
+ unsigned int key = m_KeyFunc( src );
+
+ // hash the "key" - get the correct hash table "bucket"
+ unsigned int ndxBucket;
+ if( m_bPowerOfTwo )
+ {
+ *pBucket = ndxBucket = ( key & m_ModMask );
+ }
+ else
+ {
+ int bucketCount = m_Buckets.Count();
+ *pBucket = ndxBucket = key % bucketCount;
+ }
+
+ int ndxKeyData = 0;
+ const CUtlVector<Data> &bucket = m_Buckets[ndxBucket];
+ int keyDataCount = bucket.Count();
+ for( ndxKeyData = 0; ndxKeyData < keyDataCount; ndxKeyData++ )
+ {
+ if( m_CompareFunc( bucket.Element( ndxKeyData ), src ) )
+ break;
+ }
+
+ if( ndxKeyData == keyDataCount )
+ return false;
+
+ *pIndex = ndxKeyData;
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline UtlHashHandle_t CUtlHash<Data, C, K>::Find( Data const &src ) const
+{
+ unsigned int ndxBucket;
+ int ndxKeyData = 0;
+
+ if ( DoFind( src, &ndxBucket, &ndxKeyData ) )
+ {
+ return ( BuildHandle( ndxBucket, ndxKeyData ) );
+ }
+ return ( InvalidHandle() );
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline UtlHashHandle_t CUtlHash<Data, C, K>::Insert( Data const &src )
+{
+ unsigned int ndxBucket;
+ int ndxKeyData = 0;
+
+ if ( DoFind( src, &ndxBucket, &ndxKeyData ) )
+ {
+ return ( BuildHandle( ndxBucket, ndxKeyData ) );
+ }
+
+ ndxKeyData = m_Buckets[ndxBucket].AddToTail( src );
+
+ return ( BuildHandle( ndxBucket, ndxKeyData ) );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline UtlHashHandle_t CUtlHash<Data, C, K>::Insert( Data const &src, bool *pDidInsert )
+{
+ unsigned int ndxBucket;
+ int ndxKeyData = 0;
+
+ if ( DoFind( src, &ndxBucket, &ndxKeyData ) )
+ {
+ *pDidInsert = false;
+ return ( BuildHandle( ndxBucket, ndxKeyData ) );
+ }
+
+ *pDidInsert = true;
+ ndxKeyData = m_Buckets[ndxBucket].AddToTail( src );
+
+ return ( BuildHandle( ndxBucket, ndxKeyData ) );
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline UtlHashHandle_t CUtlHash<Data, C, K>::AllocEntryFromKey( Data const &src )
+{
+ unsigned int ndxBucket;
+ int ndxKeyData = 0;
+
+ if ( DoFind( src, &ndxBucket, &ndxKeyData ) )
+ {
+ return ( BuildHandle( ndxBucket, ndxKeyData ) );
+ }
+
+ ndxKeyData = m_Buckets[ndxBucket].AddToTail();
+
+ return ( BuildHandle( ndxBucket, ndxKeyData ) );
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline void CUtlHash<Data, C, K>::Remove( UtlHashHandle_t handle )
+{
+ Assert( IsValidHandle( handle ) );
+
+ // check to see if the bucket exists
+ int ndxBucket = GetBucketIndex( handle );
+ int ndxKeyData = GetKeyDataIndex( handle );
+
+ if( m_Buckets[ndxBucket].IsValidIndex( ndxKeyData ) )
+ {
+ m_Buckets[ndxBucket].FastRemove( ndxKeyData );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline void CUtlHash<Data, C, K>::RemoveAll()
+{
+ int bucketCount = m_Buckets.Count();
+ for( int ndxBucket = 0; ndxBucket < bucketCount; ndxBucket++ )
+ {
+ m_Buckets[ndxBucket].RemoveAll();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline Data &CUtlHash<Data, C, K>::Element( UtlHashHandle_t handle )
+{
+ int ndxBucket = GetBucketIndex( handle );
+ int ndxKeyData = GetKeyDataIndex( handle );
+
+ return ( m_Buckets[ndxBucket].Element( ndxKeyData ) );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline Data const &CUtlHash<Data, C, K>::Element( UtlHashHandle_t handle ) const
+{
+ int ndxBucket = GetBucketIndex( handle );
+ int ndxKeyData = GetKeyDataIndex( handle );
+
+ return ( m_Buckets[ndxBucket].Element( ndxKeyData ) );
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline Data &CUtlHash<Data, C, K>::operator[]( UtlHashHandle_t handle )
+{
+ int ndxBucket = GetBucketIndex( handle );
+ int ndxKeyData = GetKeyDataIndex( handle );
+
+ return ( m_Buckets[ndxBucket].Element( ndxKeyData ) );
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline Data const &CUtlHash<Data, C, K>::operator[]( UtlHashHandle_t handle ) const
+{
+ int ndxBucket = GetBucketIndex( handle );
+ int ndxKeyData = GetKeyDataIndex( handle );
+
+ return ( m_Buckets[ndxBucket].Element( ndxKeyData ) );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline UtlHashHandle_t CUtlHash<Data, C, K>::GetFirstHandle() const
+{
+ return GetNextHandle( ( UtlHashHandle_t )-1 );
+}
+
+template<class Data, typename C, typename K>
+inline UtlHashHandle_t CUtlHash<Data, C, K>::GetNextHandle( UtlHashHandle_t handle ) const
+{
+ ++handle; // start at the first possible handle after the one given
+
+ int bi = GetBucketIndex( handle );
+ int ki = GetKeyDataIndex( handle );
+
+ int nBuckets = m_Buckets.Count();
+ for ( ; bi < nBuckets; ++bi )
+ {
+ if ( ki < m_Buckets[ bi ].Count() )
+ return BuildHandle( bi, ki );
+
+ ki = 0;
+ }
+
+ return InvalidHandle();
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline void CUtlHash<Data, C, K>::Log( const char *filename )
+{
+ FILE *pDebugFp;
+ pDebugFp = fopen( filename, "w" );
+ if( !pDebugFp )
+ return;
+
+ int maxBucketSize = 0;
+ int numBucketsEmpty = 0;
+
+ int bucketCount = m_Buckets.Count();
+ fprintf( pDebugFp, "\n%d Buckets\n", bucketCount );
+
+ for( int ndxBucket = 0; ndxBucket < bucketCount; ndxBucket++ )
+ {
+ int count = m_Buckets[ndxBucket].Count();
+
+ if( count > maxBucketSize ) { maxBucketSize = count; }
+ if( count == 0 )
+ numBucketsEmpty++;
+
+ fprintf( pDebugFp, "Bucket %d: %d\n", ndxBucket, count );
+ }
+
+ fprintf( pDebugFp, "\nBucketHeads Used: %d\n", bucketCount - numBucketsEmpty );
+ fprintf( pDebugFp, "Max Bucket Size: %d\n", maxBucketSize );
+
+ fclose( pDebugFp );
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline void CUtlHash<Data, C, K>::Dump( )
+{
+ int maxBucketSize = 0;
+ int numBucketsEmpty = 0;
+
+ int bucketCount = m_Buckets.Count();
+ Msg( "\n%d Buckets\n", bucketCount );
+
+ for( int ndxBucket = 0; ndxBucket < bucketCount; ndxBucket++ )
+ {
+ int count = m_Buckets[ndxBucket].Count();
+
+ if( count > maxBucketSize ) { maxBucketSize = count; }
+ if( count == 0 )
+ numBucketsEmpty++;
+
+ Msg( "Bucket %d: %d\n", ndxBucket, count );
+ }
+
+ Msg( "\nBucketHeads Used: %d\n", bucketCount - numBucketsEmpty );
+ Msg( "Max Bucket Size: %d\n", maxBucketSize );
+}
+
+//=============================================================================
+//
+// Fast Hash
+//
+// Number of buckets must be a power of 2.
+// Key must be 32-bits (unsigned int).
+//
+typedef int UtlHashFastHandle_t;
+
+#define UTLHASH_POOL_SCALAR 2
+
+class CUtlHashFastNoHash
+{
+public:
+ static int Hash( int key, int bucketMask )
+ {
+ return ( key & bucketMask );
+ }
+};
+
+class CUtlHashFastGenericHash
+{
+public:
+ static int Hash( int key, int bucketMask )
+ {
+ return ( HashIntConventional( key ) & bucketMask );
+ }
+};
+
+template<class Data, class HashFuncs = CUtlHashFastNoHash >
+class CUtlHashFast
+{
+public:
+
+ // Constructor/Deconstructor.
+ CUtlHashFast();
+ ~CUtlHashFast();
+
+ // Memory.
+ void Purge( void );
+
+ // Invalid handle.
+ static UtlHashFastHandle_t InvalidHandle( void ) { return ( UtlHashFastHandle_t )~0; }
+ inline bool IsValidHandle( UtlHashFastHandle_t hHash ) const;
+
+ // Initialize.
+ bool Init( int nBucketCount );
+
+ // Size not available; count is meaningless for multilists.
+ // int Count( void ) const;
+
+ // Insertion.
+ UtlHashFastHandle_t Insert( unsigned int uiKey, const Data &data );
+ UtlHashFastHandle_t FastInsert( unsigned int uiKey, const Data &data );
+
+ // Removal.
+ void Remove( UtlHashFastHandle_t hHash );
+ void RemoveAll( void );
+
+ // Retrieval.
+ UtlHashFastHandle_t Find( unsigned int uiKey ) const;
+
+ Data &Element( UtlHashFastHandle_t hHash );
+ Data const &Element( UtlHashFastHandle_t hHash ) const;
+ Data &operator[]( UtlHashFastHandle_t hHash );
+ Data const &operator[]( UtlHashFastHandle_t hHash ) const;
+
+ // Iteration
+ struct UtlHashFastIterator_t
+ {
+ int bucket;
+ UtlHashFastHandle_t handle;
+
+ UtlHashFastIterator_t(int _bucket, const UtlHashFastHandle_t &_handle)
+ : bucket(_bucket), handle(_handle) {};
+ // inline operator UtlHashFastHandle_t() const { return handle; };
+ };
+ inline UtlHashFastIterator_t First() const;
+ inline UtlHashFastIterator_t Next( const UtlHashFastIterator_t &hHash ) const;
+ inline bool IsValidIterator( const UtlHashFastIterator_t &iter ) const;
+ inline Data &operator[]( const UtlHashFastIterator_t &iter ) { return (*this)[iter.handle]; }
+ inline Data const &operator[]( const UtlHashFastIterator_t &iter ) const { return (*this)[iter.handle]; }
+
+//protected:
+
+ // Templatized for memory tracking purposes
+ template <typename HashData>
+ struct HashFastData_t_
+ {
+ unsigned int m_uiKey;
+ HashData m_Data;
+ };
+
+ typedef HashFastData_t_<Data> HashFastData_t;
+
+ unsigned int m_uiBucketMask;
+ CUtlVector<UtlHashFastHandle_t> m_aBuckets;
+ CUtlFixedLinkedList<HashFastData_t> m_aDataPool;
+
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> CUtlHashFast<Data,HashFuncs>::CUtlHashFast()
+{
+ Purge();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Deconstructor
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> CUtlHashFast<Data,HashFuncs>::~CUtlHashFast()
+{
+ Purge();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Destroy dynamically allocated hash data.
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> inline void CUtlHashFast<Data,HashFuncs>::Purge( void )
+{
+ m_aBuckets.Purge();
+ m_aDataPool.Purge();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Initialize the hash - set bucket count and hash grow amount.
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> bool CUtlHashFast<Data,HashFuncs>::Init( int nBucketCount )
+{
+ // Verify the bucket count is power of 2.
+ if ( !IsPowerOfTwo( nBucketCount ) )
+ return false;
+
+ // Set the bucket size.
+ m_aBuckets.SetSize( nBucketCount );
+ for ( int iBucket = 0; iBucket < nBucketCount; ++iBucket )
+ {
+ m_aBuckets[iBucket] = m_aDataPool.InvalidIndex();
+ }
+
+ // Set the mod mask.
+ m_uiBucketMask = nBucketCount - 1;
+
+ // Calculate the grow size.
+ int nGrowSize = UTLHASH_POOL_SCALAR * nBucketCount;
+ m_aDataPool.SetGrowSize( nGrowSize );
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Return the number of elements in the hash.
+// Not available because count isn't accurately maintained for multilists.
+//-----------------------------------------------------------------------------
+/*
+template<class Data, class HashFuncs> inline int CUtlHashFast<Data,HashFuncs>::Count( void ) const
+{
+ return m_aDataPool.Count();
+}
+*/
+
+//-----------------------------------------------------------------------------
+// Purpose: Insert data into the hash table given its key (unsigned int), with
+// a check to see if the element already exists within the tree.
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> inline UtlHashFastHandle_t CUtlHashFast<Data,HashFuncs>::Insert( unsigned int uiKey, const Data &data )
+{
+ // Check to see if that key already exists in the buckets (should be unique).
+ UtlHashFastHandle_t hHash = Find( uiKey );
+ if( hHash != InvalidHandle() )
+ return hHash;
+
+ return FastInsert( uiKey, data );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Insert data into the hash table given its key (unsigned int),
+// without a check to see if the element already exists within the tree.
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> inline UtlHashFastHandle_t CUtlHashFast<Data,HashFuncs>::FastInsert( unsigned int uiKey, const Data &data )
+{
+ // Get a new element from the pool.
+ int iHashData = m_aDataPool.Alloc( true );
+ HashFastData_t *pHashData = &m_aDataPool[iHashData];
+ if ( !pHashData )
+ return InvalidHandle();
+
+ // Add data to new element.
+ pHashData->m_uiKey = uiKey;
+ pHashData->m_Data = data;
+
+ // Link element.
+ int iBucket = HashFuncs::Hash( uiKey, m_uiBucketMask );
+ m_aDataPool.LinkBefore( m_aBuckets[iBucket], iHashData );
+ m_aBuckets[iBucket] = iHashData;
+
+ return iHashData;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Remove a given element from the hash.
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> inline void CUtlHashFast<Data,HashFuncs>::Remove( UtlHashFastHandle_t hHash )
+{
+ int iBucket = HashFuncs::Hash( m_aDataPool[hHash].m_uiKey, m_uiBucketMask );
+ if ( m_aBuckets[iBucket] == hHash )
+ {
+ // It is a bucket head.
+ m_aBuckets[iBucket] = m_aDataPool.Next( hHash );
+ }
+ else
+ {
+ // Not a bucket head.
+ m_aDataPool.Unlink( hHash );
+ }
+
+ // Remove the element.
+ m_aDataPool.Remove( hHash );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Remove all elements from the hash
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> inline void CUtlHashFast<Data,HashFuncs>::RemoveAll( void )
+{
+ m_aBuckets.RemoveAll();
+ m_aDataPool.RemoveAll();
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> inline UtlHashFastHandle_t CUtlHashFast<Data,HashFuncs>::Find( unsigned int uiKey ) const
+{
+ // hash the "key" - get the correct hash table "bucket"
+ int iBucket = HashFuncs::Hash( uiKey, m_uiBucketMask );
+
+ for ( int iElement = m_aBuckets[iBucket]; iElement != m_aDataPool.InvalidIndex(); iElement = m_aDataPool.Next( iElement ) )
+ {
+ if ( m_aDataPool[iElement].m_uiKey == uiKey )
+ return iElement;
+ }
+
+ return InvalidHandle();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return data given a hash handle.
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> inline Data &CUtlHashFast<Data,HashFuncs>::Element( UtlHashFastHandle_t hHash )
+{
+ return ( m_aDataPool[hHash].m_Data );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return data given a hash handle.
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> inline Data const &CUtlHashFast<Data,HashFuncs>::Element( UtlHashFastHandle_t hHash ) const
+{
+ return ( m_aDataPool[hHash].m_Data );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return data given a hash handle.
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> inline Data &CUtlHashFast<Data,HashFuncs>::operator[]( UtlHashFastHandle_t hHash )
+{
+ return ( m_aDataPool[hHash].m_Data );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return data given a hash handle.
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> inline Data const &CUtlHashFast<Data,HashFuncs>::operator[]( UtlHashFastHandle_t hHash ) const
+{
+ return ( m_aDataPool[hHash].m_Data );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: For iterating over the whole hash, return the index of the first element
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs>
+ typename CUtlHashFast<Data,HashFuncs>::UtlHashFastIterator_t
+ CUtlHashFast<Data,HashFuncs>::First() const
+{
+ // walk through the buckets to find the first one that has some data
+ int bucketCount = m_aBuckets.Count();
+ const UtlHashFastHandle_t invalidIndex = m_aDataPool.InvalidIndex();
+ for ( int bucket = 0 ; bucket < bucketCount ; ++bucket )
+ {
+ UtlHashFastHandle_t iElement = m_aBuckets[bucket]; // get the head of the bucket
+ if (iElement != invalidIndex)
+ return UtlHashFastIterator_t(bucket,iElement);
+ }
+
+ // if we are down here, the list is empty
+ return UtlHashFastIterator_t(-1, invalidIndex);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: For iterating over the whole hash, return the next element after
+// the param one. Or an invalid iterator.
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs>
+ typename CUtlHashFast<Data,HashFuncs>::UtlHashFastIterator_t
+ CUtlHashFast<Data,HashFuncs>::Next( const typename CUtlHashFast<Data,HashFuncs>::UtlHashFastIterator_t &iter ) const
+{
+ // look for the next entry in the current bucket
+ UtlHashFastHandle_t next = m_aDataPool.Next(iter.handle);
+ const UtlHashFastHandle_t invalidIndex = m_aDataPool.InvalidIndex();
+ if (next != invalidIndex)
+ {
+ // this bucket still has more elements in it
+ return UtlHashFastIterator_t(iter.bucket, next);
+ }
+
+ // otherwise look for the next bucket with data
+ int bucketCount = m_aBuckets.Count();
+ for ( int bucket = iter.bucket+1 ; bucket < bucketCount ; ++bucket )
+ {
+ UtlHashFastHandle_t next = m_aBuckets[bucket]; // get the head of the bucket
+ if (next != invalidIndex)
+ return UtlHashFastIterator_t( bucket, next );
+ }
+
+ // if we're here, there's no more data to be had
+ return UtlHashFastIterator_t(-1, invalidIndex);
+}
+
+template<class Data, class HashFuncs>
+ bool CUtlHashFast<Data,HashFuncs>::IsValidIterator( const typename CUtlHashFast::UtlHashFastIterator_t &iter ) const
+{
+ return ( (iter.bucket >= 0) && (m_aDataPool.IsValidIndex(iter.handle)) );
+}
+
+
+template<class Data, class HashFuncs> inline bool CUtlHashFast<Data,HashFuncs>::IsValidHandle( UtlHashFastHandle_t hHash ) const
+{
+ return m_aDataPool.IsValidIndex(hHash);
+}
+
+//=============================================================================
+//
+// Fixed Hash
+//
+// Number of buckets must be a power of 2.
+// Key must be 32-bits (unsigned int).
+//
+typedef int UtlHashFixedHandle_t;
+
+template <int NUM_BUCKETS>
+class CUtlHashFixedGenericHash
+{
+public:
+ static int Hash( int key, int bucketMask )
+ {
+ int hash = HashIntConventional( key );
+ if ( NUM_BUCKETS <= USHRT_MAX )
+ {
+ hash ^= ( hash >> 16 );
+ }
+ if ( NUM_BUCKETS <= UCHAR_MAX )
+ {
+ hash ^= ( hash >> 8 );
+ }
+ return ( hash & bucketMask );
+ }
+};
+
+template<class Data, int NUM_BUCKETS, class CHashFuncs = CUtlHashFastNoHash >
+class CUtlHashFixed
+{
+public:
+
+ // Constructor/Deconstructor.
+ CUtlHashFixed();
+ ~CUtlHashFixed();
+
+ // Memory.
+ void Purge( void );
+
+ // Invalid handle.
+ static UtlHashFixedHandle_t InvalidHandle( void ) { return ( UtlHashFixedHandle_t )~0; }
+
+ // Size.
+ int Count( void );
+
+ // Insertion.
+ UtlHashFixedHandle_t Insert( unsigned int uiKey, const Data &data );
+ UtlHashFixedHandle_t FastInsert( unsigned int uiKey, const Data &data );
+
+ // Removal.
+ void Remove( UtlHashFixedHandle_t hHash );
+ void RemoveAll( void );
+
+ // Retrieval.
+ UtlHashFixedHandle_t Find( unsigned int uiKey );
+
+ Data &Element( UtlHashFixedHandle_t hHash );
+ Data const &Element( UtlHashFixedHandle_t hHash ) const;
+ Data &operator[]( UtlHashFixedHandle_t hHash );
+ Data const &operator[]( UtlHashFixedHandle_t hHash ) const;
+
+ //protected:
+
+ // Templatized for memory tracking purposes
+ template <typename Data_t>
+ struct HashFixedData_t_
+ {
+ unsigned int m_uiKey;
+ Data_t m_Data;
+ };
+
+ typedef HashFixedData_t_<Data> HashFixedData_t;
+
+ enum
+ {
+ BUCKET_MASK = NUM_BUCKETS - 1
+ };
+ CUtlPtrLinkedList<HashFixedData_t> m_aBuckets[NUM_BUCKETS];
+ int m_nElements;
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::CUtlHashFixed()
+{
+ Purge();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Deconstructor
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::~CUtlHashFixed()
+{
+ Purge();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Destroy dynamically allocated hash data.
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline void CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::Purge( void )
+{
+ RemoveAll();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return the number of elements in the hash.
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline int CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::Count( void )
+{
+ return m_nElements;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Insert data into the hash table given its key (unsigned int), with
+// a check to see if the element already exists within the tree.
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline UtlHashFixedHandle_t CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::Insert( unsigned int uiKey, const Data &data )
+{
+ // Check to see if that key already exists in the buckets (should be unique).
+ UtlHashFixedHandle_t hHash = Find( uiKey );
+ if( hHash != InvalidHandle() )
+ return hHash;
+
+ return FastInsert( uiKey, data );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Insert data into the hash table given its key (unsigned int),
+// without a check to see if the element already exists within the tree.
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline UtlHashFixedHandle_t CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::FastInsert( unsigned int uiKey, const Data &data )
+{
+ int iBucket = HashFuncs::Hash( uiKey, NUM_BUCKETS - 1 );
+ UtlPtrLinkedListIndex_t iElem = m_aBuckets[iBucket].AddToHead();
+
+ HashFixedData_t *pHashData = &m_aBuckets[iBucket][iElem];
+
+ Assert( (UtlPtrLinkedListIndex_t)pHashData == iElem );
+
+ // Add data to new element.
+ pHashData->m_uiKey = uiKey;
+ pHashData->m_Data = data;
+
+ m_nElements++;
+ return (UtlHashFixedHandle_t)pHashData;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Remove a given element from the hash.
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline void CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::Remove( UtlHashFixedHandle_t hHash )
+{
+ HashFixedData_t *pHashData = (HashFixedData_t *)hHash;
+ Assert( Find(pHashData->m_uiKey) != InvalidHandle() );
+ int iBucket = HashFuncs::Hash( pHashData->m_uiKey, NUM_BUCKETS - 1 );
+ m_aBuckets[iBucket].Remove( (UtlPtrLinkedListIndex_t)pHashData );
+ m_nElements--;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Remove all elements from the hash
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline void CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::RemoveAll( void )
+{
+ for ( int i = 0; i < NUM_BUCKETS; i++ )
+ {
+ m_aBuckets[i].RemoveAll();
+ }
+ m_nElements = 0;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline UtlHashFixedHandle_t CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::Find( unsigned int uiKey )
+{
+ int iBucket = HashFuncs::Hash( uiKey, NUM_BUCKETS - 1 );
+ CUtlPtrLinkedList<HashFixedData_t> &bucket = m_aBuckets[iBucket];
+
+ for ( UtlPtrLinkedListIndex_t iElement = bucket.Head(); iElement != bucket.InvalidIndex(); iElement = bucket.Next( iElement ) )
+ {
+ if ( bucket[iElement].m_uiKey == uiKey )
+ return (UtlHashFixedHandle_t)iElement;
+ }
+
+ return InvalidHandle();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return data given a hash handle.
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline Data &CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::Element( UtlHashFixedHandle_t hHash )
+{
+ return ((HashFixedData_t *)hHash)->m_Data;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return data given a hash handle.
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline Data const &CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::Element( UtlHashFixedHandle_t hHash ) const
+{
+ return ((HashFixedData_t *)hHash)->m_Data;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return data given a hash handle.
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline Data &CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::operator[]( UtlHashFixedHandle_t hHash )
+{
+ return ((HashFixedData_t *)hHash)->m_Data;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return data given a hash handle.
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline Data const &CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::operator[]( UtlHashFixedHandle_t hHash ) const
+{
+ return ((HashFixedData_t *)hHash)->m_Data;
+}
+
+class CDefaultHash32
+{
+public:
+ static inline uint32 HashKey32( uint32 nKey ) { return HashIntConventional(nKey); }
+};
+
+class CPassthroughHash32
+{
+public:
+ static inline uint32 HashKey32( uint32 nKey ) { return nKey; }
+};
+
+
+// This is a simpler hash for scalar types that stores the entire hash + buckets in a single linear array
+// This is much more cache friendly for small (e.g. 32-bit) types stored in the hash
+template<class Data, class CHashFunction = CDefaultHash32>
+class CUtlScalarHash
+{
+public:
+
+ // Constructor/Destructor.
+ CUtlScalarHash();
+ ~CUtlScalarHash();
+
+ // Memory.
+ // void Purge( void );
+
+ // Invalid handle.
+ static const UtlHashFastHandle_t InvalidHandle( void ) { return (unsigned int)~0; }
+
+ // Initialize.
+ bool Init( int nBucketCount );
+
+ // Size.
+ int Count( void ) const { return m_dataCount; }
+
+ // Insertion.
+ UtlHashFastHandle_t Insert( unsigned int uiKey, const Data &data );
+
+ // Removal.
+ void FindAndRemove( unsigned int uiKey, const Data &dataRecord );
+ void Remove( UtlHashFastHandle_t hHash );
+ void RemoveAll( void );
+ void Grow();
+
+ // Retrieval. Finds by uiKey and then by comparing dataRecord
+ UtlHashFastHandle_t Find( unsigned int uiKey, const Data &dataRecord ) const;
+ UtlHashFastHandle_t FindByUniqueKey( unsigned int uiKey ) const;
+
+ Data &Element( UtlHashFastHandle_t hHash ) { Assert(unsigned(hHash)<=m_uiBucketMask); return m_pData[hHash].m_Data; }
+ Data const &Element( UtlHashFastHandle_t hHash ) const { Assert(unsigned(hHash)<=m_uiBucketMask); return m_pData[hHash].m_Data; }
+ Data &operator[]( UtlHashFastHandle_t hHash ) { Assert(unsigned(hHash)<=m_uiBucketMask); return m_pData[hHash].m_Data; }
+ Data const &operator[]( UtlHashFastHandle_t hHash ) const { Assert(unsigned(hHash)<=m_uiBucketMask); return m_pData[hHash].m_Data; }
+
+ unsigned int Key( UtlHashFastHandle_t hHash ) const { Assert(unsigned(hHash)<=m_uiBucketMask); return m_pData[hHash].m_uiKey; }
+
+ UtlHashFastHandle_t FirstInorder() const
+ {
+ return NextInorder(-1);
+ }
+ UtlHashFastHandle_t NextInorder( UtlHashFastHandle_t nStart ) const
+ {
+ int nElementCount = m_maxData * 2;
+ unsigned int nUnusedListElement = (unsigned int)InvalidHandle();
+ for ( int i = nStart+1; i < nElementCount; i++ )
+ {
+ if ( m_pData[i].m_uiKey != nUnusedListElement )
+ return i;
+ }
+ return nUnusedListElement;
+ }
+
+ //protected:
+
+ struct HashScalarData_t
+ {
+ unsigned int m_uiKey;
+ Data m_Data;
+ };
+
+ unsigned int m_uiBucketMask;
+ HashScalarData_t *m_pData;
+ int m_maxData;
+ int m_dataCount;
+};
+
+template<class Data, class CHashFunction> CUtlScalarHash<Data, CHashFunction>::CUtlScalarHash()
+{
+ m_pData = NULL;
+ m_uiBucketMask = 0;
+ m_maxData = 0;
+ m_dataCount = 0;
+}
+
+template<class Data, class CHashFunction> CUtlScalarHash<Data, CHashFunction>::~CUtlScalarHash()
+{
+ delete[] m_pData;
+}
+
+template<class Data, class CHashFunction> bool CUtlScalarHash<Data, CHashFunction>::Init( int nBucketCount )
+{
+ Assert(m_dataCount==0);
+ m_maxData = SmallestPowerOfTwoGreaterOrEqual(nBucketCount);
+ int elementCount = m_maxData * 2;
+ m_pData = new HashScalarData_t[elementCount];
+ m_uiBucketMask = elementCount - 1;
+ RemoveAll();
+ return true;
+}
+
+template<class Data, class CHashFunction> void CUtlScalarHash<Data, CHashFunction>::Grow()
+{
+ ASSERT_NO_REENTRY();
+ int oldElementCount = m_maxData * 2;
+ HashScalarData_t *pOldData = m_pData;
+
+ // Grow to a minimum size of 16
+ m_maxData = MAX( oldElementCount, 16 );
+ int elementCount = m_maxData * 2;
+ m_pData = new HashScalarData_t[elementCount];
+ m_uiBucketMask = elementCount-1;
+ m_dataCount = 0;
+ for ( int i = 0; i < elementCount; i++ )
+ {
+ m_pData[i].m_uiKey = InvalidHandle();
+ }
+ for ( int i = 0; i < oldElementCount; i++ )
+ {
+ if ( pOldData[i].m_uiKey != (unsigned)InvalidHandle() )
+ {
+ Insert( pOldData[i].m_uiKey, pOldData[i].m_Data );
+ }
+ }
+ delete[] pOldData;
+}
+
+template<class Data, class CHashFunction> UtlHashFastHandle_t CUtlScalarHash<Data, CHashFunction>::Insert( unsigned int uiKey, const Data &data )
+{
+ if ( m_dataCount >= m_maxData )
+ {
+ Grow();
+ }
+ m_dataCount++;
+ Assert(uiKey != (uint)InvalidHandle()); // This hash stores less data by assuming uiKey != ~0
+ int index = CHashFunction::HashKey32(uiKey) & m_uiBucketMask;
+ unsigned int endOfList = (unsigned int)InvalidHandle();
+ while ( m_pData[index].m_uiKey != endOfList )
+ {
+ index = (index+1) & m_uiBucketMask;
+ }
+ m_pData[index].m_uiKey = uiKey;
+ m_pData[index].m_Data = data;
+
+ return index;
+}
+
+// Removal.
+template<class Data, class CHashFunction> void CUtlScalarHash<Data, CHashFunction>::Remove( UtlHashFastHandle_t hHash )
+{
+ int mid = (m_uiBucketMask+1) / 2;
+ int lastRemoveIndex = hHash;
+ // remove the item
+ m_pData[lastRemoveIndex].m_uiKey = InvalidHandle();
+ m_dataCount--;
+
+ // now search for any items needing to be swapped down
+ unsigned int endOfList = (unsigned int)InvalidHandle();
+ for ( int index = (hHash+1) & m_uiBucketMask; m_pData[index].m_uiKey != endOfList; index = (index+1) & m_uiBucketMask )
+ {
+ int ideal = CHashFunction::HashKey32(m_pData[index].m_uiKey) & m_uiBucketMask;
+
+ // is the ideal index for this element <= (in a wrapped buffer sense) the ideal index of the removed element?
+ // if so, swap
+ int diff = ideal - lastRemoveIndex;
+ if ( diff > mid )
+ {
+ diff -= (m_uiBucketMask+1);
+ }
+ if ( diff < -mid )
+ {
+ diff += (m_uiBucketMask+1);
+ }
+
+ // should I swap this?
+ if ( diff <= 0 )
+ {
+ m_pData[lastRemoveIndex] = m_pData[index];
+ lastRemoveIndex = index;
+ m_pData[index].m_uiKey = InvalidHandle();
+ }
+ }
+}
+
+template<class Data, class CHashFunction> void CUtlScalarHash<Data, CHashFunction>::FindAndRemove( unsigned int uiKey, const Data &dataRecord )
+{
+ int index = CHashFunction::HashKey32(uiKey) & m_uiBucketMask;
+ unsigned int endOfList = (unsigned int)InvalidHandle();
+ while ( m_pData[index].m_uiKey != endOfList )
+ {
+ if ( m_pData[index].m_uiKey == uiKey && m_pData[index].m_Data == dataRecord )
+ {
+ Remove(index);
+ return;
+ }
+ index = (index+1) & m_uiBucketMask;
+ }
+}
+
+template<class Data, class CHashFunction> void CUtlScalarHash<Data, CHashFunction>::RemoveAll( void )
+{
+ int elementCount = m_maxData * 2;
+ for ( int i = 0; i < elementCount; i++ )
+ {
+ m_pData[i].m_uiKey = (unsigned)InvalidHandle();
+ }
+ m_dataCount = 0;
+}
+
+// Retrieval.
+template<class Data, class CHashFunction> UtlHashFastHandle_t CUtlScalarHash<Data, CHashFunction>::Find( unsigned int uiKey, const Data &dataRecord ) const
+{
+ if ( m_pData == NULL )
+ return InvalidHandle();
+ int index = CHashFunction::HashKey32(uiKey) & m_uiBucketMask;
+ unsigned int endOfList = (unsigned int)InvalidHandle();
+ while ( m_pData[index].m_uiKey != endOfList )
+ {
+ if ( m_pData[index].m_uiKey == uiKey && m_pData[index].m_Data == dataRecord )
+ return index;
+ index = (index+1) & m_uiBucketMask;
+ }
+ return InvalidHandle();
+}
+
+template<class Data, class CHashFunction> UtlHashFastHandle_t CUtlScalarHash<Data, CHashFunction>::FindByUniqueKey( unsigned int uiKey ) const
+{
+ if ( m_pData == NULL )
+ return InvalidHandle();
+ int index = CHashFunction::HashKey32(uiKey) & m_uiBucketMask;
+ unsigned int endOfList = (unsigned int)InvalidHandle();
+ while ( m_pData[index].m_uiKey != endOfList )
+ {
+ if ( m_pData[index].m_uiKey == uiKey )
+ return index;
+ index = (index+1) & m_uiBucketMask;
+ }
+ return InvalidHandle();
+}
+
+
+#endif // UTLHASH_H
diff --git a/external/vpc/public/tier1/utllinkedlist.h b/external/vpc/public/tier1/utllinkedlist.h
new file mode 100644
index 0000000..fcd5ba9
--- /dev/null
+++ b/external/vpc/public/tier1/utllinkedlist.h
@@ -0,0 +1,1087 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Linked list container class
+//
+// $Revision: $
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef UTLLINKEDLIST_H
+#define UTLLINKEDLIST_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/basetypes.h"
+#include "utlmemory.h"
+#include "utlfixedmemory.h"
+#include "utlblockmemory.h"
+#include "tier0/dbg.h"
+
+// define to enable asserts griping about things you shouldn't be doing with multilists
+// #define MULTILIST_PEDANTIC_ASSERTS 1
+
+// This is a useful macro to iterate from head to tail in a linked list.
+#define FOR_EACH_LL( listName, iteratorName ) \
+ for( int iteratorName=listName.Head(); iteratorName != listName.InvalidIndex(); iteratorName = listName.Next( iteratorName ) )
+
+//-----------------------------------------------------------------------------
+// class CUtlLinkedList:
+// 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. However,
+// you must avoid using 16- or 8-bit arithmetic on PowerPC architectures;
+// therefore you should not use UtlLinkedListElem_t::I as the type of
+// a local variable... ever. PowerPC integer arithmetic must be 32- or
+// 64-bit only; otherwise performance plummets.
+//-----------------------------------------------------------------------------
+
+template <class T, class I>
+struct UtlLinkedListElem_t
+{
+ T m_Element;
+ I m_Previous;
+ I m_Next;
+
+private:
+ // No copy constructor for these...
+ UtlLinkedListElem_t( const UtlLinkedListElem_t& );
+};
+
+
+// Class S is the storage type; the type you can use to save off indices in
+// persistent memory. Class I is the iterator type, which is what should be used
+// in local scopes. I defaults to be S, but be aware that on the 360, 16-bit
+// arithmetic is catastrophically slow. Therefore you should try to save shorts
+// in memory, but always operate on 32's or 64's in local scope.
+// The ideal parameter order would be TSMI (you are more likely to override M than I)
+// but since M depends on I we can't have the defaults in that order, alas.
+template <class T, class S = unsigned short, bool ML = false, class I = S, class M = CUtlMemory< UtlLinkedListElem_t<T, S>, I > >
+class CUtlLinkedList
+{
+public:
+ typedef T ElemType_t;
+ typedef S IndexType_t; // should really be called IndexStorageType_t, but that would be a huge change
+ typedef I IndexLocalType_t;
+ typedef M MemoryAllocator_t;
+
+ // constructor, destructor
+ CUtlLinkedList( int growSize = 0, int initSize = 0 );
+ ~CUtlLinkedList();
+
+ // 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 );
+
+ void SetGrowSize( int growSize );
+
+ // Memory deallocation
+ void Purge();
+
+ // Delete all the elements then call Purge.
+ void PurgeAndDeleteElements();
+
+ // Insertion methods....
+ I InsertBefore( I before );
+ I InsertAfter( I after );
+ I AddToHead( );
+ I AddToTail( );
+
+ I InsertBefore( I before, T const& src );
+ I InsertAfter( I after, T const& src );
+ I AddToHead( T const& src );
+ I AddToTail( T const& src );
+
+ // Find an element and return its index or InvalidIndex() if it couldn't be found.
+ I Find( const T &src ) const;
+
+ // Look for the element. If it exists, remove it and return true. Otherwise, return false.
+ bool FindAndRemove( const T &src );
+
+ // Removal methods
+ void Remove( I elem );
+ void RemoveAll();
+
+ // Allocation/deallocation methods
+ // If multilist == true, then list list may contain many
+ // non-connected lists, and IsInList and Head + Tail are meaningless...
+ I Alloc( bool multilist = false );
+ void Free( I elem );
+
+ // Identify the owner of this linked list's memory:
+ void SetAllocOwner( const char *pszAllocOwner );
+
+ // list modification
+ void LinkBefore( I before, I elem );
+ void LinkAfter( I after, I elem );
+ void Unlink( I elem );
+ void LinkToHead( I elem );
+ void LinkToTail( I elem );
+
+ // invalid index (M will never allocate an element at this index)
+ inline static S InvalidIndex() { return ( S )M::InvalidIndex(); }
+
+ // Is a given index valid to use? (representible by S and not the invalid index)
+ static bool IndexInRange( I index );
+
+ inline static size_t ElementSize() { return sizeof( ListElem_t ); }
+
+ // list statistics
+ int Count() const;
+ I MaxElementIndex() const;
+ I NumAllocated( void ) const { return m_NumAlloced; }
+
+ // Traversing the list
+ I Head() const;
+ I Tail() const;
+ I Previous( I i ) const;
+ I Next( I i ) const;
+
+ // Are nodes in the list or valid?
+ bool IsValidIndex( I i ) const;
+ bool IsInList( I i ) const;
+
+protected:
+
+ // What the linked list element looks like
+ typedef UtlLinkedListElem_t<T, S> ListElem_t;
+
+ // constructs the class
+ I AllocInternal( bool multilist = false );
+ 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]; }
+
+ // copy constructors not allowed
+ CUtlLinkedList( CUtlLinkedList<T, S, ML, I, M> const& list ) { Assert(0); }
+
+ M m_Memory;
+ I m_Head;
+ I m_Tail;
+ I m_FirstFree;
+ I m_ElementCount; // The number actually in the list
+ I m_NumAlloced; // The number of allocated elements
+ typename M::Iterator_t m_LastAlloc; // the last index allocated
+
+ // For debugging purposes;
+ // it's in release builds so this can be used in libraries correctly
+ ListElem_t *m_pElements;
+
+ FORCEINLINE M const &Memory( void ) const
+ {
+ return m_Memory;
+ }
+
+ void ResetDbgInfo()
+ {
+ m_pElements = m_Memory.Base();
+ }
+};
+
+
+// this is kind of ugly, but until C++ gets templatized typedefs in C++0x, it's our only choice
+template < class T >
+class CUtlFixedLinkedList : public CUtlLinkedList< T, intp, true, intp, CUtlFixedMemory< UtlLinkedListElem_t< T, intp > > >
+{
+public:
+ CUtlFixedLinkedList( int growSize = 0, int initSize = 0 )
+ : CUtlLinkedList< T, intp, true, intp, CUtlFixedMemory< UtlLinkedListElem_t< T, intp > > >( growSize, initSize ) {}
+
+ bool IsValidIndex( intp i ) const
+ {
+ if ( !this->Memory().IsIdxValid( i ) )
+ return false;
+
+#ifdef _DEBUG // it's safe to skip this here, since the only way to get indices after m_LastAlloc is to use MaxElementIndex
+ if ( this->Memory().IsIdxAfter( i, this->m_LastAlloc ) )
+ {
+ Assert( 0 );
+ return false; // don't read values that have been allocated, but not constructed
+ }
+#endif
+
+ return ( this->Memory()[ i ].m_Previous != i ) || ( this->Memory()[ i ].m_Next == i );
+ }
+
+private:
+ int MaxElementIndex() const { Assert( 0 ); return this->InvalidIndex(); } // fixedmemory containers don't support iteration from 0..maxelements-1
+ void ResetDbgInfo() {}
+};
+
+// this is kind of ugly, but until C++ gets templatized typedefs in C++0x, it's our only choice
+template < class T, class I = unsigned short >
+class CUtlBlockLinkedList : public CUtlLinkedList< T, I, true, I, CUtlBlockMemory< UtlLinkedListElem_t< T, I >, I > >
+{
+public:
+ CUtlBlockLinkedList( int growSize = 0, int initSize = 0 )
+ : CUtlLinkedList< T, I, true, I, CUtlBlockMemory< UtlLinkedListElem_t< T, I >, I > >( growSize, initSize ) {}
+protected:
+ void ResetDbgInfo() {}
+};
+
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+
+template <class T, class S, bool ML, class I, class M>
+CUtlLinkedList<T,S,ML,I,M>::CUtlLinkedList( int growSize, int initSize ) :
+ m_Memory( growSize, initSize ), m_LastAlloc( m_Memory.InvalidIterator() )
+{
+ // Prevent signed non-int datatypes
+ COMPILE_TIME_ASSERT( sizeof(S) == 4 || ( ( (S)-1 ) > 0 ) );
+ ConstructList();
+ ResetDbgInfo();
+}
+
+template <class T, class S, bool ML, class I, class M>
+CUtlLinkedList<T,S,ML,I,M>::~CUtlLinkedList( )
+{
+ RemoveAll();
+}
+
+template <class T, class S, bool ML, class I, class M>
+void CUtlLinkedList<T,S,ML,I,M>::ConstructList()
+{
+ m_Head = InvalidIndex();
+ m_Tail = InvalidIndex();
+ m_FirstFree = InvalidIndex();
+ m_ElementCount = 0;
+ m_NumAlloced = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// gets particular elements
+//-----------------------------------------------------------------------------
+
+template <class T, class S, bool ML, class I, class M>
+inline T& CUtlLinkedList<T,S,ML,I,M>::Element( I i )
+{
+ return m_Memory[i].m_Element;
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline T const& CUtlLinkedList<T,S,ML,I,M>::Element( I i ) const
+{
+ return m_Memory[i].m_Element;
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline T& CUtlLinkedList<T,S,ML,I,M>::operator[]( I i )
+{
+ return m_Memory[i].m_Element;
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline T const& CUtlLinkedList<T,S,ML,I,M>::operator[]( I i ) const
+{
+ return m_Memory[i].m_Element;
+}
+
+//-----------------------------------------------------------------------------
+// list statistics
+//-----------------------------------------------------------------------------
+
+template <class T, class S, bool ML, class I, class M>
+inline int CUtlLinkedList<T,S,ML,I,M>::Count() const
+{
+#ifdef MULTILIST_PEDANTIC_ASSERTS
+ AssertMsg( !ML, "CUtlLinkedList::Count() is meaningless for linked lists." );
+#endif
+ return m_ElementCount;
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline I CUtlLinkedList<T,S,ML,I,M>::MaxElementIndex() const
+{
+ return m_Memory.NumAllocated();
+}
+
+
+//-----------------------------------------------------------------------------
+// Traversing the list
+//-----------------------------------------------------------------------------
+
+template <class T, class S, bool ML, class I, class M>
+inline I CUtlLinkedList<T,S,ML,I,M>::Head() const
+{
+ return m_Head;
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline I CUtlLinkedList<T,S,ML,I,M>::Tail() const
+{
+ return m_Tail;
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline I CUtlLinkedList<T,S,ML,I,M>::Previous( I i ) const
+{
+ Assert( IsValidIndex(i) );
+ return InternalElement(i).m_Previous;
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline I CUtlLinkedList<T,S,ML,I,M>::Next( I i ) const
+{
+ Assert( IsValidIndex(i) );
+ return InternalElement(i).m_Next;
+}
+
+
+//-----------------------------------------------------------------------------
+// Are nodes in the list or valid?
+//-----------------------------------------------------------------------------
+
+#pragma warning(push)
+#pragma warning( disable: 4310 ) // Allows "(I)(S)M::INVALID_INDEX" below
+template <class T, class S, bool ML, class I, class M>
+inline bool CUtlLinkedList<T,S,ML,I,M>::IndexInRange( I index ) // Static method
+{
+ // Since S is not necessarily the type returned by M, we need to check that M returns indices
+ // which are representable by S. A common case is 'S === unsigned short', 'I == int', in which
+ // case CUtlMemory will have 'InvalidIndex == (int)-1' (which casts to 65535 in S), and will
+ // happily return elements at index 65535 and above.
+
+ // Do some static checks here:
+ // 'I' needs to be able to store 'S'
+ COMPILE_TIME_ASSERT( sizeof(I) >= sizeof(S) );
+ // 'S' should be unsigned (to avoid signed arithmetic errors for plausibly exhaustible ranges)
+ COMPILE_TIME_ASSERT( ( sizeof(S) > 2 ) || ( ( (S)-1 ) > 0 ) );
+ // M::INVALID_INDEX should be storable in S to avoid ambiguities (e.g. with 65536)
+ COMPILE_TIME_ASSERT( ( M::INVALID_INDEX == -1 ) || ( M::INVALID_INDEX == (S)M::INVALID_INDEX ) );
+
+ return ( ( (S)index == index ) && ( (S)index != InvalidIndex() ) );
+}
+#pragma warning(pop)
+
+template <class T, class S, bool ML, class I, class M>
+inline bool CUtlLinkedList<T,S,ML,I,M>::IsValidIndex( I i ) const
+{
+ if ( !m_Memory.IsIdxValid( i ) )
+ return false;
+
+ if ( m_Memory.IsIdxAfter( i, m_LastAlloc ) )
+ return false; // don't read values that have been allocated, but not constructed
+
+ return ( m_Memory[ i ].m_Previous != i ) || ( m_Memory[ i ].m_Next == i );
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline bool CUtlLinkedList<T,S,ML,I,M>::IsInList( I i ) const
+{
+ if ( !m_Memory.IsIdxValid( i ) || m_Memory.IsIdxAfter( i, m_LastAlloc ) )
+ return false; // don't read values that have been allocated, but not constructed
+
+ return Previous( i ) != i;
+}
+
+/*
+template <class T>
+inline bool CUtlFixedLinkedList<T>::IsInList( int i ) const
+{
+ return m_Memory.IsIdxValid( i ) && (Previous( i ) != i);
+}
+*/
+
+//-----------------------------------------------------------------------------
+// Makes sure we have enough memory allocated to store a requested # of elements
+//-----------------------------------------------------------------------------
+
+template< class T, class S, bool ML, class I, class M >
+void CUtlLinkedList<T,S,ML,I,M>::EnsureCapacity( int num )
+{
+ MEM_ALLOC_CREDIT_CLASS();
+ m_Memory.EnsureCapacity(num);
+ ResetDbgInfo();
+}
+
+template< class T, class S, bool ML, class I, class M >
+void CUtlLinkedList<T,S,ML,I,M>::SetGrowSize( int growSize )
+{
+ RemoveAll();
+ m_Memory.Init( growSize );
+ ResetDbgInfo();
+}
+
+template< class T, class S, bool ML, class I, class M >
+void CUtlLinkedList<T,S,ML,I,M>::SetAllocOwner( const char *pszAllocOwner )
+{
+ m_Memory.SetAllocOwner( pszAllocOwner );
+}
+
+
+//-----------------------------------------------------------------------------
+// Deallocate memory
+//-----------------------------------------------------------------------------
+
+template <class T, class S, bool ML, class I, class M>
+void CUtlLinkedList<T,S,ML,I,M>::Purge()
+{
+ RemoveAll();
+
+ m_Memory.Purge();
+ m_FirstFree = InvalidIndex();
+ m_NumAlloced = 0;
+
+ //Routing "m_LastAlloc = m_Memory.InvalidIterator();" through a local const to sidestep an internal compiler error on 360 builds
+ const typename M::Iterator_t scInvalidIterator = m_Memory.InvalidIterator();
+ m_LastAlloc = scInvalidIterator;
+ ResetDbgInfo();
+}
+
+
+template<class T, class S, bool ML, class I, class M>
+void CUtlLinkedList<T,S,ML,I,M>::PurgeAndDeleteElements()
+{
+ I iNext;
+ for( I i=Head(); i != InvalidIndex(); i=iNext )
+ {
+ iNext = Next(i);
+ delete Element(i);
+ }
+
+ Purge();
+}
+
+
+//-----------------------------------------------------------------------------
+// Node allocation/deallocation
+//-----------------------------------------------------------------------------
+template <class T, class S, bool ML, class I, class M>
+I CUtlLinkedList<T,S,ML,I,M>::AllocInternal( bool multilist )
+{
+ Assert( !multilist || ML );
+#ifdef MULTILIST_PEDANTIC_ASSERTS
+ Assert( multilist == ML );
+#endif
+ I elem;
+ if ( m_FirstFree == InvalidIndex() )
+ {
+ Assert( m_Memory.IsValidIterator( m_LastAlloc ) || m_ElementCount == 0 );
+
+ typename M::Iterator_t it = m_Memory.IsValidIterator( m_LastAlloc ) ? m_Memory.Next( m_LastAlloc ) : m_Memory.First();
+
+ if ( !m_Memory.IsValidIterator( it ) )
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ m_Memory.Grow();
+ ResetDbgInfo();
+
+ it = m_Memory.IsValidIterator( m_LastAlloc ) ? m_Memory.Next( m_LastAlloc ) : m_Memory.First();
+
+ Assert( m_Memory.IsValidIterator( it ) );
+ if ( !m_Memory.IsValidIterator( it ) )
+ {
+ ExecuteNTimes( 10, Warning( "CUtlLinkedList overflow! (exhausted memory allocator)\n" ) );
+ return InvalidIndex();
+ }
+ }
+
+ // We can overflow before the utlmemory overflows, since S != I
+ if ( !IndexInRange( m_Memory.GetIndex( it ) ) )
+ {
+ ExecuteNTimes( 10, Warning( "CUtlLinkedList overflow! (exhausted index range)\n" ) );
+ return InvalidIndex();
+ }
+
+ m_LastAlloc = it;
+ elem = m_Memory.GetIndex( m_LastAlloc );
+ m_NumAlloced++;
+ }
+ else
+ {
+ elem = m_FirstFree;
+ m_FirstFree = InternalElement( m_FirstFree ).m_Next;
+ }
+
+ if ( !multilist )
+ {
+ InternalElement( elem ).m_Next = elem;
+ InternalElement( elem ).m_Previous = elem;
+ }
+ else
+ {
+ InternalElement( elem ).m_Next = InvalidIndex();
+ InternalElement( elem ).m_Previous = InvalidIndex();
+ }
+
+ return elem;
+}
+
+template <class T, class S, bool ML, class I, class M>
+I CUtlLinkedList<T,S,ML,I,M>::Alloc( bool multilist )
+{
+ I elem = AllocInternal( multilist );
+ if ( elem == InvalidIndex() )
+ return elem;
+
+ Construct( &Element(elem) );
+
+ return elem;
+}
+
+template <class T, class S, bool ML, class I, class M>
+void CUtlLinkedList<T,S,ML,I,M>::Free( I elem )
+{
+ Assert( IsValidIndex(elem) && IndexInRange( elem ) );
+ Unlink(elem);
+
+ ListElem_t &internalElem = InternalElement(elem);
+ Destruct( &internalElem.m_Element );
+ internalElem.m_Next = m_FirstFree;
+ m_FirstFree = elem;
+}
+
+//-----------------------------------------------------------------------------
+// Insertion methods; allocates and links (uses default constructor)
+//-----------------------------------------------------------------------------
+
+template <class T, class S, bool ML, class I, class M>
+I CUtlLinkedList<T,S,ML,I,M>::InsertBefore( I before )
+{
+ // Make a new node
+ I newNode = AllocInternal();
+ if ( newNode == InvalidIndex() )
+ return newNode;
+
+ // Link it in
+ LinkBefore( before, newNode );
+
+ // Construct the data
+ Construct( &Element(newNode) );
+
+ return newNode;
+}
+
+template <class T, class S, bool ML, class I, class M>
+I CUtlLinkedList<T,S,ML,I,M>::InsertAfter( I after )
+{
+ // Make a new node
+ I newNode = AllocInternal();
+ if ( newNode == InvalidIndex() )
+ return newNode;
+
+ // Link it in
+ LinkAfter( after, newNode );
+
+ // Construct the data
+ Construct( &Element(newNode) );
+
+ return newNode;
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline I CUtlLinkedList<T,S,ML,I,M>::AddToHead( )
+{
+ return InsertAfter( InvalidIndex() );
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline I CUtlLinkedList<T,S,ML,I,M>::AddToTail( )
+{
+ return InsertBefore( InvalidIndex() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Insertion methods; allocates and links (uses copy constructor)
+//-----------------------------------------------------------------------------
+
+template <class T, class S, bool ML, class I, class M>
+I CUtlLinkedList<T,S,ML,I,M>::InsertBefore( I before, T const& src )
+{
+ // Make a new node
+ I newNode = AllocInternal();
+ if ( newNode == InvalidIndex() )
+ return newNode;
+
+ // Link it in
+ LinkBefore( before, newNode );
+
+ // Construct the data
+ CopyConstruct( &Element(newNode), src );
+
+ return newNode;
+}
+
+template <class T, class S, bool ML, class I, class M>
+I CUtlLinkedList<T,S,ML,I,M>::InsertAfter( I after, T const& src )
+{
+ // Make a new node
+ I newNode = AllocInternal();
+ if ( newNode == InvalidIndex() )
+ return newNode;
+
+ // Link it in
+ LinkAfter( after, newNode );
+
+ // Construct the data
+ CopyConstruct( &Element(newNode), src );
+
+ return newNode;
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline I CUtlLinkedList<T,S,ML,I,M>::AddToHead( T const& src )
+{
+ return InsertAfter( InvalidIndex(), src );
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline I CUtlLinkedList<T,S,ML,I,M>::AddToTail( T const& src )
+{
+ return InsertBefore( InvalidIndex(), src );
+}
+
+
+//-----------------------------------------------------------------------------
+// Removal methods
+//-----------------------------------------------------------------------------
+
+template<class T, class S, bool ML, class I, class M>
+I CUtlLinkedList<T,S,ML,I,M>::Find( const T &src ) const
+{
+ for ( I i=Head(); i != InvalidIndex(); i = Next( i ) )
+ {
+ if ( Element( i ) == src )
+ return i;
+ }
+ return InvalidIndex();
+}
+
+
+template<class T, class S, bool ML, class I, class M>
+bool CUtlLinkedList<T,S,ML,I,M>::FindAndRemove( const T &src )
+{
+ I i = Find( src );
+ if ( i == InvalidIndex() )
+ {
+ return false;
+ }
+ else
+ {
+ Remove( i );
+ return true;
+ }
+}
+
+
+template <class T, class S, bool ML, class I, class M>
+void CUtlLinkedList<T,S,ML,I,M>::Remove( I elem )
+{
+ Free( elem );
+}
+
+template <class T, class S, bool ML, class I, class M>
+void CUtlLinkedList<T,S,ML,I,M>::RemoveAll()
+{
+ // Have to do some convoluted stuff to invoke the destructor on all
+ // valid elements for the multilist case (since we don't have all elements
+ // connected to each other in a list).
+
+ if ( m_LastAlloc == m_Memory.InvalidIterator() )
+ {
+ Assert( m_Head == InvalidIndex() );
+ Assert( m_Tail == InvalidIndex() );
+ Assert( m_FirstFree == InvalidIndex() );
+ Assert( m_ElementCount == 0 );
+ return;
+ }
+
+ if ( ML )
+ {
+ for ( typename M::Iterator_t it = m_Memory.First(); it != m_Memory.InvalidIterator(); it = m_Memory.Next( it ) )
+ {
+ I i = m_Memory.GetIndex( it );
+ if ( IsValidIndex( i ) ) // skip elements already in the free list
+ {
+ ListElem_t &internalElem = InternalElement( i );
+ Destruct( &internalElem.m_Element );
+ internalElem.m_Previous = i;
+ internalElem.m_Next = m_FirstFree;
+ m_FirstFree = i;
+ }
+
+ if ( it == m_LastAlloc )
+ break; // don't destruct elements that haven't ever been constructed
+ }
+ }
+ else
+ {
+ I i = Head();
+ I next;
+ while ( i != InvalidIndex() )
+ {
+ next = Next( i );
+ ListElem_t &internalElem = InternalElement( i );
+ Destruct( &internalElem.m_Element );
+ internalElem.m_Previous = i;
+ internalElem.m_Next = next == InvalidIndex() ? m_FirstFree : next;
+ i = next;
+ }
+ if ( Head() != InvalidIndex() )
+ {
+ m_FirstFree = Head();
+ }
+ }
+
+ // Clear everything else out
+ m_Head = InvalidIndex();
+ m_Tail = InvalidIndex();
+ m_ElementCount = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// list modification
+//-----------------------------------------------------------------------------
+
+template <class T, class S, bool ML, class I, class M>
+void CUtlLinkedList<T,S,ML,I,M>::LinkBefore( I before, I elem )
+{
+ Assert( IsValidIndex(elem) );
+
+ // Unlink it if it's in the list at the moment
+ Unlink(elem);
+
+ ListElem_t * pNewElem = &InternalElement(elem);
+
+ // The element *after* our newly linked one is the one we linked before.
+ pNewElem->m_Next = before;
+
+ S newElem_mPrevious; // we need to hang on to this for the compairson against InvalidIndex()
+ // below; otherwise we get a a load-hit-store on pNewElem->m_Previous, even
+ // with
+ if (before == InvalidIndex())
+ {
+ // In this case, we're linking to the end of the list, so reset the tail
+ newElem_mPrevious = m_Tail;
+ pNewElem->m_Previous = m_Tail;
+ 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);
+ pNewElem->m_Previous = newElem_mPrevious = beforeElem->m_Previous;
+ beforeElem->m_Previous = elem;
+ }
+
+ // Reset the head if we linked to the head of the list
+ if (newElem_mPrevious == InvalidIndex())
+ m_Head = elem;
+ else
+ InternalElement(newElem_mPrevious).m_Next = elem;
+
+ // one more element baby
+ ++m_ElementCount;
+}
+
+template <class T, class S, bool ML, class I, class M>
+void CUtlLinkedList<T,S,ML,I,M>::LinkAfter( I after, I elem )
+{
+ Assert( IsValidIndex(elem) );
+
+ // Unlink it if it's in the list at the moment
+ if ( IsInList(elem) )
+ Unlink(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_Head;
+ 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_Tail = elem;
+ else
+ InternalElement(newElem.m_Next).m_Previous = elem;
+
+ // one more element baby
+ ++m_ElementCount;
+}
+
+template <class T, class S, bool ML, class I, class M>
+void CUtlLinkedList<T,S,ML,I,M>::Unlink( I elem )
+{
+ Assert( IsValidIndex(elem) );
+ if (IsInList(elem))
+ {
+ ListElem_t * pOldElem = &m_Memory[ elem ];
+
+ // If we're the first guy, reset the head
+ // otherwise, make our previous node's next pointer = our next
+ if ( pOldElem->m_Previous != InvalidIndex() )
+ {
+ m_Memory[ pOldElem->m_Previous ].m_Next = pOldElem->m_Next;
+ }
+ else
+ {
+ m_Head = pOldElem->m_Next;
+ }
+
+ // If we're the last guy, reset the tail
+ // otherwise, make our next node's prev pointer = our prev
+ if ( pOldElem->m_Next != InvalidIndex() )
+ {
+ m_Memory[ pOldElem->m_Next ].m_Previous = pOldElem->m_Previous;
+ }
+ else
+ {
+ m_Tail = pOldElem->m_Previous;
+ }
+
+ // This marks this node as not in the list,
+ // but not in the free list either
+ pOldElem->m_Previous = pOldElem->m_Next = elem;
+
+ // One less puppy
+ --m_ElementCount;
+ }
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline void CUtlLinkedList<T,S,ML,I,M>::LinkToHead( I elem )
+{
+ LinkAfter( InvalidIndex(), elem );
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline void CUtlLinkedList<T,S,ML,I,M>::LinkToTail( I elem )
+{
+ LinkBefore( InvalidIndex(), elem );
+}
+
+
+//-----------------------------------------------------------------------------
+// Class to drop in to replace a CUtlLinkedList that needs to be more memory agressive
+//-----------------------------------------------------------------------------
+
+DECLARE_POINTER_HANDLE( UtlPtrLinkedListIndex_t ); // to enforce correct usage
+
+template < typename T >
+class CUtlPtrLinkedList
+{
+public:
+ CUtlPtrLinkedList()
+ : m_pFirst( NULL ),
+ m_nElems( 0 )
+ {
+ COMPILE_TIME_ASSERT( sizeof(IndexType_t) == sizeof(Node_t *) );
+ }
+
+ ~CUtlPtrLinkedList()
+ {
+ RemoveAll();
+ }
+
+ typedef UtlPtrLinkedListIndex_t IndexType_t;
+
+ T &operator[]( IndexType_t i )
+ {
+ return (( Node_t * )i)->elem;
+ }
+
+ const T &operator[]( IndexType_t i ) const
+ {
+ return (( Node_t * )i)->elem;
+ }
+
+ IndexType_t AddToTail()
+ {
+ return DoInsertBefore( (IndexType_t)m_pFirst, NULL );
+ }
+
+ IndexType_t AddToTail( T const& src )
+ {
+ return DoInsertBefore( (IndexType_t)m_pFirst, &src );
+ }
+
+ IndexType_t AddToHead()
+ {
+ IndexType_t result = DoInsertBefore( (IndexType_t)m_pFirst, NULL );
+ m_pFirst = ((Node_t *)result);
+ return result;
+ }
+
+ IndexType_t AddToHead( T const& src )
+ {
+ IndexType_t result = DoInsertBefore( (IndexType_t)m_pFirst, &src );
+ m_pFirst = ((Node_t *)result);
+ return result;
+ }
+
+ IndexType_t InsertBefore( IndexType_t before )
+ {
+ return DoInsertBefore( before, NULL );
+ }
+
+ IndexType_t InsertAfter( IndexType_t after )
+ {
+ Node_t *pBefore = ((Node_t *)after)->next;
+ return DoInsertBefore( pBefore, NULL );
+ }
+
+ IndexType_t InsertBefore( IndexType_t before, T const& src )
+ {
+ return DoInsertBefore( before, &src );
+ }
+
+ IndexType_t InsertAfter( IndexType_t after, T const& src )
+ {
+ Node_t *pBefore = ((Node_t *)after)->next;
+ return DoInsertBefore( pBefore, &src );
+ }
+
+ void Remove( IndexType_t elem )
+ {
+ Node_t *p = (Node_t *)elem;
+
+ if ( p->pNext == p )
+ {
+ m_pFirst = NULL;
+ }
+ else
+ {
+ if ( m_pFirst == p )
+ {
+ m_pFirst = p->pNext;
+ }
+ p->pNext->pPrev = p->pPrev;
+ p->pPrev->pNext = p->pNext;
+ }
+
+ delete p;
+ m_nElems--;
+ }
+
+ void RemoveAll()
+ {
+ Node_t *p = m_pFirst;
+ if ( p )
+ {
+ do
+ {
+ Node_t *pNext = p->pNext;
+ delete p;
+ p = pNext;
+ } while( p != m_pFirst );
+ }
+
+ m_pFirst = NULL;
+ m_nElems = 0;
+ }
+
+ int Count() const
+ {
+ return m_nElems;
+ }
+
+ IndexType_t Head() const
+ {
+ return (IndexType_t)m_pFirst;
+ }
+
+ IndexType_t Next( IndexType_t i ) const
+ {
+ Node_t *p = ((Node_t *)i)->pNext;
+ if ( p != m_pFirst )
+ {
+ return (IndexType_t)p;
+ }
+ return NULL;
+ }
+
+ bool IsValidIndex( IndexType_t i ) const
+ {
+ Node_t *p = ((Node_t *)i);
+ return ( p && p->pNext && p->pPrev );
+ }
+
+ inline static IndexType_t InvalidIndex()
+ {
+ return NULL;
+ }
+private:
+
+ struct Node_t
+ {
+ Node_t() {}
+ Node_t( const T &_elem ) : elem( _elem ) {}
+
+ T elem;
+ Node_t *pPrev, *pNext;
+ };
+
+ Node_t *AllocNode( const T *pCopyFrom )
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ Node_t *p;
+
+ if ( !pCopyFrom )
+ {
+ p = new Node_t;
+ }
+ else
+ {
+ p = new Node_t( *pCopyFrom );
+ }
+
+ return p;
+ }
+
+ IndexType_t DoInsertBefore( IndexType_t before, const T *pCopyFrom )
+ {
+ Node_t *p = AllocNode( pCopyFrom );
+ Node_t *pBefore = (Node_t *)before;
+ if ( pBefore )
+ {
+ p->pNext = pBefore;
+ p->pPrev = pBefore->pPrev;
+ pBefore->pPrev = p;
+ p->pPrev->pNext = p;
+ }
+ else
+ {
+ Assert( !m_pFirst );
+ m_pFirst = p->pNext = p->pPrev = p;
+ }
+
+ m_nElems++;
+ return (IndexType_t)p;
+ }
+
+ Node_t *m_pFirst;
+ unsigned m_nElems;
+};
+
+//-----------------------------------------------------------------------------
+
+#endif // UTLLINKEDLIST_H
diff --git a/external/vpc/public/tier1/utlmap.h b/external/vpc/public/tier1/utlmap.h
new file mode 100644
index 0000000..aeca2b4
--- /dev/null
+++ b/external/vpc/public/tier1/utlmap.h
@@ -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
diff --git a/external/vpc/public/tier1/utlmemory.h b/external/vpc/public/tier1/utlmemory.h
new file mode 100644
index 0000000..40e6a19
--- /dev/null
+++ b/external/vpc/public/tier1/utlmemory.h
@@ -0,0 +1,1090 @@
+//===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+// A growable memory class.
+//===========================================================================//
+
+#ifndef UTLMEMORY_H
+#define UTLMEMORY_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/dbg.h"
+#include <string.h>
+#include "tier0/platform.h"
+
+#include "tier0/memalloc.h"
+#include "mathlib/mathlib.h"
+#include "tier0/memdbgon.h"
+
+#pragma warning (disable:4100)
+#pragma warning (disable:4514)
+
+
+//-----------------------------------------------------------------------------
+
+
+#ifdef UTLMEMORY_TRACK
+#define UTLMEMORY_TRACK_ALLOC() MemAlloc_RegisterAllocation( "||Sum of all UtlMemory||", 0, m_nAllocationCount * sizeof(T), m_nAllocationCount * sizeof(T), 0 )
+#define UTLMEMORY_TRACK_FREE() if ( !m_pMemory ) ; else MemAlloc_RegisterDeallocation( "||Sum of all UtlMemory||", 0, m_nAllocationCount * sizeof(T), m_nAllocationCount * sizeof(T), 0 )
+#else
+#define UTLMEMORY_TRACK_ALLOC() ((void)0)
+#define UTLMEMORY_TRACK_FREE() ((void)0)
+#endif
+
+
+//-----------------------------------------------------------------------------
+// The CUtlMemory class:
+// A growable memory class which doubles in size by default.
+//-----------------------------------------------------------------------------
+template< class T, class I = int >
+class CUtlMemory
+{
+public:
+ // constructor, destructor
+ CUtlMemory( int nGrowSize = 0, int nInitSize = 0 );
+ CUtlMemory( T* pMemory, int numElements );
+ CUtlMemory( const T* pMemory, int numElements );
+ ~CUtlMemory();
+
+ // Set the size by which the memory grows
+ void Init( int nGrowSize = 0, int nInitSize = 0 );
+
+ 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;
+
+ // 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; }
+
+ // Gets the base address (can change when adding elements!)
+ T* Base();
+ const T* Base() const;
+
+ // Attaches the buffer to external memory....
+ void SetExternalBuffer( T* pMemory, int numElements );
+ void SetExternalBuffer( const T* pMemory, int numElements );
+ void AssumeMemory( T *pMemory, int nSize );
+ T* Detach();
+ void *DetachMemory();
+
+ // Fast swap
+ void Swap( CUtlMemory< T, I > &mem );
+
+ // Switches the buffer from an external memory buffer to a reallocatable buffer
+ // Will copy the current contents of the external buffer to the reallocatable buffer
+ void ConvertToGrowableMemory( int nGrowSize );
+
+ // Size
+ int NumAllocated() const;
+ int Count() const;
+
+ // Grows the memory, so that at least allocated + num elements are allocated
+ 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 );
+
+ // is the memory externally allocated?
+ bool IsExternallyAllocated() const;
+
+ // is the memory read only?
+ bool IsReadOnly() const;
+
+ // Set the size by which the memory grows
+ void SetGrowSize( int size );
+
+protected:
+ void ValidateGrowSize()
+ {
+#ifdef _X360
+ if ( m_nGrowSize && m_nGrowSize != EXTERNAL_BUFFER_MARKER )
+ {
+ // Max grow size at 128 bytes on XBOX
+ const int MAX_GROW = 128;
+ if ( m_nGrowSize * sizeof(T) > MAX_GROW )
+ {
+ m_nGrowSize = max( 1, MAX_GROW / sizeof(T) );
+ }
+ }
+#endif
+ }
+
+ enum
+ {
+ EXTERNAL_BUFFER_MARKER = -1,
+ EXTERNAL_CONST_BUFFER_MARKER = -2,
+ };
+
+ T* m_pMemory;
+ int m_nAllocationCount;
+ int m_nGrowSize;
+};
+
+
+//-----------------------------------------------------------------------------
+// The CUtlMemory class:
+// A growable memory class which doubles in size by default.
+//-----------------------------------------------------------------------------
+template< class T, size_t SIZE, class I = int >
+class CUtlMemoryFixedGrowable : public CUtlMemory< T, I >
+{
+ typedef CUtlMemory< T, I > BaseClass;
+
+public:
+ CUtlMemoryFixedGrowable( int nGrowSize = 0, int nInitSize = SIZE ) : BaseClass( m_pFixedMemory, SIZE )
+ {
+ Assert( nInitSize == 0 || nInitSize == SIZE );
+ m_nMallocGrowSize = nGrowSize;
+ }
+
+ void Grow( int nCount = 1 )
+ {
+ if ( this->IsExternallyAllocated() )
+ {
+ this->ConvertToGrowableMemory( m_nMallocGrowSize );
+ }
+ BaseClass::Grow( nCount );
+ }
+
+ void EnsureCapacity( int num )
+ {
+ if ( CUtlMemory<T>::m_nAllocationCount >= num )
+ return;
+
+ if ( this->IsExternallyAllocated() )
+ {
+ // Can't grow a buffer whose memory was externally allocated
+ this->ConvertToGrowableMemory( m_nMallocGrowSize );
+ }
+
+ BaseClass::EnsureCapacity( num );
+ }
+
+private:
+ int m_nMallocGrowSize;
+ T m_pFixedMemory[ SIZE ];
+};
+
+//-----------------------------------------------------------------------------
+// The CUtlMemoryFixed class:
+// A fixed memory class
+//-----------------------------------------------------------------------------
+template< typename T, size_t SIZE, int nAlignment = 0 >
+class CUtlMemoryFixed
+{
+public:
+ // constructor, destructor
+ CUtlMemoryFixed( int nGrowSize = 0, int nInitSize = 0 ) { Assert( nInitSize == 0 || nInitSize == SIZE ); }
+ CUtlMemoryFixed( T* pMemory, int numElements ) { Assert( 0 ); }
+
+ // Can we use this index?
+ bool IsIdxValid( int i ) const { return (i >= 0) && (i < SIZE); }
+
+ // Specify the invalid ('null') index that we'll only return on failure
+ static const int INVALID_INDEX = -1; // For use with COMPILE_TIME_ASSERT
+ static int InvalidIndex() { return INVALID_INDEX; }
+
+ // Gets the base address
+ T* Base() { if ( nAlignment == 0 ) return (T*)(&m_Memory[0]); else return (T*)AlignValue( &m_Memory[0], nAlignment ); }
+ const T* Base() const { if ( nAlignment == 0 ) return (T*)(&m_Memory[0]); else return (T*)AlignValue( &m_Memory[0], nAlignment ); }
+
+ // element access
+ T& operator[]( int i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
+ const T& operator[]( int i ) const { Assert( IsIdxValid(i) ); return Base()[i]; }
+ T& Element( int i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
+ const T& Element( int 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 SIZE; }
+ int Count() const { return SIZE; }
+
+ // Grows the memory, so that at least allocated + num elements are allocated
+ void Grow( int num = 1 ) { Assert( 0 ); }
+
+ // Makes sure we've got at least this much memory
+ void EnsureCapacity( int num ) { Assert( num <= SIZE ); }
+
+ // Memory deallocation
+ void Purge() {}
+
+ // Purge all but the given number of elements (NOT IMPLEMENTED IN CUtlMemoryFixed)
+ void Purge( int numElements ) { Assert( 0 ); }
+
+ // is the memory externally allocated?
+ bool IsExternallyAllocated() const { return false; }
+
+ // Set the size by which the memory grows
+ void SetGrowSize( int size ) {}
+
+ class Iterator_t
+ {
+ public:
+ Iterator_t( int i ) : index( i ) {}
+ int 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() ); }
+ int GetIndex( const Iterator_t &it ) const { return it.index; }
+ bool IsIdxAfter( int 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() ); }
+
+private:
+ char m_Memory[ SIZE*sizeof(T) + nAlignment ];
+};
+
+#ifdef _LINUX
+#define REMEMBER_ALLOC_SIZE_FOR_VALGRIND 1
+#endif
+
+//-----------------------------------------------------------------------------
+// The CUtlMemoryConservative class:
+// A dynamic memory class that tries to minimize overhead (itself small, no custom grow factor)
+//-----------------------------------------------------------------------------
+template< typename T >
+class CUtlMemoryConservative
+{
+
+public:
+ // constructor, destructor
+ CUtlMemoryConservative( int nGrowSize = 0, int nInitSize = 0 ) : m_pMemory( NULL )
+ {
+#ifdef REMEMBER_ALLOC_SIZE_FOR_VALGRIND
+ m_nCurAllocSize = 0;
+#endif
+
+ }
+ CUtlMemoryConservative( T* pMemory, int numElements ) { Assert( 0 ); }
+ ~CUtlMemoryConservative() { if ( m_pMemory ) free( m_pMemory ); }
+
+ // Can we use this index?
+ bool IsIdxValid( int i ) const { return ( IsDebug() ) ? ( i >= 0 && i < NumAllocated() ) : ( i >= 0 ); }
+ static int InvalidIndex() { return -1; }
+
+ // Gets the base address
+ T* Base() { return m_pMemory; }
+ const T* Base() const { return m_pMemory; }
+
+ // element access
+ T& operator[]( int i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
+ const T& operator[]( int i ) const { Assert( IsIdxValid(i) ); return Base()[i]; }
+ T& Element( int i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
+ const T& Element( int i ) const { Assert( IsIdxValid(i) ); return Base()[i]; }
+
+ // Attaches the buffer to external memory....
+ void SetExternalBuffer( T* pMemory, int numElements ) { Assert( 0 ); }
+
+ // Size
+ FORCEINLINE void RememberAllocSize( size_t sz )
+ {
+#ifdef REMEMBER_ALLOC_SIZE_FOR_VALGRIND
+ m_nCurAllocSize = sz;
+#endif
+ }
+
+ size_t AllocSize( void ) const
+ {
+#ifdef REMEMBER_ALLOC_SIZE_FOR_VALGRIND
+ return m_nCurAllocSize;
+#else
+ return ( m_pMemory ) ? g_pMemAlloc->GetSize( m_pMemory ) : 0;
+#endif
+ }
+
+ int NumAllocated() const
+ {
+ return AllocSize() / sizeof( T );
+ }
+ int Count() const
+ {
+ return NumAllocated();
+ }
+
+ FORCEINLINE void ReAlloc( size_t sz )
+ {
+ m_pMemory = (T*)realloc( m_pMemory, sz );
+ RememberAllocSize( sz );
+ }
+ // Grows the memory, so that at least allocated + num elements are allocated
+ void Grow( int num = 1 )
+ {
+ int nCurN = NumAllocated();
+ ReAlloc( ( nCurN + num ) * sizeof( T ) );
+ }
+
+ // Makes sure we've got at least this much memory
+ void EnsureCapacity( int num )
+ {
+ size_t nSize = sizeof( T ) * MAX( num, Count() );
+ ReAlloc( nSize );
+ }
+
+ // Memory deallocation
+ void Purge()
+ {
+ free( m_pMemory );
+ RememberAllocSize( 0 );
+ m_pMemory = NULL;
+ }
+
+ // Purge all but the given number of elements
+ void Purge( int numElements ) { ReAlloc( numElements * sizeof(T) ); }
+
+ // is the memory externally allocated?
+ bool IsExternallyAllocated() const { return false; }
+
+ // Set the size by which the memory grows
+ void SetGrowSize( int size ) {}
+
+ class Iterator_t
+ {
+ public:
+ Iterator_t( int i, int _limit ) : index( i ), limit( _limit ) {}
+ int index;
+ int limit;
+ 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 { int limit = NumAllocated(); return Iterator_t( limit ? 0 : InvalidIndex(), limit ); }
+ Iterator_t Next( const Iterator_t &it ) const { return Iterator_t( ( it.index + 1 < it.limit ) ? it.index + 1 : InvalidIndex(), it.limit ); }
+ int GetIndex( const Iterator_t &it ) const { return it.index; }
+ bool IsIdxAfter( int i, const Iterator_t &it ) const { return i > it.index; }
+ bool IsValidIterator( const Iterator_t &it ) const { return IsIdxValid( it.index ) && ( it.index < it.limit ); }
+ Iterator_t InvalidIterator() const { return Iterator_t( InvalidIndex(), 0 ); }
+
+private:
+ T *m_pMemory;
+#ifdef REMEMBER_ALLOC_SIZE_FOR_VALGRIND
+ size_t m_nCurAllocSize;
+#endif
+
+};
+
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+
+template< class T, class I >
+CUtlMemory<T,I>::CUtlMemory( int nGrowSize, int nInitAllocationCount ) : m_pMemory(0),
+ m_nAllocationCount( nInitAllocationCount ), m_nGrowSize( nGrowSize )
+{
+ ValidateGrowSize();
+ Assert( nGrowSize >= 0 );
+ if (m_nAllocationCount)
+ {
+ UTLMEMORY_TRACK_ALLOC();
+ MEM_ALLOC_CREDIT_CLASS();
+ m_pMemory = (T*)malloc( m_nAllocationCount * sizeof(T) );
+ }
+}
+
+template< class T, class I >
+CUtlMemory<T,I>::CUtlMemory( T* pMemory, int numElements ) : m_pMemory(pMemory),
+ m_nAllocationCount( numElements )
+{
+ // Special marker indicating externally supplied modifyable memory
+ m_nGrowSize = EXTERNAL_BUFFER_MARKER;
+}
+
+template< class T, class I >
+CUtlMemory<T,I>::CUtlMemory( const T* pMemory, int numElements ) : m_pMemory( (T*)pMemory ),
+ m_nAllocationCount( numElements )
+{
+ // Special marker indicating externally supplied modifyable memory
+ m_nGrowSize = EXTERNAL_CONST_BUFFER_MARKER;
+}
+
+template< class T, class I >
+CUtlMemory<T,I>::~CUtlMemory()
+{
+ Purge();
+
+#ifdef _DEBUG
+ m_pMemory = reinterpret_cast< T* >( 0xFEFEBAAD );
+ m_nAllocationCount = 0x7BADF00D;
+#endif
+}
+
+template< class T, class I >
+void CUtlMemory<T,I>::Init( int nGrowSize /*= 0*/, int nInitSize /*= 0*/ )
+{
+ Purge();
+
+ m_nGrowSize = nGrowSize;
+ m_nAllocationCount = nInitSize;
+ ValidateGrowSize();
+ Assert( nGrowSize >= 0 );
+ if (m_nAllocationCount)
+ {
+ UTLMEMORY_TRACK_ALLOC();
+ MEM_ALLOC_CREDIT_CLASS();
+ m_pMemory = (T*)malloc( m_nAllocationCount * sizeof(T) );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Fast swap
+//-----------------------------------------------------------------------------
+template< class T, class I >
+void CUtlMemory<T,I>::Swap( CUtlMemory<T,I> &mem )
+{
+ V_swap( m_nGrowSize, mem.m_nGrowSize );
+ V_swap( m_pMemory, mem.m_pMemory );
+ V_swap( m_nAllocationCount, mem.m_nAllocationCount );
+}
+
+
+//-----------------------------------------------------------------------------
+// Switches the buffer from an external memory buffer to a reallocatable buffer
+//-----------------------------------------------------------------------------
+template< class T, class I >
+void CUtlMemory<T,I>::ConvertToGrowableMemory( int nGrowSize )
+{
+ if ( !IsExternallyAllocated() )
+ return;
+
+ m_nGrowSize = nGrowSize;
+ if (m_nAllocationCount)
+ {
+ UTLMEMORY_TRACK_ALLOC();
+ MEM_ALLOC_CREDIT_CLASS();
+
+ int nNumBytes = m_nAllocationCount * sizeof(T);
+ T *pMemory = (T*)malloc( nNumBytes );
+ memcpy( pMemory, m_pMemory, nNumBytes );
+ m_pMemory = pMemory;
+ }
+ else
+ {
+ m_pMemory = NULL;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Attaches the buffer to external memory....
+//-----------------------------------------------------------------------------
+template< class T, class I >
+void CUtlMemory<T,I>::SetExternalBuffer( T* pMemory, int numElements )
+{
+ // Blow away any existing allocated memory
+ Purge();
+
+ m_pMemory = pMemory;
+ m_nAllocationCount = numElements;
+
+ // Indicate that we don't own the memory
+ m_nGrowSize = EXTERNAL_BUFFER_MARKER;
+}
+
+template< class T, class I >
+void CUtlMemory<T,I>::SetExternalBuffer( const T* pMemory, int numElements )
+{
+ // Blow away any existing allocated memory
+ Purge();
+
+ m_pMemory = const_cast<T*>( pMemory );
+ m_nAllocationCount = numElements;
+
+ // Indicate that we don't own the memory
+ m_nGrowSize = EXTERNAL_CONST_BUFFER_MARKER;
+}
+
+template< class T, class I >
+void CUtlMemory<T,I>::AssumeMemory( T* pMemory, int numElements )
+{
+ // Blow away any existing allocated memory
+ Purge();
+
+ // Simply take the pointer but don't mark us as external
+ m_pMemory = pMemory;
+ m_nAllocationCount = numElements;
+}
+
+template< class T, class I >
+void *CUtlMemory<T,I>::DetachMemory()
+{
+ if ( IsExternallyAllocated() )
+ return NULL;
+
+ void *pMemory = m_pMemory;
+ m_pMemory = 0;
+ m_nAllocationCount = 0;
+ return pMemory;
+}
+
+template< class T, class I >
+inline T* CUtlMemory<T,I>::Detach()
+{
+ return (T*)DetachMemory();
+}
+
+
+//-----------------------------------------------------------------------------
+// element access
+//-----------------------------------------------------------------------------
+template< class T, class I >
+inline T& CUtlMemory<T,I>::operator[]( I i )
+{
+ Assert( !IsReadOnly() );
+ Assert( IsIdxValid(i) );
+ return m_pMemory[i];
+}
+
+template< class T, class I >
+inline const T& CUtlMemory<T,I>::operator[]( I i ) const
+{
+ Assert( IsIdxValid(i) );
+ return m_pMemory[i];
+}
+
+template< class T, class I >
+inline T& CUtlMemory<T,I>::Element( I i )
+{
+ Assert( !IsReadOnly() );
+ Assert( IsIdxValid(i) );
+ return m_pMemory[i];
+}
+
+template< class T, class I >
+inline const T& CUtlMemory<T,I>::Element( I i ) const
+{
+ Assert( IsIdxValid(i) );
+ return m_pMemory[i];
+}
+
+
+//-----------------------------------------------------------------------------
+// is the memory externally allocated?
+//-----------------------------------------------------------------------------
+template< class T, class I >
+bool CUtlMemory<T,I>::IsExternallyAllocated() const
+{
+ return (m_nGrowSize < 0);
+}
+
+
+//-----------------------------------------------------------------------------
+// is the memory read only?
+//-----------------------------------------------------------------------------
+template< class T, class I >
+bool CUtlMemory<T,I>::IsReadOnly() const
+{
+ return (m_nGrowSize == EXTERNAL_CONST_BUFFER_MARKER);
+}
+
+
+template< class T, class I >
+void CUtlMemory<T,I>::SetGrowSize( int nSize )
+{
+ Assert( !IsExternallyAllocated() );
+ Assert( nSize >= 0 );
+ m_nGrowSize = nSize;
+ ValidateGrowSize();
+}
+
+
+//-----------------------------------------------------------------------------
+// Gets the base address (can change when adding elements!)
+//-----------------------------------------------------------------------------
+template< class T, class I >
+inline T* CUtlMemory<T,I>::Base()
+{
+ Assert( !IsReadOnly() );
+ return m_pMemory;
+}
+
+template< class T, class I >
+inline const T *CUtlMemory<T,I>::Base() const
+{
+ return m_pMemory;
+}
+
+
+//-----------------------------------------------------------------------------
+// Size
+//-----------------------------------------------------------------------------
+template< class T, class I >
+inline int CUtlMemory<T,I>::NumAllocated() const
+{
+ return m_nAllocationCount;
+}
+
+template< class T, class I >
+inline int CUtlMemory<T,I>::Count() const
+{
+ return m_nAllocationCount;
+}
+
+
+//-----------------------------------------------------------------------------
+// Is element index valid?
+//-----------------------------------------------------------------------------
+template< class T, class I >
+inline bool CUtlMemory<T,I>::IsIdxValid( 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 ( x >= 0 ) && ( x < m_nAllocationCount );
+}
+
+//-----------------------------------------------------------------------------
+// Grows the memory
+//-----------------------------------------------------------------------------
+inline int UtlMemory_CalcNewAllocationCount( int nAllocationCount, int nGrowSize, int nNewSize, int nBytesItem )
+{
+ if ( nGrowSize )
+ {
+ nAllocationCount = ((1 + ((nNewSize - 1) / nGrowSize)) * nGrowSize);
+ }
+ else
+ {
+ if ( !nAllocationCount )
+ {
+ // Compute an allocation which is at least as big as a cache line...
+ nAllocationCount = (31 + nBytesItem) / nBytesItem;
+ }
+
+ while (nAllocationCount < nNewSize)
+ {
+#ifndef _X360
+ nAllocationCount *= 2;
+#else
+ int nNewAllocationCount = ( nAllocationCount * 9) / 8; // 12.5 %
+ if ( nNewAllocationCount > nAllocationCount )
+ nAllocationCount = nNewAllocationCount;
+ else
+ nAllocationCount *= 2;
+#endif
+ }
+ }
+
+ return nAllocationCount;
+}
+
+template< class T, class I >
+void CUtlMemory<T,I>::Grow( int num )
+{
+ Assert( num > 0 );
+
+ if ( IsExternallyAllocated() )
+ {
+ // Can't grow a buffer whose memory was externally allocated
+ Assert(0);
+ return;
+ }
+
+ // Make sure we have at least numallocated + num allocations.
+ // Use the grow rules specified for this memory (in m_nGrowSize)
+ int nAllocationRequested = m_nAllocationCount + num;
+
+ UTLMEMORY_TRACK_FREE();
+
+ int nNewAllocationCount = UtlMemory_CalcNewAllocationCount( m_nAllocationCount, m_nGrowSize, nAllocationRequested, sizeof(T) );
+
+ // if m_nAllocationRequested wraps index type I, recalculate
+ if ( ( int )( I )nNewAllocationCount < nAllocationRequested )
+ {
+ if ( ( int )( I )nNewAllocationCount == 0 && ( int )( I )( nNewAllocationCount - 1 ) >= nAllocationRequested )
+ {
+ --nNewAllocationCount; // deal w/ the common case of m_nAllocationCount == MAX_USHORT + 1
+ }
+ else
+ {
+ if ( ( int )( I )nAllocationRequested != nAllocationRequested )
+ {
+ // we've been asked to grow memory to a size s.t. the index type can't address the requested amount of memory
+ Assert( 0 );
+ return;
+ }
+ while ( ( int )( I )nNewAllocationCount < nAllocationRequested )
+ {
+ nNewAllocationCount = ( nNewAllocationCount + nAllocationRequested ) / 2;
+ }
+ }
+ }
+
+ m_nAllocationCount = nNewAllocationCount;
+
+ UTLMEMORY_TRACK_ALLOC();
+
+ if (m_pMemory)
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ m_pMemory = (T*)realloc( m_pMemory, m_nAllocationCount * sizeof(T) );
+ Assert( m_pMemory );
+ }
+ else
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ m_pMemory = (T*)malloc( m_nAllocationCount * sizeof(T) );
+ Assert( m_pMemory );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Makes sure we've got at least this much memory
+//-----------------------------------------------------------------------------
+template< class T, class I >
+inline void CUtlMemory<T,I>::EnsureCapacity( int num )
+{
+ if (m_nAllocationCount >= num)
+ return;
+
+ if ( IsExternallyAllocated() )
+ {
+ // Can't grow a buffer whose memory was externally allocated
+ Assert(0);
+ return;
+ }
+
+ UTLMEMORY_TRACK_FREE();
+
+ m_nAllocationCount = num;
+
+ UTLMEMORY_TRACK_ALLOC();
+
+ if (m_pMemory)
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ m_pMemory = (T*)realloc( m_pMemory, m_nAllocationCount * sizeof(T) );
+ }
+ else
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ m_pMemory = (T*)malloc( m_nAllocationCount * sizeof(T) );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Memory deallocation
+//-----------------------------------------------------------------------------
+template< class T, class I >
+void CUtlMemory<T,I>::Purge()
+{
+ if ( !IsExternallyAllocated() )
+ {
+ if (m_pMemory)
+ {
+ UTLMEMORY_TRACK_FREE();
+ free( (void*)m_pMemory );
+ m_pMemory = 0;
+ }
+ m_nAllocationCount = 0;
+ }
+}
+
+template< class T, class I >
+void CUtlMemory<T,I>::Purge( int numElements )
+{
+ Assert( numElements >= 0 );
+
+ if( numElements > m_nAllocationCount )
+ {
+ // Ensure this isn't a grow request in disguise.
+ Assert( numElements <= m_nAllocationCount );
+ return;
+ }
+
+ // If we have zero elements, simply do a purge:
+ if( numElements == 0 )
+ {
+ Purge();
+ return;
+ }
+
+ if ( IsExternallyAllocated() )
+ {
+ // Can't shrink a buffer whose memory was externally allocated, fail silently like purge
+ return;
+ }
+
+ // If the number of elements is the same as the allocation count, we are done.
+ if( numElements == m_nAllocationCount )
+ {
+ return;
+ }
+
+
+ if( !m_pMemory )
+ {
+ // Allocation count is non zero, but memory is null.
+ Assert( m_pMemory );
+ return;
+ }
+
+ UTLMEMORY_TRACK_FREE();
+
+ m_nAllocationCount = numElements;
+
+ UTLMEMORY_TRACK_ALLOC();
+
+ // Allocation count > 0, shrink it down.
+ MEM_ALLOC_CREDIT_CLASS();
+ m_pMemory = (T*)realloc( m_pMemory, m_nAllocationCount * sizeof(T) );
+}
+
+//-----------------------------------------------------------------------------
+// The CUtlMemory class:
+// A growable memory class which doubles in size by default.
+//-----------------------------------------------------------------------------
+template< class T, int nAlignment >
+class CUtlMemoryAligned : public CUtlMemory<T>
+{
+public:
+ // constructor, destructor
+ CUtlMemoryAligned( int nGrowSize = 0, int nInitSize = 0 );
+ CUtlMemoryAligned( T* pMemory, int numElements );
+ CUtlMemoryAligned( const T* pMemory, int numElements );
+ ~CUtlMemoryAligned();
+
+ // Attaches the buffer to external memory....
+ void SetExternalBuffer( T* pMemory, int numElements );
+ void SetExternalBuffer( const T* pMemory, int numElements );
+
+ // Grows the memory, so that at least allocated + num elements are allocated
+ 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 (NOT IMPLEMENTED IN CUtlMemoryAligned)
+ void Purge( int numElements ) { Assert( 0 ); }
+
+private:
+ void *Align( const void *pAddr );
+};
+
+
+//-----------------------------------------------------------------------------
+// Aligns a pointer
+//-----------------------------------------------------------------------------
+template< class T, int nAlignment >
+void *CUtlMemoryAligned<T, nAlignment>::Align( const void *pAddr )
+{
+ size_t nAlignmentMask = nAlignment - 1;
+ return (void*)( ((size_t)pAddr + nAlignmentMask) & (~nAlignmentMask) );
+}
+
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+template< class T, int nAlignment >
+CUtlMemoryAligned<T, nAlignment>::CUtlMemoryAligned( int nGrowSize, int nInitAllocationCount )
+{
+ CUtlMemory<T>::m_pMemory = 0;
+ CUtlMemory<T>::m_nAllocationCount = nInitAllocationCount;
+ CUtlMemory<T>::m_nGrowSize = nGrowSize;
+ this->ValidateGrowSize();
+
+ // Alignment must be a power of two
+ COMPILE_TIME_ASSERT( (nAlignment & (nAlignment-1)) == 0 );
+ Assert( (nGrowSize >= 0) && (nGrowSize != CUtlMemory<T>::EXTERNAL_BUFFER_MARKER) );
+ if ( CUtlMemory<T>::m_nAllocationCount )
+ {
+ UTLMEMORY_TRACK_ALLOC();
+ MEM_ALLOC_CREDIT_CLASS();
+ CUtlMemory<T>::m_pMemory = (T*)_aligned_malloc( nInitAllocationCount * sizeof(T), nAlignment );
+ }
+}
+
+template< class T, int nAlignment >
+CUtlMemoryAligned<T, nAlignment>::CUtlMemoryAligned( T* pMemory, int numElements )
+{
+ // Special marker indicating externally supplied memory
+ CUtlMemory<T>::m_nGrowSize = CUtlMemory<T>::EXTERNAL_BUFFER_MARKER;
+
+ CUtlMemory<T>::m_pMemory = (T*)Align( pMemory );
+ CUtlMemory<T>::m_nAllocationCount = ( (int)(pMemory + numElements) - (int)CUtlMemory<T>::m_pMemory ) / sizeof(T);
+}
+
+template< class T, int nAlignment >
+CUtlMemoryAligned<T, nAlignment>::CUtlMemoryAligned( const T* pMemory, int numElements )
+{
+ // Special marker indicating externally supplied memory
+ CUtlMemory<T>::m_nGrowSize = CUtlMemory<T>::EXTERNAL_CONST_BUFFER_MARKER;
+
+ CUtlMemory<T>::m_pMemory = (T*)Align( pMemory );
+ CUtlMemory<T>::m_nAllocationCount = ( (int)(pMemory + numElements) - (int)CUtlMemory<T>::m_pMemory ) / sizeof(T);
+}
+
+template< class T, int nAlignment >
+CUtlMemoryAligned<T, nAlignment>::~CUtlMemoryAligned()
+{
+ Purge();
+}
+
+
+//-----------------------------------------------------------------------------
+// Attaches the buffer to external memory....
+//-----------------------------------------------------------------------------
+template< class T, int nAlignment >
+void CUtlMemoryAligned<T, nAlignment>::SetExternalBuffer( T* pMemory, int numElements )
+{
+ // Blow away any existing allocated memory
+ Purge();
+
+ CUtlMemory<T>::m_pMemory = (T*)Align( pMemory );
+ CUtlMemory<T>::m_nAllocationCount = ( (int)(pMemory + numElements) - (int)CUtlMemory<T>::m_pMemory ) / sizeof(T);
+
+ // Indicate that we don't own the memory
+ CUtlMemory<T>::m_nGrowSize = CUtlMemory<T>::EXTERNAL_BUFFER_MARKER;
+}
+
+template< class T, int nAlignment >
+void CUtlMemoryAligned<T, nAlignment>::SetExternalBuffer( const T* pMemory, int numElements )
+{
+ // Blow away any existing allocated memory
+ Purge();
+
+ CUtlMemory<T>::m_pMemory = (T*)Align( pMemory );
+ CUtlMemory<T>::m_nAllocationCount = ( (int)(pMemory + numElements) - (int)CUtlMemory<T>::m_pMemory ) / sizeof(T);
+
+ // Indicate that we don't own the memory
+ CUtlMemory<T>::m_nGrowSize = CUtlMemory<T>::EXTERNAL_CONST_BUFFER_MARKER;
+}
+
+
+//-----------------------------------------------------------------------------
+// Grows the memory
+//-----------------------------------------------------------------------------
+template< class T, int nAlignment >
+void CUtlMemoryAligned<T, nAlignment>::Grow( int num )
+{
+ Assert( num > 0 );
+
+ if ( this->IsExternallyAllocated() )
+ {
+ // Can't grow a buffer whose memory was externally allocated
+ Assert(0);
+ return;
+ }
+
+ UTLMEMORY_TRACK_FREE();
+
+ // Make sure we have at least numallocated + num allocations.
+ // Use the grow rules specified for this memory (in m_nGrowSize)
+ int nAllocationRequested = CUtlMemory<T>::m_nAllocationCount + num;
+
+ CUtlMemory<T>::m_nAllocationCount = UtlMemory_CalcNewAllocationCount( CUtlMemory<T>::m_nAllocationCount, CUtlMemory<T>::m_nGrowSize, nAllocationRequested, sizeof(T) );
+
+ UTLMEMORY_TRACK_ALLOC();
+
+ if ( CUtlMemory<T>::m_pMemory )
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ CUtlMemory<T>::m_pMemory = (T*)MemAlloc_ReallocAligned( CUtlMemory<T>::m_pMemory, CUtlMemory<T>::m_nAllocationCount * sizeof(T), nAlignment );
+ Assert( CUtlMemory<T>::m_pMemory );
+ }
+ else
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ CUtlMemory<T>::m_pMemory = (T*)MemAlloc_AllocAligned( CUtlMemory<T>::m_nAllocationCount * sizeof(T), nAlignment );
+ Assert( CUtlMemory<T>::m_pMemory );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Makes sure we've got at least this much memory
+//-----------------------------------------------------------------------------
+template< class T, int nAlignment >
+inline void CUtlMemoryAligned<T, nAlignment>::EnsureCapacity( int num )
+{
+ if ( CUtlMemory<T>::m_nAllocationCount >= num )
+ return;
+
+ if ( this->IsExternallyAllocated() )
+ {
+ // Can't grow a buffer whose memory was externally allocated
+ Assert(0);
+ return;
+ }
+
+ UTLMEMORY_TRACK_FREE();
+
+ CUtlMemory<T>::m_nAllocationCount = num;
+
+ UTLMEMORY_TRACK_ALLOC();
+
+ if ( CUtlMemory<T>::m_pMemory )
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ CUtlMemory<T>::m_pMemory = (T*)MemAlloc_ReallocAligned( CUtlMemory<T>::m_pMemory, CUtlMemory<T>::m_nAllocationCount * sizeof(T), nAlignment );
+ }
+ else
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ CUtlMemory<T>::m_pMemory = (T*)MemAlloc_AllocAligned( CUtlMemory<T>::m_nAllocationCount * sizeof(T), nAlignment );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Memory deallocation
+//-----------------------------------------------------------------------------
+template< class T, int nAlignment >
+void CUtlMemoryAligned<T, nAlignment>::Purge()
+{
+ if ( !this->IsExternallyAllocated() )
+ {
+ if ( CUtlMemory<T>::m_pMemory )
+ {
+ UTLMEMORY_TRACK_FREE();
+ MemAlloc_FreeAligned( CUtlMemory<T>::m_pMemory );
+ CUtlMemory<T>::m_pMemory = 0;
+ }
+ CUtlMemory<T>::m_nAllocationCount = 0;
+ }
+}
+
+#include "tier0/memdbgoff.h"
+
+#endif // UTLMEMORY_H
diff --git a/external/vpc/public/tier1/utlmultilist.h b/external/vpc/public/tier1/utlmultilist.h
new file mode 100644
index 0000000..68e2a98
--- /dev/null
+++ b/external/vpc/public/tier1/utlmultilist.h
@@ -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
diff --git a/external/vpc/public/tier1/utlqueue.h b/external/vpc/public/tier1/utlqueue.h
new file mode 100644
index 0000000..d816407
--- /dev/null
+++ b/external/vpc/public/tier1/utlqueue.h
@@ -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
diff --git a/external/vpc/public/tier1/utlrbtree.h b/external/vpc/public/tier1/utlrbtree.h
new file mode 100644
index 0000000..5031cca
--- /dev/null
+++ b/external/vpc/public/tier1/utlrbtree.h
@@ -0,0 +1,1581 @@
+//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $Header: $
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef UTLRBTREE_H
+#define UTLRBTREE_H
+
+#include "tier1/utlmemory.h"
+#include "tier1/utlfixedmemory.h"
+#include "tier1/utlblockmemory.h"
+
+
+// This is a useful macro to iterate from start to end in order in a map
+#define FOR_EACH_UTLRBTREE( treeName, iteratorName ) \
+ for ( int iteratorName = treeName.FirstInorder(); iteratorName != treeName.InvalidIndex(); iteratorName = treeName.NextInorder( iteratorName ) )
+
+
+//-----------------------------------------------------------------------------
+// Tool to generate a default compare function for any type that implements
+// operator<, including all simple types
+//-----------------------------------------------------------------------------
+
+template <typename T >
+class CDefOps
+{
+public:
+ static bool LessFunc( const T &lhs, const T &rhs ) { return ( lhs < rhs ); }
+};
+
+#define DefLessFunc( type ) CDefOps< type >::LessFunc
+
+//-------------------------------------
+
+inline bool StringLessThan( const char * const &lhs, const char * const &rhs) {
+ if ( !lhs ) return false;
+ if ( !rhs ) return true;
+ return ( strcmp( lhs, rhs) < 0 );
+}
+
+inline bool CaselessStringLessThan( const char * const &lhs, const char * const &rhs ) {
+ if ( !lhs ) return false;
+ if ( !rhs ) return true;
+ return ( stricmp( lhs, rhs) < 0 );
+}
+
+
+// Same as CaselessStringLessThan, but it ignores differences in / and \.
+inline bool CaselessStringLessThanIgnoreSlashes( const char * const &lhs, const char * const &rhs )
+{
+ const char *pa = lhs;
+ const char *pb = rhs;
+ while ( *pa && *pb )
+ {
+ char a = *pa;
+ char b = *pb;
+
+ // Check for dir slashes.
+ if ( a == '/' || a == '\\' )
+ {
+ if ( b != '/' && b != '\\' )
+ return ('/' < b);
+ }
+ else
+ {
+ if ( a >= 'a' && a <= 'z' )
+ a = 'A' + (a - 'a');
+
+ if ( b >= 'a' && b <= 'z' )
+ b = 'A' + (b - 'a');
+
+ if ( a > b )
+ return false;
+ else if ( a < b )
+ return true;
+ }
+ ++pa;
+ ++pb;
+ }
+
+ // Filenames also must be the same length.
+ if ( *pa != *pb )
+ {
+ // If pa shorter than pb then it's "less"
+ return ( !*pa );
+ }
+
+ return false;
+}
+
+//-------------------------------------
+// inline these two templates to stop multiple definitions of the same code
+template <> inline bool CDefOps<const char *>::LessFunc( const char * const &lhs, const char * const &rhs ) { return StringLessThan( lhs, rhs ); }
+template <> inline bool CDefOps<char *>::LessFunc( char * const &lhs, char * const &rhs ) { return StringLessThan( lhs, rhs ); }
+
+//-------------------------------------
+
+template <typename RBTREE_T>
+void SetDefLessFunc( RBTREE_T &RBTree )
+{
+ RBTree.SetLessFunc( DefLessFunc( typename RBTREE_T::KeyType_t ) );
+}
+
+//-----------------------------------------------------------------------------
+// A red-black binary search tree
+//-----------------------------------------------------------------------------
+
+template < class I >
+struct UtlRBTreeLinks_t
+{
+ I m_Left;
+ I m_Right;
+ I m_Parent;
+ I m_Tag;
+};
+
+template < class T, class I >
+struct UtlRBTreeNode_t : public UtlRBTreeLinks_t< I >
+{
+ T m_Data;
+};
+
+template < class T, class I = unsigned short, typename L = bool (*)( const T &, const T & ), class M = CUtlMemory< UtlRBTreeNode_t< T, I >, I > >
+class CUtlRBTree
+{
+public:
+
+ typedef T 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 L LessFunc_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
+ CUtlRBTree( int growSize = 0, int initSize = 0, const LessFunc_t &lessfunc = 0 );
+ CUtlRBTree( const LessFunc_t &lessfunc );
+ ~CUtlRBTree( );
+
+ void EnsureCapacity( int num );
+
+ // NOTE: CopyFrom is fast but dangerous! It just memcpy's all nodes - it does NOT run copy constructors, so
+ // it is not a true deep copy (i.e 'T' must be POD for this to work - e.g CUtlString will not work).
+ void CopyFrom( const CUtlRBTree<T, I, L, M> &other );
+
+ // gets particular elements
+ T& Element( I i );
+ T const &Element( I i ) const;
+ T& operator[]( I i );
+ T const &operator[]( I i ) const;
+
+ // Gets the root
+ I Root() const;
+
+ // Num elements
+ unsigned int Count() const;
+
+ // Max "size" of the vector
+ // it's not generally safe to iterate from index 0 to MaxElement()-1 (you could do this as a potential
+ // iteration optimization, IF CUtlMemory is the allocator, and IF IsValidIndex() is tested for each element...
+ // but this should be implemented inside the CUtlRBTree iteration API, if anywhere)
+ I MaxElement() const;
+
+ // Gets the children
+ I Parent( I i ) const;
+ I LeftChild( I i ) const;
+ I RightChild( I i ) const;
+
+ // Tests if a node is a left or right child
+ bool IsLeftChild( I i ) const;
+ bool IsRightChild( I i ) const;
+
+ // Tests if root or leaf
+ bool IsRoot( I i ) const;
+ bool IsLeaf( I i ) const;
+
+ // Checks if a node is valid and in the tree
+ bool IsValidIndex( I i ) const;
+
+ // Checks if the tree as a whole is valid
+ bool IsValid() const;
+
+ // Invalid index
+ static I InvalidIndex();
+
+ // returns the tree depth (not a very fast operation)
+ int Depth( I node ) const;
+ int Depth() const;
+
+ // Sets the less func
+ void SetLessFunc( const LessFunc_t &func );
+
+ // Allocation method
+ I NewNode();
+
+ // Insert method (inserts in order)
+ // NOTE: the returned 'index' will be valid as long as the element remains in the tree
+ // (other elements being added/removed will not affect it)
+ I Insert( T const &insert );
+ void Insert( const T *pArray, int nItems );
+ I InsertIfNotFound( T const &insert );
+
+ // Find method
+ I Find( T const &search ) const;
+
+ // Remove methods
+ void RemoveAt( I i );
+ bool Remove( T const &remove );
+ void RemoveAll( );
+ void Purge();
+
+ // Allocation, deletion
+ void FreeNode( I i );
+
+ // Iteration
+ I FirstInorder() const;
+ I NextInorder( I i ) const;
+ I PrevInorder( I i ) const;
+ I LastInorder() const;
+
+ I FirstPreorder() const;
+ I NextPreorder( I i ) const;
+ I PrevPreorder( I i ) const;
+ I LastPreorder( ) const;
+
+ I FirstPostorder() const;
+ I NextPostorder( I i ) const;
+
+ // If you change the search key, this can be used to reinsert the
+ // element into the tree.
+ void Reinsert( I elem );
+
+ // swap in place
+ void Swap( CUtlRBTree< T, I, L > &that );
+
+private:
+ // Can't copy the tree this way!
+ CUtlRBTree<T, I, L, M>& operator=( const CUtlRBTree<T, I, L, M> &other );
+
+protected:
+ enum NodeColor_t
+ {
+ RED = 0,
+ BLACK
+ };
+
+ typedef UtlRBTreeNode_t< T, I > Node_t;
+ typedef UtlRBTreeLinks_t< I > Links_t;
+
+ // Sets the children
+ void SetParent( I i, I parent );
+ void SetLeftChild( I i, I child );
+ void SetRightChild( I i, I child );
+ void LinkToParent( I i, I parent, bool isLeft );
+
+ // Gets at the links
+ Links_t const &Links( I i ) const;
+ Links_t &Links( I i );
+
+ // Checks if a link is red or black
+ bool IsRed( I i ) const;
+ bool IsBlack( I i ) const;
+
+ // Sets/gets node color
+ NodeColor_t Color( I i ) const;
+ void SetColor( I i, NodeColor_t c );
+
+ // operations required to preserve tree balance
+ void RotateLeft(I i);
+ void RotateRight(I i);
+ void InsertRebalance(I i);
+ void RemoveRebalance(I i);
+
+ // Insertion, removal
+ I InsertAt( I parent, bool leftchild );
+
+ // copy constructors not allowed
+ CUtlRBTree( CUtlRBTree<T, I, L, M> const &tree );
+
+ // Inserts a node into the tree, doesn't copy the data in.
+ void FindInsertionPosition( T const &insert, I &parent, bool &leftchild );
+
+ // Remove and add back an element in the tree.
+ void Unlink( I elem );
+ void Link( I elem );
+
+ // Used for sorting.
+ LessFunc_t m_LessFunc;
+
+ M m_Elements;
+ I m_Root;
+ I m_NumElements;
+ I m_FirstFree;
+ typename M::Iterator_t m_LastAlloc; // the last index allocated
+
+ Node_t* m_pElements;
+
+ FORCEINLINE M const &Elements( void ) const
+ {
+ return m_Elements;
+ }
+
+
+ void ResetDbgInfo()
+ {
+ m_pElements = (Node_t*)m_Elements.Base();
+ }
+};
+
+// this is kind of ugly, but until C++ gets templatized typedefs in C++0x, it's our only choice
+template < class T, class I = int, typename L = bool (*)( const T &, const T & ) >
+class CUtlFixedRBTree : public CUtlRBTree< T, I, L, CUtlFixedMemory< UtlRBTreeNode_t< T, I > > >
+{
+public:
+
+ typedef L LessFunc_t;
+
+ CUtlFixedRBTree( int growSize = 0, int initSize = 0, const LessFunc_t &lessfunc = 0 )
+ : CUtlRBTree< T, I, L, CUtlFixedMemory< UtlRBTreeNode_t< T, I > > >( growSize, initSize, lessfunc ) {}
+ CUtlFixedRBTree( const LessFunc_t &lessfunc )
+ : CUtlRBTree< T, I, L, CUtlFixedMemory< UtlRBTreeNode_t< T, I > > >( lessfunc ) {}
+
+ typedef CUtlRBTree< T, I, L, CUtlFixedMemory< UtlRBTreeNode_t< T, I > > > BaseClass;
+ bool IsValidIndex( I i ) const
+ {
+ if ( !BaseClass::Elements().IsIdxValid( i ) )
+ return false;
+
+#ifdef _DEBUG // it's safe to skip this here, since the only way to get indices after m_LastAlloc is to use MaxElement()
+ if ( BaseClass::Elements().IsIdxAfter( i, this->m_LastAlloc ) )
+ {
+ Assert( 0 );
+ return false; // don't read values that have been allocated, but not constructed
+ }
+#endif
+
+ return LeftChild(i) != i;
+ }
+
+protected:
+ void ResetDbgInfo() {}
+
+private:
+ // this doesn't make sense for fixed rbtrees, since there's no useful max pointer, and the index space isn't contiguous anyways
+ I MaxElement() const;
+};
+
+// this is kind of ugly, but until C++ gets templatized typedefs in C++0x, it's our only choice
+template < class T, class I = unsigned short, typename L = bool (*)( const T &, const T & ) >
+class CUtlBlockRBTree : public CUtlRBTree< T, I, L, CUtlBlockMemory< UtlRBTreeNode_t< T, I >, I > >
+{
+public:
+ typedef L LessFunc_t;
+ CUtlBlockRBTree( int growSize = 0, int initSize = 0, const LessFunc_t &lessfunc = 0 )
+ : CUtlRBTree< T, I, L, CUtlBlockMemory< UtlRBTreeNode_t< T, I >, I > >( growSize, initSize, lessfunc ) {}
+ CUtlBlockRBTree( const LessFunc_t &lessfunc )
+ : CUtlRBTree< T, I, L, CUtlBlockMemory< UtlRBTreeNode_t< T, I >, I > >( lessfunc ) {}
+protected:
+ void ResetDbgInfo() {}
+};
+
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline CUtlRBTree<T, I, L, M>::CUtlRBTree( int growSize, int initSize, const LessFunc_t &lessfunc ) :
+m_LessFunc( lessfunc ),
+m_Elements( growSize, initSize ),
+m_Root( InvalidIndex() ),
+m_NumElements( 0 ),
+m_FirstFree( InvalidIndex() ),
+m_LastAlloc( m_Elements.InvalidIterator() )
+{
+ ResetDbgInfo();
+}
+
+template < class T, class I, typename L, class M >
+inline CUtlRBTree<T, I, L, M>::CUtlRBTree( const LessFunc_t &lessfunc ) :
+m_Elements( 0, 0 ),
+m_LessFunc( lessfunc ),
+m_Root( InvalidIndex() ),
+m_NumElements( 0 ),
+m_FirstFree( InvalidIndex() ),
+m_LastAlloc( m_Elements.InvalidIterator() )
+{
+ ResetDbgInfo();
+}
+
+template < class T, class I, typename L, class M >
+inline CUtlRBTree<T, I, L, M>::~CUtlRBTree()
+{
+ Purge();
+}
+
+template < class T, class I, typename L, class M >
+inline void CUtlRBTree<T, I, L, M>::EnsureCapacity( int num )
+{
+ m_Elements.EnsureCapacity( num );
+}
+
+template < class T, class I, typename L, class M >
+inline void CUtlRBTree<T, I, L, M>::CopyFrom( const CUtlRBTree<T, I, L, M> &other )
+{
+ Purge();
+ m_Elements.EnsureCapacity( other.m_Elements.Count() );
+ memcpy( m_Elements.Base(), other.m_Elements.Base(), other.m_Elements.Count() * sizeof( UtlRBTreeNode_t< T, I > ) );
+ m_LessFunc = other.m_LessFunc;
+ m_Root = other.m_Root;
+ m_NumElements = other.m_NumElements;
+ m_FirstFree = other.m_FirstFree;
+ m_LastAlloc = other.m_LastAlloc;
+ ResetDbgInfo();
+}
+
+//-----------------------------------------------------------------------------
+// gets particular elements
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline T &CUtlRBTree<T, I, L, M>::Element( I i )
+{
+ return m_Elements[i].m_Data;
+}
+
+template < class T, class I, typename L, class M >
+inline T const &CUtlRBTree<T, I, L, M>::Element( I i ) const
+{
+ return m_Elements[i].m_Data;
+}
+
+template < class T, class I, typename L, class M >
+inline T &CUtlRBTree<T, I, L, M>::operator[]( I i )
+{
+ return Element(i);
+}
+
+template < class T, class I, typename L, class M >
+inline T const &CUtlRBTree<T, I, L, M>::operator[]( I i ) const
+{
+ return Element(i);
+}
+
+//-----------------------------------------------------------------------------
+//
+// various accessors
+//
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Gets the root
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline I CUtlRBTree<T, I, L, M>::Root() const
+{
+ return m_Root;
+}
+
+//-----------------------------------------------------------------------------
+// Num elements
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline unsigned int CUtlRBTree<T, I, L, M>::Count() const
+{
+ return (unsigned int)m_NumElements;
+}
+
+//-----------------------------------------------------------------------------
+// Max "size" of the vector
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline I CUtlRBTree<T, I, L, M>::MaxElement() const
+{
+ return ( I )m_Elements.NumAllocated();
+}
+
+
+//-----------------------------------------------------------------------------
+// Gets the children
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline I CUtlRBTree<T, I, L, M>::Parent( I i ) const
+{
+ return Links(i).m_Parent;
+}
+
+template < class T, class I, typename L, class M >
+inline I CUtlRBTree<T, I, L, M>::LeftChild( I i ) const
+{
+ return Links(i).m_Left;
+}
+
+template < class T, class I, typename L, class M >
+inline I CUtlRBTree<T, I, L, M>::RightChild( I i ) const
+{
+ return Links(i).m_Right;
+}
+
+//-----------------------------------------------------------------------------
+// Tests if a node is a left or right child
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline bool CUtlRBTree<T, I, L, M>::IsLeftChild( I i ) const
+{
+ return LeftChild(Parent(i)) == i;
+}
+
+template < class T, class I, typename L, class M >
+inline bool CUtlRBTree<T, I, L, M>::IsRightChild( I i ) const
+{
+ return RightChild(Parent(i)) == i;
+}
+
+
+//-----------------------------------------------------------------------------
+// Tests if root or leaf
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline bool CUtlRBTree<T, I, L, M>::IsRoot( I i ) const
+{
+ return i == m_Root;
+}
+
+template < class T, class I, typename L, class M >
+inline bool CUtlRBTree<T, I, L, M>::IsLeaf( I i ) const
+{
+ return (LeftChild(i) == InvalidIndex()) && (RightChild(i) == InvalidIndex());
+}
+
+
+//-----------------------------------------------------------------------------
+// Checks if a node is valid and in the tree
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline bool CUtlRBTree<T, I, L, M>::IsValidIndex( I i ) const
+{
+ if ( !m_Elements.IsIdxValid( i ) )
+ return false;
+
+ if ( m_Elements.IsIdxAfter( i, m_LastAlloc ) )
+ return false; // don't read values that have been allocated, but not constructed
+
+ return LeftChild(i) != i;
+}
+
+
+//-----------------------------------------------------------------------------
+// Invalid index
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline I CUtlRBTree<T, I, L, M>::InvalidIndex()
+{
+ return ( I )M::InvalidIndex();
+}
+
+
+//-----------------------------------------------------------------------------
+// returns the tree depth (not a very fast operation)
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline int CUtlRBTree<T, I, L, M>::Depth() const
+{
+ return Depth(Root());
+}
+
+//-----------------------------------------------------------------------------
+// Sets the children
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline void CUtlRBTree<T, I, L, M>::SetParent( I i, I parent )
+{
+ Links(i).m_Parent = parent;
+}
+
+template < class T, class I, typename L, class M >
+inline void CUtlRBTree<T, I, L, M>::SetLeftChild( I i, I child )
+{
+ Links(i).m_Left = child;
+}
+
+template < class T, class I, typename L, class M >
+inline void CUtlRBTree<T, I, L, M>::SetRightChild( I i, I child )
+{
+ Links(i).m_Right = child;
+}
+
+//-----------------------------------------------------------------------------
+// Gets at the links
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline typename CUtlRBTree<T, I, L, M>::Links_t const &CUtlRBTree<T, I, L, M>::Links( I i ) const
+{
+ // Sentinel node, makes life easier
+ static Links_t s_Sentinel =
+ {
+ InvalidIndex(), InvalidIndex(), InvalidIndex(), CUtlRBTree<T, I, L, M>::BLACK
+ };
+
+ return (i != InvalidIndex()) ? *(Links_t*)&m_Elements[i] : *(Links_t*)&s_Sentinel;
+}
+
+template < class T, class I, typename L, class M >
+inline typename CUtlRBTree<T, I, L, M>::Links_t &CUtlRBTree<T, I, L, M>::Links( I i )
+{
+ Assert(i != InvalidIndex());
+ return *(Links_t *)&m_Elements[i];
+}
+
+//-----------------------------------------------------------------------------
+// Checks if a link is red or black
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline bool CUtlRBTree<T, I, L, M>::IsRed( I i ) const
+{
+ return (Links(i).m_Tag == RED);
+}
+
+template < class T, class I, typename L, class M >
+inline bool CUtlRBTree<T, I, L, M>::IsBlack( I i ) const
+{
+ return (Links(i).m_Tag == BLACK);
+}
+
+
+//-----------------------------------------------------------------------------
+// Sets/gets node color
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline typename CUtlRBTree<T, I, L, M>::NodeColor_t CUtlRBTree<T, I, L, M>::Color( I i ) const
+{
+ return (NodeColor_t)Links(i).m_Tag;
+}
+
+template < class T, class I, typename L, class M >
+inline void CUtlRBTree<T, I, L, M>::SetColor( I i, typename CUtlRBTree<T, I, L, M>::NodeColor_t c )
+{
+ Links(i).m_Tag = (I)c;
+}
+
+//-----------------------------------------------------------------------------
+// Allocates/ deallocates nodes
+//-----------------------------------------------------------------------------
+#pragma warning(push)
+#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::NewNode()
+{
+ I elem;
+
+ // Nothing in the free list; add.
+ if ( m_FirstFree == InvalidIndex() )
+ {
+ Assert( m_Elements.IsValidIterator( m_LastAlloc ) || m_NumElements == 0 );
+ typename M::Iterator_t it = m_Elements.IsValidIterator( m_LastAlloc ) ? m_Elements.Next( m_LastAlloc ) : m_Elements.First();
+ if ( !m_Elements.IsValidIterator( it ) )
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ m_Elements.Grow();
+
+ it = m_Elements.IsValidIterator( m_LastAlloc ) ? m_Elements.Next( m_LastAlloc ) : m_Elements.First();
+
+ Assert( m_Elements.IsValidIterator( it ) );
+ if ( !m_Elements.IsValidIterator( it ) )
+ {
+ Error( "CUtlRBTree overflow!\n" );
+ }
+ }
+ m_LastAlloc = it;
+ elem = m_Elements.GetIndex( m_LastAlloc );
+ Assert( m_Elements.IsValidIterator( m_LastAlloc ) );
+ }
+ else
+ {
+ elem = m_FirstFree;
+ m_FirstFree = Links( m_FirstFree ).m_Right;
+ }
+
+#ifdef _DEBUG
+ // reset links to invalid....
+ Links_t &node = Links( elem );
+ node.m_Left = node.m_Right = node.m_Parent = InvalidIndex();
+#endif
+
+ Construct( &Element( elem ) );
+ ResetDbgInfo();
+
+ return elem;
+}
+#pragma warning(pop)
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::FreeNode( I i )
+{
+ Assert( IsValidIndex(i) && (i != InvalidIndex()) );
+ Destruct( &Element(i) );
+ SetLeftChild( i, i ); // indicates it's in not in the tree
+ SetRightChild( i, m_FirstFree );
+ m_FirstFree = i;
+}
+
+
+//-----------------------------------------------------------------------------
+// Rotates node i to the left
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::RotateLeft(I elem)
+{
+ I rightchild = RightChild(elem);
+ SetRightChild( elem, LeftChild(rightchild) );
+ if (LeftChild(rightchild) != InvalidIndex())
+ SetParent( LeftChild(rightchild), elem );
+
+ if (rightchild != InvalidIndex())
+ SetParent( rightchild, Parent(elem) );
+ if (!IsRoot(elem))
+ {
+ if (IsLeftChild(elem))
+ SetLeftChild( Parent(elem), rightchild );
+ else
+ SetRightChild( Parent(elem), rightchild );
+ }
+ else
+ m_Root = rightchild;
+
+ SetLeftChild( rightchild, elem );
+ if (elem != InvalidIndex())
+ SetParent( elem, rightchild );
+}
+
+
+//-----------------------------------------------------------------------------
+// Rotates node i to the right
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::RotateRight(I elem)
+{
+ I leftchild = LeftChild(elem);
+ SetLeftChild( elem, RightChild(leftchild) );
+ if (RightChild(leftchild) != InvalidIndex())
+ SetParent( RightChild(leftchild), elem );
+
+ if (leftchild != InvalidIndex())
+ SetParent( leftchild, Parent(elem) );
+ if (!IsRoot(elem))
+ {
+ if (IsRightChild(elem))
+ SetRightChild( Parent(elem), leftchild );
+ else
+ SetLeftChild( Parent(elem), leftchild );
+ }
+ else
+ m_Root = leftchild;
+
+ SetRightChild( leftchild, elem );
+ if (elem != InvalidIndex())
+ SetParent( elem, leftchild );
+}
+
+
+//-----------------------------------------------------------------------------
+// Rebalances the tree after an insertion
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::InsertRebalance(I elem)
+{
+ while ( !IsRoot(elem) && (Color(Parent(elem)) == RED) )
+ {
+ I parent = Parent(elem);
+ I grandparent = Parent(parent);
+
+ /* we have a violation */
+ if (IsLeftChild(parent))
+ {
+ I uncle = RightChild(grandparent);
+ if (IsRed(uncle))
+ {
+ /* uncle is RED */
+ SetColor(parent, BLACK);
+ SetColor(uncle, BLACK);
+ SetColor(grandparent, RED);
+ elem = grandparent;
+ }
+ else
+ {
+ /* uncle is BLACK */
+ if (IsRightChild(elem))
+ {
+ /* make x a left child, will change parent and grandparent */
+ elem = parent;
+ RotateLeft(elem);
+ parent = Parent(elem);
+ grandparent = Parent(parent);
+ }
+ /* recolor and rotate */
+ SetColor(parent, BLACK);
+ SetColor(grandparent, RED);
+ RotateRight(grandparent);
+ }
+ }
+ else
+ {
+ /* mirror image of above code */
+ I uncle = LeftChild(grandparent);
+ if (IsRed(uncle))
+ {
+ /* uncle is RED */
+ SetColor(parent, BLACK);
+ SetColor(uncle, BLACK);
+ SetColor(grandparent, RED);
+ elem = grandparent;
+ }
+ else
+ {
+ /* uncle is BLACK */
+ if (IsLeftChild(elem))
+ {
+ /* make x a right child, will change parent and grandparent */
+ elem = parent;
+ RotateRight(parent);
+ parent = Parent(elem);
+ grandparent = Parent(parent);
+ }
+ /* recolor and rotate */
+ SetColor(parent, BLACK);
+ SetColor(grandparent, RED);
+ RotateLeft(grandparent);
+ }
+ }
+ }
+ SetColor( m_Root, BLACK );
+}
+
+
+//-----------------------------------------------------------------------------
+// Insert a node into the tree
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::InsertAt( I parent, bool leftchild )
+{
+ I i = NewNode();
+ LinkToParent( i, parent, leftchild );
+ ++m_NumElements;
+
+ Assert(IsValid());
+
+ return i;
+}
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::LinkToParent( I i, I parent, bool isLeft )
+{
+ Links_t &elem = Links(i);
+ elem.m_Parent = parent;
+ elem.m_Left = elem.m_Right = InvalidIndex();
+ elem.m_Tag = RED;
+
+ /* insert node in tree */
+ if (parent != InvalidIndex())
+ {
+ if (isLeft)
+ Links(parent).m_Left = i;
+ else
+ Links(parent).m_Right = i;
+ }
+ else
+ {
+ m_Root = i;
+ }
+
+ InsertRebalance(i);
+}
+
+//-----------------------------------------------------------------------------
+// Rebalance the tree after a deletion
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::RemoveRebalance(I elem)
+{
+ while (elem != m_Root && IsBlack(elem))
+ {
+ I parent = Parent(elem);
+
+ // If elem is the left child of the parent
+ if (elem == LeftChild(parent))
+ {
+ // Get our sibling
+ I sibling = RightChild(parent);
+ if (IsRed(sibling))
+ {
+ SetColor(sibling, BLACK);
+ SetColor(parent, RED);
+ RotateLeft(parent);
+
+ // We may have a new parent now
+ parent = Parent(elem);
+ sibling = RightChild(parent);
+ }
+ if ( (IsBlack(LeftChild(sibling))) && (IsBlack(RightChild(sibling))) )
+ {
+ if (sibling != InvalidIndex())
+ SetColor(sibling, RED);
+ elem = parent;
+ }
+ else
+ {
+ if (IsBlack(RightChild(sibling)))
+ {
+ SetColor(LeftChild(sibling), BLACK);
+ SetColor(sibling, RED);
+ RotateRight(sibling);
+
+ // rotation may have changed this
+ parent = Parent(elem);
+ sibling = RightChild(parent);
+ }
+ SetColor( sibling, Color(parent) );
+ SetColor( parent, BLACK );
+ SetColor( RightChild(sibling), BLACK );
+ RotateLeft( parent );
+ elem = m_Root;
+ }
+ }
+ else
+ {
+ // Elem is the right child of the parent
+ I sibling = LeftChild(parent);
+ if (IsRed(sibling))
+ {
+ SetColor(sibling, BLACK);
+ SetColor(parent, RED);
+ RotateRight(parent);
+
+ // We may have a new parent now
+ parent = Parent(elem);
+ sibling = LeftChild(parent);
+ }
+ if ( (IsBlack(RightChild(sibling))) && (IsBlack(LeftChild(sibling))) )
+ {
+ if (sibling != InvalidIndex())
+ SetColor( sibling, RED );
+ elem = parent;
+ }
+ else
+ {
+ if (IsBlack(LeftChild(sibling)))
+ {
+ SetColor( RightChild(sibling), BLACK );
+ SetColor( sibling, RED );
+ RotateLeft( sibling );
+
+ // rotation may have changed this
+ parent = Parent(elem);
+ sibling = LeftChild(parent);
+ }
+ SetColor( sibling, Color(parent) );
+ SetColor( parent, BLACK );
+ SetColor( LeftChild(sibling), BLACK );
+ RotateRight( parent );
+ elem = m_Root;
+ }
+ }
+ }
+ SetColor( elem, BLACK );
+}
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::Unlink( I elem )
+{
+ if ( elem != InvalidIndex() )
+ {
+ I x, y;
+
+ if ((LeftChild(elem) == InvalidIndex()) ||
+ (RightChild(elem) == InvalidIndex()))
+ {
+ /* y has a NIL node as a child */
+ y = elem;
+ }
+ else
+ {
+ /* find tree successor with a NIL node as a child */
+ y = RightChild(elem);
+ while (LeftChild(y) != InvalidIndex())
+ y = LeftChild(y);
+ }
+
+ /* x is y's only child */
+ if (LeftChild(y) != InvalidIndex())
+ x = LeftChild(y);
+ else
+ x = RightChild(y);
+
+ /* remove y from the parent chain */
+ if (x != InvalidIndex())
+ SetParent( x, Parent(y) );
+ if (!IsRoot(y))
+ {
+ if (IsLeftChild(y))
+ SetLeftChild( Parent(y), x );
+ else
+ SetRightChild( Parent(y), x );
+ }
+ else
+ m_Root = x;
+
+ // need to store this off now, we'll be resetting y's color
+ NodeColor_t ycolor = Color(y);
+ if (y != elem)
+ {
+ // Standard implementations copy the data around, we cannot here.
+ // Hook in y to link to the same stuff elem used to.
+ SetParent( y, Parent(elem) );
+ SetRightChild( y, RightChild(elem) );
+ SetLeftChild( y, LeftChild(elem) );
+
+ if (!IsRoot(elem))
+ if (IsLeftChild(elem))
+ SetLeftChild( Parent(elem), y );
+ else
+ SetRightChild( Parent(elem), y );
+ else
+ m_Root = y;
+
+ if (LeftChild(y) != InvalidIndex())
+ SetParent( LeftChild(y), y );
+ if (RightChild(y) != InvalidIndex())
+ SetParent( RightChild(y), y );
+
+ SetColor( y, Color(elem) );
+ }
+
+ if ((x != InvalidIndex()) && (ycolor == BLACK))
+ RemoveRebalance(x);
+ }
+}
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::Link( I elem )
+{
+ if ( elem != InvalidIndex() )
+ {
+ I parent = InvalidIndex();
+ bool leftchild = false;
+
+ FindInsertionPosition( Element( elem ), parent, leftchild );
+
+ LinkToParent( elem, parent, leftchild );
+
+ Assert(IsValid());
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Delete a node from the tree
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::RemoveAt(I elem)
+{
+ if ( elem != InvalidIndex() )
+ {
+ Unlink( elem );
+
+ FreeNode(elem);
+ --m_NumElements;
+
+ Assert(IsValid());
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// remove a node in the tree
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M > bool CUtlRBTree<T, I, L, M>::Remove( T const &search )
+{
+ I node = Find( search );
+ if (node != InvalidIndex())
+ {
+ RemoveAt(node);
+ return true;
+ }
+ return false;
+}
+
+
+//-----------------------------------------------------------------------------
+// Removes all nodes from the tree
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::RemoveAll()
+{
+ // Have to do some convoluted stuff to invoke the destructor on all
+ // valid elements for the multilist case (since we don't have all elements
+ // connected to each other in a list).
+
+ if ( m_LastAlloc == m_Elements.InvalidIterator() )
+ {
+ Assert( m_Root == InvalidIndex() );
+ Assert( m_FirstFree == InvalidIndex() );
+ Assert( m_NumElements == 0 );
+ return;
+ }
+
+ for ( typename M::Iterator_t it = m_Elements.First(); it != m_Elements.InvalidIterator(); it = m_Elements.Next( it ) )
+ {
+ I i = m_Elements.GetIndex( it );
+ if ( IsValidIndex( i ) ) // skip elements in the free list
+ {
+ Destruct( &Element( i ) );
+ SetRightChild( i, m_FirstFree );
+ SetLeftChild( i, i );
+ m_FirstFree = i;
+ }
+
+ if ( it == m_LastAlloc )
+ break; // don't destruct elements that haven't ever been constucted
+ }
+
+ // Clear everything else out
+ m_Root = InvalidIndex();
+ m_NumElements = 0;
+
+ Assert( IsValid() );
+}
+
+//-----------------------------------------------------------------------------
+// Removes all nodes from the tree and purges memory
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::Purge()
+{
+ RemoveAll();
+ m_FirstFree = InvalidIndex();
+ m_Elements.Purge();
+ m_LastAlloc = m_Elements.InvalidIterator();
+}
+
+
+//-----------------------------------------------------------------------------
+// iteration
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::FirstInorder() const
+{
+ I i = m_Root;
+ while (LeftChild(i) != InvalidIndex())
+ i = LeftChild(i);
+ return i;
+}
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::NextInorder( I i ) const
+{
+ Assert(IsValidIndex(i));
+
+ if (RightChild(i) != InvalidIndex())
+ {
+ i = RightChild(i);
+ while (LeftChild(i) != InvalidIndex())
+ i = LeftChild(i);
+ return i;
+ }
+
+ I parent = Parent(i);
+ while (IsRightChild(i))
+ {
+ i = parent;
+ if (i == InvalidIndex()) break;
+ parent = Parent(i);
+ }
+ return parent;
+}
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::PrevInorder( I i ) const
+{
+ Assert(IsValidIndex(i));
+
+ if (LeftChild(i) != InvalidIndex())
+ {
+ i = LeftChild(i);
+ while (RightChild(i) != InvalidIndex())
+ i = RightChild(i);
+ return i;
+ }
+
+ I parent = Parent(i);
+ while (IsLeftChild(i))
+ {
+ i = parent;
+ if (i == InvalidIndex()) break;
+ parent = Parent(i);
+ }
+ return parent;
+}
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::LastInorder() const
+{
+ I i = m_Root;
+ while (RightChild(i) != InvalidIndex())
+ i = RightChild(i);
+ return i;
+}
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::FirstPreorder() const
+{
+ return m_Root;
+}
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::NextPreorder( I i ) const
+{
+ if (LeftChild(i) != InvalidIndex())
+ return LeftChild(i);
+
+ if (RightChild(i) != InvalidIndex())
+ return RightChild(i);
+
+ I parent = Parent(i);
+ while( parent != InvalidIndex())
+ {
+ if (IsLeftChild(i) && (RightChild(parent) != InvalidIndex()))
+ return RightChild(parent);
+ i = parent;
+ parent = Parent(parent);
+ }
+ return InvalidIndex();
+}
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::PrevPreorder( I i ) const
+{
+ Assert(0); // not implemented yet
+ return InvalidIndex();
+}
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::LastPreorder() const
+{
+ I i = m_Root;
+ while (1)
+ {
+ while (RightChild(i) != InvalidIndex())
+ i = RightChild(i);
+
+ if (LeftChild(i) != InvalidIndex())
+ i = LeftChild(i);
+ else
+ break;
+ }
+ return i;
+}
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::FirstPostorder() const
+{
+ I i = m_Root;
+ while (!IsLeaf(i))
+ {
+ if (LeftChild(i))
+ i = LeftChild(i);
+ else
+ i = RightChild(i);
+ }
+ return i;
+}
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::NextPostorder( I i ) const
+{
+ I parent = Parent(i);
+ if (parent == InvalidIndex())
+ return InvalidIndex();
+
+ if (IsRightChild(i))
+ return parent;
+
+ if (RightChild(parent) == InvalidIndex())
+ return parent;
+
+ i = RightChild(parent);
+ while (!IsLeaf(i))
+ {
+ if (LeftChild(i))
+ i = LeftChild(i);
+ else
+ i = RightChild(i);
+ }
+ return i;
+}
+
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::Reinsert( I elem )
+{
+ Unlink( elem );
+ Link( elem );
+}
+
+
+//-----------------------------------------------------------------------------
+// returns the tree depth (not a very fast operation)
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+int CUtlRBTree<T, I, L, M>::Depth( I node ) const
+{
+ if (node == InvalidIndex())
+ return 0;
+
+ int depthright = Depth( RightChild(node) );
+ int depthleft = Depth( LeftChild(node) );
+ return MAX( depthright, depthleft ) + 1;
+}
+
+
+//#define UTLTREE_PARANOID
+
+//-----------------------------------------------------------------------------
+// Makes sure the tree is valid after every operation
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+bool CUtlRBTree<T, I, L, M>::IsValid() const
+{
+ if ( !Count() )
+ return true;
+
+ if ( m_LastAlloc == m_Elements.InvalidIterator() )
+ return false;
+
+ if ( !m_Elements.IsIdxValid( Root() ) )
+ return false;
+
+ if ( Parent( Root() ) != InvalidIndex() )
+ return false;
+
+#ifdef UTLTREE_PARANOID
+
+ // First check to see that mNumEntries matches reality.
+ // count items on the free list
+ int numFree = 0;
+ for ( int i = m_FirstFree; i != InvalidIndex(); i = RightChild( i ) )
+ {
+ ++numFree;
+ if ( !m_Elements.IsIdxValid( i ) )
+ return false;
+ }
+
+ // iterate over all elements, looking for validity
+ // based on the self pointers
+ int nElements = 0;
+ int numFree2 = 0;
+ for ( M::Iterator_t it = m_Elements.First(); it != m_Elements.InvalidIterator(); it = m_Elements.Next( it ) )
+ {
+ I i = m_Elements.GetIndex( it );
+ if ( !IsValidIndex( i ) )
+ {
+ ++numFree2;
+ }
+ else
+ {
+ ++nElements;
+
+ int right = RightChild( i );
+ int left = LeftChild( i );
+ if ( ( right == left ) && ( right != InvalidIndex() ) )
+ return false;
+
+ if ( right != InvalidIndex() )
+ {
+ if ( !IsValidIndex( right ) )
+ return false;
+ if ( Parent( right ) != i )
+ return false;
+ if ( IsRed( i ) && IsRed( right ) )
+ return false;
+ }
+
+ if ( left != InvalidIndex() )
+ {
+ if ( !IsValidIndex( left ) )
+ return false;
+ if ( Parent( left ) != i )
+ return false;
+ if ( IsRed( i ) && IsRed( left ) )
+ return false;
+ }
+ }
+
+ if ( it == m_LastAlloc )
+ break;
+ }
+ if ( numFree2 != numFree )
+ return false;
+
+ if ( nElements != m_NumElements )
+ return false;
+
+#endif // UTLTREE_PARANOID
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Sets the less func
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::SetLessFunc( const typename CUtlRBTree<T, I, L, M>::LessFunc_t &func )
+{
+ if (!m_LessFunc)
+ {
+ m_LessFunc = func;
+ }
+ else if ( Count() > 0 )
+ {
+ // need to re-sort the tree here....
+ Assert(0);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// inserts a node into the tree
+//-----------------------------------------------------------------------------
+
+// Inserts a node into the tree, doesn't copy the data in.
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::FindInsertionPosition( T const &insert, I &parent, bool &leftchild )
+{
+ Assert( !!m_LessFunc );
+
+ /* find where node belongs */
+ I current = m_Root;
+ parent = InvalidIndex();
+ leftchild = false;
+ while (current != InvalidIndex())
+ {
+ parent = current;
+ if (m_LessFunc( insert, Element(current) ))
+ {
+ leftchild = true; current = LeftChild(current);
+ }
+ else
+ {
+ leftchild = false; current = RightChild(current);
+ }
+ }
+}
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::Insert( T const &insert )
+{
+ // use copy constructor to copy it in
+ I parent = InvalidIndex();
+ bool leftchild = false;
+ FindInsertionPosition( insert, parent, leftchild );
+ I newNode = InsertAt( parent, leftchild );
+ CopyConstruct( &Element( newNode ), insert );
+ return newNode;
+}
+
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::Insert( const T *pArray, int nItems )
+{
+ while ( nItems-- )
+ {
+ Insert( *pArray++ );
+ }
+}
+
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::InsertIfNotFound( T const &insert )
+{
+ // use copy constructor to copy it in
+ I parent;
+ bool leftchild;
+
+ I current = m_Root;
+ parent = InvalidIndex();
+ leftchild = false;
+ while (current != InvalidIndex())
+ {
+ parent = current;
+ if (m_LessFunc( insert, Element(current) ))
+ {
+ leftchild = true; current = LeftChild(current);
+ }
+ else if (m_LessFunc( Element(current), insert ))
+ {
+ leftchild = false; current = RightChild(current);
+ }
+ else
+ // Match found, no insertion
+ return InvalidIndex();
+ }
+
+ I newNode = InsertAt( parent, leftchild );
+ CopyConstruct( &Element( newNode ), insert );
+ return newNode;
+}
+
+
+//-----------------------------------------------------------------------------
+// finds a node in the tree
+//-----------------------------------------------------------------------------
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::Find( T const &search ) const
+{
+ Assert( !!m_LessFunc );
+
+ I current = m_Root;
+ while (current != InvalidIndex())
+ {
+ if (m_LessFunc( search, Element(current) ))
+ current = LeftChild(current);
+ else if (m_LessFunc( Element(current), search ))
+ current = RightChild(current);
+ else
+ break;
+ }
+ return current;
+}
+
+
+//-----------------------------------------------------------------------------
+// swap in place
+//-----------------------------------------------------------------------------
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::Swap( CUtlRBTree< T, I, L > &that )
+{
+ m_Elements.Swap( that.m_Elements );
+ V_swap( m_LessFunc, that.m_LessFunc );
+ V_swap( m_Root, that.m_Root );
+ V_swap( m_NumElements, that.m_NumElements );
+ V_swap( m_FirstFree, that.m_FirstFree );
+ V_swap( m_pElements, that.m_pElements );
+ V_swap( m_LastAlloc, that.m_LastAlloc );
+ Assert( IsValid() );
+ Assert( m_Elements.IsValidIterator( m_LastAlloc ) || ( m_NumElements == 0 && m_FirstFree == InvalidIndex() ) );
+}
+
+
+#endif // UTLRBTREE_H
diff --git a/external/vpc/public/tier1/utlsortvector.h b/external/vpc/public/tier1/utlsortvector.h
new file mode 100644
index 0000000..c12de27
--- /dev/null
+++ b/external/vpc/public/tier1/utlsortvector.h
@@ -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
diff --git a/external/vpc/public/tier1/utlstack.h b/external/vpc/public/tier1/utlstack.h
new file mode 100644
index 0000000..c7ab48d
--- /dev/null
+++ b/external/vpc/public/tier1/utlstack.h
@@ -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
diff --git a/external/vpc/public/tier1/utlstring.h b/external/vpc/public/tier1/utlstring.h
new file mode 100644
index 0000000..0bd60f0
--- /dev/null
+++ b/external/vpc/public/tier1/utlstring.h
@@ -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
diff --git a/external/vpc/public/tier1/utlsymbol.h b/external/vpc/public/tier1/utlsymbol.h
new file mode 100644
index 0000000..06b8f04
--- /dev/null
+++ b/external/vpc/public/tier1/utlsymbol.h
@@ -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
diff --git a/external/vpc/public/tier1/utlvector.h b/external/vpc/public/tier1/utlvector.h
new file mode 100644
index 0000000..f98698f
--- /dev/null
+++ b/external/vpc/public/tier1/utlvector.h
@@ -0,0 +1,1275 @@
+//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+// A growable array class that maintains a free list and keeps elements
+// in the same location
+//=============================================================================//
+
+#ifndef UTLVECTOR_H
+#define UTLVECTOR_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#include <string.h>
+#include "tier0/platform.h"
+#include "tier0/dbg.h"
+#include "tier0/threadtools.h"
+#include "tier1/utlmemory.h"
+#include "tier1/utlblockmemory.h"
+#include "tier1/strtools.h"
+
+#define FOR_EACH_VEC( vecName, iteratorName ) \
+ for ( int iteratorName = 0; iteratorName < (vecName).Count(); iteratorName++ )
+#define FOR_EACH_VEC_BACK( vecName, iteratorName ) \
+ for ( int iteratorName = (vecName).Count()-1; iteratorName >= 0; iteratorName-- )
+
+//-----------------------------------------------------------------------------
+// The CUtlVector class:
+// A growable array 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 PvRealloc) when elements are inserted or
+// removed. Clients should therefore refer to the elements of the vector
+// by index (they should *never* maintain pointers to elements in the vector).
+//-----------------------------------------------------------------------------
+template< class T, class A = CUtlMemory<T> >
+class CUtlVector
+{
+ typedef A CAllocator;
+public:
+ typedef T ElemType_t;
+
+ // constructor, destructor
+ CUtlVector( int growSize = 0, int initSize = 0 );
+ CUtlVector( T* pMemory, int allocationCount, int numElements = 0 );
+ ~CUtlVector();
+
+ // Copy the array.
+ CUtlVector<T, A>& operator=( const CUtlVector<T, A> &other );
+
+ // element access
+ T& operator[]( int i );
+ const T& operator[]( int i ) const;
+ T& Element( int i );
+ const T& Element( int i ) const;
+ T& Head();
+ const T& Head() const;
+ T& Tail();
+ const T& Tail() const;
+
+ // Gets the base address (can change when adding elements!)
+ T* Base() { return m_Memory.Base(); }
+ const T* Base() const { return m_Memory.Base(); }
+
+ // Returns the number of elements in the vector
+ int Count() const;
+
+ // Is element index valid?
+ bool IsValidIndex( int i ) const;
+ static int InvalidIndex();
+
+ // Adds an element, uses default constructor
+ int AddToHead();
+ int AddToTail();
+ int InsertBefore( int elem );
+ int InsertAfter( int elem );
+
+ // Adds an element, uses copy constructor
+ int AddToHead( const T& src );
+ int AddToTail( const T& src );
+ int InsertBefore( int elem, const T& src );
+ int InsertAfter( int elem, const T& src );
+
+ // Adds multiple elements, uses default constructor
+ int AddMultipleToHead( int num );
+ int AddMultipleToTail( int num );
+ int AddMultipleToTail( int num, const T *pToCopy );
+ int InsertMultipleBefore( int elem, int num );
+ int InsertMultipleBefore( int elem, int num, const T *pToCopy );
+ int InsertMultipleAfter( int elem, int num );
+
+ // Calls RemoveAll() then AddMultipleToTail.
+ void SetSize( int size );
+ void SetCount( int count );
+ void SetCountNonDestructively( int count ); //sets count by adding or removing elements to tail TODO: This should probably be the default behavior for SetCount
+
+ // Calls SetSize and copies each element.
+ void CopyArray( const T *pArray, int size );
+
+ // Fast swap
+ void Swap( CUtlVector< T, A > &vec );
+
+ // Add the specified array to the tail.
+ int AddVectorToTail( CUtlVector<T, A> const &src );
+
+ // Finds an element (element needs operator== defined)
+ int Find( const T& src ) const;
+ void FillWithValue( const T& src );
+
+ bool HasElement( const T& src ) const;
+
+ // Makes sure we have enough memory allocated to store a requested # of elements
+ void EnsureCapacity( int num );
+
+ // Makes sure we have at least this many elements
+ void EnsureCount( int num );
+
+ // Element removal
+ void FastRemove( int elem ); // doesn't preserve order
+ void Remove( int elem ); // preserves order, shifts elements
+ bool FindAndRemove( const T& src ); // removes first occurrence of src, preserves order, shifts elements
+ bool FindAndFastRemove( const T& src ); // removes first occurrence of src, doesn't preserve order
+ void RemoveMultiple( int elem, int num ); // preserves order, shifts elements
+ void RemoveMultipleFromHead(int num); // removes num elements from tail
+ void RemoveMultipleFromTail(int num); // removes num elements from tail
+ void RemoveAll(); // doesn't deallocate memory
+
+ // Memory deallocation
+ void Purge();
+
+ // Purges the list and calls delete on each element in it.
+ void PurgeAndDeleteElements();
+
+ // Compacts the vector to the number of elements actually in use
+ void Compact();
+
+ // Set the size by which it grows when it needs to allocate more memory.
+ void SetGrowSize( int size ) { m_Memory.SetGrowSize( size ); }
+
+ int NumAllocated() const; // Only use this if you really know what you're doing!
+
+ void Sort( int (__cdecl *pfnCompare)(const T *, const T *) );
+
+ // Call this to quickly sort non-contiguously allocated vectors
+ void InPlaceQuickSort( int (__cdecl *pfnCompare)(const T *, const T *) );
+
+#ifdef DBGFLAG_VALIDATE
+ void Validate( CValidator &validator, char *pchName ); // Validate our internal structures
+#endif // DBGFLAG_VALIDATE
+
+protected:
+ // Can't copy this unless we explicitly do it!
+ CUtlVector( CUtlVector const& vec ) { Assert(0); }
+
+ // Grows the vector
+ void GrowVector( int num = 1 );
+
+
+ // Shifts elements....
+ void ShiftElementsRight( int elem, int num = 1 );
+ void ShiftElementsLeft( int elem, int num = 1 );
+
+ CAllocator m_Memory;
+ int m_Size;
+
+#ifndef _X360
+ // For easier access to the elements through the debugger
+ // it's in release builds so this can be used in libraries correctly
+ T *m_pElements;
+
+ inline void ResetDbgInfo()
+ {
+ m_pElements = Base();
+ }
+#else
+ inline void ResetDbgInfo() {}
+#endif
+
+private:
+ void InPlaceQuickSort_r( int (__cdecl *pfnCompare)(const T *, const T *), int nLeft, int nRight );
+};
+
+
+// this is kind of ugly, but until C++ gets templatized typedefs in C++0x, it's our only choice
+template < class T >
+class CUtlBlockVector : public CUtlVector< T, CUtlBlockMemory< T, int > >
+{
+public:
+ CUtlBlockVector( int growSize = 0, int initSize = 0 )
+ : CUtlVector< T, CUtlBlockMemory< T, int > >( growSize, initSize ) {}
+};
+
+//-----------------------------------------------------------------------------
+// The CUtlVectorMT class:
+// An array class with spurious mutex protection. Nothing is actually protected
+// unless you call Lock and Unlock. Also, the Mutex_t is actually not a type
+// but a member which probably isn't used.
+//-----------------------------------------------------------------------------
+
+template< class BASE_UTLVECTOR, class MUTEX_TYPE = CThreadFastMutex >
+class CUtlVectorMT : public BASE_UTLVECTOR, public MUTEX_TYPE
+{
+ typedef BASE_UTLVECTOR BaseClass;
+public:
+ // MUTEX_TYPE Mutex_t;
+
+ // constructor, destructor
+ CUtlVectorMT( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
+ CUtlVectorMT( typename BaseClass::ElemType_t* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
+};
+
+
+//-----------------------------------------------------------------------------
+// The CUtlVectorFixed class:
+// A array class with a fixed allocation scheme
+//-----------------------------------------------------------------------------
+template< class T, size_t MAX_SIZE >
+class CUtlVectorFixed : public CUtlVector< T, CUtlMemoryFixed<T, MAX_SIZE > >
+{
+ typedef CUtlVector< T, CUtlMemoryFixed<T, MAX_SIZE > > BaseClass;
+public:
+
+ // constructor, destructor
+ CUtlVectorFixed( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
+ CUtlVectorFixed( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
+};
+
+
+//-----------------------------------------------------------------------------
+// The CUtlVectorFixedGrowable class:
+// A array class with a fixed allocation scheme backed by a dynamic one
+//-----------------------------------------------------------------------------
+template< class T, size_t MAX_SIZE >
+class CUtlVectorFixedGrowable : public CUtlVector< T, CUtlMemoryFixedGrowable<T, MAX_SIZE > >
+{
+ typedef CUtlVector< T, CUtlMemoryFixedGrowable<T, MAX_SIZE > > BaseClass;
+
+public:
+ // constructor, destructor
+ CUtlVectorFixedGrowable( int growSize = 0 ) : BaseClass( growSize, MAX_SIZE ) {}
+};
+
+
+//-----------------------------------------------------------------------------
+// The CUtlVectorConservative class:
+// A array class with a conservative allocation scheme
+//-----------------------------------------------------------------------------
+template< class T >
+class CUtlVectorConservative : public CUtlVector< T, CUtlMemoryConservative<T> >
+{
+ typedef CUtlVector< T, CUtlMemoryConservative<T> > BaseClass;
+public:
+
+ // constructor, destructor
+ CUtlVectorConservative( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
+ CUtlVectorConservative( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
+};
+
+
+//-----------------------------------------------------------------------------
+// The CUtlVectorUltra Conservative class:
+// A array class with a very conservative allocation scheme, with customizable allocator
+// Especialy useful if you have a lot of vectors that are sparse, or if you're
+// carefully packing holders of vectors
+//-----------------------------------------------------------------------------
+#pragma warning(push)
+#pragma warning(disable : 4200) // warning C4200: nonstandard extension used : zero-sized array in struct/union
+#pragma warning(disable : 4815 ) // warning C4815: 'staticData' : zero-sized array in stack object will have no elements
+
+class CUtlVectorUltraConservativeAllocator
+{
+public:
+ static void *Alloc( size_t nSize )
+ {
+ return malloc( nSize );
+ }
+
+ static void *Realloc( void *pMem, size_t nSize )
+ {
+ return realloc( pMem, nSize );
+ }
+
+ static void Free( void *pMem )
+ {
+ free( pMem );
+ }
+
+ static size_t GetSize( void *pMem )
+ {
+ return mallocsize( pMem );
+ }
+
+};
+
+template <typename T, typename A = CUtlVectorUltraConservativeAllocator >
+class CUtlVectorUltraConservative : private A
+{
+public:
+ CUtlVectorUltraConservative()
+ {
+ m_pData = StaticData();
+ }
+
+ ~CUtlVectorUltraConservative()
+ {
+ RemoveAll();
+ }
+
+ int Count() const
+ {
+ return m_pData->m_Size;
+ }
+
+ static int InvalidIndex()
+ {
+ return -1;
+ }
+
+ inline bool IsValidIndex( int i ) const
+ {
+ return (i >= 0) && (i < Count());
+ }
+
+ T& operator[]( int i )
+ {
+ Assert( IsValidIndex( i ) );
+ return m_pData->m_Elements[i];
+ }
+
+ const T& operator[]( int i ) const
+ {
+ Assert( IsValidIndex( i ) );
+ return m_pData->m_Elements[i];
+ }
+
+ T& Element( int i )
+ {
+ Assert( IsValidIndex( i ) );
+ return m_pData->m_Elements[i];
+ }
+
+ const T& Element( int i ) const
+ {
+ Assert( IsValidIndex( i ) );
+ return m_pData->m_Elements[i];
+ }
+
+ void EnsureCapacity( int num )
+ {
+ int nCurCount = Count();
+ if ( num <= nCurCount )
+ {
+ return;
+ }
+ if ( m_pData == StaticData() )
+ {
+ m_pData = (Data_t *)A::Alloc( sizeof(int) + ( num * sizeof(T) ) );
+ m_pData->m_Size = 0;
+ }
+ else
+ {
+ int nNeeded = sizeof(int) + ( num * sizeof(T) );
+ int nHave = A::GetSize( m_pData );
+ if ( nNeeded > nHave )
+ {
+ m_pData = (Data_t *)A::Realloc( m_pData, nNeeded );
+ }
+ }
+ }
+
+ int AddToTail( const T& src )
+ {
+ int iNew = Count();
+ EnsureCapacity( Count() + 1 );
+ m_pData->m_Elements[iNew] = src;
+ m_pData->m_Size++;
+ return iNew;
+ }
+
+ void RemoveAll()
+ {
+ if ( Count() )
+ {
+ for (int i = m_pData->m_Size; --i >= 0; )
+ {
+ Destruct(&m_pData->m_Elements[i]);
+ }
+ }
+ if ( m_pData != StaticData() )
+ {
+ A::Free( m_pData );
+ m_pData = StaticData();
+
+ }
+ }
+
+ void PurgeAndDeleteElements()
+ {
+ if ( m_pData != StaticData() )
+ {
+ for( int i=0; i < m_pData->m_Size; i++ )
+ {
+ delete Element(i);
+ }
+ RemoveAll();
+ }
+ }
+
+ void FastRemove( int elem )
+ {
+ Assert( IsValidIndex(elem) );
+
+ Destruct( &Element(elem) );
+ if (Count() > 0)
+ {
+ if ( elem != m_pData->m_Size -1 )
+ memcpy( &Element(elem), &Element(m_pData->m_Size-1), sizeof(T) );
+ --m_pData->m_Size;
+ }
+ if ( !m_pData->m_Size )
+ {
+ A::Free( m_pData );
+ m_pData = StaticData();
+ }
+ }
+
+ void Remove( int elem )
+ {
+ Destruct( &Element(elem) );
+ ShiftElementsLeft(elem);
+ --m_pData->m_Size;
+ if ( !m_pData->m_Size )
+ {
+ A::Free( m_pData );
+ m_pData = StaticData();
+ }
+ }
+
+ int Find( const T& src ) const
+ {
+ int nCount = Count();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ if (Element(i) == src)
+ return i;
+ }
+ return -1;
+ }
+
+ bool FindAndRemove( const T& src )
+ {
+ int elem = Find( src );
+ if ( elem != -1 )
+ {
+ Remove( elem );
+ return true;
+ }
+ return false;
+ }
+
+
+ bool FindAndFastRemove( const T& src )
+ {
+ int elem = Find( src );
+ if ( elem != -1 )
+ {
+ FastRemove( elem );
+ return true;
+ }
+ return false;
+ }
+
+ struct Data_t
+ {
+ int m_Size;
+ T m_Elements[];
+ };
+
+ Data_t *m_pData;
+private:
+ void ShiftElementsLeft( int elem, int num = 1 )
+ {
+ int Size = Count();
+ Assert( IsValidIndex(elem) || ( Size == 0 ) || ( num == 0 ));
+ int numToMove = Size - elem - num;
+ if ((numToMove > 0) && (num > 0))
+ {
+ V_memmove( &Element(elem), &Element(elem+num), numToMove * sizeof(T) );
+
+#ifdef _DEBUG
+ V_memset( &Element(Size-num), 0xDD, num * sizeof(T) );
+#endif
+ }
+ }
+
+
+
+ static Data_t *StaticData()
+ {
+ static Data_t staticData;
+ Assert( staticData.m_Size == 0 );
+ return &staticData;
+ }
+};
+
+#pragma warning(pop)
+
+
+//-----------------------------------------------------------------------------
+// The CCopyableUtlVector class:
+// A array class that allows copy construction (so you can nest a CUtlVector inside of another one of our containers)
+// WARNING - this class lets you copy construct which can be an expensive operation if you don't carefully control when it happens
+// Only use this when nesting a CUtlVector() inside of another one of our container classes (i.e a CUtlMap)
+//-----------------------------------------------------------------------------
+template< class T >
+class CCopyableUtlVector : public CUtlVector< T, CUtlMemory<T> >
+{
+ typedef CUtlVector< T, CUtlMemory<T> > BaseClass;
+public:
+ CCopyableUtlVector( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
+ CCopyableUtlVector( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
+ virtual ~CCopyableUtlVector() {}
+ CCopyableUtlVector( CCopyableUtlVector const& vec ) { CopyArray( vec.Base(), vec.Count() ); }
+};
+
+// TODO (Ilya): It seems like all the functions in CUtlVector are simple enough that they should be inlined.
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+inline CUtlVector<T, A>::CUtlVector( int growSize, int initSize ) :
+ m_Memory(growSize, initSize), m_Size(0)
+{
+ ResetDbgInfo();
+}
+
+template< typename T, class A >
+inline CUtlVector<T, A>::CUtlVector( T* pMemory, int allocationCount, int numElements ) :
+ m_Memory(pMemory, allocationCount), m_Size(numElements)
+{
+ ResetDbgInfo();
+}
+
+template< typename T, class A >
+inline CUtlVector<T, A>::~CUtlVector()
+{
+ Purge();
+}
+
+template< typename T, class A >
+inline CUtlVector<T, A>& CUtlVector<T, A>::operator=( const CUtlVector<T, A> &other )
+{
+ int nCount = other.Count();
+ SetSize( nCount );
+ for ( int i = 0; i < nCount; i++ )
+ {
+ (*this)[ i ] = other[ i ];
+ }
+ return *this;
+}
+
+
+//-----------------------------------------------------------------------------
+// element access
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+inline T& CUtlVector<T, A>::operator[]( int i )
+{
+ Assert( i < m_Size );
+ return m_Memory[ i ];
+}
+
+template< typename T, class A >
+inline const T& CUtlVector<T, A>::operator[]( int i ) const
+{
+ Assert( i < m_Size );
+ return m_Memory[ i ];
+}
+
+template< typename T, class A >
+inline T& CUtlVector<T, A>::Element( int i )
+{
+ Assert( i < m_Size );
+ return m_Memory[ i ];
+}
+
+template< typename T, class A >
+inline const T& CUtlVector<T, A>::Element( int i ) const
+{
+ Assert( i < m_Size );
+ return m_Memory[ i ];
+}
+
+template< typename T, class A >
+inline T& CUtlVector<T, A>::Head()
+{
+ Assert( m_Size > 0 );
+ return m_Memory[ 0 ];
+}
+
+template< typename T, class A >
+inline const T& CUtlVector<T, A>::Head() const
+{
+ Assert( m_Size > 0 );
+ return m_Memory[ 0 ];
+}
+
+template< typename T, class A >
+inline T& CUtlVector<T, A>::Tail()
+{
+ Assert( m_Size > 0 );
+ return m_Memory[ m_Size - 1 ];
+}
+
+template< typename T, class A >
+inline const T& CUtlVector<T, A>::Tail() const
+{
+ Assert( m_Size > 0 );
+ return m_Memory[ m_Size - 1 ];
+}
+
+
+//-----------------------------------------------------------------------------
+// Count
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+inline int CUtlVector<T, A>::Count() const
+{
+ return m_Size;
+}
+
+
+//-----------------------------------------------------------------------------
+// Is element index valid?
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+inline bool CUtlVector<T, A>::IsValidIndex( int i ) const
+{
+ return (i >= 0) && (i < m_Size);
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns in invalid index
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+inline int CUtlVector<T, A>::InvalidIndex()
+{
+ return -1;
+}
+
+
+//-----------------------------------------------------------------------------
+// Grows the vector
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+void CUtlVector<T, A>::GrowVector( int num )
+{
+ if (m_Size + num > m_Memory.NumAllocated())
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ m_Memory.Grow( m_Size + num - m_Memory.NumAllocated() );
+ }
+
+ m_Size += num;
+ ResetDbgInfo();
+}
+
+
+//-----------------------------------------------------------------------------
+// Sorts the vector
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+void CUtlVector<T, A>::Sort( int (__cdecl *pfnCompare)(const T *, const T *) )
+{
+ typedef int (__cdecl *QSortCompareFunc_t)(const void *, const void *);
+ if ( Count() <= 1 )
+ return;
+
+ if ( Base() )
+ {
+ qsort( Base(), Count(), sizeof(T), (QSortCompareFunc_t)(pfnCompare) );
+ }
+ else
+ {
+ Assert( 0 );
+ // this path is untested
+ // if you want to sort vectors that use a non-sequential memory allocator,
+ // you'll probably want to patch in a quicksort algorithm here
+ // I just threw in this bubble sort to have something just in case...
+
+ for ( int i = m_Size - 1; i >= 0; --i )
+ {
+ for ( int j = 1; j <= i; ++j )
+ {
+ if ( pfnCompare( &Element( j - 1 ), &Element( j ) ) < 0 )
+ {
+ V_swap( Element( j - 1 ), Element( j ) );
+ }
+ }
+ }
+ }
+}
+
+
+//----------------------------------------------------------------------------------------------
+// Private function that does the in-place quicksort for non-contiguously allocated vectors.
+//----------------------------------------------------------------------------------------------
+template< typename T, class A >
+void CUtlVector<T, A>::InPlaceQuickSort_r( int (__cdecl *pfnCompare)(const T *, const T *), int nLeft, int nRight )
+{
+ int nPivot;
+ int nLeftIdx = nLeft;
+ int nRightIdx = nRight;
+
+ if ( nRight - nLeft > 0 )
+ {
+ nPivot = ( nLeft + nRight ) / 2;
+
+ while ( ( nLeftIdx <= nPivot ) && ( nRightIdx >= nPivot ) )
+ {
+ while ( ( pfnCompare( &Element( nLeftIdx ), &Element( nPivot ) ) < 0 ) && ( nLeftIdx <= nPivot ) )
+ {
+ nLeftIdx++;
+ }
+
+ while ( ( pfnCompare( &Element( nRightIdx ), &Element( nPivot ) ) > 0 ) && ( nRightIdx >= nPivot ) )
+ {
+ nRightIdx--;
+ }
+
+ V_swap( Element( nLeftIdx ), Element( nRightIdx ) );
+
+ nLeftIdx++;
+ nRightIdx--;
+
+ if ( ( nLeftIdx - 1 ) == nPivot )
+ {
+ nPivot = nRightIdx = nRightIdx + 1;
+ }
+ else if ( nRightIdx + 1 == nPivot )
+ {
+ nPivot = nLeftIdx = nLeftIdx - 1;
+ }
+ }
+
+ InPlaceQuickSort_r( pfnCompare, nLeft, nPivot - 1 );
+ InPlaceQuickSort_r( pfnCompare, nPivot + 1, nRight );
+ }
+}
+
+
+//----------------------------------------------------------------------------------------------
+// Call this to quickly sort non-contiguously allocated vectors. Sort uses a slower bubble sort.
+//----------------------------------------------------------------------------------------------
+template< typename T, class A >
+void CUtlVector<T, A>::InPlaceQuickSort( int (__cdecl *pfnCompare)(const T *, const T *) )
+{
+ InPlaceQuickSort_r( pfnCompare, 0, Count() - 1 );
+}
+
+
+//-----------------------------------------------------------------------------
+// Makes sure we have enough memory allocated to store a requested # of elements
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+void CUtlVector<T, A>::EnsureCapacity( int num )
+{
+ MEM_ALLOC_CREDIT_CLASS();
+ m_Memory.EnsureCapacity(num);
+ ResetDbgInfo();
+}
+
+
+//-----------------------------------------------------------------------------
+// Makes sure we have at least this many elements
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+void CUtlVector<T, A>::EnsureCount( int num )
+{
+ if (Count() < num)
+ {
+ AddMultipleToTail( num - Count() );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Shifts elements
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+void CUtlVector<T, A>::ShiftElementsRight( int elem, int num )
+{
+ Assert( IsValidIndex(elem) || ( m_Size == 0 ) || ( num == 0 ));
+ int numToMove = m_Size - elem - num;
+ if ((numToMove > 0) && (num > 0))
+ V_memmove( &Element(elem+num), &Element(elem), numToMove * sizeof(T) );
+}
+
+template< typename T, class A >
+void CUtlVector<T, A>::ShiftElementsLeft( int elem, int num )
+{
+ Assert( IsValidIndex(elem) || ( m_Size == 0 ) || ( num == 0 ));
+ int numToMove = m_Size - elem - num;
+ if ((numToMove > 0) && (num > 0))
+ {
+ V_memmove( &Element(elem), &Element(elem+num), numToMove * sizeof(T) );
+
+#ifdef _DEBUG
+ V_memset( &Element(m_Size-num), 0xDD, num * sizeof(T) );
+#endif
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Adds an element, uses default constructor
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+inline int CUtlVector<T, A>::AddToHead()
+{
+ return InsertBefore(0);
+}
+
+template< typename T, class A >
+inline int CUtlVector<T, A>::AddToTail()
+{
+ return InsertBefore( m_Size );
+}
+
+template< typename T, class A >
+inline int CUtlVector<T, A>::InsertAfter( int elem )
+{
+ return InsertBefore( elem + 1 );
+}
+
+template< typename T, class A >
+int CUtlVector<T, A>::InsertBefore( int elem )
+{
+ // Can insert at the end
+ Assert( (elem == Count()) || IsValidIndex(elem) );
+
+ GrowVector();
+ ShiftElementsRight(elem);
+ Construct( &Element(elem) );
+ return elem;
+}
+
+
+//-----------------------------------------------------------------------------
+// Adds an element, uses copy constructor
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+inline int CUtlVector<T, A>::AddToHead( const T& src )
+{
+ // Can't insert something that's in the list... reallocation may hose us
+ Assert( (Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count()) ) );
+ return InsertBefore( 0, src );
+}
+
+template< typename T, class A >
+inline int CUtlVector<T, A>::AddToTail( const T& src )
+{
+ // Can't insert something that's in the list... reallocation may hose us
+ Assert( (Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count()) ) );
+ return InsertBefore( m_Size, src );
+}
+
+template< typename T, class A >
+inline int CUtlVector<T, A>::InsertAfter( int elem, const T& src )
+{
+ // Can't insert something that's in the list... reallocation may hose us
+ Assert( (Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count()) ) );
+ return InsertBefore( elem + 1, src );
+}
+
+template< typename T, class A >
+int CUtlVector<T, A>::InsertBefore( int elem, const T& src )
+{
+ // Can't insert something that's in the list... reallocation may hose us
+ Assert( (Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count()) ) );
+
+ // Can insert at the end
+ Assert( (elem == Count()) || IsValidIndex(elem) );
+
+ GrowVector();
+ ShiftElementsRight(elem);
+ CopyConstruct( &Element(elem), src );
+ return elem;
+}
+
+
+//-----------------------------------------------------------------------------
+// Adds multiple elements, uses default constructor
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+inline int CUtlVector<T, A>::AddMultipleToHead( int num )
+{
+ return InsertMultipleBefore( 0, num );
+}
+
+template< typename T, class A >
+inline int CUtlVector<T, A>::AddMultipleToTail( int num )
+{
+ return InsertMultipleBefore( m_Size, num );
+}
+
+template< typename T, class A >
+inline int CUtlVector<T, A>::AddMultipleToTail( int num, const T *pToCopy )
+{
+ // Can't insert something that's in the list... reallocation may hose us
+ Assert( (Base() == NULL) || !pToCopy || (pToCopy + num <= Base()) || (pToCopy >= (Base() + Count()) ) );
+
+ return InsertMultipleBefore( m_Size, num, pToCopy );
+}
+
+template< typename T, class A >
+int CUtlVector<T, A>::InsertMultipleAfter( int elem, int num )
+{
+ return InsertMultipleBefore( elem + 1, num );
+}
+
+
+template< typename T, class A >
+void CUtlVector<T, A>::SetCount( int count )
+{
+ RemoveAll();
+ AddMultipleToTail( count );
+}
+
+template< typename T, class A >
+inline void CUtlVector<T, A>::SetSize( int size )
+{
+ SetCount( size );
+}
+
+template< typename T, class A >
+void CUtlVector<T, A>::SetCountNonDestructively( int count )
+{
+ int delta = count - m_Size;
+ if(delta > 0) AddMultipleToTail( delta );
+ else if(delta < 0) RemoveMultipleFromTail( -delta );
+}
+
+template< typename T, class A >
+void CUtlVector<T, A>::CopyArray( const T *pArray, int size )
+{
+ // Can't insert something that's in the list... reallocation may hose us
+ Assert( (Base() == NULL) || !pArray || (Base() >= (pArray + size)) || (pArray >= (Base() + Count()) ) );
+
+ SetSize( size );
+ for( int i=0; i < size; i++ )
+ {
+ (*this)[i] = pArray[i];
+ }
+}
+
+template< typename T, class A >
+void CUtlVector<T, A>::Swap( CUtlVector< T, A > &vec )
+{
+ m_Memory.Swap( vec.m_Memory );
+ V_swap( m_Size, vec.m_Size );
+#ifndef _X360
+ V_swap( m_pElements, vec.m_pElements );
+#endif
+}
+
+template< typename T, class A >
+int CUtlVector<T, A>::AddVectorToTail( CUtlVector const &src )
+{
+ Assert( &src != this );
+
+ int base = Count();
+
+ // Make space.
+ int nSrcCount = src.Count();
+ EnsureCapacity( base + nSrcCount );
+
+ // Copy the elements.
+ m_Size += nSrcCount;
+ for ( int i=0; i < nSrcCount; i++ )
+ {
+ CopyConstruct( &Element(base+i), src[i] );
+ }
+ return base;
+}
+
+template< typename T, class A >
+inline int CUtlVector<T, A>::InsertMultipleBefore( int elem, int num )
+{
+ if( num == 0 )
+ return elem;
+
+ // Can insert at the end
+ Assert( (elem == Count()) || IsValidIndex(elem) );
+
+ GrowVector(num);
+ ShiftElementsRight( elem, num );
+
+ // Invoke default constructors
+ for (int i = 0; i < num; ++i )
+ {
+ Construct( &Element( elem+i ) );
+ }
+
+ return elem;
+}
+
+template< typename T, class A >
+inline int CUtlVector<T, A>::InsertMultipleBefore( int elem, int num, const T *pToInsert )
+{
+ if( num == 0 )
+ return elem;
+
+ // Can insert at the end
+ Assert( (elem == Count()) || IsValidIndex(elem) );
+
+ GrowVector(num);
+ ShiftElementsRight( elem, num );
+
+ // Invoke default constructors
+ if ( !pToInsert )
+ {
+ for (int i = 0; i < num; ++i )
+ {
+ Construct( &Element( elem+i ) );
+ }
+ }
+ else
+ {
+ for ( int i=0; i < num; i++ )
+ {
+ CopyConstruct( &Element( elem+i ), pToInsert[i] );
+ }
+ }
+
+ return elem;
+}
+
+
+//-----------------------------------------------------------------------------
+// Finds an element (element needs operator== defined)
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+int CUtlVector<T, A>::Find( const T& src ) const
+{
+ for ( int i = 0; i < Count(); ++i )
+ {
+ if (Element(i) == src)
+ return i;
+ }
+ return -1;
+}
+
+template< typename T, class A >
+void CUtlVector<T, A>::FillWithValue( const T& src )
+{
+ for ( int i = 0; i < Count(); i++ )
+ {
+ Element(i) = src;
+ }
+}
+
+template< typename T, class A >
+bool CUtlVector<T, A>::HasElement( const T& src ) const
+{
+ return ( Find(src) >= 0 );
+}
+
+
+//-----------------------------------------------------------------------------
+// Element removal
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+void CUtlVector<T, A>::FastRemove( int elem )
+{
+ Assert( IsValidIndex(elem) );
+
+ Destruct( &Element(elem) );
+ if (m_Size > 0)
+ {
+ if ( elem != m_Size -1 )
+ memcpy( &Element(elem), &Element(m_Size-1), sizeof(T) );
+ --m_Size;
+ }
+}
+
+template< typename T, class A >
+void CUtlVector<T, A>::Remove( int elem )
+{
+ Destruct( &Element(elem) );
+ ShiftElementsLeft(elem);
+ --m_Size;
+}
+
+template< typename T, class A >
+bool CUtlVector<T, A>::FindAndRemove( const T& src )
+{
+ int elem = Find( src );
+ if ( elem != -1 )
+ {
+ Remove( elem );
+ return true;
+ }
+ return false;
+}
+
+template< typename T, class A >
+bool CUtlVector<T, A>::FindAndFastRemove( const T& src )
+{
+ int elem = Find( src );
+ if ( elem != -1 )
+ {
+ FastRemove( elem );
+ return true;
+ }
+ return false;
+}
+
+template< typename T, class A >
+void CUtlVector<T, A>::RemoveMultiple( int elem, int num )
+{
+ Assert( elem >= 0 );
+ Assert( elem + num <= Count() );
+
+ for (int i = elem + num; --i >= elem; )
+ Destruct(&Element(i));
+
+ ShiftElementsLeft(elem, num);
+ m_Size -= num;
+}
+
+template< typename T, class A >
+void CUtlVector<T, A>::RemoveMultipleFromHead( int num )
+{
+ Assert( num <= Count() );
+
+ for (int i = num; --i >= 0; )
+ Destruct(&Element(i));
+
+ ShiftElementsLeft(0, num);
+ m_Size -= num;
+}
+
+template< typename T, class A >
+void CUtlVector<T, A>::RemoveMultipleFromTail( int num )
+{
+ Assert( num <= Count() );
+
+ for (int i = m_Size-num; i < m_Size; i++)
+ Destruct(&Element(i));
+
+ m_Size -= num;
+}
+
+template< typename T, class A >
+void CUtlVector<T, A>::RemoveAll()
+{
+ for (int i = m_Size; --i >= 0; )
+ {
+ Destruct(&Element(i));
+ }
+
+ m_Size = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Memory deallocation
+//-----------------------------------------------------------------------------
+
+template< typename T, class A >
+inline void CUtlVector<T, A>::Purge()
+{
+ RemoveAll();
+ m_Memory.Purge();
+ ResetDbgInfo();
+}
+
+
+template< typename T, class A >
+inline void CUtlVector<T, A>::PurgeAndDeleteElements()
+{
+ for( int i=0; i < m_Size; i++ )
+ {
+ delete Element(i);
+ }
+ Purge();
+}
+
+template< typename T, class A >
+inline void CUtlVector<T, A>::Compact()
+{
+ m_Memory.Purge(m_Size);
+}
+
+template< typename T, class A >
+inline int CUtlVector<T, A>::NumAllocated() const
+{
+ return m_Memory.NumAllocated();
+}
+
+
+//-----------------------------------------------------------------------------
+// Data and memory validation
+//-----------------------------------------------------------------------------
+#ifdef DBGFLAG_VALIDATE
+template< typename T, class A >
+void CUtlVector<T, A>::Validate( CValidator &validator, char *pchName )
+{
+ validator.Push( typeid(*this).name(), this, pchName );
+
+ m_Memory.Validate( validator, "m_Memory" );
+
+ validator.Pop();
+}
+#endif // DBGFLAG_VALIDATE
+
+// A vector class for storing pointers, so that the elements pointed to by the pointers are deleted
+// on exit.
+template<class T> class CUtlVectorAutoPurge : public CUtlVector< T, CUtlMemory< T, int> >
+{
+public:
+ ~CUtlVectorAutoPurge( void )
+ {
+ this->PurgeAndDeleteElements();
+ }
+
+};
+
+// easy string list class with dynamically allocated strings. For use with V_SplitString, etc.
+// Frees the dynamic strings in destructor.
+class CUtlStringList : public CUtlVectorAutoPurge< char *>
+{
+public:
+ void CopyAndAddToTail( char const *pString ) // clone the string and add to the end
+ {
+ char *pNewStr = new char[1 + strlen( pString )];
+ V_strcpy( pNewStr, pString );
+ AddToTail( pNewStr );
+ }
+
+ static int __cdecl SortFunc( char * const * sz1, char * const * sz2 )
+ {
+ return strcmp( *sz1, *sz2 );
+ }
+
+};
+
+
+
+// <Sergiy> placing it here a few days before Cert to minimize disruption to the rest of codebase
+class CSplitString: public CUtlVector<char*, CUtlMemory<char*, int> >
+{
+public:
+ CSplitString(const char *pString, const char *pSeparator);
+ CSplitString(const char *pString, const char **pSeparators, int nSeparators);
+ ~CSplitString();
+ //
+ // NOTE: If you want to make Construct() public and implement Purge() here, you'll have to free m_szBuffer there
+ //
+private:
+ void Construct(const char *pString, const char **pSeparators, int nSeparators);
+ void PurgeAndDeleteElements();
+private:
+ char *m_szBuffer; // a copy of original string, with '\0' instead of separators
+};
+
+
+#endif // CCVECTOR_H