aboutsummaryrefslogtreecommitdiff
path: root/mp/src/public/tier1
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /mp/src/public/tier1
parentMark some more files as text. (diff)
downloadsource-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz
source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/public/tier1')
-rw-r--r--mp/src/public/tier1/CommandBuffer.h334
-rw-r--r--mp/src/public/tier1/KeyValues.h954
-rw-r--r--mp/src/public/tier1/UtlSortVector.h642
-rw-r--r--mp/src/public/tier1/UtlStringMap.h198
-rw-r--r--mp/src/public/tier1/bitbuf.h1618
-rw-r--r--mp/src/public/tier1/byteswap.h498
-rw-r--r--mp/src/public/tier1/callqueue.h406
-rw-r--r--mp/src/public/tier1/characterset.h86
-rw-r--r--mp/src/public/tier1/checksum_crc.h62
-rw-r--r--mp/src/public/tier1/checksum_md5.h124
-rw-r--r--mp/src/public/tier1/checksum_sha1.h348
-rw-r--r--mp/src/public/tier1/convar.h1344
-rw-r--r--mp/src/public/tier1/convar_serverbounded.h106
-rw-r--r--mp/src/public/tier1/datamanager.h554
-rw-r--r--mp/src/public/tier1/delegates.h198
-rw-r--r--mp/src/public/tier1/diff.h58
-rw-r--r--mp/src/public/tier1/fileio.h202
-rw-r--r--mp/src/public/tier1/fmtstr.h404
-rw-r--r--mp/src/public/tier1/functors.h1274
-rw-r--r--mp/src/public/tier1/generichash.h232
-rw-r--r--mp/src/public/tier1/iconvar.h236
-rw-r--r--mp/src/public/tier1/ilocalize.h848
-rw-r--r--mp/src/public/tier1/interface.h460
-rw-r--r--mp/src/public/tier1/kvpacker.h98
-rw-r--r--mp/src/public/tier1/lzmaDecoder.h82
-rw-r--r--mp/src/public/tier1/lzss.h138
-rw-r--r--mp/src/public/tier1/mempool.h1102
-rw-r--r--mp/src/public/tier1/memstack.h414
-rw-r--r--mp/src/public/tier1/netadr.h136
-rw-r--r--mp/src/public/tier1/passwordhash.h188
-rw-r--r--mp/src/public/tier1/processor_detect.h24
-rw-r--r--mp/src/public/tier1/rangecheckedvar.h236
-rw-r--r--mp/src/public/tier1/refcount.h770
-rw-r--r--mp/src/public/tier1/reliabletimer.h366
-rw-r--r--mp/src/public/tier1/smartptr.h558
-rw-r--r--mp/src/public/tier1/snappy-sinksource.h272
-rw-r--r--mp/src/public/tier1/snappy.h344
-rw-r--r--mp/src/public/tier1/sparsematrix.h246
-rw-r--r--mp/src/public/tier1/stringpool.h182
-rw-r--r--mp/src/public/tier1/strtools.h1694
-rw-r--r--mp/src/public/tier1/thash.h1396
-rw-r--r--mp/src/public/tier1/tier1.h212
-rw-r--r--mp/src/public/tier1/tokenreader.h198
-rw-r--r--mp/src/public/tier1/uniqueid.h112
-rw-r--r--mp/src/public/tier1/utlallocation.h268
-rw-r--r--mp/src/public/tier1/utlarray.h598
-rw-r--r--mp/src/public/tier1/utlbidirectionalset.h788
-rw-r--r--mp/src/public/tier1/utlblockmemory.h698
-rw-r--r--mp/src/public/tier1/utlbuffer.h2168
-rw-r--r--mp/src/public/tier1/utlbufferutil.h384
-rw-r--r--mp/src/public/tier1/utlcommon.h690
-rw-r--r--mp/src/public/tier1/utldelegate.h194
-rw-r--r--mp/src/public/tier1/utldelegateimpl.h5312
-rw-r--r--mp/src/public/tier1/utldict.h716
-rw-r--r--mp/src/public/tier1/utlenvelope.h482
-rw-r--r--mp/src/public/tier1/utlfixedmemory.h708
-rw-r--r--mp/src/public/tier1/utlflags.h248
-rw-r--r--mp/src/public/tier1/utlhandletable.h1172
-rw-r--r--mp/src/public/tier1/utlhash.h1872
-rw-r--r--mp/src/public/tier1/utlhashdict.h684
-rw-r--r--mp/src/public/tier1/utlhashtable.h1888
-rw-r--r--mp/src/public/tier1/utlintrusivelist.h1776
-rw-r--r--mp/src/public/tier1/utllinkedlist.h2572
-rw-r--r--mp/src/public/tier1/utlmap.h504
-rw-r--r--mp/src/public/tier1/utlmemory.h2154
-rw-r--r--mp/src/public/tier1/utlmovingaverage.h206
-rw-r--r--mp/src/public/tier1/utlmultilist.h1538
-rw-r--r--mp/src/public/tier1/utlntree.h1248
-rw-r--r--mp/src/public/tier1/utlobjectreference.h330
-rw-r--r--mp/src/public/tier1/utlpriorityqueue.h396
-rw-r--r--mp/src/public/tier1/utlqueue.h228
-rw-r--r--mp/src/public/tier1/utlrbtree.h3176
-rw-r--r--mp/src/public/tier1/utlsoacontainer.h668
-rw-r--r--mp/src/public/tier1/utlstack.h660
-rw-r--r--mp/src/public/tier1/utlstring.h802
-rw-r--r--mp/src/public/tier1/utlsymbol.h538
-rw-r--r--mp/src/public/tier1/utlsymbollarge.h998
-rw-r--r--mp/src/public/tier1/utltshash.h1250
-rw-r--r--mp/src/public/tier1/utlvector.h2420
79 files changed, 30144 insertions, 30144 deletions
diff --git a/mp/src/public/tier1/CommandBuffer.h b/mp/src/public/tier1/CommandBuffer.h
index 95971c12..d9bfd7de 100644
--- a/mp/src/public/tier1/CommandBuffer.h
+++ b/mp/src/public/tier1/CommandBuffer.h
@@ -1,167 +1,167 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $Workfile: $
-// $Date: $
-// $NoKeywords: $
-//===========================================================================//
-
-
-#ifndef COMMANDBUFFER_H
-#define COMMANDBUFFER_H
-
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include "tier1/utllinkedlist.h"
-#include "tier1/convar.h"
-
-
-//-----------------------------------------------------------------------------
-// Forward declarations
-//-----------------------------------------------------------------------------
-class CUtlBuffer;
-
-
-//-----------------------------------------------------------------------------
-// Invalid command handle
-//-----------------------------------------------------------------------------
-typedef int CommandHandle_t;
-enum
-{
- COMMAND_BUFFER_INVALID_COMMAND_HANDLE = 0
-};
-
-
-//-----------------------------------------------------------------------------
-// A command buffer class- a queue of argc/argv based commands associated
-// with a particular time
-//-----------------------------------------------------------------------------
-class CCommandBuffer
-{
-public:
- // Constructor, destructor
- CCommandBuffer( );
- ~CCommandBuffer();
-
- // Inserts text into the command buffer
- bool AddText( const char *pText, int nTickDelay = 0 );
-
- // Used to iterate over all commands appropriate for the current time
- void BeginProcessingCommands( int nDeltaTicks );
- bool DequeueNextCommand( );
- int DequeueNextCommand( const char **& ppArgv );
- 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 CCommand& GetCommand() const;
- void EndProcessingCommands();
-
- // Are we in the middle of processing commands?
- bool IsProcessingCommands();
-
- // Delays all queued commands to execute at a later time
- void DelayAllQueuedCommands( int nTickDelay );
-
- // Indicates how long to delay when encoutering a 'wait' command
- void SetWaitDelayTime( int nTickDelay );
-
- // Returns a handle to the next command to process
- // (useful when inserting commands into the buffer during processing
- // of commands to force immediate execution of those commands,
- // most relevantly, to implement a feature where you stream a file
- // worth of commands into the buffer, where the file size is too large
- // to entirely contain in the buffer).
- CommandHandle_t GetNextCommandHandle();
-
- // Specifies a max limit of the args buffer. For unittesting. Size == 0 means use default
- void LimitArgumentBufferSize( int nSize );
-
- void SetWaitEnabled( bool bEnable ) { m_bWaitEnabled = bEnable; }
- bool IsWaitEnabled( void ) { return m_bWaitEnabled; }
-
- int GetArgumentBufferSize() { return m_nArgSBufferSize; }
- int GetMaxArgumentBufferSize() { return m_nMaxArgSBufferLength; }
-
-private:
- enum
- {
- ARGS_BUFFER_LENGTH = 8192,
- };
-
- struct Command_t
- {
- int m_nTick;
- int m_nFirstArgS;
- int m_nBufferSize;
- };
-
- // Insert a command into the command queue at the appropriate time
- void InsertCommandAtAppropriateTime( int hCommand );
-
- // Insert a command into the command queue
- // Only happens if it's inserted while processing other commands
- void InsertImmediateCommand( int hCommand );
-
- // Insert a command into the command queue
- bool InsertCommand( const char *pArgS, int nCommandSize, int nTick );
-
- // Returns the length of the next command, as well as the offset to the next command
- void GetNextCommandLength( const char *pText, int nMaxLen, int *pCommandLength, int *pNextCommandOffset );
-
- // Compacts the command buffer
- void Compact();
-
- // Parses argv0 out of the buffer
- bool ParseArgV0( CUtlBuffer &buf, char *pArgv0, int nMaxLen, const char **pArgs );
-
- char m_pArgSBuffer[ ARGS_BUFFER_LENGTH ];
- int m_nLastUsedArgSSize;
- int m_nArgSBufferSize;
- CUtlFixedLinkedList< Command_t > m_Commands;
- int m_nCurrentTick;
- int m_nLastTickToProcess;
- int m_nWaitDelayTicks;
- int m_hNextCommand;
- int m_nMaxArgSBufferLength;
- bool m_bIsProcessingCommands;
- bool m_bWaitEnabled;
-
- // NOTE: This is here to avoid the pointers returned by DequeueNextCommand
- // to become invalid by calling AddText. Is there a way we can avoid the memcpy?
- CCommand m_CurrentCommand;
-};
-
-
-//-----------------------------------------------------------------------------
-// Returns the next command
-//-----------------------------------------------------------------------------
-inline int CCommandBuffer::ArgC() const
-{
- return m_CurrentCommand.ArgC();
-}
-
-inline const char **CCommandBuffer::ArgV() const
-{
- return m_CurrentCommand.ArgV();
-}
-
-inline const char *CCommandBuffer::ArgS() const
-{
- return m_CurrentCommand.ArgS();
-}
-
-inline const char *CCommandBuffer::GetCommandString() const
-{
- return m_CurrentCommand.GetCommandString();
-}
-
-inline const CCommand& CCommandBuffer::GetCommand() const
-{
- return m_CurrentCommand;
-}
-
-#endif // COMMANDBUFFER_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $Workfile: $
+// $Date: $
+// $NoKeywords: $
+//===========================================================================//
+
+
+#ifndef COMMANDBUFFER_H
+#define COMMANDBUFFER_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier1/utllinkedlist.h"
+#include "tier1/convar.h"
+
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+class CUtlBuffer;
+
+
+//-----------------------------------------------------------------------------
+// Invalid command handle
+//-----------------------------------------------------------------------------
+typedef int CommandHandle_t;
+enum
+{
+ COMMAND_BUFFER_INVALID_COMMAND_HANDLE = 0
+};
+
+
+//-----------------------------------------------------------------------------
+// A command buffer class- a queue of argc/argv based commands associated
+// with a particular time
+//-----------------------------------------------------------------------------
+class CCommandBuffer
+{
+public:
+ // Constructor, destructor
+ CCommandBuffer( );
+ ~CCommandBuffer();
+
+ // Inserts text into the command buffer
+ bool AddText( const char *pText, int nTickDelay = 0 );
+
+ // Used to iterate over all commands appropriate for the current time
+ void BeginProcessingCommands( int nDeltaTicks );
+ bool DequeueNextCommand( );
+ int DequeueNextCommand( const char **& ppArgv );
+ 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 CCommand& GetCommand() const;
+ void EndProcessingCommands();
+
+ // Are we in the middle of processing commands?
+ bool IsProcessingCommands();
+
+ // Delays all queued commands to execute at a later time
+ void DelayAllQueuedCommands( int nTickDelay );
+
+ // Indicates how long to delay when encoutering a 'wait' command
+ void SetWaitDelayTime( int nTickDelay );
+
+ // Returns a handle to the next command to process
+ // (useful when inserting commands into the buffer during processing
+ // of commands to force immediate execution of those commands,
+ // most relevantly, to implement a feature where you stream a file
+ // worth of commands into the buffer, where the file size is too large
+ // to entirely contain in the buffer).
+ CommandHandle_t GetNextCommandHandle();
+
+ // Specifies a max limit of the args buffer. For unittesting. Size == 0 means use default
+ void LimitArgumentBufferSize( int nSize );
+
+ void SetWaitEnabled( bool bEnable ) { m_bWaitEnabled = bEnable; }
+ bool IsWaitEnabled( void ) { return m_bWaitEnabled; }
+
+ int GetArgumentBufferSize() { return m_nArgSBufferSize; }
+ int GetMaxArgumentBufferSize() { return m_nMaxArgSBufferLength; }
+
+private:
+ enum
+ {
+ ARGS_BUFFER_LENGTH = 8192,
+ };
+
+ struct Command_t
+ {
+ int m_nTick;
+ int m_nFirstArgS;
+ int m_nBufferSize;
+ };
+
+ // Insert a command into the command queue at the appropriate time
+ void InsertCommandAtAppropriateTime( int hCommand );
+
+ // Insert a command into the command queue
+ // Only happens if it's inserted while processing other commands
+ void InsertImmediateCommand( int hCommand );
+
+ // Insert a command into the command queue
+ bool InsertCommand( const char *pArgS, int nCommandSize, int nTick );
+
+ // Returns the length of the next command, as well as the offset to the next command
+ void GetNextCommandLength( const char *pText, int nMaxLen, int *pCommandLength, int *pNextCommandOffset );
+
+ // Compacts the command buffer
+ void Compact();
+
+ // Parses argv0 out of the buffer
+ bool ParseArgV0( CUtlBuffer &buf, char *pArgv0, int nMaxLen, const char **pArgs );
+
+ char m_pArgSBuffer[ ARGS_BUFFER_LENGTH ];
+ int m_nLastUsedArgSSize;
+ int m_nArgSBufferSize;
+ CUtlFixedLinkedList< Command_t > m_Commands;
+ int m_nCurrentTick;
+ int m_nLastTickToProcess;
+ int m_nWaitDelayTicks;
+ int m_hNextCommand;
+ int m_nMaxArgSBufferLength;
+ bool m_bIsProcessingCommands;
+ bool m_bWaitEnabled;
+
+ // NOTE: This is here to avoid the pointers returned by DequeueNextCommand
+ // to become invalid by calling AddText. Is there a way we can avoid the memcpy?
+ CCommand m_CurrentCommand;
+};
+
+
+//-----------------------------------------------------------------------------
+// Returns the next command
+//-----------------------------------------------------------------------------
+inline int CCommandBuffer::ArgC() const
+{
+ return m_CurrentCommand.ArgC();
+}
+
+inline const char **CCommandBuffer::ArgV() const
+{
+ return m_CurrentCommand.ArgV();
+}
+
+inline const char *CCommandBuffer::ArgS() const
+{
+ return m_CurrentCommand.ArgS();
+}
+
+inline const char *CCommandBuffer::GetCommandString() const
+{
+ return m_CurrentCommand.GetCommandString();
+}
+
+inline const CCommand& CCommandBuffer::GetCommand() const
+{
+ return m_CurrentCommand;
+}
+
+#endif // COMMANDBUFFER_H
diff --git a/mp/src/public/tier1/KeyValues.h b/mp/src/public/tier1/KeyValues.h
index 2d46e377..67b2f012 100644
--- a/mp/src/public/tier1/KeyValues.h
+++ b/mp/src/public/tier1/KeyValues.h
@@ -1,477 +1,477 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//=============================================================================//
-
-#ifndef KEYVALUES_H
-#define KEYVALUES_H
-
-#ifdef _WIN32
-#pragma once
-#endif
-
-// #include <vgui/VGUI.h>
-
-#ifndef NULL
-#ifdef __cplusplus
-#define NULL 0
-#else
-#define NULL ((void *)0)
-#endif
-#endif
-
-#include "utlvector.h"
-#include "Color.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;
-typedef void * FileHandle_t;
-class CKeyValuesGrowableStringTable;
-
-//-----------------------------------------------------------------------------
-// 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 );
-
- 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).
- // You can also pass temporary KeyValues object as an argument to a function by wrapping it into KeyValues::AutoDelete
- // instance: call_my_function( KeyValues::AutoDelete( new KeyValues( "test" ) ) )
- //
- 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
- KeyValues *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 { return m_iKeyName; }
-
- // File access. Set UsesEscapeSequences true, if resource file/buffer uses Escape Sequences (eg \n, \t)
- void UsesEscapeSequences(bool state); // default false
- void UsesConditionals(bool state); // default true
- bool LoadFromFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL );
- bool SaveToFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL, bool sortKeys = false, bool bAllowEmptyString = false );
-
- // 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 );
-
- // Read from a utlbuffer...
- bool LoadFromBuffer( char const *resourceName, CUtlBuffer &buf, IBaseFileSystem* pFileSystem = NULL, const char *pPathID = 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
-
- // 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() { return m_pSub; } // returns the first subkey in the list
- KeyValues *GetNextKey() { return m_pPeer; } // returns the next subkey
- void SetNextKey( KeyValues * pDat);
- KeyValues *FindLastSubKey(); // returns the LAST subkey in the list. This requires a linked list iteration to find the key. Returns NULL if we don't have any children
-
- //
- // 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 );
- bool GetBool( const char *keyName = NULL, bool defaultValue = false );
- Color GetColor( const char *keyName = NULL /* default value is all black */);
- bool IsEmpty(const char *keyName = NULL);
-
- // Data access
- int GetInt( int keySymbol, int 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 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 sortKeys = false, bool bAllowEmptyString = false );
-
- bool WriteAsBinary( CUtlBuffer &buffer );
- bool ReadAsBinary( CUtlBuffer &buffer, int nStackDepth = 0 );
-
- // 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_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, size_t DestSizeInBytes );
-
- // Process conditional keys for widescreen support.
- bool ProcessResolutionKeys( const char *pResString );
-
- // Dump keyvalues recursively into a dump context
- bool Dump( class IKeyValuesDumpContext *pDump, int nIndentLevel = 0 );
-
- // Merge in another KeyValues, keeping "our" settings
- void RecursiveMergeKeyValues( KeyValues *baseKV );
-
-private:
- KeyValues( KeyValues& ); // prevent copy constructor being used
-
- // prevent delete being called except through deleteThis()
- ~KeyValues();
-
- KeyValues* CreateKey( const char *keyName );
-
- /// Create a child key, given that we know which child is currently the last child.
- /// This avoids the O(N^2) behaviour when adding children in sequence to KV,
- /// when CreateKey() wil have to re-locate the end of the list each time. This happens,
- /// for example, every time we load any KV file whatsoever.
- KeyValues* CreateKeyUsingKnownLastChild( const char *keyName, KeyValues *pLastChild );
- void AddSubkeyUsingKnownLastChild( KeyValues *pSubKey, KeyValues *pLastChild );
-
- 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, bool sortKeys, bool bAllowEmptyString );
- void SaveKeyToFile( KeyValues *dat, IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, int indentLevel, bool sortKeys, bool bAllowEmptyString );
- void WriteConvertedString( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, const char *pszString );
-
- void RecursiveLoadFromBuffer( char const *resourceName, CUtlBuffer &buf );
-
- // 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 );
-
- // For handling #base "filename"
- void MergeBaseKeys( CUtlVector< KeyValues * >& baseKeys );
-
- // 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);
-
- int m_iKeyName; // keyname is a symbol defined in KeyValuesSystem
-
- // 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)
- char m_bEvaluateConditionals; // true, if while parsing this KeyValue, conditionals blocks are evaluated (default true)
- char unused[1];
-
- 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
-
-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 );
-
- // Functions to get external access to whichever of the above functions we're going to call.
- static int CallGetSymbolForString( const char *name, bool bCreate = true ) { return s_pfGetSymbolForString( name, bCreate ); }
- static const char *CallGetStringForSymbol( int symbol ) { return s_pfGetStringForSymbol( 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 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;
-}
-
-bool EvaluateConditional( const char *str );
-
-class CUtlSortVectorKeyValuesByName
-{
-public:
- bool Less( const KeyValues* lhs, const KeyValues* rhs, void * )
- {
- return Q_stricmp( lhs->GetName(), rhs->GetName() ) < 0;
- }
-};
-
-//
-// 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
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef KEYVALUES_H
+#define KEYVALUES_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+// #include <vgui/VGUI.h>
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+#include "utlvector.h"
+#include "Color.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;
+typedef void * FileHandle_t;
+class CKeyValuesGrowableStringTable;
+
+//-----------------------------------------------------------------------------
+// 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 );
+
+ 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).
+ // You can also pass temporary KeyValues object as an argument to a function by wrapping it into KeyValues::AutoDelete
+ // instance: call_my_function( KeyValues::AutoDelete( new KeyValues( "test" ) ) )
+ //
+ 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
+ KeyValues *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 { return m_iKeyName; }
+
+ // File access. Set UsesEscapeSequences true, if resource file/buffer uses Escape Sequences (eg \n, \t)
+ void UsesEscapeSequences(bool state); // default false
+ void UsesConditionals(bool state); // default true
+ bool LoadFromFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL );
+ bool SaveToFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL, bool sortKeys = false, bool bAllowEmptyString = false );
+
+ // 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 );
+
+ // Read from a utlbuffer...
+ bool LoadFromBuffer( char const *resourceName, CUtlBuffer &buf, IBaseFileSystem* pFileSystem = NULL, const char *pPathID = 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
+
+ // 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() { return m_pSub; } // returns the first subkey in the list
+ KeyValues *GetNextKey() { return m_pPeer; } // returns the next subkey
+ void SetNextKey( KeyValues * pDat);
+ KeyValues *FindLastSubKey(); // returns the LAST subkey in the list. This requires a linked list iteration to find the key. Returns NULL if we don't have any children
+
+ //
+ // 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 );
+ bool GetBool( const char *keyName = NULL, bool defaultValue = false );
+ Color GetColor( const char *keyName = NULL /* default value is all black */);
+ bool IsEmpty(const char *keyName = NULL);
+
+ // Data access
+ int GetInt( int keySymbol, int 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 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 sortKeys = false, bool bAllowEmptyString = false );
+
+ bool WriteAsBinary( CUtlBuffer &buffer );
+ bool ReadAsBinary( CUtlBuffer &buffer, int nStackDepth = 0 );
+
+ // 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_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, size_t DestSizeInBytes );
+
+ // Process conditional keys for widescreen support.
+ bool ProcessResolutionKeys( const char *pResString );
+
+ // Dump keyvalues recursively into a dump context
+ bool Dump( class IKeyValuesDumpContext *pDump, int nIndentLevel = 0 );
+
+ // Merge in another KeyValues, keeping "our" settings
+ void RecursiveMergeKeyValues( KeyValues *baseKV );
+
+private:
+ KeyValues( KeyValues& ); // prevent copy constructor being used
+
+ // prevent delete being called except through deleteThis()
+ ~KeyValues();
+
+ KeyValues* CreateKey( const char *keyName );
+
+ /// Create a child key, given that we know which child is currently the last child.
+ /// This avoids the O(N^2) behaviour when adding children in sequence to KV,
+ /// when CreateKey() wil have to re-locate the end of the list each time. This happens,
+ /// for example, every time we load any KV file whatsoever.
+ KeyValues* CreateKeyUsingKnownLastChild( const char *keyName, KeyValues *pLastChild );
+ void AddSubkeyUsingKnownLastChild( KeyValues *pSubKey, KeyValues *pLastChild );
+
+ 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, bool sortKeys, bool bAllowEmptyString );
+ void SaveKeyToFile( KeyValues *dat, IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, int indentLevel, bool sortKeys, bool bAllowEmptyString );
+ void WriteConvertedString( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, const char *pszString );
+
+ void RecursiveLoadFromBuffer( char const *resourceName, CUtlBuffer &buf );
+
+ // 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 );
+
+ // For handling #base "filename"
+ void MergeBaseKeys( CUtlVector< KeyValues * >& baseKeys );
+
+ // 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);
+
+ int m_iKeyName; // keyname is a symbol defined in KeyValuesSystem
+
+ // 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)
+ char m_bEvaluateConditionals; // true, if while parsing this KeyValue, conditionals blocks are evaluated (default true)
+ char unused[1];
+
+ 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
+
+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 );
+
+ // Functions to get external access to whichever of the above functions we're going to call.
+ static int CallGetSymbolForString( const char *name, bool bCreate = true ) { return s_pfGetSymbolForString( name, bCreate ); }
+ static const char *CallGetStringForSymbol( int symbol ) { return s_pfGetStringForSymbol( 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 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;
+}
+
+bool EvaluateConditional( const char *str );
+
+class CUtlSortVectorKeyValuesByName
+{
+public:
+ bool Less( const KeyValues* lhs, const KeyValues* rhs, void * )
+ {
+ return Q_stricmp( lhs->GetName(), rhs->GetName() ) < 0;
+ }
+};
+
+//
+// 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/mp/src/public/tier1/UtlSortVector.h b/mp/src/public/tier1/UtlSortVector.h
index ec7d972d..76026925 100644
--- a/mp/src/public/tier1/UtlSortVector.h
+++ b/mp/src/public/tier1/UtlSortVector.h
@@ -1,321 +1,321 @@
-//========= Copyright 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;
-
- // 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>
-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
+//========= Copyright 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;
+
+ // 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>
+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/mp/src/public/tier1/UtlStringMap.h b/mp/src/public/tier1/UtlStringMap.h
index e4b64229..59d5c23f 100644
--- a/mp/src/public/tier1/UtlStringMap.h
+++ b/mp/src/public/tier1/UtlStringMap.h
@@ -1,99 +1,99 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-//===========================================================================//
-
-#ifndef UTLSTRINGMAP_H
-#define UTLSTRINGMAP_H
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include "utlsymbol.h"
-
-template <class T>
-class CUtlStringMap
-{
-public:
- CUtlStringMap( bool caseInsensitive = true ) : m_SymbolTable( 0, 32, caseInsensitive )
- {
- }
-
- // Get data by the string itself:
- T& operator[]( const char *pString )
- {
- CUtlSymbol symbol = m_SymbolTable.AddString( pString );
- int index = ( int )( UtlSymId_t )symbol;
- if( m_Vector.Count() <= index )
- {
- m_Vector.EnsureCount( index + 1 );
- }
- return m_Vector[index];
- }
-
- // Get data by the string's symbol table ID - only used to retrieve a pre-existing symbol, not create a new one!
- T& operator[]( UtlSymId_t n )
- {
- Assert( n >=0 && n <= m_Vector.Count() );
- return m_Vector[n];
- }
-
- const T& operator[]( UtlSymId_t n ) const
- {
- Assert( n >=0 && n <= m_Vector.Count() );
- return m_Vector[n];
- }
-
- bool Defined( const char *pString ) const
- {
- return m_SymbolTable.Find( pString ) != UTL_INVAL_SYMBOL;
- }
-
- UtlSymId_t Find( const char *pString ) const
- {
- return m_SymbolTable.Find( pString );
- }
-
- static UtlSymId_t InvalidIndex()
- {
- return UTL_INVAL_SYMBOL;
- }
-
- int GetNumStrings( void ) const
- {
- return m_SymbolTable.GetNumStrings();
- }
-
- const char *String( int n ) const
- {
- return m_SymbolTable.String( n );
- }
-
- // Clear all of the data from the map
- void Clear()
- {
- m_Vector.RemoveAll();
- m_SymbolTable.RemoveAll();
- }
-
- void Purge()
- {
- m_Vector.Purge();
- m_SymbolTable.RemoveAll();
- }
-
- void PurgeAndDeleteElements()
- {
- m_Vector.PurgeAndDeleteElements();
- m_SymbolTable.RemoveAll();
- }
-
-
-
-private:
- CUtlVector<T> m_Vector;
- CUtlSymbolTable m_SymbolTable;
-};
-
-#endif // UTLSTRINGMAP_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//===========================================================================//
+
+#ifndef UTLSTRINGMAP_H
+#define UTLSTRINGMAP_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "utlsymbol.h"
+
+template <class T>
+class CUtlStringMap
+{
+public:
+ CUtlStringMap( bool caseInsensitive = true ) : m_SymbolTable( 0, 32, caseInsensitive )
+ {
+ }
+
+ // Get data by the string itself:
+ T& operator[]( const char *pString )
+ {
+ CUtlSymbol symbol = m_SymbolTable.AddString( pString );
+ int index = ( int )( UtlSymId_t )symbol;
+ if( m_Vector.Count() <= index )
+ {
+ m_Vector.EnsureCount( index + 1 );
+ }
+ return m_Vector[index];
+ }
+
+ // Get data by the string's symbol table ID - only used to retrieve a pre-existing symbol, not create a new one!
+ T& operator[]( UtlSymId_t n )
+ {
+ Assert( n >=0 && n <= m_Vector.Count() );
+ return m_Vector[n];
+ }
+
+ const T& operator[]( UtlSymId_t n ) const
+ {
+ Assert( n >=0 && n <= m_Vector.Count() );
+ return m_Vector[n];
+ }
+
+ bool Defined( const char *pString ) const
+ {
+ return m_SymbolTable.Find( pString ) != UTL_INVAL_SYMBOL;
+ }
+
+ UtlSymId_t Find( const char *pString ) const
+ {
+ return m_SymbolTable.Find( pString );
+ }
+
+ static UtlSymId_t InvalidIndex()
+ {
+ return UTL_INVAL_SYMBOL;
+ }
+
+ int GetNumStrings( void ) const
+ {
+ return m_SymbolTable.GetNumStrings();
+ }
+
+ const char *String( int n ) const
+ {
+ return m_SymbolTable.String( n );
+ }
+
+ // Clear all of the data from the map
+ void Clear()
+ {
+ m_Vector.RemoveAll();
+ m_SymbolTable.RemoveAll();
+ }
+
+ void Purge()
+ {
+ m_Vector.Purge();
+ m_SymbolTable.RemoveAll();
+ }
+
+ void PurgeAndDeleteElements()
+ {
+ m_Vector.PurgeAndDeleteElements();
+ m_SymbolTable.RemoveAll();
+ }
+
+
+
+private:
+ CUtlVector<T> m_Vector;
+ CUtlSymbolTable m_SymbolTable;
+};
+
+#endif // UTLSTRINGMAP_H
diff --git a/mp/src/public/tier1/bitbuf.h b/mp/src/public/tier1/bitbuf.h
index b47d80d5..b92e010c 100644
--- a/mp/src/public/tier1/bitbuf.h
+++ b/mp/src/public/tier1/bitbuf.h
@@ -1,809 +1,809 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//
-//=============================================================================//
-
-// NOTE: bf_read is guaranteed to return zeros if it overflows.
-
-#ifndef BITBUF_H
-#define BITBUF_H
-
-#ifdef _WIN32
-#pragma once
-#endif
-
-
-#include "mathlib/mathlib.h"
-#include "mathlib/vector.h"
-#include "basetypes.h"
-#include "tier0/dbg.h"
-
-
-#if _DEBUG
-#define BITBUF_INLINE inline
-#else
-#define BITBUF_INLINE FORCEINLINE
-#endif
-
-//-----------------------------------------------------------------------------
-// Forward declarations.
-//-----------------------------------------------------------------------------
-
-class Vector;
-class QAngle;
-
-//-----------------------------------------------------------------------------
-// You can define a handler function that will be called in case of
-// out-of-range values and overruns here.
-//
-// NOTE: the handler is only called in debug mode.
-//
-// Call SetBitBufErrorHandler to install a handler.
-//-----------------------------------------------------------------------------
-
-typedef enum
-{
- BITBUFERROR_VALUE_OUT_OF_RANGE=0, // Tried to write a value with too few bits.
- BITBUFERROR_BUFFER_OVERRUN, // Was about to overrun a buffer.
-
- BITBUFERROR_NUM_ERRORS
-} BitBufErrorType;
-
-
-typedef void (*BitBufErrorHandler)( BitBufErrorType errorType, const char *pDebugName );
-
-
-#if defined( _DEBUG )
- extern void InternalBitBufErrorHandler( BitBufErrorType errorType, const char *pDebugName );
- #define CallErrorHandler( errorType, pDebugName ) InternalBitBufErrorHandler( errorType, pDebugName );
-#else
- #define CallErrorHandler( errorType, pDebugName )
-#endif
-
-
-// Use this to install the error handler. Call with NULL to uninstall your error handler.
-void SetBitBufErrorHandler( BitBufErrorHandler fn );
-
-
-//-----------------------------------------------------------------------------
-// Helpers.
-//-----------------------------------------------------------------------------
-
-inline int BitByte( int bits )
-{
- // return PAD_NUMBER( bits, 8 ) >> 3;
- return (bits + 7) >> 3;
-}
-
-//-----------------------------------------------------------------------------
-// namespaced helpers
-//-----------------------------------------------------------------------------
-namespace bitbuf
-{
- // ZigZag Transform: Encodes signed integers so that they can be
- // effectively used with varint encoding.
- //
- // varint operates on unsigned integers, encoding smaller numbers into
- // fewer bytes. If you try to use it on a signed integer, it will treat
- // this number as a very large unsigned integer, which means that even
- // small signed numbers like -1 will take the maximum number of bytes
- // (10) to encode. ZigZagEncode() maps signed integers to unsigned
- // in such a way that those with a small absolute value will have smaller
- // encoded values, making them appropriate for encoding using varint.
- //
- // int32 -> uint32
- // -------------------------
- // 0 -> 0
- // -1 -> 1
- // 1 -> 2
- // -2 -> 3
- // ... -> ...
- // 2147483647 -> 4294967294
- // -2147483648 -> 4294967295
- //
- // >> encode >>
- // << decode <<
-
- inline uint32 ZigZagEncode32(int32 n)
- {
- // Note: the right-shift must be arithmetic
- return(n << 1) ^ (n >> 31);
- }
-
- inline int32 ZigZagDecode32(uint32 n)
- {
- return(n >> 1) ^ -static_cast<int32>(n & 1);
- }
-
- inline uint64 ZigZagEncode64(int64 n)
- {
- // Note: the right-shift must be arithmetic
- return(n << 1) ^ (n >> 63);
- }
-
- inline int64 ZigZagDecode64(uint64 n)
- {
- return(n >> 1) ^ -static_cast<int64>(n & 1);
- }
-
- const int kMaxVarintBytes = 10;
- const int kMaxVarint32Bytes = 5;
-}
-
-//-----------------------------------------------------------------------------
-// Used for serialization
-//-----------------------------------------------------------------------------
-
-class bf_write
-{
-public:
- bf_write();
-
- // nMaxBits can be used as the number of bits in the buffer.
- // It must be <= nBytes*8. If you leave it at -1, then it's set to nBytes * 8.
- bf_write( void *pData, int nBytes, int nMaxBits = -1 );
- bf_write( const char *pDebugName, void *pData, int nBytes, int nMaxBits = -1 );
-
- // Start writing to the specified buffer.
- // nMaxBits can be used as the number of bits in the buffer.
- // It must be <= nBytes*8. If you leave it at -1, then it's set to nBytes * 8.
- void StartWriting( void *pData, int nBytes, int iStartBit = 0, int nMaxBits = -1 );
-
- // Restart buffer writing.
- void Reset();
-
- // Get the base pointer.
- unsigned char* GetBasePointer() { return (unsigned char*) m_pData; }
-
- // Enable or disable assertion on overflow. 99% of the time, it's a bug that we need to catch,
- // but there may be the occasional buffer that is allowed to overflow gracefully.
- void SetAssertOnOverflow( bool bAssert );
-
- // This can be set to assign a name that gets output if the buffer overflows.
- const char* GetDebugName();
- void SetDebugName( const char *pDebugName );
-
-
-// Seek to a specific position.
-public:
-
- void SeekToBit( int bitPos );
-
-
-// Bit functions.
-public:
-
- void WriteOneBit(int nValue);
- void WriteOneBitNoCheck(int nValue);
- void WriteOneBitAt( int iBit, int nValue );
-
- // Write signed or unsigned. Range is only checked in debug.
- void WriteUBitLong( unsigned int data, int numbits, bool bCheckRange=true );
- void WriteSBitLong( int data, int numbits );
-
- // Tell it whether or not the data is unsigned. If it's signed,
- // cast to unsigned before passing in (it will cast back inside).
- void WriteBitLong(unsigned int data, int numbits, bool bSigned);
-
- // Write a list of bits in.
- bool WriteBits(const void *pIn, int nBits);
-
- // writes an unsigned integer with variable bit length
- void WriteUBitVar( unsigned int data );
-
- // writes a varint encoded integer
- void WriteVarInt32( uint32 data );
- void WriteVarInt64( uint64 data );
- void WriteSignedVarInt32( int32 data );
- void WriteSignedVarInt64( int64 data );
- int ByteSizeVarInt32( uint32 data );
- int ByteSizeVarInt64( uint64 data );
- int ByteSizeSignedVarInt32( int32 data );
- int ByteSizeSignedVarInt64( int64 data );
-
- // Copy the bits straight out of pIn. This seeks pIn forward by nBits.
- // Returns an error if this buffer or the read buffer overflows.
- bool WriteBitsFromBuffer( class bf_read *pIn, int nBits );
-
- void WriteBitAngle( float fAngle, int numbits );
- void WriteBitCoord (const float f);
- void WriteBitCoordMP( const float f, bool bIntegral, bool bLowPrecision );
- void WriteBitFloat(float val);
- void WriteBitVec3Coord( const Vector& fa );
- void WriteBitNormal( float f );
- void WriteBitVec3Normal( const Vector& fa );
- void WriteBitAngles( const QAngle& fa );
-
-
-// Byte functions.
-public:
-
- void WriteChar(int val);
- void WriteByte(int val);
- void WriteShort(int val);
- void WriteWord(int val);
- void WriteLong(long val);
- void WriteLongLong(int64 val);
- void WriteFloat(float val);
- bool WriteBytes( const void *pBuf, int nBytes );
-
- // Returns false if it overflows the buffer.
- bool WriteString(const char *pStr);
-
-
-// Status.
-public:
-
- // How many bytes are filled in?
- int GetNumBytesWritten() const;
- int GetNumBitsWritten() const;
- int GetMaxNumBits();
- int GetNumBitsLeft();
- int GetNumBytesLeft();
- unsigned char* GetData();
- const unsigned char* GetData() const;
-
- // Has the buffer overflowed?
- bool CheckForOverflow(int nBits);
- inline bool IsOverflowed() const {return m_bOverflow;}
-
- void SetOverflowFlag();
-
-
-public:
- // The current buffer.
- unsigned long* RESTRICT m_pData;
- int m_nDataBytes;
- int m_nDataBits;
-
- // Where we are in the buffer.
- int m_iCurBit;
-
-private:
-
- // Errors?
- bool m_bOverflow;
-
- bool m_bAssertOnOverflow;
- const char *m_pDebugName;
-};
-
-
-//-----------------------------------------------------------------------------
-// Inlined methods
-//-----------------------------------------------------------------------------
-
-// How many bytes are filled in?
-inline int bf_write::GetNumBytesWritten() const
-{
- return BitByte(m_iCurBit);
-}
-
-inline int bf_write::GetNumBitsWritten() const
-{
- return m_iCurBit;
-}
-
-inline int bf_write::GetMaxNumBits()
-{
- return m_nDataBits;
-}
-
-inline int bf_write::GetNumBitsLeft()
-{
- return m_nDataBits - m_iCurBit;
-}
-
-inline int bf_write::GetNumBytesLeft()
-{
- return GetNumBitsLeft() >> 3;
-}
-
-inline unsigned char* bf_write::GetData()
-{
- return (unsigned char*) m_pData;
-}
-
-inline const unsigned char* bf_write::GetData() const
-{
- return (unsigned char*) m_pData;
-}
-
-BITBUF_INLINE bool bf_write::CheckForOverflow(int nBits)
-{
- if ( m_iCurBit + nBits > m_nDataBits )
- {
- SetOverflowFlag();
- CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
- }
-
- return m_bOverflow;
-}
-
-BITBUF_INLINE void bf_write::SetOverflowFlag()
-{
-#ifdef DBGFLAG_ASSERT
- if ( m_bAssertOnOverflow )
- {
- Assert( false );
- }
-#endif
- m_bOverflow = true;
-}
-
-BITBUF_INLINE void bf_write::WriteOneBitNoCheck(int nValue)
-{
-#if __i386__
- if(nValue)
- m_pData[m_iCurBit >> 5] |= 1u << (m_iCurBit & 31);
- else
- m_pData[m_iCurBit >> 5] &= ~(1u << (m_iCurBit & 31));
-#else
- extern unsigned long g_LittleBits[32];
- if(nValue)
- m_pData[m_iCurBit >> 5] |= g_LittleBits[m_iCurBit & 31];
- else
- m_pData[m_iCurBit >> 5] &= ~g_LittleBits[m_iCurBit & 31];
-#endif
-
- ++m_iCurBit;
-}
-
-inline void bf_write::WriteOneBit(int nValue)
-{
- if( m_iCurBit >= m_nDataBits )
- {
- SetOverflowFlag();
- CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
- return;
- }
- WriteOneBitNoCheck( nValue );
-}
-
-
-inline void bf_write::WriteOneBitAt( int iBit, int nValue )
-{
- if( iBit >= m_nDataBits )
- {
- SetOverflowFlag();
- CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
- return;
- }
-
-#if __i386__
- if(nValue)
- m_pData[iBit >> 5] |= 1u << (iBit & 31);
- else
- m_pData[iBit >> 5] &= ~(1u << (iBit & 31));
-#else
- extern unsigned long g_LittleBits[32];
- if(nValue)
- m_pData[iBit >> 5] |= g_LittleBits[iBit & 31];
- else
- m_pData[iBit >> 5] &= ~g_LittleBits[iBit & 31];
-#endif
-}
-
-BITBUF_INLINE void bf_write::WriteUBitLong( unsigned int curData, int numbits, bool bCheckRange ) RESTRICT
-{
-#ifdef _DEBUG
- // Make sure it doesn't overflow.
- if ( bCheckRange && numbits < 32 )
- {
- if ( curData >= (unsigned long)(1 << numbits) )
- {
- CallErrorHandler( BITBUFERROR_VALUE_OUT_OF_RANGE, GetDebugName() );
- }
- }
- Assert( numbits >= 0 && numbits <= 32 );
-#endif
-
- if ( GetNumBitsLeft() < numbits )
- {
- m_iCurBit = m_nDataBits;
- SetOverflowFlag();
- CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
- return;
- }
-
- int iCurBitMasked = m_iCurBit & 31;
- int iDWord = m_iCurBit >> 5;
- m_iCurBit += numbits;
-
- // Mask in a dword.
- Assert( (iDWord*4 + sizeof(long)) <= (unsigned int)m_nDataBytes );
- unsigned long * RESTRICT pOut = &m_pData[iDWord];
-
- // Rotate data into dword alignment
- curData = (curData << iCurBitMasked) | (curData >> (32 - iCurBitMasked));
-
- // Calculate bitmasks for first and second word
- unsigned int temp = 1 << (numbits-1);
- unsigned int mask1 = (temp*2-1) << iCurBitMasked;
- unsigned int mask2 = (temp-1) >> (31 - iCurBitMasked);
-
- // Only look beyond current word if necessary (avoid access violation)
- int i = mask2 & 1;
- unsigned long dword1 = LoadLittleDWord( pOut, 0 );
- unsigned long dword2 = LoadLittleDWord( pOut, i );
-
- // Drop bits into place
- dword1 ^= ( mask1 & ( curData ^ dword1 ) );
- dword2 ^= ( mask2 & ( curData ^ dword2 ) );
-
- // Note reversed order of writes so that dword1 wins if mask2 == 0 && i == 0
- StoreLittleDWord( pOut, i, dword2 );
- StoreLittleDWord( pOut, 0, dword1 );
-}
-
-// writes an unsigned integer with variable bit length
-BITBUF_INLINE void bf_write::WriteUBitVar( unsigned int data )
-{
- /* Reference:
- if ( data < 0x10u )
- WriteUBitLong( 0, 2 ), WriteUBitLong( data, 4 );
- else if ( data < 0x100u )
- WriteUBitLong( 1, 2 ), WriteUBitLong( data, 8 );
- else if ( data < 0x1000u )
- WriteUBitLong( 2, 2 ), WriteUBitLong( data, 12 );
- else
- WriteUBitLong( 3, 2 ), WriteUBitLong( data, 32 );
- */
- // a < b ? -1 : 0 translates into a CMP, SBB instruction pair
- // with no flow control. should also be branchless on consoles.
- int n = (data < 0x10u ? -1 : 0) + (data < 0x100u ? -1 : 0) + (data < 0x1000u ? -1 : 0);
- WriteUBitLong( data*4 + n + 3, 6 + n*4 + 12 );
- if ( data >= 0x1000u )
- {
- WriteUBitLong( data >> 16, 16 );
- }
-}
-
-// write raw IEEE float bits in little endian form
-BITBUF_INLINE void bf_write::WriteBitFloat(float val)
-{
- long intVal;
-
- Assert(sizeof(long) == sizeof(float));
- Assert(sizeof(float) == 4);
-
- intVal = *((long*)&val);
- WriteUBitLong( intVal, 32 );
-}
-
-//-----------------------------------------------------------------------------
-// This is useful if you just want a buffer to write into on the stack.
-//-----------------------------------------------------------------------------
-
-template<int SIZE>
-class old_bf_write_static : public bf_write
-{
-public:
- inline old_bf_write_static() : bf_write(m_StaticData, SIZE) {}
-
- char m_StaticData[SIZE];
-};
-
-
-
-//-----------------------------------------------------------------------------
-// Used for unserialization
-//-----------------------------------------------------------------------------
-
-class bf_read
-{
-public:
- bf_read();
-
- // nMaxBits can be used as the number of bits in the buffer.
- // It must be <= nBytes*8. If you leave it at -1, then it's set to nBytes * 8.
- bf_read( const void *pData, int nBytes, int nBits = -1 );
- bf_read( const char *pDebugName, const void *pData, int nBytes, int nBits = -1 );
-
- // Start reading from the specified buffer.
- // pData's start address must be dword-aligned.
- // nMaxBits can be used as the number of bits in the buffer.
- // It must be <= nBytes*8. If you leave it at -1, then it's set to nBytes * 8.
- void StartReading( const void *pData, int nBytes, int iStartBit = 0, int nBits = -1 );
-
- // Restart buffer reading.
- void Reset();
-
- // Enable or disable assertion on overflow. 99% of the time, it's a bug that we need to catch,
- // but there may be the occasional buffer that is allowed to overflow gracefully.
- void SetAssertOnOverflow( bool bAssert );
-
- // This can be set to assign a name that gets output if the buffer overflows.
- const char* GetDebugName() const { return m_pDebugName; }
- void SetDebugName( const char *pName );
-
- void ExciseBits( int startbit, int bitstoremove );
-
-
-// Bit functions.
-public:
-
- // Returns 0 or 1.
- int ReadOneBit();
-
-
-protected:
-
- unsigned int CheckReadUBitLong(int numbits); // For debugging.
- int ReadOneBitNoCheck(); // Faster version, doesn't check bounds and is inlined.
- bool CheckForOverflow(int nBits);
-
-
-public:
-
- // Get the base pointer.
- const unsigned char* GetBasePointer() { return m_pData; }
-
- BITBUF_INLINE int TotalBytesAvailable( void ) const
- {
- return m_nDataBytes;
- }
-
- // Read a list of bits in.
- void ReadBits(void *pOut, int nBits);
- // Read a list of bits in, but don't overrun the destination buffer.
- // Returns the number of bits read into the buffer. The remaining
- // bits are skipped over.
- int ReadBitsClamped_ptr(void *pOut, size_t outSizeBytes, size_t nBits);
- // Helper 'safe' template function that infers the size of the destination
- // array. This version of the function should be preferred.
- // Usage: char databuffer[100];
- // ReadBitsClamped( dataBuffer, msg->m_nLength );
- template <typename T, size_t N>
- int ReadBitsClamped( T (&pOut)[N], size_t nBits )
- {
- return ReadBitsClamped_ptr( pOut, N * sizeof(T), nBits );
- }
-
- float ReadBitAngle( int numbits );
-
- unsigned int ReadUBitLong( int numbits ) RESTRICT;
- unsigned int ReadUBitLongNoInline( int numbits ) RESTRICT;
- unsigned int PeekUBitLong( int numbits );
- int ReadSBitLong( int numbits );
-
- // reads an unsigned integer with variable bit length
- unsigned int ReadUBitVar();
- unsigned int ReadUBitVarInternal( int encodingType );
-
- // reads a varint encoded integer
- uint32 ReadVarInt32();
- uint64 ReadVarInt64();
- int32 ReadSignedVarInt32();
- int64 ReadSignedVarInt64();
-
- // You can read signed or unsigned data with this, just cast to
- // a signed int if necessary.
- unsigned int ReadBitLong(int numbits, bool bSigned);
-
- float ReadBitCoord();
- float ReadBitCoordMP( bool bIntegral, bool bLowPrecision );
- float ReadBitFloat();
- float ReadBitNormal();
- void ReadBitVec3Coord( Vector& fa );
- void ReadBitVec3Normal( Vector& fa );
- void ReadBitAngles( QAngle& fa );
-
- // Faster for comparisons but do not fully decode float values
- unsigned int ReadBitCoordBits();
- unsigned int ReadBitCoordMPBits( bool bIntegral, bool bLowPrecision );
-
-// Byte functions (these still read data in bit-by-bit).
-public:
-
- BITBUF_INLINE int ReadChar() { return (char)ReadUBitLong(8); }
- BITBUF_INLINE int ReadByte() { return ReadUBitLong(8); }
- BITBUF_INLINE int ReadShort() { return (short)ReadUBitLong(16); }
- BITBUF_INLINE int ReadWord() { return ReadUBitLong(16); }
- BITBUF_INLINE long ReadLong() { return ReadUBitLong(32); }
- int64 ReadLongLong();
- float ReadFloat();
- bool ReadBytes(void *pOut, int nBytes);
-
- // Returns false if bufLen isn't large enough to hold the
- // string in the buffer.
- //
- // Always reads to the end of the string (so you can read the
- // next piece of data waiting).
- //
- // If bLine is true, it stops when it reaches a '\n' or a null-terminator.
- //
- // pStr is always null-terminated (unless bufLen is 0).
- //
- // pOutNumChars is set to the number of characters left in pStr when the routine is
- // complete (this will never exceed bufLen-1).
- //
- bool ReadString( char *pStr, int bufLen, bool bLine=false, int *pOutNumChars=NULL );
-
- // Reads a string and allocates memory for it. If the string in the buffer
- // is > 2048 bytes, then pOverflow is set to true (if it's not NULL).
- char* ReadAndAllocateString( bool *pOverflow = 0 );
-
- // Returns nonzero if any bits differ
- int CompareBits( bf_read * RESTRICT other, int bits ) RESTRICT;
- int CompareBitsAt( int offset, bf_read * RESTRICT other, int otherOffset, int bits ) RESTRICT;
-
-// Status.
-public:
- int GetNumBytesLeft();
- int GetNumBytesRead();
- int GetNumBitsLeft();
- int GetNumBitsRead() const;
-
- // Has the buffer overflowed?
- inline bool IsOverflowed() const {return m_bOverflow;}
-
- inline bool Seek(int iBit); // Seek to a specific bit.
- inline bool SeekRelative(int iBitDelta); // Seek to an offset from the current position.
-
- // Called when the buffer is overflowed.
- void SetOverflowFlag();
-
-
-public:
-
- // The current buffer.
- const unsigned char* RESTRICT m_pData;
- int m_nDataBytes;
- int m_nDataBits;
-
- // Where we are in the buffer.
- int m_iCurBit;
-
-
-private:
- // Errors?
- bool m_bOverflow;
-
- // For debugging..
- bool m_bAssertOnOverflow;
-
- const char *m_pDebugName;
-};
-
-//-----------------------------------------------------------------------------
-// Inlines.
-//-----------------------------------------------------------------------------
-
-inline int bf_read::GetNumBytesRead()
-{
- return BitByte(m_iCurBit);
-}
-
-inline int bf_read::GetNumBitsLeft()
-{
- return m_nDataBits - m_iCurBit;
-}
-
-inline int bf_read::GetNumBytesLeft()
-{
- return GetNumBitsLeft() >> 3;
-}
-
-inline int bf_read::GetNumBitsRead() const
-{
- return m_iCurBit;
-}
-
-inline bool bf_read::Seek(int iBit)
-{
- if(iBit < 0 || iBit > m_nDataBits)
- {
- SetOverflowFlag();
- m_iCurBit = m_nDataBits;
- return false;
- }
- else
- {
- m_iCurBit = iBit;
- return true;
- }
-}
-
-// Seek to an offset from the current position.
-inline bool bf_read::SeekRelative(int iBitDelta)
-{
- return Seek(m_iCurBit+iBitDelta);
-}
-
-inline bool bf_read::CheckForOverflow(int nBits)
-{
- if( m_iCurBit + nBits > m_nDataBits )
- {
- SetOverflowFlag();
- CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
- }
-
- return m_bOverflow;
-}
-
-inline int bf_read::ReadOneBitNoCheck()
-{
-#if VALVE_LITTLE_ENDIAN
- unsigned int value = ((unsigned long * RESTRICT)m_pData)[m_iCurBit >> 5] >> (m_iCurBit & 31);
-#else
- unsigned char value = m_pData[m_iCurBit >> 3] >> (m_iCurBit & 7);
-#endif
- ++m_iCurBit;
- return value & 1;
-}
-
-inline int bf_read::ReadOneBit()
-{
- if( GetNumBitsLeft() <= 0 )
- {
- SetOverflowFlag();
- CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
- return 0;
- }
- return ReadOneBitNoCheck();
-}
-
-inline float bf_read::ReadBitFloat()
-{
- union { uint32 u; float f; } c = { ReadUBitLong(32) };
- return c.f;
-}
-
-BITBUF_INLINE unsigned int bf_read::ReadUBitVar()
-{
- // six bits: low 2 bits for encoding + first 4 bits of value
- unsigned int sixbits = ReadUBitLong(6);
- unsigned int encoding = sixbits & 3;
- if ( encoding )
- {
- // this function will seek back four bits and read the full value
- return ReadUBitVarInternal( encoding );
- }
- return sixbits >> 2;
-}
-
-BITBUF_INLINE unsigned int bf_read::ReadUBitLong( int numbits ) RESTRICT
-{
- Assert( numbits > 0 && numbits <= 32 );
-
- if ( GetNumBitsLeft() < numbits )
- {
- m_iCurBit = m_nDataBits;
- SetOverflowFlag();
- CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
- return 0;
- }
-
- unsigned int iStartBit = m_iCurBit & 31u;
- int iLastBit = m_iCurBit + numbits - 1;
- unsigned int iWordOffset1 = m_iCurBit >> 5;
- unsigned int iWordOffset2 = iLastBit >> 5;
- m_iCurBit += numbits;
-
-#if __i386__
- unsigned int bitmask = (2 << (numbits-1)) - 1;
-#else
- extern unsigned long g_ExtraMasks[33];
- unsigned int bitmask = g_ExtraMasks[numbits];
-#endif
-
- unsigned int dw1 = LoadLittleDWord( (unsigned long* RESTRICT)m_pData, iWordOffset1 ) >> iStartBit;
- unsigned int dw2 = LoadLittleDWord( (unsigned long* RESTRICT)m_pData, iWordOffset2 ) << (32 - iStartBit);
-
- return (dw1 | dw2) & bitmask;
-}
-
-BITBUF_INLINE int bf_read::CompareBits( bf_read * RESTRICT other, int numbits ) RESTRICT
-{
- return (ReadUBitLong(numbits) != other->ReadUBitLong(numbits));
-}
-
-
-#endif
-
-
-
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+
+// NOTE: bf_read is guaranteed to return zeros if it overflows.
+
+#ifndef BITBUF_H
+#define BITBUF_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#include "mathlib/mathlib.h"
+#include "mathlib/vector.h"
+#include "basetypes.h"
+#include "tier0/dbg.h"
+
+
+#if _DEBUG
+#define BITBUF_INLINE inline
+#else
+#define BITBUF_INLINE FORCEINLINE
+#endif
+
+//-----------------------------------------------------------------------------
+// Forward declarations.
+//-----------------------------------------------------------------------------
+
+class Vector;
+class QAngle;
+
+//-----------------------------------------------------------------------------
+// You can define a handler function that will be called in case of
+// out-of-range values and overruns here.
+//
+// NOTE: the handler is only called in debug mode.
+//
+// Call SetBitBufErrorHandler to install a handler.
+//-----------------------------------------------------------------------------
+
+typedef enum
+{
+ BITBUFERROR_VALUE_OUT_OF_RANGE=0, // Tried to write a value with too few bits.
+ BITBUFERROR_BUFFER_OVERRUN, // Was about to overrun a buffer.
+
+ BITBUFERROR_NUM_ERRORS
+} BitBufErrorType;
+
+
+typedef void (*BitBufErrorHandler)( BitBufErrorType errorType, const char *pDebugName );
+
+
+#if defined( _DEBUG )
+ extern void InternalBitBufErrorHandler( BitBufErrorType errorType, const char *pDebugName );
+ #define CallErrorHandler( errorType, pDebugName ) InternalBitBufErrorHandler( errorType, pDebugName );
+#else
+ #define CallErrorHandler( errorType, pDebugName )
+#endif
+
+
+// Use this to install the error handler. Call with NULL to uninstall your error handler.
+void SetBitBufErrorHandler( BitBufErrorHandler fn );
+
+
+//-----------------------------------------------------------------------------
+// Helpers.
+//-----------------------------------------------------------------------------
+
+inline int BitByte( int bits )
+{
+ // return PAD_NUMBER( bits, 8 ) >> 3;
+ return (bits + 7) >> 3;
+}
+
+//-----------------------------------------------------------------------------
+// namespaced helpers
+//-----------------------------------------------------------------------------
+namespace bitbuf
+{
+ // ZigZag Transform: Encodes signed integers so that they can be
+ // effectively used with varint encoding.
+ //
+ // varint operates on unsigned integers, encoding smaller numbers into
+ // fewer bytes. If you try to use it on a signed integer, it will treat
+ // this number as a very large unsigned integer, which means that even
+ // small signed numbers like -1 will take the maximum number of bytes
+ // (10) to encode. ZigZagEncode() maps signed integers to unsigned
+ // in such a way that those with a small absolute value will have smaller
+ // encoded values, making them appropriate for encoding using varint.
+ //
+ // int32 -> uint32
+ // -------------------------
+ // 0 -> 0
+ // -1 -> 1
+ // 1 -> 2
+ // -2 -> 3
+ // ... -> ...
+ // 2147483647 -> 4294967294
+ // -2147483648 -> 4294967295
+ //
+ // >> encode >>
+ // << decode <<
+
+ inline uint32 ZigZagEncode32(int32 n)
+ {
+ // Note: the right-shift must be arithmetic
+ return(n << 1) ^ (n >> 31);
+ }
+
+ inline int32 ZigZagDecode32(uint32 n)
+ {
+ return(n >> 1) ^ -static_cast<int32>(n & 1);
+ }
+
+ inline uint64 ZigZagEncode64(int64 n)
+ {
+ // Note: the right-shift must be arithmetic
+ return(n << 1) ^ (n >> 63);
+ }
+
+ inline int64 ZigZagDecode64(uint64 n)
+ {
+ return(n >> 1) ^ -static_cast<int64>(n & 1);
+ }
+
+ const int kMaxVarintBytes = 10;
+ const int kMaxVarint32Bytes = 5;
+}
+
+//-----------------------------------------------------------------------------
+// Used for serialization
+//-----------------------------------------------------------------------------
+
+class bf_write
+{
+public:
+ bf_write();
+
+ // nMaxBits can be used as the number of bits in the buffer.
+ // It must be <= nBytes*8. If you leave it at -1, then it's set to nBytes * 8.
+ bf_write( void *pData, int nBytes, int nMaxBits = -1 );
+ bf_write( const char *pDebugName, void *pData, int nBytes, int nMaxBits = -1 );
+
+ // Start writing to the specified buffer.
+ // nMaxBits can be used as the number of bits in the buffer.
+ // It must be <= nBytes*8. If you leave it at -1, then it's set to nBytes * 8.
+ void StartWriting( void *pData, int nBytes, int iStartBit = 0, int nMaxBits = -1 );
+
+ // Restart buffer writing.
+ void Reset();
+
+ // Get the base pointer.
+ unsigned char* GetBasePointer() { return (unsigned char*) m_pData; }
+
+ // Enable or disable assertion on overflow. 99% of the time, it's a bug that we need to catch,
+ // but there may be the occasional buffer that is allowed to overflow gracefully.
+ void SetAssertOnOverflow( bool bAssert );
+
+ // This can be set to assign a name that gets output if the buffer overflows.
+ const char* GetDebugName();
+ void SetDebugName( const char *pDebugName );
+
+
+// Seek to a specific position.
+public:
+
+ void SeekToBit( int bitPos );
+
+
+// Bit functions.
+public:
+
+ void WriteOneBit(int nValue);
+ void WriteOneBitNoCheck(int nValue);
+ void WriteOneBitAt( int iBit, int nValue );
+
+ // Write signed or unsigned. Range is only checked in debug.
+ void WriteUBitLong( unsigned int data, int numbits, bool bCheckRange=true );
+ void WriteSBitLong( int data, int numbits );
+
+ // Tell it whether or not the data is unsigned. If it's signed,
+ // cast to unsigned before passing in (it will cast back inside).
+ void WriteBitLong(unsigned int data, int numbits, bool bSigned);
+
+ // Write a list of bits in.
+ bool WriteBits(const void *pIn, int nBits);
+
+ // writes an unsigned integer with variable bit length
+ void WriteUBitVar( unsigned int data );
+
+ // writes a varint encoded integer
+ void WriteVarInt32( uint32 data );
+ void WriteVarInt64( uint64 data );
+ void WriteSignedVarInt32( int32 data );
+ void WriteSignedVarInt64( int64 data );
+ int ByteSizeVarInt32( uint32 data );
+ int ByteSizeVarInt64( uint64 data );
+ int ByteSizeSignedVarInt32( int32 data );
+ int ByteSizeSignedVarInt64( int64 data );
+
+ // Copy the bits straight out of pIn. This seeks pIn forward by nBits.
+ // Returns an error if this buffer or the read buffer overflows.
+ bool WriteBitsFromBuffer( class bf_read *pIn, int nBits );
+
+ void WriteBitAngle( float fAngle, int numbits );
+ void WriteBitCoord (const float f);
+ void WriteBitCoordMP( const float f, bool bIntegral, bool bLowPrecision );
+ void WriteBitFloat(float val);
+ void WriteBitVec3Coord( const Vector& fa );
+ void WriteBitNormal( float f );
+ void WriteBitVec3Normal( const Vector& fa );
+ void WriteBitAngles( const QAngle& fa );
+
+
+// Byte functions.
+public:
+
+ void WriteChar(int val);
+ void WriteByte(int val);
+ void WriteShort(int val);
+ void WriteWord(int val);
+ void WriteLong(long val);
+ void WriteLongLong(int64 val);
+ void WriteFloat(float val);
+ bool WriteBytes( const void *pBuf, int nBytes );
+
+ // Returns false if it overflows the buffer.
+ bool WriteString(const char *pStr);
+
+
+// Status.
+public:
+
+ // How many bytes are filled in?
+ int GetNumBytesWritten() const;
+ int GetNumBitsWritten() const;
+ int GetMaxNumBits();
+ int GetNumBitsLeft();
+ int GetNumBytesLeft();
+ unsigned char* GetData();
+ const unsigned char* GetData() const;
+
+ // Has the buffer overflowed?
+ bool CheckForOverflow(int nBits);
+ inline bool IsOverflowed() const {return m_bOverflow;}
+
+ void SetOverflowFlag();
+
+
+public:
+ // The current buffer.
+ unsigned long* RESTRICT m_pData;
+ int m_nDataBytes;
+ int m_nDataBits;
+
+ // Where we are in the buffer.
+ int m_iCurBit;
+
+private:
+
+ // Errors?
+ bool m_bOverflow;
+
+ bool m_bAssertOnOverflow;
+ const char *m_pDebugName;
+};
+
+
+//-----------------------------------------------------------------------------
+// Inlined methods
+//-----------------------------------------------------------------------------
+
+// How many bytes are filled in?
+inline int bf_write::GetNumBytesWritten() const
+{
+ return BitByte(m_iCurBit);
+}
+
+inline int bf_write::GetNumBitsWritten() const
+{
+ return m_iCurBit;
+}
+
+inline int bf_write::GetMaxNumBits()
+{
+ return m_nDataBits;
+}
+
+inline int bf_write::GetNumBitsLeft()
+{
+ return m_nDataBits - m_iCurBit;
+}
+
+inline int bf_write::GetNumBytesLeft()
+{
+ return GetNumBitsLeft() >> 3;
+}
+
+inline unsigned char* bf_write::GetData()
+{
+ return (unsigned char*) m_pData;
+}
+
+inline const unsigned char* bf_write::GetData() const
+{
+ return (unsigned char*) m_pData;
+}
+
+BITBUF_INLINE bool bf_write::CheckForOverflow(int nBits)
+{
+ if ( m_iCurBit + nBits > m_nDataBits )
+ {
+ SetOverflowFlag();
+ CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
+ }
+
+ return m_bOverflow;
+}
+
+BITBUF_INLINE void bf_write::SetOverflowFlag()
+{
+#ifdef DBGFLAG_ASSERT
+ if ( m_bAssertOnOverflow )
+ {
+ Assert( false );
+ }
+#endif
+ m_bOverflow = true;
+}
+
+BITBUF_INLINE void bf_write::WriteOneBitNoCheck(int nValue)
+{
+#if __i386__
+ if(nValue)
+ m_pData[m_iCurBit >> 5] |= 1u << (m_iCurBit & 31);
+ else
+ m_pData[m_iCurBit >> 5] &= ~(1u << (m_iCurBit & 31));
+#else
+ extern unsigned long g_LittleBits[32];
+ if(nValue)
+ m_pData[m_iCurBit >> 5] |= g_LittleBits[m_iCurBit & 31];
+ else
+ m_pData[m_iCurBit >> 5] &= ~g_LittleBits[m_iCurBit & 31];
+#endif
+
+ ++m_iCurBit;
+}
+
+inline void bf_write::WriteOneBit(int nValue)
+{
+ if( m_iCurBit >= m_nDataBits )
+ {
+ SetOverflowFlag();
+ CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
+ return;
+ }
+ WriteOneBitNoCheck( nValue );
+}
+
+
+inline void bf_write::WriteOneBitAt( int iBit, int nValue )
+{
+ if( iBit >= m_nDataBits )
+ {
+ SetOverflowFlag();
+ CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
+ return;
+ }
+
+#if __i386__
+ if(nValue)
+ m_pData[iBit >> 5] |= 1u << (iBit & 31);
+ else
+ m_pData[iBit >> 5] &= ~(1u << (iBit & 31));
+#else
+ extern unsigned long g_LittleBits[32];
+ if(nValue)
+ m_pData[iBit >> 5] |= g_LittleBits[iBit & 31];
+ else
+ m_pData[iBit >> 5] &= ~g_LittleBits[iBit & 31];
+#endif
+}
+
+BITBUF_INLINE void bf_write::WriteUBitLong( unsigned int curData, int numbits, bool bCheckRange ) RESTRICT
+{
+#ifdef _DEBUG
+ // Make sure it doesn't overflow.
+ if ( bCheckRange && numbits < 32 )
+ {
+ if ( curData >= (unsigned long)(1 << numbits) )
+ {
+ CallErrorHandler( BITBUFERROR_VALUE_OUT_OF_RANGE, GetDebugName() );
+ }
+ }
+ Assert( numbits >= 0 && numbits <= 32 );
+#endif
+
+ if ( GetNumBitsLeft() < numbits )
+ {
+ m_iCurBit = m_nDataBits;
+ SetOverflowFlag();
+ CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
+ return;
+ }
+
+ int iCurBitMasked = m_iCurBit & 31;
+ int iDWord = m_iCurBit >> 5;
+ m_iCurBit += numbits;
+
+ // Mask in a dword.
+ Assert( (iDWord*4 + sizeof(long)) <= (unsigned int)m_nDataBytes );
+ unsigned long * RESTRICT pOut = &m_pData[iDWord];
+
+ // Rotate data into dword alignment
+ curData = (curData << iCurBitMasked) | (curData >> (32 - iCurBitMasked));
+
+ // Calculate bitmasks for first and second word
+ unsigned int temp = 1 << (numbits-1);
+ unsigned int mask1 = (temp*2-1) << iCurBitMasked;
+ unsigned int mask2 = (temp-1) >> (31 - iCurBitMasked);
+
+ // Only look beyond current word if necessary (avoid access violation)
+ int i = mask2 & 1;
+ unsigned long dword1 = LoadLittleDWord( pOut, 0 );
+ unsigned long dword2 = LoadLittleDWord( pOut, i );
+
+ // Drop bits into place
+ dword1 ^= ( mask1 & ( curData ^ dword1 ) );
+ dword2 ^= ( mask2 & ( curData ^ dword2 ) );
+
+ // Note reversed order of writes so that dword1 wins if mask2 == 0 && i == 0
+ StoreLittleDWord( pOut, i, dword2 );
+ StoreLittleDWord( pOut, 0, dword1 );
+}
+
+// writes an unsigned integer with variable bit length
+BITBUF_INLINE void bf_write::WriteUBitVar( unsigned int data )
+{
+ /* Reference:
+ if ( data < 0x10u )
+ WriteUBitLong( 0, 2 ), WriteUBitLong( data, 4 );
+ else if ( data < 0x100u )
+ WriteUBitLong( 1, 2 ), WriteUBitLong( data, 8 );
+ else if ( data < 0x1000u )
+ WriteUBitLong( 2, 2 ), WriteUBitLong( data, 12 );
+ else
+ WriteUBitLong( 3, 2 ), WriteUBitLong( data, 32 );
+ */
+ // a < b ? -1 : 0 translates into a CMP, SBB instruction pair
+ // with no flow control. should also be branchless on consoles.
+ int n = (data < 0x10u ? -1 : 0) + (data < 0x100u ? -1 : 0) + (data < 0x1000u ? -1 : 0);
+ WriteUBitLong( data*4 + n + 3, 6 + n*4 + 12 );
+ if ( data >= 0x1000u )
+ {
+ WriteUBitLong( data >> 16, 16 );
+ }
+}
+
+// write raw IEEE float bits in little endian form
+BITBUF_INLINE void bf_write::WriteBitFloat(float val)
+{
+ long intVal;
+
+ Assert(sizeof(long) == sizeof(float));
+ Assert(sizeof(float) == 4);
+
+ intVal = *((long*)&val);
+ WriteUBitLong( intVal, 32 );
+}
+
+//-----------------------------------------------------------------------------
+// This is useful if you just want a buffer to write into on the stack.
+//-----------------------------------------------------------------------------
+
+template<int SIZE>
+class old_bf_write_static : public bf_write
+{
+public:
+ inline old_bf_write_static() : bf_write(m_StaticData, SIZE) {}
+
+ char m_StaticData[SIZE];
+};
+
+
+
+//-----------------------------------------------------------------------------
+// Used for unserialization
+//-----------------------------------------------------------------------------
+
+class bf_read
+{
+public:
+ bf_read();
+
+ // nMaxBits can be used as the number of bits in the buffer.
+ // It must be <= nBytes*8. If you leave it at -1, then it's set to nBytes * 8.
+ bf_read( const void *pData, int nBytes, int nBits = -1 );
+ bf_read( const char *pDebugName, const void *pData, int nBytes, int nBits = -1 );
+
+ // Start reading from the specified buffer.
+ // pData's start address must be dword-aligned.
+ // nMaxBits can be used as the number of bits in the buffer.
+ // It must be <= nBytes*8. If you leave it at -1, then it's set to nBytes * 8.
+ void StartReading( const void *pData, int nBytes, int iStartBit = 0, int nBits = -1 );
+
+ // Restart buffer reading.
+ void Reset();
+
+ // Enable or disable assertion on overflow. 99% of the time, it's a bug that we need to catch,
+ // but there may be the occasional buffer that is allowed to overflow gracefully.
+ void SetAssertOnOverflow( bool bAssert );
+
+ // This can be set to assign a name that gets output if the buffer overflows.
+ const char* GetDebugName() const { return m_pDebugName; }
+ void SetDebugName( const char *pName );
+
+ void ExciseBits( int startbit, int bitstoremove );
+
+
+// Bit functions.
+public:
+
+ // Returns 0 or 1.
+ int ReadOneBit();
+
+
+protected:
+
+ unsigned int CheckReadUBitLong(int numbits); // For debugging.
+ int ReadOneBitNoCheck(); // Faster version, doesn't check bounds and is inlined.
+ bool CheckForOverflow(int nBits);
+
+
+public:
+
+ // Get the base pointer.
+ const unsigned char* GetBasePointer() { return m_pData; }
+
+ BITBUF_INLINE int TotalBytesAvailable( void ) const
+ {
+ return m_nDataBytes;
+ }
+
+ // Read a list of bits in.
+ void ReadBits(void *pOut, int nBits);
+ // Read a list of bits in, but don't overrun the destination buffer.
+ // Returns the number of bits read into the buffer. The remaining
+ // bits are skipped over.
+ int ReadBitsClamped_ptr(void *pOut, size_t outSizeBytes, size_t nBits);
+ // Helper 'safe' template function that infers the size of the destination
+ // array. This version of the function should be preferred.
+ // Usage: char databuffer[100];
+ // ReadBitsClamped( dataBuffer, msg->m_nLength );
+ template <typename T, size_t N>
+ int ReadBitsClamped( T (&pOut)[N], size_t nBits )
+ {
+ return ReadBitsClamped_ptr( pOut, N * sizeof(T), nBits );
+ }
+
+ float ReadBitAngle( int numbits );
+
+ unsigned int ReadUBitLong( int numbits ) RESTRICT;
+ unsigned int ReadUBitLongNoInline( int numbits ) RESTRICT;
+ unsigned int PeekUBitLong( int numbits );
+ int ReadSBitLong( int numbits );
+
+ // reads an unsigned integer with variable bit length
+ unsigned int ReadUBitVar();
+ unsigned int ReadUBitVarInternal( int encodingType );
+
+ // reads a varint encoded integer
+ uint32 ReadVarInt32();
+ uint64 ReadVarInt64();
+ int32 ReadSignedVarInt32();
+ int64 ReadSignedVarInt64();
+
+ // You can read signed or unsigned data with this, just cast to
+ // a signed int if necessary.
+ unsigned int ReadBitLong(int numbits, bool bSigned);
+
+ float ReadBitCoord();
+ float ReadBitCoordMP( bool bIntegral, bool bLowPrecision );
+ float ReadBitFloat();
+ float ReadBitNormal();
+ void ReadBitVec3Coord( Vector& fa );
+ void ReadBitVec3Normal( Vector& fa );
+ void ReadBitAngles( QAngle& fa );
+
+ // Faster for comparisons but do not fully decode float values
+ unsigned int ReadBitCoordBits();
+ unsigned int ReadBitCoordMPBits( bool bIntegral, bool bLowPrecision );
+
+// Byte functions (these still read data in bit-by-bit).
+public:
+
+ BITBUF_INLINE int ReadChar() { return (char)ReadUBitLong(8); }
+ BITBUF_INLINE int ReadByte() { return ReadUBitLong(8); }
+ BITBUF_INLINE int ReadShort() { return (short)ReadUBitLong(16); }
+ BITBUF_INLINE int ReadWord() { return ReadUBitLong(16); }
+ BITBUF_INLINE long ReadLong() { return ReadUBitLong(32); }
+ int64 ReadLongLong();
+ float ReadFloat();
+ bool ReadBytes(void *pOut, int nBytes);
+
+ // Returns false if bufLen isn't large enough to hold the
+ // string in the buffer.
+ //
+ // Always reads to the end of the string (so you can read the
+ // next piece of data waiting).
+ //
+ // If bLine is true, it stops when it reaches a '\n' or a null-terminator.
+ //
+ // pStr is always null-terminated (unless bufLen is 0).
+ //
+ // pOutNumChars is set to the number of characters left in pStr when the routine is
+ // complete (this will never exceed bufLen-1).
+ //
+ bool ReadString( char *pStr, int bufLen, bool bLine=false, int *pOutNumChars=NULL );
+
+ // Reads a string and allocates memory for it. If the string in the buffer
+ // is > 2048 bytes, then pOverflow is set to true (if it's not NULL).
+ char* ReadAndAllocateString( bool *pOverflow = 0 );
+
+ // Returns nonzero if any bits differ
+ int CompareBits( bf_read * RESTRICT other, int bits ) RESTRICT;
+ int CompareBitsAt( int offset, bf_read * RESTRICT other, int otherOffset, int bits ) RESTRICT;
+
+// Status.
+public:
+ int GetNumBytesLeft();
+ int GetNumBytesRead();
+ int GetNumBitsLeft();
+ int GetNumBitsRead() const;
+
+ // Has the buffer overflowed?
+ inline bool IsOverflowed() const {return m_bOverflow;}
+
+ inline bool Seek(int iBit); // Seek to a specific bit.
+ inline bool SeekRelative(int iBitDelta); // Seek to an offset from the current position.
+
+ // Called when the buffer is overflowed.
+ void SetOverflowFlag();
+
+
+public:
+
+ // The current buffer.
+ const unsigned char* RESTRICT m_pData;
+ int m_nDataBytes;
+ int m_nDataBits;
+
+ // Where we are in the buffer.
+ int m_iCurBit;
+
+
+private:
+ // Errors?
+ bool m_bOverflow;
+
+ // For debugging..
+ bool m_bAssertOnOverflow;
+
+ const char *m_pDebugName;
+};
+
+//-----------------------------------------------------------------------------
+// Inlines.
+//-----------------------------------------------------------------------------
+
+inline int bf_read::GetNumBytesRead()
+{
+ return BitByte(m_iCurBit);
+}
+
+inline int bf_read::GetNumBitsLeft()
+{
+ return m_nDataBits - m_iCurBit;
+}
+
+inline int bf_read::GetNumBytesLeft()
+{
+ return GetNumBitsLeft() >> 3;
+}
+
+inline int bf_read::GetNumBitsRead() const
+{
+ return m_iCurBit;
+}
+
+inline bool bf_read::Seek(int iBit)
+{
+ if(iBit < 0 || iBit > m_nDataBits)
+ {
+ SetOverflowFlag();
+ m_iCurBit = m_nDataBits;
+ return false;
+ }
+ else
+ {
+ m_iCurBit = iBit;
+ return true;
+ }
+}
+
+// Seek to an offset from the current position.
+inline bool bf_read::SeekRelative(int iBitDelta)
+{
+ return Seek(m_iCurBit+iBitDelta);
+}
+
+inline bool bf_read::CheckForOverflow(int nBits)
+{
+ if( m_iCurBit + nBits > m_nDataBits )
+ {
+ SetOverflowFlag();
+ CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
+ }
+
+ return m_bOverflow;
+}
+
+inline int bf_read::ReadOneBitNoCheck()
+{
+#if VALVE_LITTLE_ENDIAN
+ unsigned int value = ((unsigned long * RESTRICT)m_pData)[m_iCurBit >> 5] >> (m_iCurBit & 31);
+#else
+ unsigned char value = m_pData[m_iCurBit >> 3] >> (m_iCurBit & 7);
+#endif
+ ++m_iCurBit;
+ return value & 1;
+}
+
+inline int bf_read::ReadOneBit()
+{
+ if( GetNumBitsLeft() <= 0 )
+ {
+ SetOverflowFlag();
+ CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
+ return 0;
+ }
+ return ReadOneBitNoCheck();
+}
+
+inline float bf_read::ReadBitFloat()
+{
+ union { uint32 u; float f; } c = { ReadUBitLong(32) };
+ return c.f;
+}
+
+BITBUF_INLINE unsigned int bf_read::ReadUBitVar()
+{
+ // six bits: low 2 bits for encoding + first 4 bits of value
+ unsigned int sixbits = ReadUBitLong(6);
+ unsigned int encoding = sixbits & 3;
+ if ( encoding )
+ {
+ // this function will seek back four bits and read the full value
+ return ReadUBitVarInternal( encoding );
+ }
+ return sixbits >> 2;
+}
+
+BITBUF_INLINE unsigned int bf_read::ReadUBitLong( int numbits ) RESTRICT
+{
+ Assert( numbits > 0 && numbits <= 32 );
+
+ if ( GetNumBitsLeft() < numbits )
+ {
+ m_iCurBit = m_nDataBits;
+ SetOverflowFlag();
+ CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() );
+ return 0;
+ }
+
+ unsigned int iStartBit = m_iCurBit & 31u;
+ int iLastBit = m_iCurBit + numbits - 1;
+ unsigned int iWordOffset1 = m_iCurBit >> 5;
+ unsigned int iWordOffset2 = iLastBit >> 5;
+ m_iCurBit += numbits;
+
+#if __i386__
+ unsigned int bitmask = (2 << (numbits-1)) - 1;
+#else
+ extern unsigned long g_ExtraMasks[33];
+ unsigned int bitmask = g_ExtraMasks[numbits];
+#endif
+
+ unsigned int dw1 = LoadLittleDWord( (unsigned long* RESTRICT)m_pData, iWordOffset1 ) >> iStartBit;
+ unsigned int dw2 = LoadLittleDWord( (unsigned long* RESTRICT)m_pData, iWordOffset2 ) << (32 - iStartBit);
+
+ return (dw1 | dw2) & bitmask;
+}
+
+BITBUF_INLINE int bf_read::CompareBits( bf_read * RESTRICT other, int numbits ) RESTRICT
+{
+ return (ReadUBitLong(numbits) != other->ReadUBitLong(numbits));
+}
+
+
+#endif
+
+
+
diff --git a/mp/src/public/tier1/byteswap.h b/mp/src/public/tier1/byteswap.h
index c7bc3c87..9b082541 100644
--- a/mp/src/public/tier1/byteswap.h
+++ b/mp/src/public/tier1/byteswap.h
@@ -1,249 +1,249 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Low level byte swapping routines.
-//
-// $NoKeywords: $
-//=============================================================================
-#ifndef BYTESWAP_H
-#define BYTESWAP_H
-#if defined(_WIN32)
-#pragma once
-#endif
-
-#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:
- 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, 0, &temp );
- __storewordbytereverse( *(word+1), 4, &temp );
- }
- break;
-
- case 4:
- __storewordbytereverse( *word, 0, &temp );
- break;
-
- case 2:
- __storeshortbytereverse( *input, 0, &temp );
- break;
-
- default:
- Assert( "Invalid size in CByteswap::LowLevelByteSwap" && 0 );
- }
-#else
- for( int i = 0; i < sizeof(T); i++ )
- {
- ((unsigned char* )&temp)[i] = ((unsigned char*)input)[sizeof(T)-(i+1)];
- }
-#endif
- Q_memcpy( output, &temp, sizeof(T) );
- }
-
- unsigned int m_bSwapBytes : 1;
- unsigned int m_bBigEndian : 1;
-};
-
-#endif /* !BYTESWAP_H */
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Low level byte swapping routines.
+//
+// $NoKeywords: $
+//=============================================================================
+#ifndef BYTESWAP_H
+#define BYTESWAP_H
+#if defined(_WIN32)
+#pragma once
+#endif
+
+#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:
+ 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, 0, &temp );
+ __storewordbytereverse( *(word+1), 4, &temp );
+ }
+ break;
+
+ case 4:
+ __storewordbytereverse( *word, 0, &temp );
+ break;
+
+ case 2:
+ __storeshortbytereverse( *input, 0, &temp );
+ break;
+
+ default:
+ Assert( "Invalid size in CByteswap::LowLevelByteSwap" && 0 );
+ }
+#else
+ for( int i = 0; i < sizeof(T); i++ )
+ {
+ ((unsigned char* )&temp)[i] = ((unsigned char*)input)[sizeof(T)-(i+1)];
+ }
+#endif
+ Q_memcpy( output, &temp, sizeof(T) );
+ }
+
+ unsigned int m_bSwapBytes : 1;
+ unsigned int m_bBigEndian : 1;
+};
+
+#endif /* !BYTESWAP_H */
diff --git a/mp/src/public/tier1/callqueue.h b/mp/src/public/tier1/callqueue.h
index c576efec..5e0e9940 100644
--- a/mp/src/public/tier1/callqueue.h
+++ b/mp/src/public/tier1/callqueue.h
@@ -1,203 +1,203 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-//=============================================================================
-
-#ifndef CALLQUEUE_H
-#define CALLQUEUE_H
-
-#include "tier0/tslist.h"
-#include "functors.h"
-
-#if defined( _WIN32 )
-#pragma once
-#endif
-
-//-----------------------------------------------------
-// Avert thy eyes! Imagine rather:
-//
-// void QueueCall( <function>, [args1, [arg2,]...]
-// void QueueCall( <object>, <function>, [args1, [arg2,]...]
-// void QueueRefCall( <object>, <<function>, [args1, [arg2,]...]
-//-----------------------------------------------------
-
-#define DEFINE_CALLQUEUE_NONMEMBER_QUEUE_CALL(N) \
- template <typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
- void QueueCall(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
- { \
- QueueFunctorInternal( CreateFunctor( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \
- }
-
-//-------------------------------------
-
-#define DEFINE_CALLQUEUE_MEMBER_QUEUE_CALL(N) \
- template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
- void QueueCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
- { \
- QueueFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \
- }
-
-//-------------------------------------
-
-#define DEFINE_CALLQUEUE_CONST_MEMBER_QUEUE_CALL(N) \
- template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
- void QueueCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \
- { \
- QueueFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \
- }
-
-//-------------------------------------
-
-#define DEFINE_CALLQUEUE_REF_COUNTING_MEMBER_QUEUE_CALL(N) \
- template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
- void QueueRefCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
- { \
- QueueFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \
- }
-
-//-------------------------------------
-
-#define DEFINE_CALLQUEUE_REF_COUNTING_CONST_MEMBER_QUEUE_CALL(N) \
- template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
- void QueueRefCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \
- { \
- QueueFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \
- \
- }
-
-#define FUNC_GENERATE_QUEUE_METHODS() \
- FUNC_GENERATE_ALL( DEFINE_CALLQUEUE_NONMEMBER_QUEUE_CALL ); \
- FUNC_GENERATE_ALL( DEFINE_CALLQUEUE_MEMBER_QUEUE_CALL ); \
- FUNC_GENERATE_ALL( DEFINE_CALLQUEUE_CONST_MEMBER_QUEUE_CALL );\
- FUNC_GENERATE_ALL( DEFINE_CALLQUEUE_REF_COUNTING_MEMBER_QUEUE_CALL ); \
- FUNC_GENERATE_ALL( DEFINE_CALLQUEUE_REF_COUNTING_CONST_MEMBER_QUEUE_CALL )
-
-//-----------------------------------------------------
-
-template <typename QUEUE_TYPE = CTSQueue<CFunctor *> >
-class CCallQueueT
-{
-public:
- CCallQueueT()
- : m_bNoQueue( false )
- {
-#ifdef _DEBUG
- m_nCurSerialNumber = 0;
- m_nBreakSerialNumber = (unsigned)-1;
-#endif
- }
-
- void DisableQueue( bool bDisable )
- {
- if ( m_bNoQueue == bDisable )
- {
- return;
- }
- if ( !m_bNoQueue )
- CallQueued();
-
- m_bNoQueue = bDisable;
- }
-
- bool IsDisabled() const
- {
- return m_bNoQueue;
- }
-
- int Count()
- {
- return m_queue.Count();
- }
-
- void CallQueued()
- {
- if ( !m_queue.Count() )
- {
- return;
- }
-
- m_queue.PushItem( NULL );
-
- CFunctor *pFunctor;
-
- while ( m_queue.PopItem( &pFunctor ) && pFunctor != NULL )
- {
-#ifdef _DEBUG
- if ( pFunctor->m_nUserID == m_nBreakSerialNumber)
- {
- m_nBreakSerialNumber = (unsigned)-1;
- }
-#endif
- (*pFunctor)();
- pFunctor->Release();
- }
-
- }
-
- void QueueFunctor( CFunctor *pFunctor )
- {
- Assert( pFunctor );
- QueueFunctorInternal( RetAddRef( pFunctor ) );
- }
-
- void Flush()
- {
- m_queue.PushItem( NULL );
-
- CFunctor *pFunctor;
-
- while ( m_queue.PopItem( &pFunctor ) && pFunctor != NULL )
- {
- pFunctor->Release();
- }
- }
-
- FUNC_GENERATE_QUEUE_METHODS();
-
-private:
- void QueueFunctorInternal( CFunctor *pFunctor )
- {
- if ( !m_bNoQueue )
- {
-#ifdef _DEBUG
- pFunctor->m_nUserID = m_nCurSerialNumber++;
-#endif
- m_queue.PushItem( pFunctor );
- }
- else
- {
- (*pFunctor)();
- pFunctor->Release();
- }
- }
-
- QUEUE_TYPE m_queue;
- bool m_bNoQueue;
- unsigned m_nCurSerialNumber;
- unsigned m_nBreakSerialNumber;
-};
-
-class CCallQueue : public CCallQueueT<>
-{
-};
-
-//-----------------------------------------------------
-// Optional interface that can be bound to concrete CCallQueue
-//-----------------------------------------------------
-
-class ICallQueue
-{
-public:
- void QueueFunctor( CFunctor *pFunctor )
- {
- QueueFunctorInternal( RetAddRef( pFunctor ) );
- }
-
- FUNC_GENERATE_QUEUE_METHODS();
-
-private:
- virtual void QueueFunctorInternal( CFunctor *pFunctor ) = 0;
-};
-
-#endif // CALLQUEUE_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef CALLQUEUE_H
+#define CALLQUEUE_H
+
+#include "tier0/tslist.h"
+#include "functors.h"
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+//-----------------------------------------------------
+// Avert thy eyes! Imagine rather:
+//
+// void QueueCall( <function>, [args1, [arg2,]...]
+// void QueueCall( <object>, <function>, [args1, [arg2,]...]
+// void QueueRefCall( <object>, <<function>, [args1, [arg2,]...]
+//-----------------------------------------------------
+
+#define DEFINE_CALLQUEUE_NONMEMBER_QUEUE_CALL(N) \
+ template <typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ void QueueCall(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ QueueFunctorInternal( CreateFunctor( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \
+ }
+
+//-------------------------------------
+
+#define DEFINE_CALLQUEUE_MEMBER_QUEUE_CALL(N) \
+ template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ void QueueCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ QueueFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \
+ }
+
+//-------------------------------------
+
+#define DEFINE_CALLQUEUE_CONST_MEMBER_QUEUE_CALL(N) \
+ template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ void QueueCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ QueueFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \
+ }
+
+//-------------------------------------
+
+#define DEFINE_CALLQUEUE_REF_COUNTING_MEMBER_QUEUE_CALL(N) \
+ template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ void QueueRefCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ QueueFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \
+ }
+
+//-------------------------------------
+
+#define DEFINE_CALLQUEUE_REF_COUNTING_CONST_MEMBER_QUEUE_CALL(N) \
+ template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ void QueueRefCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ QueueFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \
+ \
+ }
+
+#define FUNC_GENERATE_QUEUE_METHODS() \
+ FUNC_GENERATE_ALL( DEFINE_CALLQUEUE_NONMEMBER_QUEUE_CALL ); \
+ FUNC_GENERATE_ALL( DEFINE_CALLQUEUE_MEMBER_QUEUE_CALL ); \
+ FUNC_GENERATE_ALL( DEFINE_CALLQUEUE_CONST_MEMBER_QUEUE_CALL );\
+ FUNC_GENERATE_ALL( DEFINE_CALLQUEUE_REF_COUNTING_MEMBER_QUEUE_CALL ); \
+ FUNC_GENERATE_ALL( DEFINE_CALLQUEUE_REF_COUNTING_CONST_MEMBER_QUEUE_CALL )
+
+//-----------------------------------------------------
+
+template <typename QUEUE_TYPE = CTSQueue<CFunctor *> >
+class CCallQueueT
+{
+public:
+ CCallQueueT()
+ : m_bNoQueue( false )
+ {
+#ifdef _DEBUG
+ m_nCurSerialNumber = 0;
+ m_nBreakSerialNumber = (unsigned)-1;
+#endif
+ }
+
+ void DisableQueue( bool bDisable )
+ {
+ if ( m_bNoQueue == bDisable )
+ {
+ return;
+ }
+ if ( !m_bNoQueue )
+ CallQueued();
+
+ m_bNoQueue = bDisable;
+ }
+
+ bool IsDisabled() const
+ {
+ return m_bNoQueue;
+ }
+
+ int Count()
+ {
+ return m_queue.Count();
+ }
+
+ void CallQueued()
+ {
+ if ( !m_queue.Count() )
+ {
+ return;
+ }
+
+ m_queue.PushItem( NULL );
+
+ CFunctor *pFunctor;
+
+ while ( m_queue.PopItem( &pFunctor ) && pFunctor != NULL )
+ {
+#ifdef _DEBUG
+ if ( pFunctor->m_nUserID == m_nBreakSerialNumber)
+ {
+ m_nBreakSerialNumber = (unsigned)-1;
+ }
+#endif
+ (*pFunctor)();
+ pFunctor->Release();
+ }
+
+ }
+
+ void QueueFunctor( CFunctor *pFunctor )
+ {
+ Assert( pFunctor );
+ QueueFunctorInternal( RetAddRef( pFunctor ) );
+ }
+
+ void Flush()
+ {
+ m_queue.PushItem( NULL );
+
+ CFunctor *pFunctor;
+
+ while ( m_queue.PopItem( &pFunctor ) && pFunctor != NULL )
+ {
+ pFunctor->Release();
+ }
+ }
+
+ FUNC_GENERATE_QUEUE_METHODS();
+
+private:
+ void QueueFunctorInternal( CFunctor *pFunctor )
+ {
+ if ( !m_bNoQueue )
+ {
+#ifdef _DEBUG
+ pFunctor->m_nUserID = m_nCurSerialNumber++;
+#endif
+ m_queue.PushItem( pFunctor );
+ }
+ else
+ {
+ (*pFunctor)();
+ pFunctor->Release();
+ }
+ }
+
+ QUEUE_TYPE m_queue;
+ bool m_bNoQueue;
+ unsigned m_nCurSerialNumber;
+ unsigned m_nBreakSerialNumber;
+};
+
+class CCallQueue : public CCallQueueT<>
+{
+};
+
+//-----------------------------------------------------
+// Optional interface that can be bound to concrete CCallQueue
+//-----------------------------------------------------
+
+class ICallQueue
+{
+public:
+ void QueueFunctor( CFunctor *pFunctor )
+ {
+ QueueFunctorInternal( RetAddRef( pFunctor ) );
+ }
+
+ FUNC_GENERATE_QUEUE_METHODS();
+
+private:
+ virtual void QueueFunctorInternal( CFunctor *pFunctor ) = 0;
+};
+
+#endif // CALLQUEUE_H
diff --git a/mp/src/public/tier1/characterset.h b/mp/src/public/tier1/characterset.h
index 8bd35352..0c639e1a 100644
--- a/mp/src/public/tier1/characterset.h
+++ b/mp/src/public/tier1/characterset.h
@@ -1,43 +1,43 @@
-//========= Copyright 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
+//========= Copyright 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/mp/src/public/tier1/checksum_crc.h b/mp/src/public/tier1/checksum_crc.h
index 130577ee..dbbc50a4 100644
--- a/mp/src/public/tier1/checksum_crc.h
+++ b/mp/src/public/tier1/checksum_crc.h
@@ -1,31 +1,31 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Generic CRC functions
-//
-// $NoKeywords: $
-//=============================================================================//
-#ifndef CHECKSUM_CRC_H
-#define CHECKSUM_CRC_H
-#ifdef _WIN32
-#pragma once
-#endif
-
-typedef unsigned int 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
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Generic CRC functions
+//
+// $NoKeywords: $
+//=============================================================================//
+#ifndef CHECKSUM_CRC_H
+#define CHECKSUM_CRC_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+typedef unsigned int 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/mp/src/public/tier1/checksum_md5.h b/mp/src/public/tier1/checksum_md5.h
index 34f82823..e7cf7ec9 100644
--- a/mp/src/public/tier1/checksum_md5.h
+++ b/mp/src/public/tier1/checksum_md5.h
@@ -1,62 +1,62 @@
-//========= Copyright 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
-#define MD5_BIT_LENGTH ( MD5_DIGEST_LENGTH * sizeof(unsigned char) )
-struct MD5Value_t
-{
- unsigned char bits[MD5_DIGEST_LENGTH];
-
- void Zero();
- bool IsZero() const;
-
- bool operator==( const MD5Value_t &src ) const;
- bool operator!=( const MD5Value_t &src ) const;
-
-};
-
-// 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 );
-
-/// Convenience wrapper to calculate the MD5 for a buffer, all in one step, without
-/// bothering with the context object.
-void MD5_ProcessSingleBuffer( const void *p, int len, MD5Value_t &md5Result );
-
-unsigned int MD5_PseudoRandom(unsigned int nSeed);
-
-/// Returns true if the values match.
-bool MD5_Compare( const MD5Value_t &data, const MD5Value_t &compare );
-
-inline bool MD5Value_t::operator==( const MD5Value_t &src ) const
-{
- return MD5_Compare( *this, src );
-}
-
-inline bool MD5Value_t::operator!=( const MD5Value_t &src ) const
-{
- return !MD5_Compare( *this, src );
-}
-
-#endif // CHECKSUM_MD5_H
+//========= Copyright 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
+#define MD5_BIT_LENGTH ( MD5_DIGEST_LENGTH * sizeof(unsigned char) )
+struct MD5Value_t
+{
+ unsigned char bits[MD5_DIGEST_LENGTH];
+
+ void Zero();
+ bool IsZero() const;
+
+ bool operator==( const MD5Value_t &src ) const;
+ bool operator!=( const MD5Value_t &src ) const;
+
+};
+
+// 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 );
+
+/// Convenience wrapper to calculate the MD5 for a buffer, all in one step, without
+/// bothering with the context object.
+void MD5_ProcessSingleBuffer( const void *p, int len, MD5Value_t &md5Result );
+
+unsigned int MD5_PseudoRandom(unsigned int nSeed);
+
+/// Returns true if the values match.
+bool MD5_Compare( const MD5Value_t &data, const MD5Value_t &compare );
+
+inline bool MD5Value_t::operator==( const MD5Value_t &src ) const
+{
+ return MD5_Compare( *this, src );
+}
+
+inline bool MD5Value_t::operator!=( const MD5Value_t &src ) const
+{
+ return !MD5_Compare( *this, src );
+}
+
+#endif // CHECKSUM_MD5_H
diff --git a/mp/src/public/tier1/checksum_sha1.h b/mp/src/public/tier1/checksum_sha1.h
index 9a503c0d..7c87aa5c 100644
--- a/mp/src/public/tier1/checksum_sha1.h
+++ b/mp/src/public/tier1/checksum_sha1.h
@@ -1,174 +1,174 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Implementation of SHA-1
-//
-//=============================================================================
-
-#ifndef CHECKSUM_SHA1_H
-#define CHECKSUM_SHA1_H
-
-#if defined( _WIN32 )
-#pragma once
-#endif
-
-/*
- 100% free public domain implementation of the SHA-1
- algorithm by Dominik Reichl <[email protected]>
-
-
- === Test Vectors (from FIPS PUB 180-1) ===
-
- SHA1("abc") =
- A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
-
- SHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") =
- 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
-
- SHA1(A million repetitions of "a") =
- 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
-*/
-
-#if !defined(_MINIMUM_BUILD_)
-#include <stdio.h> // Needed for file access
-#if defined( _PS3 )
-#include <sys/memory.h>
-#else
-#include <memory.h>
-#endif
-#include <string.h> // Needed for strcat and strcpy
-#endif
-
-// If you're compiling big endian, just comment out the following line
-#define SHA1_LITTLE_ENDIAN
-
-typedef union
-{
- unsigned char c[64];
- unsigned long l[16];
-} SHA1_WORKSPACE_BLOCK;
-
-// SHA1 hash
-const unsigned int k_cubHash = 20;
-const unsigned int k_cchHash = 41; // k_cubHash * 2, plus 1 for terminator
-#pragma pack( push, 1 )
-typedef unsigned char SHADigest_t[ k_cubHash ];
-#pragma pack( pop )
-
-#if !defined(_MINIMUM_BUILD_)
-class CSHA1
-#else
-class Minimum_CSHA1
-#endif
-{
-public:
- // Two different formats for ReportHash(...)
- enum
- {
- REPORT_HEX = 0,
- REPORT_DIGIT = 1
- };
-
- // Constructor and Destructor
-#if !defined(_MINIMUM_BUILD_)
- CSHA1();
- virtual ~CSHA1() ;
-#else
- Minimum_CSHA1() ;
- ~Minimum_CSHA1() ; // no virtual destructor's in the minimal builds !
-#endif
-
- unsigned long m_state[5];
- unsigned long m_count[2];
- unsigned char m_buffer[64];
- unsigned char m_digest[k_cubHash];
-
- void Reset();
-
- // Update the hash value
- void Update(unsigned char *data, unsigned int len);
-#if !defined(_MINIMUM_BUILD_)
- bool HashFile(char *szFileName);
-#endif
-
- // Finalize hash and report
- void Final();
-#if !defined(_MINIMUM_BUILD_)
- void ReportHash(char *szReport, unsigned char uReportType = REPORT_HEX);
-#endif
- void GetHash(unsigned char *uDest);
-
-private:
- // Private SHA-1 transformation
- void Transform(unsigned long state[5], unsigned char buffer[64]);
-
- // Member variables
- unsigned char m_workspace[64];
- SHA1_WORKSPACE_BLOCK *m_block; // SHA1 pointer to the byte array above
-};
-
-#define GenerateHash( hash, pubData, cubData ) { CSHA1 sha1; sha1.Update( (byte *)pubData, cubData ); sha1.Final(); sha1.GetHash( hash ); }
-
-#if !defined(_MINIMUM_BUILD_)
-// hash comparison function, for use with CUtlMap/CUtlRBTree
-bool HashLessFunc( SHADigest_t const &lhs, SHADigest_t const &rhs );
-
-// utility class for manipulating SHA1 hashes in their compact form
-struct CSHA
-{
-public:
- SHADigest_t m_shaDigest;
-
- CSHA()
- {
- memset( m_shaDigest, 0, k_cubHash );
- }
-
- explicit CSHA( const SHADigest_t rhs )
- {
- memcpy( m_shaDigest, rhs, k_cubHash );
- }
-
- SHADigest_t &SHADigest()
- {
- return m_shaDigest;
- }
-
- bool operator<( const CSHA &rhs ) const
- {
- return memcmp( m_shaDigest, rhs.m_shaDigest, k_cubHash ) < 0;
- }
-
- bool operator==( const CSHA &rhs ) const
- {
- return memcmp( m_shaDigest, rhs.m_shaDigest, k_cubHash ) == 0;
- }
-
- bool operator!=( const CSHA &rhs ) const
- {
- return !(*this == rhs);
- }
-
- bool operator==( const SHADigest_t &rhs ) const
- {
- return memcmp( m_shaDigest, rhs, k_cubHash ) == 0;
- }
-
- bool operator!=( const SHADigest_t &rhs ) const
- {
- return !(*this == rhs);
- }
-
- CSHA &operator=( const SHADigest_t rhs )
- {
- memcpy( m_shaDigest, rhs, k_cubHash );
- return *this;
- }
-
- void AssignTo( SHADigest_t rhs ) const
- {
- memcpy( rhs, m_shaDigest, k_cubHash );
- }
-};
-#endif // _MINIMUM_BUILD_
-
-#endif // CHECKSUM_SHA1_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Implementation of SHA-1
+//
+//=============================================================================
+
+#ifndef CHECKSUM_SHA1_H
+#define CHECKSUM_SHA1_H
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+/*
+ 100% free public domain implementation of the SHA-1
+ algorithm by Dominik Reichl <[email protected]>
+
+
+ === Test Vectors (from FIPS PUB 180-1) ===
+
+ SHA1("abc") =
+ A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+
+ SHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") =
+ 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+
+ SHA1(A million repetitions of "a") =
+ 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+#if !defined(_MINIMUM_BUILD_)
+#include <stdio.h> // Needed for file access
+#if defined( _PS3 )
+#include <sys/memory.h>
+#else
+#include <memory.h>
+#endif
+#include <string.h> // Needed for strcat and strcpy
+#endif
+
+// If you're compiling big endian, just comment out the following line
+#define SHA1_LITTLE_ENDIAN
+
+typedef union
+{
+ unsigned char c[64];
+ unsigned long l[16];
+} SHA1_WORKSPACE_BLOCK;
+
+// SHA1 hash
+const unsigned int k_cubHash = 20;
+const unsigned int k_cchHash = 41; // k_cubHash * 2, plus 1 for terminator
+#pragma pack( push, 1 )
+typedef unsigned char SHADigest_t[ k_cubHash ];
+#pragma pack( pop )
+
+#if !defined(_MINIMUM_BUILD_)
+class CSHA1
+#else
+class Minimum_CSHA1
+#endif
+{
+public:
+ // Two different formats for ReportHash(...)
+ enum
+ {
+ REPORT_HEX = 0,
+ REPORT_DIGIT = 1
+ };
+
+ // Constructor and Destructor
+#if !defined(_MINIMUM_BUILD_)
+ CSHA1();
+ virtual ~CSHA1() ;
+#else
+ Minimum_CSHA1() ;
+ ~Minimum_CSHA1() ; // no virtual destructor's in the minimal builds !
+#endif
+
+ unsigned long m_state[5];
+ unsigned long m_count[2];
+ unsigned char m_buffer[64];
+ unsigned char m_digest[k_cubHash];
+
+ void Reset();
+
+ // Update the hash value
+ void Update(unsigned char *data, unsigned int len);
+#if !defined(_MINIMUM_BUILD_)
+ bool HashFile(char *szFileName);
+#endif
+
+ // Finalize hash and report
+ void Final();
+#if !defined(_MINIMUM_BUILD_)
+ void ReportHash(char *szReport, unsigned char uReportType = REPORT_HEX);
+#endif
+ void GetHash(unsigned char *uDest);
+
+private:
+ // Private SHA-1 transformation
+ void Transform(unsigned long state[5], unsigned char buffer[64]);
+
+ // Member variables
+ unsigned char m_workspace[64];
+ SHA1_WORKSPACE_BLOCK *m_block; // SHA1 pointer to the byte array above
+};
+
+#define GenerateHash( hash, pubData, cubData ) { CSHA1 sha1; sha1.Update( (byte *)pubData, cubData ); sha1.Final(); sha1.GetHash( hash ); }
+
+#if !defined(_MINIMUM_BUILD_)
+// hash comparison function, for use with CUtlMap/CUtlRBTree
+bool HashLessFunc( SHADigest_t const &lhs, SHADigest_t const &rhs );
+
+// utility class for manipulating SHA1 hashes in their compact form
+struct CSHA
+{
+public:
+ SHADigest_t m_shaDigest;
+
+ CSHA()
+ {
+ memset( m_shaDigest, 0, k_cubHash );
+ }
+
+ explicit CSHA( const SHADigest_t rhs )
+ {
+ memcpy( m_shaDigest, rhs, k_cubHash );
+ }
+
+ SHADigest_t &SHADigest()
+ {
+ return m_shaDigest;
+ }
+
+ bool operator<( const CSHA &rhs ) const
+ {
+ return memcmp( m_shaDigest, rhs.m_shaDigest, k_cubHash ) < 0;
+ }
+
+ bool operator==( const CSHA &rhs ) const
+ {
+ return memcmp( m_shaDigest, rhs.m_shaDigest, k_cubHash ) == 0;
+ }
+
+ bool operator!=( const CSHA &rhs ) const
+ {
+ return !(*this == rhs);
+ }
+
+ bool operator==( const SHADigest_t &rhs ) const
+ {
+ return memcmp( m_shaDigest, rhs, k_cubHash ) == 0;
+ }
+
+ bool operator!=( const SHADigest_t &rhs ) const
+ {
+ return !(*this == rhs);
+ }
+
+ CSHA &operator=( const SHADigest_t rhs )
+ {
+ memcpy( m_shaDigest, rhs, k_cubHash );
+ return *this;
+ }
+
+ void AssignTo( SHADigest_t rhs ) const
+ {
+ memcpy( rhs, m_shaDigest, k_cubHash );
+ }
+};
+#endif // _MINIMUM_BUILD_
+
+#endif // CHECKSUM_SHA1_H
diff --git a/mp/src/public/tier1/convar.h b/mp/src/public/tier1/convar.h
index 7cf21f53..2174e1f9 100644
--- a/mp/src/public/tier1/convar.h
+++ b/mp/src/public/tier1/convar.h
@@ -1,672 +1,672 @@
-//========= Copyright 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 "icvar.h"
-
-#ifdef _WIN32
-#define FORCEINLINE_CVAR FORCEINLINE
-#elif POSIX
-#define FORCEINLINE_CVAR inline
-#else
-#error "implement me"
-#endif
-
-
-//-----------------------------------------------------------------------------
-// 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( _X360 ) && !defined( _RETAIL )
-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 );
-
- // 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;
-
-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;
- virtual void AddFlags( int flags );
- virtual bool IsCommand( void ) const;
-
- // Install a change callback (there shouldn't already be one....)
- void InstallChangeCallback( FnChangeCallback_t callback );
-
- // Retrieve value
- FORCEINLINE_CVAR float GetFloat( void ) const;
- FORCEINLINE_CVAR int GetInt( void ) const;
- FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); }
- FORCEINLINE_CVAR char const *GetString( void ) 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 );
-
- // Reset to default value
- void Revert( void );
-
- // True if it has a min/max setting
- bool GetMin( float& minVal ) const;
- bool GetMax( float& maxVal ) const;
- const char *GetDefault( void ) const;
- void SetDefault( const char *pszDefault );
-
-private:
- // 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 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();
- int GetFlags() { return m_pParent->m_nFlags; }
-private:
-
- // 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;
-
- // Value
- // Dynamically allocated
- char *m_pszString;
- int m_StringLength;
-
- // Values
- float m_fValue;
- int m_nValue;
-
- // Min/Max values
- bool m_bHasMin;
- float m_fMinVal;
- bool m_bHasMax;
- float m_fMaxVal;
-
- // Call this function when ConVar changes
- FnChangeCallback_t m_fnChangeCallback;
-};
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Return ConVar value as a float
-// Output : float
-//-----------------------------------------------------------------------------
-FORCEINLINE_CVAR float ConVar::GetFloat( void ) const
-{
- return m_pParent->m_fValue;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Return ConVar value as an int
-// Output : int
-//-----------------------------------------------------------------------------
-FORCEINLINE_CVAR int ConVar::GetInt( void ) const
-{
- return m_pParent->m_nValue;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
-// Output : const char *
-//-----------------------------------------------------------------------------
-FORCEINLINE_CVAR const char *ConVar::GetString( void ) const
-{
- if ( m_nFlags & FCVAR_NEVER_AS_STRING )
- return "FCVAR_NEVER_AS_STRING";
-
- return ( m_pParent->m_pszString ) ? m_pParent->m_pszString : "";
-}
-
-
-//-----------------------------------------------------------------------------
-// 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;
- 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( bool bValue );
-
- const char *GetName() const;
-
- const char *GetDefault() 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();
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Return ConVar value as a float
-//-----------------------------------------------------------------------------
-FORCEINLINE_CVAR float ConVarRef::GetFloat( void ) const
-{
- return m_pConVarState->m_fValue;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Return ConVar value as an int
-//-----------------------------------------------------------------------------
-FORCEINLINE_CVAR int ConVarRef::GetInt( void ) const
-{
- return m_pConVarState->m_nValue;
-}
-
-//-----------------------------------------------------------------------------
-// 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_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( bool bValue )
-{
- m_pConVar->SetValue( bValue ? 1 : 0 );
-}
-
-FORCEINLINE_CVAR const char *ConVarRef::GetDefault() const
-{
- return 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_PrintFlags( const ConCommandBase *var );
-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
+//========= Copyright 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 "icvar.h"
+
+#ifdef _WIN32
+#define FORCEINLINE_CVAR FORCEINLINE
+#elif POSIX
+#define FORCEINLINE_CVAR inline
+#else
+#error "implement me"
+#endif
+
+
+//-----------------------------------------------------------------------------
+// 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( _X360 ) && !defined( _RETAIL )
+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 );
+
+ // 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;
+
+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;
+ virtual void AddFlags( int flags );
+ virtual bool IsCommand( void ) const;
+
+ // Install a change callback (there shouldn't already be one....)
+ void InstallChangeCallback( FnChangeCallback_t callback );
+
+ // Retrieve value
+ FORCEINLINE_CVAR float GetFloat( void ) const;
+ FORCEINLINE_CVAR int GetInt( void ) const;
+ FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); }
+ FORCEINLINE_CVAR char const *GetString( void ) 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 );
+
+ // Reset to default value
+ void Revert( void );
+
+ // True if it has a min/max setting
+ bool GetMin( float& minVal ) const;
+ bool GetMax( float& maxVal ) const;
+ const char *GetDefault( void ) const;
+ void SetDefault( const char *pszDefault );
+
+private:
+ // 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 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();
+ int GetFlags() { return m_pParent->m_nFlags; }
+private:
+
+ // 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;
+
+ // Value
+ // Dynamically allocated
+ char *m_pszString;
+ int m_StringLength;
+
+ // Values
+ float m_fValue;
+ int m_nValue;
+
+ // Min/Max values
+ bool m_bHasMin;
+ float m_fMinVal;
+ bool m_bHasMax;
+ float m_fMaxVal;
+
+ // Call this function when ConVar changes
+ FnChangeCallback_t m_fnChangeCallback;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Return ConVar value as a float
+// Output : float
+//-----------------------------------------------------------------------------
+FORCEINLINE_CVAR float ConVar::GetFloat( void ) const
+{
+ return m_pParent->m_fValue;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return ConVar value as an int
+// Output : int
+//-----------------------------------------------------------------------------
+FORCEINLINE_CVAR int ConVar::GetInt( void ) const
+{
+ return m_pParent->m_nValue;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
+// Output : const char *
+//-----------------------------------------------------------------------------
+FORCEINLINE_CVAR const char *ConVar::GetString( void ) const
+{
+ if ( m_nFlags & FCVAR_NEVER_AS_STRING )
+ return "FCVAR_NEVER_AS_STRING";
+
+ return ( m_pParent->m_pszString ) ? m_pParent->m_pszString : "";
+}
+
+
+//-----------------------------------------------------------------------------
+// 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;
+ 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( bool bValue );
+
+ const char *GetName() const;
+
+ const char *GetDefault() 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();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Return ConVar value as a float
+//-----------------------------------------------------------------------------
+FORCEINLINE_CVAR float ConVarRef::GetFloat( void ) const
+{
+ return m_pConVarState->m_fValue;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return ConVar value as an int
+//-----------------------------------------------------------------------------
+FORCEINLINE_CVAR int ConVarRef::GetInt( void ) const
+{
+ return m_pConVarState->m_nValue;
+}
+
+//-----------------------------------------------------------------------------
+// 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_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( bool bValue )
+{
+ m_pConVar->SetValue( bValue ? 1 : 0 );
+}
+
+FORCEINLINE_CVAR const char *ConVarRef::GetDefault() const
+{
+ return 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_PrintFlags( const ConCommandBase *var );
+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/mp/src/public/tier1/convar_serverbounded.h b/mp/src/public/tier1/convar_serverbounded.h
index 59287ec6..3bdd1ab3 100644
--- a/mp/src/public/tier1/convar_serverbounded.h
+++ b/mp/src/public/tier1/convar_serverbounded.h
@@ -1,53 +1,53 @@
-//========= Copyright 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
+//========= Copyright 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/mp/src/public/tier1/datamanager.h b/mp/src/public/tier1/datamanager.h
index 6c72bf9e..88030547 100644
--- a/mp/src/public/tier1/datamanager.h
+++ b/mp/src/public/tier1/datamanager.h
@@ -1,277 +1,277 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-//=============================================================================//
-
-#ifndef RESOURCEMANAGER_H
-#define RESOURCEMANAGER_H
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include "tier0/threadtools.h"
-#include "utlmultilist.h"
-#include "utlvector.h"
-
-FORWARD_DECLARE_HANDLE( memhandle_t );
-
-#define INVALID_MEMHANDLE ((memhandle_t)0xffffffff)
-
-class CDataManagerBase
-{
-public:
-
- // public API
- // -----------------------------------------------------------------------------
- // memhandle_t CreateResource( params ) // implemented by derived class
- void DestroyResource( memhandle_t handle );
-
- // type-safe implementation in derived class
- //void *LockResource( memhandle_t handle );
- int UnlockResource( memhandle_t handle );
- void TouchResource( memhandle_t handle );
- void MarkAsStale( memhandle_t handle ); // move to head of LRU
-
- int LockCount( memhandle_t handle );
- int BreakLock( memhandle_t handle );
- int BreakAllLocks();
-
- // HACKHACK: For convenience - offers no lock protection
- // type-safe implementation in derived class
- //void *GetResource_NoLock( memhandle_t handle );
-
- unsigned int TargetSize();
- unsigned int AvailableSize();
- unsigned int UsedSize();
-
- void NotifySizeChanged( memhandle_t handle, unsigned int oldSize, unsigned int newSize );
-
- void SetTargetSize( unsigned int targetSize );
-
- // NOTE: flush is equivalent to Destroy
- unsigned int FlushAllUnlocked();
- unsigned int FlushToTargetSize();
- unsigned int FlushAll();
- unsigned int Purge( unsigned int nBytesToPurge );
- unsigned int EnsureCapacity( unsigned int size );
-
- // Thread lock
- virtual void Lock() {}
- virtual bool TryLock() { return true; }
- virtual void Unlock() {}
-
- // Iteration
-
- // -----------------------------------------------------------------------------
-
- // Debugging only!!!!
- void GetLRUHandleList( CUtlVector< memhandle_t >& list );
- void GetLockHandleList( CUtlVector< memhandle_t >& list );
-
-
-protected:
- // derived class must call these to implement public API
- unsigned short CreateHandle( bool bCreateLocked );
- memhandle_t StoreResourceInHandle( unsigned short memoryIndex, void *pStore, unsigned int realSize );
- void *GetResource_NoLock( memhandle_t handle );
- void *GetResource_NoLockNoLRUTouch( memhandle_t handle );
- void *LockResource( memhandle_t handle );
-
- // NOTE: you must call this from the destructor of the derived class! (will assert otherwise)
- void FreeAllLists() { FlushAll(); m_listsAreFreed = true; }
-
- CDataManagerBase( unsigned int maxSize );
- virtual ~CDataManagerBase();
-
-
- inline unsigned int MemTotal_Inline() const { return m_targetMemorySize; }
- inline unsigned int MemAvailable_Inline() const { return m_targetMemorySize - m_memUsed; }
- inline unsigned int MemUsed_Inline() const { return m_memUsed; }
-
-// Implemented by derived class:
- virtual void DestroyResourceStorage( void * ) = 0;
- virtual unsigned int GetRealSize( void * ) = 0;
-
- memhandle_t ToHandle( unsigned short index );
- unsigned short FromHandle( memhandle_t handle );
-
- void TouchByIndex( unsigned short memoryIndex );
- void * GetForFreeByIndex( unsigned short memoryIndex );
-
- // One of these is stored per active allocation
- struct resource_lru_element_t
- {
- resource_lru_element_t()
- {
- lockCount = 0;
- serial = 1;
- pStore = 0;
- }
-
- unsigned short lockCount;
- unsigned short serial;
- void *pStore;
- };
-
- unsigned int m_targetMemorySize;
- unsigned int m_memUsed;
-
- CUtlMultiList< resource_lru_element_t, unsigned short > m_memoryLists;
-
- unsigned short m_lruList;
- unsigned short m_lockList;
- unsigned short m_freeList;
- unsigned short m_listsAreFreed : 1;
- unsigned short m_unused : 15;
-
-};
-
-template< class STORAGE_TYPE, class CREATE_PARAMS, class LOCK_TYPE = STORAGE_TYPE *, class MUTEX_TYPE = CThreadNullMutex>
-class CDataManager : public CDataManagerBase
-{
- typedef CDataManagerBase BaseClass;
-public:
-
- CDataManager<STORAGE_TYPE, CREATE_PARAMS, LOCK_TYPE, MUTEX_TYPE>( unsigned int size = (unsigned)-1 ) : BaseClass(size) {}
-
-
- ~CDataManager<STORAGE_TYPE, CREATE_PARAMS, LOCK_TYPE, MUTEX_TYPE>()
- {
- // NOTE: This must be called in all implementations of CDataManager
- FreeAllLists();
- }
-
- // Use GetData() to translate pointer to LOCK_TYPE
- LOCK_TYPE LockResource( memhandle_t hMem )
- {
- void *pLock = BaseClass::LockResource( hMem );
- if ( pLock )
- {
- return StoragePointer(pLock)->GetData();
- }
-
- return NULL;
- }
-
- // Use GetData() to translate pointer to LOCK_TYPE
- LOCK_TYPE GetResource_NoLock( memhandle_t hMem )
- {
- void *pLock = const_cast<void *>(BaseClass::GetResource_NoLock( hMem ));
- if ( pLock )
- {
- return StoragePointer(pLock)->GetData();
- }
- return NULL;
- }
-
- // Use GetData() to translate pointer to LOCK_TYPE
- // Doesn't touch the memory LRU
- LOCK_TYPE GetResource_NoLockNoLRUTouch( memhandle_t hMem )
- {
- void *pLock = const_cast<void *>(BaseClass::GetResource_NoLockNoLRUTouch( hMem ));
- if ( pLock )
- {
- return StoragePointer(pLock)->GetData();
- }
- return NULL;
- }
-
- // Wrapper to match implementation of allocation with typed storage & alloc params.
- memhandle_t CreateResource( const CREATE_PARAMS &createParams, bool bCreateLocked = false )
- {
- BaseClass::EnsureCapacity(STORAGE_TYPE::EstimatedSize(createParams));
- unsigned short memoryIndex = BaseClass::CreateHandle( bCreateLocked );
- STORAGE_TYPE *pStore = STORAGE_TYPE::CreateResource( createParams );
- return BaseClass::StoreResourceInHandle( memoryIndex, pStore, pStore->Size() );
- }
-
- // Iteration. Must lock first
- memhandle_t GetFirstUnlocked()
- {
- unsigned node = m_memoryLists.Head(m_lruList);
- if ( node == m_memoryLists.InvalidIndex() )
- {
- return INVALID_MEMHANDLE;
- }
- return ToHandle( node );
- }
-
- memhandle_t GetFirstLocked()
- {
- unsigned node = m_memoryLists.Head(m_lockList);
- if ( node == m_memoryLists.InvalidIndex() )
- {
- return INVALID_MEMHANDLE;
- }
- return ToHandle( node );
- }
-
- memhandle_t GetNext( memhandle_t hPrev )
- {
- if ( hPrev == INVALID_MEMHANDLE )
- {
- return INVALID_MEMHANDLE;
- }
-
- unsigned short iNext = m_memoryLists.Next( FromHandle( hPrev ) );
- if ( iNext == m_memoryLists.InvalidIndex() )
- {
- return INVALID_MEMHANDLE;
- }
-
- return ToHandle( iNext );
- }
-
- MUTEX_TYPE &AccessMutex() { return m_mutex; }
- virtual void Lock() { m_mutex.Lock(); }
- virtual bool TryLock() { return m_mutex.TryLock(); }
- virtual void Unlock() { m_mutex.Unlock(); }
-
-private:
- STORAGE_TYPE *StoragePointer( void *pMem )
- {
- return static_cast<STORAGE_TYPE *>(pMem);
- }
-
- virtual void DestroyResourceStorage( void *pStore )
- {
- StoragePointer(pStore)->DestroyResource();
- }
-
- virtual unsigned int GetRealSize( void *pStore )
- {
- return StoragePointer(pStore)->Size();
- }
-
- MUTEX_TYPE m_mutex;
-};
-
-//-----------------------------------------------------------------------------
-
-inline unsigned short CDataManagerBase::FromHandle( memhandle_t handle )
-{
- unsigned int fullWord = (unsigned int)handle;
- unsigned short serial = fullWord>>16;
- unsigned short index = fullWord & 0xFFFF;
- index--;
- if ( m_memoryLists.IsValidIndex(index) && m_memoryLists[index].serial == serial )
- return index;
- return m_memoryLists.InvalidIndex();
-}
-
-inline int CDataManagerBase::LockCount( memhandle_t handle )
-{
- Lock();
- int result = 0;
- unsigned short memoryIndex = FromHandle(handle);
- if ( memoryIndex != m_memoryLists.InvalidIndex() )
- {
- result = m_memoryLists[memoryIndex].lockCount;
- }
- Unlock();
- return result;
-}
-
-
-#endif // RESOURCEMANAGER_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#ifndef RESOURCEMANAGER_H
+#define RESOURCEMANAGER_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/threadtools.h"
+#include "utlmultilist.h"
+#include "utlvector.h"
+
+FORWARD_DECLARE_HANDLE( memhandle_t );
+
+#define INVALID_MEMHANDLE ((memhandle_t)0xffffffff)
+
+class CDataManagerBase
+{
+public:
+
+ // public API
+ // -----------------------------------------------------------------------------
+ // memhandle_t CreateResource( params ) // implemented by derived class
+ void DestroyResource( memhandle_t handle );
+
+ // type-safe implementation in derived class
+ //void *LockResource( memhandle_t handle );
+ int UnlockResource( memhandle_t handle );
+ void TouchResource( memhandle_t handle );
+ void MarkAsStale( memhandle_t handle ); // move to head of LRU
+
+ int LockCount( memhandle_t handle );
+ int BreakLock( memhandle_t handle );
+ int BreakAllLocks();
+
+ // HACKHACK: For convenience - offers no lock protection
+ // type-safe implementation in derived class
+ //void *GetResource_NoLock( memhandle_t handle );
+
+ unsigned int TargetSize();
+ unsigned int AvailableSize();
+ unsigned int UsedSize();
+
+ void NotifySizeChanged( memhandle_t handle, unsigned int oldSize, unsigned int newSize );
+
+ void SetTargetSize( unsigned int targetSize );
+
+ // NOTE: flush is equivalent to Destroy
+ unsigned int FlushAllUnlocked();
+ unsigned int FlushToTargetSize();
+ unsigned int FlushAll();
+ unsigned int Purge( unsigned int nBytesToPurge );
+ unsigned int EnsureCapacity( unsigned int size );
+
+ // Thread lock
+ virtual void Lock() {}
+ virtual bool TryLock() { return true; }
+ virtual void Unlock() {}
+
+ // Iteration
+
+ // -----------------------------------------------------------------------------
+
+ // Debugging only!!!!
+ void GetLRUHandleList( CUtlVector< memhandle_t >& list );
+ void GetLockHandleList( CUtlVector< memhandle_t >& list );
+
+
+protected:
+ // derived class must call these to implement public API
+ unsigned short CreateHandle( bool bCreateLocked );
+ memhandle_t StoreResourceInHandle( unsigned short memoryIndex, void *pStore, unsigned int realSize );
+ void *GetResource_NoLock( memhandle_t handle );
+ void *GetResource_NoLockNoLRUTouch( memhandle_t handle );
+ void *LockResource( memhandle_t handle );
+
+ // NOTE: you must call this from the destructor of the derived class! (will assert otherwise)
+ void FreeAllLists() { FlushAll(); m_listsAreFreed = true; }
+
+ CDataManagerBase( unsigned int maxSize );
+ virtual ~CDataManagerBase();
+
+
+ inline unsigned int MemTotal_Inline() const { return m_targetMemorySize; }
+ inline unsigned int MemAvailable_Inline() const { return m_targetMemorySize - m_memUsed; }
+ inline unsigned int MemUsed_Inline() const { return m_memUsed; }
+
+// Implemented by derived class:
+ virtual void DestroyResourceStorage( void * ) = 0;
+ virtual unsigned int GetRealSize( void * ) = 0;
+
+ memhandle_t ToHandle( unsigned short index );
+ unsigned short FromHandle( memhandle_t handle );
+
+ void TouchByIndex( unsigned short memoryIndex );
+ void * GetForFreeByIndex( unsigned short memoryIndex );
+
+ // One of these is stored per active allocation
+ struct resource_lru_element_t
+ {
+ resource_lru_element_t()
+ {
+ lockCount = 0;
+ serial = 1;
+ pStore = 0;
+ }
+
+ unsigned short lockCount;
+ unsigned short serial;
+ void *pStore;
+ };
+
+ unsigned int m_targetMemorySize;
+ unsigned int m_memUsed;
+
+ CUtlMultiList< resource_lru_element_t, unsigned short > m_memoryLists;
+
+ unsigned short m_lruList;
+ unsigned short m_lockList;
+ unsigned short m_freeList;
+ unsigned short m_listsAreFreed : 1;
+ unsigned short m_unused : 15;
+
+};
+
+template< class STORAGE_TYPE, class CREATE_PARAMS, class LOCK_TYPE = STORAGE_TYPE *, class MUTEX_TYPE = CThreadNullMutex>
+class CDataManager : public CDataManagerBase
+{
+ typedef CDataManagerBase BaseClass;
+public:
+
+ CDataManager<STORAGE_TYPE, CREATE_PARAMS, LOCK_TYPE, MUTEX_TYPE>( unsigned int size = (unsigned)-1 ) : BaseClass(size) {}
+
+
+ ~CDataManager<STORAGE_TYPE, CREATE_PARAMS, LOCK_TYPE, MUTEX_TYPE>()
+ {
+ // NOTE: This must be called in all implementations of CDataManager
+ FreeAllLists();
+ }
+
+ // Use GetData() to translate pointer to LOCK_TYPE
+ LOCK_TYPE LockResource( memhandle_t hMem )
+ {
+ void *pLock = BaseClass::LockResource( hMem );
+ if ( pLock )
+ {
+ return StoragePointer(pLock)->GetData();
+ }
+
+ return NULL;
+ }
+
+ // Use GetData() to translate pointer to LOCK_TYPE
+ LOCK_TYPE GetResource_NoLock( memhandle_t hMem )
+ {
+ void *pLock = const_cast<void *>(BaseClass::GetResource_NoLock( hMem ));
+ if ( pLock )
+ {
+ return StoragePointer(pLock)->GetData();
+ }
+ return NULL;
+ }
+
+ // Use GetData() to translate pointer to LOCK_TYPE
+ // Doesn't touch the memory LRU
+ LOCK_TYPE GetResource_NoLockNoLRUTouch( memhandle_t hMem )
+ {
+ void *pLock = const_cast<void *>(BaseClass::GetResource_NoLockNoLRUTouch( hMem ));
+ if ( pLock )
+ {
+ return StoragePointer(pLock)->GetData();
+ }
+ return NULL;
+ }
+
+ // Wrapper to match implementation of allocation with typed storage & alloc params.
+ memhandle_t CreateResource( const CREATE_PARAMS &createParams, bool bCreateLocked = false )
+ {
+ BaseClass::EnsureCapacity(STORAGE_TYPE::EstimatedSize(createParams));
+ unsigned short memoryIndex = BaseClass::CreateHandle( bCreateLocked );
+ STORAGE_TYPE *pStore = STORAGE_TYPE::CreateResource( createParams );
+ return BaseClass::StoreResourceInHandle( memoryIndex, pStore, pStore->Size() );
+ }
+
+ // Iteration. Must lock first
+ memhandle_t GetFirstUnlocked()
+ {
+ unsigned node = m_memoryLists.Head(m_lruList);
+ if ( node == m_memoryLists.InvalidIndex() )
+ {
+ return INVALID_MEMHANDLE;
+ }
+ return ToHandle( node );
+ }
+
+ memhandle_t GetFirstLocked()
+ {
+ unsigned node = m_memoryLists.Head(m_lockList);
+ if ( node == m_memoryLists.InvalidIndex() )
+ {
+ return INVALID_MEMHANDLE;
+ }
+ return ToHandle( node );
+ }
+
+ memhandle_t GetNext( memhandle_t hPrev )
+ {
+ if ( hPrev == INVALID_MEMHANDLE )
+ {
+ return INVALID_MEMHANDLE;
+ }
+
+ unsigned short iNext = m_memoryLists.Next( FromHandle( hPrev ) );
+ if ( iNext == m_memoryLists.InvalidIndex() )
+ {
+ return INVALID_MEMHANDLE;
+ }
+
+ return ToHandle( iNext );
+ }
+
+ MUTEX_TYPE &AccessMutex() { return m_mutex; }
+ virtual void Lock() { m_mutex.Lock(); }
+ virtual bool TryLock() { return m_mutex.TryLock(); }
+ virtual void Unlock() { m_mutex.Unlock(); }
+
+private:
+ STORAGE_TYPE *StoragePointer( void *pMem )
+ {
+ return static_cast<STORAGE_TYPE *>(pMem);
+ }
+
+ virtual void DestroyResourceStorage( void *pStore )
+ {
+ StoragePointer(pStore)->DestroyResource();
+ }
+
+ virtual unsigned int GetRealSize( void *pStore )
+ {
+ return StoragePointer(pStore)->Size();
+ }
+
+ MUTEX_TYPE m_mutex;
+};
+
+//-----------------------------------------------------------------------------
+
+inline unsigned short CDataManagerBase::FromHandle( memhandle_t handle )
+{
+ unsigned int fullWord = (unsigned int)handle;
+ unsigned short serial = fullWord>>16;
+ unsigned short index = fullWord & 0xFFFF;
+ index--;
+ if ( m_memoryLists.IsValidIndex(index) && m_memoryLists[index].serial == serial )
+ return index;
+ return m_memoryLists.InvalidIndex();
+}
+
+inline int CDataManagerBase::LockCount( memhandle_t handle )
+{
+ Lock();
+ int result = 0;
+ unsigned short memoryIndex = FromHandle(handle);
+ if ( memoryIndex != m_memoryLists.InvalidIndex() )
+ {
+ result = m_memoryLists[memoryIndex].lockCount;
+ }
+ Unlock();
+ return result;
+}
+
+
+#endif // RESOURCEMANAGER_H
diff --git a/mp/src/public/tier1/delegates.h b/mp/src/public/tier1/delegates.h
index a81d70ec..35a50cf7 100644
--- a/mp/src/public/tier1/delegates.h
+++ b/mp/src/public/tier1/delegates.h
@@ -1,99 +1,99 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Simple macros to generate delegation code
-//
-//=============================================================================
-
-#ifndef DELEGATES_H
-#define DELEGATES_H
-
-#if defined( _WIN32 )
-#pragma once
-#endif
-
-#define DELEGATE_TO_OBJECT_0( RetType, FuncName, pDelegated ) RetType FuncName() { return (pDelegated)->FuncName(); }
-#define DELEGATE_TO_OBJECT_0V( FuncName, pDelegated ) void FuncName() { (pDelegated)->FuncName(); }
-#define DELEGATE_TO_OBJECT_1( RetType, FuncName, ArgType1, pDelegated ) RetType FuncName( ArgType1 a1 ) { return (pDelegated)->FuncName( a1 ); }
-#define DELEGATE_TO_OBJECT_1V( FuncName, ArgType1, pDelegated ) void FuncName( ArgType1 a1 ) { (pDelegated)->FuncName( a1 ); }
-#define DELEGATE_TO_OBJECT_2( RetType, FuncName, ArgType1, ArgType2, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2 ) { return (pDelegated)->FuncName( a1, a2 ); }
-#define DELEGATE_TO_OBJECT_2V( FuncName, ArgType1, ArgType2, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2 ) { (pDelegated)->FuncName( a1, a2 ); }
-#define DELEGATE_TO_OBJECT_3( RetType, FuncName, ArgType1, ArgType2, ArgType3, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) { return (pDelegated)->FuncName( a1, a2, a3 ); }
-#define DELEGATE_TO_OBJECT_3V( FuncName, ArgType1, ArgType2, ArgType3, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) { (pDelegated)->FuncName( a1, a2, a3 ); }
-#define DELEGATE_TO_OBJECT_4( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) { return (pDelegated)->FuncName( a1, a2, a3, a4 ); }
-#define DELEGATE_TO_OBJECT_4V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) { (pDelegated)->FuncName( a1, a2, a3, a4 ); }
-#define DELEGATE_TO_OBJECT_5( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) { return (pDelegated)->FuncName( a1, a2, a3, a4, a5 ); }
-#define DELEGATE_TO_OBJECT_5V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) { (pDelegated)->FuncName( a1, a2, a3, a4, a5 ); }
-#define DELEGATE_TO_OBJECT_6( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6 ); }
-#define DELEGATE_TO_OBJECT_6V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6 ); }
-#define DELEGATE_TO_OBJECT_7( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7 ); }
-#define DELEGATE_TO_OBJECT_7V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7 ); }
-#define DELEGATE_TO_OBJECT_8( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); }
-#define DELEGATE_TO_OBJECT_8V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); }
-#define DELEGATE_TO_OBJECT_9( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); }
-#define DELEGATE_TO_OBJECT_9V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); }
-#define DELEGATE_TO_OBJECT_11V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9, ArgType10 a10, ArgType11 a11 ) { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 ); }
-
-#define DELEGATE_TO_OBJECT_0C( RetType, FuncName, pDelegated ) RetType FuncName() const { return (pDelegated)->FuncName(); }
-#define DELEGATE_TO_OBJECT_0VC( FuncName, pDelegated ) void FuncName() const { (pDelegated)->FuncName(); }
-#define DELEGATE_TO_OBJECT_1C( RetType, FuncName, ArgType1, pDelegated ) RetType FuncName( ArgType1 a1 ) const { return (pDelegated)->FuncName( a1 ); }
-#define DELEGATE_TO_OBJECT_1VC( FuncName, ArgType1, pDelegated ) void FuncName( ArgType1 a1 ) const { (pDelegated)->FuncName( a1 ); }
-#define DELEGATE_TO_OBJECT_2C( RetType, FuncName, ArgType1, ArgType2, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2 ) const { return (pDelegated)->FuncName( a1, a2 ); }
-#define DELEGATE_TO_OBJECT_2VC( FuncName, ArgType1, ArgType2, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2 ) const { (pDelegated)->FuncName( a1, a2 ); }
-#define DELEGATE_TO_OBJECT_3C( RetType, FuncName, ArgType1, ArgType2, ArgType3, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) const { return (pDelegated)->FuncName( a1, a2, a3 ); }
-#define DELEGATE_TO_OBJECT_3VC( FuncName, ArgType1, ArgType2, ArgType3, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) const { (pDelegated)->FuncName( a1, a2, a3 ); }
-#define DELEGATE_TO_OBJECT_4C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) const { return (pDelegated)->FuncName( a1, a2, a3, a4 ); }
-#define DELEGATE_TO_OBJECT_4VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) const { (pDelegated)->FuncName( a1, a2, a3, a4 ); }
-#define DELEGATE_TO_OBJECT_5C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) const { return (pDelegated)->FuncName( a1, a2, a3, a4, a5 ); }
-#define DELEGATE_TO_OBJECT_5VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) const { (pDelegated)->FuncName( a1, a2, a3, a4, a5 ); }
-#define DELEGATE_TO_OBJECT_6C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) const { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6 ); }
-#define DELEGATE_TO_OBJECT_6VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) const { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6 ); }
-#define DELEGATE_TO_OBJECT_7C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) const { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7 ); }
-#define DELEGATE_TO_OBJECT_7VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) const { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7 ); }
-#define DELEGATE_TO_OBJECT_8C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) const { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); }
-#define DELEGATE_TO_OBJECT_8VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) const { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); }
-#define DELEGATE_TO_OBJECT_9C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) const { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); }
-#define DELEGATE_TO_OBJECT_9VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) const { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); }
-
-#define DELEGATE_TO_BASE_0( RetType, FuncName, BaseClass ) RetType FuncName() { return BaseClass::FuncName(); }
-#define DELEGATE_TO_BASE_0V( FuncName, BaseClass ) void FuncName() { BaseClass::FuncName(); }
-#define DELEGATE_TO_BASE_1( RetType, FuncName, ArgType1, BaseClass ) RetType FuncName( ArgType1 a1 ) { return BaseClass::FuncName( a1 ); }
-#define DELEGATE_TO_BASE_1V( FuncName, ArgType1, BaseClass ) void FuncName( ArgType1 a1 ) { BaseClass::FuncName( a1 ); }
-#define DELEGATE_TO_BASE_2( RetType, FuncName, ArgType1, ArgType2, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2 ) { return BaseClass::FuncName( a1, a2 ); }
-#define DELEGATE_TO_BASE_2V( FuncName, ArgType1, ArgType2, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2 ) { BaseClass::FuncName( a1, a2 ); }
-#define DELEGATE_TO_BASE_3( RetType, FuncName, ArgType1, ArgType2, ArgType3, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) { return BaseClass::FuncName( a1, a2, a3 ); }
-#define DELEGATE_TO_BASE_3V( FuncName, ArgType1, ArgType2, ArgType3, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) { BaseClass::FuncName( a1, a2, a3 ); }
-#define DELEGATE_TO_BASE_4( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) { return BaseClass::FuncName( a1, a2, a3, a4 ); }
-#define DELEGATE_TO_BASE_4V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) { BaseClass::FuncName( a1, a2, a3, a4 ); }
-#define DELEGATE_TO_BASE_5( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) { return BaseClass::FuncName( a1, a2, a3, a4, a5 ); }
-#define DELEGATE_TO_BASE_5V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) { BaseClass::FuncName( a1, a2, a3, a4, a5 ); }
-#define DELEGATE_TO_BASE_6( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6 ); }
-#define DELEGATE_TO_BASE_6V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) { BaseClass::FuncName( a1, a2, a3, a4, a5, a6 ); }
-#define DELEGATE_TO_BASE_7( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7 ); }
-#define DELEGATE_TO_BASE_7V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) { BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7 ); }
-#define DELEGATE_TO_BASE_8( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); }
-#define DELEGATE_TO_BASE_8V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) { BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); }
-#define DELEGATE_TO_BASE_9( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); }
-#define DELEGATE_TO_BASE_9V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) { BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); }
-
-#define DELEGATE_TO_BASE_0C( RetType, FuncName, BaseClass ) RetType FuncName() const { return BaseClass::FuncName(); }
-#define DELEGATE_TO_BASE_0VC( FuncName, BaseClass ) void FuncName() const { BaseClass::FuncName(); }
-#define DELEGATE_TO_BASE_1C( RetType, FuncName, ArgType1, BaseClass ) RetType FuncName( ArgType1 a1 ) const { return BaseClass::FuncName( a1 ); }
-#define DELEGATE_TO_BASE_1VC( FuncName, ArgType1, BaseClass ) void FuncName( ArgType1 a1 ) const { BaseClass::FuncName( a1 ); }
-#define DELEGATE_TO_BASE_2C( RetType, FuncName, ArgType1, ArgType2, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2 ) const { return BaseClass::FuncName( a1, a2 ); }
-#define DELEGATE_TO_BASE_2VC( FuncName, ArgType1, ArgType2, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2 ) const { BaseClass::FuncName( a1, a2 ); }
-#define DELEGATE_TO_BASE_3C( RetType, FuncName, ArgType1, ArgType2, ArgType3, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) const { return BaseClass::FuncName( a1, a2, a3 ); }
-#define DELEGATE_TO_BASE_3VC( FuncName, ArgType1, ArgType2, ArgType3, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) const { BaseClass::FuncName( a1, a2, a3 ); }
-#define DELEGATE_TO_BASE_4C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) const { return BaseClass::FuncName( a1, a2, a3, a4 ); }
-#define DELEGATE_TO_BASE_4VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) const { BaseClass::FuncName( a1, a2, a3, a4 ); }
-#define DELEGATE_TO_BASE_5C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) const { return BaseClass::FuncName( a1, a2, a3, a4, a5 ); }
-#define DELEGATE_TO_BASE_5VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) const { BaseClass::FuncName( a1, a2, a3, a4, a5 ); }
-#define DELEGATE_TO_BASE_6C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) const { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6 ); }
-#define DELEGATE_TO_BASE_6VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) const { BaseClass::FuncName( a1, a2, a3, a4, a5, a6 ); }
-#define DELEGATE_TO_BASE_7C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) const { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7 ); }
-#define DELEGATE_TO_BASE_7VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) const { BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7 ); }
-#define DELEGATE_TO_BASE_8C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) const { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); }
-#define DELEGATE_TO_BASE_8VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) const { BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); }
-#define DELEGATE_TO_BASE_9C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) const { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); }
-#define DELEGATE_TO_BASE_9VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) const { BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); }
-
-#endif // DELEGATES_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Simple macros to generate delegation code
+//
+//=============================================================================
+
+#ifndef DELEGATES_H
+#define DELEGATES_H
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+#define DELEGATE_TO_OBJECT_0( RetType, FuncName, pDelegated ) RetType FuncName() { return (pDelegated)->FuncName(); }
+#define DELEGATE_TO_OBJECT_0V( FuncName, pDelegated ) void FuncName() { (pDelegated)->FuncName(); }
+#define DELEGATE_TO_OBJECT_1( RetType, FuncName, ArgType1, pDelegated ) RetType FuncName( ArgType1 a1 ) { return (pDelegated)->FuncName( a1 ); }
+#define DELEGATE_TO_OBJECT_1V( FuncName, ArgType1, pDelegated ) void FuncName( ArgType1 a1 ) { (pDelegated)->FuncName( a1 ); }
+#define DELEGATE_TO_OBJECT_2( RetType, FuncName, ArgType1, ArgType2, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2 ) { return (pDelegated)->FuncName( a1, a2 ); }
+#define DELEGATE_TO_OBJECT_2V( FuncName, ArgType1, ArgType2, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2 ) { (pDelegated)->FuncName( a1, a2 ); }
+#define DELEGATE_TO_OBJECT_3( RetType, FuncName, ArgType1, ArgType2, ArgType3, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) { return (pDelegated)->FuncName( a1, a2, a3 ); }
+#define DELEGATE_TO_OBJECT_3V( FuncName, ArgType1, ArgType2, ArgType3, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) { (pDelegated)->FuncName( a1, a2, a3 ); }
+#define DELEGATE_TO_OBJECT_4( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) { return (pDelegated)->FuncName( a1, a2, a3, a4 ); }
+#define DELEGATE_TO_OBJECT_4V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) { (pDelegated)->FuncName( a1, a2, a3, a4 ); }
+#define DELEGATE_TO_OBJECT_5( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) { return (pDelegated)->FuncName( a1, a2, a3, a4, a5 ); }
+#define DELEGATE_TO_OBJECT_5V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) { (pDelegated)->FuncName( a1, a2, a3, a4, a5 ); }
+#define DELEGATE_TO_OBJECT_6( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6 ); }
+#define DELEGATE_TO_OBJECT_6V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6 ); }
+#define DELEGATE_TO_OBJECT_7( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7 ); }
+#define DELEGATE_TO_OBJECT_7V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7 ); }
+#define DELEGATE_TO_OBJECT_8( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); }
+#define DELEGATE_TO_OBJECT_8V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); }
+#define DELEGATE_TO_OBJECT_9( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); }
+#define DELEGATE_TO_OBJECT_9V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); }
+#define DELEGATE_TO_OBJECT_11V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9, ArgType10 a10, ArgType11 a11 ) { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 ); }
+
+#define DELEGATE_TO_OBJECT_0C( RetType, FuncName, pDelegated ) RetType FuncName() const { return (pDelegated)->FuncName(); }
+#define DELEGATE_TO_OBJECT_0VC( FuncName, pDelegated ) void FuncName() const { (pDelegated)->FuncName(); }
+#define DELEGATE_TO_OBJECT_1C( RetType, FuncName, ArgType1, pDelegated ) RetType FuncName( ArgType1 a1 ) const { return (pDelegated)->FuncName( a1 ); }
+#define DELEGATE_TO_OBJECT_1VC( FuncName, ArgType1, pDelegated ) void FuncName( ArgType1 a1 ) const { (pDelegated)->FuncName( a1 ); }
+#define DELEGATE_TO_OBJECT_2C( RetType, FuncName, ArgType1, ArgType2, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2 ) const { return (pDelegated)->FuncName( a1, a2 ); }
+#define DELEGATE_TO_OBJECT_2VC( FuncName, ArgType1, ArgType2, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2 ) const { (pDelegated)->FuncName( a1, a2 ); }
+#define DELEGATE_TO_OBJECT_3C( RetType, FuncName, ArgType1, ArgType2, ArgType3, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) const { return (pDelegated)->FuncName( a1, a2, a3 ); }
+#define DELEGATE_TO_OBJECT_3VC( FuncName, ArgType1, ArgType2, ArgType3, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) const { (pDelegated)->FuncName( a1, a2, a3 ); }
+#define DELEGATE_TO_OBJECT_4C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) const { return (pDelegated)->FuncName( a1, a2, a3, a4 ); }
+#define DELEGATE_TO_OBJECT_4VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) const { (pDelegated)->FuncName( a1, a2, a3, a4 ); }
+#define DELEGATE_TO_OBJECT_5C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) const { return (pDelegated)->FuncName( a1, a2, a3, a4, a5 ); }
+#define DELEGATE_TO_OBJECT_5VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) const { (pDelegated)->FuncName( a1, a2, a3, a4, a5 ); }
+#define DELEGATE_TO_OBJECT_6C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) const { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6 ); }
+#define DELEGATE_TO_OBJECT_6VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) const { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6 ); }
+#define DELEGATE_TO_OBJECT_7C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) const { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7 ); }
+#define DELEGATE_TO_OBJECT_7VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) const { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7 ); }
+#define DELEGATE_TO_OBJECT_8C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) const { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); }
+#define DELEGATE_TO_OBJECT_8VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) const { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); }
+#define DELEGATE_TO_OBJECT_9C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) const { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); }
+#define DELEGATE_TO_OBJECT_9VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) const { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); }
+
+#define DELEGATE_TO_BASE_0( RetType, FuncName, BaseClass ) RetType FuncName() { return BaseClass::FuncName(); }
+#define DELEGATE_TO_BASE_0V( FuncName, BaseClass ) void FuncName() { BaseClass::FuncName(); }
+#define DELEGATE_TO_BASE_1( RetType, FuncName, ArgType1, BaseClass ) RetType FuncName( ArgType1 a1 ) { return BaseClass::FuncName( a1 ); }
+#define DELEGATE_TO_BASE_1V( FuncName, ArgType1, BaseClass ) void FuncName( ArgType1 a1 ) { BaseClass::FuncName( a1 ); }
+#define DELEGATE_TO_BASE_2( RetType, FuncName, ArgType1, ArgType2, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2 ) { return BaseClass::FuncName( a1, a2 ); }
+#define DELEGATE_TO_BASE_2V( FuncName, ArgType1, ArgType2, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2 ) { BaseClass::FuncName( a1, a2 ); }
+#define DELEGATE_TO_BASE_3( RetType, FuncName, ArgType1, ArgType2, ArgType3, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) { return BaseClass::FuncName( a1, a2, a3 ); }
+#define DELEGATE_TO_BASE_3V( FuncName, ArgType1, ArgType2, ArgType3, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) { BaseClass::FuncName( a1, a2, a3 ); }
+#define DELEGATE_TO_BASE_4( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) { return BaseClass::FuncName( a1, a2, a3, a4 ); }
+#define DELEGATE_TO_BASE_4V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) { BaseClass::FuncName( a1, a2, a3, a4 ); }
+#define DELEGATE_TO_BASE_5( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) { return BaseClass::FuncName( a1, a2, a3, a4, a5 ); }
+#define DELEGATE_TO_BASE_5V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) { BaseClass::FuncName( a1, a2, a3, a4, a5 ); }
+#define DELEGATE_TO_BASE_6( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6 ); }
+#define DELEGATE_TO_BASE_6V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) { BaseClass::FuncName( a1, a2, a3, a4, a5, a6 ); }
+#define DELEGATE_TO_BASE_7( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7 ); }
+#define DELEGATE_TO_BASE_7V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) { BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7 ); }
+#define DELEGATE_TO_BASE_8( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); }
+#define DELEGATE_TO_BASE_8V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) { BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); }
+#define DELEGATE_TO_BASE_9( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); }
+#define DELEGATE_TO_BASE_9V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) { BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); }
+
+#define DELEGATE_TO_BASE_0C( RetType, FuncName, BaseClass ) RetType FuncName() const { return BaseClass::FuncName(); }
+#define DELEGATE_TO_BASE_0VC( FuncName, BaseClass ) void FuncName() const { BaseClass::FuncName(); }
+#define DELEGATE_TO_BASE_1C( RetType, FuncName, ArgType1, BaseClass ) RetType FuncName( ArgType1 a1 ) const { return BaseClass::FuncName( a1 ); }
+#define DELEGATE_TO_BASE_1VC( FuncName, ArgType1, BaseClass ) void FuncName( ArgType1 a1 ) const { BaseClass::FuncName( a1 ); }
+#define DELEGATE_TO_BASE_2C( RetType, FuncName, ArgType1, ArgType2, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2 ) const { return BaseClass::FuncName( a1, a2 ); }
+#define DELEGATE_TO_BASE_2VC( FuncName, ArgType1, ArgType2, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2 ) const { BaseClass::FuncName( a1, a2 ); }
+#define DELEGATE_TO_BASE_3C( RetType, FuncName, ArgType1, ArgType2, ArgType3, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) const { return BaseClass::FuncName( a1, a2, a3 ); }
+#define DELEGATE_TO_BASE_3VC( FuncName, ArgType1, ArgType2, ArgType3, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) const { BaseClass::FuncName( a1, a2, a3 ); }
+#define DELEGATE_TO_BASE_4C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) const { return BaseClass::FuncName( a1, a2, a3, a4 ); }
+#define DELEGATE_TO_BASE_4VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) const { BaseClass::FuncName( a1, a2, a3, a4 ); }
+#define DELEGATE_TO_BASE_5C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) const { return BaseClass::FuncName( a1, a2, a3, a4, a5 ); }
+#define DELEGATE_TO_BASE_5VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) const { BaseClass::FuncName( a1, a2, a3, a4, a5 ); }
+#define DELEGATE_TO_BASE_6C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) const { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6 ); }
+#define DELEGATE_TO_BASE_6VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) const { BaseClass::FuncName( a1, a2, a3, a4, a5, a6 ); }
+#define DELEGATE_TO_BASE_7C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) const { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7 ); }
+#define DELEGATE_TO_BASE_7VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) const { BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7 ); }
+#define DELEGATE_TO_BASE_8C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) const { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); }
+#define DELEGATE_TO_BASE_8VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) const { BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); }
+#define DELEGATE_TO_BASE_9C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) const { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); }
+#define DELEGATE_TO_BASE_9VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) const { BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); }
+
+#endif // DELEGATES_H
diff --git a/mp/src/public/tier1/diff.h b/mp/src/public/tier1/diff.h
index a17c5087..fc2fb752 100644
--- a/mp/src/public/tier1/diff.h
+++ b/mp/src/public/tier1/diff.h
@@ -1,29 +1,29 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//
-// Serialization/unserialization buffer
-//=============================================================================//
-
-#ifndef DIFF_H
-#define DIFF_H
-#pragma once
-
-int FindDiffs(uint8 const *NewBlock, uint8 const *OldBlock,
- int NewSize, int OldSize, int &DiffListSize,uint8 *Output,uint32 OutSize);
-
-int FindDiffsForLargeFiles(uint8 const *NewBlock, uint8 const *OldBlock,
- int NewSize, int OldSize, int &DiffListSize,uint8 *Output,
- uint32 OutSize,
- int hashsize=65536);
-
-void ApplyDiffs(uint8 const *OldBlock, uint8 const *DiffList,
- int OldSize, int DiffListSize, int &ResultListSize,uint8 *Output,uint32 OutSize);
-
-int FindDiffsLowMemory(uint8 const *NewBlock, uint8 const *OldBlock,
- int NewSize, int OldSize, int &DiffListSize,uint8 *Output,uint32 OutSize);
-
-#endif
-
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+// Serialization/unserialization buffer
+//=============================================================================//
+
+#ifndef DIFF_H
+#define DIFF_H
+#pragma once
+
+int FindDiffs(uint8 const *NewBlock, uint8 const *OldBlock,
+ int NewSize, int OldSize, int &DiffListSize,uint8 *Output,uint32 OutSize);
+
+int FindDiffsForLargeFiles(uint8 const *NewBlock, uint8 const *OldBlock,
+ int NewSize, int OldSize, int &DiffListSize,uint8 *Output,
+ uint32 OutSize,
+ int hashsize=65536);
+
+void ApplyDiffs(uint8 const *OldBlock, uint8 const *DiffList,
+ int OldSize, int DiffListSize, int &ResultListSize,uint8 *Output,uint32 OutSize);
+
+int FindDiffsLowMemory(uint8 const *NewBlock, uint8 const *OldBlock,
+ int NewSize, int OldSize, int &DiffListSize,uint8 *Output,uint32 OutSize);
+
+#endif
+
diff --git a/mp/src/public/tier1/fileio.h b/mp/src/public/tier1/fileio.h
index f2f76e8d..d85ca182 100644
--- a/mp/src/public/tier1/fileio.h
+++ b/mp/src/public/tier1/fileio.h
@@ -1,101 +1,101 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: A collection of utility classes to simplify file I/O, and
-// as much as possible contain portability problems. Here avoiding
-// including windows.h.
-//
-//=============================================================================
-
-#ifndef FILEIO_H
-#define FILEIO_H
-
-#if defined (_WIN32)
-#else
-#include <sys/types.h>
-#include <sys/stat.h>
-#if !defined( _PS3 )
-#include <signal.h>
-#endif // _PS3
-#endif
-
-#include "tier0/platform.h"
-#include "tier1/utlstring.h"
-#include "tier1/utllinkedlist.h"
-
-const int64 k_nMillion = 1000000;
-const int64 k_nThousand = 1000;
-const int64 k_nKiloByte = 1024;
-const int64 k_nMegabyte = k_nKiloByte * k_nKiloByte;
-const int64 k_nGigabyte = k_nMegabyte * k_nKiloByte;
-
-class CPathString
-{
-public:
-
- // Constructors: Automatically fixes slashes and removes double slashes when the object is
- // constructed, and then knows how to append magic \\?\ on Windows for unicode paths
- CPathString( const char *pchUTF8Path );
- ~CPathString();
-
- // Gets the path in UTF8
- const char *GetUTF8Path();
-
- // Gets wchar_t based path, with \\?\ pre-pended (allowing long paths on Win32, should only be used with unicode aware filesystem calls)
- const wchar_t *GetWCharPathPrePended();
-
-private:
-
- void PopulateWCharPath();
-
- char *m_pchUTF8Path;
- wchar_t *m_pwchWideCharPathPrepended;
-
-};
-
-#if !defined(_PS3)
-//-----------------------------------------------------------------------------
-// Purpose: Encapsulates watching a directory for file changes
-//-----------------------------------------------------------------------------
-class CDirWatcher
-{
-public:
- CDirWatcher();
- ~CDirWatcher();
-
- // only one directory can be watched at a time
- void SetDirToWatch( const char *pchDir );
-
- // retrieve any changes
- bool GetChangedFile( CUtlString *psFile );
-
-#ifdef DBGFLAG_VALIDATE
- void Validate( CValidator &validator, const char *pchName );
-#endif
-
-private:
- CUtlLinkedList<CUtlString> m_listChangedFiles;
- void *m_hFile;
- void *m_pOverlapped;
- void *m_pFileInfo;
-#ifdef OSX
-public:
- struct timespec m_modTime;
- void AddFileToChangeList( const char *pchFile );
- CUtlString m_BaseDir;
-private:
- void *m_WatcherStream;
-#endif
- friend class CDirWatcherFriend;
-
-#ifdef LINUX
- void AddFileToChangeList( const char *pchFile );
-#endif
-#ifdef WIN32
- // used by callback functions to push a file onto the list
- void AddFileToChangeList( const char *pchFile );
- void PostDirWatch();
-#endif
-};
-#endif // _PS3
-
-#endif // FILEIO_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: A collection of utility classes to simplify file I/O, and
+// as much as possible contain portability problems. Here avoiding
+// including windows.h.
+//
+//=============================================================================
+
+#ifndef FILEIO_H
+#define FILEIO_H
+
+#if defined (_WIN32)
+#else
+#include <sys/types.h>
+#include <sys/stat.h>
+#if !defined( _PS3 )
+#include <signal.h>
+#endif // _PS3
+#endif
+
+#include "tier0/platform.h"
+#include "tier1/utlstring.h"
+#include "tier1/utllinkedlist.h"
+
+const int64 k_nMillion = 1000000;
+const int64 k_nThousand = 1000;
+const int64 k_nKiloByte = 1024;
+const int64 k_nMegabyte = k_nKiloByte * k_nKiloByte;
+const int64 k_nGigabyte = k_nMegabyte * k_nKiloByte;
+
+class CPathString
+{
+public:
+
+ // Constructors: Automatically fixes slashes and removes double slashes when the object is
+ // constructed, and then knows how to append magic \\?\ on Windows for unicode paths
+ CPathString( const char *pchUTF8Path );
+ ~CPathString();
+
+ // Gets the path in UTF8
+ const char *GetUTF8Path();
+
+ // Gets wchar_t based path, with \\?\ pre-pended (allowing long paths on Win32, should only be used with unicode aware filesystem calls)
+ const wchar_t *GetWCharPathPrePended();
+
+private:
+
+ void PopulateWCharPath();
+
+ char *m_pchUTF8Path;
+ wchar_t *m_pwchWideCharPathPrepended;
+
+};
+
+#if !defined(_PS3)
+//-----------------------------------------------------------------------------
+// Purpose: Encapsulates watching a directory for file changes
+//-----------------------------------------------------------------------------
+class CDirWatcher
+{
+public:
+ CDirWatcher();
+ ~CDirWatcher();
+
+ // only one directory can be watched at a time
+ void SetDirToWatch( const char *pchDir );
+
+ // retrieve any changes
+ bool GetChangedFile( CUtlString *psFile );
+
+#ifdef DBGFLAG_VALIDATE
+ void Validate( CValidator &validator, const char *pchName );
+#endif
+
+private:
+ CUtlLinkedList<CUtlString> m_listChangedFiles;
+ void *m_hFile;
+ void *m_pOverlapped;
+ void *m_pFileInfo;
+#ifdef OSX
+public:
+ struct timespec m_modTime;
+ void AddFileToChangeList( const char *pchFile );
+ CUtlString m_BaseDir;
+private:
+ void *m_WatcherStream;
+#endif
+ friend class CDirWatcherFriend;
+
+#ifdef LINUX
+ void AddFileToChangeList( const char *pchFile );
+#endif
+#ifdef WIN32
+ // used by callback functions to push a file onto the list
+ void AddFileToChangeList( const char *pchFile );
+ void PostDirWatch();
+#endif
+};
+#endif // _PS3
+
+#endif // FILEIO_H
diff --git a/mp/src/public/tier1/fmtstr.h b/mp/src/public/tier1/fmtstr.h
index 64d44add..8c9ccf47 100644
--- a/mp/src/public/tier1/fmtstr.h
+++ b/mp/src/public/tier1/fmtstr.h
@@ -1,202 +1,202 @@
-//========= Copyright 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
-#if defined(POSIX)
-#pragma GCC visibility push(hidden)
-#endif
-
-//=============================================================================
-
-// using macro to be compatable with GCC
-#define FmtStrVSNPrintf( szBuf, nBufSize, bQuietTruncation, ppszFormat, nPrevLen, lastArg ) \
- do \
- { \
- int result; \
- va_list arg_ptr; \
- bool bTruncated = false; \
- static unsigned int scAsserted = 0; \
- \
- va_start(arg_ptr, lastArg); \
- result = Q_vsnprintfRet( (szBuf), nBufSize, (*(ppszFormat)), arg_ptr, &bTruncated ); \
- va_end(arg_ptr); \
- \
- if ( bTruncated && !(bQuietTruncation) && scAsserted < 5 ) \
- { \
- Assert( !bTruncated ); \
- scAsserted++; \
- } \
- m_nLength = nPrevLen + result; \
- } \
- 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(PRINTF_FORMAT_STRING const char *pszFormat, ...) FMTFUNCTION( 2, 3 )
- {
- InitQuietTruncation();
- FmtStrVSNPrintf( m_szBuf, SIZE_BUF, m_bQuietTruncation, &pszFormat, 0, pszFormat );
- }
-
- // Use this for pass-through formatting
- CFmtStrN(const char ** ppszFormat, ...)
- {
- InitQuietTruncation();
- FmtStrVSNPrintf( m_szBuf, SIZE_BUF, m_bQuietTruncation, ppszFormat, 0, ppszFormat );
- }
-
- // Explicit reformat
- const char *sprintf(PRINTF_FORMAT_STRING const char *pszFormat, ...) FMTFUNCTION( 2, 3 )
- {
- FmtStrVSNPrintf( m_szBuf, SIZE_BUF, m_bQuietTruncation, &pszFormat, 0, pszFormat );
- return m_szBuf;
- }
-
- // Use this for pass-through formatting
- void VSprintf(const char **ppszFormat, ...)
- {
- FmtStrVSNPrintf( m_szBuf, SIZE_BUF, m_bQuietTruncation, ppszFormat, 0, ppszFormat);
- }
-
- // Compatible API with CUtlString for converting to const char*
- const char *Get( ) const { return m_szBuf; }
- const char *String( ) const { return m_szBuf; }
- // Use for access
- operator const char *() const { return m_szBuf; }
- char *Access() { return m_szBuf; }
-
- CFmtStrN<SIZE_BUF> & operator=( const char *pchValue )
- {
- V_strncpy( m_szBuf, pchValue, SIZE_BUF );
- m_nLength = V_strlen( m_szBuf );
- 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(PRINTF_FORMAT_STRING const char *pchFormat, ... ) FMTFUNCTION( 2, 3 )
- {
- char *pchEnd = m_szBuf + m_nLength;
- FmtStrVSNPrintf( pchEnd, SIZE_BUF - m_nLength, m_bQuietTruncation, &pchFormat, m_nLength, pchFormat );
- }
-
- void AppendFormatV( const char *pchFormat, va_list args );
- void Append( const char *pchValue ) { AppendFormat( "%s", 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;
-
-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;
-}
-
-
-#if defined(POSIX)
-#pragma GCC visibility pop
-#endif
-
-//-----------------------------------------------------------------------------
-//
-// Purpose: Default-sized string formatter
-//
-
-#define FMTSTR_STD_LEN 256
-
-typedef CFmtStrN<FMTSTR_STD_LEN> CFmtStr;
-typedef CFmtStrQuietTruncationN<FMTSTR_STD_LEN> CFmtStrQuietTruncation;
-typedef CFmtStrN<1024> CFmtStr1024;
-typedef CFmtStrN<8192> CFmtStrMax;
-
-//=============================================================================
-
-bool BGetLocalFormattedDateAndTime( time_t timeVal, char *pchDate, int cubDate, char *pchTime, int cubTime );
-bool BGetLocalFormattedDate( time_t timeVal, char *pchDate, int cubDate );
-bool BGetLocalFormattedTime( time_t timeVal, char *pchTime, int cubTime );
-
-#endif // FMTSTR_H
+//========= Copyright 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
+#if defined(POSIX)
+#pragma GCC visibility push(hidden)
+#endif
+
+//=============================================================================
+
+// using macro to be compatable with GCC
+#define FmtStrVSNPrintf( szBuf, nBufSize, bQuietTruncation, ppszFormat, nPrevLen, lastArg ) \
+ do \
+ { \
+ int result; \
+ va_list arg_ptr; \
+ bool bTruncated = false; \
+ static unsigned int scAsserted = 0; \
+ \
+ va_start(arg_ptr, lastArg); \
+ result = Q_vsnprintfRet( (szBuf), nBufSize, (*(ppszFormat)), arg_ptr, &bTruncated ); \
+ va_end(arg_ptr); \
+ \
+ if ( bTruncated && !(bQuietTruncation) && scAsserted < 5 ) \
+ { \
+ Assert( !bTruncated ); \
+ scAsserted++; \
+ } \
+ m_nLength = nPrevLen + result; \
+ } \
+ 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(PRINTF_FORMAT_STRING const char *pszFormat, ...) FMTFUNCTION( 2, 3 )
+ {
+ InitQuietTruncation();
+ FmtStrVSNPrintf( m_szBuf, SIZE_BUF, m_bQuietTruncation, &pszFormat, 0, pszFormat );
+ }
+
+ // Use this for pass-through formatting
+ CFmtStrN(const char ** ppszFormat, ...)
+ {
+ InitQuietTruncation();
+ FmtStrVSNPrintf( m_szBuf, SIZE_BUF, m_bQuietTruncation, ppszFormat, 0, ppszFormat );
+ }
+
+ // Explicit reformat
+ const char *sprintf(PRINTF_FORMAT_STRING const char *pszFormat, ...) FMTFUNCTION( 2, 3 )
+ {
+ FmtStrVSNPrintf( m_szBuf, SIZE_BUF, m_bQuietTruncation, &pszFormat, 0, pszFormat );
+ return m_szBuf;
+ }
+
+ // Use this for pass-through formatting
+ void VSprintf(const char **ppszFormat, ...)
+ {
+ FmtStrVSNPrintf( m_szBuf, SIZE_BUF, m_bQuietTruncation, ppszFormat, 0, ppszFormat);
+ }
+
+ // Compatible API with CUtlString for converting to const char*
+ const char *Get( ) const { return m_szBuf; }
+ const char *String( ) const { return m_szBuf; }
+ // Use for access
+ operator const char *() const { return m_szBuf; }
+ char *Access() { return m_szBuf; }
+
+ CFmtStrN<SIZE_BUF> & operator=( const char *pchValue )
+ {
+ V_strncpy( m_szBuf, pchValue, SIZE_BUF );
+ m_nLength = V_strlen( m_szBuf );
+ 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(PRINTF_FORMAT_STRING const char *pchFormat, ... ) FMTFUNCTION( 2, 3 )
+ {
+ char *pchEnd = m_szBuf + m_nLength;
+ FmtStrVSNPrintf( pchEnd, SIZE_BUF - m_nLength, m_bQuietTruncation, &pchFormat, m_nLength, pchFormat );
+ }
+
+ void AppendFormatV( const char *pchFormat, va_list args );
+ void Append( const char *pchValue ) { AppendFormat( "%s", 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;
+
+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;
+}
+
+
+#if defined(POSIX)
+#pragma GCC visibility pop
+#endif
+
+//-----------------------------------------------------------------------------
+//
+// Purpose: Default-sized string formatter
+//
+
+#define FMTSTR_STD_LEN 256
+
+typedef CFmtStrN<FMTSTR_STD_LEN> CFmtStr;
+typedef CFmtStrQuietTruncationN<FMTSTR_STD_LEN> CFmtStrQuietTruncation;
+typedef CFmtStrN<1024> CFmtStr1024;
+typedef CFmtStrN<8192> CFmtStrMax;
+
+//=============================================================================
+
+bool BGetLocalFormattedDateAndTime( time_t timeVal, char *pchDate, int cubDate, char *pchTime, int cubTime );
+bool BGetLocalFormattedDate( time_t timeVal, char *pchDate, int cubDate );
+bool BGetLocalFormattedTime( time_t timeVal, char *pchTime, int cubTime );
+
+#endif // FMTSTR_H
diff --git a/mp/src/public/tier1/functors.h b/mp/src/public/tier1/functors.h
index f6094ada..afc45d3a 100644
--- a/mp/src/public/tier1/functors.h
+++ b/mp/src/public/tier1/functors.h
@@ -1,637 +1,637 @@
-//========= Copyright 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
-
-#include "tier0/platform.h"
-#include "tier1/refcount.h"
-#include "tier1/utlenvelope.h"
-
-#if defined( _WIN32 )
-#pragma once
-#endif
-
-//-----------------------------------------------------------------------------
-//
-// Macros used as basis for template generation. Just ignore the man behind the
-// curtain
-//
-//-----------------------------------------------------------------------------
-
-#define FUNC_TEMPLATE_ARG_PARAMS_0
-#define FUNC_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_CALL_MEMBER_ARGS_0
-#define FUNC_CALL_ARGS_0
-#define FUNC_FUNCTOR_CALL_ARGS_0
-#define FUNC_TEMPLATE_FUNC_PARAMS_0
-#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_0
-#define FUNC_ADDL_TEMPLATE_FUNC_PARAMS_0
-
-#define FUNC_TEMPLATE_ARG_PARAMS_1 , typename ARG_TYPE_1
-#define FUNC_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_CALL_MEMBER_ARGS_1 m_arg1
-#define FUNC_CALL_ARGS_1 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_ADDL_TEMPLATE_FUNC_PARAMS_1 , FUNC_ARG_TYPE_1
-
-#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_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_CALL_MEMBER_ARGS_2 m_arg1, m_arg2
-#define FUNC_CALL_ARGS_2 arg1, 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_ADDL_TEMPLATE_FUNC_PARAMS_2 , FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2
-
-#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_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_CALL_MEMBER_ARGS_3 m_arg1, m_arg2, m_arg3
-#define FUNC_CALL_ARGS_3 arg1, arg2, 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_ADDL_TEMPLATE_FUNC_PARAMS_3 , FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3
-
-#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_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_CALL_MEMBER_ARGS_4 m_arg1, m_arg2, m_arg3, m_arg4
-#define FUNC_CALL_ARGS_4 arg1, arg2, arg3, 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_ADDL_TEMPLATE_FUNC_PARAMS_4 , FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4
-
-#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_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_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_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_ADDL_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_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_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_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_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_ADDL_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_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_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_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_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_ADDL_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_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_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_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_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_ADDL_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_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_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_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_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_ADDL_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_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_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_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_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_ADDL_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_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_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_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_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_ADDL_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_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_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_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_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_ADDL_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_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_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_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_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_ADDL_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_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_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_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_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_ADDL_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_GENERATE_ALL( INNERMACRONAME ) \
- INNERMACRONAME(0); \
- 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)
-
-//-----------------------------------------------------------------------------
-//
-// Purpose: Base class of all function objects
-//
-//-----------------------------------------------------------------------------
-
-abstract_class CFunctor : public IRefCounted
-{
-public:
- CFunctor()
- {
-#ifdef DEBUG
- m_nUserID = 0;
-#endif
- }
- // Add a virtual destructor to silence the clang warning.
- // This is harmless but not important since the only derived class
- // doesn't have a destructor.
- virtual ~CFunctor() {}
-
- virtual void operator()() = 0;
-
- unsigned m_nUserID; // For debugging
-};
-
-
-//-----------------------------------------------------------------------------
-// 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
-{
-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 );
-
-//-----------------------------------------------------------------------------
-//
-// 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 );
-
-//-----------------------------------------------------------------------------
-//
-// 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
+//========= Copyright 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
+
+#include "tier0/platform.h"
+#include "tier1/refcount.h"
+#include "tier1/utlenvelope.h"
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+//-----------------------------------------------------------------------------
+//
+// Macros used as basis for template generation. Just ignore the man behind the
+// curtain
+//
+//-----------------------------------------------------------------------------
+
+#define FUNC_TEMPLATE_ARG_PARAMS_0
+#define FUNC_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_CALL_MEMBER_ARGS_0
+#define FUNC_CALL_ARGS_0
+#define FUNC_FUNCTOR_CALL_ARGS_0
+#define FUNC_TEMPLATE_FUNC_PARAMS_0
+#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_0
+#define FUNC_ADDL_TEMPLATE_FUNC_PARAMS_0
+
+#define FUNC_TEMPLATE_ARG_PARAMS_1 , typename ARG_TYPE_1
+#define FUNC_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_CALL_MEMBER_ARGS_1 m_arg1
+#define FUNC_CALL_ARGS_1 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_ADDL_TEMPLATE_FUNC_PARAMS_1 , FUNC_ARG_TYPE_1
+
+#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_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_CALL_MEMBER_ARGS_2 m_arg1, m_arg2
+#define FUNC_CALL_ARGS_2 arg1, 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_ADDL_TEMPLATE_FUNC_PARAMS_2 , FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2
+
+#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_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_CALL_MEMBER_ARGS_3 m_arg1, m_arg2, m_arg3
+#define FUNC_CALL_ARGS_3 arg1, arg2, 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_ADDL_TEMPLATE_FUNC_PARAMS_3 , FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3
+
+#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_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_CALL_MEMBER_ARGS_4 m_arg1, m_arg2, m_arg3, m_arg4
+#define FUNC_CALL_ARGS_4 arg1, arg2, arg3, 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_ADDL_TEMPLATE_FUNC_PARAMS_4 , FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4
+
+#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_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_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_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_ADDL_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_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_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_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_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_ADDL_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_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_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_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_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_ADDL_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_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_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_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_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_ADDL_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_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_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_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_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_ADDL_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_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_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_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_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_ADDL_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_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_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_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_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_ADDL_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_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_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_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_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_ADDL_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_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_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_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_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_ADDL_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_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_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_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_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_ADDL_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_GENERATE_ALL( INNERMACRONAME ) \
+ INNERMACRONAME(0); \
+ 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)
+
+//-----------------------------------------------------------------------------
+//
+// Purpose: Base class of all function objects
+//
+//-----------------------------------------------------------------------------
+
+abstract_class CFunctor : public IRefCounted
+{
+public:
+ CFunctor()
+ {
+#ifdef DEBUG
+ m_nUserID = 0;
+#endif
+ }
+ // Add a virtual destructor to silence the clang warning.
+ // This is harmless but not important since the only derived class
+ // doesn't have a destructor.
+ virtual ~CFunctor() {}
+
+ virtual void operator()() = 0;
+
+ unsigned m_nUserID; // For debugging
+};
+
+
+//-----------------------------------------------------------------------------
+// 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
+{
+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 );
+
+//-----------------------------------------------------------------------------
+//
+// 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 );
+
+//-----------------------------------------------------------------------------
+//
+// 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/mp/src/public/tier1/generichash.h b/mp/src/public/tier1/generichash.h
index 70226b45..59b8b610 100644
--- a/mp/src/public/tier1/generichash.h
+++ b/mp/src/public/tier1/generichash.h
@@ -1,116 +1,116 @@
-//========= Copyright 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 */
+//========= Copyright 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/mp/src/public/tier1/iconvar.h b/mp/src/public/tier1/iconvar.h
index b33154ce..1ea5f7af 100644
--- a/mp/src/public/tier1/iconvar.h
+++ b/mp/src/public/tier1/iconvar.h
@@ -1,118 +1,118 @@
-//========= Copyright 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"
-
-
-//-----------------------------------------------------------------------------
-// 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 autocomplete. 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_CHEAT (1<<14) // Only useable in singleplayer / debug / multiplayer & sv_cheats
-
-#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_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_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_XBOX (1<<24) // cvar written to config.cfg on the Xbox
-
-#define FCVAR_ACCESSIBLE_FROM_THREADS (1<<25) // used as a debugging tool necessary to check material system thread convars
-
-#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_AVAILABLE (1<<15)
-// #define FCVAR_AVAILABLE (1<<18)
-// #define FCVAR_AVAILABLE (1<<19)
-// #define FCVAR_AVAILABLE (1<<20)
-// #define FCVAR_AVAILABLE (1<<21)
-// #define FCVAR_AVAILABLE (1<<23)
-// #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;
-
- // Return name of command
- virtual const char *GetName( 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;
-};
-
-
-#endif // ICONVAR_H
+//========= Copyright 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"
+
+
+//-----------------------------------------------------------------------------
+// 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 autocomplete. 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_CHEAT (1<<14) // Only useable in singleplayer / debug / multiplayer & sv_cheats
+
+#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_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_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_XBOX (1<<24) // cvar written to config.cfg on the Xbox
+
+#define FCVAR_ACCESSIBLE_FROM_THREADS (1<<25) // used as a debugging tool necessary to check material system thread convars
+
+#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_AVAILABLE (1<<15)
+// #define FCVAR_AVAILABLE (1<<18)
+// #define FCVAR_AVAILABLE (1<<19)
+// #define FCVAR_AVAILABLE (1<<20)
+// #define FCVAR_AVAILABLE (1<<21)
+// #define FCVAR_AVAILABLE (1<<23)
+// #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;
+
+ // Return name of command
+ virtual const char *GetName( 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;
+};
+
+
+#endif // ICONVAR_H
diff --git a/mp/src/public/tier1/ilocalize.h b/mp/src/public/tier1/ilocalize.h
index a3dd6bb8..fed7af6d 100644
--- a/mp/src/public/tier1/ilocalize.h
+++ b/mp/src/public/tier1/ilocalize.h
@@ -1,424 +1,424 @@
-
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//===========================================================================//
-
-#ifndef TIER1_ILOCALIZE_H
-#define TIER1_ILOCALIZE_H
-
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include "appframework/IAppSystem.h"
-#include <tier1/KeyValues.h>
-
-// unicode character type
-// for more unicode manipulation functions #include <wchar.h>
-#if !defined(_WCHAR_T_DEFINED) && !defined(GNUC)
-typedef unsigned short wchar_t;
-#define _WCHAR_T_DEFINED
-#endif
-
-
-// direct references to localized strings
-typedef unsigned long StringIndex_t;
-const unsigned long INVALID_LOCALIZE_STRING_INDEX = (StringIndex_t) -1;
-
-//-----------------------------------------------------------------------------
-// Purpose: Handles localization of text
-// looks up string names and returns the localized unicode text
-//-----------------------------------------------------------------------------
-abstract_class ILocalize
-{
-public:
- // adds the contents of a file to the localization table
- virtual bool AddFile( const char *fileName, const char *pPathID = NULL, bool bIncludeFallbackSearchPaths = false ) = 0;
-
- // Remove all strings from the table
- virtual void RemoveAll() = 0;
-
- // Finds the localized text for tokenName
- virtual wchar_t *Find(char const *tokenName) = 0;
-
- // finds the index of a token by token name, INVALID_STRING_INDEX if not found
- virtual StringIndex_t FindIndex(const char *tokenName) = 0;
-
- // gets the values by the string index
- virtual const char *GetNameByIndex(StringIndex_t index) = 0;
- virtual wchar_t *GetValueByIndex(StringIndex_t index) = 0;
-
- ///////////////////////////////////////////////////////////////////
- // the following functions should only be used by localization editors
-
- // iteration functions
- virtual StringIndex_t GetFirstStringIndex() = 0;
- // returns the next index, or INVALID_STRING_INDEX if no more strings available
- virtual StringIndex_t GetNextStringIndex(StringIndex_t index) = 0;
-
- // adds a single name/unicode string pair to the table
- virtual void AddString( const char *tokenName, wchar_t *unicodeString, const char *fileName ) = 0;
-
- // changes the value of a string
- virtual void SetValueByIndex(StringIndex_t index, wchar_t *newValue) = 0;
-
- // saves the entire contents of the token tree to the file
- virtual bool SaveToFile( const char *fileName ) = 0;
-
- // iterates the filenames
- virtual int GetLocalizationFileCount() = 0;
- virtual const char *GetLocalizationFileName(int index) = 0;
-
- // returns the name of the file the specified localized string is stored in
- virtual const char *GetFileNameByIndex(StringIndex_t index) = 0;
-
- // for development only, reloads localization files
- virtual void ReloadLocalizationFiles( ) = 0;
-
- virtual const char *FindAsUTF8( const char *pchTokenName ) = 0;
-
- // need to replace the existing ConstructString with this
- virtual void ConstructString(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) wchar_t *unicodeOutput, int unicodeBufferSizeInBytes, const char *tokenName, KeyValues *localizationVariables) = 0;
- virtual void ConstructString(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) wchar_t *unicodeOutput, int unicodeBufferSizeInBytes, StringIndex_t unlocalizedTextSymbol, KeyValues *localizationVariables) = 0;
-
- ///////////////////////////////////////////////////////////////////
- // static interface
-
- // converts an english string to unicode
- // returns the number of wchar_t in resulting string, including null terminator
- static int ConvertANSIToUnicode(const char *ansi, OUT_Z_BYTECAP(unicodeBufferSizeInBytes) wchar_t *unicode, int unicodeBufferSizeInBytes);
-
- // converts an unicode string to an english string
- // unrepresentable characters are converted to system default
- // returns the number of characters in resulting string, including null terminator
- static int ConvertUnicodeToANSI(const wchar_t *unicode, OUT_Z_BYTECAP(ansiBufferSize) char *ansi, int ansiBufferSize);
-
- // builds a localized formatted string
- // uses the format strings first: %s1, %s2, ... unicode strings (wchar_t *)
- template < typename T >
- static void ConstructString(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) T *unicodeOuput, int unicodeBufferSizeInBytes, const T *formatString, int numFormatParameters, ...)
- {
- va_list argList;
- va_start( argList, numFormatParameters );
-
- ConstructStringVArgsInternal( unicodeOuput, unicodeBufferSizeInBytes, formatString, numFormatParameters, argList );
-
- va_end( argList );
- }
-
- template < typename T >
- static void ConstructStringVArgs(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) T *unicodeOuput, int unicodeBufferSizeInBytes, const T *formatString, int numFormatParameters, va_list argList)
- {
- ConstructStringVArgsInternal( unicodeOuput, unicodeBufferSizeInBytes, formatString, numFormatParameters, argList );
- }
-
- template < typename T >
- static void ConstructString(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) T *unicodeOutput, int unicodeBufferSizeInBytes, const T *formatString, KeyValues *localizationVariables)
- {
- ConstructStringKeyValuesInternal( unicodeOutput, unicodeBufferSizeInBytes, formatString, localizationVariables );
- }
-
-private:
- // internal "interface"
- static void ConstructStringVArgsInternal(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) char *unicodeOutput, int unicodeBufferSizeInBytes, const char *formatString, int numFormatParameters, va_list argList);
- static void ConstructStringVArgsInternal(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) wchar_t *unicodeOutput, int unicodeBufferSizeInBytes, const wchar_t *formatString, int numFormatParameters, va_list argList);
-
- static void ConstructStringKeyValuesInternal(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) char *unicodeOutput, int unicodeBufferSizeInBytes, const char *formatString, KeyValues *localizationVariables);
- static void ConstructStringKeyValuesInternal(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) wchar_t *unicodeOutput, int unicodeBufferSizeInBytes, const wchar_t *formatString, KeyValues *localizationVariables);
-};
-
-#ifdef GC
-
- typedef char locchar_t;
-
- #define loc_snprintf Q_snprintf
- #define loc_sprintf_safe V_sprintf_safe
- #define loc_sncat Q_strncat
- #define loc_scat_safe V_strcat_safe
- #define loc_sncpy Q_strncpy
- #define loc_scpy_safe V_strcpy_safe
- #define loc_strlen Q_strlen
- #define LOCCHAR( x ) x
-
-#else
-
- typedef wchar_t locchar_t;
-
- #define loc_snprintf V_snwprintf
- #define loc_sprintf_safe V_swprintf_safe
- #define loc_sncat V_wcsncat
- #define loc_scat_safe V_wcscat_safe
- #define loc_sncpy Q_wcsncpy
- #define loc_scpy_safe V_wcscpy_safe
- #define loc_strlen Q_wcslen
- #define LOCCHAR(x) L ## x
-
-#endif
-
-// --------------------------------------------------------------------------
-// Purpose:
-// --------------------------------------------------------------------------
-
-template < typename T >
-class TypedKeyValuesStringHelper
-{
-public:
- static const T *Read( KeyValues *pKeyValues, const char *pKeyName, const T *pDefaultValue );
- static void Write( KeyValues *pKeyValues, const char *pKeyName, const T *pValue );
-};
-
-// --------------------------------------------------------------------------
-
-template < >
-class TypedKeyValuesStringHelper<char>
-{
-public:
- static const char *Read( KeyValues *pKeyValues, const char *pKeyName, const char *pDefaultValue ) { return pKeyValues->GetString( pKeyName, pDefaultValue ); }
- static void Write( KeyValues *pKeyValues, const char *pKeyName, const char *pValue ) { pKeyValues->SetString( pKeyName, pValue ); }
-};
-
-// --------------------------------------------------------------------------
-
-template < >
-class TypedKeyValuesStringHelper<wchar_t>
-{
-public:
- static const wchar_t *Read( KeyValues *pKeyValues, const char *pKeyName, const wchar_t *pDefaultValue ) { return pKeyValues->GetWString( pKeyName, pDefaultValue ); }
- static void Write( KeyValues *pKeyValues, const char *pKeyName, const wchar_t *pValue ) { pKeyValues->SetWString( pKeyName, pValue ); }
-};
-
-// --------------------------------------------------------------------------
-// Purpose: CLocalizedStringArg<> is a class that will take a variable of any
-// arbitary type and convert it to a string of whatever character type
-// we're using for localization (locchar_t).
-//
-// Independently it isn't very useful, though it can be used to sort-of-
-// intelligently fill out the correct format string. It's designed to be
-// used for the arguments of CConstructLocalizedString, which can be of
-// arbitrary number and type.
-//
-// If you pass in a (non-specialized) pointer, the code will assume that
-// you meant that pointer to be used as a localized string. This will
-// still fail to compile if some non-string type is passed in, but will
-// handle weird combinations of const/volatile/whatever automatically.
-// --------------------------------------------------------------------------
-
-// The base implementation doesn't do anything except fail to compile if you
-// use it. Getting an "incomplete type" error here means that you tried to construct
-// a localized string with a type that doesn't have a specialization.
-template < typename T >
-class CLocalizedStringArg;
-
-// --------------------------------------------------------------------------
-
-template < typename T >
-class CLocalizedStringArgStringImpl
-{
-public:
- enum { kIsValid = true };
-
- CLocalizedStringArgStringImpl( const locchar_t *pStr ) : m_pStr( pStr ) { }
-
- const locchar_t *GetLocArg() const { Assert( m_pStr ); return m_pStr; }
-
-private:
- const locchar_t *m_pStr;
-};
-
-// --------------------------------------------------------------------------
-
-template < typename T >
-class CLocalizedStringArg<T *> : public CLocalizedStringArgStringImpl<T>
-{
-public:
- CLocalizedStringArg( const locchar_t *pStr ) : CLocalizedStringArgStringImpl<T>( pStr ) { }
-};
-
-// --------------------------------------------------------------------------
-
-template < typename T >
-class CLocalizedStringArgPrintfImpl
-{
-public:
- enum { kIsValid = true };
-
- CLocalizedStringArgPrintfImpl( T value, const locchar_t *loc_Format ) { loc_snprintf( m_cBuffer, kBufferSize, loc_Format, value ); }
-
- const locchar_t *GetLocArg() const { return m_cBuffer; }
-
-private:
- enum { kBufferSize = 128, };
- locchar_t m_cBuffer[ kBufferSize ];
-};
-
-// --------------------------------------------------------------------------
-
-template < >
-class CLocalizedStringArg<uint16> : public CLocalizedStringArgPrintfImpl<uint16>
-{
-public:
- CLocalizedStringArg( uint16 unValue ) : CLocalizedStringArgPrintfImpl<uint16>( unValue, LOCCHAR("%u") ) { }
-};
-
-// --------------------------------------------------------------------------
-
-template < >
-class CLocalizedStringArg<uint32> : public CLocalizedStringArgPrintfImpl<uint32>
-{
-public:
- CLocalizedStringArg( uint32 unValue ) : CLocalizedStringArgPrintfImpl<uint32>( unValue, LOCCHAR("%u") ) { }
-};
-
-// --------------------------------------------------------------------------
-
-template < >
-class CLocalizedStringArg<uint64> : public CLocalizedStringArgPrintfImpl<uint64>
-{
-public:
- CLocalizedStringArg( uint64 unValue ) : CLocalizedStringArgPrintfImpl<uint64>( unValue, LOCCHAR("%llu") ) { }
-};
-
-// --------------------------------------------------------------------------
-
-template < >
-class CLocalizedStringArg<float> : public CLocalizedStringArgPrintfImpl<float>
-{
-public:
- // Display one decimal point if we've got a value less than one, and no point
- // if we're greater than one or are effectively zero.
- CLocalizedStringArg( float fValue )
- : CLocalizedStringArgPrintfImpl<float>( fValue,
- fabsf( fValue ) <= FLT_EPSILON || fabsf( fValue ) >= 1.0f ? LOCCHAR("%.0f") : LOCCHAR("%.1f") )
- {
- //
- }
-};
-
-// --------------------------------------------------------------------------
-// Purpose:
-// --------------------------------------------------------------------------
-class CConstructLocalizedString
-{
-public:
- template < typename T >
- CConstructLocalizedString( const locchar_t *loc_Format, T arg0 )
- {
- COMPILE_TIME_ASSERT( CLocalizedStringArg<T>::kIsValid );
-
- m_loc_Buffer[0] = '\0';
-
- if ( loc_Format )
- {
- ::ILocalize::ConstructString( m_loc_Buffer, sizeof( m_loc_Buffer ), loc_Format, 1, CLocalizedStringArg<T>( arg0 ).GetLocArg() );
- }
- }
-
- template < typename T, typename U >
- CConstructLocalizedString( const locchar_t *loc_Format, T arg0, U arg1 )
- {
- COMPILE_TIME_ASSERT( CLocalizedStringArg<T>::kIsValid );
- COMPILE_TIME_ASSERT( CLocalizedStringArg<U>::kIsValid );
-
- m_loc_Buffer[0] = '\0';
-
- if ( loc_Format )
- {
- ::ILocalize::ConstructString( m_loc_Buffer, sizeof( m_loc_Buffer ), loc_Format, 2, CLocalizedStringArg<T>( arg0 ).GetLocArg(), CLocalizedStringArg<U>( arg1 ).GetLocArg() );
- }
- }
-
- template < typename T, typename U, typename V >
- CConstructLocalizedString( const locchar_t *loc_Format, T arg0, U arg1, V arg2 )
- {
- COMPILE_TIME_ASSERT( CLocalizedStringArg<T>::kIsValid );
- COMPILE_TIME_ASSERT( CLocalizedStringArg<U>::kIsValid );
- COMPILE_TIME_ASSERT( CLocalizedStringArg<V>::kIsValid );
-
- m_loc_Buffer[0] = '\0';
-
- if ( loc_Format )
- {
- ::ILocalize::ConstructString( m_loc_Buffer,
- sizeof( m_loc_Buffer ),
- loc_Format,
- 3,
- CLocalizedStringArg<T>( arg0 ).GetLocArg(),
- CLocalizedStringArg<U>( arg1 ).GetLocArg(),
- CLocalizedStringArg<V>( arg2 ).GetLocArg() );
- }
- }
-
- template < typename T, typename U, typename V, typename W >
- CConstructLocalizedString( const locchar_t *loc_Format, T arg0, U arg1, V arg2, W arg3 )
- {
- COMPILE_TIME_ASSERT( CLocalizedStringArg<T>::kIsValid );
- COMPILE_TIME_ASSERT( CLocalizedStringArg<U>::kIsValid );
- COMPILE_TIME_ASSERT( CLocalizedStringArg<V>::kIsValid );
- COMPILE_TIME_ASSERT( CLocalizedStringArg<W>::kIsValid );
-
- m_loc_Buffer[0] = '\0';
-
- if ( loc_Format )
- {
- ::ILocalize::ConstructString( m_loc_Buffer,
- sizeof( m_loc_Buffer ),
- loc_Format,
- 4,
- CLocalizedStringArg<T>( arg0 ).GetLocArg(),
- CLocalizedStringArg<U>( arg1 ).GetLocArg(),
- CLocalizedStringArg<V>( arg2 ).GetLocArg(),
- CLocalizedStringArg<W>( arg3 ).GetLocArg() );
- }
- }
-
- template < typename T, typename U, typename V, typename W, typename X, typename Y >
- CConstructLocalizedString( const locchar_t *loc_Format, T arg0, U arg1, V arg2, W arg3, X arg4, Y arg5 )
- {
- COMPILE_TIME_ASSERT( CLocalizedStringArg<T>::kIsValid );
- COMPILE_TIME_ASSERT( CLocalizedStringArg<U>::kIsValid );
- COMPILE_TIME_ASSERT( CLocalizedStringArg<V>::kIsValid );
- COMPILE_TIME_ASSERT( CLocalizedStringArg<W>::kIsValid );
- COMPILE_TIME_ASSERT( CLocalizedStringArg<X>::kIsValid );
- COMPILE_TIME_ASSERT( CLocalizedStringArg<Y>::kIsValid );
-
- m_loc_Buffer[0] = '\0';
-
- if ( loc_Format )
- {
- ::ILocalize::ConstructString( m_loc_Buffer,
- sizeof( m_loc_Buffer ),
- loc_Format,
- 6,
- CLocalizedStringArg<T>( arg0 ).GetLocArg(),
- CLocalizedStringArg<U>( arg1 ).GetLocArg(),
- CLocalizedStringArg<V>( arg2 ).GetLocArg(),
- CLocalizedStringArg<W>( arg3 ).GetLocArg(),
- CLocalizedStringArg<X>( arg4 ).GetLocArg(),
- CLocalizedStringArg<Y>( arg5 ).GetLocArg() );
- }
- }
-
- CConstructLocalizedString( const locchar_t *loc_Format, KeyValues *pKeyValues )
- {
- m_loc_Buffer[0] = '\0';
-
- if ( loc_Format && pKeyValues )
- {
- ::ILocalize::ConstructString( m_loc_Buffer, sizeof( m_loc_Buffer ), loc_Format, pKeyValues );
- }
- }
-
- operator const locchar_t *() const
- {
- return m_loc_Buffer;
- }
-
-private:
- enum { kBufferSize = 512, };
- locchar_t m_loc_Buffer[ kBufferSize ];
-};
-
-#endif // TIER1_ILOCALIZE_H
+
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//===========================================================================//
+
+#ifndef TIER1_ILOCALIZE_H
+#define TIER1_ILOCALIZE_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "appframework/IAppSystem.h"
+#include <tier1/KeyValues.h>
+
+// unicode character type
+// for more unicode manipulation functions #include <wchar.h>
+#if !defined(_WCHAR_T_DEFINED) && !defined(GNUC)
+typedef unsigned short wchar_t;
+#define _WCHAR_T_DEFINED
+#endif
+
+
+// direct references to localized strings
+typedef unsigned long StringIndex_t;
+const unsigned long INVALID_LOCALIZE_STRING_INDEX = (StringIndex_t) -1;
+
+//-----------------------------------------------------------------------------
+// Purpose: Handles localization of text
+// looks up string names and returns the localized unicode text
+//-----------------------------------------------------------------------------
+abstract_class ILocalize
+{
+public:
+ // adds the contents of a file to the localization table
+ virtual bool AddFile( const char *fileName, const char *pPathID = NULL, bool bIncludeFallbackSearchPaths = false ) = 0;
+
+ // Remove all strings from the table
+ virtual void RemoveAll() = 0;
+
+ // Finds the localized text for tokenName
+ virtual wchar_t *Find(char const *tokenName) = 0;
+
+ // finds the index of a token by token name, INVALID_STRING_INDEX if not found
+ virtual StringIndex_t FindIndex(const char *tokenName) = 0;
+
+ // gets the values by the string index
+ virtual const char *GetNameByIndex(StringIndex_t index) = 0;
+ virtual wchar_t *GetValueByIndex(StringIndex_t index) = 0;
+
+ ///////////////////////////////////////////////////////////////////
+ // the following functions should only be used by localization editors
+
+ // iteration functions
+ virtual StringIndex_t GetFirstStringIndex() = 0;
+ // returns the next index, or INVALID_STRING_INDEX if no more strings available
+ virtual StringIndex_t GetNextStringIndex(StringIndex_t index) = 0;
+
+ // adds a single name/unicode string pair to the table
+ virtual void AddString( const char *tokenName, wchar_t *unicodeString, const char *fileName ) = 0;
+
+ // changes the value of a string
+ virtual void SetValueByIndex(StringIndex_t index, wchar_t *newValue) = 0;
+
+ // saves the entire contents of the token tree to the file
+ virtual bool SaveToFile( const char *fileName ) = 0;
+
+ // iterates the filenames
+ virtual int GetLocalizationFileCount() = 0;
+ virtual const char *GetLocalizationFileName(int index) = 0;
+
+ // returns the name of the file the specified localized string is stored in
+ virtual const char *GetFileNameByIndex(StringIndex_t index) = 0;
+
+ // for development only, reloads localization files
+ virtual void ReloadLocalizationFiles( ) = 0;
+
+ virtual const char *FindAsUTF8( const char *pchTokenName ) = 0;
+
+ // need to replace the existing ConstructString with this
+ virtual void ConstructString(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) wchar_t *unicodeOutput, int unicodeBufferSizeInBytes, const char *tokenName, KeyValues *localizationVariables) = 0;
+ virtual void ConstructString(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) wchar_t *unicodeOutput, int unicodeBufferSizeInBytes, StringIndex_t unlocalizedTextSymbol, KeyValues *localizationVariables) = 0;
+
+ ///////////////////////////////////////////////////////////////////
+ // static interface
+
+ // converts an english string to unicode
+ // returns the number of wchar_t in resulting string, including null terminator
+ static int ConvertANSIToUnicode(const char *ansi, OUT_Z_BYTECAP(unicodeBufferSizeInBytes) wchar_t *unicode, int unicodeBufferSizeInBytes);
+
+ // converts an unicode string to an english string
+ // unrepresentable characters are converted to system default
+ // returns the number of characters in resulting string, including null terminator
+ static int ConvertUnicodeToANSI(const wchar_t *unicode, OUT_Z_BYTECAP(ansiBufferSize) char *ansi, int ansiBufferSize);
+
+ // builds a localized formatted string
+ // uses the format strings first: %s1, %s2, ... unicode strings (wchar_t *)
+ template < typename T >
+ static void ConstructString(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) T *unicodeOuput, int unicodeBufferSizeInBytes, const T *formatString, int numFormatParameters, ...)
+ {
+ va_list argList;
+ va_start( argList, numFormatParameters );
+
+ ConstructStringVArgsInternal( unicodeOuput, unicodeBufferSizeInBytes, formatString, numFormatParameters, argList );
+
+ va_end( argList );
+ }
+
+ template < typename T >
+ static void ConstructStringVArgs(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) T *unicodeOuput, int unicodeBufferSizeInBytes, const T *formatString, int numFormatParameters, va_list argList)
+ {
+ ConstructStringVArgsInternal( unicodeOuput, unicodeBufferSizeInBytes, formatString, numFormatParameters, argList );
+ }
+
+ template < typename T >
+ static void ConstructString(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) T *unicodeOutput, int unicodeBufferSizeInBytes, const T *formatString, KeyValues *localizationVariables)
+ {
+ ConstructStringKeyValuesInternal( unicodeOutput, unicodeBufferSizeInBytes, formatString, localizationVariables );
+ }
+
+private:
+ // internal "interface"
+ static void ConstructStringVArgsInternal(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) char *unicodeOutput, int unicodeBufferSizeInBytes, const char *formatString, int numFormatParameters, va_list argList);
+ static void ConstructStringVArgsInternal(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) wchar_t *unicodeOutput, int unicodeBufferSizeInBytes, const wchar_t *formatString, int numFormatParameters, va_list argList);
+
+ static void ConstructStringKeyValuesInternal(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) char *unicodeOutput, int unicodeBufferSizeInBytes, const char *formatString, KeyValues *localizationVariables);
+ static void ConstructStringKeyValuesInternal(OUT_Z_BYTECAP(unicodeBufferSizeInBytes) wchar_t *unicodeOutput, int unicodeBufferSizeInBytes, const wchar_t *formatString, KeyValues *localizationVariables);
+};
+
+#ifdef GC
+
+ typedef char locchar_t;
+
+ #define loc_snprintf Q_snprintf
+ #define loc_sprintf_safe V_sprintf_safe
+ #define loc_sncat Q_strncat
+ #define loc_scat_safe V_strcat_safe
+ #define loc_sncpy Q_strncpy
+ #define loc_scpy_safe V_strcpy_safe
+ #define loc_strlen Q_strlen
+ #define LOCCHAR( x ) x
+
+#else
+
+ typedef wchar_t locchar_t;
+
+ #define loc_snprintf V_snwprintf
+ #define loc_sprintf_safe V_swprintf_safe
+ #define loc_sncat V_wcsncat
+ #define loc_scat_safe V_wcscat_safe
+ #define loc_sncpy Q_wcsncpy
+ #define loc_scpy_safe V_wcscpy_safe
+ #define loc_strlen Q_wcslen
+ #define LOCCHAR(x) L ## x
+
+#endif
+
+// --------------------------------------------------------------------------
+// Purpose:
+// --------------------------------------------------------------------------
+
+template < typename T >
+class TypedKeyValuesStringHelper
+{
+public:
+ static const T *Read( KeyValues *pKeyValues, const char *pKeyName, const T *pDefaultValue );
+ static void Write( KeyValues *pKeyValues, const char *pKeyName, const T *pValue );
+};
+
+// --------------------------------------------------------------------------
+
+template < >
+class TypedKeyValuesStringHelper<char>
+{
+public:
+ static const char *Read( KeyValues *pKeyValues, const char *pKeyName, const char *pDefaultValue ) { return pKeyValues->GetString( pKeyName, pDefaultValue ); }
+ static void Write( KeyValues *pKeyValues, const char *pKeyName, const char *pValue ) { pKeyValues->SetString( pKeyName, pValue ); }
+};
+
+// --------------------------------------------------------------------------
+
+template < >
+class TypedKeyValuesStringHelper<wchar_t>
+{
+public:
+ static const wchar_t *Read( KeyValues *pKeyValues, const char *pKeyName, const wchar_t *pDefaultValue ) { return pKeyValues->GetWString( pKeyName, pDefaultValue ); }
+ static void Write( KeyValues *pKeyValues, const char *pKeyName, const wchar_t *pValue ) { pKeyValues->SetWString( pKeyName, pValue ); }
+};
+
+// --------------------------------------------------------------------------
+// Purpose: CLocalizedStringArg<> is a class that will take a variable of any
+// arbitary type and convert it to a string of whatever character type
+// we're using for localization (locchar_t).
+//
+// Independently it isn't very useful, though it can be used to sort-of-
+// intelligently fill out the correct format string. It's designed to be
+// used for the arguments of CConstructLocalizedString, which can be of
+// arbitrary number and type.
+//
+// If you pass in a (non-specialized) pointer, the code will assume that
+// you meant that pointer to be used as a localized string. This will
+// still fail to compile if some non-string type is passed in, but will
+// handle weird combinations of const/volatile/whatever automatically.
+// --------------------------------------------------------------------------
+
+// The base implementation doesn't do anything except fail to compile if you
+// use it. Getting an "incomplete type" error here means that you tried to construct
+// a localized string with a type that doesn't have a specialization.
+template < typename T >
+class CLocalizedStringArg;
+
+// --------------------------------------------------------------------------
+
+template < typename T >
+class CLocalizedStringArgStringImpl
+{
+public:
+ enum { kIsValid = true };
+
+ CLocalizedStringArgStringImpl( const locchar_t *pStr ) : m_pStr( pStr ) { }
+
+ const locchar_t *GetLocArg() const { Assert( m_pStr ); return m_pStr; }
+
+private:
+ const locchar_t *m_pStr;
+};
+
+// --------------------------------------------------------------------------
+
+template < typename T >
+class CLocalizedStringArg<T *> : public CLocalizedStringArgStringImpl<T>
+{
+public:
+ CLocalizedStringArg( const locchar_t *pStr ) : CLocalizedStringArgStringImpl<T>( pStr ) { }
+};
+
+// --------------------------------------------------------------------------
+
+template < typename T >
+class CLocalizedStringArgPrintfImpl
+{
+public:
+ enum { kIsValid = true };
+
+ CLocalizedStringArgPrintfImpl( T value, const locchar_t *loc_Format ) { loc_snprintf( m_cBuffer, kBufferSize, loc_Format, value ); }
+
+ const locchar_t *GetLocArg() const { return m_cBuffer; }
+
+private:
+ enum { kBufferSize = 128, };
+ locchar_t m_cBuffer[ kBufferSize ];
+};
+
+// --------------------------------------------------------------------------
+
+template < >
+class CLocalizedStringArg<uint16> : public CLocalizedStringArgPrintfImpl<uint16>
+{
+public:
+ CLocalizedStringArg( uint16 unValue ) : CLocalizedStringArgPrintfImpl<uint16>( unValue, LOCCHAR("%u") ) { }
+};
+
+// --------------------------------------------------------------------------
+
+template < >
+class CLocalizedStringArg<uint32> : public CLocalizedStringArgPrintfImpl<uint32>
+{
+public:
+ CLocalizedStringArg( uint32 unValue ) : CLocalizedStringArgPrintfImpl<uint32>( unValue, LOCCHAR("%u") ) { }
+};
+
+// --------------------------------------------------------------------------
+
+template < >
+class CLocalizedStringArg<uint64> : public CLocalizedStringArgPrintfImpl<uint64>
+{
+public:
+ CLocalizedStringArg( uint64 unValue ) : CLocalizedStringArgPrintfImpl<uint64>( unValue, LOCCHAR("%llu") ) { }
+};
+
+// --------------------------------------------------------------------------
+
+template < >
+class CLocalizedStringArg<float> : public CLocalizedStringArgPrintfImpl<float>
+{
+public:
+ // Display one decimal point if we've got a value less than one, and no point
+ // if we're greater than one or are effectively zero.
+ CLocalizedStringArg( float fValue )
+ : CLocalizedStringArgPrintfImpl<float>( fValue,
+ fabsf( fValue ) <= FLT_EPSILON || fabsf( fValue ) >= 1.0f ? LOCCHAR("%.0f") : LOCCHAR("%.1f") )
+ {
+ //
+ }
+};
+
+// --------------------------------------------------------------------------
+// Purpose:
+// --------------------------------------------------------------------------
+class CConstructLocalizedString
+{
+public:
+ template < typename T >
+ CConstructLocalizedString( const locchar_t *loc_Format, T arg0 )
+ {
+ COMPILE_TIME_ASSERT( CLocalizedStringArg<T>::kIsValid );
+
+ m_loc_Buffer[0] = '\0';
+
+ if ( loc_Format )
+ {
+ ::ILocalize::ConstructString( m_loc_Buffer, sizeof( m_loc_Buffer ), loc_Format, 1, CLocalizedStringArg<T>( arg0 ).GetLocArg() );
+ }
+ }
+
+ template < typename T, typename U >
+ CConstructLocalizedString( const locchar_t *loc_Format, T arg0, U arg1 )
+ {
+ COMPILE_TIME_ASSERT( CLocalizedStringArg<T>::kIsValid );
+ COMPILE_TIME_ASSERT( CLocalizedStringArg<U>::kIsValid );
+
+ m_loc_Buffer[0] = '\0';
+
+ if ( loc_Format )
+ {
+ ::ILocalize::ConstructString( m_loc_Buffer, sizeof( m_loc_Buffer ), loc_Format, 2, CLocalizedStringArg<T>( arg0 ).GetLocArg(), CLocalizedStringArg<U>( arg1 ).GetLocArg() );
+ }
+ }
+
+ template < typename T, typename U, typename V >
+ CConstructLocalizedString( const locchar_t *loc_Format, T arg0, U arg1, V arg2 )
+ {
+ COMPILE_TIME_ASSERT( CLocalizedStringArg<T>::kIsValid );
+ COMPILE_TIME_ASSERT( CLocalizedStringArg<U>::kIsValid );
+ COMPILE_TIME_ASSERT( CLocalizedStringArg<V>::kIsValid );
+
+ m_loc_Buffer[0] = '\0';
+
+ if ( loc_Format )
+ {
+ ::ILocalize::ConstructString( m_loc_Buffer,
+ sizeof( m_loc_Buffer ),
+ loc_Format,
+ 3,
+ CLocalizedStringArg<T>( arg0 ).GetLocArg(),
+ CLocalizedStringArg<U>( arg1 ).GetLocArg(),
+ CLocalizedStringArg<V>( arg2 ).GetLocArg() );
+ }
+ }
+
+ template < typename T, typename U, typename V, typename W >
+ CConstructLocalizedString( const locchar_t *loc_Format, T arg0, U arg1, V arg2, W arg3 )
+ {
+ COMPILE_TIME_ASSERT( CLocalizedStringArg<T>::kIsValid );
+ COMPILE_TIME_ASSERT( CLocalizedStringArg<U>::kIsValid );
+ COMPILE_TIME_ASSERT( CLocalizedStringArg<V>::kIsValid );
+ COMPILE_TIME_ASSERT( CLocalizedStringArg<W>::kIsValid );
+
+ m_loc_Buffer[0] = '\0';
+
+ if ( loc_Format )
+ {
+ ::ILocalize::ConstructString( m_loc_Buffer,
+ sizeof( m_loc_Buffer ),
+ loc_Format,
+ 4,
+ CLocalizedStringArg<T>( arg0 ).GetLocArg(),
+ CLocalizedStringArg<U>( arg1 ).GetLocArg(),
+ CLocalizedStringArg<V>( arg2 ).GetLocArg(),
+ CLocalizedStringArg<W>( arg3 ).GetLocArg() );
+ }
+ }
+
+ template < typename T, typename U, typename V, typename W, typename X, typename Y >
+ CConstructLocalizedString( const locchar_t *loc_Format, T arg0, U arg1, V arg2, W arg3, X arg4, Y arg5 )
+ {
+ COMPILE_TIME_ASSERT( CLocalizedStringArg<T>::kIsValid );
+ COMPILE_TIME_ASSERT( CLocalizedStringArg<U>::kIsValid );
+ COMPILE_TIME_ASSERT( CLocalizedStringArg<V>::kIsValid );
+ COMPILE_TIME_ASSERT( CLocalizedStringArg<W>::kIsValid );
+ COMPILE_TIME_ASSERT( CLocalizedStringArg<X>::kIsValid );
+ COMPILE_TIME_ASSERT( CLocalizedStringArg<Y>::kIsValid );
+
+ m_loc_Buffer[0] = '\0';
+
+ if ( loc_Format )
+ {
+ ::ILocalize::ConstructString( m_loc_Buffer,
+ sizeof( m_loc_Buffer ),
+ loc_Format,
+ 6,
+ CLocalizedStringArg<T>( arg0 ).GetLocArg(),
+ CLocalizedStringArg<U>( arg1 ).GetLocArg(),
+ CLocalizedStringArg<V>( arg2 ).GetLocArg(),
+ CLocalizedStringArg<W>( arg3 ).GetLocArg(),
+ CLocalizedStringArg<X>( arg4 ).GetLocArg(),
+ CLocalizedStringArg<Y>( arg5 ).GetLocArg() );
+ }
+ }
+
+ CConstructLocalizedString( const locchar_t *loc_Format, KeyValues *pKeyValues )
+ {
+ m_loc_Buffer[0] = '\0';
+
+ if ( loc_Format && pKeyValues )
+ {
+ ::ILocalize::ConstructString( m_loc_Buffer, sizeof( m_loc_Buffer ), loc_Format, pKeyValues );
+ }
+ }
+
+ operator const locchar_t *() const
+ {
+ return m_loc_Buffer;
+ }
+
+private:
+ enum { kBufferSize = 512, };
+ locchar_t m_loc_Buffer[ kBufferSize ];
+};
+
+#endif // TIER1_ILOCALIZE_H
diff --git a/mp/src/public/tier1/interface.h b/mp/src/public/tier1/interface.h
index 22ce5a5c..5453f67d 100644
--- a/mp/src/public/tier1/interface.h
+++ b/mp/src/public/tier1/interface.h
@@ -1,230 +1,230 @@
-//========= Copyright 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
-
-#ifdef _LINUX
-#include <dlfcn.h> // dlopen,dlclose, et al
-#include <unistd.h>
-
-#define GetProcAddress dlsym
-
-#ifdef _snprintf
-#undef _snprintf
-#endif
-#define _snprintf snprintf
-#endif
-
-// TODO: move interface.cpp into tier0 library.
-#include "tier0/platform.h"
-
-// 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.
- static InterfaceReg *s_pInterfaceRegs;
-};
-
-// 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_WITH_NAMESPACE(className, interfaceNamespace, interfaceName, versionName, globalVarName) \
- static void* __Create##className##interfaceName##_interface() {return static_cast<interfaceNamespace interfaceName *>( &globalVarName );} \
- static InterfaceReg __g_Create##className##interfaceName##_reg(__Create##className##interfaceName##_interface, versionName);
-#else
-#define EXPOSE_SINGLE_INTERFACE_GLOBALVAR_WITH_NAMESPACE(className, interfaceNamespace, interfaceName, versionName, globalVarName) \
- namespace _SUBSYSTEM \
- { \
- static void* __Create##className##interfaceName##_interface() {return static_cast<interfaceNamespace interfaceName *>( &globalVarName );} \
- static InterfaceReg __g_Create##className##interfaceName##_reg(__Create##className##interfaceName##_interface, versionName); \
- }
-#endif
-
-#define EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, globalVarName) \
- EXPOSE_SINGLE_INTERFACE_GLOBALVAR_WITH_NAMESPACE(className, , interfaceName, versionName, globalVarName)
-
-// 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 );
-
-enum Sys_Flags
-{
- SYS_NOFLAGS = 0x00,
- SYS_NOLOAD = 0x01 // no loading, no ref-counting, only returns handle if lib is loaded.
-};
-
-//-----------------------------------------------------------------------------
-// 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, Sys_Flags flags = SYS_NOFLAGS );
-extern void Sys_UnloadModule( CSysModule *pModule );
-
-// 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
-
-
-
+//========= Copyright 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
+
+#ifdef _LINUX
+#include <dlfcn.h> // dlopen,dlclose, et al
+#include <unistd.h>
+
+#define GetProcAddress dlsym
+
+#ifdef _snprintf
+#undef _snprintf
+#endif
+#define _snprintf snprintf
+#endif
+
+// TODO: move interface.cpp into tier0 library.
+#include "tier0/platform.h"
+
+// 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.
+ static InterfaceReg *s_pInterfaceRegs;
+};
+
+// 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_WITH_NAMESPACE(className, interfaceNamespace, interfaceName, versionName, globalVarName) \
+ static void* __Create##className##interfaceName##_interface() {return static_cast<interfaceNamespace interfaceName *>( &globalVarName );} \
+ static InterfaceReg __g_Create##className##interfaceName##_reg(__Create##className##interfaceName##_interface, versionName);
+#else
+#define EXPOSE_SINGLE_INTERFACE_GLOBALVAR_WITH_NAMESPACE(className, interfaceNamespace, interfaceName, versionName, globalVarName) \
+ namespace _SUBSYSTEM \
+ { \
+ static void* __Create##className##interfaceName##_interface() {return static_cast<interfaceNamespace interfaceName *>( &globalVarName );} \
+ static InterfaceReg __g_Create##className##interfaceName##_reg(__Create##className##interfaceName##_interface, versionName); \
+ }
+#endif
+
+#define EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, globalVarName) \
+ EXPOSE_SINGLE_INTERFACE_GLOBALVAR_WITH_NAMESPACE(className, , interfaceName, versionName, globalVarName)
+
+// 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 );
+
+enum Sys_Flags
+{
+ SYS_NOFLAGS = 0x00,
+ SYS_NOLOAD = 0x01 // no loading, no ref-counting, only returns handle if lib is loaded.
+};
+
+//-----------------------------------------------------------------------------
+// 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, Sys_Flags flags = SYS_NOFLAGS );
+extern void Sys_UnloadModule( CSysModule *pModule );
+
+// 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/mp/src/public/tier1/kvpacker.h b/mp/src/public/tier1/kvpacker.h
index 8812ee4e..7e47fa1a 100644
--- a/mp/src/public/tier1/kvpacker.h
+++ b/mp/src/public/tier1/kvpacker.h
@@ -1,49 +1,49 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//=============================================================================//
-
-#ifndef KVPACKER_H
-#define KVPACKER_H
-
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include "KeyValues.h"
-
-//-----------------------------------------------------------------------------
-// Purpose: Handles packing KeyValues binary packing and unpacking in a a
-// consistent way across all branches, including Steam. If you change
-// this packing format you need to do so in a backward compatible way
-// so that the Steam servers and all the various GCs can still talk to
-// each other.
-//-----------------------------------------------------------------------------
-class KVPacker
-{
-public:
- bool WriteAsBinary( KeyValues *pNode, CUtlBuffer &buffer );
- bool ReadAsBinary( KeyValues *pNode, CUtlBuffer &buffer );
-
-private:
- // These types are used for serialization of KeyValues nodes.
- // Do not renumber them or you will break serialization across
- // branches.
- enum EPackType
- {
- PACKTYPE_NONE = 0,
- PACKTYPE_STRING,
- PACKTYPE_INT,
- PACKTYPE_FLOAT,
- PACKTYPE_PTR,
- PACKTYPE_WSTRING,
- PACKTYPE_COLOR,
- PACKTYPE_UINT64,
- PACKTYPE_NULLMARKER, // used to mark the end of a block in the binary format
- };
-};
-
-
-#endif // KVPACKER_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef KVPACKER_H
+#define KVPACKER_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "KeyValues.h"
+
+//-----------------------------------------------------------------------------
+// Purpose: Handles packing KeyValues binary packing and unpacking in a a
+// consistent way across all branches, including Steam. If you change
+// this packing format you need to do so in a backward compatible way
+// so that the Steam servers and all the various GCs can still talk to
+// each other.
+//-----------------------------------------------------------------------------
+class KVPacker
+{
+public:
+ bool WriteAsBinary( KeyValues *pNode, CUtlBuffer &buffer );
+ bool ReadAsBinary( KeyValues *pNode, CUtlBuffer &buffer );
+
+private:
+ // These types are used for serialization of KeyValues nodes.
+ // Do not renumber them or you will break serialization across
+ // branches.
+ enum EPackType
+ {
+ PACKTYPE_NONE = 0,
+ PACKTYPE_STRING,
+ PACKTYPE_INT,
+ PACKTYPE_FLOAT,
+ PACKTYPE_PTR,
+ PACKTYPE_WSTRING,
+ PACKTYPE_COLOR,
+ PACKTYPE_UINT64,
+ PACKTYPE_NULLMARKER, // used to mark the end of a block in the binary format
+ };
+};
+
+
+#endif // KVPACKER_H
diff --git a/mp/src/public/tier1/lzmaDecoder.h b/mp/src/public/tier1/lzmaDecoder.h
index 8aa1f2ca..51ecfd1a 100644
--- a/mp/src/public/tier1/lzmaDecoder.h
+++ b/mp/src/public/tier1/lzmaDecoder.h
@@ -1,41 +1,41 @@
-//
-// LZMA Decoder. Designed for run time decoding.
-//
-// LZMA SDK 4.43 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
-// http://www.7-zip.org/
-//
-//=====================================================================================//
-
-#ifndef _LZMADECODER_H
-#define _LZMADECODER_H
-#pragma once
-
-#if !defined( _X360 )
-#define LZMA_ID (('A'<<24)|('M'<<16)|('Z'<<8)|('L'))
-#else
-#define LZMA_ID (('L'<<24)|('Z'<<16)|('M'<<8)|('A'))
-#endif
-
-// bind the buffer for correct identification
-#pragma pack(1)
-struct lzma_header_t
-{
- unsigned int id;
- unsigned int actualSize; // always little endian
- unsigned int lzmaSize; // always little endian
- unsigned char properties[5];
-};
-#pragma pack()
-
-class CLZMA
-{
-public:
- unsigned int Uncompress( unsigned char *pInput, unsigned char *pOutput );
- bool IsCompressed( unsigned char *pInput );
- unsigned int GetActualSize( unsigned char *pInput );
-
-private:
-};
-
-#endif
-
+//
+// LZMA Decoder. Designed for run time decoding.
+//
+// LZMA SDK 4.43 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+// http://www.7-zip.org/
+//
+//=====================================================================================//
+
+#ifndef _LZMADECODER_H
+#define _LZMADECODER_H
+#pragma once
+
+#if !defined( _X360 )
+#define LZMA_ID (('A'<<24)|('M'<<16)|('Z'<<8)|('L'))
+#else
+#define LZMA_ID (('L'<<24)|('Z'<<16)|('M'<<8)|('A'))
+#endif
+
+// bind the buffer for correct identification
+#pragma pack(1)
+struct lzma_header_t
+{
+ unsigned int id;
+ unsigned int actualSize; // always little endian
+ unsigned int lzmaSize; // always little endian
+ unsigned char properties[5];
+};
+#pragma pack()
+
+class CLZMA
+{
+public:
+ unsigned int Uncompress( unsigned char *pInput, unsigned char *pOutput );
+ bool IsCompressed( unsigned char *pInput );
+ unsigned int GetActualSize( unsigned char *pInput );
+
+private:
+};
+
+#endif
+
diff --git a/mp/src/public/tier1/lzss.h b/mp/src/public/tier1/lzss.h
index 0afdfef0..8b3409a9 100644
--- a/mp/src/public/tier1/lzss.h
+++ b/mp/src/public/tier1/lzss.h
@@ -1,69 +1,69 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// LZSS Codec. Designed for fast cheap gametime encoding/decoding. Compression results
-// are not aggresive as other alogrithms, but gets 2:1 on most arbitrary uncompressed data.
-//
-//=====================================================================================//
-
-#ifndef _LZSS_H
-#define _LZSS_H
-#pragma once
-
-#define LZSS_ID uint32( BigLong( ('L'<<24)|('Z'<<16)|('S'<<8)|('S') ) )
-#define SNAPPY_ID uint32( BigLong( ('S'<<24)|('N'<<16)|('A'<<8)|('P') ) )
-
-// bind the buffer for correct identification
-struct lzss_header_t
-{
- unsigned int id;
- unsigned int actualSize; // always little endian
-};
-
-class CUtlBuffer;
-
-#define DEFAULT_LZSS_WINDOW_SIZE 4096
-
-class CLZSS
-{
-public:
- unsigned char* Compress( const unsigned char *pInput, int inputlen, unsigned int *pOutputSize );
- unsigned char* CompressNoAlloc( const unsigned char *pInput, int inputlen, unsigned char *pOutput, unsigned int *pOutputSize );
- unsigned int Uncompress( const unsigned char *pInput, unsigned char *pOutput );
- //unsigned int Uncompress( unsigned char *pInput, CUtlBuffer &buf );
- unsigned int SafeUncompress( const unsigned char *pInput, unsigned char *pOutput, unsigned int unBufSize );
-
- static bool IsCompressed( const unsigned char *pInput );
- static unsigned int GetActualSize( const unsigned char *pInput );
-
- // windowsize must be a power of two.
- FORCEINLINE CLZSS( int nWindowSize = DEFAULT_LZSS_WINDOW_SIZE );
-
-private:
- // expected to be sixteen bytes
- struct lzss_node_t
- {
- const unsigned char *pData;
- lzss_node_t *pPrev;
- lzss_node_t *pNext;
- char empty[4];
- };
-
- struct lzss_list_t
- {
- lzss_node_t *pStart;
- lzss_node_t *pEnd;
- };
-
- void BuildHash( const unsigned char *pData );
- lzss_list_t *m_pHashTable;
- lzss_node_t *m_pHashTarget;
- int m_nWindowSize;
-
-};
-
-FORCEINLINE CLZSS::CLZSS( int nWindowSize )
-{
- m_nWindowSize = nWindowSize;
-}
-#endif
-
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// LZSS Codec. Designed for fast cheap gametime encoding/decoding. Compression results
+// are not aggresive as other alogrithms, but gets 2:1 on most arbitrary uncompressed data.
+//
+//=====================================================================================//
+
+#ifndef _LZSS_H
+#define _LZSS_H
+#pragma once
+
+#define LZSS_ID uint32( BigLong( ('L'<<24)|('Z'<<16)|('S'<<8)|('S') ) )
+#define SNAPPY_ID uint32( BigLong( ('S'<<24)|('N'<<16)|('A'<<8)|('P') ) )
+
+// bind the buffer for correct identification
+struct lzss_header_t
+{
+ unsigned int id;
+ unsigned int actualSize; // always little endian
+};
+
+class CUtlBuffer;
+
+#define DEFAULT_LZSS_WINDOW_SIZE 4096
+
+class CLZSS
+{
+public:
+ unsigned char* Compress( const unsigned char *pInput, int inputlen, unsigned int *pOutputSize );
+ unsigned char* CompressNoAlloc( const unsigned char *pInput, int inputlen, unsigned char *pOutput, unsigned int *pOutputSize );
+ unsigned int Uncompress( const unsigned char *pInput, unsigned char *pOutput );
+ //unsigned int Uncompress( unsigned char *pInput, CUtlBuffer &buf );
+ unsigned int SafeUncompress( const unsigned char *pInput, unsigned char *pOutput, unsigned int unBufSize );
+
+ static bool IsCompressed( const unsigned char *pInput );
+ static unsigned int GetActualSize( const unsigned char *pInput );
+
+ // windowsize must be a power of two.
+ FORCEINLINE CLZSS( int nWindowSize = DEFAULT_LZSS_WINDOW_SIZE );
+
+private:
+ // expected to be sixteen bytes
+ struct lzss_node_t
+ {
+ const unsigned char *pData;
+ lzss_node_t *pPrev;
+ lzss_node_t *pNext;
+ char empty[4];
+ };
+
+ struct lzss_list_t
+ {
+ lzss_node_t *pStart;
+ lzss_node_t *pEnd;
+ };
+
+ void BuildHash( const unsigned char *pData );
+ lzss_list_t *m_pHashTable;
+ lzss_node_t *m_pHashTarget;
+ int m_nWindowSize;
+
+};
+
+FORCEINLINE CLZSS::CLZSS( int nWindowSize )
+{
+ m_nWindowSize = nWindowSize;
+}
+#endif
+
diff --git a/mp/src/public/tier1/mempool.h b/mp/src/public/tier1/mempool.h
index 65eeb7c9..88406fbf 100644
--- a/mp/src/public/tier1/mempool.h
+++ b/mp/src/public/tier1/mempool.h
@@ -1,551 +1,551 @@
-//========= Copyright 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)( PRINTF_FORMAT_STRING 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() { return m_BlocksAllocated; }
- int PeakCount() { return m_PeakAlloc; }
-
-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.
-
- // Put m_BlocksAllocated in front of m_pHeadOfFreeList for better
- // packing on 64-bit where pointers are 8-byte aligned.
- int m_BlocksAllocated;
- // FIXME: Change m_ppMemBlob into a growable array?
- void *m_pHeadOfFreeList;
- 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;
-};
-
-
-//-----------------------------------------------------------------------------
-//
-//-----------------------------------------------------------------------------
-class CMemoryPoolMT : public CUtlMemoryPool
-{
-public:
- CMemoryPoolMT(int blockSize, int numElements, int growMode = GROW_FAST, const char *pszAllocOwner = NULL) : CUtlMemoryPool( blockSize, numElements, growMode, pszAllocOwner) {}
-
-
- 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 ) {
- #ifdef PLATFORM_64BITS
- COMPILE_TIME_ASSERT( sizeof(CUtlMemoryPool) == 64 );
- #else
- COMPILE_TIME_ASSERT( sizeof(CUtlMemoryPool) == 48 );
- #endif
- }
-
- T* Alloc();
- T* AllocZero();
- void Free( T *pMem );
-
- void Clear();
-};
-
-
-//-----------------------------------------------------------------------------
-// Specialized pool for aligned data management (e.g., Xbox cubemaps)
-//-----------------------------------------------------------------------------
-template <int ITEM_SIZE, int ALIGNMENT, int CHUNK_SIZE, class CAllocator, int COMPACT_THRESHOLD = 4 >
-class CAlignedMemPool
-{
- enum
- {
- BLOCK_SIZE = ALIGN_VALUE( ITEM_SIZE, ALIGNMENT ) > 8 ? 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() { return m_Chunks.Count() * ( CHUNK_SIZE / BLOCK_SIZE ); }
- int NumAllocated() { return NumTotal() - m_nFree; }
- int NumFree() { return m_nFree; }
-
- int BytesTotal() { return NumTotal() * BLOCK_SIZE; }
- int BytesAllocated() { return NumAllocated() * BLOCK_SIZE; }
- int BytesFree() { 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;
- float m_TimeLastCompact;
-};
-
-//-----------------------------------------------------------------------------
-// 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;
- while ( m_AvailableObjects.PopItem( &p ) )
- {
- delete p;
- }
- }
-
- T *GetObject( bool bCreateNewIfEmpty = bDefCreateNewIfEmpty )
- {
- T *p;
- 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;
-};
-
-//-----------------------------------------------------------------------------
-
-
-template< class T >
-inline T* CClassMemoryPool<T>::Alloc()
-{
- T *pRet;
-
- {
- MEM_ALLOC_CREDIT_(MEM_ALLOC_CLASSNAME(T));
- pRet = (T*)CUtlMemoryPool::Alloc();
- }
-
- if ( pRet )
- {
- Construct( pRet );
- }
- return pRet;
-}
-
-template< class T >
-inline T* CClassMemoryPool<T>::AllocZero()
-{
- T *pRet;
-
- {
- MEM_ALLOC_CREDIT_(MEM_ALLOC_CLASSNAME(T));
- 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, int COMPACT_THRESHOLD >
-inline CAlignedMemPool<ITEM_SIZE, ALIGNMENT, CHUNK_SIZE, CAllocator, 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, int COMPACT_THRESHOLD >
-inline void *CAlignedMemPool<ITEM_SIZE, ALIGNMENT, CHUNK_SIZE, CAllocator, COMPACT_THRESHOLD>::Alloc()
-{
- if ( !m_pFirstFree )
- {
- 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, int COMPACT_THRESHOLD >
-inline void CAlignedMemPool<ITEM_SIZE, ALIGNMENT, CHUNK_SIZE, CAllocator, COMPACT_THRESHOLD>::Free( void *p )
-{
- // 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 )
- {
- float time = Plat_FloatTime();
- float compactTime = ( m_nFree >= ( CHUNK_SIZE / BLOCK_SIZE ) * COMPACT_THRESHOLD * 4 ) ? 15.0 : 30.0;
- if ( m_TimeLastCompact > time || m_TimeLastCompact + compactTime < Plat_FloatTime() )
- {
- Compact();
- m_TimeLastCompact = time;
- }
- }
-}
-
-template <int ITEM_SIZE, int ALIGNMENT, int CHUNK_SIZE, class CAllocator, int COMPACT_THRESHOLD >
-inline int __cdecl CAlignedMemPool<ITEM_SIZE, ALIGNMENT, CHUNK_SIZE, CAllocator, 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, int COMPACT_THRESHOLD >
-inline void CAlignedMemPool<ITEM_SIZE, ALIGNMENT, CHUNK_SIZE, CAllocator, 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
+//========= Copyright 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)( PRINTF_FORMAT_STRING 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() { return m_BlocksAllocated; }
+ int PeakCount() { return m_PeakAlloc; }
+
+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.
+
+ // Put m_BlocksAllocated in front of m_pHeadOfFreeList for better
+ // packing on 64-bit where pointers are 8-byte aligned.
+ int m_BlocksAllocated;
+ // FIXME: Change m_ppMemBlob into a growable array?
+ void *m_pHeadOfFreeList;
+ 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;
+};
+
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+class CMemoryPoolMT : public CUtlMemoryPool
+{
+public:
+ CMemoryPoolMT(int blockSize, int numElements, int growMode = GROW_FAST, const char *pszAllocOwner = NULL) : CUtlMemoryPool( blockSize, numElements, growMode, pszAllocOwner) {}
+
+
+ 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 ) {
+ #ifdef PLATFORM_64BITS
+ COMPILE_TIME_ASSERT( sizeof(CUtlMemoryPool) == 64 );
+ #else
+ COMPILE_TIME_ASSERT( sizeof(CUtlMemoryPool) == 48 );
+ #endif
+ }
+
+ T* Alloc();
+ T* AllocZero();
+ void Free( T *pMem );
+
+ void Clear();
+};
+
+
+//-----------------------------------------------------------------------------
+// Specialized pool for aligned data management (e.g., Xbox cubemaps)
+//-----------------------------------------------------------------------------
+template <int ITEM_SIZE, int ALIGNMENT, int CHUNK_SIZE, class CAllocator, int COMPACT_THRESHOLD = 4 >
+class CAlignedMemPool
+{
+ enum
+ {
+ BLOCK_SIZE = ALIGN_VALUE( ITEM_SIZE, ALIGNMENT ) > 8 ? 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() { return m_Chunks.Count() * ( CHUNK_SIZE / BLOCK_SIZE ); }
+ int NumAllocated() { return NumTotal() - m_nFree; }
+ int NumFree() { return m_nFree; }
+
+ int BytesTotal() { return NumTotal() * BLOCK_SIZE; }
+ int BytesAllocated() { return NumAllocated() * BLOCK_SIZE; }
+ int BytesFree() { 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;
+ float m_TimeLastCompact;
+};
+
+//-----------------------------------------------------------------------------
+// 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;
+ while ( m_AvailableObjects.PopItem( &p ) )
+ {
+ delete p;
+ }
+ }
+
+ T *GetObject( bool bCreateNewIfEmpty = bDefCreateNewIfEmpty )
+ {
+ T *p;
+ 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;
+};
+
+//-----------------------------------------------------------------------------
+
+
+template< class T >
+inline T* CClassMemoryPool<T>::Alloc()
+{
+ T *pRet;
+
+ {
+ MEM_ALLOC_CREDIT_(MEM_ALLOC_CLASSNAME(T));
+ pRet = (T*)CUtlMemoryPool::Alloc();
+ }
+
+ if ( pRet )
+ {
+ Construct( pRet );
+ }
+ return pRet;
+}
+
+template< class T >
+inline T* CClassMemoryPool<T>::AllocZero()
+{
+ T *pRet;
+
+ {
+ MEM_ALLOC_CREDIT_(MEM_ALLOC_CLASSNAME(T));
+ 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, int COMPACT_THRESHOLD >
+inline CAlignedMemPool<ITEM_SIZE, ALIGNMENT, CHUNK_SIZE, CAllocator, 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, int COMPACT_THRESHOLD >
+inline void *CAlignedMemPool<ITEM_SIZE, ALIGNMENT, CHUNK_SIZE, CAllocator, COMPACT_THRESHOLD>::Alloc()
+{
+ if ( !m_pFirstFree )
+ {
+ 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, int COMPACT_THRESHOLD >
+inline void CAlignedMemPool<ITEM_SIZE, ALIGNMENT, CHUNK_SIZE, CAllocator, COMPACT_THRESHOLD>::Free( void *p )
+{
+ // 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 )
+ {
+ float time = Plat_FloatTime();
+ float compactTime = ( m_nFree >= ( CHUNK_SIZE / BLOCK_SIZE ) * COMPACT_THRESHOLD * 4 ) ? 15.0 : 30.0;
+ if ( m_TimeLastCompact > time || m_TimeLastCompact + compactTime < Plat_FloatTime() )
+ {
+ Compact();
+ m_TimeLastCompact = time;
+ }
+ }
+}
+
+template <int ITEM_SIZE, int ALIGNMENT, int CHUNK_SIZE, class CAllocator, int COMPACT_THRESHOLD >
+inline int __cdecl CAlignedMemPool<ITEM_SIZE, ALIGNMENT, CHUNK_SIZE, CAllocator, 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, int COMPACT_THRESHOLD >
+inline void CAlignedMemPool<ITEM_SIZE, ALIGNMENT, CHUNK_SIZE, CAllocator, 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/mp/src/public/tier1/memstack.h b/mp/src/public/tier1/memstack.h
index dff0f240..e5f08855 100644
--- a/mp/src/public/tier1/memstack.h
+++ b/mp/src/public/tier1/memstack.h
@@ -1,207 +1,207 @@
-//========= Copyright 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
-
-//-----------------------------------------------------------------------------
-
-typedef unsigned MemoryStackMark_t;
-
-class CMemoryStack
-{
-public:
- CMemoryStack();
- ~CMemoryStack();
-
- bool Init( unsigned maxSize = 0, unsigned commitSize = 0, unsigned initialCommit = 0, unsigned alignment = 16 );
-#ifdef _X360
- bool InitPhysical( unsigned size = 0, unsigned alignment = 16 );
-#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(); }
-
-private:
- bool CommitTo( byte * ) RESTRICT;
-
- byte *m_pNextAlloc;
- byte *m_pCommitLimit;
- byte *m_pAllocLimit;
-
- byte *m_pBase;
-
- unsigned m_maxSize;
- unsigned m_alignment;
-#ifdef _WIN32
- unsigned m_commitSize;
- unsigned m_minCommit;
-#endif
-#ifdef _X360
- bool m_bPhysical;
-#endif
-};
-
-//-------------------------------------
-
-FORCEINLINE void *CMemoryStack::Alloc( unsigned bytes, bool bClear ) RESTRICT
-{
- Assert( m_pBase );
-
- int alignment = m_alignment;
- if ( bytes )
- {
- bytes = AlignValue( bytes, alignment );
- }
- else
- {
- bytes = 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 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( 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 { return (i >= 0) && (i < 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 { return it.index >= 0 && it.index < 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 ) {}
-
-private:
- CMemoryStack m_MemoryStack;
- int m_nAllocated;
-};
-
-//-----------------------------------------------------------------------------
-
-#endif // MEMSTACK_H
+//========= Copyright 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
+
+//-----------------------------------------------------------------------------
+
+typedef unsigned MemoryStackMark_t;
+
+class CMemoryStack
+{
+public:
+ CMemoryStack();
+ ~CMemoryStack();
+
+ bool Init( unsigned maxSize = 0, unsigned commitSize = 0, unsigned initialCommit = 0, unsigned alignment = 16 );
+#ifdef _X360
+ bool InitPhysical( unsigned size = 0, unsigned alignment = 16 );
+#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(); }
+
+private:
+ bool CommitTo( byte * ) RESTRICT;
+
+ byte *m_pNextAlloc;
+ byte *m_pCommitLimit;
+ byte *m_pAllocLimit;
+
+ byte *m_pBase;
+
+ unsigned m_maxSize;
+ unsigned m_alignment;
+#ifdef _WIN32
+ unsigned m_commitSize;
+ unsigned m_minCommit;
+#endif
+#ifdef _X360
+ bool m_bPhysical;
+#endif
+};
+
+//-------------------------------------
+
+FORCEINLINE void *CMemoryStack::Alloc( unsigned bytes, bool bClear ) RESTRICT
+{
+ Assert( m_pBase );
+
+ int alignment = m_alignment;
+ if ( bytes )
+ {
+ bytes = AlignValue( bytes, alignment );
+ }
+ else
+ {
+ bytes = 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 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( 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 { return (i >= 0) && (i < 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 { return it.index >= 0 && it.index < 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 ) {}
+
+private:
+ CMemoryStack m_MemoryStack;
+ int m_nAllocated;
+};
+
+//-----------------------------------------------------------------------------
+
+#endif // MEMSTACK_H
diff --git a/mp/src/public/tier1/netadr.h b/mp/src/public/tier1/netadr.h
index fdc28504..9249613e 100644
--- a/mp/src/public/tier1/netadr.h
+++ b/mp/src/public/tier1/netadr.h
@@ -1,68 +1,68 @@
-//========= Copyright 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;
-
-typedef struct netadr_s
-{
-public:
- netadr_s() { SetIP( 0 ); SetPort( 0 ); SetType( NA_IP ); }
- netadr_s( uint unIP, uint16 usPort ) { SetIP( unIP ); SetPort( usPort ); SetType( NA_IP ); }
- netadr_s( 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_s &a, bool onlyBase = false) const;
- bool CompareClassBAdr (const netadr_s &a) const;
- bool CompareClassCAdr (const netadr_s &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 GetIPHostByteOrder() const;
- unsigned int GetIPNetworkByteOrder() 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
- void SetFromSocket( int hSocket );
- bool operator==(const netadr_s &netadr) const {return ( CompareAdr( netadr ) );}
- bool operator<(const netadr_s &netadr) const;
-
-public: // members are public to avoid to much changes
-
- netadrtype_t type;
- unsigned char ip[4];
- unsigned short port;
-} netadr_t;
-
-#endif // NETADR_H
+//========= Copyright 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;
+
+typedef struct netadr_s
+{
+public:
+ netadr_s() { SetIP( 0 ); SetPort( 0 ); SetType( NA_IP ); }
+ netadr_s( uint unIP, uint16 usPort ) { SetIP( unIP ); SetPort( usPort ); SetType( NA_IP ); }
+ netadr_s( 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_s &a, bool onlyBase = false) const;
+ bool CompareClassBAdr (const netadr_s &a) const;
+ bool CompareClassCAdr (const netadr_s &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 GetIPHostByteOrder() const;
+ unsigned int GetIPNetworkByteOrder() 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
+ void SetFromSocket( int hSocket );
+ bool operator==(const netadr_s &netadr) const {return ( CompareAdr( netadr ) );}
+ bool operator<(const netadr_s &netadr) const;
+
+public: // members are public to avoid to much changes
+
+ netadrtype_t type;
+ unsigned char ip[4];
+ unsigned short port;
+} netadr_t;
+
+#endif // NETADR_H
diff --git a/mp/src/public/tier1/passwordhash.h b/mp/src/public/tier1/passwordhash.h
index b2480590..f557c7f7 100644
--- a/mp/src/public/tier1/passwordhash.h
+++ b/mp/src/public/tier1/passwordhash.h
@@ -1,94 +1,94 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Cryptographic hash agility helper definitions
-//
-//=============================================================================
-
-#ifndef PASSWORDHASH_H
-#define PASSWORDHASH_H
-
-#if defined( _WIN32 )
-#pragma once
-#endif
-
-
-#include "checksum_sha1.h"
-
-typedef unsigned char BigPasswordHash_t[32];
-typedef unsigned char PBKDF2Hash_t[32];
-
-//
-// A union of all the possible password hash types.
-// When adding to this, if the maximum size of the
-// structure has changed then the Account table and
-// the AccountSecurityHistory table need to be manually
-// revised using something like the following SQL:
-//
-// ALTER TABLE Account ALTER COLUMN PasswordHash binary(32)
-// ALTER TABLE AccountSecurityHistory ALTER COLUMN PasswordHashOld binary(32)
-// ALTER TABLE AccountSecurityHistory ALTER COLUMN PasswordHashNew binary(32)
-//
-// Replace 32 with the new size of PasswordHash_t.
-//
-// If the width of those columns does not match sizeof(PasswordHash_t), many
-// database operations will fail.
-//
-// Note that while this query was correct at the time this code was checked in,
-// it may not be sufficient at the time you actually change the size of the
-// type, so look around.
-//
-typedef union
-{
- SHADigest_t sha;
- BigPasswordHash_t bigpassword;
- PBKDF2Hash_t pbkdf2;
-} PasswordHash_t;
-
-
-//
-// Enum of all available password hash algorithms. These should
-// be consecutive and ordinals should never be reused.
-//
-// k_EHashSHA1: A salted SHA-1 hash, width 20 bytes.
-// k_EHashBigPassword: For testing purposes, a salted SHA-1 hash extended to 32 bytes, with 6 bytes of 0x1 on either side.
-// k_EHashPBKDF2_1000: A PKCS#5 v2.0 Password-Based Key Derivation Function hash (PBKDF2-HMAC-SHA256) with 1,000 iterations.
-// The digest width is 32 bytes.
-// k_EHashPBKDF2_5000: A PKCS#5 v2.0 Password-Based Key Derivation Function hash (PBKDF2-HMAC-SHA256) with 5,000 iterations.
-// k_EHashPBKDF2_10000: A PKCS#5 v2.0 Password-Based Key Derivation Function hash (PBKDF2-HMAC-SHA256) with 10,000 iterations.
-// k_EHashSHA1WrappedWithPBKDF2_10000: A SHA-1 hash which is then further hashed with PBKDF2 at 10,000 rounds. Used for
-// strengthening old hashes in the database that haven't been logged in in a long time.
-//
-// Make sure to update k_EHashMax when adding new hash types. Also add the length into the k_HashLengths array below.
-enum EPasswordHashAlg
-{
- k_EHashSHA1 = 0,
- k_EHashBigPassword = 1,
- k_EHashPBKDF2_1000 = 2,
- k_EHashPBKDF2_5000 = 3,
- k_EHashPBKDF2_10000 = 4,
- k_EHashSHA1WrappedWithPBKDF2_10000 = 5,
- k_EHashMax = 5,
-};
-
-//
-// Hash sizes for the various available hash algorithms,
-// indexed by EPasswordHashAlg.
-const size_t k_HashLengths[] = {
- sizeof(SHADigest_t),
- sizeof(BigPasswordHash_t),
- sizeof(PBKDF2Hash_t),
- sizeof(PBKDF2Hash_t),
- sizeof(PBKDF2Hash_t),
- sizeof(PBKDF2Hash_t),
-};
-
-#if defined(C_ASSERT)
-//
-// If you're hitting this assert at compile time, it means that you've added a new
-// hash type and properly updated k_EHashMax, but you forgot to add the length
-// of the new hash type into k_HashLengths. So do that.
-//
-C_ASSERT( ( ( sizeof(k_HashLengths) / sizeof(size_t) ) == k_EHashMax + 1 ) );
-#endif
-
-#endif // PASSWORDHASH_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Cryptographic hash agility helper definitions
+//
+//=============================================================================
+
+#ifndef PASSWORDHASH_H
+#define PASSWORDHASH_H
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+
+#include "checksum_sha1.h"
+
+typedef unsigned char BigPasswordHash_t[32];
+typedef unsigned char PBKDF2Hash_t[32];
+
+//
+// A union of all the possible password hash types.
+// When adding to this, if the maximum size of the
+// structure has changed then the Account table and
+// the AccountSecurityHistory table need to be manually
+// revised using something like the following SQL:
+//
+// ALTER TABLE Account ALTER COLUMN PasswordHash binary(32)
+// ALTER TABLE AccountSecurityHistory ALTER COLUMN PasswordHashOld binary(32)
+// ALTER TABLE AccountSecurityHistory ALTER COLUMN PasswordHashNew binary(32)
+//
+// Replace 32 with the new size of PasswordHash_t.
+//
+// If the width of those columns does not match sizeof(PasswordHash_t), many
+// database operations will fail.
+//
+// Note that while this query was correct at the time this code was checked in,
+// it may not be sufficient at the time you actually change the size of the
+// type, so look around.
+//
+typedef union
+{
+ SHADigest_t sha;
+ BigPasswordHash_t bigpassword;
+ PBKDF2Hash_t pbkdf2;
+} PasswordHash_t;
+
+
+//
+// Enum of all available password hash algorithms. These should
+// be consecutive and ordinals should never be reused.
+//
+// k_EHashSHA1: A salted SHA-1 hash, width 20 bytes.
+// k_EHashBigPassword: For testing purposes, a salted SHA-1 hash extended to 32 bytes, with 6 bytes of 0x1 on either side.
+// k_EHashPBKDF2_1000: A PKCS#5 v2.0 Password-Based Key Derivation Function hash (PBKDF2-HMAC-SHA256) with 1,000 iterations.
+// The digest width is 32 bytes.
+// k_EHashPBKDF2_5000: A PKCS#5 v2.0 Password-Based Key Derivation Function hash (PBKDF2-HMAC-SHA256) with 5,000 iterations.
+// k_EHashPBKDF2_10000: A PKCS#5 v2.0 Password-Based Key Derivation Function hash (PBKDF2-HMAC-SHA256) with 10,000 iterations.
+// k_EHashSHA1WrappedWithPBKDF2_10000: A SHA-1 hash which is then further hashed with PBKDF2 at 10,000 rounds. Used for
+// strengthening old hashes in the database that haven't been logged in in a long time.
+//
+// Make sure to update k_EHashMax when adding new hash types. Also add the length into the k_HashLengths array below.
+enum EPasswordHashAlg
+{
+ k_EHashSHA1 = 0,
+ k_EHashBigPassword = 1,
+ k_EHashPBKDF2_1000 = 2,
+ k_EHashPBKDF2_5000 = 3,
+ k_EHashPBKDF2_10000 = 4,
+ k_EHashSHA1WrappedWithPBKDF2_10000 = 5,
+ k_EHashMax = 5,
+};
+
+//
+// Hash sizes for the various available hash algorithms,
+// indexed by EPasswordHashAlg.
+const size_t k_HashLengths[] = {
+ sizeof(SHADigest_t),
+ sizeof(BigPasswordHash_t),
+ sizeof(PBKDF2Hash_t),
+ sizeof(PBKDF2Hash_t),
+ sizeof(PBKDF2Hash_t),
+ sizeof(PBKDF2Hash_t),
+};
+
+#if defined(C_ASSERT)
+//
+// If you're hitting this assert at compile time, it means that you've added a new
+// hash type and properly updated k_EHashMax, but you forgot to add the length
+// of the new hash type into k_HashLengths. So do that.
+//
+C_ASSERT( ( ( sizeof(k_HashLengths) / sizeof(size_t) ) == k_EHashMax + 1 ) );
+#endif
+
+#endif // PASSWORDHASH_H
diff --git a/mp/src/public/tier1/processor_detect.h b/mp/src/public/tier1/processor_detect.h
index cd0239bb..cb4cc37e 100644
--- a/mp/src/public/tier1/processor_detect.h
+++ b/mp/src/public/tier1/processor_detect.h
@@ -1,12 +1,12 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: functions to expose CPU capabilities
-//
-// $NoKeywords: $
-//=============================================================================//
-
-bool CheckMMXTechnology(void);
-bool CheckSSETechnology(void);
-bool CheckSSE2Technology(void);
-bool Check3DNowTechnology(void);
-
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: functions to expose CPU capabilities
+//
+// $NoKeywords: $
+//=============================================================================//
+
+bool CheckMMXTechnology(void);
+bool CheckSSETechnology(void);
+bool CheckSSE2Technology(void);
+bool Check3DNowTechnology(void);
+
diff --git a/mp/src/public/tier1/rangecheckedvar.h b/mp/src/public/tier1/rangecheckedvar.h
index 8d9eba70..52313f82 100644
--- a/mp/src/public/tier1/rangecheckedvar.h
+++ b/mp/src/public/tier1/rangecheckedvar.h
@@ -1,118 +1,118 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-//=============================================================================//
-
-#ifndef RANGECHECKEDVAR_H
-#define RANGECHECKEDVAR_H
-#ifdef _WIN32
-#pragma once
-#endif
-
-
-#include "tier0/dbg.h"
-#include "tier0/threadtools.h"
-#include "mathlib/vector.h"
-#include <float.h>
-
-
-// Use this to disable range checks within a scope.
-class CDisableRangeChecks
-{
-public:
- CDisableRangeChecks();
- ~CDisableRangeChecks();
-};
-
-
-template< class T >
-inline void RangeCheck( const T &value, int minValue, int maxValue )
-{
-#ifdef _DEBUG
- extern bool g_bDoRangeChecks;
- if ( ThreadInMainThread() && g_bDoRangeChecks )
- {
- // Ignore the min/max stuff for now.. just make sure it's not a NAN.
- Assert( _finite( value ) );
- }
-#endif
-}
-
-inline void RangeCheck( const Vector &value, int minValue, int maxValue )
-{
-#ifdef _DEBUG
- RangeCheck( value.x, minValue, maxValue );
- RangeCheck( value.y, minValue, maxValue );
- RangeCheck( value.z, minValue, maxValue );
-#endif
-}
-
-
-template< class T, int minValue, int maxValue, int startValue >
-class CRangeCheckedVar
-{
-public:
-
- inline CRangeCheckedVar()
- {
- m_Val = startValue;
- }
-
- inline CRangeCheckedVar( const T &value )
- {
- *this = value;
- }
-
- T GetRaw() const
- {
- return m_Val;
- }
-
- // Clamp the value to its limits. Interpolation code uses this after interpolating.
- inline void Clamp()
- {
- if ( m_Val < minValue )
- m_Val = minValue;
- else if ( m_Val > maxValue )
- m_Val = maxValue;
- }
-
- inline operator const T&() const
- {
- return m_Val;
- }
-
- inline CRangeCheckedVar<T, minValue, maxValue, startValue>& operator=( const T &value )
- {
- RangeCheck( value, minValue, maxValue );
- m_Val = value;
- return *this;
- }
-
- inline CRangeCheckedVar<T, minValue, maxValue, startValue>& operator+=( const T &value )
- {
- return (*this = m_Val + value);
- }
-
- inline CRangeCheckedVar<T, minValue, maxValue, startValue>& operator-=( const T &value )
- {
- return (*this = m_Val - value);
- }
-
- inline CRangeCheckedVar<T, minValue, maxValue, startValue>& operator*=( const T &value )
- {
- return (*this = m_Val * value);
- }
-
- inline CRangeCheckedVar<T, minValue, maxValue, startValue>& operator/=( const T &value )
- {
- return (*this = m_Val / value);
- }
-
-private:
-
- T m_Val;
-};
-
-#endif // RANGECHECKEDVAR_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#ifndef RANGECHECKEDVAR_H
+#define RANGECHECKEDVAR_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#include "tier0/dbg.h"
+#include "tier0/threadtools.h"
+#include "mathlib/vector.h"
+#include <float.h>
+
+
+// Use this to disable range checks within a scope.
+class CDisableRangeChecks
+{
+public:
+ CDisableRangeChecks();
+ ~CDisableRangeChecks();
+};
+
+
+template< class T >
+inline void RangeCheck( const T &value, int minValue, int maxValue )
+{
+#ifdef _DEBUG
+ extern bool g_bDoRangeChecks;
+ if ( ThreadInMainThread() && g_bDoRangeChecks )
+ {
+ // Ignore the min/max stuff for now.. just make sure it's not a NAN.
+ Assert( _finite( value ) );
+ }
+#endif
+}
+
+inline void RangeCheck( const Vector &value, int minValue, int maxValue )
+{
+#ifdef _DEBUG
+ RangeCheck( value.x, minValue, maxValue );
+ RangeCheck( value.y, minValue, maxValue );
+ RangeCheck( value.z, minValue, maxValue );
+#endif
+}
+
+
+template< class T, int minValue, int maxValue, int startValue >
+class CRangeCheckedVar
+{
+public:
+
+ inline CRangeCheckedVar()
+ {
+ m_Val = startValue;
+ }
+
+ inline CRangeCheckedVar( const T &value )
+ {
+ *this = value;
+ }
+
+ T GetRaw() const
+ {
+ return m_Val;
+ }
+
+ // Clamp the value to its limits. Interpolation code uses this after interpolating.
+ inline void Clamp()
+ {
+ if ( m_Val < minValue )
+ m_Val = minValue;
+ else if ( m_Val > maxValue )
+ m_Val = maxValue;
+ }
+
+ inline operator const T&() const
+ {
+ return m_Val;
+ }
+
+ inline CRangeCheckedVar<T, minValue, maxValue, startValue>& operator=( const T &value )
+ {
+ RangeCheck( value, minValue, maxValue );
+ m_Val = value;
+ return *this;
+ }
+
+ inline CRangeCheckedVar<T, minValue, maxValue, startValue>& operator+=( const T &value )
+ {
+ return (*this = m_Val + value);
+ }
+
+ inline CRangeCheckedVar<T, minValue, maxValue, startValue>& operator-=( const T &value )
+ {
+ return (*this = m_Val - value);
+ }
+
+ inline CRangeCheckedVar<T, minValue, maxValue, startValue>& operator*=( const T &value )
+ {
+ return (*this = m_Val * value);
+ }
+
+ inline CRangeCheckedVar<T, minValue, maxValue, startValue>& operator/=( const T &value )
+ {
+ return (*this = m_Val / value);
+ }
+
+private:
+
+ T m_Val;
+};
+
+#endif // RANGECHECKEDVAR_H
diff --git a/mp/src/public/tier1/refcount.h b/mp/src/public/tier1/refcount.h
index 5dd50011..264da100 100644
--- a/mp/src/public/tier1/refcount.h
+++ b/mp/src/public/tier1/refcount.h
@@ -1,385 +1,385 @@
-//========= Copyright 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( (long *)p ); }
- static int Decrement( int *p) { return ThreadInterlockedDecrement( (long *)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
-//-----------------------------------------------------------------------------
-
-template <class BASE_REFCOUNTED, int FINAL_REFS, const char *pszName>
-class CRefDebug : public BASE_REFCOUNTED
-{
-public:
-#ifdef _DEBUG
- 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
+//========= Copyright 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( (long *)p ); }
+ static int Decrement( int *p) { return ThreadInterlockedDecrement( (long *)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
+//-----------------------------------------------------------------------------
+
+template <class BASE_REFCOUNTED, int FINAL_REFS, const char *pszName>
+class CRefDebug : public BASE_REFCOUNTED
+{
+public:
+#ifdef _DEBUG
+ 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/mp/src/public/tier1/reliabletimer.h b/mp/src/public/tier1/reliabletimer.h
index f20f3bdf..c830fbe3 100644
--- a/mp/src/public/tier1/reliabletimer.h
+++ b/mp/src/public/tier1/reliabletimer.h
@@ -1,183 +1,183 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-//=============================================================================
-
-#ifndef RELIABLETIMER_H
-#define RELIABLETIMER_H
-
-#include "tier0/dbg.h"
-//#include "constants.h"
-#include "tier0/fasttimer.h"
-#include "tier1/tier1.h"
-#include "tier1/strtools.h"
-
-#define DbgAssert Assert
-#define kMILLION (1000000)
-#define kTHOUSAND (1000)
-
-// Timer class that uses QueryPerformanceCounter. This is heavier-weight than CFastTimer which uses rdtsc,
-// but this is reliable on multi-core systems whereas CFastTimer is not.
-
-class CReliableTimer
-{
-public:
- CReliableTimer();
- void Start();
- void End();
- int64 GetMicroseconds();
- int64 GetMilliseconds();
- void SetLimit( uint64 m_cMicroSecDuration );
- bool BLimitReached();
- int64 CMicroSecOverage();
- int64 CMicroSecLeft();
- int64 CMilliSecLeft();
-private:
- int64 GetPerformanceCountNow();
-
- int64 m_nPerformanceCounterStart;
- int64 m_nPerformanceCounterEnd;
- int64 m_nPerformanceCounterLimit;
-
- static int64 sm_nPerformanceFrequency;
- static bool sm_bUseQPC;
-};
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Records timer start time
-//-----------------------------------------------------------------------------
-inline void CReliableTimer::Start()
-{
- m_nPerformanceCounterStart = GetPerformanceCountNow();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Records timer end time
-//-----------------------------------------------------------------------------
-inline void CReliableTimer::End()
-{
- m_nPerformanceCounterEnd = GetPerformanceCountNow();
-
- // enforce that we've advanced at least one cycle
- if ( m_nPerformanceCounterEnd < m_nPerformanceCounterStart )
- {
-#ifdef _SERVER
- if ( m_nPerformanceCounterEnd+10000 < m_nPerformanceCounterStart )
- AssertMsgOnce( false, CDbgFmtMsg( "CReliableTimer went backwards - start:%lld end:%lld", m_nPerformanceCounterStart, m_nPerformanceCounterEnd ).ToString() );
-#endif
- m_nPerformanceCounterEnd = m_nPerformanceCounterStart + 1;
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Gets microseconds elapsed between start and end
-//-----------------------------------------------------------------------------
-inline int64 CReliableTimer::GetMicroseconds()
-{
- DbgAssert( m_nPerformanceCounterStart ); // timer must have been started
- DbgAssert( m_nPerformanceCounterEnd ); // timer must have been ended
- DbgAssert( 0 != sm_nPerformanceFrequency ); // must have calc'd performance counter frequency
- return ( ( m_nPerformanceCounterEnd - m_nPerformanceCounterStart ) * kMILLION / sm_nPerformanceFrequency );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Gets microseconds elapsed between start and end
-//-----------------------------------------------------------------------------
-inline int64 CReliableTimer::GetMilliseconds()
-{
- DbgAssert( m_nPerformanceCounterStart ); // timer must have been started
- DbgAssert( m_nPerformanceCounterEnd ); // timer must have been ended
- DbgAssert( 0 != sm_nPerformanceFrequency ); // must have calc'd performance counter frequency
- return ( ( m_nPerformanceCounterEnd - m_nPerformanceCounterStart ) * kTHOUSAND / sm_nPerformanceFrequency );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Sets a limit on this timer that can subsequently be checked against
-//-----------------------------------------------------------------------------
-inline void CReliableTimer::SetLimit( uint64 cMicroSecDuration )
-{
- DbgAssert( 0 != sm_nPerformanceFrequency ); // must have calc'd performance counter frequency
- m_nPerformanceCounterStart = GetPerformanceCountNow();
- m_nPerformanceCounterLimit = m_nPerformanceCounterStart + ( ( cMicroSecDuration * sm_nPerformanceFrequency ) / kMILLION );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Returns if previously set limit has been reached
-//-----------------------------------------------------------------------------
-inline bool CReliableTimer::BLimitReached()
-{
- DbgAssert( m_nPerformanceCounterStart ); // SetLimit must have been called
- DbgAssert( m_nPerformanceCounterLimit ); // SetLimit must have been called
- int64 nPerformanceCountNow = GetPerformanceCountNow();
-
- // make sure time advances
- if ( nPerformanceCountNow < m_nPerformanceCounterStart )
- {
-#ifdef _SERVER
- if ( nPerformanceCountNow+10000 < m_nPerformanceCounterStart )
- AssertMsgOnce( false, CDbgFmtMsg( "CReliableTimer went backwards - start:%lld end:%lld", m_nPerformanceCounterStart, m_nPerformanceCounterEnd ).ToString() );
-#endif
- // reset the limit to be lower, to match our new clock
- m_nPerformanceCounterLimit = nPerformanceCountNow + (m_nPerformanceCounterLimit - m_nPerformanceCounterStart);
- }
-
- return ( nPerformanceCountNow >= m_nPerformanceCounterLimit );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Returns microseconds current time is past limit, or 0 if not past limit
-//-----------------------------------------------------------------------------
-inline int64 CReliableTimer::CMicroSecOverage()
-{
- DbgAssert( m_nPerformanceCounterStart ); // SetLimit must have been called
- DbgAssert( m_nPerformanceCounterLimit ); // SetLimit must have been called
- int64 nPerformanceCountNow = GetPerformanceCountNow();
-#ifdef _SERVER
- if ( nPerformanceCountNow+10000 < m_nPerformanceCounterStart )
- AssertMsgOnce( nPerformanceCountNow >= m_nPerformanceCounterStart, CDbgFmtMsg( "CReliableTimer went backwards - start:%lld end:%lld", m_nPerformanceCounterStart, m_nPerformanceCounterEnd ).ToString() );
-#endif
- int64 nPerformanceCountOver = ( nPerformanceCountNow > m_nPerformanceCounterLimit ?
- nPerformanceCountNow - m_nPerformanceCounterLimit : 0 );
-
- Assert( 0 != sm_nPerformanceFrequency ); // must have calc'd performance counter frequency
- return ( nPerformanceCountOver * kMILLION / sm_nPerformanceFrequency );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Returns microseconds remaining until limit
-//-----------------------------------------------------------------------------
-inline int64 CReliableTimer::CMicroSecLeft()
-{
- DbgAssert( m_nPerformanceCounterStart ); // SetLimit must have been called
- DbgAssert( m_nPerformanceCounterLimit ); // SetLimit must have been called
- int64 nPerformanceCountNow = GetPerformanceCountNow();
-#ifdef _SERVER
- if ( nPerformanceCountNow+10000 < m_nPerformanceCounterStart )
- AssertMsgOnce( nPerformanceCountNow >= m_nPerformanceCounterStart, CDbgFmtMsg( "CReliableTimer went backwards - start:%lld end:%lld", m_nPerformanceCounterStart, m_nPerformanceCounterEnd ).ToString() );
-#endif
- int64 nPerformanceCountLeft = ( nPerformanceCountNow < m_nPerformanceCounterLimit ?
- m_nPerformanceCounterLimit - nPerformanceCountNow : 0 );
-
- DbgAssert( 0 != sm_nPerformanceFrequency ); // must have calc'd performance counter frequency
- return ( nPerformanceCountLeft * kMILLION / sm_nPerformanceFrequency );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Returns milliseconds remaining until limit
-//-----------------------------------------------------------------------------
-inline int64 CReliableTimer::CMilliSecLeft()
-{
- return CMicroSecLeft() / 1000;
-}
-
-
-#endif // TICKLIMITTIMER_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef RELIABLETIMER_H
+#define RELIABLETIMER_H
+
+#include "tier0/dbg.h"
+//#include "constants.h"
+#include "tier0/fasttimer.h"
+#include "tier1/tier1.h"
+#include "tier1/strtools.h"
+
+#define DbgAssert Assert
+#define kMILLION (1000000)
+#define kTHOUSAND (1000)
+
+// Timer class that uses QueryPerformanceCounter. This is heavier-weight than CFastTimer which uses rdtsc,
+// but this is reliable on multi-core systems whereas CFastTimer is not.
+
+class CReliableTimer
+{
+public:
+ CReliableTimer();
+ void Start();
+ void End();
+ int64 GetMicroseconds();
+ int64 GetMilliseconds();
+ void SetLimit( uint64 m_cMicroSecDuration );
+ bool BLimitReached();
+ int64 CMicroSecOverage();
+ int64 CMicroSecLeft();
+ int64 CMilliSecLeft();
+private:
+ int64 GetPerformanceCountNow();
+
+ int64 m_nPerformanceCounterStart;
+ int64 m_nPerformanceCounterEnd;
+ int64 m_nPerformanceCounterLimit;
+
+ static int64 sm_nPerformanceFrequency;
+ static bool sm_bUseQPC;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Records timer start time
+//-----------------------------------------------------------------------------
+inline void CReliableTimer::Start()
+{
+ m_nPerformanceCounterStart = GetPerformanceCountNow();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Records timer end time
+//-----------------------------------------------------------------------------
+inline void CReliableTimer::End()
+{
+ m_nPerformanceCounterEnd = GetPerformanceCountNow();
+
+ // enforce that we've advanced at least one cycle
+ if ( m_nPerformanceCounterEnd < m_nPerformanceCounterStart )
+ {
+#ifdef _SERVER
+ if ( m_nPerformanceCounterEnd+10000 < m_nPerformanceCounterStart )
+ AssertMsgOnce( false, CDbgFmtMsg( "CReliableTimer went backwards - start:%lld end:%lld", m_nPerformanceCounterStart, m_nPerformanceCounterEnd ).ToString() );
+#endif
+ m_nPerformanceCounterEnd = m_nPerformanceCounterStart + 1;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Gets microseconds elapsed between start and end
+//-----------------------------------------------------------------------------
+inline int64 CReliableTimer::GetMicroseconds()
+{
+ DbgAssert( m_nPerformanceCounterStart ); // timer must have been started
+ DbgAssert( m_nPerformanceCounterEnd ); // timer must have been ended
+ DbgAssert( 0 != sm_nPerformanceFrequency ); // must have calc'd performance counter frequency
+ return ( ( m_nPerformanceCounterEnd - m_nPerformanceCounterStart ) * kMILLION / sm_nPerformanceFrequency );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Gets microseconds elapsed between start and end
+//-----------------------------------------------------------------------------
+inline int64 CReliableTimer::GetMilliseconds()
+{
+ DbgAssert( m_nPerformanceCounterStart ); // timer must have been started
+ DbgAssert( m_nPerformanceCounterEnd ); // timer must have been ended
+ DbgAssert( 0 != sm_nPerformanceFrequency ); // must have calc'd performance counter frequency
+ return ( ( m_nPerformanceCounterEnd - m_nPerformanceCounterStart ) * kTHOUSAND / sm_nPerformanceFrequency );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Sets a limit on this timer that can subsequently be checked against
+//-----------------------------------------------------------------------------
+inline void CReliableTimer::SetLimit( uint64 cMicroSecDuration )
+{
+ DbgAssert( 0 != sm_nPerformanceFrequency ); // must have calc'd performance counter frequency
+ m_nPerformanceCounterStart = GetPerformanceCountNow();
+ m_nPerformanceCounterLimit = m_nPerformanceCounterStart + ( ( cMicroSecDuration * sm_nPerformanceFrequency ) / kMILLION );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns if previously set limit has been reached
+//-----------------------------------------------------------------------------
+inline bool CReliableTimer::BLimitReached()
+{
+ DbgAssert( m_nPerformanceCounterStart ); // SetLimit must have been called
+ DbgAssert( m_nPerformanceCounterLimit ); // SetLimit must have been called
+ int64 nPerformanceCountNow = GetPerformanceCountNow();
+
+ // make sure time advances
+ if ( nPerformanceCountNow < m_nPerformanceCounterStart )
+ {
+#ifdef _SERVER
+ if ( nPerformanceCountNow+10000 < m_nPerformanceCounterStart )
+ AssertMsgOnce( false, CDbgFmtMsg( "CReliableTimer went backwards - start:%lld end:%lld", m_nPerformanceCounterStart, m_nPerformanceCounterEnd ).ToString() );
+#endif
+ // reset the limit to be lower, to match our new clock
+ m_nPerformanceCounterLimit = nPerformanceCountNow + (m_nPerformanceCounterLimit - m_nPerformanceCounterStart);
+ }
+
+ return ( nPerformanceCountNow >= m_nPerformanceCounterLimit );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns microseconds current time is past limit, or 0 if not past limit
+//-----------------------------------------------------------------------------
+inline int64 CReliableTimer::CMicroSecOverage()
+{
+ DbgAssert( m_nPerformanceCounterStart ); // SetLimit must have been called
+ DbgAssert( m_nPerformanceCounterLimit ); // SetLimit must have been called
+ int64 nPerformanceCountNow = GetPerformanceCountNow();
+#ifdef _SERVER
+ if ( nPerformanceCountNow+10000 < m_nPerformanceCounterStart )
+ AssertMsgOnce( nPerformanceCountNow >= m_nPerformanceCounterStart, CDbgFmtMsg( "CReliableTimer went backwards - start:%lld end:%lld", m_nPerformanceCounterStart, m_nPerformanceCounterEnd ).ToString() );
+#endif
+ int64 nPerformanceCountOver = ( nPerformanceCountNow > m_nPerformanceCounterLimit ?
+ nPerformanceCountNow - m_nPerformanceCounterLimit : 0 );
+
+ Assert( 0 != sm_nPerformanceFrequency ); // must have calc'd performance counter frequency
+ return ( nPerformanceCountOver * kMILLION / sm_nPerformanceFrequency );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns microseconds remaining until limit
+//-----------------------------------------------------------------------------
+inline int64 CReliableTimer::CMicroSecLeft()
+{
+ DbgAssert( m_nPerformanceCounterStart ); // SetLimit must have been called
+ DbgAssert( m_nPerformanceCounterLimit ); // SetLimit must have been called
+ int64 nPerformanceCountNow = GetPerformanceCountNow();
+#ifdef _SERVER
+ if ( nPerformanceCountNow+10000 < m_nPerformanceCounterStart )
+ AssertMsgOnce( nPerformanceCountNow >= m_nPerformanceCounterStart, CDbgFmtMsg( "CReliableTimer went backwards - start:%lld end:%lld", m_nPerformanceCounterStart, m_nPerformanceCounterEnd ).ToString() );
+#endif
+ int64 nPerformanceCountLeft = ( nPerformanceCountNow < m_nPerformanceCounterLimit ?
+ m_nPerformanceCounterLimit - nPerformanceCountNow : 0 );
+
+ DbgAssert( 0 != sm_nPerformanceFrequency ); // must have calc'd performance counter frequency
+ return ( nPerformanceCountLeft * kMILLION / sm_nPerformanceFrequency );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns milliseconds remaining until limit
+//-----------------------------------------------------------------------------
+inline int64 CReliableTimer::CMilliSecLeft()
+{
+ return CMicroSecLeft() / 1000;
+}
+
+
+#endif // TICKLIMITTIMER_H
diff --git a/mp/src/public/tier1/smartptr.h b/mp/src/public/tier1/smartptr.h
index a0065e5a..466ca0bc 100644
--- a/mp/src/public/tier1/smartptr.h
+++ b/mp/src/public/tier1/smartptr.h
@@ -1,279 +1,279 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//=============================================================================//
-
-#ifndef SMARTPTR_H
-#define SMARTPTR_H
-#ifdef _WIN32
-#pragma once
-#endif
-
-
-class CRefCountAccessor
-{
-public:
- template< class T >
- static void AddRef( T *pObj )
- {
- pObj->AddRef();
- }
-
- template< class T >
- static void Release( T *pObj )
- {
- pObj->Release();
- }
-};
-
-// This can be used if your objects use AddReference/ReleaseReference function names.
-class CRefCountAccessorLongName
-{
-public:
- template< class T >
- static void AddRef( T *pObj )
- {
- pObj->AddReference();
- }
-
- template< class T >
- static void Release( T *pObj )
- {
- pObj->ReleaseReference();
- }
-};
-
-
-//
-// CPlainAutoPtr
-// is a smart wrapper for a pointer on the stack that performs "delete" upon destruction.
-//
-// No reference counting is performed, copying is prohibited "s_p2.Attach( s_p1.Detach() )" should be used
-// for readability and ease of maintenance.
-//
-// Auto pointer supports an "arrow" operator for invoking methods on the pointee and a "dereference" operator
-// for getting a pointee reference.
-//
-// No automatic casting to bool/ptrtype is performed to avoid bugs and problems (read on "safe bool idiom"
-// if casting to bool or pointer happens to be useful).
-//
-// Test for validity with "IsValid", get the pointer with "Get".
-//
-template < typename T >
-class CPlainAutoPtr
-{
-public:
- explicit CPlainAutoPtr( T *p = NULL ) : m_p( p ) {}
- ~CPlainAutoPtr( void ) { Delete(); }
-
-public:
- void Delete( void ) { delete Detach(); }
-
-private: // Disallow copying, use Detach() instead to avoid ambiguity
- CPlainAutoPtr( CPlainAutoPtr const &x );
- CPlainAutoPtr & operator = ( CPlainAutoPtr const &x );
-
-public:
- void Attach( T *p ) { m_p = p; }
- T * Detach( void ) { T * p( m_p ); m_p = NULL; return p; }
-
-public:
- bool IsValid( void ) const { return m_p != NULL; }
- T * Get( void ) const { return m_p; }
- T * operator -> ( void ) const { return Get(); }
- T & operator * ( void ) const { return *Get(); }
-
-private:
- T * m_p;
-};
-
-//
-// CArrayAutoPtr
-// is a smart wrapper for an array pointer on the stack that performs "delete []" upon destruction.
-//
-// No reference counting is performed, copying is prohibited "s_p2.Attach( s_p1.Detach() )" should be used
-// for readability and ease of maintenance.
-//
-// Auto pointer supports an "indexing" operator for accessing array elements.
-//
-// No automatic casting to bool/ptrtype is performed to avoid bugs and problems (read on "safe bool idiom"
-// if casting to bool or pointer happens to be useful).
-//
-// Test for validity with "IsValid", get the array pointer with "Get".
-//
-template < typename T >
-class CArrayAutoPtr : public CPlainAutoPtr < T > // Warning: no polymorphic destructor (delete on base class will be a mistake)
-{
-public:
- explicit CArrayAutoPtr( T *p = NULL ) { this->Attach( p ); }
- ~CArrayAutoPtr( void ) { this->Delete(); }
-
-public:
- void Delete( void ) { delete [] CPlainAutoPtr < T >::Detach(); }
-
-public:
- T & operator [] ( int k ) const { return CPlainAutoPtr < T >::Get()[ k ]; }
-};
-
-
-// Smart pointers can be used to automatically free an object when nobody points
-// at it anymore. Things contained in smart pointers must implement AddRef and Release
-// functions. If those functions are private, then the class must make
-// CRefCountAccessor a friend.
-template<class T, class RefCountAccessor=CRefCountAccessor>
-class CSmartPtr
-{
-public:
- CSmartPtr();
- CSmartPtr( T *pObj );
- CSmartPtr( const CSmartPtr<T,RefCountAccessor> &other );
- ~CSmartPtr();
-
- T* operator=( T *pObj );
- void operator=( const CSmartPtr<T,RefCountAccessor> &other );
- const T* operator->() const;
- T* operator->();
- bool operator!() const;
- bool operator==( const T *pOther ) const;
- bool IsValid() const; // Tells if the pointer is valid.
- T* GetObject() const; // Get temporary object pointer, don't store it for later reuse!
- void MarkDeleted();
-
-private:
- T *m_pObj;
-};
-
-
-template< class T, class RefCountAccessor >
-inline CSmartPtr<T,RefCountAccessor>::CSmartPtr()
-{
- m_pObj = NULL;
-}
-
-template< class T, class RefCountAccessor >
-inline CSmartPtr<T,RefCountAccessor>::CSmartPtr( T *pObj )
-{
- m_pObj = NULL;
- *this = pObj;
-}
-
-template< class T, class RefCountAccessor >
-inline CSmartPtr<T,RefCountAccessor>::CSmartPtr( const CSmartPtr<T,RefCountAccessor> &other )
-{
- m_pObj = NULL;
- *this = other;
-}
-
-template< class T, class RefCountAccessor >
-inline CSmartPtr<T,RefCountAccessor>::~CSmartPtr()
-{
- if ( m_pObj )
- {
- RefCountAccessor::Release( m_pObj );
- }
-}
-
-template< class T, class RefCountAccessor >
-inline T* CSmartPtr<T,RefCountAccessor>::operator=( T *pObj )
-{
- if ( pObj == m_pObj )
- return pObj;
-
- if ( pObj )
- {
- RefCountAccessor::AddRef( pObj );
- }
- if ( m_pObj )
- {
- RefCountAccessor::Release( m_pObj );
- }
- m_pObj = pObj;
- return pObj;
-}
-
-template< class T, class RefCountAccessor >
-inline void CSmartPtr<T,RefCountAccessor>::MarkDeleted()
-{
- m_pObj = NULL;
-}
-
-template< class T, class RefCountAccessor >
-inline void CSmartPtr<T,RefCountAccessor>::operator=( const CSmartPtr<T,RefCountAccessor> &other )
-{
- *this = other.m_pObj;
-}
-
-template< class T, class RefCountAccessor >
-inline const T* CSmartPtr<T,RefCountAccessor>::operator->() const
-{
- return m_pObj;
-}
-
-template< class T, class RefCountAccessor >
-inline T* CSmartPtr<T,RefCountAccessor>::operator->()
-{
- return m_pObj;
-}
-
-template< class T, class RefCountAccessor >
-inline bool CSmartPtr<T,RefCountAccessor>::operator!() const
-{
- return !m_pObj;
-}
-
-template< class T, class RefCountAccessor >
-inline bool CSmartPtr<T,RefCountAccessor>::operator==( const T *pOther ) const
-{
- return m_pObj == pOther;
-}
-
-template< class T, class RefCountAccessor >
-inline bool CSmartPtr<T,RefCountAccessor>::IsValid() const
-{
- return m_pObj != NULL;
-}
-
-template< class T, class RefCountAccessor >
-inline T* CSmartPtr<T,RefCountAccessor>::GetObject() const
-{
- return m_pObj;
-}
-
-
-//
-// CAutoPushPop
-// allows you to set value of a variable upon construction and destruction.
-// Constructors:
-// CAutoPushPop x( myvar )
-// saves the value and restores upon destruction.
-// CAutoPushPop x( myvar, newvalue )
-// saves the value, assigns new value upon construction, restores saved value upon destruction.
-// CAutoPushPop x( myvar, newvalue, restorevalue )
-// assigns new value upon construction, assignes restorevalue upon destruction.
-//
-template < typename T >
-class CAutoPushPop
-{
-public:
- explicit CAutoPushPop( T& var ) : m_rVar( var ), m_valPop( var ) {}
- CAutoPushPop( T& var, T const &valPush ) : m_rVar( var ), m_valPop( var ) { m_rVar = valPush; }
- CAutoPushPop( T& var, T const &valPush, T const &valPop ) : m_rVar( var ), m_valPop( var ) { m_rVar = valPush; }
-
- ~CAutoPushPop() { m_rVar = m_valPop; }
-
-private: // forbid copying
- CAutoPushPop( CAutoPushPop const &x );
- CAutoPushPop & operator = ( CAutoPushPop const &x );
-
-public:
- T & Get() { return m_rVar; }
-
-private:
- T &m_rVar;
- T m_valPop;
-};
-
-
-#endif // SMARTPTR_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef SMARTPTR_H
+#define SMARTPTR_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+class CRefCountAccessor
+{
+public:
+ template< class T >
+ static void AddRef( T *pObj )
+ {
+ pObj->AddRef();
+ }
+
+ template< class T >
+ static void Release( T *pObj )
+ {
+ pObj->Release();
+ }
+};
+
+// This can be used if your objects use AddReference/ReleaseReference function names.
+class CRefCountAccessorLongName
+{
+public:
+ template< class T >
+ static void AddRef( T *pObj )
+ {
+ pObj->AddReference();
+ }
+
+ template< class T >
+ static void Release( T *pObj )
+ {
+ pObj->ReleaseReference();
+ }
+};
+
+
+//
+// CPlainAutoPtr
+// is a smart wrapper for a pointer on the stack that performs "delete" upon destruction.
+//
+// No reference counting is performed, copying is prohibited "s_p2.Attach( s_p1.Detach() )" should be used
+// for readability and ease of maintenance.
+//
+// Auto pointer supports an "arrow" operator for invoking methods on the pointee and a "dereference" operator
+// for getting a pointee reference.
+//
+// No automatic casting to bool/ptrtype is performed to avoid bugs and problems (read on "safe bool idiom"
+// if casting to bool or pointer happens to be useful).
+//
+// Test for validity with "IsValid", get the pointer with "Get".
+//
+template < typename T >
+class CPlainAutoPtr
+{
+public:
+ explicit CPlainAutoPtr( T *p = NULL ) : m_p( p ) {}
+ ~CPlainAutoPtr( void ) { Delete(); }
+
+public:
+ void Delete( void ) { delete Detach(); }
+
+private: // Disallow copying, use Detach() instead to avoid ambiguity
+ CPlainAutoPtr( CPlainAutoPtr const &x );
+ CPlainAutoPtr & operator = ( CPlainAutoPtr const &x );
+
+public:
+ void Attach( T *p ) { m_p = p; }
+ T * Detach( void ) { T * p( m_p ); m_p = NULL; return p; }
+
+public:
+ bool IsValid( void ) const { return m_p != NULL; }
+ T * Get( void ) const { return m_p; }
+ T * operator -> ( void ) const { return Get(); }
+ T & operator * ( void ) const { return *Get(); }
+
+private:
+ T * m_p;
+};
+
+//
+// CArrayAutoPtr
+// is a smart wrapper for an array pointer on the stack that performs "delete []" upon destruction.
+//
+// No reference counting is performed, copying is prohibited "s_p2.Attach( s_p1.Detach() )" should be used
+// for readability and ease of maintenance.
+//
+// Auto pointer supports an "indexing" operator for accessing array elements.
+//
+// No automatic casting to bool/ptrtype is performed to avoid bugs and problems (read on "safe bool idiom"
+// if casting to bool or pointer happens to be useful).
+//
+// Test for validity with "IsValid", get the array pointer with "Get".
+//
+template < typename T >
+class CArrayAutoPtr : public CPlainAutoPtr < T > // Warning: no polymorphic destructor (delete on base class will be a mistake)
+{
+public:
+ explicit CArrayAutoPtr( T *p = NULL ) { this->Attach( p ); }
+ ~CArrayAutoPtr( void ) { this->Delete(); }
+
+public:
+ void Delete( void ) { delete [] CPlainAutoPtr < T >::Detach(); }
+
+public:
+ T & operator [] ( int k ) const { return CPlainAutoPtr < T >::Get()[ k ]; }
+};
+
+
+// Smart pointers can be used to automatically free an object when nobody points
+// at it anymore. Things contained in smart pointers must implement AddRef and Release
+// functions. If those functions are private, then the class must make
+// CRefCountAccessor a friend.
+template<class T, class RefCountAccessor=CRefCountAccessor>
+class CSmartPtr
+{
+public:
+ CSmartPtr();
+ CSmartPtr( T *pObj );
+ CSmartPtr( const CSmartPtr<T,RefCountAccessor> &other );
+ ~CSmartPtr();
+
+ T* operator=( T *pObj );
+ void operator=( const CSmartPtr<T,RefCountAccessor> &other );
+ const T* operator->() const;
+ T* operator->();
+ bool operator!() const;
+ bool operator==( const T *pOther ) const;
+ bool IsValid() const; // Tells if the pointer is valid.
+ T* GetObject() const; // Get temporary object pointer, don't store it for later reuse!
+ void MarkDeleted();
+
+private:
+ T *m_pObj;
+};
+
+
+template< class T, class RefCountAccessor >
+inline CSmartPtr<T,RefCountAccessor>::CSmartPtr()
+{
+ m_pObj = NULL;
+}
+
+template< class T, class RefCountAccessor >
+inline CSmartPtr<T,RefCountAccessor>::CSmartPtr( T *pObj )
+{
+ m_pObj = NULL;
+ *this = pObj;
+}
+
+template< class T, class RefCountAccessor >
+inline CSmartPtr<T,RefCountAccessor>::CSmartPtr( const CSmartPtr<T,RefCountAccessor> &other )
+{
+ m_pObj = NULL;
+ *this = other;
+}
+
+template< class T, class RefCountAccessor >
+inline CSmartPtr<T,RefCountAccessor>::~CSmartPtr()
+{
+ if ( m_pObj )
+ {
+ RefCountAccessor::Release( m_pObj );
+ }
+}
+
+template< class T, class RefCountAccessor >
+inline T* CSmartPtr<T,RefCountAccessor>::operator=( T *pObj )
+{
+ if ( pObj == m_pObj )
+ return pObj;
+
+ if ( pObj )
+ {
+ RefCountAccessor::AddRef( pObj );
+ }
+ if ( m_pObj )
+ {
+ RefCountAccessor::Release( m_pObj );
+ }
+ m_pObj = pObj;
+ return pObj;
+}
+
+template< class T, class RefCountAccessor >
+inline void CSmartPtr<T,RefCountAccessor>::MarkDeleted()
+{
+ m_pObj = NULL;
+}
+
+template< class T, class RefCountAccessor >
+inline void CSmartPtr<T,RefCountAccessor>::operator=( const CSmartPtr<T,RefCountAccessor> &other )
+{
+ *this = other.m_pObj;
+}
+
+template< class T, class RefCountAccessor >
+inline const T* CSmartPtr<T,RefCountAccessor>::operator->() const
+{
+ return m_pObj;
+}
+
+template< class T, class RefCountAccessor >
+inline T* CSmartPtr<T,RefCountAccessor>::operator->()
+{
+ return m_pObj;
+}
+
+template< class T, class RefCountAccessor >
+inline bool CSmartPtr<T,RefCountAccessor>::operator!() const
+{
+ return !m_pObj;
+}
+
+template< class T, class RefCountAccessor >
+inline bool CSmartPtr<T,RefCountAccessor>::operator==( const T *pOther ) const
+{
+ return m_pObj == pOther;
+}
+
+template< class T, class RefCountAccessor >
+inline bool CSmartPtr<T,RefCountAccessor>::IsValid() const
+{
+ return m_pObj != NULL;
+}
+
+template< class T, class RefCountAccessor >
+inline T* CSmartPtr<T,RefCountAccessor>::GetObject() const
+{
+ return m_pObj;
+}
+
+
+//
+// CAutoPushPop
+// allows you to set value of a variable upon construction and destruction.
+// Constructors:
+// CAutoPushPop x( myvar )
+// saves the value and restores upon destruction.
+// CAutoPushPop x( myvar, newvalue )
+// saves the value, assigns new value upon construction, restores saved value upon destruction.
+// CAutoPushPop x( myvar, newvalue, restorevalue )
+// assigns new value upon construction, assignes restorevalue upon destruction.
+//
+template < typename T >
+class CAutoPushPop
+{
+public:
+ explicit CAutoPushPop( T& var ) : m_rVar( var ), m_valPop( var ) {}
+ CAutoPushPop( T& var, T const &valPush ) : m_rVar( var ), m_valPop( var ) { m_rVar = valPush; }
+ CAutoPushPop( T& var, T const &valPush, T const &valPop ) : m_rVar( var ), m_valPop( var ) { m_rVar = valPush; }
+
+ ~CAutoPushPop() { m_rVar = m_valPop; }
+
+private: // forbid copying
+ CAutoPushPop( CAutoPushPop const &x );
+ CAutoPushPop & operator = ( CAutoPushPop const &x );
+
+public:
+ T & Get() { return m_rVar; }
+
+private:
+ T &m_rVar;
+ T m_valPop;
+};
+
+
+#endif // SMARTPTR_H
diff --git a/mp/src/public/tier1/snappy-sinksource.h b/mp/src/public/tier1/snappy-sinksource.h
index c7c3df9d..430baeab 100644
--- a/mp/src/public/tier1/snappy-sinksource.h
+++ b/mp/src/public/tier1/snappy-sinksource.h
@@ -1,136 +1,136 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef UTIL_SNAPPY_SNAPPY_SINKSOURCE_H_
-#define UTIL_SNAPPY_SNAPPY_SINKSOURCE_H_
-
-#include <stddef.h>
-
-
-namespace snappy {
-
-// A Sink is an interface that consumes a sequence of bytes.
-class Sink {
- public:
- Sink() { }
- virtual ~Sink();
-
- // Append "bytes[0,n-1]" to this.
- virtual void Append(const char* bytes, size_t n) = 0;
-
- // Returns a writable buffer of the specified length for appending.
- // May return a pointer to the caller-owned scratch buffer which
- // must have at least the indicated length. The returned buffer is
- // only valid until the next operation on this Sink.
- //
- // After writing at most "length" bytes, call Append() with the
- // pointer returned from this function and the number of bytes
- // written. Many Append() implementations will avoid copying
- // bytes if this function returned an internal buffer.
- //
- // If a non-scratch buffer is returned, the caller may only pass a
- // prefix of it to Append(). That is, it is not correct to pass an
- // interior pointer of the returned array to Append().
- //
- // The default implementation always returns the scratch buffer.
- virtual char* GetAppendBuffer(size_t length, char* scratch);
-
- private:
- // No copying
- Sink(const Sink&);
- void operator=(const Sink&);
-};
-
-// A Source is an interface that yields a sequence of bytes
-class Source {
- public:
- Source() { }
- virtual ~Source();
-
- // Return the number of bytes left to read from the source
- virtual size_t Available() const = 0;
-
- // Peek at the next flat region of the source. Does not reposition
- // the source. The returned region is empty iff Available()==0.
- //
- // Returns a pointer to the beginning of the region and store its
- // length in *len.
- //
- // The returned region is valid until the next call to Skip() or
- // until this object is destroyed, whichever occurs first.
- //
- // The returned region may be larger than Available() (for example
- // if this ByteSource is a view on a substring of a larger source).
- // The caller is responsible for ensuring that it only reads the
- // Available() bytes.
- virtual const char* Peek(size_t* len) = 0;
-
- // Skip the next n bytes. Invalidates any buffer returned by
- // a previous call to Peek().
- // REQUIRES: Available() >= n
- virtual void Skip(size_t n) = 0;
-
- private:
- // No copying
- Source(const Source&);
- void operator=(const Source&);
-};
-
-// A Source implementation that yields the contents of a flat array
-class ByteArraySource : public Source {
- public:
- ByteArraySource(const char* p, size_t n) : ptr_(p), left_(n) { }
- virtual ~ByteArraySource();
- virtual size_t Available() const;
- virtual const char* Peek(size_t* len);
- virtual void Skip(size_t n);
- private:
- const char* ptr_;
- size_t left_;
-};
-
-// A Sink implementation that writes to a flat array without any bound checks.
-class UncheckedByteArraySink : public Sink {
- public:
- explicit UncheckedByteArraySink(char* dest) : dest_(dest) { }
- virtual ~UncheckedByteArraySink();
- virtual void Append(const char* data, size_t n);
- virtual char* GetAppendBuffer(size_t len, char* scratch);
-
- // Return the current output pointer so that a caller can see how
- // many bytes were produced.
- // Note: this is not a Sink method.
- char* CurrentDestination() const { return dest_; }
- private:
- char* dest_;
-};
-
-
-}
-
-#endif // UTIL_SNAPPY_SNAPPY_SINKSOURCE_H_
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef UTIL_SNAPPY_SNAPPY_SINKSOURCE_H_
+#define UTIL_SNAPPY_SNAPPY_SINKSOURCE_H_
+
+#include <stddef.h>
+
+
+namespace snappy {
+
+// A Sink is an interface that consumes a sequence of bytes.
+class Sink {
+ public:
+ Sink() { }
+ virtual ~Sink();
+
+ // Append "bytes[0,n-1]" to this.
+ virtual void Append(const char* bytes, size_t n) = 0;
+
+ // Returns a writable buffer of the specified length for appending.
+ // May return a pointer to the caller-owned scratch buffer which
+ // must have at least the indicated length. The returned buffer is
+ // only valid until the next operation on this Sink.
+ //
+ // After writing at most "length" bytes, call Append() with the
+ // pointer returned from this function and the number of bytes
+ // written. Many Append() implementations will avoid copying
+ // bytes if this function returned an internal buffer.
+ //
+ // If a non-scratch buffer is returned, the caller may only pass a
+ // prefix of it to Append(). That is, it is not correct to pass an
+ // interior pointer of the returned array to Append().
+ //
+ // The default implementation always returns the scratch buffer.
+ virtual char* GetAppendBuffer(size_t length, char* scratch);
+
+ private:
+ // No copying
+ Sink(const Sink&);
+ void operator=(const Sink&);
+};
+
+// A Source is an interface that yields a sequence of bytes
+class Source {
+ public:
+ Source() { }
+ virtual ~Source();
+
+ // Return the number of bytes left to read from the source
+ virtual size_t Available() const = 0;
+
+ // Peek at the next flat region of the source. Does not reposition
+ // the source. The returned region is empty iff Available()==0.
+ //
+ // Returns a pointer to the beginning of the region and store its
+ // length in *len.
+ //
+ // The returned region is valid until the next call to Skip() or
+ // until this object is destroyed, whichever occurs first.
+ //
+ // The returned region may be larger than Available() (for example
+ // if this ByteSource is a view on a substring of a larger source).
+ // The caller is responsible for ensuring that it only reads the
+ // Available() bytes.
+ virtual const char* Peek(size_t* len) = 0;
+
+ // Skip the next n bytes. Invalidates any buffer returned by
+ // a previous call to Peek().
+ // REQUIRES: Available() >= n
+ virtual void Skip(size_t n) = 0;
+
+ private:
+ // No copying
+ Source(const Source&);
+ void operator=(const Source&);
+};
+
+// A Source implementation that yields the contents of a flat array
+class ByteArraySource : public Source {
+ public:
+ ByteArraySource(const char* p, size_t n) : ptr_(p), left_(n) { }
+ virtual ~ByteArraySource();
+ virtual size_t Available() const;
+ virtual const char* Peek(size_t* len);
+ virtual void Skip(size_t n);
+ private:
+ const char* ptr_;
+ size_t left_;
+};
+
+// A Sink implementation that writes to a flat array without any bound checks.
+class UncheckedByteArraySink : public Sink {
+ public:
+ explicit UncheckedByteArraySink(char* dest) : dest_(dest) { }
+ virtual ~UncheckedByteArraySink();
+ virtual void Append(const char* data, size_t n);
+ virtual char* GetAppendBuffer(size_t len, char* scratch);
+
+ // Return the current output pointer so that a caller can see how
+ // many bytes were produced.
+ // Note: this is not a Sink method.
+ char* CurrentDestination() const { return dest_; }
+ private:
+ char* dest_;
+};
+
+
+}
+
+#endif // UTIL_SNAPPY_SNAPPY_SINKSOURCE_H_
diff --git a/mp/src/public/tier1/snappy.h b/mp/src/public/tier1/snappy.h
index 1c9ad6bf..c5eeea01 100644
--- a/mp/src/public/tier1/snappy.h
+++ b/mp/src/public/tier1/snappy.h
@@ -1,172 +1,172 @@
-// Copyright 2005 and onwards Google Inc.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// A light-weight compression algorithm. It is designed for speed of
-// compression and decompression, rather than for the utmost in space
-// savings.
-//
-// For getting better compression ratios when you are compressing data
-// with long repeated sequences or compressing data that is similar to
-// other data, while still compressing fast, you might look at first
-// using BMDiff and then compressing the output of BMDiff with
-// Snappy.
-
-#ifndef UTIL_SNAPPY_SNAPPY_H__
-#define UTIL_SNAPPY_SNAPPY_H__
-
-// [email protected]: Added this kludge. We really need to stop #defining this in our code.
-#undef min
-#undef max
-
-#include <stddef.h>
-#ifdef _WIN32
-#pragma warning(disable:4530) // warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
-#endif //_WIN32
-#include <string>
-
-#include "tier0/platform.h"
-
-#define SNAPPY_MAJOR 1
-#define SNAPPY_MINOR 0
-#define SNAPPY_PATCHLEVEL 3
-#define SNAPPY_VERSION \
- ((SNAPPY_MAJOR << 16) | (SNAPPY_MINOR << 8) | SNAPPY_PATCHLEVEL)
-
-#define SNAPPY_DISALLOW_COPY_AND_ASSIGN(TypeName) \
- TypeName(const TypeName&); \
- void operator=(const TypeName&)
-
-namespace snappy {
- class Source;
- class Sink;
-
- // ------------------------------------------------------------------------
- // Generic compression/decompression routines.
- // ------------------------------------------------------------------------
-
- // Compress the bytes read from "*source" and append to "*sink". Return the
- // number of bytes written.
- size_t Compress(Source* source, Sink* sink);
-
- bool GetUncompressedLength(Source* source, uint32* result);
-
- // ------------------------------------------------------------------------
- // Higher-level string based routines (should be sufficient for most users)
- // ------------------------------------------------------------------------
-
- // Sets "*output" to the compressed version of "input[0,input_length-1]".
- // Original contents of *output are lost.
- //
- // REQUIRES: "input[]" is not an alias of "*output".
- size_t Compress(const char* input, size_t input_length, std::string* output);
-
- // Decompresses "compressed[0,compressed_length-1]" to "*uncompressed".
- // Original contents of "*uncompressed" are lost.
- //
- // REQUIRES: "compressed[]" is not an alias of "*uncompressed".
- //
- // returns false if the message is corrupted and could not be decompressed
- bool Uncompress(const char* compressed, size_t compressed_length,
- std::string* uncompressed);
-
-
- // ------------------------------------------------------------------------
- // Lower-level character array based routines. May be useful for
- // efficiency reasons in certain circumstances.
- // ------------------------------------------------------------------------
-
- // REQUIRES: "compressed" must point to an area of memory that is at
- // least "MaxCompressedLength(input_length)" bytes in length.
- //
- // Takes the data stored in "input[0..input_length]" and stores
- // it in the array pointed to by "compressed".
- //
- // "*compressed_length" is set to the length of the compressed output.
- //
- // Example:
- // char* output = new char[snappy::MaxCompressedLength(input_length)];
- // size_t output_length;
- // RawCompress(input, input_length, output, &output_length);
- // ... Process(output, output_length) ...
- // delete [] output;
- void RawCompress(const char* input,
- size_t input_length,
- char* compressed,
- size_t* compressed_length);
-
- // Given data in "compressed[0..compressed_length-1]" generated by
- // calling the Snappy::Compress routine, this routine
- // stores the uncompressed data to
- // uncompressed[0..GetUncompressedLength(compressed)-1]
- // returns false if the message is corrupted and could not be decrypted
- bool RawUncompress(const char* compressed, size_t compressed_length,
- char* uncompressed);
-
- // Given data from the byte source 'compressed' generated by calling
- // the Snappy::Compress routine, this routine stores the uncompressed
- // data to
- // uncompressed[0..GetUncompressedLength(compressed,compressed_length)-1]
- // returns false if the message is corrupted and could not be decrypted
- bool RawUncompress(Source* compressed, char* uncompressed);
-
- // Returns the maximal size of the compressed representation of
- // input data that is "source_bytes" bytes in length;
- size_t MaxCompressedLength(size_t source_bytes);
-
- // REQUIRES: "compressed[]" was produced by RawCompress() or Compress()
- // Returns true and stores the length of the uncompressed data in
- // *result normally. Returns false on parsing error.
- // This operation takes O(1) time.
- bool GetUncompressedLength(const char* compressed, size_t compressed_length,
- size_t* result);
-
- // Returns true iff the contents of "compressed[]" can be uncompressed
- // successfully. Does not return the uncompressed data. Takes
- // time proportional to compressed_length, but is usually at least
- // a factor of four faster than actual decompression.
- bool IsValidCompressedBuffer(const char* compressed,
- size_t compressed_length);
-
- // *** DO NOT CHANGE THE VALUE OF kBlockSize ***
- //
- // New Compression code chops up the input into blocks of at most
- // the following size. This ensures that back-references in the
- // output never cross kBlockSize block boundaries. This can be
- // helpful in implementing blocked decompression. However the
- // decompression code should not rely on this guarantee since older
- // compression code may not obey it.
- static const int kBlockLog = 15;
- static const int kBlockSize = 1 << kBlockLog;
-
- static const int kMaxHashTableBits = 14;
- static const int kMaxHashTableSize = 1 << kMaxHashTableBits;
-
-} // end namespace snappy
-
-
-#endif // UTIL_SNAPPY_SNAPPY_H__
+// Copyright 2005 and onwards Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// A light-weight compression algorithm. It is designed for speed of
+// compression and decompression, rather than for the utmost in space
+// savings.
+//
+// For getting better compression ratios when you are compressing data
+// with long repeated sequences or compressing data that is similar to
+// other data, while still compressing fast, you might look at first
+// using BMDiff and then compressing the output of BMDiff with
+// Snappy.
+
+#ifndef UTIL_SNAPPY_SNAPPY_H__
+#define UTIL_SNAPPY_SNAPPY_H__
+
+// [email protected]: Added this kludge. We really need to stop #defining this in our code.
+#undef min
+#undef max
+
+#include <stddef.h>
+#ifdef _WIN32
+#pragma warning(disable:4530) // warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
+#endif //_WIN32
+#include <string>
+
+#include "tier0/platform.h"
+
+#define SNAPPY_MAJOR 1
+#define SNAPPY_MINOR 0
+#define SNAPPY_PATCHLEVEL 3
+#define SNAPPY_VERSION \
+ ((SNAPPY_MAJOR << 16) | (SNAPPY_MINOR << 8) | SNAPPY_PATCHLEVEL)
+
+#define SNAPPY_DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&); \
+ void operator=(const TypeName&)
+
+namespace snappy {
+ class Source;
+ class Sink;
+
+ // ------------------------------------------------------------------------
+ // Generic compression/decompression routines.
+ // ------------------------------------------------------------------------
+
+ // Compress the bytes read from "*source" and append to "*sink". Return the
+ // number of bytes written.
+ size_t Compress(Source* source, Sink* sink);
+
+ bool GetUncompressedLength(Source* source, uint32* result);
+
+ // ------------------------------------------------------------------------
+ // Higher-level string based routines (should be sufficient for most users)
+ // ------------------------------------------------------------------------
+
+ // Sets "*output" to the compressed version of "input[0,input_length-1]".
+ // Original contents of *output are lost.
+ //
+ // REQUIRES: "input[]" is not an alias of "*output".
+ size_t Compress(const char* input, size_t input_length, std::string* output);
+
+ // Decompresses "compressed[0,compressed_length-1]" to "*uncompressed".
+ // Original contents of "*uncompressed" are lost.
+ //
+ // REQUIRES: "compressed[]" is not an alias of "*uncompressed".
+ //
+ // returns false if the message is corrupted and could not be decompressed
+ bool Uncompress(const char* compressed, size_t compressed_length,
+ std::string* uncompressed);
+
+
+ // ------------------------------------------------------------------------
+ // Lower-level character array based routines. May be useful for
+ // efficiency reasons in certain circumstances.
+ // ------------------------------------------------------------------------
+
+ // REQUIRES: "compressed" must point to an area of memory that is at
+ // least "MaxCompressedLength(input_length)" bytes in length.
+ //
+ // Takes the data stored in "input[0..input_length]" and stores
+ // it in the array pointed to by "compressed".
+ //
+ // "*compressed_length" is set to the length of the compressed output.
+ //
+ // Example:
+ // char* output = new char[snappy::MaxCompressedLength(input_length)];
+ // size_t output_length;
+ // RawCompress(input, input_length, output, &output_length);
+ // ... Process(output, output_length) ...
+ // delete [] output;
+ void RawCompress(const char* input,
+ size_t input_length,
+ char* compressed,
+ size_t* compressed_length);
+
+ // Given data in "compressed[0..compressed_length-1]" generated by
+ // calling the Snappy::Compress routine, this routine
+ // stores the uncompressed data to
+ // uncompressed[0..GetUncompressedLength(compressed)-1]
+ // returns false if the message is corrupted and could not be decrypted
+ bool RawUncompress(const char* compressed, size_t compressed_length,
+ char* uncompressed);
+
+ // Given data from the byte source 'compressed' generated by calling
+ // the Snappy::Compress routine, this routine stores the uncompressed
+ // data to
+ // uncompressed[0..GetUncompressedLength(compressed,compressed_length)-1]
+ // returns false if the message is corrupted and could not be decrypted
+ bool RawUncompress(Source* compressed, char* uncompressed);
+
+ // Returns the maximal size of the compressed representation of
+ // input data that is "source_bytes" bytes in length;
+ size_t MaxCompressedLength(size_t source_bytes);
+
+ // REQUIRES: "compressed[]" was produced by RawCompress() or Compress()
+ // Returns true and stores the length of the uncompressed data in
+ // *result normally. Returns false on parsing error.
+ // This operation takes O(1) time.
+ bool GetUncompressedLength(const char* compressed, size_t compressed_length,
+ size_t* result);
+
+ // Returns true iff the contents of "compressed[]" can be uncompressed
+ // successfully. Does not return the uncompressed data. Takes
+ // time proportional to compressed_length, but is usually at least
+ // a factor of four faster than actual decompression.
+ bool IsValidCompressedBuffer(const char* compressed,
+ size_t compressed_length);
+
+ // *** DO NOT CHANGE THE VALUE OF kBlockSize ***
+ //
+ // New Compression code chops up the input into blocks of at most
+ // the following size. This ensures that back-references in the
+ // output never cross kBlockSize block boundaries. This can be
+ // helpful in implementing blocked decompression. However the
+ // decompression code should not rely on this guarantee since older
+ // compression code may not obey it.
+ static const int kBlockLog = 15;
+ static const int kBlockSize = 1 << kBlockLog;
+
+ static const int kMaxHashTableBits = 14;
+ static const int kMaxHashTableSize = 1 << kMaxHashTableBits;
+
+} // end namespace snappy
+
+
+#endif // UTIL_SNAPPY_SNAPPY_H__
diff --git a/mp/src/public/tier1/sparsematrix.h b/mp/src/public/tier1/sparsematrix.h
index e1f4b770..d882e5f9 100644
--- a/mp/src/public/tier1/sparsematrix.h
+++ b/mp/src/public/tier1/sparsematrix.h
@@ -1,123 +1,123 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// A class allowing storage of a sparse NxN matirx as an array of sparse rows
-//===========================================================================//
-
-#ifndef SPARSEMATRIX_H
-#define SPARSEMATRIX_H
-
-#include "tier1/utlvector.h"
-
-/// CSparseMatrix is a matrix which compresses each row individually, not storing the zeros. NOte,
-/// that while you can randomly set any element in a CSparseMatrix, you really want to do it top to
-/// bottom or you will have bad perf as data is moved around to insert new elements.
-class CSparseMatrix
-{
-public:
- struct NonZeroValueDescriptor_t
- {
- int m_nColumnNumber;
- float m_flValue;
- };
-
- struct RowDescriptor_t
- {
- int m_nNonZeroCount; // number of non-zero elements in the row
- int m_nDataIndex; // index of NonZeroValueDescriptor_t for the first non-zero value
- };
-
- int m_nNumRows;
- int m_nNumCols;
- CUtlVector<RowDescriptor_t> m_rowDescriptors;
- CUtlVector<NonZeroValueDescriptor_t> m_entries;
- int m_nHighestRowAppendedTo;
-
- void AdjustAllRowIndicesAfter( int nStartRow, int nDelta );
-public:
- FORCEINLINE float Element( int nRow, int nCol ) const;
- void SetElement( int nRow, int nCol, float flValue );
- void SetDimensions( int nNumRows, int nNumCols );
- void AppendElement( int nRow, int nCol, float flValue );
- void FinishedAppending( void );
-
- FORCEINLINE int Height( void ) const { return m_nNumRows; }
- FORCEINLINE int Width( void ) const { return m_nNumCols; }
-
-};
-
-
-
-FORCEINLINE float CSparseMatrix::Element( int nRow, int nCol ) const
-{
- Assert( nCol < m_nNumCols );
- int nCount = m_rowDescriptors[nRow].m_nNonZeroCount;
- if ( nCount )
- {
- NonZeroValueDescriptor_t const *pValue = &(m_entries[m_rowDescriptors[nRow].m_nDataIndex]);
- do
- {
- int nIdx = pValue->m_nColumnNumber;
- if ( nIdx == nCol )
- {
- return pValue->m_flValue;
- }
- if ( nIdx > nCol )
- {
- break;
- }
- pValue++;
- } while( --nCount );
- }
- return 0;
-}
-
-
-
-// type-specific overrides of matrixmath template for special case sparse routines
-
-namespace MatrixMath
-{
- /// sparse * dense matrix x matrix multiplication
- template<class BTYPE, class OUTTYPE>
- void MatrixMultiply( CSparseMatrix const &matA, BTYPE const &matB, OUTTYPE *pMatrixOut )
- {
- Assert( matA.Width() == matB.Height() );
- pMatrixOut->SetDimensions( matA.Height(), matB.Width() );
- for( int i = 0; i < matA.Height(); i++ )
- {
- for( int j = 0; j < matB.Width(); j++ )
- {
- // compute inner product efficiently because of sparsity
- int nCnt = matA.m_rowDescriptors[i].m_nNonZeroCount;
- int nDataIdx = matA.m_rowDescriptors[i].m_nDataIndex;
- float flDot = 0.0;
- for( int nIdx = 0; nIdx < nCnt; nIdx++ )
- {
- float flAValue = matA.m_entries[nIdx + nDataIdx].m_flValue;
- int nCol = matA.m_entries[nIdx + nDataIdx].m_nColumnNumber;
- flDot += flAValue * matB.Element( nCol, j );
- }
- pMatrixOut->SetElement( i, j, flDot );
- }
- }
- }
-
- FORCEINLINE void AppendElement( CSparseMatrix &matrix, int nRow, int nCol, float flValue )
- {
- matrix.AppendElement( nRow, nCol, flValue ); // default implementation
- }
-
- FORCEINLINE void FinishedAppending( CSparseMatrix &matrix )
- {
- matrix.FinishedAppending();
- }
-
-};
-
-
-
-
-
-#endif // SPARSEMATRIX_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// A class allowing storage of a sparse NxN matirx as an array of sparse rows
+//===========================================================================//
+
+#ifndef SPARSEMATRIX_H
+#define SPARSEMATRIX_H
+
+#include "tier1/utlvector.h"
+
+/// CSparseMatrix is a matrix which compresses each row individually, not storing the zeros. NOte,
+/// that while you can randomly set any element in a CSparseMatrix, you really want to do it top to
+/// bottom or you will have bad perf as data is moved around to insert new elements.
+class CSparseMatrix
+{
+public:
+ struct NonZeroValueDescriptor_t
+ {
+ int m_nColumnNumber;
+ float m_flValue;
+ };
+
+ struct RowDescriptor_t
+ {
+ int m_nNonZeroCount; // number of non-zero elements in the row
+ int m_nDataIndex; // index of NonZeroValueDescriptor_t for the first non-zero value
+ };
+
+ int m_nNumRows;
+ int m_nNumCols;
+ CUtlVector<RowDescriptor_t> m_rowDescriptors;
+ CUtlVector<NonZeroValueDescriptor_t> m_entries;
+ int m_nHighestRowAppendedTo;
+
+ void AdjustAllRowIndicesAfter( int nStartRow, int nDelta );
+public:
+ FORCEINLINE float Element( int nRow, int nCol ) const;
+ void SetElement( int nRow, int nCol, float flValue );
+ void SetDimensions( int nNumRows, int nNumCols );
+ void AppendElement( int nRow, int nCol, float flValue );
+ void FinishedAppending( void );
+
+ FORCEINLINE int Height( void ) const { return m_nNumRows; }
+ FORCEINLINE int Width( void ) const { return m_nNumCols; }
+
+};
+
+
+
+FORCEINLINE float CSparseMatrix::Element( int nRow, int nCol ) const
+{
+ Assert( nCol < m_nNumCols );
+ int nCount = m_rowDescriptors[nRow].m_nNonZeroCount;
+ if ( nCount )
+ {
+ NonZeroValueDescriptor_t const *pValue = &(m_entries[m_rowDescriptors[nRow].m_nDataIndex]);
+ do
+ {
+ int nIdx = pValue->m_nColumnNumber;
+ if ( nIdx == nCol )
+ {
+ return pValue->m_flValue;
+ }
+ if ( nIdx > nCol )
+ {
+ break;
+ }
+ pValue++;
+ } while( --nCount );
+ }
+ return 0;
+}
+
+
+
+// type-specific overrides of matrixmath template for special case sparse routines
+
+namespace MatrixMath
+{
+ /// sparse * dense matrix x matrix multiplication
+ template<class BTYPE, class OUTTYPE>
+ void MatrixMultiply( CSparseMatrix const &matA, BTYPE const &matB, OUTTYPE *pMatrixOut )
+ {
+ Assert( matA.Width() == matB.Height() );
+ pMatrixOut->SetDimensions( matA.Height(), matB.Width() );
+ for( int i = 0; i < matA.Height(); i++ )
+ {
+ for( int j = 0; j < matB.Width(); j++ )
+ {
+ // compute inner product efficiently because of sparsity
+ int nCnt = matA.m_rowDescriptors[i].m_nNonZeroCount;
+ int nDataIdx = matA.m_rowDescriptors[i].m_nDataIndex;
+ float flDot = 0.0;
+ for( int nIdx = 0; nIdx < nCnt; nIdx++ )
+ {
+ float flAValue = matA.m_entries[nIdx + nDataIdx].m_flValue;
+ int nCol = matA.m_entries[nIdx + nDataIdx].m_nColumnNumber;
+ flDot += flAValue * matB.Element( nCol, j );
+ }
+ pMatrixOut->SetElement( i, j, flDot );
+ }
+ }
+ }
+
+ FORCEINLINE void AppendElement( CSparseMatrix &matrix, int nRow, int nCol, float flValue )
+ {
+ matrix.AppendElement( nRow, nCol, flValue ); // default implementation
+ }
+
+ FORCEINLINE void FinishedAppending( CSparseMatrix &matrix )
+ {
+ matrix.FinishedAppending();
+ }
+
+};
+
+
+
+
+
+#endif // SPARSEMATRIX_H
diff --git a/mp/src/public/tier1/stringpool.h b/mp/src/public/tier1/stringpool.h
index bfb0872d..6b1dfaef 100644
--- a/mp/src/public/tier1/stringpool.h
+++ b/mp/src/public/tier1/stringpool.h
@@ -1,91 +1,91 @@
-//========= Copyright 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"
-
-//-----------------------------------------------------------------------------
-// Purpose: Allocates memory for strings, checking for duplicates first,
-// reusing exising strings if duplicate found.
-//-----------------------------------------------------------------------------
-
-class CStringPool
-{
-public:
- CStringPool();
- ~CStringPool();
-
- unsigned int Count() const;
-
- const char * Allocate( 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;
-
-public:
- CCountedStringPool();
- 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();
-};
-
-#endif // STRINGPOOL_H
+//========= Copyright 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"
+
+//-----------------------------------------------------------------------------
+// Purpose: Allocates memory for strings, checking for duplicates first,
+// reusing exising strings if duplicate found.
+//-----------------------------------------------------------------------------
+
+class CStringPool
+{
+public:
+ CStringPool();
+ ~CStringPool();
+
+ unsigned int Count() const;
+
+ const char * Allocate( 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;
+
+public:
+ CCountedStringPool();
+ 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();
+};
+
+#endif // STRINGPOOL_H
diff --git a/mp/src/public/tier1/strtools.h b/mp/src/public/tier1/strtools.h
index 6089a8f4..93d0af6d 100644
--- a/mp/src/public/tier1/strtools.h
+++ b/mp/src/public/tier1/strtools.h
@@ -1,847 +1,847 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//
-//===========================================================================//
-
-#ifndef TIER1_STRTOOLS_H
-#define TIER1_STRTOOLS_H
-
-#include "tier0/platform.h"
-
-#include <ctype.h>
-#include <stdarg.h>
-#ifdef _WIN32
-#pragma once
-#elif POSIX
-#include <wchar.h>
-#include <math.h>
-#include <wctype.h>
-#endif
-
-#include <string.h>
-#include <stdlib.h>
-
-#ifdef _WIN64
-#define str_size unsigned int
-#else
-#define str_size size_t
-#endif
-
-template< class T, class I > class CUtlMemory;
-template< class T, class A > class CUtlVector;
-
-
-//-----------------------------------------------------------------------------
-// Portable versions of standard string functions
-//-----------------------------------------------------------------------------
-void _V_memset ( const char* file, int line, void *dest, int fill, int count );
-void _V_memcpy ( const char* file, int line, void *dest, const void *src, int count );
-void _V_memmove ( const char* file, int line, void *dest, const void *src, int count );
-int _V_memcmp ( const char* file, int line, const void *m1, const void *m2, int count );
-int _V_strlen ( const char* file, int line, const char *str );
-void _V_strcpy ( const char* file, int line, char *dest, const char *src );
-char* _V_strrchr ( const char* file, int line, const char *s, char c );
-int _V_strcmp ( const char* file, int line, const char *s1, const char *s2 );
-int _V_wcscmp ( const char* file, int line, const wchar_t *s1, const wchar_t *s2 );
-char* _V_strstr ( const char* file, int line, const char *s1, const char *search );
-int _V_wcslen ( const char* file, int line, 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);
-
-// ASCII-optimized functions which fall back to CRT only when necessary
-char *V_strupr( char *start );
-char *V_strlower( char *start );
-int V_stricmp( const char *s1, const char *s2 );
-int V_strncmp( const char *s1, const char *s2, int count );
-int V_strnicmp( const char *s1, const char *s2, int n );
-
-#ifdef POSIX
-
-inline char *strupr( char *start )
-{
- return V_strupr( start );
-}
-
-inline char *strlwr( char *start )
-{
- return V_strlower( 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
-
-
-#ifdef _DEBUG
-
-#define V_memset(dest, fill, count) _V_memset (__FILE__, __LINE__, (dest), (fill), (count))
-#define V_memcpy(dest, src, count) _V_memcpy (__FILE__, __LINE__, (dest), (src), (count))
-#define V_memmove(dest, src, count) _V_memmove (__FILE__, __LINE__, (dest), (src), (count))
-#define V_memcmp(m1, m2, count) _V_memcmp (__FILE__, __LINE__, (m1), (m2), (count))
-#define V_strlen(str) _V_strlen (__FILE__, __LINE__, (str))
-#define V_strcpy(dest, src) _V_strcpy (__FILE__, __LINE__, (dest), (src))
-#define V_strrchr(s, c) _V_strrchr (__FILE__, __LINE__, (s), (c))
-#define V_strcmp(s1, s2) _V_strcmp (__FILE__, __LINE__, (s1), (s2))
-#define V_wcscmp(s1, s2) _V_wcscmp (__FILE__, __LINE__, (s1), (s2))
-#define V_strstr(s1, search ) _V_strstr (__FILE__, __LINE__, (s1), (search) )
-#define V_wcslen(pwch) _V_wcslen (__FILE__, __LINE__, (pwch))
-#define V_wcslower(start) _V_wcslower (__FILE__, __LINE__, (start))
-#define V_wcsupr(start) _V_wcsupr (__FILE__, __LINE__, (start))
-
-#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 char* V_strstr( const char *s1, const char *search ) { return (char*)strstr( s1, search ); }
-inline wchar_t* V_wcslower (wchar_t *start) { return _wcslwr( start ); }
-inline wchar_t* V_wcsupr (wchar_t *start) { return _wcsupr( start ); }
-
-#endif
-
-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 );
-inline int V_strcasecmp (const char *s1, const char *s2) { return V_stricmp(s1, s2); }
-inline int V_strncasecmp (const char *s1, const char *s2, int n) { return V_strnicmp(s1, s2, n); }
-void V_qsort_s( void *base, size_t num, size_t width, int ( __cdecl *compare )(void *, const void *,
-const void *), void *context );
-
-
-// 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 );
-
-// this is locale-unaware and therefore faster version of standard isdigit()
-// It also avoids sign-extension errors.
-inline bool V_isdigit( char c )
-{
- return c >= '0' && c <= '9';
-}
-
-// The islower/isdigit/etc. functions all expect a parameter that is either
-// 0-0xFF or EOF. It is easy to violate this constraint simply by passing
-// 'char' to these functions instead of unsigned char.
-// The V_ functions handle the char/unsigned char mismatch by taking a
-// char parameter and casting it to unsigned char so that chars with the
-// sign bit set will be zero extended instead of sign extended.
-// Not that EOF cannot be passed to these functions.
-//
-// These functions could also be used for optimizations if locale
-// considerations make some of the CRT functions slow.
-//#undef isdigit // In case this is implemented as a macro
-//#define isdigit use_V_isdigit_instead_of_isdigit
-inline bool V_isalpha(char c) { return isalpha( (unsigned char)c ) != 0; }
-//#undef isalpha
-//#define isalpha use_V_isalpha_instead_of_isalpha
-inline bool V_isalnum(char c) { return isalnum( (unsigned char)c ) != 0; }
-//#undef isalnum
-//#define isalnum use_V_isalnum_instead_of_isalnum
-inline bool V_isprint(char c) { return isprint( (unsigned char)c ) != 0; }
-//#undef isprint
-//#define isprint use_V_isprint_instead_of_isprint
-inline bool V_isxdigit(char c) { return isxdigit( (unsigned char)c ) != 0; }
-//#undef isxdigit
-//#define isxdigit use_V_isxdigit_instead_of_isxdigit
-inline bool V_ispunct(char c) { return ispunct( (unsigned char)c ) != 0; }
-//#undef ispunct
-//#define ispunct use_V_ispunct_instead_of_ispunct
-inline bool V_isgraph(char c) { return isgraph( (unsigned char)c ) != 0; }
-//#undef isgraph
-//#define isgraph use_V_isgraph_instead_of_isgraph
-inline bool V_isupper(char c) { return isupper( (unsigned char)c ) != 0; }
-//#undef isupper
-//#define isupper use_V_isupper_instead_of_isupper
-inline bool V_islower(char c) { return islower( (unsigned char)c ) != 0; }
-//#undef islower
-//#define islower use_V_islower_instead_of_islower
-inline bool V_iscntrl(char c) { return iscntrl( (unsigned char)c ) != 0; }
-//#undef iscntrl
-//#define iscntrl use_V_iscntrl_instead_of_iscntrl
-inline bool V_isspace(char c) { return isspace( (unsigned char)c ) != 0; }
-//#undef isspace
-//#define isspace use_V_isspace_instead_of_isspace
-
-
-// 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( OUT_Z_CAP(maxLenInChars) char *pDest, const char *pSrc, int maxLenInChars );
-
-// Ultimate safe strcpy function, for arrays only -- buffer size is inferred by the compiler
-template <size_t maxLenInChars> void V_strcpy_safe( OUT_Z_ARRAY char (&pDest)[maxLenInChars], const char *pSrc )
-{
- V_strncpy( pDest, pSrc, (int)maxLenInChars );
-}
-
-void V_wcsncpy( OUT_Z_BYTECAP(maxLenInBytes) wchar_t *pDest, wchar_t const *pSrc, int maxLenInBytes );
-template <size_t maxLenInChars> void V_wcscpy_safe( OUT_Z_ARRAY wchar_t (&pDest)[maxLenInChars], wchar_t const *pSrc )
-{
- V_wcsncpy( pDest, pSrc, maxLenInChars * sizeof(*pDest) );
-}
-
-#define COPY_ALL_CHARACTERS -1
-char *V_strncat( INOUT_Z_CAP(cchDest) char *pDest, const char *pSrc, size_t cchDest, int max_chars_to_copy=COPY_ALL_CHARACTERS );
-template <size_t cchDest> char *V_strcat_safe( INOUT_Z_ARRAY char (&pDest)[cchDest], const char *pSrc, int nMaxCharsToCopy=COPY_ALL_CHARACTERS )
-{
- return V_strncat( pDest, pSrc, (int)cchDest, nMaxCharsToCopy );
-}
-
-wchar_t *V_wcsncat( INOUT_Z_CAP(cchDest) wchar_t *pDest, const wchar_t *pSrc, size_t cchDest, int nMaxCharsToCopy=COPY_ALL_CHARACTERS );
-template <size_t cchDest> wchar_t *V_wcscat_safe( INOUT_Z_ARRAY wchar_t (&pDest)[cchDest], const wchar_t *pSrc, int nMaxCharsToCopy=COPY_ALL_CHARACTERS )
-{
- return V_wcsncat( pDest, pSrc, (int)cchDest, nMaxCharsToCopy );
-}
-
-char *V_strnlwr( INOUT_Z_CAP(cchBuf) char *pBuf, size_t cchBuf);
-template <size_t cchDest> char *V_strlwr_safe( INOUT_Z_ARRAY char (&pBuf)[cchDest] )
-{
- return _V_strnlwr( pBuf, (int)cchDest );
-}
-
-
-// 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
-#define CORRECT_PATH_SEPARATOR '/'
-#define CORRECT_PATH_SEPARATOR_S "/"
-#define INCORRECT_PATH_SEPARATOR '\\'
-#define INCORRECT_PATH_SEPARATOR_S "\\"
-#endif
-
-int V_vsnprintf( OUT_Z_CAP(maxLenInCharacters) char *pDest, int maxLenInCharacters, PRINTF_FORMAT_STRING const char *pFormat, va_list params );
-template <size_t maxLenInCharacters> int V_vsprintf_safe( OUT_Z_ARRAY char (&pDest)[maxLenInCharacters], PRINTF_FORMAT_STRING const char *pFormat, va_list params ) { return V_vsnprintf( pDest, maxLenInCharacters, pFormat, params ); }
-
-int V_snprintf( OUT_Z_CAP(maxLenInChars) char *pDest, int maxLenInChars, PRINTF_FORMAT_STRING const char *pFormat, ... ) FMTFUNCTION( 3, 4 );
-// gcc insists on only having format annotations on declarations, not definitions, which is why I have both.
-template <size_t maxLenInChars> int V_sprintf_safe( OUT_Z_ARRAY char (&pDest)[maxLenInChars], PRINTF_FORMAT_STRING const char *pFormat, ... ) FMTFUNCTION( 2, 3 );
-template <size_t maxLenInChars> int V_sprintf_safe( OUT_Z_ARRAY char (&pDest)[maxLenInChars], PRINTF_FORMAT_STRING const char *pFormat, ... )
-{
- va_list params;
- va_start( params, pFormat );
- int result = V_vsnprintf( pDest, maxLenInChars, pFormat, params );
- va_end( params );
- return result;
-}
-
-int V_vsnwprintf( OUT_Z_CAP(maxLenInCharacters) wchar_t *pDest, int maxLenInCharacters, PRINTF_FORMAT_STRING const wchar_t *pFormat, va_list params );
-template <size_t maxLenInCharacters> int V_vswprintf_safe( OUT_Z_ARRAY wchar_t (&pDest)[maxLenInCharacters], PRINTF_FORMAT_STRING const wchar_t *pFormat, va_list params ) { return V_vsnwprintf( pDest, maxLenInCharacters, pFormat, params ); }
-int V_vsnprintfRet( OUT_Z_CAP(maxLenInCharacters) char *pDest, int maxLenInCharacters, PRINTF_FORMAT_STRING const char *pFormat, va_list params, bool *pbTruncated );
-template <size_t maxLenInCharacters> int V_vsprintfRet_safe( OUT_Z_ARRAY char (&pDest)[maxLenInCharacters], PRINTF_FORMAT_STRING const char *pFormat, va_list params, bool *pbTruncated ) { return V_vsnprintfRet( pDest, maxLenInCharacters, pFormat, params, pbTruncated ); }
-
-// FMTFUNCTION can only be used on ASCII functions, not wide-char functions.
-int V_snwprintf( OUT_Z_CAP(maxLenInCharacters) wchar_t *pDest, int maxLenInCharacters, PRINTF_FORMAT_STRING const wchar_t *pFormat, ... );
-template <size_t maxLenInChars> int V_swprintf_safe( OUT_Z_ARRAY wchar_t (&pDest)[maxLenInChars], PRINTF_FORMAT_STRING const wchar_t *pFormat, ... )
-{
- va_list params;
- va_start( params, pFormat );
- int result = V_vsnwprintf( pDest, maxLenInChars, pFormat, params );
- va_end( params );
- return result;
-}
-
-// 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 );
-
-// conversion functions wchar_t <-> char, returning the number of characters converted
-int V_UTF8ToUnicode( const char *pUTF8, OUT_Z_BYTECAP(cubDestSizeInBytes) wchar_t *pwchDest, int cubDestSizeInBytes );
-int V_UnicodeToUTF8( const wchar_t *pUnicode, OUT_Z_BYTECAP(cubDestSizeInBytes) char *pUTF8, int cubDestSizeInBytes );
-int V_UCS2ToUnicode( const ucs2 *pUCS2, OUT_Z_BYTECAP(cubDestSizeInBytes) wchar_t *pUnicode, int cubDestSizeInBytes );
-int V_UCS2ToUTF8( const ucs2 *pUCS2, OUT_Z_BYTECAP(cubDestSizeInBytes) char *pUTF8, int cubDestSizeInBytes );
-int V_UnicodeToUCS2( const wchar_t *pUnicode, int cubSrcInBytes, OUT_Z_BYTECAP(cubDestSizeInBytes) char *pUCS2, int cubDestSizeInBytes );
-int V_UTF8ToUCS2( const char *pUTF8, int cubSrcInBytes, OUT_Z_BYTECAP(cubDestSizeInBytes) ucs2 *pUCS2, int cubDestSizeInBytes );
-
-// strips leading and trailing whitespace; returns true if any characters were removed. UTF-8 and UTF-16 versions.
-bool Q_StripPrecedingAndTrailingWhitespace( char *pch );
-bool Q_StripPrecedingAndTrailingWhitespaceW( wchar_t *pwch );
-
-// strips leading and trailing whitespace, also taking "aggressive" characters
-// like punctuation spaces, non-breaking spaces, composing characters, and so on
-bool Q_AggressiveStripPrecedingAndTrailingWhitespace( char *pch );
-bool Q_AggressiveStripPrecedingAndTrailingWhitespaceW( wchar_t *pwch );
-
-// 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!!!)
-unsigned char V_nibble( char c );
-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
-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 );
-// 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.
-// Also incorporates the behavior of V_FixSlashes and optionally V_FixDoubleSlashes.
-// 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, bool bRemoveDoubleSlashes = true );
-
-// 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( OUT_Z_CAP(nOutLen) 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( INOUT_Z_CAP(strSize) char *pStr, int strSize );
-
-// Returns true if the path is an absolute path.
-bool V_IsAbsolutePath( IN_Z 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( IN_Z const char *pIn, IN_Z const char *pMatch, const char *pReplaceWith,
- OUT_Z_CAP(outLen) 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( IN_Z const char *pString, IN_Z const char *pSeparator, CUtlVector<char*, CUtlMemory<char*, int> > &outStrings );
-
-// Just like V_SplitString, but it can use multiple possible separators.
-void V_SplitString2( IN_Z 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( OUT_Z_CAP(maxLen) 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, OUT_Z_CAP(outSize) char *pOut, int outSize );
-
-// Chop off the left nChars of a string.
-void V_StrLeft( const char *pStr, int nChars, OUT_Z_CAP(outSize) char *pOut, int outSize );
-
-// Chop off the right nChars of a string.
-void V_StrRight( const char *pStr, int nChars, OUT_Z_CAP(outSize) 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, OUT_Z_BYTECAP(nOutSizeInBytes) wchar_t *pWString, int nOutSizeInBytes );
-void V_wcstostr( const wchar_t *pWString, int nInSize, OUT_Z_CAP(nOutSizeInBytes) char *pString, int nOutSizeInBytes );
-
-// buffer-safe strcat
-inline void V_strcat( INOUT_Z_CAP(cchDest) char *dest, const char *src, int cchDest )
-{
- V_strncat( dest, src, cchDest, COPY_ALL_CHARACTERS );
-}
-
-// Buffer safe wcscat
-inline void V_wcscat( INOUT_Z_CAP(cchDest) wchar_t *dest, const wchar_t *src, int cchDest )
-{
- V_wcsncat( dest, src, cchDest, COPY_ALL_CHARACTERS );
-}
-
-//-----------------------------------------------------------------------------
-// generic unique name helper functions
-//-----------------------------------------------------------------------------
-
-// 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 == NULL )
- return 0;
-
- int freeindex = startindex;
-
- int nNames = nameArray.Count();
- for ( int i = 0; i < nNames; ++i )
- {
- const char *pName = nameArray[ i ];
- if ( !pName )
- continue;
-
- const char *pIndexStr = StringAfterPrefix( pName, prefix );
- if ( pIndexStr )
- {
- int index = *pIndexStr ? atoi( pIndexStr ) : 1;
- 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( OUT_Z_CAP(memsize) 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;
-}
-
-
-//
-// This utility class is for performing UTF-8 <-> UTF-16 conversion.
-// It is intended for use with function/method parameters.
-//
-// For example, you can call
-// FunctionTakingUTF16( CStrAutoEncode( utf8_string ).ToWString() )
-// or
-// FunctionTakingUTF8( CStrAutoEncode( utf16_string ).ToString() )
-//
-// The converted string is allocated off the heap, and destroyed when
-// the object goes out of scope.
-//
-// if the string cannot be converted, NULL is returned.
-//
-// This class doesn't have any conversion operators; the intention is
-// to encourage the developer to get used to having to think about which
-// encoding is desired.
-//
-class CStrAutoEncode
-{
-public:
-
- // ctor
- explicit CStrAutoEncode( const char *pch )
- {
- m_pch = pch;
- m_pwch = NULL;
-#if !defined( WIN32 ) && !defined(_WIN32)
- m_pucs2 = NULL;
-#endif
- m_bCreatedUTF16 = false;
- }
-
- // ctor
- explicit CStrAutoEncode( const wchar_t *pwch )
- {
- m_pch = NULL;
- m_pwch = pwch;
-#if !defined( WIN32 ) && !defined(_WIN32)
- m_pucs2 = NULL;
-#endif
- m_bCreatedUTF16 = true;
- }
-
-#if !defined(WIN32) && !defined(_WINDOWS) && !defined(_WIN32)
- explicit CStrAutoEncode( const ucs2 *pwch )
- {
- m_pch = NULL;
- m_pwch = NULL;
- m_pucs2 = pwch;
- m_bCreatedUTF16 = true;
- }
-#endif
-
- // returns the UTF-8 string, converting on the fly.
- const char* ToString()
- {
- PopulateUTF8();
- return m_pch;
- }
-
- // returns the UTF-8 string - a writable pointer.
- // only use this if you don't want to call const_cast
- // yourself. We need this for cases like CreateProcess.
- char* ToStringWritable()
- {
- PopulateUTF8();
- return const_cast< char* >( m_pch );
- }
-
- // returns the UTF-16 string, converting on the fly.
- const wchar_t* ToWString()
- {
- PopulateUTF16();
- return m_pwch;
- }
-
-#if !defined( WIN32 ) && !defined(_WIN32)
- // returns the UTF-16 string, converting on the fly.
- const ucs2* ToUCS2String()
- {
- PopulateUCS2();
- return m_pucs2;
- }
-#endif
-
- // returns the UTF-16 string - a writable pointer.
- // only use this if you don't want to call const_cast
- // yourself. We need this for cases like CreateProcess.
- wchar_t* ToWStringWritable()
- {
- PopulateUTF16();
- return const_cast< wchar_t* >( m_pwch );
- }
-
- // dtor
- ~CStrAutoEncode()
- {
- // if we're "native unicode" then the UTF-8 string is something we allocated,
- // and vice versa.
- if ( m_bCreatedUTF16 )
- {
- delete [] m_pch;
- }
- else
- {
- delete [] m_pwch;
- }
- }
-
-private:
- // ensure we have done any conversion work required to farm out a
- // UTF-8 encoded string.
- //
- // We perform two heap allocs here; the first one is the worst-case
- // (four bytes per Unicode code point). This is usually quite pessimistic,
- // so we perform a second allocation that's just the size we need.
- void PopulateUTF8()
- {
- if ( !m_bCreatedUTF16 )
- return; // no work to do
- if ( m_pwch == NULL )
- return; // don't have a UTF-16 string to convert
- if ( m_pch != NULL )
- return; // already been converted to UTF-8; no work to do
-
- // each Unicode code point can expand to as many as four bytes in UTF-8; we
- // also need to leave room for the terminating NUL.
- uint32 cbMax = 4 * static_cast<uint32>( V_wcslen( m_pwch ) ) + 1;
- char *pchTemp = new char[ cbMax ];
- if ( V_UnicodeToUTF8( m_pwch, pchTemp, cbMax ) )
- {
- uint32 cchAlloc = static_cast<uint32>( V_strlen( pchTemp ) ) + 1;
- char *pchHeap = new char[ cchAlloc ];
- V_strncpy( pchHeap, pchTemp, cchAlloc );
- delete [] pchTemp;
- m_pch = pchHeap;
- }
- else
- {
- // do nothing, and leave the UTF-8 string NULL
- delete [] pchTemp;
- }
- }
-
- // ensure we have done any conversion work required to farm out a
- // UTF-16 encoded string.
- //
- // We perform two heap allocs here; the first one is the worst-case
- // (one code point per UTF-8 byte). This is sometimes pessimistic,
- // so we perform a second allocation that's just the size we need.
- void PopulateUTF16()
- {
- if ( m_bCreatedUTF16 )
- return; // no work to do
- if ( m_pch == NULL )
- return; // no UTF-8 string to convert
- if ( m_pwch != NULL )
- return; // already been converted to UTF-16; no work to do
-
- uint32 cchMax = static_cast<uint32>( V_strlen( m_pch ) ) + 1;
- wchar_t *pwchTemp = new wchar_t[ cchMax ];
- if ( V_UTF8ToUnicode( m_pch, pwchTemp, cchMax * sizeof( wchar_t ) ) )
- {
- uint32 cchAlloc = static_cast<uint32>( V_wcslen( pwchTemp ) ) + 1;
- wchar_t *pwchHeap = new wchar_t[ cchAlloc ];
- V_wcsncpy( pwchHeap, pwchTemp, cchAlloc * sizeof( wchar_t ) );
- delete [] pwchTemp;
- m_pwch = pwchHeap;
- }
- else
- {
- // do nothing, and leave the UTF-16 string NULL
- delete [] pwchTemp;
- }
- }
-
-#if !defined( WIN32 ) && !defined(_WIN32)
- // ensure we have done any conversion work required to farm out a
- // UTF-16 encoded string.
- //
- // We perform two heap allocs here; the first one is the worst-case
- // (one code point per UTF-8 byte). This is sometimes pessimistic,
- // so we perform a second allocation that's just the size we need.
- void PopulateUCS2()
- {
- if ( m_pch == NULL )
- return; // no UTF-8 string to convert
- if ( m_pucs2 != NULL )
- return; // already been converted to UTF-16; no work to do
-
- uint32 cchMax = static_cast<uint32>( V_strlen( m_pch ) ) + 1;
- ucs2 *pwchTemp = new ucs2[ cchMax ];
- if ( V_UTF8ToUCS2( m_pch, cchMax, pwchTemp, cchMax * sizeof( ucs2 ) ) )
- {
- uint32 cchAlloc = cchMax;
- ucs2 *pwchHeap = new ucs2[ cchAlloc ];
- memcpy( pwchHeap, pwchTemp, cchAlloc * sizeof( ucs2 ) );
- delete [] pwchTemp;
- m_pucs2 = pwchHeap;
- }
- else
- {
- // do nothing, and leave the UTF-16 string NULL
- delete [] pwchTemp;
- }
- }
-#endif
-
- // one of these pointers is an owned pointer; whichever
- // one is the encoding OTHER than the one we were initialized
- // with is the pointer we've allocated and must free.
- const char *m_pch;
- const wchar_t *m_pwch;
-#if !defined( WIN32 ) && !defined(_WIN32)
- const ucs2 *m_pucs2;
-#endif
- // "created as UTF-16", means our owned string is the UTF-8 string not the UTF-16 one.
- bool m_bCreatedUTF16;
-
-};
-
-
-
-// NOTE: This is for backward compatability!
-// We need to DLL-export the Q methods in vstdlib but not link to them in other projects
-#if !defined( VSTDLIB_BACKWARD_COMPAT )
-
-#define Q_memset V_memset
-#define Q_memcpy V_memcpy
-#define Q_memmove V_memmove
-#define Q_memcmp V_memcmp
-#define Q_strlen V_strlen
-#define Q_strcpy V_strcpy
-#define Q_strrchr V_strrchr
-#define Q_strcmp V_strcmp
-#define Q_wcscmp V_wcscmp
-#define Q_stricmp V_stricmp
-#define Q_strstr V_strstr
-#define Q_strupr V_strupr
-#define Q_strlower V_strlower
-#define Q_wcslen V_wcslen
-#define Q_strncmp V_strncmp
-#define Q_strcasecmp V_strcasecmp
-#define Q_strncasecmp V_strncasecmp
-#define Q_strnicmp V_strnicmp
-#define Q_atoi V_atoi
-#define Q_atoi64 V_atoi64
-#define Q_atoui64 V_atoui64
-#define Q_atof V_atof
-#define Q_stristr V_stristr
-#define Q_strnistr V_strnistr
-#define Q_strnchr V_strnchr
-#define Q_normalizeFloatString V_normalizeFloatString
-#define Q_strncpy V_strncpy
-#define Q_snprintf V_snprintf
-#define Q_wcsncpy V_wcsncpy
-#define Q_strncat V_strncat
-#define Q_strnlwr V_strnlwr
-#define Q_vsnprintf V_vsnprintf
-#define Q_vsnprintfRet V_vsnprintfRet
-#define Q_pretifymem V_pretifymem
-#define Q_pretifynum V_pretifynum
-#define Q_UTF8ToUnicode V_UTF8ToUnicode
-#define Q_UnicodeToUTF8 V_UnicodeToUTF8
-#define Q_hextobinary V_hextobinary
-#define Q_binarytohex V_binarytohex
-#define Q_FileBase V_FileBase
-#define Q_StripTrailingSlash V_StripTrailingSlash
-#define Q_StripExtension V_StripExtension
-#define Q_DefaultExtension V_DefaultExtension
-#define Q_SetExtension V_SetExtension
-#define Q_StripFilename V_StripFilename
-#define Q_StripLastDir V_StripLastDir
-#define Q_UnqualifiedFileName V_UnqualifiedFileName
-#define Q_ComposeFileName V_ComposeFileName
-#define Q_ExtractFilePath V_ExtractFilePath
-#define Q_ExtractFileExtension V_ExtractFileExtension
-#define Q_GetFileExtension V_GetFileExtension
-#define Q_RemoveDotSlashes V_RemoveDotSlashes
-#define Q_MakeAbsolutePath V_MakeAbsolutePath
-#define Q_AppendSlash V_AppendSlash
-#define Q_IsAbsolutePath V_IsAbsolutePath
-#define Q_StrSubst V_StrSubst
-#define Q_SplitString V_SplitString
-#define Q_SplitString2 V_SplitString2
-#define Q_StrSlice V_StrSlice
-#define Q_StrLeft V_StrLeft
-#define Q_StrRight V_StrRight
-#define Q_FixSlashes V_FixSlashes
-#define Q_strtowcs V_strtowcs
-#define Q_wcstostr V_wcstostr
-#define Q_strcat V_strcat
-#define Q_GenerateUniqueNameIndex V_GenerateUniqueNameIndex
-#define Q_GenerateUniqueName V_GenerateUniqueName
-#define Q_MakeRelativePath V_MakeRelativePath
-#define Q_qsort_s V_qsort_s
-
-#endif // !defined( VSTDLIB_DLL_EXPORT )
-
-
-#endif // TIER1_STRTOOLS_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
+
+#ifndef TIER1_STRTOOLS_H
+#define TIER1_STRTOOLS_H
+
+#include "tier0/platform.h"
+
+#include <ctype.h>
+#include <stdarg.h>
+#ifdef _WIN32
+#pragma once
+#elif POSIX
+#include <wchar.h>
+#include <math.h>
+#include <wctype.h>
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef _WIN64
+#define str_size unsigned int
+#else
+#define str_size size_t
+#endif
+
+template< class T, class I > class CUtlMemory;
+template< class T, class A > class CUtlVector;
+
+
+//-----------------------------------------------------------------------------
+// Portable versions of standard string functions
+//-----------------------------------------------------------------------------
+void _V_memset ( const char* file, int line, void *dest, int fill, int count );
+void _V_memcpy ( const char* file, int line, void *dest, const void *src, int count );
+void _V_memmove ( const char* file, int line, void *dest, const void *src, int count );
+int _V_memcmp ( const char* file, int line, const void *m1, const void *m2, int count );
+int _V_strlen ( const char* file, int line, const char *str );
+void _V_strcpy ( const char* file, int line, char *dest, const char *src );
+char* _V_strrchr ( const char* file, int line, const char *s, char c );
+int _V_strcmp ( const char* file, int line, const char *s1, const char *s2 );
+int _V_wcscmp ( const char* file, int line, const wchar_t *s1, const wchar_t *s2 );
+char* _V_strstr ( const char* file, int line, const char *s1, const char *search );
+int _V_wcslen ( const char* file, int line, 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);
+
+// ASCII-optimized functions which fall back to CRT only when necessary
+char *V_strupr( char *start );
+char *V_strlower( char *start );
+int V_stricmp( const char *s1, const char *s2 );
+int V_strncmp( const char *s1, const char *s2, int count );
+int V_strnicmp( const char *s1, const char *s2, int n );
+
+#ifdef POSIX
+
+inline char *strupr( char *start )
+{
+ return V_strupr( start );
+}
+
+inline char *strlwr( char *start )
+{
+ return V_strlower( 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
+
+
+#ifdef _DEBUG
+
+#define V_memset(dest, fill, count) _V_memset (__FILE__, __LINE__, (dest), (fill), (count))
+#define V_memcpy(dest, src, count) _V_memcpy (__FILE__, __LINE__, (dest), (src), (count))
+#define V_memmove(dest, src, count) _V_memmove (__FILE__, __LINE__, (dest), (src), (count))
+#define V_memcmp(m1, m2, count) _V_memcmp (__FILE__, __LINE__, (m1), (m2), (count))
+#define V_strlen(str) _V_strlen (__FILE__, __LINE__, (str))
+#define V_strcpy(dest, src) _V_strcpy (__FILE__, __LINE__, (dest), (src))
+#define V_strrchr(s, c) _V_strrchr (__FILE__, __LINE__, (s), (c))
+#define V_strcmp(s1, s2) _V_strcmp (__FILE__, __LINE__, (s1), (s2))
+#define V_wcscmp(s1, s2) _V_wcscmp (__FILE__, __LINE__, (s1), (s2))
+#define V_strstr(s1, search ) _V_strstr (__FILE__, __LINE__, (s1), (search) )
+#define V_wcslen(pwch) _V_wcslen (__FILE__, __LINE__, (pwch))
+#define V_wcslower(start) _V_wcslower (__FILE__, __LINE__, (start))
+#define V_wcsupr(start) _V_wcsupr (__FILE__, __LINE__, (start))
+
+#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 char* V_strstr( const char *s1, const char *search ) { return (char*)strstr( s1, search ); }
+inline wchar_t* V_wcslower (wchar_t *start) { return _wcslwr( start ); }
+inline wchar_t* V_wcsupr (wchar_t *start) { return _wcsupr( start ); }
+
+#endif
+
+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 );
+inline int V_strcasecmp (const char *s1, const char *s2) { return V_stricmp(s1, s2); }
+inline int V_strncasecmp (const char *s1, const char *s2, int n) { return V_strnicmp(s1, s2, n); }
+void V_qsort_s( void *base, size_t num, size_t width, int ( __cdecl *compare )(void *, const void *,
+const void *), void *context );
+
+
+// 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 );
+
+// this is locale-unaware and therefore faster version of standard isdigit()
+// It also avoids sign-extension errors.
+inline bool V_isdigit( char c )
+{
+ return c >= '0' && c <= '9';
+}
+
+// The islower/isdigit/etc. functions all expect a parameter that is either
+// 0-0xFF or EOF. It is easy to violate this constraint simply by passing
+// 'char' to these functions instead of unsigned char.
+// The V_ functions handle the char/unsigned char mismatch by taking a
+// char parameter and casting it to unsigned char so that chars with the
+// sign bit set will be zero extended instead of sign extended.
+// Not that EOF cannot be passed to these functions.
+//
+// These functions could also be used for optimizations if locale
+// considerations make some of the CRT functions slow.
+//#undef isdigit // In case this is implemented as a macro
+//#define isdigit use_V_isdigit_instead_of_isdigit
+inline bool V_isalpha(char c) { return isalpha( (unsigned char)c ) != 0; }
+//#undef isalpha
+//#define isalpha use_V_isalpha_instead_of_isalpha
+inline bool V_isalnum(char c) { return isalnum( (unsigned char)c ) != 0; }
+//#undef isalnum
+//#define isalnum use_V_isalnum_instead_of_isalnum
+inline bool V_isprint(char c) { return isprint( (unsigned char)c ) != 0; }
+//#undef isprint
+//#define isprint use_V_isprint_instead_of_isprint
+inline bool V_isxdigit(char c) { return isxdigit( (unsigned char)c ) != 0; }
+//#undef isxdigit
+//#define isxdigit use_V_isxdigit_instead_of_isxdigit
+inline bool V_ispunct(char c) { return ispunct( (unsigned char)c ) != 0; }
+//#undef ispunct
+//#define ispunct use_V_ispunct_instead_of_ispunct
+inline bool V_isgraph(char c) { return isgraph( (unsigned char)c ) != 0; }
+//#undef isgraph
+//#define isgraph use_V_isgraph_instead_of_isgraph
+inline bool V_isupper(char c) { return isupper( (unsigned char)c ) != 0; }
+//#undef isupper
+//#define isupper use_V_isupper_instead_of_isupper
+inline bool V_islower(char c) { return islower( (unsigned char)c ) != 0; }
+//#undef islower
+//#define islower use_V_islower_instead_of_islower
+inline bool V_iscntrl(char c) { return iscntrl( (unsigned char)c ) != 0; }
+//#undef iscntrl
+//#define iscntrl use_V_iscntrl_instead_of_iscntrl
+inline bool V_isspace(char c) { return isspace( (unsigned char)c ) != 0; }
+//#undef isspace
+//#define isspace use_V_isspace_instead_of_isspace
+
+
+// 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( OUT_Z_CAP(maxLenInChars) char *pDest, const char *pSrc, int maxLenInChars );
+
+// Ultimate safe strcpy function, for arrays only -- buffer size is inferred by the compiler
+template <size_t maxLenInChars> void V_strcpy_safe( OUT_Z_ARRAY char (&pDest)[maxLenInChars], const char *pSrc )
+{
+ V_strncpy( pDest, pSrc, (int)maxLenInChars );
+}
+
+void V_wcsncpy( OUT_Z_BYTECAP(maxLenInBytes) wchar_t *pDest, wchar_t const *pSrc, int maxLenInBytes );
+template <size_t maxLenInChars> void V_wcscpy_safe( OUT_Z_ARRAY wchar_t (&pDest)[maxLenInChars], wchar_t const *pSrc )
+{
+ V_wcsncpy( pDest, pSrc, maxLenInChars * sizeof(*pDest) );
+}
+
+#define COPY_ALL_CHARACTERS -1
+char *V_strncat( INOUT_Z_CAP(cchDest) char *pDest, const char *pSrc, size_t cchDest, int max_chars_to_copy=COPY_ALL_CHARACTERS );
+template <size_t cchDest> char *V_strcat_safe( INOUT_Z_ARRAY char (&pDest)[cchDest], const char *pSrc, int nMaxCharsToCopy=COPY_ALL_CHARACTERS )
+{
+ return V_strncat( pDest, pSrc, (int)cchDest, nMaxCharsToCopy );
+}
+
+wchar_t *V_wcsncat( INOUT_Z_CAP(cchDest) wchar_t *pDest, const wchar_t *pSrc, size_t cchDest, int nMaxCharsToCopy=COPY_ALL_CHARACTERS );
+template <size_t cchDest> wchar_t *V_wcscat_safe( INOUT_Z_ARRAY wchar_t (&pDest)[cchDest], const wchar_t *pSrc, int nMaxCharsToCopy=COPY_ALL_CHARACTERS )
+{
+ return V_wcsncat( pDest, pSrc, (int)cchDest, nMaxCharsToCopy );
+}
+
+char *V_strnlwr( INOUT_Z_CAP(cchBuf) char *pBuf, size_t cchBuf);
+template <size_t cchDest> char *V_strlwr_safe( INOUT_Z_ARRAY char (&pBuf)[cchDest] )
+{
+ return _V_strnlwr( pBuf, (int)cchDest );
+}
+
+
+// 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
+#define CORRECT_PATH_SEPARATOR '/'
+#define CORRECT_PATH_SEPARATOR_S "/"
+#define INCORRECT_PATH_SEPARATOR '\\'
+#define INCORRECT_PATH_SEPARATOR_S "\\"
+#endif
+
+int V_vsnprintf( OUT_Z_CAP(maxLenInCharacters) char *pDest, int maxLenInCharacters, PRINTF_FORMAT_STRING const char *pFormat, va_list params );
+template <size_t maxLenInCharacters> int V_vsprintf_safe( OUT_Z_ARRAY char (&pDest)[maxLenInCharacters], PRINTF_FORMAT_STRING const char *pFormat, va_list params ) { return V_vsnprintf( pDest, maxLenInCharacters, pFormat, params ); }
+
+int V_snprintf( OUT_Z_CAP(maxLenInChars) char *pDest, int maxLenInChars, PRINTF_FORMAT_STRING const char *pFormat, ... ) FMTFUNCTION( 3, 4 );
+// gcc insists on only having format annotations on declarations, not definitions, which is why I have both.
+template <size_t maxLenInChars> int V_sprintf_safe( OUT_Z_ARRAY char (&pDest)[maxLenInChars], PRINTF_FORMAT_STRING const char *pFormat, ... ) FMTFUNCTION( 2, 3 );
+template <size_t maxLenInChars> int V_sprintf_safe( OUT_Z_ARRAY char (&pDest)[maxLenInChars], PRINTF_FORMAT_STRING const char *pFormat, ... )
+{
+ va_list params;
+ va_start( params, pFormat );
+ int result = V_vsnprintf( pDest, maxLenInChars, pFormat, params );
+ va_end( params );
+ return result;
+}
+
+int V_vsnwprintf( OUT_Z_CAP(maxLenInCharacters) wchar_t *pDest, int maxLenInCharacters, PRINTF_FORMAT_STRING const wchar_t *pFormat, va_list params );
+template <size_t maxLenInCharacters> int V_vswprintf_safe( OUT_Z_ARRAY wchar_t (&pDest)[maxLenInCharacters], PRINTF_FORMAT_STRING const wchar_t *pFormat, va_list params ) { return V_vsnwprintf( pDest, maxLenInCharacters, pFormat, params ); }
+int V_vsnprintfRet( OUT_Z_CAP(maxLenInCharacters) char *pDest, int maxLenInCharacters, PRINTF_FORMAT_STRING const char *pFormat, va_list params, bool *pbTruncated );
+template <size_t maxLenInCharacters> int V_vsprintfRet_safe( OUT_Z_ARRAY char (&pDest)[maxLenInCharacters], PRINTF_FORMAT_STRING const char *pFormat, va_list params, bool *pbTruncated ) { return V_vsnprintfRet( pDest, maxLenInCharacters, pFormat, params, pbTruncated ); }
+
+// FMTFUNCTION can only be used on ASCII functions, not wide-char functions.
+int V_snwprintf( OUT_Z_CAP(maxLenInCharacters) wchar_t *pDest, int maxLenInCharacters, PRINTF_FORMAT_STRING const wchar_t *pFormat, ... );
+template <size_t maxLenInChars> int V_swprintf_safe( OUT_Z_ARRAY wchar_t (&pDest)[maxLenInChars], PRINTF_FORMAT_STRING const wchar_t *pFormat, ... )
+{
+ va_list params;
+ va_start( params, pFormat );
+ int result = V_vsnwprintf( pDest, maxLenInChars, pFormat, params );
+ va_end( params );
+ return result;
+}
+
+// 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 );
+
+// conversion functions wchar_t <-> char, returning the number of characters converted
+int V_UTF8ToUnicode( const char *pUTF8, OUT_Z_BYTECAP(cubDestSizeInBytes) wchar_t *pwchDest, int cubDestSizeInBytes );
+int V_UnicodeToUTF8( const wchar_t *pUnicode, OUT_Z_BYTECAP(cubDestSizeInBytes) char *pUTF8, int cubDestSizeInBytes );
+int V_UCS2ToUnicode( const ucs2 *pUCS2, OUT_Z_BYTECAP(cubDestSizeInBytes) wchar_t *pUnicode, int cubDestSizeInBytes );
+int V_UCS2ToUTF8( const ucs2 *pUCS2, OUT_Z_BYTECAP(cubDestSizeInBytes) char *pUTF8, int cubDestSizeInBytes );
+int V_UnicodeToUCS2( const wchar_t *pUnicode, int cubSrcInBytes, OUT_Z_BYTECAP(cubDestSizeInBytes) char *pUCS2, int cubDestSizeInBytes );
+int V_UTF8ToUCS2( const char *pUTF8, int cubSrcInBytes, OUT_Z_BYTECAP(cubDestSizeInBytes) ucs2 *pUCS2, int cubDestSizeInBytes );
+
+// strips leading and trailing whitespace; returns true if any characters were removed. UTF-8 and UTF-16 versions.
+bool Q_StripPrecedingAndTrailingWhitespace( char *pch );
+bool Q_StripPrecedingAndTrailingWhitespaceW( wchar_t *pwch );
+
+// strips leading and trailing whitespace, also taking "aggressive" characters
+// like punctuation spaces, non-breaking spaces, composing characters, and so on
+bool Q_AggressiveStripPrecedingAndTrailingWhitespace( char *pch );
+bool Q_AggressiveStripPrecedingAndTrailingWhitespaceW( wchar_t *pwch );
+
+// 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!!!)
+unsigned char V_nibble( char c );
+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
+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 );
+// 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.
+// Also incorporates the behavior of V_FixSlashes and optionally V_FixDoubleSlashes.
+// 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, bool bRemoveDoubleSlashes = true );
+
+// 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( OUT_Z_CAP(nOutLen) 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( INOUT_Z_CAP(strSize) char *pStr, int strSize );
+
+// Returns true if the path is an absolute path.
+bool V_IsAbsolutePath( IN_Z 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( IN_Z const char *pIn, IN_Z const char *pMatch, const char *pReplaceWith,
+ OUT_Z_CAP(outLen) 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( IN_Z const char *pString, IN_Z const char *pSeparator, CUtlVector<char*, CUtlMemory<char*, int> > &outStrings );
+
+// Just like V_SplitString, but it can use multiple possible separators.
+void V_SplitString2( IN_Z 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( OUT_Z_CAP(maxLen) 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, OUT_Z_CAP(outSize) char *pOut, int outSize );
+
+// Chop off the left nChars of a string.
+void V_StrLeft( const char *pStr, int nChars, OUT_Z_CAP(outSize) char *pOut, int outSize );
+
+// Chop off the right nChars of a string.
+void V_StrRight( const char *pStr, int nChars, OUT_Z_CAP(outSize) 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, OUT_Z_BYTECAP(nOutSizeInBytes) wchar_t *pWString, int nOutSizeInBytes );
+void V_wcstostr( const wchar_t *pWString, int nInSize, OUT_Z_CAP(nOutSizeInBytes) char *pString, int nOutSizeInBytes );
+
+// buffer-safe strcat
+inline void V_strcat( INOUT_Z_CAP(cchDest) char *dest, const char *src, int cchDest )
+{
+ V_strncat( dest, src, cchDest, COPY_ALL_CHARACTERS );
+}
+
+// Buffer safe wcscat
+inline void V_wcscat( INOUT_Z_CAP(cchDest) wchar_t *dest, const wchar_t *src, int cchDest )
+{
+ V_wcsncat( dest, src, cchDest, COPY_ALL_CHARACTERS );
+}
+
+//-----------------------------------------------------------------------------
+// generic unique name helper functions
+//-----------------------------------------------------------------------------
+
+// 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 == NULL )
+ return 0;
+
+ int freeindex = startindex;
+
+ int nNames = nameArray.Count();
+ for ( int i = 0; i < nNames; ++i )
+ {
+ const char *pName = nameArray[ i ];
+ if ( !pName )
+ continue;
+
+ const char *pIndexStr = StringAfterPrefix( pName, prefix );
+ if ( pIndexStr )
+ {
+ int index = *pIndexStr ? atoi( pIndexStr ) : 1;
+ 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( OUT_Z_CAP(memsize) 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;
+}
+
+
+//
+// This utility class is for performing UTF-8 <-> UTF-16 conversion.
+// It is intended for use with function/method parameters.
+//
+// For example, you can call
+// FunctionTakingUTF16( CStrAutoEncode( utf8_string ).ToWString() )
+// or
+// FunctionTakingUTF8( CStrAutoEncode( utf16_string ).ToString() )
+//
+// The converted string is allocated off the heap, and destroyed when
+// the object goes out of scope.
+//
+// if the string cannot be converted, NULL is returned.
+//
+// This class doesn't have any conversion operators; the intention is
+// to encourage the developer to get used to having to think about which
+// encoding is desired.
+//
+class CStrAutoEncode
+{
+public:
+
+ // ctor
+ explicit CStrAutoEncode( const char *pch )
+ {
+ m_pch = pch;
+ m_pwch = NULL;
+#if !defined( WIN32 ) && !defined(_WIN32)
+ m_pucs2 = NULL;
+#endif
+ m_bCreatedUTF16 = false;
+ }
+
+ // ctor
+ explicit CStrAutoEncode( const wchar_t *pwch )
+ {
+ m_pch = NULL;
+ m_pwch = pwch;
+#if !defined( WIN32 ) && !defined(_WIN32)
+ m_pucs2 = NULL;
+#endif
+ m_bCreatedUTF16 = true;
+ }
+
+#if !defined(WIN32) && !defined(_WINDOWS) && !defined(_WIN32)
+ explicit CStrAutoEncode( const ucs2 *pwch )
+ {
+ m_pch = NULL;
+ m_pwch = NULL;
+ m_pucs2 = pwch;
+ m_bCreatedUTF16 = true;
+ }
+#endif
+
+ // returns the UTF-8 string, converting on the fly.
+ const char* ToString()
+ {
+ PopulateUTF8();
+ return m_pch;
+ }
+
+ // returns the UTF-8 string - a writable pointer.
+ // only use this if you don't want to call const_cast
+ // yourself. We need this for cases like CreateProcess.
+ char* ToStringWritable()
+ {
+ PopulateUTF8();
+ return const_cast< char* >( m_pch );
+ }
+
+ // returns the UTF-16 string, converting on the fly.
+ const wchar_t* ToWString()
+ {
+ PopulateUTF16();
+ return m_pwch;
+ }
+
+#if !defined( WIN32 ) && !defined(_WIN32)
+ // returns the UTF-16 string, converting on the fly.
+ const ucs2* ToUCS2String()
+ {
+ PopulateUCS2();
+ return m_pucs2;
+ }
+#endif
+
+ // returns the UTF-16 string - a writable pointer.
+ // only use this if you don't want to call const_cast
+ // yourself. We need this for cases like CreateProcess.
+ wchar_t* ToWStringWritable()
+ {
+ PopulateUTF16();
+ return const_cast< wchar_t* >( m_pwch );
+ }
+
+ // dtor
+ ~CStrAutoEncode()
+ {
+ // if we're "native unicode" then the UTF-8 string is something we allocated,
+ // and vice versa.
+ if ( m_bCreatedUTF16 )
+ {
+ delete [] m_pch;
+ }
+ else
+ {
+ delete [] m_pwch;
+ }
+ }
+
+private:
+ // ensure we have done any conversion work required to farm out a
+ // UTF-8 encoded string.
+ //
+ // We perform two heap allocs here; the first one is the worst-case
+ // (four bytes per Unicode code point). This is usually quite pessimistic,
+ // so we perform a second allocation that's just the size we need.
+ void PopulateUTF8()
+ {
+ if ( !m_bCreatedUTF16 )
+ return; // no work to do
+ if ( m_pwch == NULL )
+ return; // don't have a UTF-16 string to convert
+ if ( m_pch != NULL )
+ return; // already been converted to UTF-8; no work to do
+
+ // each Unicode code point can expand to as many as four bytes in UTF-8; we
+ // also need to leave room for the terminating NUL.
+ uint32 cbMax = 4 * static_cast<uint32>( V_wcslen( m_pwch ) ) + 1;
+ char *pchTemp = new char[ cbMax ];
+ if ( V_UnicodeToUTF8( m_pwch, pchTemp, cbMax ) )
+ {
+ uint32 cchAlloc = static_cast<uint32>( V_strlen( pchTemp ) ) + 1;
+ char *pchHeap = new char[ cchAlloc ];
+ V_strncpy( pchHeap, pchTemp, cchAlloc );
+ delete [] pchTemp;
+ m_pch = pchHeap;
+ }
+ else
+ {
+ // do nothing, and leave the UTF-8 string NULL
+ delete [] pchTemp;
+ }
+ }
+
+ // ensure we have done any conversion work required to farm out a
+ // UTF-16 encoded string.
+ //
+ // We perform two heap allocs here; the first one is the worst-case
+ // (one code point per UTF-8 byte). This is sometimes pessimistic,
+ // so we perform a second allocation that's just the size we need.
+ void PopulateUTF16()
+ {
+ if ( m_bCreatedUTF16 )
+ return; // no work to do
+ if ( m_pch == NULL )
+ return; // no UTF-8 string to convert
+ if ( m_pwch != NULL )
+ return; // already been converted to UTF-16; no work to do
+
+ uint32 cchMax = static_cast<uint32>( V_strlen( m_pch ) ) + 1;
+ wchar_t *pwchTemp = new wchar_t[ cchMax ];
+ if ( V_UTF8ToUnicode( m_pch, pwchTemp, cchMax * sizeof( wchar_t ) ) )
+ {
+ uint32 cchAlloc = static_cast<uint32>( V_wcslen( pwchTemp ) ) + 1;
+ wchar_t *pwchHeap = new wchar_t[ cchAlloc ];
+ V_wcsncpy( pwchHeap, pwchTemp, cchAlloc * sizeof( wchar_t ) );
+ delete [] pwchTemp;
+ m_pwch = pwchHeap;
+ }
+ else
+ {
+ // do nothing, and leave the UTF-16 string NULL
+ delete [] pwchTemp;
+ }
+ }
+
+#if !defined( WIN32 ) && !defined(_WIN32)
+ // ensure we have done any conversion work required to farm out a
+ // UTF-16 encoded string.
+ //
+ // We perform two heap allocs here; the first one is the worst-case
+ // (one code point per UTF-8 byte). This is sometimes pessimistic,
+ // so we perform a second allocation that's just the size we need.
+ void PopulateUCS2()
+ {
+ if ( m_pch == NULL )
+ return; // no UTF-8 string to convert
+ if ( m_pucs2 != NULL )
+ return; // already been converted to UTF-16; no work to do
+
+ uint32 cchMax = static_cast<uint32>( V_strlen( m_pch ) ) + 1;
+ ucs2 *pwchTemp = new ucs2[ cchMax ];
+ if ( V_UTF8ToUCS2( m_pch, cchMax, pwchTemp, cchMax * sizeof( ucs2 ) ) )
+ {
+ uint32 cchAlloc = cchMax;
+ ucs2 *pwchHeap = new ucs2[ cchAlloc ];
+ memcpy( pwchHeap, pwchTemp, cchAlloc * sizeof( ucs2 ) );
+ delete [] pwchTemp;
+ m_pucs2 = pwchHeap;
+ }
+ else
+ {
+ // do nothing, and leave the UTF-16 string NULL
+ delete [] pwchTemp;
+ }
+ }
+#endif
+
+ // one of these pointers is an owned pointer; whichever
+ // one is the encoding OTHER than the one we were initialized
+ // with is the pointer we've allocated and must free.
+ const char *m_pch;
+ const wchar_t *m_pwch;
+#if !defined( WIN32 ) && !defined(_WIN32)
+ const ucs2 *m_pucs2;
+#endif
+ // "created as UTF-16", means our owned string is the UTF-8 string not the UTF-16 one.
+ bool m_bCreatedUTF16;
+
+};
+
+
+
+// NOTE: This is for backward compatability!
+// We need to DLL-export the Q methods in vstdlib but not link to them in other projects
+#if !defined( VSTDLIB_BACKWARD_COMPAT )
+
+#define Q_memset V_memset
+#define Q_memcpy V_memcpy
+#define Q_memmove V_memmove
+#define Q_memcmp V_memcmp
+#define Q_strlen V_strlen
+#define Q_strcpy V_strcpy
+#define Q_strrchr V_strrchr
+#define Q_strcmp V_strcmp
+#define Q_wcscmp V_wcscmp
+#define Q_stricmp V_stricmp
+#define Q_strstr V_strstr
+#define Q_strupr V_strupr
+#define Q_strlower V_strlower
+#define Q_wcslen V_wcslen
+#define Q_strncmp V_strncmp
+#define Q_strcasecmp V_strcasecmp
+#define Q_strncasecmp V_strncasecmp
+#define Q_strnicmp V_strnicmp
+#define Q_atoi V_atoi
+#define Q_atoi64 V_atoi64
+#define Q_atoui64 V_atoui64
+#define Q_atof V_atof
+#define Q_stristr V_stristr
+#define Q_strnistr V_strnistr
+#define Q_strnchr V_strnchr
+#define Q_normalizeFloatString V_normalizeFloatString
+#define Q_strncpy V_strncpy
+#define Q_snprintf V_snprintf
+#define Q_wcsncpy V_wcsncpy
+#define Q_strncat V_strncat
+#define Q_strnlwr V_strnlwr
+#define Q_vsnprintf V_vsnprintf
+#define Q_vsnprintfRet V_vsnprintfRet
+#define Q_pretifymem V_pretifymem
+#define Q_pretifynum V_pretifynum
+#define Q_UTF8ToUnicode V_UTF8ToUnicode
+#define Q_UnicodeToUTF8 V_UnicodeToUTF8
+#define Q_hextobinary V_hextobinary
+#define Q_binarytohex V_binarytohex
+#define Q_FileBase V_FileBase
+#define Q_StripTrailingSlash V_StripTrailingSlash
+#define Q_StripExtension V_StripExtension
+#define Q_DefaultExtension V_DefaultExtension
+#define Q_SetExtension V_SetExtension
+#define Q_StripFilename V_StripFilename
+#define Q_StripLastDir V_StripLastDir
+#define Q_UnqualifiedFileName V_UnqualifiedFileName
+#define Q_ComposeFileName V_ComposeFileName
+#define Q_ExtractFilePath V_ExtractFilePath
+#define Q_ExtractFileExtension V_ExtractFileExtension
+#define Q_GetFileExtension V_GetFileExtension
+#define Q_RemoveDotSlashes V_RemoveDotSlashes
+#define Q_MakeAbsolutePath V_MakeAbsolutePath
+#define Q_AppendSlash V_AppendSlash
+#define Q_IsAbsolutePath V_IsAbsolutePath
+#define Q_StrSubst V_StrSubst
+#define Q_SplitString V_SplitString
+#define Q_SplitString2 V_SplitString2
+#define Q_StrSlice V_StrSlice
+#define Q_StrLeft V_StrLeft
+#define Q_StrRight V_StrRight
+#define Q_FixSlashes V_FixSlashes
+#define Q_strtowcs V_strtowcs
+#define Q_wcstostr V_wcstostr
+#define Q_strcat V_strcat
+#define Q_GenerateUniqueNameIndex V_GenerateUniqueNameIndex
+#define Q_GenerateUniqueName V_GenerateUniqueName
+#define Q_MakeRelativePath V_MakeRelativePath
+#define Q_qsort_s V_qsort_s
+
+#endif // !defined( VSTDLIB_DLL_EXPORT )
+
+
+#endif // TIER1_STRTOOLS_H
diff --git a/mp/src/public/tier1/thash.h b/mp/src/public/tier1/thash.h
index 453aebf0..51020749 100644
--- a/mp/src/public/tier1/thash.h
+++ b/mp/src/public/tier1/thash.h
@@ -1,698 +1,698 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//=============================================================================
-
-#ifndef THASH_H
-#define THASH_H
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include <typeinfo>
-
-//#define DBGFLAG_THASH // Perform extra sanity checks on the THash
-
-
-// THash
-// This is a heavyweight, templatized version of DHash.
-// It differs from DHash in the following ways:
-// - It's templetized, and automatically constructs and destructs its records as appropriate
-// - It provides a scheduling service, which can be used to touch every record in the table
-// at a specified interval. The scheduler is low-overhead, and provides a very smooth
-// distribution of touches across frames.
-
-// Template arguments:
-// Data: the class to be stored in the hash table
-// I: the type of the primary key (uint32 by default)
-template<class Data, typename I=uint32>
-class CTHash
-{
-private:
- // RecHdr
- // We insert one of these at the beginning of every record. It's used for
- // keeping the records in a linked list.
- typedef struct RecHdr_t
- {
- RecHdr_t *m_pRecHdrNext; // Next item in our linked list
- RecHdr_t *m_pRecHdrPrev; // Previous item in our linked list
- I m_unKey; // Key of this item
- int m_iBucket; // The bucket we're in
- int m_nRunRatio; // We want to run 1 cycle out of every m_nRunRatio
- // cycles (not at all if 0).
-#ifdef DBGFLAG_THASH
- uint m_iCycleLast; // Last cycle we were visited (whether or not we ran)
-#endif
- } RecHdr_t;
-
- // Bucket
- // Each hash bucket is represented by a Bucket structure, which points to the
- // first record with the bucket's hash.
- typedef struct Bucket_t
- {
- RecHdr_t *m_pRecHdrFirst; // First record in our list
- } Bucket_t;
-
-
-public:
- // Constructors & destructors
- CTHash( int cFramesPerCycle );
- ~CTHash();
-
- // Initializer
- void Init( int cRecordInit, int cBuckets );
-
- // Insert a record into the table
- Data *PvRecordInsert( I unKey );
- // Insert a record into the table and set the allocated object's pointer as the hash key
- Data *PvRecordInsertAutoKey();
- // Changes the key for a previously inserted item
- void ChangeKey( Data * pvRecord, I unOldKey, I unNewKey );
-
- // Remove a record
- void Remove( I unKey );
- // Remove a record
- void Remove( Data * pvRecord );
- // Remove all records
- void RemoveAll();
-
- // Find a record
- Data *PvRecordFind( I unKey ) const;
-
- // How many records do we have
- int Count() const { return m_cRecordInUse; }
-
- // Iterate through our members
- Data *PvRecordFirst() const;
- Data *PvRecordNext( Data *pvRecordCur ) const;
-
- // We provide a scheduling service. Call StartFrameSchedule when you want to start running
- // records in a given frame, and repeatedly call PvRecordRun until it returns NULL (or you
- // run our of time).
- void SetRunRatio( Data *pvRecord, int nRunRatio );
- void SetMicroSecPerCycle( int cMicroSecPerCycle, int cMicroSecPerFrame ) { m_cFramesPerCycle = cMicroSecPerCycle / cMicroSecPerFrame; }
- void StartFrameSchedule( bool bNewFrame );
- Data *PvRecordRun();
-
- bool BCompletedPass();
-
-#ifdef DBGFLAG_VALIDATE
- virtual void Validate( CValidator &validator, const char *pchName );
-#endif // DBGFLAG_VALIDATE
-
-
-private:
- // Insert a record into the table
- Data *PvRecordInsertInternal( RecHdr_t *pRecHdr, I unKey );
-
- // Get the record associated with a THashHdr
- Data *PvRecordFromPRecHdr( RecHdr_t *pRecHdr ) const { return ( Data * ) ( ( ( uint8 * ) pRecHdr + sizeof( RecHdr_t ) ) ); }
-
- // Get the RecHdr preceding a PvRecord
- RecHdr_t *PRecHdrFromPvRecord( Data *pvRecord ) const { return ( ( ( RecHdr_t * ) pvRecord ) - 1 ); }
-
- // Get the hash bucket corresponding to a key
- int IBucket( I unKey ) const;
-
- void InsertIntoHash( RecHdr_t *pRecHdr, I unKey );
- void RemoveFromHash( Data * pvRecord );
-
- int m_cBucket; // # of hash buckets we have
- Bucket_t *m_pBucket; // Big array of hash buckets
-
- CUtlMemoryPool *m_pMemoryPoolRecord; // All our data records
-
- int m_cRecordInUse; // # of records in use
- RecHdr_t m_RecHdrHead; // Head of our linked list
- RecHdr_t m_RecHdrTail; // Tail of our linked list
-
- int m_cFramesPerCycle; // Run each of our records once every m_cFramesPerCycle frames
- RecHdr_t *m_pRecHdrRunNext; // Next record to run (be careful-- this is more complicated than it sounds)
- int m_iBucketRunMax; // Stop running when we get to this bucket
- uint m_iCycleCur; // Current cycle (ie, how many times we've made a complete scheduler pass)
- uint m_iCycleLast; // Our previous cycle
- uint m_iFrameCur; // Our current frame (incremented once each StartFrameSchedule)
- uint m_iCycleLastReported; // Last cycle checked by BCompletedPass()
-};
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Constructor
-// Input: cMicroSecRunInterval - How often we want the scheduler to run each of our records
-//-----------------------------------------------------------------------------
-template<class Data, class I>
-CTHash<Data,I>::CTHash( int cFramesPerCycle )
-{
- m_cBucket = 0;
- m_pBucket = NULL;
- m_pMemoryPoolRecord = NULL;
- m_cRecordInUse = 0;
-
- m_cFramesPerCycle = cFramesPerCycle;
- m_pRecHdrRunNext = &m_RecHdrTail; // This will make us start at the beginning on our first frame
- m_iBucketRunMax = 0;
- m_iCycleCur = 0;
- m_iCycleLast = 0;
- m_iFrameCur = 0;
- m_iCycleLastReported = 0;
-
- m_RecHdrHead.m_pRecHdrPrev = NULL;
- m_RecHdrHead.m_pRecHdrNext = &m_RecHdrTail;
- m_RecHdrHead.m_iBucket = -1;
-
- m_RecHdrTail.m_pRecHdrPrev = &m_RecHdrHead;
- m_RecHdrTail.m_pRecHdrNext = NULL;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Destructor
-//-----------------------------------------------------------------------------
-template<class Data, class I>
-CTHash<Data,I>::~CTHash()
-{
- RemoveAll();
-
- if ( NULL != m_pBucket )
- FreePv( m_pBucket );
- m_pBucket = NULL;
-
- if ( NULL != m_pMemoryPoolRecord )
- delete( m_pMemoryPoolRecord );
- m_pMemoryPoolRecord = NULL;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Initializer. Allocate our various arrays, and set up the free
-// list.
-// Input: cRecordInit - Initial # of data records we can contain
-// cBucket - # of hash buckets we should use
-//-----------------------------------------------------------------------------
-template<class Data, class I>
-void CTHash<Data,I>::Init( int cRecordInit, int cBucket )
-{
- Assert( cRecordInit > 0 ); // need to init with non-zero value or memory pool will never grow
-
- // Copy our parameters
- m_cBucket = cBucket;
-
- // Alloc our arrays
- m_pBucket = ( Bucket_t * ) PvAlloc( sizeof( Bucket_t ) * m_cBucket );
- m_pMemoryPoolRecord = new CUtlMemoryPool( sizeof( Data ) + sizeof( RecHdr_t ), cRecordInit,
- CUtlMemoryPool::GROW_SLOW );
-
- // Init the hash buckets
- for ( int iBucket = 0; iBucket < m_cBucket; iBucket++ )
- m_pBucket[iBucket].m_pRecHdrFirst = NULL;
-
- // Make the tail have an illegally large bucket
- m_RecHdrTail.m_iBucket = m_cBucket + 1;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Inserts a new record into the table
-// Input: unKey - Primary key of the new record
-// Output: Pointer to the new record
-//-----------------------------------------------------------------------------
-template<class Data, class I>
-Data *CTHash<Data,I>::PvRecordInsert( I unKey )
-{
- Assert( PvRecordFind( unKey ) == NULL ); // keys are unique; no record with this key may exist
-
- // Find a free record
- RecHdr_t *pRecHdr = ( RecHdr_t * ) m_pMemoryPoolRecord->Alloc();
-
- return PvRecordInsertInternal( pRecHdr, unKey );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Inserts a new record into the table and sets its key to the pointer
-// value of the record
-// Output: Pointer to the new record
-//-----------------------------------------------------------------------------
-template<class Data, class I>
-Data *CTHash<Data,I>::PvRecordInsertAutoKey()
-{
- // Find a free record
- RecHdr_t *pRecHdr = ( RecHdr_t * ) m_pMemoryPoolRecord->Alloc();
-
- return PvRecordInsertInternal( pRecHdr, (I) PvRecordFromPRecHdr( pRecHdr ) );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Inserts an allocated record into the hash table with specified key
-// and calls the constructor of the allocated object
-// Input: pRecHdr - record to insert
-// unKey - hash key to use for record
-// Output: Pointer to the new record
-//-----------------------------------------------------------------------------
-template<class Data, class I>
-Data *CTHash<Data,I>::PvRecordInsertInternal( RecHdr_t *pRecHdr, I unKey )
-{
- InsertIntoHash( pRecHdr, unKey );
-
- // assert that we don't have too many items per bucket
- static bool s_bPerfWarning = false;
- if ( !s_bPerfWarning && Count() >= ( 5 * m_cBucket ) )
- {
- s_bPerfWarning = true;
- AssertMsg( false, "Performance warning: too many items, not enough buckets" );
- Msg( "not enough buckets in thash class %s (%d records, %d buckets)\n",
-#ifdef _WIN32
- typeid(*this).raw_name(),
-#else
- typeid(*this).name(),
-#endif
- Count(), m_cBucket );
- }
-
- // Construct ourselves
- Data *pData = PvRecordFromPRecHdr( pRecHdr );
- Construct<Data>( pData );
- return pData;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Changes key on previously inserted item
-// Input: pvRecord - record to change key for
-// unOldKey - old key (not strictly needed, but helpful consistency check)
-// unNewKey - new key to use
-//-----------------------------------------------------------------------------
-template<class Data, class I>
-void CTHash<Data,I>::ChangeKey( Data * pvRecord, I unOldKey, I unNewKey )
-{
- Data * pvRecordFound = PvRecordFind( unOldKey );
- Assert( pvRecordFound == pvRecord );
- if ( pvRecordFound == pvRecord )
- {
- RemoveFromHash( pvRecord );
- InsertIntoHash( PRecHdrFromPvRecord( pvRecord), unNewKey );
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Removes the entry with a specified key from the table
-// Input: unKey - Key of the entry to remove
-//-----------------------------------------------------------------------------
-template<class Data, class I>
-void CTHash<Data,I>::Remove( I unKey )
-{
- Data *pvRemove = ( Data * ) PvRecordFind( unKey );
- Assert( pvRemove );
- if ( !pvRemove )
- return;
- Remove( pvRemove );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Removes the specified entry from the table
-// Input: pvRemove - Pointer to the entry to remove
-//-----------------------------------------------------------------------------
-template<class Data, class I>
-void CTHash<Data,I>::Remove( Data * pvRemove )
-{
- // Destruct the record we're removing
- Destruct<Data>( pvRemove );
-
- RemoveFromHash( pvRemove );
- m_pMemoryPoolRecord->Free( PRecHdrFromPvRecord( pvRemove ) );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Removes all entries from the table
-//-----------------------------------------------------------------------------
-template<class Data, class I>
-void CTHash<Data,I>::RemoveAll()
-{
- Data * pvRecord = PvRecordFirst();
- while ( pvRecord )
- {
- Data *pvRecordNext = PvRecordNext( pvRecord );
- Remove( pvRecord );
- pvRecord = pvRecordNext;
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Finds the entry with a specified key
-// Input: unKey - Key to find
-//-----------------------------------------------------------------------------
-template<class Data, class I>
-Data *CTHash<Data,I>::PvRecordFind( I unKey ) const
-{
- // Find our hash bucket
- int iBucket = IBucket( unKey );
-
- // Walk the bucket's list looking for an exact match
- for ( RecHdr_t *pRecHdr = m_pBucket[iBucket].m_pRecHdrFirst;
- NULL != pRecHdr && pRecHdr->m_iBucket == iBucket;
- pRecHdr = pRecHdr->m_pRecHdrNext )
- {
- if ( unKey == pRecHdr->m_unKey )
- return PvRecordFromPRecHdr( pRecHdr );
- }
-
- // Didn't find a match
- return NULL;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Finds our first record
-// Output: Pointer to our first record
-//-----------------------------------------------------------------------------
-template<class Data, class I>
-Data *CTHash<Data,I>::PvRecordFirst() const
-{
- if ( &m_RecHdrTail != m_RecHdrHead.m_pRecHdrNext )
- return PvRecordFromPRecHdr( m_RecHdrHead.m_pRecHdrNext );
- else
- return NULL;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Iterates to the record after a given record
-// Input: Pointer to a current record
-// Output: Pointer to the next record
-//-----------------------------------------------------------------------------
-template<class Data, class I>
-Data *CTHash<Data,I>::PvRecordNext( Data *pvRecordCur ) const
-{
- RecHdr_t *pRecHdr = PRecHdrFromPvRecord( pvRecordCur );
- if ( &m_RecHdrTail == pRecHdr->m_pRecHdrNext )
- return NULL;
-
- return PvRecordFromPRecHdr( pRecHdr->m_pRecHdrNext );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Sets the run ratio of a particular record in the hash table.
-// The record will be run 1 cycle out of every nRunRatio cycles.
-// Input: pvRecord - The record we're setting
-// nRunRatio - The run ratio for this record
-//-----------------------------------------------------------------------------
-template<class Data, class I>
-void CTHash<Data,I>::SetRunRatio( Data *pvRecord, int nRunRatio )
-{
- PRecHdrFromPvRecord( pvRecord )->m_nRunRatio = nRunRatio;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Prepares us to run all records that are due to be run this frame.
-// Records are run at a particular time dependent on their hash bucket,
-// regardless of when they were last run.
-// Input: bNewFrame - True if this is a new frame. If false, we've run
-// off the end of the list and are checking whether
-// we need to keep going at the beginning.
-//-----------------------------------------------------------------------------
-template<class Data, class I>
-void CTHash<Data,I>::StartFrameSchedule( bool bNewFrame )
-{
- // Calculate our current frame and cycle cycle
- if ( bNewFrame )
- {
- m_iCycleLast = m_iCycleCur;
- m_iFrameCur++;
- m_iCycleCur = m_iFrameCur / m_cFramesPerCycle;
- }
-
- // Calculate the last bucket to run
- int iFrameInCycle = m_iFrameCur % m_cFramesPerCycle;
- m_iBucketRunMax = ( int ) ( ( ( int64 ) ( iFrameInCycle + 1 ) * ( int64 ) m_cBucket )
- / ( int64 ) m_cFramesPerCycle );
- AssertFatal( m_iBucketRunMax >= 0 && m_iBucketRunMax <= m_cBucket );
-
- // Are we starting a new cycle?
- if ( m_iCycleCur > m_iCycleLast )
- {
-#ifdef DBGFLAG_THASH
- Assert( m_iCycleCur == m_iCycleLast + 1 );
-#endif
-
- // Did we finish the last cycle?
- if ( &m_RecHdrTail == m_pRecHdrRunNext )
- {
- m_pRecHdrRunNext = m_RecHdrHead.m_pRecHdrNext;
- }
- // No-- finish it up before moving on
- else
- {
- m_iBucketRunMax = m_cBucket + 1;
- }
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Returns the next record to run, if any
-// Output: Pointer to the next record that needs to run (NULL if we're done)
-//-----------------------------------------------------------------------------
-template<class Data, class I>
-Data *CTHash<Data,I>::PvRecordRun()
-{
- // Loop until we find a record to run, or until we pass m_iBucketRunMax
- for ( ; ; )
- {
- // Are we past our stopping point?
- if ( m_pRecHdrRunNext->m_iBucket >= m_iBucketRunMax )
- {
- // If this cycle ran to the very end, see if we need to start over
- if ( m_iBucketRunMax > m_cBucket )
- {
- StartFrameSchedule( false );
- continue;
- }
-
- return NULL;
- }
-
-#ifdef DBGFLAG_THASH
- Assert( m_pRecHdrRunNext->m_iBucket >= m_iBucketRunFirst );
- if ( 0 != m_pRecHdrRunNext->m_iCycleLast )
- {
- if ( m_pRecHdrRunNext->m_iCycleLast == m_iCycleCur )
- {
- DMsg( SPEW_CONSOLE, 1, "Double cycle: hdr = 0x%x, last frame = %d, curFrame = %d, first = %d, last = %d, bucket = %d\n",
- m_pRecHdrRunNext, m_pRecHdrRunNext->m_iFrameLast, m_iFrame,
- m_iBucketRunFirst, m_iBucketRunMax, m_pRecHdrRunNext->m_iBucket );
- }
- else if ( m_pRecHdrRunNext->m_iCycleLast != m_iCycleCur - 1 )
- {
- DMsg( SPEW_CONSOLE, 1, "Skipped cycle: hdr = 0x%x, cycleLast = %u, cycleCur = %u (missed %u cycles)\n",
- m_pRecHdrRunNext, m_pRecHdrRunNext->m_iCycleLast, m_iCycleCur,
- m_iCycleCur - m_pRecHdrRunNext->m_iCycleLast );
- Assert( false );
- }
- }
- m_pRecHdrRunNext->m_iCycleLast = m_iCycleCur;
- m_pRecHdrRunNext->m_iFrameLast = m_iFrame;
-#endif
-
- // Set up the record to run next time
- RecHdr_t *pRecHdrCur = m_pRecHdrRunNext;
- m_pRecHdrRunNext = m_pRecHdrRunNext->m_pRecHdrNext;
-
- // Does this record need to run?
- if ( 0 == pRecHdrCur->m_nRunRatio )
- continue;
-
- if ( 0 == m_iCycleCur % pRecHdrCur->m_nRunRatio )
- return PvRecordFromPRecHdr( pRecHdrCur );
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Return true if we've completed a scheduler pass since last called
-//-----------------------------------------------------------------------------
-template<class Data, class I>
-bool CTHash<Data,I>::BCompletedPass()
-{
- if ( m_iCycleCur != m_iCycleLastReported )
- {
- m_iCycleLastReported = m_iCycleCur;
- return true;
- }
- return false;
-}
-
-
-extern const unsigned char g_CTHashRandomValues[256]; // definition lives in globals.cpp
-
-//-----------------------------------------------------------------------------
-// Purpose: Returns the index of the hash bucket corresponding to a particular key
-// Input: unKey - Key to find
-// Output: Index of the hash bucket corresponding to unKey
-//-----------------------------------------------------------------------------
-template<class Data, class I>
-int CTHash<Data,I>::IBucket( I unKey ) const
-{
- AssertFatal( m_cBucket > 0 );
-
- // This is a pearsons hash variant that returns a maximum of 32 bits
- size_t size = sizeof(I);
- const uint8 * k = (const uint8 *) &unKey;
- uint32 byte_one = 0, byte_two = 0, byte_three = 0, byte_four = 0, n;
-
- while (size)
- {
- --size;
- n = *k++;
- byte_one = g_CTHashRandomValues[byte_one ^ n];
-
- if (size)
- {
- --size;
- n = *k++;
- byte_two = g_CTHashRandomValues[byte_two ^ n];
- }
- else
- break;
-
- if (size)
- {
- --size;
- n = *k++;
- byte_three = g_CTHashRandomValues[byte_three ^ n];
- }
- else
- break;
-
- if (size)
- {
- --size;
- n = *k++;
- byte_four = g_CTHashRandomValues[byte_four ^ n];
- }
- else
- break;
- }
-
- uint32 idx = ( byte_four << 24 ) | ( byte_three << 16 ) | ( byte_two << 8 ) | byte_one;
- idx = idx % m_cBucket;
- return ( (int) idx );
-}
-
-
-#ifdef DBGFLAG_VALIDATE
-//-----------------------------------------------------------------------------
-// Purpose: Run a global validation pass on all of our data structures and memory
-// allocations.
-// Input: validator - Our global validator object
-// pchName - Our name (typically a member var in our container)
-//-----------------------------------------------------------------------------
-template<class Data, class I>
-void CTHash<Data,I>::Validate( CValidator &validator, const char *pchName )
-{
- VALIDATE_SCOPE();
-
- validator.ClaimMemory( m_pBucket );
- ValidatePtr( m_pMemoryPoolRecord );
-
-#if defined( _DEBUG )
- // first verify m_cRecordInUse
- Data * pvRecord = PvRecordFirst();
- int cItems = 0;
- while ( pvRecord )
- {
- Data *pvRecordNext = PvRecordNext( pvRecord );
- cItems++;
- pvRecord = pvRecordNext;
- }
- Assert( m_cRecordInUse == cItems );
- // then ask the mempool to verify this
- if ( m_pMemoryPoolRecord )
- m_pMemoryPoolRecord->LeakCheck( cItems );
-#endif // _DEBUG
-}
-#endif // DBGFLAG_VALIDATE
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Inserts a new record into the table
-// Input: unKey - Primary key of the new record
-// Output: Pointer to the new record
-//-----------------------------------------------------------------------------
-template<class Data, class I>
-void CTHash<Data,I>::InsertIntoHash( RecHdr_t *pRecHdr, I unKey )
-{
- m_cRecordInUse++;
-
- // Init the RecHdr
- pRecHdr->m_unKey = unKey;
- pRecHdr->m_nRunRatio = 1;
-
- // Find our hash bucket
- int iBucket = IBucket( unKey );
- pRecHdr->m_iBucket = iBucket;
-#ifdef DBGFLAG_THASH
- pRecHdr->m_iCycleLast = 0;
-#endif
-
- // Find where to insert ourselves in the linked list
- RecHdr_t *pRecHdrInsertBefore = &m_RecHdrTail;
- // Find the first bucket with anything in it that's at or after our bucket
- for ( int iBucketT = iBucket; iBucketT < m_cBucket; iBucketT++ )
- {
- if ( NULL != m_pBucket[iBucketT].m_pRecHdrFirst )
- {
- pRecHdrInsertBefore = m_pBucket[iBucketT].m_pRecHdrFirst;
- break;
- }
- }
-
- // Insert ourselves
- pRecHdr->m_pRecHdrNext = pRecHdrInsertBefore;
- pRecHdr->m_pRecHdrPrev = pRecHdrInsertBefore->m_pRecHdrPrev;
- pRecHdrInsertBefore->m_pRecHdrPrev = pRecHdr;
- pRecHdr->m_pRecHdrPrev->m_pRecHdrNext = pRecHdr;
-
- // Our bucket should point to us
- m_pBucket[iBucket].m_pRecHdrFirst = pRecHdr;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Removes the specified entry from the table
-// Input: pvRemove - Pointer to the entry to remove
-//-----------------------------------------------------------------------------
-template<class Data, class I>
-void CTHash<Data,I>::RemoveFromHash( Data * pvRemove )
-{
- // Find our RecHdr
- RecHdr_t *pRecHdr = PRecHdrFromPvRecord( pvRemove );
-
- // If our bucket points to us, point it to the next record (or else NULL)
- int iBucket = IBucket( pRecHdr->m_unKey );
- if ( pRecHdr == m_pBucket[iBucket].m_pRecHdrFirst )
- {
- if ( pRecHdr->m_pRecHdrNext->m_iBucket == iBucket )
- m_pBucket[iBucket].m_pRecHdrFirst = pRecHdr->m_pRecHdrNext;
- else
- m_pBucket[iBucket].m_pRecHdrFirst = NULL;
- }
-
- // Remove us from the linked list
- pRecHdr->m_pRecHdrPrev->m_pRecHdrNext = pRecHdr->m_pRecHdrNext;
- pRecHdr->m_pRecHdrNext->m_pRecHdrPrev = pRecHdr->m_pRecHdrPrev;
-
- // Are we the next record to run?
- if ( pRecHdr == m_pRecHdrRunNext )
- m_pRecHdrRunNext = pRecHdr->m_pRecHdrNext;
-
- m_cRecordInUse--;
-}
-
-#endif // THASH_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================
+
+#ifndef THASH_H
+#define THASH_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include <typeinfo>
+
+//#define DBGFLAG_THASH // Perform extra sanity checks on the THash
+
+
+// THash
+// This is a heavyweight, templatized version of DHash.
+// It differs from DHash in the following ways:
+// - It's templetized, and automatically constructs and destructs its records as appropriate
+// - It provides a scheduling service, which can be used to touch every record in the table
+// at a specified interval. The scheduler is low-overhead, and provides a very smooth
+// distribution of touches across frames.
+
+// Template arguments:
+// Data: the class to be stored in the hash table
+// I: the type of the primary key (uint32 by default)
+template<class Data, typename I=uint32>
+class CTHash
+{
+private:
+ // RecHdr
+ // We insert one of these at the beginning of every record. It's used for
+ // keeping the records in a linked list.
+ typedef struct RecHdr_t
+ {
+ RecHdr_t *m_pRecHdrNext; // Next item in our linked list
+ RecHdr_t *m_pRecHdrPrev; // Previous item in our linked list
+ I m_unKey; // Key of this item
+ int m_iBucket; // The bucket we're in
+ int m_nRunRatio; // We want to run 1 cycle out of every m_nRunRatio
+ // cycles (not at all if 0).
+#ifdef DBGFLAG_THASH
+ uint m_iCycleLast; // Last cycle we were visited (whether or not we ran)
+#endif
+ } RecHdr_t;
+
+ // Bucket
+ // Each hash bucket is represented by a Bucket structure, which points to the
+ // first record with the bucket's hash.
+ typedef struct Bucket_t
+ {
+ RecHdr_t *m_pRecHdrFirst; // First record in our list
+ } Bucket_t;
+
+
+public:
+ // Constructors & destructors
+ CTHash( int cFramesPerCycle );
+ ~CTHash();
+
+ // Initializer
+ void Init( int cRecordInit, int cBuckets );
+
+ // Insert a record into the table
+ Data *PvRecordInsert( I unKey );
+ // Insert a record into the table and set the allocated object's pointer as the hash key
+ Data *PvRecordInsertAutoKey();
+ // Changes the key for a previously inserted item
+ void ChangeKey( Data * pvRecord, I unOldKey, I unNewKey );
+
+ // Remove a record
+ void Remove( I unKey );
+ // Remove a record
+ void Remove( Data * pvRecord );
+ // Remove all records
+ void RemoveAll();
+
+ // Find a record
+ Data *PvRecordFind( I unKey ) const;
+
+ // How many records do we have
+ int Count() const { return m_cRecordInUse; }
+
+ // Iterate through our members
+ Data *PvRecordFirst() const;
+ Data *PvRecordNext( Data *pvRecordCur ) const;
+
+ // We provide a scheduling service. Call StartFrameSchedule when you want to start running
+ // records in a given frame, and repeatedly call PvRecordRun until it returns NULL (or you
+ // run our of time).
+ void SetRunRatio( Data *pvRecord, int nRunRatio );
+ void SetMicroSecPerCycle( int cMicroSecPerCycle, int cMicroSecPerFrame ) { m_cFramesPerCycle = cMicroSecPerCycle / cMicroSecPerFrame; }
+ void StartFrameSchedule( bool bNewFrame );
+ Data *PvRecordRun();
+
+ bool BCompletedPass();
+
+#ifdef DBGFLAG_VALIDATE
+ virtual void Validate( CValidator &validator, const char *pchName );
+#endif // DBGFLAG_VALIDATE
+
+
+private:
+ // Insert a record into the table
+ Data *PvRecordInsertInternal( RecHdr_t *pRecHdr, I unKey );
+
+ // Get the record associated with a THashHdr
+ Data *PvRecordFromPRecHdr( RecHdr_t *pRecHdr ) const { return ( Data * ) ( ( ( uint8 * ) pRecHdr + sizeof( RecHdr_t ) ) ); }
+
+ // Get the RecHdr preceding a PvRecord
+ RecHdr_t *PRecHdrFromPvRecord( Data *pvRecord ) const { return ( ( ( RecHdr_t * ) pvRecord ) - 1 ); }
+
+ // Get the hash bucket corresponding to a key
+ int IBucket( I unKey ) const;
+
+ void InsertIntoHash( RecHdr_t *pRecHdr, I unKey );
+ void RemoveFromHash( Data * pvRecord );
+
+ int m_cBucket; // # of hash buckets we have
+ Bucket_t *m_pBucket; // Big array of hash buckets
+
+ CUtlMemoryPool *m_pMemoryPoolRecord; // All our data records
+
+ int m_cRecordInUse; // # of records in use
+ RecHdr_t m_RecHdrHead; // Head of our linked list
+ RecHdr_t m_RecHdrTail; // Tail of our linked list
+
+ int m_cFramesPerCycle; // Run each of our records once every m_cFramesPerCycle frames
+ RecHdr_t *m_pRecHdrRunNext; // Next record to run (be careful-- this is more complicated than it sounds)
+ int m_iBucketRunMax; // Stop running when we get to this bucket
+ uint m_iCycleCur; // Current cycle (ie, how many times we've made a complete scheduler pass)
+ uint m_iCycleLast; // Our previous cycle
+ uint m_iFrameCur; // Our current frame (incremented once each StartFrameSchedule)
+ uint m_iCycleLastReported; // Last cycle checked by BCompletedPass()
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+// Input: cMicroSecRunInterval - How often we want the scheduler to run each of our records
+//-----------------------------------------------------------------------------
+template<class Data, class I>
+CTHash<Data,I>::CTHash( int cFramesPerCycle )
+{
+ m_cBucket = 0;
+ m_pBucket = NULL;
+ m_pMemoryPoolRecord = NULL;
+ m_cRecordInUse = 0;
+
+ m_cFramesPerCycle = cFramesPerCycle;
+ m_pRecHdrRunNext = &m_RecHdrTail; // This will make us start at the beginning on our first frame
+ m_iBucketRunMax = 0;
+ m_iCycleCur = 0;
+ m_iCycleLast = 0;
+ m_iFrameCur = 0;
+ m_iCycleLastReported = 0;
+
+ m_RecHdrHead.m_pRecHdrPrev = NULL;
+ m_RecHdrHead.m_pRecHdrNext = &m_RecHdrTail;
+ m_RecHdrHead.m_iBucket = -1;
+
+ m_RecHdrTail.m_pRecHdrPrev = &m_RecHdrHead;
+ m_RecHdrTail.m_pRecHdrNext = NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Destructor
+//-----------------------------------------------------------------------------
+template<class Data, class I>
+CTHash<Data,I>::~CTHash()
+{
+ RemoveAll();
+
+ if ( NULL != m_pBucket )
+ FreePv( m_pBucket );
+ m_pBucket = NULL;
+
+ if ( NULL != m_pMemoryPoolRecord )
+ delete( m_pMemoryPoolRecord );
+ m_pMemoryPoolRecord = NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Initializer. Allocate our various arrays, and set up the free
+// list.
+// Input: cRecordInit - Initial # of data records we can contain
+// cBucket - # of hash buckets we should use
+//-----------------------------------------------------------------------------
+template<class Data, class I>
+void CTHash<Data,I>::Init( int cRecordInit, int cBucket )
+{
+ Assert( cRecordInit > 0 ); // need to init with non-zero value or memory pool will never grow
+
+ // Copy our parameters
+ m_cBucket = cBucket;
+
+ // Alloc our arrays
+ m_pBucket = ( Bucket_t * ) PvAlloc( sizeof( Bucket_t ) * m_cBucket );
+ m_pMemoryPoolRecord = new CUtlMemoryPool( sizeof( Data ) + sizeof( RecHdr_t ), cRecordInit,
+ CUtlMemoryPool::GROW_SLOW );
+
+ // Init the hash buckets
+ for ( int iBucket = 0; iBucket < m_cBucket; iBucket++ )
+ m_pBucket[iBucket].m_pRecHdrFirst = NULL;
+
+ // Make the tail have an illegally large bucket
+ m_RecHdrTail.m_iBucket = m_cBucket + 1;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Inserts a new record into the table
+// Input: unKey - Primary key of the new record
+// Output: Pointer to the new record
+//-----------------------------------------------------------------------------
+template<class Data, class I>
+Data *CTHash<Data,I>::PvRecordInsert( I unKey )
+{
+ Assert( PvRecordFind( unKey ) == NULL ); // keys are unique; no record with this key may exist
+
+ // Find a free record
+ RecHdr_t *pRecHdr = ( RecHdr_t * ) m_pMemoryPoolRecord->Alloc();
+
+ return PvRecordInsertInternal( pRecHdr, unKey );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Inserts a new record into the table and sets its key to the pointer
+// value of the record
+// Output: Pointer to the new record
+//-----------------------------------------------------------------------------
+template<class Data, class I>
+Data *CTHash<Data,I>::PvRecordInsertAutoKey()
+{
+ // Find a free record
+ RecHdr_t *pRecHdr = ( RecHdr_t * ) m_pMemoryPoolRecord->Alloc();
+
+ return PvRecordInsertInternal( pRecHdr, (I) PvRecordFromPRecHdr( pRecHdr ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Inserts an allocated record into the hash table with specified key
+// and calls the constructor of the allocated object
+// Input: pRecHdr - record to insert
+// unKey - hash key to use for record
+// Output: Pointer to the new record
+//-----------------------------------------------------------------------------
+template<class Data, class I>
+Data *CTHash<Data,I>::PvRecordInsertInternal( RecHdr_t *pRecHdr, I unKey )
+{
+ InsertIntoHash( pRecHdr, unKey );
+
+ // assert that we don't have too many items per bucket
+ static bool s_bPerfWarning = false;
+ if ( !s_bPerfWarning && Count() >= ( 5 * m_cBucket ) )
+ {
+ s_bPerfWarning = true;
+ AssertMsg( false, "Performance warning: too many items, not enough buckets" );
+ Msg( "not enough buckets in thash class %s (%d records, %d buckets)\n",
+#ifdef _WIN32
+ typeid(*this).raw_name(),
+#else
+ typeid(*this).name(),
+#endif
+ Count(), m_cBucket );
+ }
+
+ // Construct ourselves
+ Data *pData = PvRecordFromPRecHdr( pRecHdr );
+ Construct<Data>( pData );
+ return pData;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Changes key on previously inserted item
+// Input: pvRecord - record to change key for
+// unOldKey - old key (not strictly needed, but helpful consistency check)
+// unNewKey - new key to use
+//-----------------------------------------------------------------------------
+template<class Data, class I>
+void CTHash<Data,I>::ChangeKey( Data * pvRecord, I unOldKey, I unNewKey )
+{
+ Data * pvRecordFound = PvRecordFind( unOldKey );
+ Assert( pvRecordFound == pvRecord );
+ if ( pvRecordFound == pvRecord )
+ {
+ RemoveFromHash( pvRecord );
+ InsertIntoHash( PRecHdrFromPvRecord( pvRecord), unNewKey );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Removes the entry with a specified key from the table
+// Input: unKey - Key of the entry to remove
+//-----------------------------------------------------------------------------
+template<class Data, class I>
+void CTHash<Data,I>::Remove( I unKey )
+{
+ Data *pvRemove = ( Data * ) PvRecordFind( unKey );
+ Assert( pvRemove );
+ if ( !pvRemove )
+ return;
+ Remove( pvRemove );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Removes the specified entry from the table
+// Input: pvRemove - Pointer to the entry to remove
+//-----------------------------------------------------------------------------
+template<class Data, class I>
+void CTHash<Data,I>::Remove( Data * pvRemove )
+{
+ // Destruct the record we're removing
+ Destruct<Data>( pvRemove );
+
+ RemoveFromHash( pvRemove );
+ m_pMemoryPoolRecord->Free( PRecHdrFromPvRecord( pvRemove ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Removes all entries from the table
+//-----------------------------------------------------------------------------
+template<class Data, class I>
+void CTHash<Data,I>::RemoveAll()
+{
+ Data * pvRecord = PvRecordFirst();
+ while ( pvRecord )
+ {
+ Data *pvRecordNext = PvRecordNext( pvRecord );
+ Remove( pvRecord );
+ pvRecord = pvRecordNext;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Finds the entry with a specified key
+// Input: unKey - Key to find
+//-----------------------------------------------------------------------------
+template<class Data, class I>
+Data *CTHash<Data,I>::PvRecordFind( I unKey ) const
+{
+ // Find our hash bucket
+ int iBucket = IBucket( unKey );
+
+ // Walk the bucket's list looking for an exact match
+ for ( RecHdr_t *pRecHdr = m_pBucket[iBucket].m_pRecHdrFirst;
+ NULL != pRecHdr && pRecHdr->m_iBucket == iBucket;
+ pRecHdr = pRecHdr->m_pRecHdrNext )
+ {
+ if ( unKey == pRecHdr->m_unKey )
+ return PvRecordFromPRecHdr( pRecHdr );
+ }
+
+ // Didn't find a match
+ return NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Finds our first record
+// Output: Pointer to our first record
+//-----------------------------------------------------------------------------
+template<class Data, class I>
+Data *CTHash<Data,I>::PvRecordFirst() const
+{
+ if ( &m_RecHdrTail != m_RecHdrHead.m_pRecHdrNext )
+ return PvRecordFromPRecHdr( m_RecHdrHead.m_pRecHdrNext );
+ else
+ return NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Iterates to the record after a given record
+// Input: Pointer to a current record
+// Output: Pointer to the next record
+//-----------------------------------------------------------------------------
+template<class Data, class I>
+Data *CTHash<Data,I>::PvRecordNext( Data *pvRecordCur ) const
+{
+ RecHdr_t *pRecHdr = PRecHdrFromPvRecord( pvRecordCur );
+ if ( &m_RecHdrTail == pRecHdr->m_pRecHdrNext )
+ return NULL;
+
+ return PvRecordFromPRecHdr( pRecHdr->m_pRecHdrNext );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Sets the run ratio of a particular record in the hash table.
+// The record will be run 1 cycle out of every nRunRatio cycles.
+// Input: pvRecord - The record we're setting
+// nRunRatio - The run ratio for this record
+//-----------------------------------------------------------------------------
+template<class Data, class I>
+void CTHash<Data,I>::SetRunRatio( Data *pvRecord, int nRunRatio )
+{
+ PRecHdrFromPvRecord( pvRecord )->m_nRunRatio = nRunRatio;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Prepares us to run all records that are due to be run this frame.
+// Records are run at a particular time dependent on their hash bucket,
+// regardless of when they were last run.
+// Input: bNewFrame - True if this is a new frame. If false, we've run
+// off the end of the list and are checking whether
+// we need to keep going at the beginning.
+//-----------------------------------------------------------------------------
+template<class Data, class I>
+void CTHash<Data,I>::StartFrameSchedule( bool bNewFrame )
+{
+ // Calculate our current frame and cycle cycle
+ if ( bNewFrame )
+ {
+ m_iCycleLast = m_iCycleCur;
+ m_iFrameCur++;
+ m_iCycleCur = m_iFrameCur / m_cFramesPerCycle;
+ }
+
+ // Calculate the last bucket to run
+ int iFrameInCycle = m_iFrameCur % m_cFramesPerCycle;
+ m_iBucketRunMax = ( int ) ( ( ( int64 ) ( iFrameInCycle + 1 ) * ( int64 ) m_cBucket )
+ / ( int64 ) m_cFramesPerCycle );
+ AssertFatal( m_iBucketRunMax >= 0 && m_iBucketRunMax <= m_cBucket );
+
+ // Are we starting a new cycle?
+ if ( m_iCycleCur > m_iCycleLast )
+ {
+#ifdef DBGFLAG_THASH
+ Assert( m_iCycleCur == m_iCycleLast + 1 );
+#endif
+
+ // Did we finish the last cycle?
+ if ( &m_RecHdrTail == m_pRecHdrRunNext )
+ {
+ m_pRecHdrRunNext = m_RecHdrHead.m_pRecHdrNext;
+ }
+ // No-- finish it up before moving on
+ else
+ {
+ m_iBucketRunMax = m_cBucket + 1;
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the next record to run, if any
+// Output: Pointer to the next record that needs to run (NULL if we're done)
+//-----------------------------------------------------------------------------
+template<class Data, class I>
+Data *CTHash<Data,I>::PvRecordRun()
+{
+ // Loop until we find a record to run, or until we pass m_iBucketRunMax
+ for ( ; ; )
+ {
+ // Are we past our stopping point?
+ if ( m_pRecHdrRunNext->m_iBucket >= m_iBucketRunMax )
+ {
+ // If this cycle ran to the very end, see if we need to start over
+ if ( m_iBucketRunMax > m_cBucket )
+ {
+ StartFrameSchedule( false );
+ continue;
+ }
+
+ return NULL;
+ }
+
+#ifdef DBGFLAG_THASH
+ Assert( m_pRecHdrRunNext->m_iBucket >= m_iBucketRunFirst );
+ if ( 0 != m_pRecHdrRunNext->m_iCycleLast )
+ {
+ if ( m_pRecHdrRunNext->m_iCycleLast == m_iCycleCur )
+ {
+ DMsg( SPEW_CONSOLE, 1, "Double cycle: hdr = 0x%x, last frame = %d, curFrame = %d, first = %d, last = %d, bucket = %d\n",
+ m_pRecHdrRunNext, m_pRecHdrRunNext->m_iFrameLast, m_iFrame,
+ m_iBucketRunFirst, m_iBucketRunMax, m_pRecHdrRunNext->m_iBucket );
+ }
+ else if ( m_pRecHdrRunNext->m_iCycleLast != m_iCycleCur - 1 )
+ {
+ DMsg( SPEW_CONSOLE, 1, "Skipped cycle: hdr = 0x%x, cycleLast = %u, cycleCur = %u (missed %u cycles)\n",
+ m_pRecHdrRunNext, m_pRecHdrRunNext->m_iCycleLast, m_iCycleCur,
+ m_iCycleCur - m_pRecHdrRunNext->m_iCycleLast );
+ Assert( false );
+ }
+ }
+ m_pRecHdrRunNext->m_iCycleLast = m_iCycleCur;
+ m_pRecHdrRunNext->m_iFrameLast = m_iFrame;
+#endif
+
+ // Set up the record to run next time
+ RecHdr_t *pRecHdrCur = m_pRecHdrRunNext;
+ m_pRecHdrRunNext = m_pRecHdrRunNext->m_pRecHdrNext;
+
+ // Does this record need to run?
+ if ( 0 == pRecHdrCur->m_nRunRatio )
+ continue;
+
+ if ( 0 == m_iCycleCur % pRecHdrCur->m_nRunRatio )
+ return PvRecordFromPRecHdr( pRecHdrCur );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Return true if we've completed a scheduler pass since last called
+//-----------------------------------------------------------------------------
+template<class Data, class I>
+bool CTHash<Data,I>::BCompletedPass()
+{
+ if ( m_iCycleCur != m_iCycleLastReported )
+ {
+ m_iCycleLastReported = m_iCycleCur;
+ return true;
+ }
+ return false;
+}
+
+
+extern const unsigned char g_CTHashRandomValues[256]; // definition lives in globals.cpp
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the index of the hash bucket corresponding to a particular key
+// Input: unKey - Key to find
+// Output: Index of the hash bucket corresponding to unKey
+//-----------------------------------------------------------------------------
+template<class Data, class I>
+int CTHash<Data,I>::IBucket( I unKey ) const
+{
+ AssertFatal( m_cBucket > 0 );
+
+ // This is a pearsons hash variant that returns a maximum of 32 bits
+ size_t size = sizeof(I);
+ const uint8 * k = (const uint8 *) &unKey;
+ uint32 byte_one = 0, byte_two = 0, byte_three = 0, byte_four = 0, n;
+
+ while (size)
+ {
+ --size;
+ n = *k++;
+ byte_one = g_CTHashRandomValues[byte_one ^ n];
+
+ if (size)
+ {
+ --size;
+ n = *k++;
+ byte_two = g_CTHashRandomValues[byte_two ^ n];
+ }
+ else
+ break;
+
+ if (size)
+ {
+ --size;
+ n = *k++;
+ byte_three = g_CTHashRandomValues[byte_three ^ n];
+ }
+ else
+ break;
+
+ if (size)
+ {
+ --size;
+ n = *k++;
+ byte_four = g_CTHashRandomValues[byte_four ^ n];
+ }
+ else
+ break;
+ }
+
+ uint32 idx = ( byte_four << 24 ) | ( byte_three << 16 ) | ( byte_two << 8 ) | byte_one;
+ idx = idx % m_cBucket;
+ return ( (int) idx );
+}
+
+
+#ifdef DBGFLAG_VALIDATE
+//-----------------------------------------------------------------------------
+// Purpose: Run a global validation pass on all of our data structures and memory
+// allocations.
+// Input: validator - Our global validator object
+// pchName - Our name (typically a member var in our container)
+//-----------------------------------------------------------------------------
+template<class Data, class I>
+void CTHash<Data,I>::Validate( CValidator &validator, const char *pchName )
+{
+ VALIDATE_SCOPE();
+
+ validator.ClaimMemory( m_pBucket );
+ ValidatePtr( m_pMemoryPoolRecord );
+
+#if defined( _DEBUG )
+ // first verify m_cRecordInUse
+ Data * pvRecord = PvRecordFirst();
+ int cItems = 0;
+ while ( pvRecord )
+ {
+ Data *pvRecordNext = PvRecordNext( pvRecord );
+ cItems++;
+ pvRecord = pvRecordNext;
+ }
+ Assert( m_cRecordInUse == cItems );
+ // then ask the mempool to verify this
+ if ( m_pMemoryPoolRecord )
+ m_pMemoryPoolRecord->LeakCheck( cItems );
+#endif // _DEBUG
+}
+#endif // DBGFLAG_VALIDATE
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Inserts a new record into the table
+// Input: unKey - Primary key of the new record
+// Output: Pointer to the new record
+//-----------------------------------------------------------------------------
+template<class Data, class I>
+void CTHash<Data,I>::InsertIntoHash( RecHdr_t *pRecHdr, I unKey )
+{
+ m_cRecordInUse++;
+
+ // Init the RecHdr
+ pRecHdr->m_unKey = unKey;
+ pRecHdr->m_nRunRatio = 1;
+
+ // Find our hash bucket
+ int iBucket = IBucket( unKey );
+ pRecHdr->m_iBucket = iBucket;
+#ifdef DBGFLAG_THASH
+ pRecHdr->m_iCycleLast = 0;
+#endif
+
+ // Find where to insert ourselves in the linked list
+ RecHdr_t *pRecHdrInsertBefore = &m_RecHdrTail;
+ // Find the first bucket with anything in it that's at or after our bucket
+ for ( int iBucketT = iBucket; iBucketT < m_cBucket; iBucketT++ )
+ {
+ if ( NULL != m_pBucket[iBucketT].m_pRecHdrFirst )
+ {
+ pRecHdrInsertBefore = m_pBucket[iBucketT].m_pRecHdrFirst;
+ break;
+ }
+ }
+
+ // Insert ourselves
+ pRecHdr->m_pRecHdrNext = pRecHdrInsertBefore;
+ pRecHdr->m_pRecHdrPrev = pRecHdrInsertBefore->m_pRecHdrPrev;
+ pRecHdrInsertBefore->m_pRecHdrPrev = pRecHdr;
+ pRecHdr->m_pRecHdrPrev->m_pRecHdrNext = pRecHdr;
+
+ // Our bucket should point to us
+ m_pBucket[iBucket].m_pRecHdrFirst = pRecHdr;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Removes the specified entry from the table
+// Input: pvRemove - Pointer to the entry to remove
+//-----------------------------------------------------------------------------
+template<class Data, class I>
+void CTHash<Data,I>::RemoveFromHash( Data * pvRemove )
+{
+ // Find our RecHdr
+ RecHdr_t *pRecHdr = PRecHdrFromPvRecord( pvRemove );
+
+ // If our bucket points to us, point it to the next record (or else NULL)
+ int iBucket = IBucket( pRecHdr->m_unKey );
+ if ( pRecHdr == m_pBucket[iBucket].m_pRecHdrFirst )
+ {
+ if ( pRecHdr->m_pRecHdrNext->m_iBucket == iBucket )
+ m_pBucket[iBucket].m_pRecHdrFirst = pRecHdr->m_pRecHdrNext;
+ else
+ m_pBucket[iBucket].m_pRecHdrFirst = NULL;
+ }
+
+ // Remove us from the linked list
+ pRecHdr->m_pRecHdrPrev->m_pRecHdrNext = pRecHdr->m_pRecHdrNext;
+ pRecHdr->m_pRecHdrNext->m_pRecHdrPrev = pRecHdr->m_pRecHdrPrev;
+
+ // Are we the next record to run?
+ if ( pRecHdr == m_pRecHdrRunNext )
+ m_pRecHdrRunNext = pRecHdr->m_pRecHdrNext;
+
+ m_cRecordInUse--;
+}
+
+#endif // THASH_H
diff --git a/mp/src/public/tier1/tier1.h b/mp/src/public/tier1/tier1.h
index 7e48c3c3..ac790673 100644
--- a/mp/src/public/tier1/tier1.h
+++ b/mp/src/public/tier1/tier1.h
@@ -1,106 +1,106 @@
-//========= Copyright 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
-//-----------------------------------------------------------------------------
-class ICvar;
-class IProcessUtils;
-
-
-//-----------------------------------------------------------------------------
-// These tier1 libraries must be set by any users of this library.
-// They can be set by calling ConnectTier1Libraries.
-// It is hoped that setting this, and using this library will be the common mechanism for
-// allowing link libraries to access tier1 library interfaces
-//-----------------------------------------------------------------------------
-
-// These are marked DLL_EXPORT for Linux.
-DLL_EXPORT ICvar *cvar;
-extern ICvar *g_pCVar;
-extern IProcessUtils *g_pProcessUtils;
-
-
-//-----------------------------------------------------------------------------
-// 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:
- CTier1AppSystem( bool bIsPrimaryAppSystem = true ) : BaseClass( bIsPrimaryAppSystem )
- {
- }
-
- virtual bool Connect( CreateInterfaceFn factory )
- {
- if ( !BaseClass::Connect( factory ) )
- return false;
-
- if ( BaseClass::IsPrimaryAppSystem() )
- {
- ConnectTier1Libraries( &factory, 1 );
- }
- return true;
- }
-
- virtual void Disconnect()
- {
- if ( BaseClass::IsPrimaryAppSystem() )
- {
- DisconnectTier1Libraries();
- }
- BaseClass::Disconnect();
- }
-
- virtual InitReturnVal_t Init()
- {
- InitReturnVal_t nRetVal = BaseClass::Init();
- if ( nRetVal != INIT_OK )
- return nRetVal;
-
- if ( g_pCVar && BaseClass::IsPrimaryAppSystem() )
- {
- ConVar_Register( ConVarFlag );
- }
- return INIT_OK;
- }
-
- virtual void Shutdown()
- {
- if ( g_pCVar && BaseClass::IsPrimaryAppSystem() )
- {
- ConVar_Unregister( );
- }
- BaseClass::Shutdown( );
- }
-};
-
-
-#endif // TIER1_H
-
+//========= Copyright 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
+//-----------------------------------------------------------------------------
+class ICvar;
+class IProcessUtils;
+
+
+//-----------------------------------------------------------------------------
+// These tier1 libraries must be set by any users of this library.
+// They can be set by calling ConnectTier1Libraries.
+// It is hoped that setting this, and using this library will be the common mechanism for
+// allowing link libraries to access tier1 library interfaces
+//-----------------------------------------------------------------------------
+
+// These are marked DLL_EXPORT for Linux.
+DLL_EXPORT ICvar *cvar;
+extern ICvar *g_pCVar;
+extern IProcessUtils *g_pProcessUtils;
+
+
+//-----------------------------------------------------------------------------
+// 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:
+ CTier1AppSystem( bool bIsPrimaryAppSystem = true ) : BaseClass( bIsPrimaryAppSystem )
+ {
+ }
+
+ virtual bool Connect( CreateInterfaceFn factory )
+ {
+ if ( !BaseClass::Connect( factory ) )
+ return false;
+
+ if ( BaseClass::IsPrimaryAppSystem() )
+ {
+ ConnectTier1Libraries( &factory, 1 );
+ }
+ return true;
+ }
+
+ virtual void Disconnect()
+ {
+ if ( BaseClass::IsPrimaryAppSystem() )
+ {
+ DisconnectTier1Libraries();
+ }
+ BaseClass::Disconnect();
+ }
+
+ virtual InitReturnVal_t Init()
+ {
+ InitReturnVal_t nRetVal = BaseClass::Init();
+ if ( nRetVal != INIT_OK )
+ return nRetVal;
+
+ if ( g_pCVar && BaseClass::IsPrimaryAppSystem() )
+ {
+ ConVar_Register( ConVarFlag );
+ }
+ return INIT_OK;
+ }
+
+ virtual void Shutdown()
+ {
+ if ( g_pCVar && BaseClass::IsPrimaryAppSystem() )
+ {
+ ConVar_Unregister( );
+ }
+ BaseClass::Shutdown( );
+ }
+};
+
+
+#endif // TIER1_H
+
diff --git a/mp/src/public/tier1/tokenreader.h b/mp/src/public/tier1/tokenreader.h
index 14061e76..b174869c 100644
--- a/mp/src/public/tier1/tokenreader.h
+++ b/mp/src/public/tier1/tokenreader.h
@@ -1,99 +1,99 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//=============================================================================//
-
-#ifndef TOKENREADER_H
-#define TOKENREADER_H
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include "tier0/basetypes.h"
-
-#ifdef _WIN32
-#pragma warning(push, 1)
-#pragma warning(disable:4701 4702 4530)
-#endif
-
-#undef min
-#undef max
-#include <fstream>
-#include "valve_minmax_on.h"
-
-#ifdef _WIN32
-#pragma warning(pop)
-#endif
-
-#include <assert.h>
-
-
-typedef enum
-{
- TOKENSTRINGTOOLONG = -4,
- TOKENERROR = -3,
- TOKENNONE = -2,
- TOKENEOF = -1,
- OPERATOR,
- INTEGER,
- STRING,
- IDENT
-} trtoken_t;
-
-
-#define IsToken(s1, s2) !strcmpi(s1, s2)
-
-#define MAX_TOKEN 128 + 1
-#define MAX_IDENT 64 + 1
-#define MAX_STRING 128 + 1
-
-
-class TokenReader : private std::ifstream
-{
-public:
-
- TokenReader();
-
- bool Open(const char *pszFilename);
- trtoken_t NextToken(char *pszStore, int nSize);
- trtoken_t NextTokenDynamic(char **ppszStore);
- void Close();
-
- void IgnoreTill(trtoken_t ttype, const char *pszToken);
- void Stuff(trtoken_t ttype, const char *pszToken);
- bool Expecting(trtoken_t ttype, const char *pszToken);
- const char *Error(char *error, ...);
- trtoken_t PeekTokenType(char* = NULL, int maxlen = 0);
-
- inline int GetErrorCount(void);
-
-private:
- // compiler can't generate an assignment operator since descended from std::ifstream
- inline TokenReader(TokenReader const &);
- inline int operator=(TokenReader const &);
-
- trtoken_t GetString(char *pszStore, int nSize);
- bool SkipWhiteSpace(void);
-
- int m_nLine;
- int m_nErrorCount;
-
- char m_szFilename[128];
- char m_szStuffed[128];
- bool m_bStuffed;
- trtoken_t m_eStuffed;
-};
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Returns the total number of parsing errors since this file was opened.
-//-----------------------------------------------------------------------------
-int TokenReader::GetErrorCount(void)
-{
- return(m_nErrorCount);
-}
-
-
-#endif // TOKENREADER_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef TOKENREADER_H
+#define TOKENREADER_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/basetypes.h"
+
+#ifdef _WIN32
+#pragma warning(push, 1)
+#pragma warning(disable:4701 4702 4530)
+#endif
+
+#undef min
+#undef max
+#include <fstream>
+#include "valve_minmax_on.h"
+
+#ifdef _WIN32
+#pragma warning(pop)
+#endif
+
+#include <assert.h>
+
+
+typedef enum
+{
+ TOKENSTRINGTOOLONG = -4,
+ TOKENERROR = -3,
+ TOKENNONE = -2,
+ TOKENEOF = -1,
+ OPERATOR,
+ INTEGER,
+ STRING,
+ IDENT
+} trtoken_t;
+
+
+#define IsToken(s1, s2) !strcmpi(s1, s2)
+
+#define MAX_TOKEN 128 + 1
+#define MAX_IDENT 64 + 1
+#define MAX_STRING 128 + 1
+
+
+class TokenReader : private std::ifstream
+{
+public:
+
+ TokenReader();
+
+ bool Open(const char *pszFilename);
+ trtoken_t NextToken(char *pszStore, int nSize);
+ trtoken_t NextTokenDynamic(char **ppszStore);
+ void Close();
+
+ void IgnoreTill(trtoken_t ttype, const char *pszToken);
+ void Stuff(trtoken_t ttype, const char *pszToken);
+ bool Expecting(trtoken_t ttype, const char *pszToken);
+ const char *Error(char *error, ...);
+ trtoken_t PeekTokenType(char* = NULL, int maxlen = 0);
+
+ inline int GetErrorCount(void);
+
+private:
+ // compiler can't generate an assignment operator since descended from std::ifstream
+ inline TokenReader(TokenReader const &);
+ inline int operator=(TokenReader const &);
+
+ trtoken_t GetString(char *pszStore, int nSize);
+ bool SkipWhiteSpace(void);
+
+ int m_nLine;
+ int m_nErrorCount;
+
+ char m_szFilename[128];
+ char m_szStuffed[128];
+ bool m_bStuffed;
+ trtoken_t m_eStuffed;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the total number of parsing errors since this file was opened.
+//-----------------------------------------------------------------------------
+int TokenReader::GetErrorCount(void)
+{
+ return(m_nErrorCount);
+}
+
+
+#endif // TOKENREADER_H
diff --git a/mp/src/public/tier1/uniqueid.h b/mp/src/public/tier1/uniqueid.h
index e7df1600..fd3fe262 100644
--- a/mp/src/public/tier1/uniqueid.h
+++ b/mp/src/public/tier1/uniqueid.h
@@ -1,56 +1,56 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//
-// Utilities for globally unique IDs
-//=============================================================================//
-
-#ifndef UNIQUEID_H
-#define UNIQUEID_H
-
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include "tier1/utlvector.h"
-
-
-//-----------------------------------------------------------------------------
-// Forward declarations
-//-----------------------------------------------------------------------------
-struct UniqueId_t;
-class CUtlBuffer;
-
-
-//-----------------------------------------------------------------------------
-// Defines a globally unique ID
-//-----------------------------------------------------------------------------
-struct UniqueId_t
-{
- unsigned char m_Value[16];
-};
-
-
-//-----------------------------------------------------------------------------
-// Methods related to unique ids
-//-----------------------------------------------------------------------------
-void CreateUniqueId( UniqueId_t *pDest );
-void InvalidateUniqueId( UniqueId_t *pDest );
-bool IsUniqueIdValid( const UniqueId_t &id );
-bool IsUniqueIdEqual( const UniqueId_t &id1, const UniqueId_t &id2 );
-void UniqueIdToString( const UniqueId_t &id, char *pBuf, int nMaxLen );
-bool UniqueIdFromString( UniqueId_t *pDest, const char *pBuf, int nMaxLen = 0 );
-void CopyUniqueId( const UniqueId_t &src, UniqueId_t *pDest );
-bool Serialize( CUtlBuffer &buf, const UniqueId_t &src );
-bool Unserialize( CUtlBuffer &buf, UniqueId_t &dest );
-
-inline bool operator ==( const UniqueId_t& lhs, const UniqueId_t& rhs )
-{
- return !Q_memcmp( (void *)&lhs.m_Value[ 0 ], (void *)&rhs.m_Value[ 0 ], sizeof( lhs.m_Value ) );
-}
-
-
-#endif // UNIQUEID_H
-
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+// Utilities for globally unique IDs
+//=============================================================================//
+
+#ifndef UNIQUEID_H
+#define UNIQUEID_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier1/utlvector.h"
+
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+struct UniqueId_t;
+class CUtlBuffer;
+
+
+//-----------------------------------------------------------------------------
+// Defines a globally unique ID
+//-----------------------------------------------------------------------------
+struct UniqueId_t
+{
+ unsigned char m_Value[16];
+};
+
+
+//-----------------------------------------------------------------------------
+// Methods related to unique ids
+//-----------------------------------------------------------------------------
+void CreateUniqueId( UniqueId_t *pDest );
+void InvalidateUniqueId( UniqueId_t *pDest );
+bool IsUniqueIdValid( const UniqueId_t &id );
+bool IsUniqueIdEqual( const UniqueId_t &id1, const UniqueId_t &id2 );
+void UniqueIdToString( const UniqueId_t &id, char *pBuf, int nMaxLen );
+bool UniqueIdFromString( UniqueId_t *pDest, const char *pBuf, int nMaxLen = 0 );
+void CopyUniqueId( const UniqueId_t &src, UniqueId_t *pDest );
+bool Serialize( CUtlBuffer &buf, const UniqueId_t &src );
+bool Unserialize( CUtlBuffer &buf, UniqueId_t &dest );
+
+inline bool operator ==( const UniqueId_t& lhs, const UniqueId_t& rhs )
+{
+ return !Q_memcmp( (void *)&lhs.m_Value[ 0 ], (void *)&rhs.m_Value[ 0 ], sizeof( lhs.m_Value ) );
+}
+
+
+#endif // UNIQUEID_H
+
diff --git a/mp/src/public/tier1/utlallocation.h b/mp/src/public/tier1/utlallocation.h
index c0116b08..65416bcf 100644
--- a/mp/src/public/tier1/utlallocation.h
+++ b/mp/src/public/tier1/utlallocation.h
@@ -1,134 +1,134 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-// The CUtlAllocation class:
-// A single allocation in the style of CUtlMemory/CUtlString/CUtlBuffer
-// as compact as possible, no virtuals or extraneous data
-// to be used primarily to replace CUtlBuffer
-//=============================================================================
-
-#ifndef UTLALLOCATION_H
-#define UTLALLOCATION_H
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include "tier1/utlmemory.h"
-
-class CUtlAllocation
-{
-public:
-
- // constructor, destructor
- CUtlAllocation()
- {
- m_pMemory = NULL;
- }
-
- CUtlAllocation( const void *pMemory, int cub )
- {
- m_pMemory = NULL;
- Copy( pMemory, cub );
- }
-
- CUtlAllocation( CUtlAllocation const &src )
- {
- m_pMemory = NULL;
- Copy( src );
- }
-
- ~CUtlAllocation()
- {
- Purge();
- }
-
- CUtlAllocation &operator=( CUtlAllocation const &src )
- {
- Copy( src );
- return *this;
- }
-
- bool operator==( CUtlAllocation const &src )
- {
- if ( Count() != src.Count() )
- return false;
- return Q_memcmp( Base(), src.Base(), Count() ) == 0;
- }
-
- void Copy( const void *pMemory, int cub )
- {
- if ( cub == 0 || pMemory == NULL )
- {
- Purge();
- return;
- }
- if ( cub != Count() )
- {
- Purge();
- m_pMemory = (ActualMemory_t *)malloc( cub + sizeof( int ) );
- m_pMemory->cub = cub;
- }
- Q_memcpy( Base(), pMemory, cub );
- }
-
- // Gets the base address
- uint8* Base()
- {
- if ( m_pMemory == NULL )
- return NULL;
- return m_pMemory->rgub;
- }
-
- const uint8* Base() const
- {
- if ( m_pMemory == NULL )
- return NULL;
- return m_pMemory->rgub;
- }
-
- // Size
- int Count() const
- {
- if ( m_pMemory == NULL )
- return 0;
- return m_pMemory->cub;
- }
-
- // Memory deallocation
- void Purge()
- {
- if ( m_pMemory )
- free(m_pMemory);
- m_pMemory = NULL;
- }
-
- void Copy( const CUtlAllocation &alloc )
- {
- Copy( alloc.Base(), alloc.Count() );
- }
-
- void Swap( CUtlAllocation &alloc )
- {
- ActualMemory_t *pTemp = m_pMemory;
- m_pMemory = alloc.m_pMemory;
- alloc.m_pMemory = pTemp;
- }
-
- void Alloc( int cub )
- {
- Purge();
- m_pMemory = (ActualMemory_t *)malloc( cub + sizeof( int ) );
- m_pMemory->cub = cub;
- }
-
-private:
- struct ActualMemory_t
- {
- int cub;
- uint8 rgub[4]; // i'd prefer to make this 0 but the compiler whines when i do
- };
-
- ActualMemory_t *m_pMemory;
-};
-
-#endif // UTLALLOCATION_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+// The CUtlAllocation class:
+// A single allocation in the style of CUtlMemory/CUtlString/CUtlBuffer
+// as compact as possible, no virtuals or extraneous data
+// to be used primarily to replace CUtlBuffer
+//=============================================================================
+
+#ifndef UTLALLOCATION_H
+#define UTLALLOCATION_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier1/utlmemory.h"
+
+class CUtlAllocation
+{
+public:
+
+ // constructor, destructor
+ CUtlAllocation()
+ {
+ m_pMemory = NULL;
+ }
+
+ CUtlAllocation( const void *pMemory, int cub )
+ {
+ m_pMemory = NULL;
+ Copy( pMemory, cub );
+ }
+
+ CUtlAllocation( CUtlAllocation const &src )
+ {
+ m_pMemory = NULL;
+ Copy( src );
+ }
+
+ ~CUtlAllocation()
+ {
+ Purge();
+ }
+
+ CUtlAllocation &operator=( CUtlAllocation const &src )
+ {
+ Copy( src );
+ return *this;
+ }
+
+ bool operator==( CUtlAllocation const &src )
+ {
+ if ( Count() != src.Count() )
+ return false;
+ return Q_memcmp( Base(), src.Base(), Count() ) == 0;
+ }
+
+ void Copy( const void *pMemory, int cub )
+ {
+ if ( cub == 0 || pMemory == NULL )
+ {
+ Purge();
+ return;
+ }
+ if ( cub != Count() )
+ {
+ Purge();
+ m_pMemory = (ActualMemory_t *)malloc( cub + sizeof( int ) );
+ m_pMemory->cub = cub;
+ }
+ Q_memcpy( Base(), pMemory, cub );
+ }
+
+ // Gets the base address
+ uint8* Base()
+ {
+ if ( m_pMemory == NULL )
+ return NULL;
+ return m_pMemory->rgub;
+ }
+
+ const uint8* Base() const
+ {
+ if ( m_pMemory == NULL )
+ return NULL;
+ return m_pMemory->rgub;
+ }
+
+ // Size
+ int Count() const
+ {
+ if ( m_pMemory == NULL )
+ return 0;
+ return m_pMemory->cub;
+ }
+
+ // Memory deallocation
+ void Purge()
+ {
+ if ( m_pMemory )
+ free(m_pMemory);
+ m_pMemory = NULL;
+ }
+
+ void Copy( const CUtlAllocation &alloc )
+ {
+ Copy( alloc.Base(), alloc.Count() );
+ }
+
+ void Swap( CUtlAllocation &alloc )
+ {
+ ActualMemory_t *pTemp = m_pMemory;
+ m_pMemory = alloc.m_pMemory;
+ alloc.m_pMemory = pTemp;
+ }
+
+ void Alloc( int cub )
+ {
+ Purge();
+ m_pMemory = (ActualMemory_t *)malloc( cub + sizeof( int ) );
+ m_pMemory->cub = cub;
+ }
+
+private:
+ struct ActualMemory_t
+ {
+ int cub;
+ uint8 rgub[4]; // i'd prefer to make this 0 but the compiler whines when i do
+ };
+
+ ActualMemory_t *m_pMemory;
+};
+
+#endif // UTLALLOCATION_H
diff --git a/mp/src/public/tier1/utlarray.h b/mp/src/public/tier1/utlarray.h
index bc50b068..36850860 100644
--- a/mp/src/public/tier1/utlarray.h
+++ b/mp/src/public/tier1/utlarray.h
@@ -1,299 +1,299 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//
-// A growable array class that maintains a free list and keeps elements
-// in the same location
-//=============================================================================//
-
-#ifndef UTLARRAY_H
-#define UTLARRAY_H
-
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include "tier0/platform.h"
-#include "tier0/dbg.h"
-#include "vstdlib/random.h"
-
-#define FOR_EACH_ARRAY( vecName, iteratorName ) \
- for ( int iteratorName = 0; (vecName).IsUtlArray && iteratorName < (vecName).Count(); iteratorName++ )
-#define FOR_EACH_ARRAY_BACK( vecName, iteratorName ) \
- for ( int iteratorName = (vecName).Count()-1; (vecName).IsUtlArray && iteratorName >= 0; iteratorName-- )
-
-// utlarray derives from this so we can do the type check above
-struct base_array_t
-{
-public:
- static const bool IsUtlArray = true; // Used to match this at compiletime
-};
-
-#if defined( GNUC ) && defined( DEBUG )
-// gcc in debug doesn't optimize away the need for the storage of IsUtlArray so make one here
-// as this is in a shared header use SELECTANY to make it throw away the dupe symbols
-const bool base_array_t::IsUtlArray SELECTANY;
-#endif
-
-//-----------------------------------------------------------------------------
-template< class T, size_t MAX_SIZE >
-class CUtlArray : public base_array_t
-{
-public:
- typedef T ElemType_t;
-
- CUtlArray();
- CUtlArray( T* pMemory, size_t count );
- ~CUtlArray();
-
- CUtlArray<T, MAX_SIZE>& operator=( const CUtlArray<T, MAX_SIZE> &other );
- CUtlArray( CUtlArray const& vec );
-
- // element access
- T& operator[]( int i );
- const T& operator[]( int i ) const;
- T& Element( int i );
- const T& Element( int i ) const;
- T& Random();
- const T& Random() const;
-
- T* Base();
- const T* Base() const;
-
- // Returns the number of elements in the array, NumAllocated() is included for consistency with UtlVector
- int Count() const;
- int NumAllocated() const;
-
- // Is element index valid?
- bool IsValidIndex( int i ) const;
- static int InvalidIndex();
-
- void CopyArray( const T *pArray, size_t count );
-
- void Swap( CUtlArray< T, MAX_SIZE > &vec );
-
- // Finds an element (element needs operator== defined)
- int Find( const T& src ) const;
- void FillWithValue( const T& src );
-
- bool HasElement( const T& src ) const;
-
- // calls delete on each element in it.
- void DeleteElements();
-
- void Sort( int (__cdecl *pfnCompare)(const T *, const T *) );
-
-protected:
- T m_Memory[ MAX_SIZE ];
-};
-
-//-----------------------------------------------------------------------------
-// constructor, destructor
-//-----------------------------------------------------------------------------
-template< typename T, size_t MAX_SIZE >
-inline CUtlArray<T, MAX_SIZE>::CUtlArray()
-{
-}
-
-template< typename T, size_t MAX_SIZE >
-inline CUtlArray<T, MAX_SIZE>::CUtlArray( T* pMemory, size_t count )
-{
- CopyArray( pMemory, count );
-}
-
-template< typename T, size_t MAX_SIZE >
-inline CUtlArray<T, MAX_SIZE>::~CUtlArray()
-{
-}
-
-template< typename T, size_t MAX_SIZE >
-inline CUtlArray<T, MAX_SIZE>& CUtlArray<T, MAX_SIZE>::operator=( const CUtlArray<T, MAX_SIZE> &other )
-{
- if ( this != &other )
- {
- for ( size_t n = 0; n < MAX_SIZE; ++n )
- {
- m_Memory[n] = other.m_Memory[n];
- }
- }
- return *this;
-}
-
-template< typename T, size_t MAX_SIZE >
-inline CUtlArray<T, MAX_SIZE>::CUtlArray( CUtlArray const& vec )
-{
- for ( size_t n = 0; n < MAX_SIZE; ++n )
- {
- m_Memory[n] = vec.m_Memory[n];
- }
-}
-
-template< typename T, size_t MAX_SIZE >
-inline T *CUtlArray<T, MAX_SIZE>::Base()
-{
- return &m_Memory[0];
-}
-
-template< typename T, size_t MAX_SIZE >
-inline const T *CUtlArray<T, MAX_SIZE>::Base() const
-{
- return &m_Memory[0];
-}
-
-//-----------------------------------------------------------------------------
-// element access
-//-----------------------------------------------------------------------------
-template< typename T, size_t MAX_SIZE >
-inline T& CUtlArray<T, MAX_SIZE>::operator[]( int i )
-{
- Assert( IsValidIndex( i ) );
- return m_Memory[ i ];
-}
-
-template< typename T, size_t MAX_SIZE >
-inline const T& CUtlArray<T, MAX_SIZE>::operator[]( int i ) const
-{
- Assert( IsValidIndex( i ) );
- return m_Memory[ i ];
-}
-
-template< typename T, size_t MAX_SIZE >
-inline T& CUtlArray<T, MAX_SIZE>::Element( int i )
-{
- Assert( IsValidIndex( i ) );
- return m_Memory[ i ];
-}
-
-template< typename T, size_t MAX_SIZE >
-inline const T& CUtlArray<T, MAX_SIZE>::Element( int i ) const
-{
- Assert( IsValidIndex( i ) );
- return m_Memory[ i ];
-}
-
-template< typename T, size_t MAX_SIZE >
-inline T& CUtlArray<T, MAX_SIZE>::Random()
-{
- Assert( MAX_SIZE > 0 );
- return m_Memory[ RandomInt( 0, MAX_SIZE - 1 ) ];
-}
-
-template< typename T, size_t MAX_SIZE >
-inline const T& CUtlArray<T, MAX_SIZE>::Random() const
-{
- Assert( MAX_SIZE > 0 );
- return m_Memory[ RandomInt( 0, MAX_SIZE - 1 ) ];
-}
-
-
-//-----------------------------------------------------------------------------
-// Count
-//-----------------------------------------------------------------------------
-template< typename T, size_t MAX_SIZE >
-inline int CUtlArray<T, MAX_SIZE>::Count() const
-{
- return (int)MAX_SIZE;
-}
-
-
-//-----------------------------------------------------------------------------
-template< typename T, size_t MAX_SIZE >
-inline int CUtlArray<T, MAX_SIZE>::NumAllocated() const
-{
- return (int)MAX_SIZE;
-}
-
-//-----------------------------------------------------------------------------
-// Is element index valid?
-//-----------------------------------------------------------------------------
-template< typename T, size_t MAX_SIZE >
-inline bool CUtlArray<T, MAX_SIZE>::IsValidIndex( int i ) const
-{
- return (i >= 0) && (i < MAX_SIZE);
-}
-
-
-//-----------------------------------------------------------------------------
-// Returns in invalid index
-//-----------------------------------------------------------------------------
-template< typename T, size_t MAX_SIZE >
-inline int CUtlArray<T, MAX_SIZE>::InvalidIndex()
-{
- return -1;
-}
-
-
-//-----------------------------------------------------------------------------
-// Sorts the vector
-//-----------------------------------------------------------------------------
-template< typename T, size_t MAX_SIZE >
-void CUtlArray<T, MAX_SIZE>::Sort( int (__cdecl *pfnCompare)(const T *, const T *) )
-{
- typedef int (__cdecl *QSortCompareFunc_t)(const void *, const void *);
- if ( Count() <= 1 )
- return;
-
- qsort( Base(), Count(), sizeof(T), (QSortCompareFunc_t)(pfnCompare) );
-}
-
-template< typename T, size_t MAX_SIZE >
-void CUtlArray<T, MAX_SIZE>::CopyArray( const T *pArray, size_t count )
-{
- Assert( count < MAX_SIZE );
-
- for ( size_t n = 0; n < count; ++n )
- {
- m_Memory[n] = pArray[n];
- }
-}
-
-template< typename T, size_t MAX_SIZE >
-void CUtlArray<T, MAX_SIZE>::Swap( CUtlArray< T, MAX_SIZE > &vec )
-{
- for ( size_t n = 0; n < MAX_SIZE; ++n )
- {
- V_swap( m_Memory[n], vec.m_Memory[n] );
- }
-}
-
-//-----------------------------------------------------------------------------
-// Finds an element (element needs operator== defined)
-//-----------------------------------------------------------------------------
-template< typename T, size_t MAX_SIZE >
-int CUtlArray<T, MAX_SIZE>::Find( const T& src ) const
-{
- for ( int i = 0; i < Count(); ++i )
- {
- if (Element(i) == src)
- return i;
- }
- return -1;
-}
-
-template< typename T, size_t MAX_SIZE >
-void CUtlArray<T, MAX_SIZE>::FillWithValue( const T& src )
-{
- for ( int i = 0; i < Count(); i++ )
- {
- Element(i) = src;
- }
-}
-
-template< typename T, size_t MAX_SIZE >
-bool CUtlArray<T, MAX_SIZE>::HasElement( const T& src ) const
-{
- return ( Find(src) >= 0 );
-}
-
-template< typename T, size_t MAX_SIZE >
-inline void CUtlArray<T, MAX_SIZE>::DeleteElements()
-{
- for( int i=0; i < MAX_SIZE; i++ )
- {
- delete Element(i);
- }
-}
-
-#endif // UTLARRAY_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+// A growable array class that maintains a free list and keeps elements
+// in the same location
+//=============================================================================//
+
+#ifndef UTLARRAY_H
+#define UTLARRAY_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/platform.h"
+#include "tier0/dbg.h"
+#include "vstdlib/random.h"
+
+#define FOR_EACH_ARRAY( vecName, iteratorName ) \
+ for ( int iteratorName = 0; (vecName).IsUtlArray && iteratorName < (vecName).Count(); iteratorName++ )
+#define FOR_EACH_ARRAY_BACK( vecName, iteratorName ) \
+ for ( int iteratorName = (vecName).Count()-1; (vecName).IsUtlArray && iteratorName >= 0; iteratorName-- )
+
+// utlarray derives from this so we can do the type check above
+struct base_array_t
+{
+public:
+ static const bool IsUtlArray = true; // Used to match this at compiletime
+};
+
+#if defined( GNUC ) && defined( DEBUG )
+// gcc in debug doesn't optimize away the need for the storage of IsUtlArray so make one here
+// as this is in a shared header use SELECTANY to make it throw away the dupe symbols
+const bool base_array_t::IsUtlArray SELECTANY;
+#endif
+
+//-----------------------------------------------------------------------------
+template< class T, size_t MAX_SIZE >
+class CUtlArray : public base_array_t
+{
+public:
+ typedef T ElemType_t;
+
+ CUtlArray();
+ CUtlArray( T* pMemory, size_t count );
+ ~CUtlArray();
+
+ CUtlArray<T, MAX_SIZE>& operator=( const CUtlArray<T, MAX_SIZE> &other );
+ CUtlArray( CUtlArray const& vec );
+
+ // element access
+ T& operator[]( int i );
+ const T& operator[]( int i ) const;
+ T& Element( int i );
+ const T& Element( int i ) const;
+ T& Random();
+ const T& Random() const;
+
+ T* Base();
+ const T* Base() const;
+
+ // Returns the number of elements in the array, NumAllocated() is included for consistency with UtlVector
+ int Count() const;
+ int NumAllocated() const;
+
+ // Is element index valid?
+ bool IsValidIndex( int i ) const;
+ static int InvalidIndex();
+
+ void CopyArray( const T *pArray, size_t count );
+
+ void Swap( CUtlArray< T, MAX_SIZE > &vec );
+
+ // Finds an element (element needs operator== defined)
+ int Find( const T& src ) const;
+ void FillWithValue( const T& src );
+
+ bool HasElement( const T& src ) const;
+
+ // calls delete on each element in it.
+ void DeleteElements();
+
+ void Sort( int (__cdecl *pfnCompare)(const T *, const T *) );
+
+protected:
+ T m_Memory[ MAX_SIZE ];
+};
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+template< typename T, size_t MAX_SIZE >
+inline CUtlArray<T, MAX_SIZE>::CUtlArray()
+{
+}
+
+template< typename T, size_t MAX_SIZE >
+inline CUtlArray<T, MAX_SIZE>::CUtlArray( T* pMemory, size_t count )
+{
+ CopyArray( pMemory, count );
+}
+
+template< typename T, size_t MAX_SIZE >
+inline CUtlArray<T, MAX_SIZE>::~CUtlArray()
+{
+}
+
+template< typename T, size_t MAX_SIZE >
+inline CUtlArray<T, MAX_SIZE>& CUtlArray<T, MAX_SIZE>::operator=( const CUtlArray<T, MAX_SIZE> &other )
+{
+ if ( this != &other )
+ {
+ for ( size_t n = 0; n < MAX_SIZE; ++n )
+ {
+ m_Memory[n] = other.m_Memory[n];
+ }
+ }
+ return *this;
+}
+
+template< typename T, size_t MAX_SIZE >
+inline CUtlArray<T, MAX_SIZE>::CUtlArray( CUtlArray const& vec )
+{
+ for ( size_t n = 0; n < MAX_SIZE; ++n )
+ {
+ m_Memory[n] = vec.m_Memory[n];
+ }
+}
+
+template< typename T, size_t MAX_SIZE >
+inline T *CUtlArray<T, MAX_SIZE>::Base()
+{
+ return &m_Memory[0];
+}
+
+template< typename T, size_t MAX_SIZE >
+inline const T *CUtlArray<T, MAX_SIZE>::Base() const
+{
+ return &m_Memory[0];
+}
+
+//-----------------------------------------------------------------------------
+// element access
+//-----------------------------------------------------------------------------
+template< typename T, size_t MAX_SIZE >
+inline T& CUtlArray<T, MAX_SIZE>::operator[]( int i )
+{
+ Assert( IsValidIndex( i ) );
+ return m_Memory[ i ];
+}
+
+template< typename T, size_t MAX_SIZE >
+inline const T& CUtlArray<T, MAX_SIZE>::operator[]( int i ) const
+{
+ Assert( IsValidIndex( i ) );
+ return m_Memory[ i ];
+}
+
+template< typename T, size_t MAX_SIZE >
+inline T& CUtlArray<T, MAX_SIZE>::Element( int i )
+{
+ Assert( IsValidIndex( i ) );
+ return m_Memory[ i ];
+}
+
+template< typename T, size_t MAX_SIZE >
+inline const T& CUtlArray<T, MAX_SIZE>::Element( int i ) const
+{
+ Assert( IsValidIndex( i ) );
+ return m_Memory[ i ];
+}
+
+template< typename T, size_t MAX_SIZE >
+inline T& CUtlArray<T, MAX_SIZE>::Random()
+{
+ Assert( MAX_SIZE > 0 );
+ return m_Memory[ RandomInt( 0, MAX_SIZE - 1 ) ];
+}
+
+template< typename T, size_t MAX_SIZE >
+inline const T& CUtlArray<T, MAX_SIZE>::Random() const
+{
+ Assert( MAX_SIZE > 0 );
+ return m_Memory[ RandomInt( 0, MAX_SIZE - 1 ) ];
+}
+
+
+//-----------------------------------------------------------------------------
+// Count
+//-----------------------------------------------------------------------------
+template< typename T, size_t MAX_SIZE >
+inline int CUtlArray<T, MAX_SIZE>::Count() const
+{
+ return (int)MAX_SIZE;
+}
+
+
+//-----------------------------------------------------------------------------
+template< typename T, size_t MAX_SIZE >
+inline int CUtlArray<T, MAX_SIZE>::NumAllocated() const
+{
+ return (int)MAX_SIZE;
+}
+
+//-----------------------------------------------------------------------------
+// Is element index valid?
+//-----------------------------------------------------------------------------
+template< typename T, size_t MAX_SIZE >
+inline bool CUtlArray<T, MAX_SIZE>::IsValidIndex( int i ) const
+{
+ return (i >= 0) && (i < MAX_SIZE);
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns in invalid index
+//-----------------------------------------------------------------------------
+template< typename T, size_t MAX_SIZE >
+inline int CUtlArray<T, MAX_SIZE>::InvalidIndex()
+{
+ return -1;
+}
+
+
+//-----------------------------------------------------------------------------
+// Sorts the vector
+//-----------------------------------------------------------------------------
+template< typename T, size_t MAX_SIZE >
+void CUtlArray<T, MAX_SIZE>::Sort( int (__cdecl *pfnCompare)(const T *, const T *) )
+{
+ typedef int (__cdecl *QSortCompareFunc_t)(const void *, const void *);
+ if ( Count() <= 1 )
+ return;
+
+ qsort( Base(), Count(), sizeof(T), (QSortCompareFunc_t)(pfnCompare) );
+}
+
+template< typename T, size_t MAX_SIZE >
+void CUtlArray<T, MAX_SIZE>::CopyArray( const T *pArray, size_t count )
+{
+ Assert( count < MAX_SIZE );
+
+ for ( size_t n = 0; n < count; ++n )
+ {
+ m_Memory[n] = pArray[n];
+ }
+}
+
+template< typename T, size_t MAX_SIZE >
+void CUtlArray<T, MAX_SIZE>::Swap( CUtlArray< T, MAX_SIZE > &vec )
+{
+ for ( size_t n = 0; n < MAX_SIZE; ++n )
+ {
+ V_swap( m_Memory[n], vec.m_Memory[n] );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Finds an element (element needs operator== defined)
+//-----------------------------------------------------------------------------
+template< typename T, size_t MAX_SIZE >
+int CUtlArray<T, MAX_SIZE>::Find( const T& src ) const
+{
+ for ( int i = 0; i < Count(); ++i )
+ {
+ if (Element(i) == src)
+ return i;
+ }
+ return -1;
+}
+
+template< typename T, size_t MAX_SIZE >
+void CUtlArray<T, MAX_SIZE>::FillWithValue( const T& src )
+{
+ for ( int i = 0; i < Count(); i++ )
+ {
+ Element(i) = src;
+ }
+}
+
+template< typename T, size_t MAX_SIZE >
+bool CUtlArray<T, MAX_SIZE>::HasElement( const T& src ) const
+{
+ return ( Find(src) >= 0 );
+}
+
+template< typename T, size_t MAX_SIZE >
+inline void CUtlArray<T, MAX_SIZE>::DeleteElements()
+{
+ for( int i=0; i < MAX_SIZE; i++ )
+ {
+ delete Element(i);
+ }
+}
+
+#endif // UTLARRAY_H
diff --git a/mp/src/public/tier1/utlbidirectionalset.h b/mp/src/public/tier1/utlbidirectionalset.h
index a2e6d746..36aea62b 100644
--- a/mp/src/public/tier1/utlbidirectionalset.h
+++ b/mp/src/public/tier1/utlbidirectionalset.h
@@ -1,394 +1,394 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Bi-directional set. A Bucket knows about the elements that lie
-// in it, and the elements know about the buckets they lie in.
-//
-// $Revision: $
-// $NoKeywords: $
-//=============================================================================//
-
-#ifndef UTLBIDIRECTIONALSET_H
-#define UTLBIDIRECTIONALSET_H
-
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include "tier0/dbg.h"
-#include "utllinkedlist.h"
-
-//-----------------------------------------------------------------------------
-// Templatized helper class to deal with the kinds of things that spatial
-// partition code always seems to have; buckets with lists of lots of elements
-// and elements that live in lots of buckets. This makes it really quick to
-// add and remove elements, and to iterate over all elements in a bucket.
-//
-// For this to work, you must initialize the set with two functions one that
-// maps from bucket to the index of the first element in that bucket, and one
-// that maps from element to the index of the first bucket that element lies in.
-// The set will completely manage the index, it's just expected that those
-// indices will be stored outside the set.
-//
-// S is the storage type of the index; it is the type that you may use to
-// save indices into memory. I is the local iterator type, which you should
-// use in any local scope (eg, inside a for() loop.) The reason for this is
-// that you may wish to use unsigned shorts inside the structs you are
-// saving with a CBidirectionalSet; but 16-bit arithmetic is catastrophically
-// slow on a PowerPC -- during testing we saw CBidirectionalSet:: operations
-// consume as much as 8% of the frame.
-//
-// For this reason, on the 360, the handles have been typedef'd to native
-// register types (U32) which are accepted as parameters by the functions.
-// The implicit assumption is that CBucketHandle and CElementHandle can
-// be safely cast to ints! You can increase to U64 without performance
-// penalty if necessary; the PowerPC is a 64-bit processor.
-//-----------------------------------------------------------------------------
-template< class CBucketHandle, class CElementHandle, class S, class I = S >
-class CBidirectionalSet
-{
-public:
- // Install methods to get at the first bucket given a element
- // and vice versa...
- typedef S& (*FirstElementFunc_t)(CBucketHandle);
- typedef S& (*FirstBucketFunc_t)(CElementHandle);
-
-#ifdef _X360
- typedef uint32 CBucketHandlePram;
- typedef uint32 CElementHandlePram;
-#else
- typedef CBucketHandle CBucketHandlePram;
- typedef CElementHandle CElementHandlePram;
-#endif
-
- // Constructor
- CBidirectionalSet();
-
- // Call this before using the set
- void Init( FirstElementFunc_t elemFunc, FirstBucketFunc_t bucketFunc );
-
- // Add an element to a particular bucket
- void AddElementToBucket( CBucketHandlePram bucket, CElementHandlePram element );
-
- // Prevalidate an add to a particular bucket
- // NOTE: EXPENSIVE!!!
- void ValidateAddElementToBucket( CBucketHandlePram bucket, CElementHandlePram element );
-
- // Test if an element is in a particular bucket.
- // NOTE: EXPENSIVE!!!
- bool IsElementInBucket( CBucketHandlePram bucket, CElementHandlePram element );
-
- // Remove an element from a particular bucket
- void RemoveElementFromBucket( CBucketHandlePram bucket, CElementHandlePram element );
-
- // Remove an element from all buckets
- void RemoveElement( CElementHandlePram element );
- void RemoveBucket( CBucketHandlePram element );
-
- // Used to iterate elements in a bucket; I is the iterator
- I FirstElement( CBucketHandlePram bucket ) const;
- I NextElement( I idx ) const;
- CElementHandle Element( I idx ) const;
-
- // Used to iterate buckets associated with an element; I is the iterator
- I FirstBucket( CElementHandlePram bucket ) const;
- I NextBucket( I idx ) const;
- CBucketHandle Bucket( I idx ) const;
-
- static S InvalidIndex();
-
- // Ensure capacity
- void EnsureCapacity( int count );
-
- // Deallocate....
- void Purge();
-
- int NumAllocated( void ) const;
-
-private:
- struct BucketListInfo_t
- {
- CElementHandle m_Element;
- S m_BucketListIndex; // what's the m_BucketsUsedByElement index of the entry?
- };
-
- struct ElementListInfo_t
- {
- CBucketHandle m_Bucket;
- S m_ElementListIndex; // what's the m_ElementsInBucket index of the entry?
- };
-
- // Maintains a list of all elements in a particular bucket
- CUtlLinkedList< BucketListInfo_t, S, true, I > m_ElementsInBucket;
-
- // Maintains a list of all buckets a particular element lives in
- CUtlLinkedList< ElementListInfo_t, S, true, I > m_BucketsUsedByElement;
-
- FirstBucketFunc_t m_FirstBucket;
- FirstElementFunc_t m_FirstElement;
-};
-
-
-//-----------------------------------------------------------------------------
-// Constructor
-//-----------------------------------------------------------------------------
-template< class CBucketHandle, class CElementHandle, class S, class I >
-CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::CBidirectionalSet( )
-{
- m_FirstBucket = NULL;
- m_FirstElement = NULL;
-}
-
-
-//-----------------------------------------------------------------------------
-// Call this before using the set
-//-----------------------------------------------------------------------------
-template< class CBucketHandle, class CElementHandle, class S, class I >
-void CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::Init( FirstElementFunc_t elemFunc, FirstBucketFunc_t bucketFunc )
-{
- m_FirstBucket = bucketFunc;
- m_FirstElement = elemFunc;
-}
-
-
-//-----------------------------------------------------------------------------
-// Adds an element to the bucket
-//-----------------------------------------------------------------------------
-template< class CBucketHandle, class CElementHandle, class S, class I >
-void CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::ValidateAddElementToBucket( CBucketHandlePram bucket, CElementHandlePram element )
-{
-#ifdef _DEBUG
- // Make sure that this element doesn't already exist in the list of elements in the bucket
- I elementInBucket = m_FirstElement( bucket );
- while( elementInBucket != m_ElementsInBucket.InvalidIndex() )
- {
- // If you hit an Assert here, fix the calling code. It's too expensive to ensure
- // that each item only shows up once here. Hopefully you can do something better
- // outside of here.
- Assert( m_ElementsInBucket[elementInBucket].m_Element != element );
- elementInBucket = m_ElementsInBucket.Next( elementInBucket );
- }
- // Make sure that this bucket doesn't already exist in the element's list of buckets.
- I bucketInElement = m_FirstBucket( element );
- while( bucketInElement != m_BucketsUsedByElement.InvalidIndex() )
- {
- // If you hit an Assert here, fix the calling code. It's too expensive to ensure
- // that each item only shows up once here. Hopefully you can do something better
- // outside of here.
- Assert( m_BucketsUsedByElement[bucketInElement].m_Bucket != bucket );
- bucketInElement = m_BucketsUsedByElement.Next( bucketInElement );
- }
-#endif
-}
-
-
-//-----------------------------------------------------------------------------
-// Adds an element to the bucket
-//-----------------------------------------------------------------------------
-template< class CBucketHandle, class CElementHandle, class S, class I >
-void CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::AddElementToBucket( CBucketHandlePram bucket, CElementHandlePram element )
-{
- Assert( m_FirstBucket && m_FirstElement );
-
- // Allocate new element + bucket entries
- I idx = m_ElementsInBucket.Alloc(true);
- I list = m_BucketsUsedByElement.Alloc( true );
-
- // Store off the element data
- m_ElementsInBucket[idx].m_Element = element;
- m_ElementsInBucket[idx].m_BucketListIndex = list;
-
- // Here's the bucket data
- m_BucketsUsedByElement[list].m_Bucket = bucket;
- m_BucketsUsedByElement[list].m_ElementListIndex = idx;
-
- // Insert the element into the list of elements in the bucket
- S& firstElementInBucket = m_FirstElement( bucket );
- if ( firstElementInBucket != m_ElementsInBucket.InvalidIndex() )
- m_ElementsInBucket.LinkBefore( firstElementInBucket, idx );
- firstElementInBucket = idx;
-
- // Insert the bucket into the element's list of buckets
- S& firstBucketInElement = m_FirstBucket( element );
- if ( firstBucketInElement != m_BucketsUsedByElement.InvalidIndex() )
- m_BucketsUsedByElement.LinkBefore( firstBucketInElement, list );
- firstBucketInElement = list;
-}
-
-//-----------------------------------------------------------------------------
-// Test if an element is in a particular bucket.
-// NOTE: EXPENSIVE!!!
-//-----------------------------------------------------------------------------
-template< class CBucketHandle, class CElementHandle, class S, class I >
-bool CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::IsElementInBucket( CBucketHandlePram bucket, CElementHandlePram element )
-{
- // Search through all elements in this bucket to see if element is in there.
- I elementInBucket = m_FirstElement( bucket );
- while( elementInBucket != m_ElementsInBucket.InvalidIndex() )
- {
- if( m_ElementsInBucket[elementInBucket].m_Element == element )
- {
- return true;
- }
- elementInBucket = m_ElementsInBucket.Next( elementInBucket );
- }
- return false;
-}
-
-
-//-----------------------------------------------------------------------------
-// Remove an element from a particular bucket
-//-----------------------------------------------------------------------------
-template< class CBucketHandle, class CElementHandle, class S, class I >
-void CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::RemoveElementFromBucket( CBucketHandlePram bucket, CElementHandlePram element )
-{
- // FIXME: Implement me!
- Assert(0);
-}
-
-
-//-----------------------------------------------------------------------------
-// Removes an element from all buckets
-//-----------------------------------------------------------------------------
-template< class CBucketHandle, class CElementHandle, class S, class I >
-void CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::RemoveElement( CElementHandlePram element )
-{
- Assert( m_FirstBucket && m_FirstElement );
-
- // Iterate over the list of all buckets the element is in
- I i = m_FirstBucket( element );
- while (i != m_BucketsUsedByElement.InvalidIndex())
- {
- CBucketHandlePram bucket = m_BucketsUsedByElement[i].m_Bucket;
- I elementListIndex = m_BucketsUsedByElement[i].m_ElementListIndex;
-
- // Unhook the element from the bucket's list of elements
- if (elementListIndex == m_FirstElement(bucket))
- m_FirstElement(bucket) = m_ElementsInBucket.Next(elementListIndex);
- m_ElementsInBucket.Free(elementListIndex);
-
- I prevNode = i;
- i = m_BucketsUsedByElement.Next(i);
- m_BucketsUsedByElement.Free(prevNode);
- }
-
- // Mark the list as empty
- m_FirstBucket( element ) = m_BucketsUsedByElement.InvalidIndex();
-}
-
-//-----------------------------------------------------------------------------
-// Removes a bucket from all elements
-//-----------------------------------------------------------------------------
-template< class CBucketHandle, class CElementHandle, class S, class I >
-void CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::RemoveBucket( CBucketHandlePram bucket )
-{
- // Iterate over the list of all elements in the bucket
- I i = m_FirstElement( bucket );
- while (i != m_ElementsInBucket.InvalidIndex())
- {
- CElementHandlePram element = m_ElementsInBucket[i].m_Element;
- I bucketListIndex = m_ElementsInBucket[i].m_BucketListIndex;
-
- // Unhook the bucket from the element's list of buckets
- if (bucketListIndex == m_FirstBucket(element))
- m_FirstBucket(element) = m_BucketsUsedByElement.Next(bucketListIndex);
- m_BucketsUsedByElement.Free(bucketListIndex);
-
- // Remove the list element
- I prevNode = i;
- i = m_ElementsInBucket.Next(i);
- m_ElementsInBucket.Free(prevNode);
- }
-
- // Mark the bucket list as empty
- m_FirstElement( bucket ) = m_ElementsInBucket.InvalidIndex();
-}
-
-
-//-----------------------------------------------------------------------------
-// Ensure capacity
-//-----------------------------------------------------------------------------
-template< class CBucketHandle, class CElementHandle, class S, class I >
-void CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::EnsureCapacity( int count )
-{
- m_ElementsInBucket.EnsureCapacity( count );
- m_BucketsUsedByElement.EnsureCapacity( count );
-}
-
-
-//-----------------------------------------------------------------------------
-// Deallocate....
-//-----------------------------------------------------------------------------
-template< class CBucketHandle, class CElementHandle, class S, class I >
-void CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::Purge()
-{
- m_ElementsInBucket.Purge( );
- m_BucketsUsedByElement.Purge( );
-}
-
-
-//-----------------------------------------------------------------------------
-// Number of elements allocated in each linked list (should be the same)
-//-----------------------------------------------------------------------------
-template< class CBucketHandle, class CElementHandle, class S, class I >
-int CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::NumAllocated( void ) const
-{
- Assert( m_ElementsInBucket.NumAllocated() == m_BucketsUsedByElement.NumAllocated() );
- return m_ElementsInBucket.NumAllocated();
-}
-
-
-//-----------------------------------------------------------------------------
-// Invalid index for iteration..
-//-----------------------------------------------------------------------------
-template< class CBucketHandle, class CElementHandle, class S, class I >
-inline S CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::InvalidIndex()
-{
- return CUtlLinkedList< CElementHandle, I >::InvalidIndex();
-}
-
-
-//-----------------------------------------------------------------------------
-// Used to iterate elements in a bucket; I is the iterator
-//-----------------------------------------------------------------------------
-template< class CBucketHandle, class CElementHandle, class S, class I >
-inline I CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::FirstElement( CBucketHandlePram bucket ) const
-{
- Assert( m_FirstElement );
- return m_FirstElement(bucket);
-}
-
-template< class CBucketHandle, class CElementHandle, class S, class I >
-inline I CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::NextElement( I idx ) const
-{
- return m_ElementsInBucket.Next(idx);
-}
-
-template< class CBucketHandle, class CElementHandle, class S, class I >
-inline CElementHandle CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::Element( I idx ) const
-{
- return m_ElementsInBucket[idx].m_Element;
-}
-
-//-----------------------------------------------------------------------------
-// Used to iterate buckets an element lies in; I is the iterator
-//-----------------------------------------------------------------------------
-template< class CBucketHandle, class CElementHandle, class S, class I >
-inline I CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::FirstBucket( CElementHandlePram element ) const
-{
- Assert( m_FirstBucket );
- return m_FirstBucket(element);
-}
-
-template< class CBucketHandle, class CElementHandle, class S, class I >
-inline I CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::NextBucket( I idx ) const
-{
- return m_BucketsUsedByElement.Next(idx);
-}
-
-template< class CBucketHandle, class CElementHandle, class S, class I >
-inline CBucketHandle CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::Bucket( I idx ) const
-{
- return m_BucketsUsedByElement[idx].m_Bucket;
-}
-
-#endif // UTLBIDIRECTIONALSET_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Bi-directional set. A Bucket knows about the elements that lie
+// in it, and the elements know about the buckets they lie in.
+//
+// $Revision: $
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef UTLBIDIRECTIONALSET_H
+#define UTLBIDIRECTIONALSET_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/dbg.h"
+#include "utllinkedlist.h"
+
+//-----------------------------------------------------------------------------
+// Templatized helper class to deal with the kinds of things that spatial
+// partition code always seems to have; buckets with lists of lots of elements
+// and elements that live in lots of buckets. This makes it really quick to
+// add and remove elements, and to iterate over all elements in a bucket.
+//
+// For this to work, you must initialize the set with two functions one that
+// maps from bucket to the index of the first element in that bucket, and one
+// that maps from element to the index of the first bucket that element lies in.
+// The set will completely manage the index, it's just expected that those
+// indices will be stored outside the set.
+//
+// S is the storage type of the index; it is the type that you may use to
+// save indices into memory. I is the local iterator type, which you should
+// use in any local scope (eg, inside a for() loop.) The reason for this is
+// that you may wish to use unsigned shorts inside the structs you are
+// saving with a CBidirectionalSet; but 16-bit arithmetic is catastrophically
+// slow on a PowerPC -- during testing we saw CBidirectionalSet:: operations
+// consume as much as 8% of the frame.
+//
+// For this reason, on the 360, the handles have been typedef'd to native
+// register types (U32) which are accepted as parameters by the functions.
+// The implicit assumption is that CBucketHandle and CElementHandle can
+// be safely cast to ints! You can increase to U64 without performance
+// penalty if necessary; the PowerPC is a 64-bit processor.
+//-----------------------------------------------------------------------------
+template< class CBucketHandle, class CElementHandle, class S, class I = S >
+class CBidirectionalSet
+{
+public:
+ // Install methods to get at the first bucket given a element
+ // and vice versa...
+ typedef S& (*FirstElementFunc_t)(CBucketHandle);
+ typedef S& (*FirstBucketFunc_t)(CElementHandle);
+
+#ifdef _X360
+ typedef uint32 CBucketHandlePram;
+ typedef uint32 CElementHandlePram;
+#else
+ typedef CBucketHandle CBucketHandlePram;
+ typedef CElementHandle CElementHandlePram;
+#endif
+
+ // Constructor
+ CBidirectionalSet();
+
+ // Call this before using the set
+ void Init( FirstElementFunc_t elemFunc, FirstBucketFunc_t bucketFunc );
+
+ // Add an element to a particular bucket
+ void AddElementToBucket( CBucketHandlePram bucket, CElementHandlePram element );
+
+ // Prevalidate an add to a particular bucket
+ // NOTE: EXPENSIVE!!!
+ void ValidateAddElementToBucket( CBucketHandlePram bucket, CElementHandlePram element );
+
+ // Test if an element is in a particular bucket.
+ // NOTE: EXPENSIVE!!!
+ bool IsElementInBucket( CBucketHandlePram bucket, CElementHandlePram element );
+
+ // Remove an element from a particular bucket
+ void RemoveElementFromBucket( CBucketHandlePram bucket, CElementHandlePram element );
+
+ // Remove an element from all buckets
+ void RemoveElement( CElementHandlePram element );
+ void RemoveBucket( CBucketHandlePram element );
+
+ // Used to iterate elements in a bucket; I is the iterator
+ I FirstElement( CBucketHandlePram bucket ) const;
+ I NextElement( I idx ) const;
+ CElementHandle Element( I idx ) const;
+
+ // Used to iterate buckets associated with an element; I is the iterator
+ I FirstBucket( CElementHandlePram bucket ) const;
+ I NextBucket( I idx ) const;
+ CBucketHandle Bucket( I idx ) const;
+
+ static S InvalidIndex();
+
+ // Ensure capacity
+ void EnsureCapacity( int count );
+
+ // Deallocate....
+ void Purge();
+
+ int NumAllocated( void ) const;
+
+private:
+ struct BucketListInfo_t
+ {
+ CElementHandle m_Element;
+ S m_BucketListIndex; // what's the m_BucketsUsedByElement index of the entry?
+ };
+
+ struct ElementListInfo_t
+ {
+ CBucketHandle m_Bucket;
+ S m_ElementListIndex; // what's the m_ElementsInBucket index of the entry?
+ };
+
+ // Maintains a list of all elements in a particular bucket
+ CUtlLinkedList< BucketListInfo_t, S, true, I > m_ElementsInBucket;
+
+ // Maintains a list of all buckets a particular element lives in
+ CUtlLinkedList< ElementListInfo_t, S, true, I > m_BucketsUsedByElement;
+
+ FirstBucketFunc_t m_FirstBucket;
+ FirstElementFunc_t m_FirstElement;
+};
+
+
+//-----------------------------------------------------------------------------
+// Constructor
+//-----------------------------------------------------------------------------
+template< class CBucketHandle, class CElementHandle, class S, class I >
+CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::CBidirectionalSet( )
+{
+ m_FirstBucket = NULL;
+ m_FirstElement = NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// Call this before using the set
+//-----------------------------------------------------------------------------
+template< class CBucketHandle, class CElementHandle, class S, class I >
+void CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::Init( FirstElementFunc_t elemFunc, FirstBucketFunc_t bucketFunc )
+{
+ m_FirstBucket = bucketFunc;
+ m_FirstElement = elemFunc;
+}
+
+
+//-----------------------------------------------------------------------------
+// Adds an element to the bucket
+//-----------------------------------------------------------------------------
+template< class CBucketHandle, class CElementHandle, class S, class I >
+void CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::ValidateAddElementToBucket( CBucketHandlePram bucket, CElementHandlePram element )
+{
+#ifdef _DEBUG
+ // Make sure that this element doesn't already exist in the list of elements in the bucket
+ I elementInBucket = m_FirstElement( bucket );
+ while( elementInBucket != m_ElementsInBucket.InvalidIndex() )
+ {
+ // If you hit an Assert here, fix the calling code. It's too expensive to ensure
+ // that each item only shows up once here. Hopefully you can do something better
+ // outside of here.
+ Assert( m_ElementsInBucket[elementInBucket].m_Element != element );
+ elementInBucket = m_ElementsInBucket.Next( elementInBucket );
+ }
+ // Make sure that this bucket doesn't already exist in the element's list of buckets.
+ I bucketInElement = m_FirstBucket( element );
+ while( bucketInElement != m_BucketsUsedByElement.InvalidIndex() )
+ {
+ // If you hit an Assert here, fix the calling code. It's too expensive to ensure
+ // that each item only shows up once here. Hopefully you can do something better
+ // outside of here.
+ Assert( m_BucketsUsedByElement[bucketInElement].m_Bucket != bucket );
+ bucketInElement = m_BucketsUsedByElement.Next( bucketInElement );
+ }
+#endif
+}
+
+
+//-----------------------------------------------------------------------------
+// Adds an element to the bucket
+//-----------------------------------------------------------------------------
+template< class CBucketHandle, class CElementHandle, class S, class I >
+void CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::AddElementToBucket( CBucketHandlePram bucket, CElementHandlePram element )
+{
+ Assert( m_FirstBucket && m_FirstElement );
+
+ // Allocate new element + bucket entries
+ I idx = m_ElementsInBucket.Alloc(true);
+ I list = m_BucketsUsedByElement.Alloc( true );
+
+ // Store off the element data
+ m_ElementsInBucket[idx].m_Element = element;
+ m_ElementsInBucket[idx].m_BucketListIndex = list;
+
+ // Here's the bucket data
+ m_BucketsUsedByElement[list].m_Bucket = bucket;
+ m_BucketsUsedByElement[list].m_ElementListIndex = idx;
+
+ // Insert the element into the list of elements in the bucket
+ S& firstElementInBucket = m_FirstElement( bucket );
+ if ( firstElementInBucket != m_ElementsInBucket.InvalidIndex() )
+ m_ElementsInBucket.LinkBefore( firstElementInBucket, idx );
+ firstElementInBucket = idx;
+
+ // Insert the bucket into the element's list of buckets
+ S& firstBucketInElement = m_FirstBucket( element );
+ if ( firstBucketInElement != m_BucketsUsedByElement.InvalidIndex() )
+ m_BucketsUsedByElement.LinkBefore( firstBucketInElement, list );
+ firstBucketInElement = list;
+}
+
+//-----------------------------------------------------------------------------
+// Test if an element is in a particular bucket.
+// NOTE: EXPENSIVE!!!
+//-----------------------------------------------------------------------------
+template< class CBucketHandle, class CElementHandle, class S, class I >
+bool CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::IsElementInBucket( CBucketHandlePram bucket, CElementHandlePram element )
+{
+ // Search through all elements in this bucket to see if element is in there.
+ I elementInBucket = m_FirstElement( bucket );
+ while( elementInBucket != m_ElementsInBucket.InvalidIndex() )
+ {
+ if( m_ElementsInBucket[elementInBucket].m_Element == element )
+ {
+ return true;
+ }
+ elementInBucket = m_ElementsInBucket.Next( elementInBucket );
+ }
+ return false;
+}
+
+
+//-----------------------------------------------------------------------------
+// Remove an element from a particular bucket
+//-----------------------------------------------------------------------------
+template< class CBucketHandle, class CElementHandle, class S, class I >
+void CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::RemoveElementFromBucket( CBucketHandlePram bucket, CElementHandlePram element )
+{
+ // FIXME: Implement me!
+ Assert(0);
+}
+
+
+//-----------------------------------------------------------------------------
+// Removes an element from all buckets
+//-----------------------------------------------------------------------------
+template< class CBucketHandle, class CElementHandle, class S, class I >
+void CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::RemoveElement( CElementHandlePram element )
+{
+ Assert( m_FirstBucket && m_FirstElement );
+
+ // Iterate over the list of all buckets the element is in
+ I i = m_FirstBucket( element );
+ while (i != m_BucketsUsedByElement.InvalidIndex())
+ {
+ CBucketHandlePram bucket = m_BucketsUsedByElement[i].m_Bucket;
+ I elementListIndex = m_BucketsUsedByElement[i].m_ElementListIndex;
+
+ // Unhook the element from the bucket's list of elements
+ if (elementListIndex == m_FirstElement(bucket))
+ m_FirstElement(bucket) = m_ElementsInBucket.Next(elementListIndex);
+ m_ElementsInBucket.Free(elementListIndex);
+
+ I prevNode = i;
+ i = m_BucketsUsedByElement.Next(i);
+ m_BucketsUsedByElement.Free(prevNode);
+ }
+
+ // Mark the list as empty
+ m_FirstBucket( element ) = m_BucketsUsedByElement.InvalidIndex();
+}
+
+//-----------------------------------------------------------------------------
+// Removes a bucket from all elements
+//-----------------------------------------------------------------------------
+template< class CBucketHandle, class CElementHandle, class S, class I >
+void CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::RemoveBucket( CBucketHandlePram bucket )
+{
+ // Iterate over the list of all elements in the bucket
+ I i = m_FirstElement( bucket );
+ while (i != m_ElementsInBucket.InvalidIndex())
+ {
+ CElementHandlePram element = m_ElementsInBucket[i].m_Element;
+ I bucketListIndex = m_ElementsInBucket[i].m_BucketListIndex;
+
+ // Unhook the bucket from the element's list of buckets
+ if (bucketListIndex == m_FirstBucket(element))
+ m_FirstBucket(element) = m_BucketsUsedByElement.Next(bucketListIndex);
+ m_BucketsUsedByElement.Free(bucketListIndex);
+
+ // Remove the list element
+ I prevNode = i;
+ i = m_ElementsInBucket.Next(i);
+ m_ElementsInBucket.Free(prevNode);
+ }
+
+ // Mark the bucket list as empty
+ m_FirstElement( bucket ) = m_ElementsInBucket.InvalidIndex();
+}
+
+
+//-----------------------------------------------------------------------------
+// Ensure capacity
+//-----------------------------------------------------------------------------
+template< class CBucketHandle, class CElementHandle, class S, class I >
+void CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::EnsureCapacity( int count )
+{
+ m_ElementsInBucket.EnsureCapacity( count );
+ m_BucketsUsedByElement.EnsureCapacity( count );
+}
+
+
+//-----------------------------------------------------------------------------
+// Deallocate....
+//-----------------------------------------------------------------------------
+template< class CBucketHandle, class CElementHandle, class S, class I >
+void CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::Purge()
+{
+ m_ElementsInBucket.Purge( );
+ m_BucketsUsedByElement.Purge( );
+}
+
+
+//-----------------------------------------------------------------------------
+// Number of elements allocated in each linked list (should be the same)
+//-----------------------------------------------------------------------------
+template< class CBucketHandle, class CElementHandle, class S, class I >
+int CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::NumAllocated( void ) const
+{
+ Assert( m_ElementsInBucket.NumAllocated() == m_BucketsUsedByElement.NumAllocated() );
+ return m_ElementsInBucket.NumAllocated();
+}
+
+
+//-----------------------------------------------------------------------------
+// Invalid index for iteration..
+//-----------------------------------------------------------------------------
+template< class CBucketHandle, class CElementHandle, class S, class I >
+inline S CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::InvalidIndex()
+{
+ return CUtlLinkedList< CElementHandle, I >::InvalidIndex();
+}
+
+
+//-----------------------------------------------------------------------------
+// Used to iterate elements in a bucket; I is the iterator
+//-----------------------------------------------------------------------------
+template< class CBucketHandle, class CElementHandle, class S, class I >
+inline I CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::FirstElement( CBucketHandlePram bucket ) const
+{
+ Assert( m_FirstElement );
+ return m_FirstElement(bucket);
+}
+
+template< class CBucketHandle, class CElementHandle, class S, class I >
+inline I CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::NextElement( I idx ) const
+{
+ return m_ElementsInBucket.Next(idx);
+}
+
+template< class CBucketHandle, class CElementHandle, class S, class I >
+inline CElementHandle CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::Element( I idx ) const
+{
+ return m_ElementsInBucket[idx].m_Element;
+}
+
+//-----------------------------------------------------------------------------
+// Used to iterate buckets an element lies in; I is the iterator
+//-----------------------------------------------------------------------------
+template< class CBucketHandle, class CElementHandle, class S, class I >
+inline I CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::FirstBucket( CElementHandlePram element ) const
+{
+ Assert( m_FirstBucket );
+ return m_FirstBucket(element);
+}
+
+template< class CBucketHandle, class CElementHandle, class S, class I >
+inline I CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::NextBucket( I idx ) const
+{
+ return m_BucketsUsedByElement.Next(idx);
+}
+
+template< class CBucketHandle, class CElementHandle, class S, class I >
+inline CBucketHandle CBidirectionalSet<CBucketHandle,CElementHandle,S,I>::Bucket( I idx ) const
+{
+ return m_BucketsUsedByElement[idx].m_Bucket;
+}
+
+#endif // UTLBIDIRECTIONALSET_H
diff --git a/mp/src/public/tier1/utlblockmemory.h b/mp/src/public/tier1/utlblockmemory.h
index 8ceb0a2b..69885060 100644
--- a/mp/src/public/tier1/utlblockmemory.h
+++ b/mp/src/public/tier1/utlblockmemory.h
@@ -1,349 +1,349 @@
-//========= Copyright 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 )
-{
- swap( m_pMemory, mem.m_pMemory );
- swap( m_nBlocks, mem.m_nBlocks );
- swap( m_nIndexMask, mem.m_nIndexMask );
- 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
+//========= Copyright 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 )
+{
+ swap( m_pMemory, mem.m_pMemory );
+ swap( m_nBlocks, mem.m_nBlocks );
+ swap( m_nIndexMask, mem.m_nIndexMask );
+ 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/mp/src/public/tier1/utlbuffer.h b/mp/src/public/tier1/utlbuffer.h
index 82c42f9b..4213dd6a 100644
--- a/mp/src/public/tier1/utlbuffer.h
+++ b/mp/src/public/tier1/utlbuffer.h
@@ -1,1084 +1,1084 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//
-// Serialization/unserialization buffer
-//=============================================================================//
-
-#ifndef UTLBUFFER_H
-#define UTLBUFFER_H
-
-#ifdef _WIN32
-#pragma once
-#endif
-
-#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;
- const 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;
- const 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 ) )
-
-
-//-----------------------------------------------------------------------------
-// Command parsing..
-//-----------------------------------------------------------------------------
-class CUtlBuffer
-{
-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 );
-
- // Attaches the buffer to external memory....
- void SetExternalBuffer( void* pMemory, int nSize, int nInitialPut, int nFlags = 0 );
- bool IsExternallyAllocated() const;
- // Takes ownership of the passed memory, including freeing it when this buffer is destroyed.
- void AssumeMemory( void *pMemory, int nSize, int nInitialPut, int nFlags = 0 );
-
- // copies data from another buffer
- void CopyBuffer( const CUtlBuffer &buffer );
- void CopyBuffer( const void *pubData, int cubData );
-
- void Swap( CUtlBuffer &buf );
- void Swap( CUtlMemory<uint8> &mem );
-
- FORCEINLINE void ActivateByteSwappingIfBigEndian( void )
- {
- if ( IsX360() )
- 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();
-
- // 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( );
- int GetIntHex( );
- unsigned int GetUnsignedInt( );
- float GetFloat( );
- double GetDouble( );
- 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( SCANF_FORMAT_STRING 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 PutUint64( uint64 ub );
- void PutInt16( int16 s16 );
- 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 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( PRINTF_FORMAT_STRING 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();
- // Returns the base as a const char*, only valid in text mode.
- const char *String() const;
-
- // 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 );
-
-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 );
-
- void AddNullTermination( );
-
- // 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, const char *pszFmt );
- template <typename T> void GetTypeBin( T& dest );
- template <typename T> void GetObject( T *src );
-
- template <typename T> void PutType( T src, const char *pszFmt );
- template <typename T> void PutTypeBin( T src );
- template <typename T> void PutObject( T *src );
-
- 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( _X360 )
- 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
- {
- Q_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 ) ) )
- {
- uintptr_t pData = (uintptr_t)PeekGet();
- if ( IsX360() && ( 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 <typename T>
-inline void CUtlBuffer::GetType( T &dest, const char *pszFmt )
-{
- if (!IsText())
- {
- GetTypeBin( dest );
- }
- else
- {
- dest = 0;
- Scanf( pszFmt, &dest );
- }
-}
-
-inline char CUtlBuffer::GetChar( )
-{
- char c;
- GetType( c, "%c" );
- return c;
-}
-
-inline unsigned char CUtlBuffer::GetUnsignedChar( )
-{
- unsigned char c;
- GetType( c, "%u" );
- return c;
-}
-
-inline short CUtlBuffer::GetShort( )
-{
- short s;
- GetType( s, "%d" );
- return s;
-}
-
-inline unsigned short CUtlBuffer::GetUnsignedShort( )
-{
- unsigned short s;
- GetType( s, "%u" );
- return s;
-}
-
-inline int CUtlBuffer::GetInt( )
-{
- int i;
- GetType( i, "%d" );
- return i;
-}
-
-inline int64 CUtlBuffer::GetInt64( )
-{
- int64 i;
- GetType( i, "%lld" );
- return i;
-}
-
-inline int CUtlBuffer::GetIntHex( )
-{
- int i;
- GetType( i, "%x" );
- return i;
-}
-
-inline unsigned int CUtlBuffer::GetUnsignedInt( )
-{
- unsigned int u;
- GetType( u, "%u" );
- return u;
-}
-
-inline float CUtlBuffer::GetFloat( )
-{
- float f;
- GetType( f, "%f" );
- return f;
-}
-
-inline double CUtlBuffer::GetDouble( )
-{
- double d;
- GetType( d, "%f" );
- return d;
-}
-
-
-//-----------------------------------------------------------------------------
-// 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();
- }
-}
-
-
-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();
- }
-}
-
-template <typename T>
-inline void CUtlBuffer::PutType( T src, const char *pszFmt )
-{
- if (!IsText())
- {
- PutTypeBin( src );
- }
- else
- {
- Printf( pszFmt, 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 )
-{
- PutType( c, "%u" );
-}
-
-inline void CUtlBuffer::PutUint64( uint64 ub )
-{
- PutType( ub, "%llu" );
-}
-
-inline void CUtlBuffer::PutInt16( int16 s16 )
-{
- PutType( s16, "%d" );
-}
-
-inline void CUtlBuffer::PutShort( short s )
-{
- PutType( s, "%d" );
-}
-
-inline void CUtlBuffer::PutUnsignedShort( unsigned short s )
-{
- PutType( s, "%u" );
-}
-
-inline void CUtlBuffer::PutInt( int i )
-{
- PutType( i, "%d" );
-}
-
-inline void CUtlBuffer::PutInt64( int64 i )
-{
- PutType( i, "%llu" );
-}
-
-inline void CUtlBuffer::PutUnsignedInt( unsigned int u )
-{
- PutType( u, "%u" );
-}
-
-inline void CUtlBuffer::PutFloat( float f )
-{
- PutType( f, "%f" );
-}
-
-inline void CUtlBuffer::PutDouble( double d )
-{
- PutType( d, "%f" );
-}
-
-
-//-----------------------------------------------------------------------------
-// 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();
-}
-
-// Returns the base as a const char*, only valid in text mode.
-inline const char *CUtlBuffer::String() const
-{
- Assert( IsText() );
- return reinterpret_cast<const char*>( 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();
-}
-
-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::CopyBuffer( const CUtlBuffer &buffer )
-{
- CopyBuffer( buffer.Base(), buffer.TellPut() );
-}
-
-inline void CUtlBuffer::CopyBuffer( const void *pubData, int cubData )
-{
- Clear();
- if ( cubData )
- {
- Put( pubData, cubData );
- }
-}
-
-#endif // UTLBUFFER_H
-
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+// Serialization/unserialization buffer
+//=============================================================================//
+
+#ifndef UTLBUFFER_H
+#define UTLBUFFER_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#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;
+ const 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;
+ const 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 ) )
+
+
+//-----------------------------------------------------------------------------
+// Command parsing..
+//-----------------------------------------------------------------------------
+class CUtlBuffer
+{
+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 );
+
+ // Attaches the buffer to external memory....
+ void SetExternalBuffer( void* pMemory, int nSize, int nInitialPut, int nFlags = 0 );
+ bool IsExternallyAllocated() const;
+ // Takes ownership of the passed memory, including freeing it when this buffer is destroyed.
+ void AssumeMemory( void *pMemory, int nSize, int nInitialPut, int nFlags = 0 );
+
+ // copies data from another buffer
+ void CopyBuffer( const CUtlBuffer &buffer );
+ void CopyBuffer( const void *pubData, int cubData );
+
+ void Swap( CUtlBuffer &buf );
+ void Swap( CUtlMemory<uint8> &mem );
+
+ FORCEINLINE void ActivateByteSwappingIfBigEndian( void )
+ {
+ if ( IsX360() )
+ 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();
+
+ // 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( );
+ int GetIntHex( );
+ unsigned int GetUnsignedInt( );
+ float GetFloat( );
+ double GetDouble( );
+ 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( SCANF_FORMAT_STRING 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 PutUint64( uint64 ub );
+ void PutInt16( int16 s16 );
+ 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 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( PRINTF_FORMAT_STRING 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();
+ // Returns the base as a const char*, only valid in text mode.
+ const char *String() const;
+
+ // 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 );
+
+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 );
+
+ void AddNullTermination( );
+
+ // 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, const char *pszFmt );
+ template <typename T> void GetTypeBin( T& dest );
+ template <typename T> void GetObject( T *src );
+
+ template <typename T> void PutType( T src, const char *pszFmt );
+ template <typename T> void PutTypeBin( T src );
+ template <typename T> void PutObject( T *src );
+
+ 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( _X360 )
+ 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
+ {
+ Q_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 ) ) )
+ {
+ uintptr_t pData = (uintptr_t)PeekGet();
+ if ( IsX360() && ( 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 <typename T>
+inline void CUtlBuffer::GetType( T &dest, const char *pszFmt )
+{
+ if (!IsText())
+ {
+ GetTypeBin( dest );
+ }
+ else
+ {
+ dest = 0;
+ Scanf( pszFmt, &dest );
+ }
+}
+
+inline char CUtlBuffer::GetChar( )
+{
+ char c;
+ GetType( c, "%c" );
+ return c;
+}
+
+inline unsigned char CUtlBuffer::GetUnsignedChar( )
+{
+ unsigned char c;
+ GetType( c, "%u" );
+ return c;
+}
+
+inline short CUtlBuffer::GetShort( )
+{
+ short s;
+ GetType( s, "%d" );
+ return s;
+}
+
+inline unsigned short CUtlBuffer::GetUnsignedShort( )
+{
+ unsigned short s;
+ GetType( s, "%u" );
+ return s;
+}
+
+inline int CUtlBuffer::GetInt( )
+{
+ int i;
+ GetType( i, "%d" );
+ return i;
+}
+
+inline int64 CUtlBuffer::GetInt64( )
+{
+ int64 i;
+ GetType( i, "%lld" );
+ return i;
+}
+
+inline int CUtlBuffer::GetIntHex( )
+{
+ int i;
+ GetType( i, "%x" );
+ return i;
+}
+
+inline unsigned int CUtlBuffer::GetUnsignedInt( )
+{
+ unsigned int u;
+ GetType( u, "%u" );
+ return u;
+}
+
+inline float CUtlBuffer::GetFloat( )
+{
+ float f;
+ GetType( f, "%f" );
+ return f;
+}
+
+inline double CUtlBuffer::GetDouble( )
+{
+ double d;
+ GetType( d, "%f" );
+ return d;
+}
+
+
+//-----------------------------------------------------------------------------
+// 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();
+ }
+}
+
+
+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();
+ }
+}
+
+template <typename T>
+inline void CUtlBuffer::PutType( T src, const char *pszFmt )
+{
+ if (!IsText())
+ {
+ PutTypeBin( src );
+ }
+ else
+ {
+ Printf( pszFmt, 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 )
+{
+ PutType( c, "%u" );
+}
+
+inline void CUtlBuffer::PutUint64( uint64 ub )
+{
+ PutType( ub, "%llu" );
+}
+
+inline void CUtlBuffer::PutInt16( int16 s16 )
+{
+ PutType( s16, "%d" );
+}
+
+inline void CUtlBuffer::PutShort( short s )
+{
+ PutType( s, "%d" );
+}
+
+inline void CUtlBuffer::PutUnsignedShort( unsigned short s )
+{
+ PutType( s, "%u" );
+}
+
+inline void CUtlBuffer::PutInt( int i )
+{
+ PutType( i, "%d" );
+}
+
+inline void CUtlBuffer::PutInt64( int64 i )
+{
+ PutType( i, "%llu" );
+}
+
+inline void CUtlBuffer::PutUnsignedInt( unsigned int u )
+{
+ PutType( u, "%u" );
+}
+
+inline void CUtlBuffer::PutFloat( float f )
+{
+ PutType( f, "%f" );
+}
+
+inline void CUtlBuffer::PutDouble( double d )
+{
+ PutType( d, "%f" );
+}
+
+
+//-----------------------------------------------------------------------------
+// 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();
+}
+
+// Returns the base as a const char*, only valid in text mode.
+inline const char *CUtlBuffer::String() const
+{
+ Assert( IsText() );
+ return reinterpret_cast<const char*>( 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();
+}
+
+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::CopyBuffer( const CUtlBuffer &buffer )
+{
+ CopyBuffer( buffer.Base(), buffer.TellPut() );
+}
+
+inline void CUtlBuffer::CopyBuffer( const void *pubData, int cubData )
+{
+ Clear();
+ if ( cubData )
+ {
+ Put( pubData, cubData );
+ }
+}
+
+#endif // UTLBUFFER_H
+
diff --git a/mp/src/public/tier1/utlbufferutil.h b/mp/src/public/tier1/utlbufferutil.h
index a5b1c9f2..a52a528a 100644
--- a/mp/src/public/tier1/utlbufferutil.h
+++ b/mp/src/public/tier1/utlbufferutil.h
@@ -1,192 +1,192 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//
-// Utilities for serialization/unserialization buffer
-//=============================================================================//
-
-#ifndef UTLBUFFERUTIL_H
-#define UTLBUFFERUTIL_H
-
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include "tier1/utlvector.h"
-#include "tier1/utlbuffer.h"
-
-
-//-----------------------------------------------------------------------------
-// Forward declarations
-//-----------------------------------------------------------------------------
-class Vector2D;
-class Vector;
-class Vector4D;
-class QAngle;
-class Quaternion;
-class VMatrix;
-class Color;
-class CUtlBinaryBlock;
-class CUtlString;
-class CUtlCharConversion;
-
-
-//-----------------------------------------------------------------------------
-// For string serialization, set the delimiter rules
-//-----------------------------------------------------------------------------
-void SetSerializationDelimiter( CUtlCharConversion *pConv );
-void SetSerializationArrayDelimiter( const char *pDelimiter );
-
-
-//-----------------------------------------------------------------------------
-// Standard serialization methods for basic types
-//-----------------------------------------------------------------------------
-bool Serialize( CUtlBuffer &buf, const bool &src );
-bool Unserialize( CUtlBuffer &buf, bool &dest );
-
-bool Serialize( CUtlBuffer &buf, const int &src );
-bool Unserialize( CUtlBuffer &buf, int &dest );
-
-bool Serialize( CUtlBuffer &buf, const float &src );
-bool Unserialize( CUtlBuffer &buf, float &dest );
-
-bool Serialize( CUtlBuffer &buf, const Vector2D &src );
-bool Unserialize( CUtlBuffer &buf, Vector2D &dest );
-
-bool Serialize( CUtlBuffer &buf, const Vector &src );
-bool Unserialize( CUtlBuffer &buf, Vector &dest );
-
-bool Serialize( CUtlBuffer &buf, const Vector4D &src );
-bool Unserialize( CUtlBuffer &buf, Vector4D &dest );
-
-bool Serialize( CUtlBuffer &buf, const QAngle &src );
-bool Unserialize( CUtlBuffer &buf, QAngle &dest );
-
-bool Serialize( CUtlBuffer &buf, const Quaternion &src );
-bool Unserialize( CUtlBuffer &buf, Quaternion &dest );
-
-bool Serialize( CUtlBuffer &buf, const VMatrix &src );
-bool Unserialize( CUtlBuffer &buf, VMatrix &dest );
-
-bool Serialize( CUtlBuffer &buf, const Color &src );
-bool Unserialize( CUtlBuffer &buf, Color &dest );
-
-bool Serialize( CUtlBuffer &buf, const CUtlBinaryBlock &src );
-bool Unserialize( CUtlBuffer &buf, CUtlBinaryBlock &dest );
-
-bool Serialize( CUtlBuffer &buf, const CUtlString &src );
-bool Unserialize( CUtlBuffer &buf, CUtlString &dest );
-
-
-//-----------------------------------------------------------------------------
-// You can use this to check if a type serializes on multiple lines
-//-----------------------------------------------------------------------------
-template< class T >
-inline bool SerializesOnMultipleLines()
-{
- return false;
-}
-
-template< >
-inline bool SerializesOnMultipleLines<VMatrix>()
-{
- return true;
-}
-
-template< >
-inline bool SerializesOnMultipleLines<CUtlBinaryBlock>()
-{
- return true;
-}
-
-
-//-----------------------------------------------------------------------------
-// Vector serialization
-//-----------------------------------------------------------------------------
-template< class T >
-bool Serialize( CUtlBuffer &buf, const CUtlVector<T> &src )
-{
- extern const char *s_pUtlBufferUtilArrayDelim;
-
- int nCount = src.Count();
-
- if ( !buf.IsText() )
- {
- buf.PutInt( nCount );
- for ( int i = 0; i < nCount; ++i )
- {
- ::Serialize( buf, src[i] );
- }
- return buf.IsValid();
- }
-
- if ( !SerializesOnMultipleLines<T>() )
- {
- buf.PutChar('\n');
- for ( int i = 0; i < nCount; ++i )
- {
- ::Serialize( buf, src[i] );
- if ( s_pUtlBufferUtilArrayDelim && (i != nCount-1) )
- {
- buf.PutString( s_pUtlBufferUtilArrayDelim );
- }
- buf.PutChar('\n');
- }
- }
- else
- {
- for ( int i = 0; i < nCount; ++i )
- {
- ::Serialize( buf, src[i] );
- if ( s_pUtlBufferUtilArrayDelim && (i != nCount-1) )
- {
- buf.PutString( s_pUtlBufferUtilArrayDelim );
- }
- buf.PutChar(' ');
- }
- }
-
- return buf.IsValid();
-}
-
-template< class T >
-bool Unserialize( CUtlBuffer &buf, CUtlVector<T> &dest )
-{
- dest.RemoveAll();
-
- MEM_ALLOC_CREDIT_FUNCTION();
-
- if ( !buf.IsText() )
- {
- int nCount = buf.GetInt();
- if ( nCount )
- {
- dest.EnsureCapacity( nCount );
- for ( int i = 0; i < nCount; ++i )
- {
- VerifyEquals( dest.AddToTail(), i );
- if ( !::Unserialize( buf, dest[i] ) )
- return false;
- }
- }
- return buf.IsValid();
- }
-
- while ( true )
- {
- buf.EatWhiteSpace();
- if ( !buf.IsValid() )
- break;
-
- int i = dest.AddToTail( );
- if ( ! ::Unserialize( buf, dest[i] ) )
- return false;
- }
- return true;
-}
-
-
-#endif // UTLBUFFERUTIL_H
-
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+// Utilities for serialization/unserialization buffer
+//=============================================================================//
+
+#ifndef UTLBUFFERUTIL_H
+#define UTLBUFFERUTIL_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier1/utlvector.h"
+#include "tier1/utlbuffer.h"
+
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+class Vector2D;
+class Vector;
+class Vector4D;
+class QAngle;
+class Quaternion;
+class VMatrix;
+class Color;
+class CUtlBinaryBlock;
+class CUtlString;
+class CUtlCharConversion;
+
+
+//-----------------------------------------------------------------------------
+// For string serialization, set the delimiter rules
+//-----------------------------------------------------------------------------
+void SetSerializationDelimiter( CUtlCharConversion *pConv );
+void SetSerializationArrayDelimiter( const char *pDelimiter );
+
+
+//-----------------------------------------------------------------------------
+// Standard serialization methods for basic types
+//-----------------------------------------------------------------------------
+bool Serialize( CUtlBuffer &buf, const bool &src );
+bool Unserialize( CUtlBuffer &buf, bool &dest );
+
+bool Serialize( CUtlBuffer &buf, const int &src );
+bool Unserialize( CUtlBuffer &buf, int &dest );
+
+bool Serialize( CUtlBuffer &buf, const float &src );
+bool Unserialize( CUtlBuffer &buf, float &dest );
+
+bool Serialize( CUtlBuffer &buf, const Vector2D &src );
+bool Unserialize( CUtlBuffer &buf, Vector2D &dest );
+
+bool Serialize( CUtlBuffer &buf, const Vector &src );
+bool Unserialize( CUtlBuffer &buf, Vector &dest );
+
+bool Serialize( CUtlBuffer &buf, const Vector4D &src );
+bool Unserialize( CUtlBuffer &buf, Vector4D &dest );
+
+bool Serialize( CUtlBuffer &buf, const QAngle &src );
+bool Unserialize( CUtlBuffer &buf, QAngle &dest );
+
+bool Serialize( CUtlBuffer &buf, const Quaternion &src );
+bool Unserialize( CUtlBuffer &buf, Quaternion &dest );
+
+bool Serialize( CUtlBuffer &buf, const VMatrix &src );
+bool Unserialize( CUtlBuffer &buf, VMatrix &dest );
+
+bool Serialize( CUtlBuffer &buf, const Color &src );
+bool Unserialize( CUtlBuffer &buf, Color &dest );
+
+bool Serialize( CUtlBuffer &buf, const CUtlBinaryBlock &src );
+bool Unserialize( CUtlBuffer &buf, CUtlBinaryBlock &dest );
+
+bool Serialize( CUtlBuffer &buf, const CUtlString &src );
+bool Unserialize( CUtlBuffer &buf, CUtlString &dest );
+
+
+//-----------------------------------------------------------------------------
+// You can use this to check if a type serializes on multiple lines
+//-----------------------------------------------------------------------------
+template< class T >
+inline bool SerializesOnMultipleLines()
+{
+ return false;
+}
+
+template< >
+inline bool SerializesOnMultipleLines<VMatrix>()
+{
+ return true;
+}
+
+template< >
+inline bool SerializesOnMultipleLines<CUtlBinaryBlock>()
+{
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Vector serialization
+//-----------------------------------------------------------------------------
+template< class T >
+bool Serialize( CUtlBuffer &buf, const CUtlVector<T> &src )
+{
+ extern const char *s_pUtlBufferUtilArrayDelim;
+
+ int nCount = src.Count();
+
+ if ( !buf.IsText() )
+ {
+ buf.PutInt( nCount );
+ for ( int i = 0; i < nCount; ++i )
+ {
+ ::Serialize( buf, src[i] );
+ }
+ return buf.IsValid();
+ }
+
+ if ( !SerializesOnMultipleLines<T>() )
+ {
+ buf.PutChar('\n');
+ for ( int i = 0; i < nCount; ++i )
+ {
+ ::Serialize( buf, src[i] );
+ if ( s_pUtlBufferUtilArrayDelim && (i != nCount-1) )
+ {
+ buf.PutString( s_pUtlBufferUtilArrayDelim );
+ }
+ buf.PutChar('\n');
+ }
+ }
+ else
+ {
+ for ( int i = 0; i < nCount; ++i )
+ {
+ ::Serialize( buf, src[i] );
+ if ( s_pUtlBufferUtilArrayDelim && (i != nCount-1) )
+ {
+ buf.PutString( s_pUtlBufferUtilArrayDelim );
+ }
+ buf.PutChar(' ');
+ }
+ }
+
+ return buf.IsValid();
+}
+
+template< class T >
+bool Unserialize( CUtlBuffer &buf, CUtlVector<T> &dest )
+{
+ dest.RemoveAll();
+
+ MEM_ALLOC_CREDIT_FUNCTION();
+
+ if ( !buf.IsText() )
+ {
+ int nCount = buf.GetInt();
+ if ( nCount )
+ {
+ dest.EnsureCapacity( nCount );
+ for ( int i = 0; i < nCount; ++i )
+ {
+ VerifyEquals( dest.AddToTail(), i );
+ if ( !::Unserialize( buf, dest[i] ) )
+ return false;
+ }
+ }
+ return buf.IsValid();
+ }
+
+ while ( true )
+ {
+ buf.EatWhiteSpace();
+ if ( !buf.IsValid() )
+ break;
+
+ int i = dest.AddToTail( );
+ if ( ! ::Unserialize( buf, dest[i] ) )
+ return false;
+ }
+ return true;
+}
+
+
+#endif // UTLBUFFERUTIL_H
+
diff --git a/mp/src/public/tier1/utlcommon.h b/mp/src/public/tier1/utlcommon.h
index 85f91017..d44dc2d5 100644
--- a/mp/src/public/tier1/utlcommon.h
+++ b/mp/src/public/tier1/utlcommon.h
@@ -1,345 +1,345 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: common helpers for reuse among various Utl containers
-//
-// $NoKeywords: $
-//
-//=============================================================================//
-
-#ifndef UTLCOMMON_H
-#define UTLCOMMON_H
-#pragma once
-
-//-----------------------------------------------------------------------------
-// Henry Goffin (henryg) was here. Questions? Bugs? Go slap him around a bit.
-//-----------------------------------------------------------------------------
-
-// empty_t is the canonical "no-value" type which is fully defined but empty.
-struct empty_t {};
-
-// undefined_t is the canonical "undefined" type, used mostly for typedefs;
-// parameters of type undefined_t will not compile, which is actually useful
-// behavior when it comes to template programming. Google "SFINAE" for info.
-struct undefined_t;
-
-// CTypeSelect<sel,A,B>::type is a typedef of A if sel is nonzero, else B
-template <int sel, typename A, typename B>
-struct CTypeSelect { typedef A type; };
-
-template <typename A, typename B>
-struct CTypeSelect<0, A, B> { typedef B type; };
-
-// CTypeEquals<A, B>::value is nonzero if A and B are the same type
-template <typename A, typename B, bool bIgnoreConstVolatile = false, bool bIgnoreReference = false>
-struct CTypeEquals { enum { value = 0 }; };
-
-template <typename Same>
-struct CTypeEquals<Same, Same, false, false> { enum { value = 1 }; };
-
-template <typename A, typename B>
-struct CTypeEquals<A, B, true, true> : CTypeEquals< const volatile A&, const volatile B& > {};
-
-template <typename A, typename B>
-struct CTypeEquals<A, B, true, false> : CTypeEquals< const volatile A, const volatile B > {};
-
-template <typename A, typename B>
-struct CTypeEquals<A, B, false, true> : CTypeEquals< A&, B& > {};
-
-// CUtlKeyValuePair is intended for use with key-lookup containers.
-// Because it is specialized for "empty_t" values, one container can
-// function as either a set of keys OR a key-value dictionary while
-// avoiding storage waste or padding for the empty_t value objects.
-template <typename K, typename V>
-class CUtlKeyValuePair
-{
-public:
- typedef V ValueReturn_t;
- K m_key;
- V m_value;
-
- CUtlKeyValuePair() {}
-
- template < typename KInit >
- explicit CUtlKeyValuePair( const KInit &k ) : m_key( k ) {}
-
- template < typename KInit, typename VInit >
- CUtlKeyValuePair( const KInit &k, const VInit &v ) : m_key( k ), m_value( v ) {}
-
- V &GetValue() { return m_value; }
- const V &GetValue() const { return m_value; }
-};
-
-template <typename K>
-class CUtlKeyValuePair<K, empty_t>
-{
-public:
- typedef const K ValueReturn_t;
- K m_key;
-
- CUtlKeyValuePair() {}
-
- template < typename KInit >
- explicit CUtlKeyValuePair( const KInit &k ) : m_key( k ) {}
-
- template < typename KInit >
- CUtlKeyValuePair( const KInit &k, empty_t ) : m_key( k ) {}
-
- CUtlKeyValuePair( const K &k, const empty_t& ) : m_key( k ) {}
- const K &GetValue() const { return m_key; }
-};
-
-
-// Default functors. You can specialize these if your type does
-// not implement operator== or operator< in an efficient way for
-// some odd reason.
-template <typename T> struct DefaultLessFunctor;
-template <typename T> struct DefaultEqualFunctor;
-
-// Hashing functor used by hash tables. You can either specialize
-// for types which are widely used, or plug a custom functor directly
-// into the hash table. If you do roll your own, please read up on
-// bit-mixing and the avalanche property; be sure that your values
-// are reasonably well-distributed across the entire 32-bit range.
-// http://en.wikipedia.org/wiki/Avalanche_effect
-// http://home.comcast.net/~bretm/hash/5.html
-//
-template <typename T> struct DefaultHashFunctor;
-
-// Argument type information. Struct currently contains one or two typedefs:
-// typename Arg_t = primary argument type. Usually const T&, sometimes T.
-// typename Alt_t = optional alternate type. Usually *undefined*.
-//
-// Any specializations should be implemented via simple inheritance
-// from ArgumentTypeInfoImpl< BestArgType, [optional] AlternateArgType >
-//
-template <typename T> struct ArgumentTypeInfo;
-
-
-// Some fundamental building-block functors...
-struct StringLessFunctor { bool operator()( const char *a, const char *b ) const { return Q_strcmp( a, b ) < 0; } };
-struct StringEqualFunctor { bool operator()( const char *a, const char *b ) const { return Q_strcmp( a, b ) == 0; } };
-struct CaselessStringLessFunctor { bool operator()( const char *a, const char *b ) const { return Q_strcasecmp( a, b ) < 0; } };
-struct CaselessStringEqualFunctor { bool operator()( const char *a, const char *b ) const { return Q_strcasecmp( a, b ) == 0; } };
-
-struct Mix32HashFunctor { unsigned int operator()( uint32 s ) const; };
-struct StringHashFunctor { unsigned int operator()( const char* s ) const; };
-struct CaselessStringHashFunctor { unsigned int operator()( const char* s ) const; };
-
-struct PointerLessFunctor { bool operator()( const void *a, const void *b ) const { return a < b; } };
-struct PointerEqualFunctor { bool operator()( const void *a, const void *b ) const { return a == b; } };
-struct PointerHashFunctor { unsigned int operator()( const void* s ) const { return Mix32HashFunctor()((uint32)POINTER_TO_INT(s)); } };
-
-
-// Generic implementation of Less and Equal functors
-template < typename T >
-struct DefaultLessFunctor
-{
- bool operator()( typename ArgumentTypeInfo< T >::Arg_t a, typename ArgumentTypeInfo< T >::Arg_t b ) const { return a < b; }
- bool operator()( typename ArgumentTypeInfo< T >::Alt_t a, typename ArgumentTypeInfo< T >::Arg_t b ) const { return a < b; }
- bool operator()( typename ArgumentTypeInfo< T >::Arg_t a, typename ArgumentTypeInfo< T >::Alt_t b ) const { return a < b; }
-};
-
-template < typename T >
-struct DefaultEqualFunctor
-{
- bool operator()( typename ArgumentTypeInfo< T >::Arg_t a, typename ArgumentTypeInfo< T >::Arg_t b ) const { return a == b; }
- bool operator()( typename ArgumentTypeInfo< T >::Alt_t a, typename ArgumentTypeInfo< T >::Arg_t b ) const { return a == b; }
- bool operator()( typename ArgumentTypeInfo< T >::Arg_t a, typename ArgumentTypeInfo< T >::Alt_t b ) const { return a == b; }
-};
-
-// Hashes for basic types
-template <> struct DefaultHashFunctor<char> : Mix32HashFunctor { };
-template <> struct DefaultHashFunctor<signed char> : Mix32HashFunctor { };
-template <> struct DefaultHashFunctor<unsigned char> : Mix32HashFunctor { };
-template <> struct DefaultHashFunctor<signed short> : Mix32HashFunctor { };
-template <> struct DefaultHashFunctor<unsigned short> : Mix32HashFunctor { };
-template <> struct DefaultHashFunctor<signed int> : Mix32HashFunctor { };
-template <> struct DefaultHashFunctor<unsigned int> : Mix32HashFunctor { };
-template <> struct DefaultHashFunctor<signed long> : Mix32HashFunctor { };
-template <> struct DefaultHashFunctor<unsigned long> : Mix32HashFunctor { };
-template <> struct DefaultHashFunctor<void*> : PointerHashFunctor { };
-template <> struct DefaultHashFunctor<const void*> : PointerHashFunctor { };
-#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
-template <> struct DefaultHashFunctor<wchar_t> : Mix32HashFunctor { };
-#endif
-
-// String specializations. If you want to operate on raw values, use
-// PointerLessFunctor and friends from the "building-block" section above
-template <> struct DefaultLessFunctor<char*> : StringLessFunctor { };
-template <> struct DefaultLessFunctor<const char*> : StringLessFunctor { };
-template <> struct DefaultEqualFunctor<char*> : StringEqualFunctor { };
-template <> struct DefaultEqualFunctor<const char*> : StringEqualFunctor { };
-template <> struct DefaultHashFunctor<char*> : StringHashFunctor { };
-template <> struct DefaultHashFunctor<const char*> : StringHashFunctor { };
-
-// CUtlString/CUtlConstString are specialized here and not in utlstring.h
-// because I consider string datatypes to be fundamental, and don't feel
-// comfortable making that header file dependent on this one. (henryg)
-class CUtlString;
-template < typename T > class CUtlConstStringBase;
-
-template <> struct DefaultLessFunctor<CUtlString> : StringLessFunctor { };
-template <> struct DefaultHashFunctor<CUtlString> : StringHashFunctor { };
-template < typename T > struct DefaultLessFunctor< CUtlConstStringBase<T> > : StringLessFunctor { };
-template < typename T > struct DefaultHashFunctor< CUtlConstStringBase<T> > : StringHashFunctor { };
-
-
-// Helpers to deduce if a type defines a public AltArgumentType_t typedef:
-template < typename T >
-struct HasClassAltArgumentType
-{
- template < typename X > static long Test( typename X::AltArgumentType_t* );
- template < typename X > static char Test( ... );
- enum { value = ( sizeof( Test< T >( NULL ) ) != sizeof( char ) ) };
-};
-
-template < typename T, bool = HasClassAltArgumentType< T >::value >
-struct GetClassAltArgumentType { typedef typename T::AltArgumentType_t Result_t; };
-
-template < typename T >
-struct GetClassAltArgumentType< T, false > { typedef undefined_t Result_t; };
-
-// Unwrap references; reference types don't have member typedefs.
-template < typename T >
-struct GetClassAltArgumentType< T&, false > : GetClassAltArgumentType< T > { };
-
-// ArgumentTypeInfoImpl is the base for all ArgumentTypeInfo specializations.
-template < typename ArgT, typename AltT = typename GetClassAltArgumentType<ArgT>::Result_t >
-struct ArgumentTypeInfoImpl
-{
- enum { has_alt = 1 };
- typedef ArgT Arg_t;
- typedef AltT Alt_t;
-};
-
-// Handle cases where AltArgumentType_t is typedef'd to undefined_t
-template < typename ArgT >
-struct ArgumentTypeInfoImpl< ArgT, undefined_t >
-{
- enum { has_alt = 0 };
- typedef ArgT Arg_t;
- typedef undefined_t Alt_t;
-};
-
-// Handle cases where AltArgumentType_t is typedef'd to the primary type
-template < typename ArgT >
-struct ArgumentTypeInfoImpl< ArgT, ArgT >
-{
- enum { has_alt = 0 };
- typedef ArgT Arg_t;
- typedef undefined_t Alt_t;
-};
-
-
-// By default, everything is passed via const ref and doesn't define an alternate type.
-template <typename T> struct ArgumentTypeInfo : ArgumentTypeInfoImpl< const T& > { };
-
-// Small native types are most efficiently passed by value.
-template <> struct ArgumentTypeInfo< bool > : ArgumentTypeInfoImpl< bool > { };
-template <> struct ArgumentTypeInfo< char > : ArgumentTypeInfoImpl< char > { };
-template <> struct ArgumentTypeInfo< signed char > : ArgumentTypeInfoImpl< signed char > { };
-template <> struct ArgumentTypeInfo< unsigned char > : ArgumentTypeInfoImpl< unsigned char > { };
-template <> struct ArgumentTypeInfo< signed short > : ArgumentTypeInfoImpl< signed short > { };
-template <> struct ArgumentTypeInfo< unsigned short > : ArgumentTypeInfoImpl< unsigned short > { };
-template <> struct ArgumentTypeInfo< signed int > : ArgumentTypeInfoImpl< signed int > { };
-template <> struct ArgumentTypeInfo< unsigned int > : ArgumentTypeInfoImpl< unsigned int > { };
-template <> struct ArgumentTypeInfo< signed long > : ArgumentTypeInfoImpl< signed long > { };
-template <> struct ArgumentTypeInfo< unsigned long > : ArgumentTypeInfoImpl< unsigned long > { };
-template <> struct ArgumentTypeInfo< signed long long > : ArgumentTypeInfoImpl< signed long long > { };
-template <> struct ArgumentTypeInfo< unsigned long long > : ArgumentTypeInfoImpl< unsigned long long > { };
-template <> struct ArgumentTypeInfo< float > : ArgumentTypeInfoImpl< float > { };
-template <> struct ArgumentTypeInfo< double > : ArgumentTypeInfoImpl< double > { };
-template <> struct ArgumentTypeInfo< long double > : ArgumentTypeInfoImpl< long double > { };
-#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
-template <> struct ArgumentTypeInfo< wchar_t > : ArgumentTypeInfoImpl< wchar_t > { };
-#endif
-
-// Pointers are also most efficiently passed by value.
-template < typename T > struct ArgumentTypeInfo< T* > : ArgumentTypeInfoImpl< T* > { };
-
-
-// Specializations to unwrap const-decorated types and references
-template <typename T> struct ArgumentTypeInfo<const T> : ArgumentTypeInfo<T> { };
-template <typename T> struct ArgumentTypeInfo<volatile T> : ArgumentTypeInfo<T> { };
-template <typename T> struct ArgumentTypeInfo<const volatile T> : ArgumentTypeInfo<T> { };
-template <typename T> struct ArgumentTypeInfo<T&> : ArgumentTypeInfo<T> { };
-
-template <typename T> struct DefaultLessFunctor<const T> : DefaultLessFunctor<T> { };
-template <typename T> struct DefaultLessFunctor<volatile T> : DefaultLessFunctor<T> { };
-template <typename T> struct DefaultLessFunctor<const volatile T> : DefaultLessFunctor<T> { };
-template <typename T> struct DefaultLessFunctor<T&> : DefaultLessFunctor<T> { };
-
-template <typename T> struct DefaultEqualFunctor<const T> : DefaultEqualFunctor<T> { };
-template <typename T> struct DefaultEqualFunctor<volatile T> : DefaultEqualFunctor<T> { };
-template <typename T> struct DefaultEqualFunctor<const volatile T> : DefaultEqualFunctor<T> { };
-template <typename T> struct DefaultEqualFunctor<T&> : DefaultEqualFunctor<T> { };
-
-template <typename T> struct DefaultHashFunctor<const T> : DefaultHashFunctor<T> { };
-template <typename T> struct DefaultHashFunctor<volatile T> : DefaultHashFunctor<T> { };
-template <typename T> struct DefaultHashFunctor<const volatile T> : DefaultHashFunctor<T> { };
-template <typename T> struct DefaultHashFunctor<T&> : DefaultHashFunctor<T> { };
-
-
-// Hash all pointer types as raw pointers by default
-template <typename T> struct DefaultHashFunctor< T * > : PointerHashFunctor { };
-
-
-// Here follow the useful implementations.
-
-// Bob Jenkins's 32-bit mix function.
-inline unsigned int Mix32HashFunctor::operator()( uint32 n ) const
-{
- // Perform a mixture of the bits in n, where each bit
- // of the input value has an equal chance to affect each
- // bit of the output. This turns tightly clustered input
- // values into a smooth distribution.
- //
- // This takes 16-20 cycles on modern x86 architectures;
- // that's roughly the same cost as a mispredicted branch.
- // It's also reasonably efficient on PPC-based consoles.
- //
- // If you're still thinking, "too many instructions!",
- // do keep in mind that reading one byte of uncached RAM
- // is about 30x slower than executing this code. It pays
- // to have a good hash function which minimizes collisions
- // (and therefore long lookup chains).
- 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;
-}
-
-// Based on the widely-used FNV-1A string hash with a final
-// mixing step to improve dispersion for very small and very
-// large hash table sizes.
-inline unsigned int StringHashFunctor::operator()( const char* s ) const
-{
- uint32 h = 2166136261u;
- for ( ; *s; ++s )
- {
- uint32 c = (unsigned char) *s;
- h = (h ^ c) * 16777619;
- }
- return (h ^ (h << 17)) + (h >> 21);
-}
-
-// Equivalent to StringHashFunctor on lower-case strings.
-inline unsigned int CaselessStringHashFunctor::operator()( const char* s ) const
-{
- uint32 h = 2166136261u;
- for ( ; *s; ++s )
- {
- uint32 c = (unsigned char) *s;
- // Brutally fast branchless ASCII tolower():
- // if ((c >= 'A') && (c <= 'Z')) c += ('a' - 'A');
- c += (((('A'-1) - c) & (c - ('Z'+1))) >> 26) & 32;
- h = (h ^ c) * 16777619;
- }
- return (h ^ (h << 17)) + (h >> 21);
-}
-
-
-#endif // UTLCOMMON_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: common helpers for reuse among various Utl containers
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+
+#ifndef UTLCOMMON_H
+#define UTLCOMMON_H
+#pragma once
+
+//-----------------------------------------------------------------------------
+// Henry Goffin (henryg) was here. Questions? Bugs? Go slap him around a bit.
+//-----------------------------------------------------------------------------
+
+// empty_t is the canonical "no-value" type which is fully defined but empty.
+struct empty_t {};
+
+// undefined_t is the canonical "undefined" type, used mostly for typedefs;
+// parameters of type undefined_t will not compile, which is actually useful
+// behavior when it comes to template programming. Google "SFINAE" for info.
+struct undefined_t;
+
+// CTypeSelect<sel,A,B>::type is a typedef of A if sel is nonzero, else B
+template <int sel, typename A, typename B>
+struct CTypeSelect { typedef A type; };
+
+template <typename A, typename B>
+struct CTypeSelect<0, A, B> { typedef B type; };
+
+// CTypeEquals<A, B>::value is nonzero if A and B are the same type
+template <typename A, typename B, bool bIgnoreConstVolatile = false, bool bIgnoreReference = false>
+struct CTypeEquals { enum { value = 0 }; };
+
+template <typename Same>
+struct CTypeEquals<Same, Same, false, false> { enum { value = 1 }; };
+
+template <typename A, typename B>
+struct CTypeEquals<A, B, true, true> : CTypeEquals< const volatile A&, const volatile B& > {};
+
+template <typename A, typename B>
+struct CTypeEquals<A, B, true, false> : CTypeEquals< const volatile A, const volatile B > {};
+
+template <typename A, typename B>
+struct CTypeEquals<A, B, false, true> : CTypeEquals< A&, B& > {};
+
+// CUtlKeyValuePair is intended for use with key-lookup containers.
+// Because it is specialized for "empty_t" values, one container can
+// function as either a set of keys OR a key-value dictionary while
+// avoiding storage waste or padding for the empty_t value objects.
+template <typename K, typename V>
+class CUtlKeyValuePair
+{
+public:
+ typedef V ValueReturn_t;
+ K m_key;
+ V m_value;
+
+ CUtlKeyValuePair() {}
+
+ template < typename KInit >
+ explicit CUtlKeyValuePair( const KInit &k ) : m_key( k ) {}
+
+ template < typename KInit, typename VInit >
+ CUtlKeyValuePair( const KInit &k, const VInit &v ) : m_key( k ), m_value( v ) {}
+
+ V &GetValue() { return m_value; }
+ const V &GetValue() const { return m_value; }
+};
+
+template <typename K>
+class CUtlKeyValuePair<K, empty_t>
+{
+public:
+ typedef const K ValueReturn_t;
+ K m_key;
+
+ CUtlKeyValuePair() {}
+
+ template < typename KInit >
+ explicit CUtlKeyValuePair( const KInit &k ) : m_key( k ) {}
+
+ template < typename KInit >
+ CUtlKeyValuePair( const KInit &k, empty_t ) : m_key( k ) {}
+
+ CUtlKeyValuePair( const K &k, const empty_t& ) : m_key( k ) {}
+ const K &GetValue() const { return m_key; }
+};
+
+
+// Default functors. You can specialize these if your type does
+// not implement operator== or operator< in an efficient way for
+// some odd reason.
+template <typename T> struct DefaultLessFunctor;
+template <typename T> struct DefaultEqualFunctor;
+
+// Hashing functor used by hash tables. You can either specialize
+// for types which are widely used, or plug a custom functor directly
+// into the hash table. If you do roll your own, please read up on
+// bit-mixing and the avalanche property; be sure that your values
+// are reasonably well-distributed across the entire 32-bit range.
+// http://en.wikipedia.org/wiki/Avalanche_effect
+// http://home.comcast.net/~bretm/hash/5.html
+//
+template <typename T> struct DefaultHashFunctor;
+
+// Argument type information. Struct currently contains one or two typedefs:
+// typename Arg_t = primary argument type. Usually const T&, sometimes T.
+// typename Alt_t = optional alternate type. Usually *undefined*.
+//
+// Any specializations should be implemented via simple inheritance
+// from ArgumentTypeInfoImpl< BestArgType, [optional] AlternateArgType >
+//
+template <typename T> struct ArgumentTypeInfo;
+
+
+// Some fundamental building-block functors...
+struct StringLessFunctor { bool operator()( const char *a, const char *b ) const { return Q_strcmp( a, b ) < 0; } };
+struct StringEqualFunctor { bool operator()( const char *a, const char *b ) const { return Q_strcmp( a, b ) == 0; } };
+struct CaselessStringLessFunctor { bool operator()( const char *a, const char *b ) const { return Q_strcasecmp( a, b ) < 0; } };
+struct CaselessStringEqualFunctor { bool operator()( const char *a, const char *b ) const { return Q_strcasecmp( a, b ) == 0; } };
+
+struct Mix32HashFunctor { unsigned int operator()( uint32 s ) const; };
+struct StringHashFunctor { unsigned int operator()( const char* s ) const; };
+struct CaselessStringHashFunctor { unsigned int operator()( const char* s ) const; };
+
+struct PointerLessFunctor { bool operator()( const void *a, const void *b ) const { return a < b; } };
+struct PointerEqualFunctor { bool operator()( const void *a, const void *b ) const { return a == b; } };
+struct PointerHashFunctor { unsigned int operator()( const void* s ) const { return Mix32HashFunctor()((uint32)POINTER_TO_INT(s)); } };
+
+
+// Generic implementation of Less and Equal functors
+template < typename T >
+struct DefaultLessFunctor
+{
+ bool operator()( typename ArgumentTypeInfo< T >::Arg_t a, typename ArgumentTypeInfo< T >::Arg_t b ) const { return a < b; }
+ bool operator()( typename ArgumentTypeInfo< T >::Alt_t a, typename ArgumentTypeInfo< T >::Arg_t b ) const { return a < b; }
+ bool operator()( typename ArgumentTypeInfo< T >::Arg_t a, typename ArgumentTypeInfo< T >::Alt_t b ) const { return a < b; }
+};
+
+template < typename T >
+struct DefaultEqualFunctor
+{
+ bool operator()( typename ArgumentTypeInfo< T >::Arg_t a, typename ArgumentTypeInfo< T >::Arg_t b ) const { return a == b; }
+ bool operator()( typename ArgumentTypeInfo< T >::Alt_t a, typename ArgumentTypeInfo< T >::Arg_t b ) const { return a == b; }
+ bool operator()( typename ArgumentTypeInfo< T >::Arg_t a, typename ArgumentTypeInfo< T >::Alt_t b ) const { return a == b; }
+};
+
+// Hashes for basic types
+template <> struct DefaultHashFunctor<char> : Mix32HashFunctor { };
+template <> struct DefaultHashFunctor<signed char> : Mix32HashFunctor { };
+template <> struct DefaultHashFunctor<unsigned char> : Mix32HashFunctor { };
+template <> struct DefaultHashFunctor<signed short> : Mix32HashFunctor { };
+template <> struct DefaultHashFunctor<unsigned short> : Mix32HashFunctor { };
+template <> struct DefaultHashFunctor<signed int> : Mix32HashFunctor { };
+template <> struct DefaultHashFunctor<unsigned int> : Mix32HashFunctor { };
+template <> struct DefaultHashFunctor<signed long> : Mix32HashFunctor { };
+template <> struct DefaultHashFunctor<unsigned long> : Mix32HashFunctor { };
+template <> struct DefaultHashFunctor<void*> : PointerHashFunctor { };
+template <> struct DefaultHashFunctor<const void*> : PointerHashFunctor { };
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+template <> struct DefaultHashFunctor<wchar_t> : Mix32HashFunctor { };
+#endif
+
+// String specializations. If you want to operate on raw values, use
+// PointerLessFunctor and friends from the "building-block" section above
+template <> struct DefaultLessFunctor<char*> : StringLessFunctor { };
+template <> struct DefaultLessFunctor<const char*> : StringLessFunctor { };
+template <> struct DefaultEqualFunctor<char*> : StringEqualFunctor { };
+template <> struct DefaultEqualFunctor<const char*> : StringEqualFunctor { };
+template <> struct DefaultHashFunctor<char*> : StringHashFunctor { };
+template <> struct DefaultHashFunctor<const char*> : StringHashFunctor { };
+
+// CUtlString/CUtlConstString are specialized here and not in utlstring.h
+// because I consider string datatypes to be fundamental, and don't feel
+// comfortable making that header file dependent on this one. (henryg)
+class CUtlString;
+template < typename T > class CUtlConstStringBase;
+
+template <> struct DefaultLessFunctor<CUtlString> : StringLessFunctor { };
+template <> struct DefaultHashFunctor<CUtlString> : StringHashFunctor { };
+template < typename T > struct DefaultLessFunctor< CUtlConstStringBase<T> > : StringLessFunctor { };
+template < typename T > struct DefaultHashFunctor< CUtlConstStringBase<T> > : StringHashFunctor { };
+
+
+// Helpers to deduce if a type defines a public AltArgumentType_t typedef:
+template < typename T >
+struct HasClassAltArgumentType
+{
+ template < typename X > static long Test( typename X::AltArgumentType_t* );
+ template < typename X > static char Test( ... );
+ enum { value = ( sizeof( Test< T >( NULL ) ) != sizeof( char ) ) };
+};
+
+template < typename T, bool = HasClassAltArgumentType< T >::value >
+struct GetClassAltArgumentType { typedef typename T::AltArgumentType_t Result_t; };
+
+template < typename T >
+struct GetClassAltArgumentType< T, false > { typedef undefined_t Result_t; };
+
+// Unwrap references; reference types don't have member typedefs.
+template < typename T >
+struct GetClassAltArgumentType< T&, false > : GetClassAltArgumentType< T > { };
+
+// ArgumentTypeInfoImpl is the base for all ArgumentTypeInfo specializations.
+template < typename ArgT, typename AltT = typename GetClassAltArgumentType<ArgT>::Result_t >
+struct ArgumentTypeInfoImpl
+{
+ enum { has_alt = 1 };
+ typedef ArgT Arg_t;
+ typedef AltT Alt_t;
+};
+
+// Handle cases where AltArgumentType_t is typedef'd to undefined_t
+template < typename ArgT >
+struct ArgumentTypeInfoImpl< ArgT, undefined_t >
+{
+ enum { has_alt = 0 };
+ typedef ArgT Arg_t;
+ typedef undefined_t Alt_t;
+};
+
+// Handle cases where AltArgumentType_t is typedef'd to the primary type
+template < typename ArgT >
+struct ArgumentTypeInfoImpl< ArgT, ArgT >
+{
+ enum { has_alt = 0 };
+ typedef ArgT Arg_t;
+ typedef undefined_t Alt_t;
+};
+
+
+// By default, everything is passed via const ref and doesn't define an alternate type.
+template <typename T> struct ArgumentTypeInfo : ArgumentTypeInfoImpl< const T& > { };
+
+// Small native types are most efficiently passed by value.
+template <> struct ArgumentTypeInfo< bool > : ArgumentTypeInfoImpl< bool > { };
+template <> struct ArgumentTypeInfo< char > : ArgumentTypeInfoImpl< char > { };
+template <> struct ArgumentTypeInfo< signed char > : ArgumentTypeInfoImpl< signed char > { };
+template <> struct ArgumentTypeInfo< unsigned char > : ArgumentTypeInfoImpl< unsigned char > { };
+template <> struct ArgumentTypeInfo< signed short > : ArgumentTypeInfoImpl< signed short > { };
+template <> struct ArgumentTypeInfo< unsigned short > : ArgumentTypeInfoImpl< unsigned short > { };
+template <> struct ArgumentTypeInfo< signed int > : ArgumentTypeInfoImpl< signed int > { };
+template <> struct ArgumentTypeInfo< unsigned int > : ArgumentTypeInfoImpl< unsigned int > { };
+template <> struct ArgumentTypeInfo< signed long > : ArgumentTypeInfoImpl< signed long > { };
+template <> struct ArgumentTypeInfo< unsigned long > : ArgumentTypeInfoImpl< unsigned long > { };
+template <> struct ArgumentTypeInfo< signed long long > : ArgumentTypeInfoImpl< signed long long > { };
+template <> struct ArgumentTypeInfo< unsigned long long > : ArgumentTypeInfoImpl< unsigned long long > { };
+template <> struct ArgumentTypeInfo< float > : ArgumentTypeInfoImpl< float > { };
+template <> struct ArgumentTypeInfo< double > : ArgumentTypeInfoImpl< double > { };
+template <> struct ArgumentTypeInfo< long double > : ArgumentTypeInfoImpl< long double > { };
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+template <> struct ArgumentTypeInfo< wchar_t > : ArgumentTypeInfoImpl< wchar_t > { };
+#endif
+
+// Pointers are also most efficiently passed by value.
+template < typename T > struct ArgumentTypeInfo< T* > : ArgumentTypeInfoImpl< T* > { };
+
+
+// Specializations to unwrap const-decorated types and references
+template <typename T> struct ArgumentTypeInfo<const T> : ArgumentTypeInfo<T> { };
+template <typename T> struct ArgumentTypeInfo<volatile T> : ArgumentTypeInfo<T> { };
+template <typename T> struct ArgumentTypeInfo<const volatile T> : ArgumentTypeInfo<T> { };
+template <typename T> struct ArgumentTypeInfo<T&> : ArgumentTypeInfo<T> { };
+
+template <typename T> struct DefaultLessFunctor<const T> : DefaultLessFunctor<T> { };
+template <typename T> struct DefaultLessFunctor<volatile T> : DefaultLessFunctor<T> { };
+template <typename T> struct DefaultLessFunctor<const volatile T> : DefaultLessFunctor<T> { };
+template <typename T> struct DefaultLessFunctor<T&> : DefaultLessFunctor<T> { };
+
+template <typename T> struct DefaultEqualFunctor<const T> : DefaultEqualFunctor<T> { };
+template <typename T> struct DefaultEqualFunctor<volatile T> : DefaultEqualFunctor<T> { };
+template <typename T> struct DefaultEqualFunctor<const volatile T> : DefaultEqualFunctor<T> { };
+template <typename T> struct DefaultEqualFunctor<T&> : DefaultEqualFunctor<T> { };
+
+template <typename T> struct DefaultHashFunctor<const T> : DefaultHashFunctor<T> { };
+template <typename T> struct DefaultHashFunctor<volatile T> : DefaultHashFunctor<T> { };
+template <typename T> struct DefaultHashFunctor<const volatile T> : DefaultHashFunctor<T> { };
+template <typename T> struct DefaultHashFunctor<T&> : DefaultHashFunctor<T> { };
+
+
+// Hash all pointer types as raw pointers by default
+template <typename T> struct DefaultHashFunctor< T * > : PointerHashFunctor { };
+
+
+// Here follow the useful implementations.
+
+// Bob Jenkins's 32-bit mix function.
+inline unsigned int Mix32HashFunctor::operator()( uint32 n ) const
+{
+ // Perform a mixture of the bits in n, where each bit
+ // of the input value has an equal chance to affect each
+ // bit of the output. This turns tightly clustered input
+ // values into a smooth distribution.
+ //
+ // This takes 16-20 cycles on modern x86 architectures;
+ // that's roughly the same cost as a mispredicted branch.
+ // It's also reasonably efficient on PPC-based consoles.
+ //
+ // If you're still thinking, "too many instructions!",
+ // do keep in mind that reading one byte of uncached RAM
+ // is about 30x slower than executing this code. It pays
+ // to have a good hash function which minimizes collisions
+ // (and therefore long lookup chains).
+ 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;
+}
+
+// Based on the widely-used FNV-1A string hash with a final
+// mixing step to improve dispersion for very small and very
+// large hash table sizes.
+inline unsigned int StringHashFunctor::operator()( const char* s ) const
+{
+ uint32 h = 2166136261u;
+ for ( ; *s; ++s )
+ {
+ uint32 c = (unsigned char) *s;
+ h = (h ^ c) * 16777619;
+ }
+ return (h ^ (h << 17)) + (h >> 21);
+}
+
+// Equivalent to StringHashFunctor on lower-case strings.
+inline unsigned int CaselessStringHashFunctor::operator()( const char* s ) const
+{
+ uint32 h = 2166136261u;
+ for ( ; *s; ++s )
+ {
+ uint32 c = (unsigned char) *s;
+ // Brutally fast branchless ASCII tolower():
+ // if ((c >= 'A') && (c <= 'Z')) c += ('a' - 'A');
+ c += (((('A'-1) - c) & (c - ('Z'+1))) >> 26) & 32;
+ h = (h ^ c) * 16777619;
+ }
+ return (h ^ (h << 17)) + (h >> 21);
+}
+
+
+#endif // UTLCOMMON_H
diff --git a/mp/src/public/tier1/utldelegate.h b/mp/src/public/tier1/utldelegate.h
index f1d58ff0..04c5dad2 100644
--- a/mp/src/public/tier1/utldelegate.h
+++ b/mp/src/public/tier1/utldelegate.h
@@ -1,97 +1,97 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: A header describing use of the delegate system. It's hiding
-// the highly complex implementation details of the delegate system
-//
-// $NoKeywords: $
-//
-//===========================================================================//
-
-#ifndef UTLDELEGATE_H
-#define UTLDELEGATE_H
-
-#ifdef _WIN32
-#pragma once
-#endif
-
-
-//-----------------------------------------------------------------------------
-// The delegate system: A method of invoking methods, whether they are
-// member methods of classes, static methods of classes, or free functions,
-// dealing with all the nastiness in differences between how the calls have
-// to happen yet works in a highly optimal fashion. For details, see
-//
-// http://www.codeproject.com/cpp/FastDelegate.asp
-//
-// The delegate design pattern is described here
-//
-// http://en.wikipedia.org/wiki/Delegation_(programming)
-//-----------------------------------------------------------------------------
-
-#ifdef UTLDELEGATE_USAGE_DEMONSTRATION
-
-//-----------------------------------------------------------------------------
-// Here, we show how to use this system (the ifdef UTLDELEGATE_USAGE_DEMONSTRATION is used to get syntax coloring).
-//-----------------------------------------------------------------------------
-
-// First, define the functions you wish to call.
-int Test1( char *pString, float x );
-class CTestClass
-{
-public:
- void Test2();
- static float Test3( int x );
-};
-
-void Test()
-{
- CTestClass testClass;
-
- // CUtlDelegate is a class that can be used to invoke methods of classes
- // or static functions in a highly efficient manner.
-
- // There are a couple ways to hook up a delegate. One is in a constructor
- // Note that the template parameter of CUtlFastDelegate looks like the
- // function type: first, you have the return type, then ( parameter list )
- CUtlDelegate< int ( char *, float ) > delegate1( &Test1 );
-
- // Another way is to use the UtlMakeDelegate method, allowing you to
- // define the delegate later. Note that UtlMakeDelegate does *not* do a heap allocation
- CUtlDelegate< void () > delegate2;
- delegate2 = UtlMakeDelegate( &testClass, &CTestClass::Test2 );
-
- // A third method is to use the Bind() method of CUtlFastDelegate
- // Note that you do not pass in the class pointer for static functions
- CUtlDelegate< float ( int ) > delegate3;
- delegate3.Bind( &CTestClass::Test3 );
-
- // Use the () operator to invoke the function calls.
- int x = delegate1( "hello", 1.0f );
- delegate2();
- float y = delegate3( 5 );
-
- // Use the Clear() method to unbind a delegate.
- delegate1.Clear();
-
- // You can use operator! or IsEmpty() to see if a delegate is bound
- if ( !delegate1.IsEmpty() )
- {
- delegate1( "hello2" );
- }
-
- // Delegates maintain an internal non-templatized representation of the
- // functions they are bound to called CUtlAbstractDelegate. These are
- // useful when keeping a list of untyped delegates or when passing
- // delegates across interface boundaries.
- const CUtlAbstractDelegate &abstractDelegate3 = delegate3.GetAbstractDelegate();
- CUtlDelegate< float ( int ) > delegate4;
- delegate4.SetAbstractDelegate( abstractDelegate3 );
- delegate4( 10 );
-}
-
-#endif // UTLDELEGATE_USAGE_DEMONSTRATION
-
-// Looking in this file may cause blindness.
-#include "tier1/utldelegateimpl.h"
-
-#endif // UTLDELEGATE_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: A header describing use of the delegate system. It's hiding
+// the highly complex implementation details of the delegate system
+//
+// $NoKeywords: $
+//
+//===========================================================================//
+
+#ifndef UTLDELEGATE_H
+#define UTLDELEGATE_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+//-----------------------------------------------------------------------------
+// The delegate system: A method of invoking methods, whether they are
+// member methods of classes, static methods of classes, or free functions,
+// dealing with all the nastiness in differences between how the calls have
+// to happen yet works in a highly optimal fashion. For details, see
+//
+// http://www.codeproject.com/cpp/FastDelegate.asp
+//
+// The delegate design pattern is described here
+//
+// http://en.wikipedia.org/wiki/Delegation_(programming)
+//-----------------------------------------------------------------------------
+
+#ifdef UTLDELEGATE_USAGE_DEMONSTRATION
+
+//-----------------------------------------------------------------------------
+// Here, we show how to use this system (the ifdef UTLDELEGATE_USAGE_DEMONSTRATION is used to get syntax coloring).
+//-----------------------------------------------------------------------------
+
+// First, define the functions you wish to call.
+int Test1( char *pString, float x );
+class CTestClass
+{
+public:
+ void Test2();
+ static float Test3( int x );
+};
+
+void Test()
+{
+ CTestClass testClass;
+
+ // CUtlDelegate is a class that can be used to invoke methods of classes
+ // or static functions in a highly efficient manner.
+
+ // There are a couple ways to hook up a delegate. One is in a constructor
+ // Note that the template parameter of CUtlFastDelegate looks like the
+ // function type: first, you have the return type, then ( parameter list )
+ CUtlDelegate< int ( char *, float ) > delegate1( &Test1 );
+
+ // Another way is to use the UtlMakeDelegate method, allowing you to
+ // define the delegate later. Note that UtlMakeDelegate does *not* do a heap allocation
+ CUtlDelegate< void () > delegate2;
+ delegate2 = UtlMakeDelegate( &testClass, &CTestClass::Test2 );
+
+ // A third method is to use the Bind() method of CUtlFastDelegate
+ // Note that you do not pass in the class pointer for static functions
+ CUtlDelegate< float ( int ) > delegate3;
+ delegate3.Bind( &CTestClass::Test3 );
+
+ // Use the () operator to invoke the function calls.
+ int x = delegate1( "hello", 1.0f );
+ delegate2();
+ float y = delegate3( 5 );
+
+ // Use the Clear() method to unbind a delegate.
+ delegate1.Clear();
+
+ // You can use operator! or IsEmpty() to see if a delegate is bound
+ if ( !delegate1.IsEmpty() )
+ {
+ delegate1( "hello2" );
+ }
+
+ // Delegates maintain an internal non-templatized representation of the
+ // functions they are bound to called CUtlAbstractDelegate. These are
+ // useful when keeping a list of untyped delegates or when passing
+ // delegates across interface boundaries.
+ const CUtlAbstractDelegate &abstractDelegate3 = delegate3.GetAbstractDelegate();
+ CUtlDelegate< float ( int ) > delegate4;
+ delegate4.SetAbstractDelegate( abstractDelegate3 );
+ delegate4( 10 );
+}
+
+#endif // UTLDELEGATE_USAGE_DEMONSTRATION
+
+// Looking in this file may cause blindness.
+#include "tier1/utldelegateimpl.h"
+
+#endif // UTLDELEGATE_H
diff --git a/mp/src/public/tier1/utldelegateimpl.h b/mp/src/public/tier1/utldelegateimpl.h
index 12f8a3c2..cf9809d8 100644
--- a/mp/src/public/tier1/utldelegateimpl.h
+++ b/mp/src/public/tier1/utldelegateimpl.h
@@ -1,2656 +1,2656 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-// FastDelegate.h
-// Efficient delegates in C++ that generate only two lines of asm code!
-// Documentation is found at http://www.codeproject.com/cpp/FastDelegate.asp
-//
-// - Don Clugston, Mar 2004.
-// Major contributions were made by Jody Hagins.
-// History:
-// 24-Apr-04 1.0 * Submitted to CodeProject.
-// 28-Apr-04 1.1 * Prevent most unsafe uses of evil static function hack.
-// * Improved syntax for horrible_cast (thanks Paul Bludov).
-// * Tested on Metrowerks MWCC and Intel ICL (IA32)
-// * Compiled, but not run, on Comeau C++ and Intel Itanium ICL.
-// 27-Jun-04 1.2 * Now works on Borland C++ Builder 5.5
-// * Now works on /clr "managed C++" code on VC7, VC7.1
-// * Comeau C++ now compiles without warnings.
-// * Prevent the virtual inheritance case from being used on
-// VC6 and earlier, which generate incorrect code.
-// * Improved warning and error messages. Non-standard hacks
-// now have compile-time checks to make them safer.
-// * implicit_cast used instead of static_cast in many cases.
-// * If calling a const member function, a const class pointer can be used.
-// * UtlMakeDelegate() global helper function added to simplify pass-by-value.
-// * Added fastdelegate.Clear()
-// 16-Jul-04 1.2.1* Workaround for gcc bug (const member function pointers in templates)
-// 30-Oct-04 1.3 * Support for (non-void) return values.
-// * No more workarounds in client code!
-// MSVC and Intel now use a clever hack invented by John Dlugosz:
-// - The FASTDELEGATEDECLARE workaround is no longer necessary.
-// - No more warning messages for VC6
-// * Less use of macros. Error messages should be more comprehensible.
-// * Added include guards
-// * Added FastDelegate::IsEmpty() to test if invocation is safe (Thanks Neville Franks).
-// * Now tested on VS 2005 Express Beta, PGI C++
-// 24-Dec-04 1.4 * Added CUtlAbstractDelegate, to allow collections of disparate delegates.
-// * <,>,<=,>= comparison operators to allow storage in ordered containers.
-// * Substantial reduction of code size, especially the 'Closure' class.
-// * Standardised all the compiler-specific workarounds.
-// * MFP conversion now works for CodePlay (but not yet supported in the full code).
-// * Now compiles without warnings on _any_ supported compiler, including BCC 5.5.1
-// * New syntax: FastDelegate< int (char *, double) >.
-// 14-Feb-05 1.4.1* Now treats =0 as equivalent to .Clear(), ==0 as equivalent to .IsEmpty(). (Thanks elfric).
-// * Now tested on Intel ICL for AMD64, VS2005 Beta for AMD64 and Itanium.
-// 30-Mar-05 1.5 * Safebool idiom: "if (dg)" is now equivalent to "if (!dg.IsEmpty())"
-// * Fully supported by CodePlay VectorC
-// * Bugfix for Metrowerks: IsEmpty() was buggy because a valid MFP can be 0 on MWCC!
-// * More optimal assignment,== and != operators for static function pointers.
-// 22-Jul-10 xxx * Reformatted + renamed to match valve coding standards
-// * Added UtlMakeDelegate for static functions
-
-#ifndef UTLDELEGATEIMPL_H
-#define UTLDELEGATEIMPL_H
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-#include <memory.h> // to allow <,> comparisons
-
-////////////////////////////////////////////////////////////////////////////////
-// Configuration options
-//
-////////////////////////////////////////////////////////////////////////////////
-
-// Uncomment the following #define for optimally-sized delegates.
-// In this case, the generated asm code is almost identical to the code you'd get
-// if the compiler had native support for delegates.
-// It will not work on systems where sizeof(dataptr) < sizeof(codeptr).
-// Thus, it will not work for DOS compilers using the medium model.
-// It will also probably fail on some DSP systems.
-#define FASTDELEGATE_USESTATICFUNCTIONHACK
-
-// Uncomment the next line to allow function declarator syntax.
-// It is automatically enabled for those compilers where it is known to work.
-//#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
-
-////////////////////////////////////////////////////////////////////////////////
-// Compiler identification for workarounds
-//
-////////////////////////////////////////////////////////////////////////////////
-
-// Compiler identification. It's not easy to identify Visual C++ because
-// many vendors fraudulently define Microsoft's identifiers.
-#if defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__VECTOR_C) && !defined(__ICL) && !defined(__BORLANDC__)
-#define FASTDLGT_ISMSVC
-
-#if (_MSC_VER <1300) // Many workarounds are required for VC6.
-#define FASTDLGT_VC6
-#pragma warning(disable:4786) // disable this ridiculous warning
-#endif
-
-#endif
-
-// Does the compiler uses Microsoft's member function pointer structure?
-// If so, it needs special treatment.
-// Metrowerks CodeWarrior, Intel, and CodePlay fraudulently define Microsoft's
-// identifier, _MSC_VER. We need to filter Metrowerks out.
-#if defined(_MSC_VER) && !defined(__MWERKS__)
-#define FASTDLGT_MICROSOFT_MFP
-
-#if !defined(__VECTOR_C)
-// CodePlay doesn't have the __single/multi/virtual_inheritance keywords
-#define FASTDLGT_HASINHERITANCE_KEYWORDS
-#endif
-#endif
-
-// Does it allow function declarator syntax? The following compilers are known to work:
-#if defined(FASTDLGT_ISMSVC) && (_MSC_VER >=1310) // VC 7.1
-#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
-#endif
-
-// Gcc(2.95+), and versions of Digital Mars, Intel and Comeau in common use.
-#if defined (__DMC__) || defined(__GNUC__) || defined(__ICL) || defined(__COMO__)
-#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
-#endif
-
-// It works on Metrowerks MWCC 3.2.2. From boost.Config it should work on earlier ones too.
-#if defined (__MWERKS__)
-#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
-#endif
-
-#ifdef __GNUC__ // Workaround GCC bug #8271
- // At present, GCC doesn't recognize constness of MFPs in templates
-#define FASTDELEGATE_GCC_BUG_8271
-#endif
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-// General tricks used in this code
-//
-// (a) Error messages are generated by typdefing an array of negative size to
-// generate compile-time errors.
-// (b) Warning messages on MSVC are generated by declaring unused variables, and
-// enabling the "variable XXX is never used" warning.
-// (c) Unions are used in a few compiler-specific cases to perform illegal casts.
-// (d) For Microsoft and Intel, when adjusting the 'this' pointer, it's cast to
-// (char *) first to ensure that the correct number of *bytes* are added.
-//
-////////////////////////////////////////////////////////////////////////////////
-// Helper templates
-//
-////////////////////////////////////////////////////////////////////////////////
-
-
-namespace detail // we'll hide the implementation details in a nested namespace.
-{
-
-// implicit_cast< >
-// I believe this was originally going to be in the C++ standard but
-// was left out by accident. It's even milder than static_cast.
-// I use it instead of static_cast<> to emphasize that I'm not doing
-// anything nasty.
-// Usage is identical to static_cast<>
-template <class OutputClass, class InputClass>
-inline OutputClass implicit_cast(InputClass input)
-{
- return input;
-}
-
-// horrible_cast< >
-// This is truly evil. It completely subverts C++'s type system, allowing you
-// to cast from any class to any other class. Technically, using a union
-// to perform the cast is undefined behaviour (even in C). But we can see if
-// it is OK by checking that the union is the same size as each of its members.
-// horrible_cast<> should only be used for compiler-specific workarounds.
-// Usage is identical to reinterpret_cast<>.
-
-// This union is declared outside the horrible_cast because BCC 5.5.1
-// can't inline a function with a nested class, and gives a warning.
-template <class OutputClass, class InputClass>
-union horrible_union
-{
- OutputClass out;
- InputClass in;
-};
-
-template <class OutputClass, class InputClass>
-inline OutputClass horrible_cast(const InputClass input)
-{
- horrible_union<OutputClass, InputClass> u;
- // Cause a compile-time error if in, out and u are not the same size.
- // If the compile fails here, it means the compiler has peculiar
- // unions which would prevent the cast from working.
- typedef int ERROR_CantUseHorrible_cast[sizeof(InputClass)==sizeof(u)
- && sizeof(InputClass)==sizeof(OutputClass) ? 1 : -1];
- u.in = input;
- return u.out;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Workarounds
-//
-////////////////////////////////////////////////////////////////////////////////
-
-// Backwards compatibility: This macro used to be necessary in the virtual inheritance
-// case for Intel and Microsoft. Now it just forward-declares the class.
-#define FASTDELEGATEDECLARE(CLASSNAME) class CLASSNAME;
-
-// Prevent use of the static function hack with the DOS medium model.
-#ifdef __MEDIUM__
-#undef FASTDELEGATE_USESTATICFUNCTIONHACK
-#endif
-
-// DefaultVoid - a workaround for 'void' templates in VC6.
-//
-// (1) VC6 and earlier do not allow 'void' as a default template argument.
-// (2) They also doesn't allow you to return 'void' from a function.
-//
-// Workaround for (1): Declare a dummy type 'DefaultVoid' which we use
-// when we'd like to use 'void'. We convert it into 'void' and back
-// using the templates DefaultVoidToVoid<> and VoidToDefaultVoid<>.
-// Workaround for (2): On VC6, the code for calling a void function is
-// identical to the code for calling a non-void function in which the
-// return value is never used, provided the return value is returned
-// in the EAX register, rather than on the stack.
-// This is true for most fundamental types such as int, enum, void *.
-// Const void * is the safest option since it doesn't participate
-// in any automatic conversions. But on a 16-bit compiler it might
-// cause extra code to be generated, so we disable it for all compilers
-// except for VC6 (and VC5).
-#ifdef FASTDLGT_VC6
-// VC6 workaround
-typedef const void * DefaultVoid;
-#else
-// On any other compiler, just use a normal void.
-typedef void DefaultVoid;
-#endif
-
-// Translate from 'DefaultVoid' to 'void'.
-// Everything else is unchanged
-template <class T>
-struct DefaultVoidToVoid { typedef T type; };
-
-template <>
-struct DefaultVoidToVoid<DefaultVoid> { typedef void type; };
-
-// Translate from 'void' into 'DefaultVoid'
-// Everything else is unchanged
-template <class T>
-struct VoidToDefaultVoid { typedef T type; };
-
-template <>
-struct VoidToDefaultVoid<void> { typedef DefaultVoid type; };
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-// Fast Delegates, part 1:
-//
-// Conversion of member function pointer to a standard form
-//
-////////////////////////////////////////////////////////////////////////////////
-
-// GenericClass is a fake class, ONLY used to provide a type.
-// It is vitally important that it is never defined, so that the compiler doesn't
-// think it can optimize the invocation. For example, Borland generates simpler
-// code if it knows the class only uses single inheritance.
-
-// Compilers using Microsoft's structure need to be treated as a special case.
-#ifdef FASTDLGT_MICROSOFT_MFP
-
-#ifdef FASTDLGT_HASINHERITANCE_KEYWORDS
- // For Microsoft and Intel, we want to ensure that it's the most efficient type of MFP
- // (4 bytes), even when the /vmg option is used. Declaring an empty class
- // would give 16 byte pointers in this case....
- class __single_inheritance GenericClass;
-#endif
- // ...but for Codeplay, an empty class *always* gives 4 byte pointers.
- // If compiled with the /clr option ("managed C++"), the JIT compiler thinks
- // it needs to load GenericClass before it can call any of its functions,
- // (compiles OK but crashes at runtime!), so we need to declare an
- // empty class to make it happy.
- // Codeplay and VC4 can't cope with the unknown_inheritance case either.
- class GenericClass {};
-#else
- class GenericClass;
-#endif
-
-// The size of a single inheritance member function pointer.
-const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (GenericClass::*)());
-
-// SimplifyMemFunc< >::Convert()
-//
-// A template function that converts an arbitrary member function pointer into the
-// simplest possible form of member function pointer, using a supplied 'this' pointer.
-// According to the standard, this can be done legally with reinterpret_cast<>.
-// For (non-standard) compilers which use member function pointers which vary in size
-// depending on the class, we need to use knowledge of the internal structure of a
-// member function pointer, as used by the compiler. Template specialization is used
-// to distinguish between the sizes. Because some compilers don't support partial
-// template specialisation, I use full specialisation of a wrapper struct.
-
-// general case -- don't know how to convert it. Force a compile failure
-template <int N>
-struct SimplifyMemFunc
-{
- template <class X, class XFuncType, class GenericMemFuncType>
- inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
- GenericMemFuncType &bound_func)
- {
- // Unsupported member function type -- force a compile failure.
- // (it's illegal to have a array with negative size).
- typedef char ERROR_Unsupported_member_function_pointer_on_this_compiler[N-100];
- return 0;
- }
-};
-
-// For compilers where all member func ptrs are the same size, everything goes here.
-// For non-standard compilers, only single_inheritance classes go here.
-template <>
-struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE>
-{
- template <class X, class XFuncType, class GenericMemFuncType>
- inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
- GenericMemFuncType &bound_func)
- {
-#if defined __DMC__
- // Digital Mars doesn't allow you to cast between abitrary PMF's,
- // even though the standard says you can. The 32-bit compiler lets you
- // static_cast through an int, but the DOS compiler doesn't.
- bound_func = horrible_cast<GenericMemFuncType>(function_to_bind);
-#else
- bound_func = reinterpret_cast<GenericMemFuncType>(function_to_bind);
-#endif
- return reinterpret_cast<GenericClass *>(pthis);
- }
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// Fast Delegates, part 1b:
-//
-// Workarounds for Microsoft and Intel
-//
-////////////////////////////////////////////////////////////////////////////////
-
-
-// Compilers with member function pointers which violate the standard (MSVC, Intel, Codeplay),
-// need to be treated as a special case.
-#ifdef FASTDLGT_MICROSOFT_MFP
-
-// We use unions to perform horrible_casts. I would like to use #pragma pack(push, 1)
-// at the start of each function for extra safety, but VC6 seems to ICE
-// intermittently if you do this inside a template.
-
-// __multiple_inheritance classes go here
-// Nasty hack for Microsoft and Intel (IA32 and Itanium)
-template<>
-struct SimplifyMemFunc< SINGLE_MEMFUNCPTR_SIZE + sizeof(int) >
-{
- template <class X, class XFuncType, class GenericMemFuncType>
- inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
- GenericMemFuncType &bound_func)
- {
- // We need to use a horrible_cast to do this conversion.
- // In MSVC, a multiple inheritance member pointer is internally defined as:
- union
- {
- XFuncType func;
- struct
- {
- GenericMemFuncType funcaddress; // points to the actual member function
- int delta; // #BYTES to be added to the 'this' pointer
- }s;
- } u;
- // Check that the horrible_cast will work
- typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s)? 1 : -1];
- u.func = function_to_bind;
- bound_func = u.s.funcaddress;
- return reinterpret_cast<GenericClass *>(reinterpret_cast<char *>(pthis) + u.s.delta);
- }
-};
-
-// virtual inheritance is a real nuisance. It's inefficient and complicated.
-// On MSVC and Intel, there isn't enough information in the pointer itself to
-// enable conversion to a closure pointer. Earlier versions of this code didn't
-// work for all cases, and generated a compile-time error instead.
-// But a very clever hack invented by John M. Dlugosz solves this problem.
-// My code is somewhat different to his: I have no asm code, and I make no
-// assumptions about the calling convention that is used.
-
-// In VC++ and ICL, a virtual_inheritance member pointer
-// is internally defined as:
-struct MicrosoftVirtualMFP
-{
- void (GenericClass::*codeptr)(); // points to the actual member function
- int delta; // #bytes to be added to the 'this' pointer
- int vtable_index; // or 0 if no virtual inheritance
-};
-// The CRUCIAL feature of Microsoft/Intel MFPs which we exploit is that the
-// m_codeptr member is *always* called, regardless of the values of the other
-// members. (This is *not* true for other compilers, eg GCC, which obtain the
-// function address from the vtable if a virtual function is being called).
-// Dlugosz's trick is to make the codeptr point to a probe function which
-// returns the 'this' pointer that was used.
-
-// Define a generic class that uses virtual inheritance.
-// It has a trival member function that returns the value of the 'this' pointer.
-struct GenericVirtualClass : virtual public GenericClass
-{
- typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)();
- GenericVirtualClass * GetThis() { return this; }
-};
-
-// __virtual_inheritance classes go here
-#ifdef _MSC_VER
-#pragma warning( disable : 4121 )
-#endif
-
-template <>
-struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE + 2*sizeof(int) >
-{
- template <class X, class XFuncType, class GenericMemFuncType>
- inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
- GenericMemFuncType &bound_func)
- {
- union
- {
- XFuncType func;
- GenericClass* (X::*ProbeFunc)();
- MicrosoftVirtualMFP s;
- } u;
- u.func = function_to_bind;
- bound_func = reinterpret_cast<GenericMemFuncType>(u.s.codeptr);
- union
- {
- GenericVirtualClass::ProbePtrType virtfunc;
- MicrosoftVirtualMFP s;
- } u2;
- // Check that the horrible_cast<>s will work
- typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s)
- && sizeof(function_to_bind)==sizeof(u.ProbeFunc)
- && sizeof(u2.virtfunc)==sizeof(u2.s) ? 1 : -1];
- // Unfortunately, taking the address of a MF prevents it from being inlined, so
- // this next line can't be completely optimised away by the compiler.
- u2.virtfunc = &GenericVirtualClass::GetThis;
- u.s.codeptr = u2.s.codeptr;
- return (pthis->*u.ProbeFunc)();
- }
-};
-#ifdef _MSC_VER
-#pragma warning( default : 4121 )
-#endif
-
-#if (_MSC_VER <1300)
-
-// Nasty hack for Microsoft Visual C++ 6.0
-// unknown_inheritance classes go here
-// There is a compiler bug in MSVC6 which generates incorrect code in this case!!
-template <>
-struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE + 3*sizeof(int) >
-{
- template <class X, class XFuncType, class GenericMemFuncType>
- inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
- GenericMemFuncType &bound_func)
- {
- // There is an apalling but obscure compiler bug in MSVC6 and earlier:
- // vtable_index and 'vtordisp' are always set to 0 in the
- // unknown_inheritance case!
- // This means that an incorrect function could be called!!!
- // Compiling with the /vmg option leads to potentially incorrect code.
- // This is probably the reason that the IDE has a user interface for specifying
- // the /vmg option, but it is disabled - you can only specify /vmg on
- // the command line. In VC1.5 and earlier, the compiler would ICE if it ever
- // encountered this situation.
- // It is OK to use the /vmg option if /vmm or /vms is specified.
-
- // Fortunately, the wrong function is only called in very obscure cases.
- // It only occurs when a derived class overrides a virtual function declared
- // in a virtual base class, and the member function
- // points to the *Derived* version of that function. The problem can be
- // completely averted in 100% of cases by using the *Base class* for the
- // member fpointer. Ie, if you use the base class as an interface, you'll
- // stay out of trouble.
- // Occasionally, you might want to point directly to a derived class function
- // that isn't an override of a base class. In this case, both vtable_index
- // and 'vtordisp' are zero, but a virtual_inheritance pointer will be generated.
- // We can generate correct code in this case. To prevent an incorrect call from
- // ever being made, on MSVC6 we generate a warning, and call a function to
- // make the program crash instantly.
- typedef char ERROR_VC6CompilerBug[-100];
- return 0;
- }
-};
-
-
-#else
-
-// Nasty hack for Microsoft and Intel (IA32 and Itanium)
-// unknown_inheritance classes go here
-// This is probably the ugliest bit of code I've ever written. Look at the casts!
-// There is a compiler bug in MSVC6 which prevents it from using this code.
-template <>
-struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE + 3*sizeof(int) >
-{
- template <class X, class XFuncType, class GenericMemFuncType>
- inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
- GenericMemFuncType &bound_func)
- {
- // The member function pointer is 16 bytes long. We can't use a normal cast, but
- // we can use a union to do the conversion.
- union
- {
- XFuncType func;
- // In VC++ and ICL, an unknown_inheritance member pointer
- // is internally defined as:
- struct
- {
- GenericMemFuncType funcaddress; // points to the actual member function
- int delta; // #bytes to be added to the 'this' pointer
- int vtordisp; // #bytes to add to 'this' to find the vtable
- int vtable_index; // or 0 if no virtual inheritance
- } s;
- } u;
- // Check that the horrible_cast will work
- typedef int ERROR_CantUsehorrible_cast[sizeof(XFuncType)==sizeof(u.s)? 1 : -1];
- u.func = function_to_bind;
- bound_func = u.s.funcaddress;
- int virtual_delta = 0;
- if (u.s.vtable_index)
- { // Virtual inheritance is used
- // First, get to the vtable.
- // It is 'vtordisp' bytes from the start of the class.
- const int * vtable = *reinterpret_cast<const int *const*>(
- reinterpret_cast<const char *>(pthis) + u.s.vtordisp );
-
- // 'vtable_index' tells us where in the table we should be looking.
- virtual_delta = u.s.vtordisp + *reinterpret_cast<const int *>(
- reinterpret_cast<const char *>(vtable) + u.s.vtable_index);
- }
- // The int at 'virtual_delta' gives us the amount to add to 'this'.
- // Finally we can add the three components together. Phew!
- return reinterpret_cast<GenericClass *>(
- reinterpret_cast<char *>(pthis) + u.s.delta + virtual_delta);
- };
-};
-#endif // MSVC 7 and greater
-
-#endif // MS/Intel hacks
-
-} // namespace detail
-
-////////////////////////////////////////////////////////////////////////////////
-// Fast Delegates, part 2:
-//
-// Define the delegate storage, and cope with static functions
-//
-////////////////////////////////////////////////////////////////////////////////
-
-// CUtlAbstractDelegate -- an opaque structure which can hold an arbitary delegate.
-// It knows nothing about the calling convention or number of arguments used by
-// the function pointed to.
-// It supplies comparison operators so that it can be stored in STL collections.
-// It cannot be set to anything other than null, nor invoked directly:
-// it must be converted to a specific delegate.
-
-// Implementation:
-// There are two possible implementations: the Safe method and the Evil method.
-// CUtlAbstractDelegate - Safe version
-//
-// This implementation is standard-compliant, but a bit tricky.
-// A static function pointer is stored inside the class.
-// Here are the valid values:
-// +-- Static pointer --+--pThis --+-- pMemFunc-+-- Meaning------+
-// | 0 | 0 | 0 | Empty |
-// | !=0 |(dontcare)| Invoker | Static function|
-// | 0 | !=0 | !=0* | Method call |
-// +--------------------+----------+------------+----------------+
-// * For Metrowerks, this can be 0. (first virtual function in a
-// single_inheritance class).
-// When stored stored inside a specific delegate, the 'dontcare' entries are replaced
-// with a reference to the delegate itself. This complicates the = and == operators
-// for the delegate class.
-
-// CUtlAbstractDelegate - Evil version
-//
-// For compilers where data pointers are at least as big as code pointers, it is
-// possible to store the function pointer in the this pointer, using another
-// horrible_cast. In this case the CUtlAbstractDelegate implementation is simple:
-// +--pThis --+-- pMemFunc-+-- Meaning---------------------+
-// | 0 | 0 | Empty |
-// | !=0 | !=0* | Static function or method call|
-// +----------+------------+-------------------------------+
-// * For Metrowerks, this can be 0. (first virtual function in a
-// single_inheritance class).
-// Note that the Sun C++ and MSVC documentation explicitly state that they
-// support static_cast between void * and function pointers.
-
-class CUtlAbstractDelegate
-{
-protected:
- // the data is protected, not private, because many
- // compilers have problems with template friends.
- typedef void (detail::GenericClass::*GenericMemFuncType)(); // arbitrary MFP.
- detail::GenericClass *m_pthis;
- GenericMemFuncType m_pFunction;
-
-#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
- typedef void (*GenericFuncPtr)(); // arbitrary code pointer
- GenericFuncPtr m_pStaticFunction;
-#endif
-
-public:
-#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
- CUtlAbstractDelegate() : m_pthis(0), m_pFunction(0), m_pStaticFunction(0) {};
- void Clear()
- {
- m_pthis=0; m_pFunction=0; m_pStaticFunction=0;
- }
-#else
- CUtlAbstractDelegate() : m_pthis(0), m_pFunction(0) {};
- void Clear() { m_pthis=0; m_pFunction=0; }
-#endif
-public:
-#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
- inline bool IsEqual (const CUtlAbstractDelegate &x) const
- {
- // We have to cope with the static function pointers as a special case
- if (m_pFunction!=x.m_pFunction)
- return false;
- // the static function ptrs must either both be equal, or both be 0.
- if (m_pStaticFunction!=x.m_pStaticFunction)
- return false;
- if (m_pStaticFunction!=0)
- return m_pthis==x.m_pthis;
- else
- return true;
- }
-#else // Evil Method
- inline bool IsEqual (const CUtlAbstractDelegate &x) const
- {
- return m_pthis==x.m_pthis && m_pFunction==x.m_pFunction;
- }
-#endif
- // Provide a strict weak ordering for DelegateMementos.
- inline bool IsLess(const CUtlAbstractDelegate &right) const
- {
- // deal with static function pointers first
-#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
- if (m_pStaticFunction !=0 || right.m_pStaticFunction!=0)
- return m_pStaticFunction < right.m_pStaticFunction;
-#endif
- if (m_pthis !=right.m_pthis)
- return m_pthis < right.m_pthis;
- // There are no ordering operators for member function pointers,
- // but we can fake one by comparing each byte. The resulting ordering is
- // arbitrary (and compiler-dependent), but it permits storage in ordered STL containers.
- return memcmp(&m_pFunction, &right.m_pFunction, sizeof(m_pFunction)) < 0;
-
- }
- // BUGFIX (Mar 2005):
- // We can't just compare m_pFunction because on Metrowerks,
- // m_pFunction can be zero even if the delegate is not empty!
- inline bool operator ! () const // Is it bound to anything?
- {
- return m_pthis==0 && m_pFunction==0;
- }
- inline bool IsEmpty() const // Is it bound to anything?
- {
- return m_pthis==0 && m_pFunction==0;
- }
-public:
- CUtlAbstractDelegate & operator = (const CUtlAbstractDelegate &right)
- {
- SetMementoFrom(right);
- return *this;
- }
- inline bool operator <(const CUtlAbstractDelegate &right)
- {
- return IsLess(right);
- }
- inline bool operator >(const CUtlAbstractDelegate &right)
- {
- return right.IsLess(*this);
- }
- CUtlAbstractDelegate (const CUtlAbstractDelegate &right) :
- m_pFunction(right.m_pFunction), m_pthis(right.m_pthis)
-#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
- , m_pStaticFunction (right.m_pStaticFunction)
-#endif
- {}
-
- // Only use this if you really know what you're doing.
- // It's used in cases where I've cached off a delegate previously
- void UnsafeThisPointerSlam( void *pThis )
- {
- m_pthis = (detail::GenericClass*)( pThis );
- }
-
- void *UnsafeGetThisPtr()
- {
- return m_pthis;
- }
-
-protected:
- void SetMementoFrom(const CUtlAbstractDelegate &right)
- {
- m_pFunction = right.m_pFunction;
- m_pthis = right.m_pthis;
-#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
- m_pStaticFunction = right.m_pStaticFunction;
-#endif
- }
-};
-
-
-// ClosurePtr<>
-//
-// A private wrapper class that adds function signatures to CUtlAbstractDelegate.
-// It's the class that does most of the actual work.
-// The signatures are specified by:
-// GenericMemFunc: must be a type of GenericClass member function pointer.
-// StaticFuncPtr: must be a type of function pointer with the same signature
-// as GenericMemFunc.
-// UnvoidStaticFuncPtr: is the same as StaticFuncPtr, except on VC6
-// where it never returns void (returns DefaultVoid instead).
-
-// An outer class, FastDelegateN<>, handles the invoking and creates the
-// necessary typedefs.
-// This class does everything else.
-
-namespace detail
-{
-
-template < class GenericMemFunc, class StaticFuncPtr, class UnvoidStaticFuncPtr>
-class ClosurePtr : public CUtlAbstractDelegate
-{
-public:
- // These functions are for setting the delegate to a member function.
-
- // Here's the clever bit: we convert an arbitrary member function into a
- // standard form. XMemFunc should be a member function of class X, but I can't
- // enforce that here. It needs to be enforced by the wrapper class.
- template < class X, class XMemFunc >
- inline void bindmemfunc(X *pthis, XMemFunc function_to_bind )
- {
- m_pthis = SimplifyMemFunc< sizeof(function_to_bind) >
- ::Convert(pthis, function_to_bind, m_pFunction);
-#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
- m_pStaticFunction = 0;
-#endif
- }
- // For const member functions, we only need a const class pointer.
- // Since we know that the member function is const, it's safe to
- // remove the const qualifier from the 'this' pointer with a const_cast.
- // VC6 has problems if we just overload 'bindmemfunc', so we give it a different name.
- template < class X, class XMemFunc>
- inline void bindconstmemfunc(const X *pthis, XMemFunc function_to_bind)
- {
- m_pthis= SimplifyMemFunc< sizeof(function_to_bind) >
- ::Convert(const_cast<X*>(pthis), function_to_bind, m_pFunction);
-#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
- m_pStaticFunction = 0;
-#endif
- }
-#ifdef FASTDELEGATE_GCC_BUG_8271 // At present, GCC doesn't recognize constness of MFPs in templates
- template < class X, class XMemFunc>
- inline void bindmemfunc(const X *pthis, XMemFunc function_to_bind)
- {
- bindconstmemfunc(pthis, function_to_bind);
-#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
- m_pStaticFunction = 0;
-#endif
- }
-#endif
- // These functions are required for invoking the stored function
- inline GenericClass *GetClosureThis() const { return m_pthis; }
- inline GenericMemFunc GetClosureMemPtr() const { return reinterpret_cast<GenericMemFunc>(m_pFunction); }
-
-// There are a few ways of dealing with static function pointers.
-// There's a standard-compliant, but tricky method.
-// There's also a straightforward hack, that won't work on DOS compilers using the
-// medium memory model. It's so evil that I can't recommend it, but I've
-// implemented it anyway because it produces very nice asm code.
-
-#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
-
-// ClosurePtr<> - Safe version
-//
-// This implementation is standard-compliant, but a bit tricky.
-// I store the function pointer inside the class, and the delegate then
-// points to itself. Whenever the delegate is copied, these self-references
-// must be transformed, and this complicates the = and == operators.
-public:
- // The next two functions are for operator ==, =, and the copy constructor.
- // We may need to convert the m_pthis pointers, so that
- // they remain as self-references.
- template< class DerivedClass >
- inline void CopyFrom (DerivedClass *pParent, const CUtlAbstractDelegate &x)
- {
- SetMementoFrom(x);
- if (m_pStaticFunction!=0)
- {
- // transform self references...
- m_pthis=reinterpret_cast<GenericClass *>(pParent);
- }
- }
- // For static functions, the 'static_function_invoker' class in the parent
- // will be called. The parent then needs to call GetStaticFunction() to find out
- // the actual function to invoke.
- template < class DerivedClass, class ParentInvokerSig >
- inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker,
- StaticFuncPtr function_to_bind )
- {
- if (function_to_bind==0)
- { // cope with assignment to 0
- m_pFunction=0;
- }
- else
- {
- bindmemfunc(pParent, static_function_invoker);
- }
- m_pStaticFunction=reinterpret_cast<GenericFuncPtr>(function_to_bind);
- }
- inline UnvoidStaticFuncPtr GetStaticFunction() const
- {
- return reinterpret_cast<UnvoidStaticFuncPtr>(m_pStaticFunction);
- }
-#else
-
-// ClosurePtr<> - Evil version
-//
-// For compilers where data pointers are at least as big as code pointers, it is
-// possible to store the function pointer in the this pointer, using another
-// horrible_cast. Invocation isn't any faster, but it saves 4 bytes, and
-// speeds up comparison and assignment. If C++ provided direct language support
-// for delegates, they would produce asm code that was almost identical to this.
-// Note that the Sun C++ and MSVC documentation explicitly state that they
-// support static_cast between void * and function pointers.
-
- template< class DerivedClass >
- inline void CopyFrom (DerivedClass *pParent, const CUtlAbstractDelegate &right)
- {
- pParent;
- SetMementoFrom(right);
- }
- // For static functions, the 'static_function_invoker' class in the parent
- // will be called. The parent then needs to call GetStaticFunction() to find out
- // the actual function to invoke.
- // ******** EVIL, EVIL CODE! *******
- template < class DerivedClass, class ParentInvokerSig>
- inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker,
- StaticFuncPtr function_to_bind)
- {
- if (function_to_bind==0)
- { // cope with assignment to 0
- m_pFunction=0;
- }
- else
- {
- // We'll be ignoring the 'this' pointer, but we need to make sure we pass
- // a valid value to bindmemfunc().
- bindmemfunc(pParent, static_function_invoker);
- }
-
- // WARNING! Evil hack. We store the function in the 'this' pointer!
- // Ensure that there's a compilation failure if function pointers
- // and data pointers have different sizes.
- // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK.
- typedef int ERROR_CantUseEvilMethod[sizeof(GenericClass *)==sizeof(function_to_bind) ? 1 : -1];
- m_pthis = horrible_cast<GenericClass *>(function_to_bind);
- // MSVC, SunC++ and DMC accept the following (non-standard) code:
-// m_pthis = static_cast<GenericClass *>(static_cast<void *>(function_to_bind));
- // BCC32, Comeau and DMC accept this method. MSVC7.1 needs __int64 instead of long
-// m_pthis = reinterpret_cast<GenericClass *>(reinterpret_cast<long>(function_to_bind));
- }
- // ******** EVIL, EVIL CODE! *******
- // This function will be called with an invalid 'this' pointer!!
- // We're just returning the 'this' pointer, converted into
- // a function pointer!
- inline UnvoidStaticFuncPtr GetStaticFunction() const
- {
- // Ensure that there's a compilation failure if function pointers
- // and data pointers have different sizes.
- // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK.
- typedef int ERROR_CantUseEvilMethod[sizeof(UnvoidStaticFuncPtr)==sizeof(this) ? 1 : -1];
- return horrible_cast<UnvoidStaticFuncPtr>(this);
- }
-#endif // !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
-
- // Does the closure contain this static function?
- inline bool IsEqualToStaticFuncPtr(StaticFuncPtr funcptr)
- {
- if (funcptr==0) return IsEmpty();
- // For the Evil method, if it doesn't actually contain a static function, this will return an arbitrary
- // value that is not equal to any valid function pointer.
- else return funcptr==reinterpret_cast<StaticFuncPtr>(GetStaticFunction());
- }
-};
-
-
-} // namespace detail
-
-////////////////////////////////////////////////////////////////////////////////
-// Fast Delegates, part 3:
-//
-// Wrapper classes to ensure type safety
-//
-////////////////////////////////////////////////////////////////////////////////
-
-
-// Once we have the member function conversion templates, it's easy to make the
-// wrapper classes. So that they will work with as many compilers as possible,
-// the classes are of the form
-// FastDelegate3<int, char *, double>
-// They can cope with any combination of parameters. The max number of parameters
-// allowed is 8, but it is trivial to increase this limit.
-// Note that we need to treat const member functions seperately.
-// All this class does is to enforce type safety, and invoke the delegate with
-// the correct list of parameters.
-
-// Because of the weird rule about the class of derived member function pointers,
-// you sometimes need to apply a downcast to the 'this' pointer.
-// This is the reason for the use of "implicit_cast<X*>(pthis)" in the code below.
-// If CDerivedClass is derived from CBaseClass, but doesn't override SimpleVirtualFunction,
-// without this trick you'd need to write:
-// MyDelegate(static_cast<CBaseClass *>(&d), &CDerivedClass::SimpleVirtualFunction);
-// but with the trick you can write
-// MyDelegate(&d, &CDerivedClass::SimpleVirtualFunction);
-
-// RetType is the type the compiler uses in compiling the template. For VC6,
-// it cannot be void. DesiredRetType is the real type which is returned from
-// all of the functions. It can be void.
-
-// Implicit conversion to "bool" is achieved using the safe_bool idiom,
-// using member data pointers (MDP). This allows "if (dg)..." syntax
-// Because some compilers (eg codeplay) don't have a unique value for a zero
-// MDP, an extra padding member is added to the SafeBool struct.
-// Some compilers (eg VC6) won't implicitly convert from 0 to an MDP, so
-// in that case the static function constructor is not made explicit; this
-// allows "if (dg==0) ..." to compile.
-
-//N=0
-template<class RetType=detail::DefaultVoid>
-class FastDelegate0
-{
-private:
- typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
- typedef DesiredRetType (*StaticFunctionPtr)();
- typedef RetType (*UnvoidStaticFunctionPtr)();
- typedef RetType (detail::GenericClass::*GenericMemFn)();
- typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
- ClosureType m_Closure;
-public:
- // Typedefs to aid generic programming
- typedef FastDelegate0 type;
-
- // Construction and comparison functions
- FastDelegate0() { Clear(); }
- FastDelegate0(const FastDelegate0 &x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
- void operator = (const FastDelegate0 &x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
- bool operator ==(const FastDelegate0 &x) const
- {
- return m_Closure.IsEqual(x.m_Closure);
- }
- bool operator !=(const FastDelegate0 &x) const
- {
- return !m_Closure.IsEqual(x.m_Closure);
- }
- bool operator <(const FastDelegate0 &x) const
- {
- return m_Closure.IsLess(x.m_Closure);
- }
- bool operator >(const FastDelegate0 &x) const
- {
- return x.m_Closure.IsLess(m_Closure);
- }
- // Binding to non-const member functions
- template < class X, class Y >
- FastDelegate0(Y *pthis, DesiredRetType (X::* function_to_bind)() )
- {
- m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
- }
- template < class X, class Y >
- inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)())
- {
- m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
- }
- // Binding to const member functions.
- template < class X, class Y >
- FastDelegate0(const Y *pthis, DesiredRetType (X::* function_to_bind)() const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);
- }
- template < class X, class Y >
- inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)() const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);
- }
- // Static functions. We convert them into a member function call.
- // This constructor also provides implicit conversion
- FastDelegate0(DesiredRetType (*function_to_bind)() )
- {
- Bind(function_to_bind);
- }
- // for efficiency, prevent creation of a temporary
- void operator = (DesiredRetType (*function_to_bind)() )
- {
- Bind(function_to_bind);
- }
- inline void Bind(DesiredRetType (*function_to_bind)())
- {
- m_Closure.bindstaticfunc(this, &FastDelegate0::InvokeStaticFunction,
- function_to_bind);
- }
- // Invoke the delegate
- RetType operator() () const
- {
- return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))();
- }
- // Implicit conversion to "bool" using the safe_bool idiom
-private:
- typedef struct SafeBoolStruct
- {
- int a_data_pointer_to_this_is_0_on_buggy_compilers;
- StaticFunctionPtr m_nonzero;
- } UselessTypedef;
- typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
-public:
- operator unspecified_bool_type() const
- {
- return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
- }
- // necessary to allow ==0 to work despite the safe_bool idiom
- inline bool operator==(StaticFunctionPtr funcptr)
- {
- return m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
- inline bool operator!=(StaticFunctionPtr funcptr)
- {
- return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
- inline bool operator ! () const
- { // Is it bound to anything?
- return !m_Closure;
- }
- inline bool IsEmpty() const
- {
- return !m_Closure;
- }
- void Clear() { m_Closure.Clear();}
- // Conversion to and from the CUtlAbstractDelegate storage class
- const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; }
- void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); }
-
-private: // Invoker for static functions
- RetType InvokeStaticFunction() const
- {
- return (*(m_Closure.GetStaticFunction()))();
- }
-};
-
-//N=1
-template<class Param1, class RetType=detail::DefaultVoid>
-class FastDelegate1
-{
-private:
- typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
- typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1);
- typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1);
- typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1);
- typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
- ClosureType m_Closure;
-public:
- // Typedefs to aid generic programming
- typedef FastDelegate1 type;
-
- // Construction and comparison functions
- FastDelegate1() { Clear(); }
- FastDelegate1(const FastDelegate1 &x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
- void operator = (const FastDelegate1 &x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
- bool operator ==(const FastDelegate1 &x) const
- {
- return m_Closure.IsEqual(x.m_Closure);
- }
- bool operator !=(const FastDelegate1 &x) const
- {
- return !m_Closure.IsEqual(x.m_Closure);
- }
- bool operator <(const FastDelegate1 &x) const
- {
- return m_Closure.IsLess(x.m_Closure);
- }
- bool operator >(const FastDelegate1 &x) const
- {
- return x.m_Closure.IsLess(m_Closure);
- }
- // Binding to non-const member functions
- template < class X, class Y >
- FastDelegate1(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) )
- {
- m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
- }
- template < class X, class Y >
- inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1))
- {
- m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
- }
- // Binding to const member functions.
- template < class X, class Y >
- FastDelegate1(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);
- }
- template < class X, class Y >
- inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);
- }
- // Static functions. We convert them into a member function call.
- // This constructor also provides implicit conversion
- FastDelegate1(DesiredRetType (*function_to_bind)(Param1 p1) )
- {
- Bind(function_to_bind);
- }
- // for efficiency, prevent creation of a temporary
- void operator = (DesiredRetType (*function_to_bind)(Param1 p1) )
- {
- Bind(function_to_bind);
- }
- inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1))
- {
- m_Closure.bindstaticfunc(this, &FastDelegate1::InvokeStaticFunction,
- function_to_bind);
- }
- // Invoke the delegate
- RetType operator() (Param1 p1) const
- {
- return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1);
- }
- // Implicit conversion to "bool" using the safe_bool idiom
-private:
- typedef struct SafeBoolStruct
- {
- int a_data_pointer_to_this_is_0_on_buggy_compilers;
- StaticFunctionPtr m_nonzero;
- } UselessTypedef;
- typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
-public:
- operator unspecified_bool_type() const
- {
- return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
- }
- // necessary to allow ==0 to work despite the safe_bool idiom
- inline bool operator==(StaticFunctionPtr funcptr)
- {
- return m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
- inline bool operator!=(StaticFunctionPtr funcptr)
- {
- return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
- inline bool operator ! () const
- { // Is it bound to anything?
- return !m_Closure;
- }
- inline bool IsEmpty() const
- {
- return !m_Closure;
- }
- void Clear() { m_Closure.Clear();}
- // Conversion to and from the CUtlAbstractDelegate storage class
- const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; }
- void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); }
-
-private: // Invoker for static functions
- RetType InvokeStaticFunction(Param1 p1) const
- {
- return (*(m_Closure.GetStaticFunction()))(p1);
- }
-};
-
-//N=2
-template<class Param1, class Param2, class RetType=detail::DefaultVoid>
-class FastDelegate2
-{
-private:
- typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
- typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2);
- typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2);
- typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2);
- typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
- ClosureType m_Closure;
-public:
- // Typedefs to aid generic programming
- typedef FastDelegate2 type;
-
- // Construction and comparison functions
- FastDelegate2() { Clear(); }
- FastDelegate2(const FastDelegate2 &x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
- void operator = (const FastDelegate2 &x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
- bool operator ==(const FastDelegate2 &x) const
- {
- return m_Closure.IsEqual(x.m_Closure);
- }
- bool operator !=(const FastDelegate2 &x) const
- {
- return !m_Closure.IsEqual(x.m_Closure);
- }
- bool operator <(const FastDelegate2 &x) const
- {
- return m_Closure.IsLess(x.m_Closure);
- }
- bool operator >(const FastDelegate2 &x) const
- {
- return x.m_Closure.IsLess(m_Closure);
- }
- // Binding to non-const member functions
- template < class X, class Y >
- FastDelegate2(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) )
- {
- m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
- }
- template < class X, class Y >
- inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2))
- {
- m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
- }
- // Binding to const member functions.
- template < class X, class Y >
- FastDelegate2(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);
- }
- template < class X, class Y >
- inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);
- }
- // Static functions. We convert them into a member function call.
- // This constructor also provides implicit conversion
- FastDelegate2(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) )
- {
- Bind(function_to_bind);
- }
- // for efficiency, prevent creation of a temporary
- void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) )
- {
- Bind(function_to_bind);
- }
- inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2))
- {
- m_Closure.bindstaticfunc(this, &FastDelegate2::InvokeStaticFunction,
- function_to_bind);
- }
- // Invoke the delegate
- RetType operator() (Param1 p1, Param2 p2) const
- {
- return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2);
- }
- // Implicit conversion to "bool" using the safe_bool idiom
-private:
- typedef struct SafeBoolStruct
- {
- int a_data_pointer_to_this_is_0_on_buggy_compilers;
- StaticFunctionPtr m_nonzero;
- } UselessTypedef;
- typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
-public:
- operator unspecified_bool_type() const
- {
- return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
- }
- // necessary to allow ==0 to work despite the safe_bool idiom
- inline bool operator==(StaticFunctionPtr funcptr)
- {
- return m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
- inline bool operator!=(StaticFunctionPtr funcptr)
- {
- return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
- inline bool operator ! () const
- { // Is it bound to anything?
- return !m_Closure;
- }
- inline bool IsEmpty() const
- {
- return !m_Closure;
- }
- void Clear() { m_Closure.Clear();}
- // Conversion to and from the CUtlAbstractDelegate storage class
- const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; }
- void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); }
-
-private: // Invoker for static functions
- RetType InvokeStaticFunction(Param1 p1, Param2 p2) const
- {
- return (*(m_Closure.GetStaticFunction()))(p1, p2);
- }
-};
-
-//N=3
-template<class Param1, class Param2, class Param3, class RetType=detail::DefaultVoid>
-class FastDelegate3
-{
-private:
- typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
- typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3);
- typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3);
- typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3);
- typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
- ClosureType m_Closure;
-public:
- // Typedefs to aid generic programming
- typedef FastDelegate3 type;
-
- // Construction and comparison functions
- FastDelegate3() { Clear(); }
- FastDelegate3(const FastDelegate3 &x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
- void operator = (const FastDelegate3 &x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
- bool operator ==(const FastDelegate3 &x) const
- {
- return m_Closure.IsEqual(x.m_Closure);
- }
- bool operator !=(const FastDelegate3 &x) const
- {
- return !m_Closure.IsEqual(x.m_Closure);
- }
- bool operator <(const FastDelegate3 &x) const
- {
- return m_Closure.IsLess(x.m_Closure);
- }
- bool operator >(const FastDelegate3 &x) const
- {
- return x.m_Closure.IsLess(m_Closure);
- }
- // Binding to non-const member functions
- template < class X, class Y >
- FastDelegate3(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) )
- {
- m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
- }
- template < class X, class Y >
- inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3))
- {
- m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
- }
- // Binding to const member functions.
- template < class X, class Y >
- FastDelegate3(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);
- }
- template < class X, class Y >
- inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);
- }
- // Static functions. We convert them into a member function call.
- // This constructor also provides implicit conversion
- FastDelegate3(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) )
- {
- Bind(function_to_bind);
- }
- // for efficiency, prevent creation of a temporary
- void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) )
- {
- Bind(function_to_bind);
- }
- inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3))
- {
- m_Closure.bindstaticfunc(this, &FastDelegate3::InvokeStaticFunction,
- function_to_bind);
- }
- // Invoke the delegate
- RetType operator() (Param1 p1, Param2 p2, Param3 p3) const
- {
- return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3);
- }
- // Implicit conversion to "bool" using the safe_bool idiom
-private:
- typedef struct SafeBoolStruct
- {
- int a_data_pointer_to_this_is_0_on_buggy_compilers;
- StaticFunctionPtr m_nonzero;
- } UselessTypedef;
- typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
-public:
- operator unspecified_bool_type() const
- {
- return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
- }
- // necessary to allow ==0 to work despite the safe_bool idiom
- inline bool operator==(StaticFunctionPtr funcptr)
- {
- return m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
- inline bool operator!=(StaticFunctionPtr funcptr)
- {
- return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
- inline bool operator ! () const
- { // Is it bound to anything?
- return !m_Closure;
- }
- inline bool IsEmpty() const
- {
- return !m_Closure;
- }
- void Clear() { m_Closure.Clear();}
- // Conversion to and from the CUtlAbstractDelegate storage class
- const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; }
- void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); }
-
-private: // Invoker for static functions
- RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3) const
- {
- return (*(m_Closure.GetStaticFunction()))(p1, p2, p3);
- }
-};
-
-//N=4
-template<class Param1, class Param2, class Param3, class Param4, class RetType=detail::DefaultVoid>
-class FastDelegate4
-{
-private:
- typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
- typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
- typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
- typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
- typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
- ClosureType m_Closure;
-public:
- // Typedefs to aid generic programming
- typedef FastDelegate4 type;
-
- // Construction and comparison functions
- FastDelegate4() { Clear(); }
- FastDelegate4(const FastDelegate4 &x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
- void operator = (const FastDelegate4 &x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
- bool operator ==(const FastDelegate4 &x) const
- {
- return m_Closure.IsEqual(x.m_Closure);
- }
- bool operator !=(const FastDelegate4 &x) const
- {
- return !m_Closure.IsEqual(x.m_Closure);
- }
- bool operator <(const FastDelegate4 &x) const
- {
- return m_Closure.IsLess(x.m_Closure);
- }
- bool operator >(const FastDelegate4 &x) const
- {
- return x.m_Closure.IsLess(m_Closure);
- }
- // Binding to non-const member functions
- template < class X, class Y >
- FastDelegate4(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) )
- {
- m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
- }
- template < class X, class Y >
- inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4))
- {
- m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
- }
- // Binding to const member functions.
- template < class X, class Y >
- FastDelegate4(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);
- }
- template < class X, class Y >
- inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);
- }
- // Static functions. We convert them into a member function call.
- // This constructor also provides implicit conversion
- FastDelegate4(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) )
- {
- Bind(function_to_bind);
- }
- // for efficiency, prevent creation of a temporary
- void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) )
- {
- Bind(function_to_bind);
- }
- inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4))
- {
- m_Closure.bindstaticfunc(this, &FastDelegate4::InvokeStaticFunction,
- function_to_bind);
- }
- // Invoke the delegate
- RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4) const
- {
- return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4);
- }
- // Implicit conversion to "bool" using the safe_bool idiom
-private:
- typedef struct SafeBoolStruct
- {
- int a_data_pointer_to_this_is_0_on_buggy_compilers;
- StaticFunctionPtr m_nonzero;
- } UselessTypedef;
- typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
-public:
- operator unspecified_bool_type() const
- {
- return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
- }
- // necessary to allow ==0 to work despite the safe_bool idiom
- inline bool operator==(StaticFunctionPtr funcptr)
- {
- return m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
- inline bool operator!=(StaticFunctionPtr funcptr)
- {
- return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
- inline bool operator ! () const
- { // Is it bound to anything?
- return !m_Closure;
- }
- inline bool IsEmpty() const
- {
- return !m_Closure;
- }
- void Clear() { m_Closure.Clear();}
- // Conversion to and from the CUtlAbstractDelegate storage class
- const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; }
- void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); }
-
-private: // Invoker for static functions
- RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const
- {
- return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4);
- }
-};
-
-//N=5
-template<class Param1, class Param2, class Param3, class Param4, class Param5, class RetType=detail::DefaultVoid>
-class FastDelegate5
-{
-private:
- typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
- typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
- typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
- typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
- typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
- ClosureType m_Closure;
-public:
- // Typedefs to aid generic programming
- typedef FastDelegate5 type;
-
- // Construction and comparison functions
- FastDelegate5() { Clear(); }
- FastDelegate5(const FastDelegate5 &x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
- void operator = (const FastDelegate5 &x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
- bool operator ==(const FastDelegate5 &x) const
- {
- return m_Closure.IsEqual(x.m_Closure);
- }
- bool operator !=(const FastDelegate5 &x) const
- {
- return !m_Closure.IsEqual(x.m_Closure);
- }
- bool operator <(const FastDelegate5 &x) const
- {
- return m_Closure.IsLess(x.m_Closure);
- }
- bool operator >(const FastDelegate5 &x) const
- {
- return x.m_Closure.IsLess(m_Closure);
- }
- // Binding to non-const member functions
- template < class X, class Y >
- FastDelegate5(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) )
- {
- m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
- }
- template < class X, class Y >
- inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5))
- {
- m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
- }
- // Binding to const member functions.
- template < class X, class Y >
- FastDelegate5(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);
- }
- template < class X, class Y >
- inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);
- }
- // Static functions. We convert them into a member function call.
- // This constructor also provides implicit conversion
- FastDelegate5(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) )
- {
- Bind(function_to_bind);
- }
- // for efficiency, prevent creation of a temporary
- void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) )
- {
- Bind(function_to_bind);
- }
- inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5))
- {
- m_Closure.bindstaticfunc(this, &FastDelegate5::InvokeStaticFunction,
- function_to_bind);
- }
- // Invoke the delegate
- RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const
- {
- return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5);
- }
- // Implicit conversion to "bool" using the safe_bool idiom
-private:
- typedef struct SafeBoolStruct
- {
- int a_data_pointer_to_this_is_0_on_buggy_compilers;
- StaticFunctionPtr m_nonzero;
- } UselessTypedef;
- typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
-public:
- operator unspecified_bool_type() const
- {
- return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
- }
- // necessary to allow ==0 to work despite the safe_bool idiom
- inline bool operator==(StaticFunctionPtr funcptr)
- {
- return m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
- inline bool operator!=(StaticFunctionPtr funcptr)
- {
- return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
- inline bool operator ! () const
- { // Is it bound to anything?
- return !m_Closure;
- }
- inline bool IsEmpty() const
- {
- return !m_Closure;
- }
- void Clear() { m_Closure.Clear();}
- // Conversion to and from the CUtlAbstractDelegate storage class
- const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; }
- void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); }
-
-private: // Invoker for static functions
- RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const
- {
- return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5);
- }
-};
-
-//N=6
-template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType=detail::DefaultVoid>
-class FastDelegate6
-{
-private:
- typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
- typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
- typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
- typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
- typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
- ClosureType m_Closure;
-public:
- // Typedefs to aid generic programming
- typedef FastDelegate6 type;
-
- // Construction and comparison functions
- FastDelegate6() { Clear(); }
- FastDelegate6(const FastDelegate6 &x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
- void operator = (const FastDelegate6 &x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
- bool operator ==(const FastDelegate6 &x) const
- {
- return m_Closure.IsEqual(x.m_Closure);
- }
- bool operator !=(const FastDelegate6 &x) const
- {
- return !m_Closure.IsEqual(x.m_Closure);
- }
- bool operator <(const FastDelegate6 &x) const
- {
- return m_Closure.IsLess(x.m_Closure);
- }
- bool operator >(const FastDelegate6 &x) const
- {
- return x.m_Closure.IsLess(m_Closure);
- }
- // Binding to non-const member functions
- template < class X, class Y >
- FastDelegate6(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) )
- {
- m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
- }
- template < class X, class Y >
- inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6))
- {
- m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
- }
- // Binding to const member functions.
- template < class X, class Y >
- FastDelegate6(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);
- }
- template < class X, class Y >
- inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);
- }
- // Static functions. We convert them into a member function call.
- // This constructor also provides implicit conversion
- FastDelegate6(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) )
- {
- Bind(function_to_bind);
- }
- // for efficiency, prevent creation of a temporary
- void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) )
- {
- Bind(function_to_bind);
- }
- inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6))
- {
- m_Closure.bindstaticfunc(this, &FastDelegate6::InvokeStaticFunction,
- function_to_bind);
- }
- // Invoke the delegate
- RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const
- {
- return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6);
- }
- // Implicit conversion to "bool" using the safe_bool idiom
-private:
- typedef struct SafeBoolStruct
- {
- int a_data_pointer_to_this_is_0_on_buggy_compilers;
- StaticFunctionPtr m_nonzero;
- } UselessTypedef;
- typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
-public:
- operator unspecified_bool_type() const
- {
- return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
- }
- // necessary to allow ==0 to work despite the safe_bool idiom
- inline bool operator==(StaticFunctionPtr funcptr)
- {
- return m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
- inline bool operator!=(StaticFunctionPtr funcptr)
- {
- return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
- inline bool operator ! () const
- { // Is it bound to anything?
- return !m_Closure;
- }
- inline bool IsEmpty() const
- {
- return !m_Closure;
- }
- void Clear() { m_Closure.Clear();}
- // Conversion to and from the CUtlAbstractDelegate storage class
- const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; }
- void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); }
-
-private: // Invoker for static functions
- RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const
- {
- return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6);
- }
-};
-
-//N=7
-template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType=detail::DefaultVoid>
-class FastDelegate7
-{
-private:
- typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
- typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
- typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
- typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
- typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
- ClosureType m_Closure;
-public:
- // Typedefs to aid generic programming
- typedef FastDelegate7 type;
-
- // Construction and comparison functions
- FastDelegate7() { Clear(); }
- FastDelegate7(const FastDelegate7 &x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
- void operator = (const FastDelegate7 &x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
- bool operator ==(const FastDelegate7 &x) const
- {
- return m_Closure.IsEqual(x.m_Closure);
- }
- bool operator !=(const FastDelegate7 &x) const
- {
- return !m_Closure.IsEqual(x.m_Closure);
- }
- bool operator <(const FastDelegate7 &x) const
- {
- return m_Closure.IsLess(x.m_Closure);
- }
- bool operator >(const FastDelegate7 &x) const
- {
- return x.m_Closure.IsLess(m_Closure);
- }
- // Binding to non-const member functions
- template < class X, class Y >
- FastDelegate7(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) )
- {
- m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
- }
- template < class X, class Y >
- inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7))
- {
- m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
- }
- // Binding to const member functions.
- template < class X, class Y >
- FastDelegate7(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);
- }
- template < class X, class Y >
- inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);
- }
- // Static functions. We convert them into a member function call.
- // This constructor also provides implicit conversion
- FastDelegate7(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) )
- {
- Bind(function_to_bind);
- }
- // for efficiency, prevent creation of a temporary
- void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) )
- {
- Bind(function_to_bind);
- }
- inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7))
- {
- m_Closure.bindstaticfunc(this, &FastDelegate7::InvokeStaticFunction,
- function_to_bind);
- }
- // Invoke the delegate
- RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const
- {
- return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7);
- }
- // Implicit conversion to "bool" using the safe_bool idiom
-private:
- typedef struct SafeBoolStruct
- {
- int a_data_pointer_to_this_is_0_on_buggy_compilers;
- StaticFunctionPtr m_nonzero;
- } UselessTypedef;
- typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
-public:
- operator unspecified_bool_type() const
- {
- return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
- }
- // necessary to allow ==0 to work despite the safe_bool idiom
- inline bool operator==(StaticFunctionPtr funcptr)
- {
- return m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
- inline bool operator!=(StaticFunctionPtr funcptr)
- {
- return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
- inline bool operator ! () const
- { // Is it bound to anything?
- return !m_Closure;
- }
- inline bool IsEmpty() const
- {
- return !m_Closure;
- }
- void Clear() { m_Closure.Clear();}
- // Conversion to and from the CUtlAbstractDelegate storage class
- const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; }
- void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); }
-
-private: // Invoker for static functions
- RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const
- {
- return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7);
- }
-};
-
-//N=8
-template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType=detail::DefaultVoid>
-class FastDelegate8
-{
-private:
- typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
- typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
- typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
- typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
- typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
- ClosureType m_Closure;
-public:
- // Typedefs to aid generic programming
- typedef FastDelegate8 type;
-
- // Construction and comparison functions
- FastDelegate8() { Clear(); }
- FastDelegate8(const FastDelegate8 &x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
- void operator = (const FastDelegate8 &x)
- {
- m_Closure.CopyFrom(this, x.m_Closure);
- }
- bool operator ==(const FastDelegate8 &x) const
- {
- return m_Closure.IsEqual(x.m_Closure);
- }
- bool operator !=(const FastDelegate8 &x) const
- {
- return !m_Closure.IsEqual(x.m_Closure);
- }
- bool operator <(const FastDelegate8 &x) const
- {
- return m_Closure.IsLess(x.m_Closure);
- }
- bool operator >(const FastDelegate8 &x) const
- {
- return x.m_Closure.IsLess(m_Closure);
- }
- // Binding to non-const member functions
- template < class X, class Y >
- FastDelegate8(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) )
- {
- m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
- }
- template < class X, class Y >
- inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8))
- {
- m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
- }
- // Binding to const member functions.
- template < class X, class Y >
- FastDelegate8(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);
- }
- template < class X, class Y >
- inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const)
- {
- m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);
- }
- // Static functions. We convert them into a member function call.
- // This constructor also provides implicit conversion
- FastDelegate8(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) )
- {
- Bind(function_to_bind);
- }
- // for efficiency, prevent creation of a temporary
- void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) )
- {
- Bind(function_to_bind);
- }
- inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8))
- {
- m_Closure.bindstaticfunc(this, &FastDelegate8::InvokeStaticFunction,
- function_to_bind);
- }
- // Invoke the delegate
- RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const
- {
- return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8);
- }
- // Implicit conversion to "bool" using the safe_bool idiom
-private:
- typedef struct SafeBoolStruct
- {
- int a_data_pointer_to_this_is_0_on_buggy_compilers;
- StaticFunctionPtr m_nonzero;
- } UselessTypedef;
- typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
-public:
- operator unspecified_bool_type() const
- {
- return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
- }
- // necessary to allow ==0 to work despite the safe_bool idiom
- inline bool operator==(StaticFunctionPtr funcptr)
- {
- return m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
- inline bool operator!=(StaticFunctionPtr funcptr)
- {
- return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
- }
- inline bool operator ! () const
- { // Is it bound to anything?
- return !m_Closure;
- }
- inline bool IsEmpty() const
- {
- return !m_Closure;
- }
- void Clear() { m_Closure.Clear();}
- // Conversion to and from the CUtlAbstractDelegate storage class
- const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; }
- void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); }
-
-private: // Invoker for static functions
- RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const
- {
- return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8);
- }
-};
-
-
-////////////////////////////////////////////////////////////////////////////////
-// Fast Delegates, part 4:
-//
-// CUtlDelegate<> class (Original author: Jody Hagins)
-// Allows boost::function style syntax like:
-// CUtlDelegate< double (int, long) >
-// instead of:
-// FastDelegate2< int, long, double >
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#ifdef FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
-
-// Declare CUtlDelegate as a class template. It will be specialized
-// later for all number of arguments.
-template <typename Signature>
-class CUtlDelegate;
-
-//N=0
-// Specialization to allow use of
-// CUtlDelegate< R ( ) >
-// instead of
-// FastDelegate0 < R >
-template<typename R>
-class CUtlDelegate< R ( ) >
- // Inherit from FastDelegate0 so that it can be treated just like a FastDelegate0
- : public FastDelegate0 < R >
-{
-public:
- // Make using the base type a bit easier via typedef.
- typedef FastDelegate0 < R > BaseType;
-
- // Allow users access to the specific type of this delegate.
- typedef CUtlDelegate SelfType;
-
- // Mimic the base class constructors.
- CUtlDelegate() : BaseType() { }
-
- template < class X, class Y >
- CUtlDelegate(Y * pthis, R (X::* function_to_bind)( ))
- : BaseType(pthis, function_to_bind)
- { }
-
- template < class X, class Y >
- CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( ) const)
- : BaseType(pthis, function_to_bind)
- { }
-
- CUtlDelegate(R (*function_to_bind)( ))
- : BaseType(function_to_bind)
- { }
-
- void operator = (const BaseType &x)
- {
- *static_cast<BaseType*>(this) = x;
- }
-};
-
-//N=1
-// Specialization to allow use of
-// CUtlDelegate< R ( Param1 ) >
-// instead of
-// FastDelegate1 < Param1, R >
-template<typename R, class Param1>
-class CUtlDelegate< R ( Param1 ) >
- // Inherit from FastDelegate1 so that it can be treated just like a FastDelegate1
- : public FastDelegate1 < Param1, R >
-{
- public:
- // Make using the base type a bit easier via typedef.
- typedef FastDelegate1 < Param1, R > BaseType;
-
- // Allow users access to the specific type of this delegate.
- typedef CUtlDelegate SelfType;
-
- // Mimic the base class constructors.
- CUtlDelegate() : BaseType() { }
-
- template < class X, class Y >
- CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1 ))
- : BaseType(pthis, function_to_bind)
- { }
-
- template < class X, class Y >
- CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1 ) const)
- : BaseType(pthis, function_to_bind)
- { }
-
- CUtlDelegate(R (*function_to_bind)( Param1 p1 ))
- : BaseType(function_to_bind)
- { }
-
- void operator = (const BaseType &x)
- {
- *static_cast<BaseType*>(this) = x;
- }
-};
-
-//N=2
-// Specialization to allow use of
-// CUtlDelegate< R ( Param1, Param2 ) >
-// instead of
-// FastDelegate2 < Param1, Param2, R >
-template<typename R, class Param1, class Param2>
-class CUtlDelegate< R ( Param1, Param2 ) >
- // Inherit from FastDelegate2 so that it can be treated just like a FastDelegate2
- : public FastDelegate2 < Param1, Param2, R >
-{
- public:
- // Make using the base type a bit easier via typedef.
- typedef FastDelegate2 < Param1, Param2, R > BaseType;
-
- // Allow users access to the specific type of this delegate.
- typedef CUtlDelegate SelfType;
-
- // Mimic the base class constructors.
- CUtlDelegate() : BaseType() { }
-
- template < class X, class Y >
- CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2 ))
- : BaseType(pthis, function_to_bind)
- { }
-
- template < class X, class Y >
- CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2 ) const)
- : BaseType(pthis, function_to_bind)
- { }
-
- CUtlDelegate(R (*function_to_bind)( Param1 p1, Param2 p2 ))
- : BaseType(function_to_bind)
- { }
-
- void operator = (const BaseType &x)
- {
- *static_cast<BaseType*>(this) = x;
- }
-};
-
-//N=3
-// Specialization to allow use of
-// CUtlDelegate< R ( Param1, Param2, Param3 ) >
-// instead of
-// FastDelegate3 < Param1, Param2, Param3, R >
-template<typename R, class Param1, class Param2, class Param3>
-class CUtlDelegate< R ( Param1, Param2, Param3 ) >
- // Inherit from FastDelegate3 so that it can be treated just like a FastDelegate3
- : public FastDelegate3 < Param1, Param2, Param3, R >
-{
-public:
- // Make using the base type a bit easier via typedef.
- typedef FastDelegate3 < Param1, Param2, Param3, R > BaseType;
-
- // Allow users access to the specific type of this delegate.
- typedef CUtlDelegate SelfType;
-
- // Mimic the base class constructors.
- CUtlDelegate() : BaseType() { }
-
- template < class X, class Y >
- CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ))
- : BaseType(pthis, function_to_bind)
- { }
-
- template < class X, class Y >
- CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ) const)
- : BaseType(pthis, function_to_bind)
- { }
-
- CUtlDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ))
- : BaseType(function_to_bind)
- { }
-
- void operator = (const BaseType &x)
- {
- *static_cast<BaseType*>(this) = x;
- }
-};
-
-//N=4
-// Specialization to allow use of
-// CUtlDelegate< R ( Param1, Param2, Param3, Param4 ) >
-// instead of
-// FastDelegate4 < Param1, Param2, Param3, Param4, R >
-template<typename R, class Param1, class Param2, class Param3, class Param4>
-class CUtlDelegate< R ( Param1, Param2, Param3, Param4 ) >
- // Inherit from FastDelegate4 so that it can be treated just like a FastDelegate4
- : public FastDelegate4 < Param1, Param2, Param3, Param4, R >
-{
-public:
- // Make using the base type a bit easier via typedef.
- typedef FastDelegate4 < Param1, Param2, Param3, Param4, R > BaseType;
-
- // Allow users access to the specific type of this delegate.
- typedef CUtlDelegate SelfType;
-
- // Mimic the base class constructors.
- CUtlDelegate() : BaseType() { }
-
- template < class X, class Y >
- CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ))
- : BaseType(pthis, function_to_bind)
- { }
-
- template < class X, class Y >
- CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) const)
- : BaseType(pthis, function_to_bind)
- { }
-
- CUtlDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ))
- : BaseType(function_to_bind)
- { }
-
- void operator = (const BaseType &x)
- {
- *static_cast<BaseType*>(this) = x;
- }
-};
-
-//N=5
-// Specialization to allow use of
-// CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) >
-// instead of
-// FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R >
-template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5>
-class CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) >
- // Inherit from FastDelegate5 so that it can be treated just like a FastDelegate5
- : public FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R >
-{
-public:
- // Make using the base type a bit easier via typedef.
- typedef FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > BaseType;
-
- // Allow users access to the specific type of this delegate.
- typedef CUtlDelegate SelfType;
-
- // Mimic the base class constructors.
- CUtlDelegate() : BaseType() { }
-
- template < class X, class Y >
- CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ))
- : BaseType(pthis, function_to_bind)
- { }
-
- template < class X, class Y >
- CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) const)
- : BaseType(pthis, function_to_bind)
- { }
-
- CUtlDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ))
- : BaseType(function_to_bind)
- { }
-
- void operator = (const BaseType &x)
- {
- *static_cast<BaseType*>(this) = x;
- }
-};
-
-//N=6
-// Specialization to allow use of
-// CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) >
-// instead of
-// FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R >
-template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6>
-class CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) >
- // Inherit from FastDelegate6 so that it can be treated just like a FastDelegate6
- : public FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R >
-{
-public:
- // Make using the base type a bit easier via typedef.
- typedef FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > BaseType;
-
- // Allow users access to the specific type of this delegate.
- typedef CUtlDelegate SelfType;
-
- // Mimic the base class constructors.
- CUtlDelegate() : BaseType() { }
-
- template < class X, class Y >
- CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ))
- : BaseType(pthis, function_to_bind)
- { }
-
- template < class X, class Y >
- CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) const)
- : BaseType(pthis, function_to_bind)
- { }
-
- CUtlDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ))
- : BaseType(function_to_bind)
- { }
-
- void operator = (const BaseType &x)
- {
- *static_cast<BaseType*>(this) = x;
- }
-};
-
-//N=7
-// Specialization to allow use of
-// CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >
-// instead of
-// FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R >
-template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7>
-class CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >
- // Inherit from FastDelegate7 so that it can be treated just like a FastDelegate7
- : public FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R >
-{
-public:
- // Make using the base type a bit easier via typedef.
- typedef FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > BaseType;
-
- // Allow users access to the specific type of this delegate.
- typedef CUtlDelegate SelfType;
-
- // Mimic the base class constructors.
- CUtlDelegate() : BaseType() { }
-
- template < class X, class Y >
- CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ))
- : BaseType(pthis, function_to_bind)
- { }
-
- template < class X, class Y >
- CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) const)
- : BaseType(pthis, function_to_bind)
- { }
-
- CUtlDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ))
- : BaseType(function_to_bind)
- { }
-
- void operator = (const BaseType &x)
- {
- *static_cast<BaseType*>(this) = x;
- }
-};
-
-//N=8
-// Specialization to allow use of
-// CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >
-// instead of
-// FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R >
-template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8>
-class CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >
- // Inherit from FastDelegate8 so that it can be treated just like a FastDelegate8
- : public FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R >
-{
-public:
- // Make using the base type a bit easier via typedef.
- typedef FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > BaseType;
-
- // Allow users access to the specific type of this delegate.
- typedef CUtlDelegate SelfType;
-
- // Mimic the base class constructors.
- CUtlDelegate() : BaseType() { }
-
- template < class X, class Y >
- CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ))
- : BaseType(pthis, function_to_bind)
- { }
-
- template < class X, class Y >
- CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) const)
- : BaseType(pthis, function_to_bind)
- { }
-
- CUtlDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ))
- : BaseType(function_to_bind)
- { }
-
- void operator = (const BaseType &x)
- {
- *static_cast<BaseType*>(this) = x;
- }
-};
-
-
-#endif //FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
-
-////////////////////////////////////////////////////////////////////////////////
-// Fast Delegates, part 5:
-//
-// UtlMakeDelegate() helper function
-//
-// UtlMakeDelegate(&x, &X::func) returns a fastdelegate of the type
-// necessary for calling x.func() with the correct number of arguments.
-// This makes it possible to eliminate many typedefs from user code.
-//
-////////////////////////////////////////////////////////////////////////////////
-
-// Also declare overloads of a UtlMakeDelegate() global function to
-// reduce the need for typedefs.
-// We need seperate overloads for const and non-const member functions.
-// Also, because of the weird rule about the class of derived member function pointers,
-// implicit downcasts may need to be applied later to the 'this' pointer.
-// That's why two classes (X and Y) appear in the definitions. Y must be implicitly
-// castable to X.
-
-// Workaround for VC6. VC6 needs void return types converted into DefaultVoid.
-// GCC 3.2 and later won't compile this unless it's preceded by 'typename',
-// but VC6 doesn't allow 'typename' in this context.
-// So, I have to use a macro.
-
-#ifdef FASTDLGT_VC6
-#define FASTDLGT_RETTYPE detail::VoidToDefaultVoid<RetType>::type
-#else
-#define FASTDLGT_RETTYPE RetType
-#endif
-
-
-//N=0
-template <class X, class Y, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( ) > UtlMakeDelegate(Y* x, RetType (X::*func)())
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( ) >(x, func);
-}
-
-template <class X, class Y, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( ) > UtlMakeDelegate(Y* x, RetType (X::*func)() const)
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( ) >(x, func);
-}
-
-template < class RetType >
-CUtlDelegate< FASTDLGT_RETTYPE ( ) > UtlMakeDelegate( RetType (*func)())
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( ) >( func );
-}
-
-//N=1
-template <class X, class Y, class Param1, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1))
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1 ) >(x, func);
-}
-
-template <class X, class Y, class Param1, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1) const)
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1 ) >(x, func);
-}
-
-template < class Param1, class RetType >
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1 ) > UtlMakeDelegate( RetType (*func)(Param1 p1))
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1 ) >( func );
-}
-
-
-//N=2
-template <class X, class Y, class Param1, class Param2, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2))
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2 ) >(x, func);
-}
-
-template <class X, class Y, class Param1, class Param2, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2) const)
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2 ) >(x, func);
-}
-
-template <class Param1, class Param2, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2 ) > UtlMakeDelegate( RetType (*func)(Param1 p1, Param2 p2))
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2 ) >(func);
-}
-
-//N=3
-template <class X, class Y, class Param1, class Param2, class Param3, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3))
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3 ) >(x, func);
-}
-
-template <class X, class Y, class Param1, class Param2, class Param3, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3) const)
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3 ) >(x, func);
-}
-
-template <class Param1, class Param2, class Param3, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3 ) > UtlMakeDelegate( RetType (*func)(Param1 p1, Param2 p2, Param3 p3))
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3 ) >(func);
-}
-
-//N=4
-template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4))
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4 ) >(x, func);
-}
-
-template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const)
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4 ) >(x, func);
-}
-
-template <class Param1, class Param2, class Param3, class Param4, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4 ) > UtlMakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4))
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4 ) >(func);
-}
-
-//N=5
-template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5))
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5 ) >(x, func);
-}
-
-template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const)
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5 ) >(x, func);
-}
-
-template <class Param1, class Param2, class Param3, class Param4, class Param5, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5 ) > UtlMakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5))
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5 ) >(func);
-}
-
-//N=6
-template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6))
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6 ) >(x, func);
-}
-
-template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const)
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6 ) >(x, func);
-}
-
-template <class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6 ) > UtlMakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6))
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6 ) >(func);
-}
-
-//N=7
-template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7))
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >(x, func);
-}
-
-template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const)
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >(x, func);
-}
-
-template <class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > UtlMakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7))
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >(func);
-}
-
-//N=8
-template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8))
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >(x, func);
-}
-
-template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const)
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >(x, func);
-}
-
-template <class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType>
-CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > UtlMakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8))
-{
- return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >(func);
-}
-
-
-// clean up after ourselves...
-#undef FASTDLGT_RETTYPE
-
-#endif // !defined(UTLDELEGATEIMPL_H)
-
+//========= Copyright Valve Corporation, All rights reserved. ============//
+// FastDelegate.h
+// Efficient delegates in C++ that generate only two lines of asm code!
+// Documentation is found at http://www.codeproject.com/cpp/FastDelegate.asp
+//
+// - Don Clugston, Mar 2004.
+// Major contributions were made by Jody Hagins.
+// History:
+// 24-Apr-04 1.0 * Submitted to CodeProject.
+// 28-Apr-04 1.1 * Prevent most unsafe uses of evil static function hack.
+// * Improved syntax for horrible_cast (thanks Paul Bludov).
+// * Tested on Metrowerks MWCC and Intel ICL (IA32)
+// * Compiled, but not run, on Comeau C++ and Intel Itanium ICL.
+// 27-Jun-04 1.2 * Now works on Borland C++ Builder 5.5
+// * Now works on /clr "managed C++" code on VC7, VC7.1
+// * Comeau C++ now compiles without warnings.
+// * Prevent the virtual inheritance case from being used on
+// VC6 and earlier, which generate incorrect code.
+// * Improved warning and error messages. Non-standard hacks
+// now have compile-time checks to make them safer.
+// * implicit_cast used instead of static_cast in many cases.
+// * If calling a const member function, a const class pointer can be used.
+// * UtlMakeDelegate() global helper function added to simplify pass-by-value.
+// * Added fastdelegate.Clear()
+// 16-Jul-04 1.2.1* Workaround for gcc bug (const member function pointers in templates)
+// 30-Oct-04 1.3 * Support for (non-void) return values.
+// * No more workarounds in client code!
+// MSVC and Intel now use a clever hack invented by John Dlugosz:
+// - The FASTDELEGATEDECLARE workaround is no longer necessary.
+// - No more warning messages for VC6
+// * Less use of macros. Error messages should be more comprehensible.
+// * Added include guards
+// * Added FastDelegate::IsEmpty() to test if invocation is safe (Thanks Neville Franks).
+// * Now tested on VS 2005 Express Beta, PGI C++
+// 24-Dec-04 1.4 * Added CUtlAbstractDelegate, to allow collections of disparate delegates.
+// * <,>,<=,>= comparison operators to allow storage in ordered containers.
+// * Substantial reduction of code size, especially the 'Closure' class.
+// * Standardised all the compiler-specific workarounds.
+// * MFP conversion now works for CodePlay (but not yet supported in the full code).
+// * Now compiles without warnings on _any_ supported compiler, including BCC 5.5.1
+// * New syntax: FastDelegate< int (char *, double) >.
+// 14-Feb-05 1.4.1* Now treats =0 as equivalent to .Clear(), ==0 as equivalent to .IsEmpty(). (Thanks elfric).
+// * Now tested on Intel ICL for AMD64, VS2005 Beta for AMD64 and Itanium.
+// 30-Mar-05 1.5 * Safebool idiom: "if (dg)" is now equivalent to "if (!dg.IsEmpty())"
+// * Fully supported by CodePlay VectorC
+// * Bugfix for Metrowerks: IsEmpty() was buggy because a valid MFP can be 0 on MWCC!
+// * More optimal assignment,== and != operators for static function pointers.
+// 22-Jul-10 xxx * Reformatted + renamed to match valve coding standards
+// * Added UtlMakeDelegate for static functions
+
+#ifndef UTLDELEGATEIMPL_H
+#define UTLDELEGATEIMPL_H
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include <memory.h> // to allow <,> comparisons
+
+////////////////////////////////////////////////////////////////////////////////
+// Configuration options
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// Uncomment the following #define for optimally-sized delegates.
+// In this case, the generated asm code is almost identical to the code you'd get
+// if the compiler had native support for delegates.
+// It will not work on systems where sizeof(dataptr) < sizeof(codeptr).
+// Thus, it will not work for DOS compilers using the medium model.
+// It will also probably fail on some DSP systems.
+#define FASTDELEGATE_USESTATICFUNCTIONHACK
+
+// Uncomment the next line to allow function declarator syntax.
+// It is automatically enabled for those compilers where it is known to work.
+//#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
+
+////////////////////////////////////////////////////////////////////////////////
+// Compiler identification for workarounds
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// Compiler identification. It's not easy to identify Visual C++ because
+// many vendors fraudulently define Microsoft's identifiers.
+#if defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__VECTOR_C) && !defined(__ICL) && !defined(__BORLANDC__)
+#define FASTDLGT_ISMSVC
+
+#if (_MSC_VER <1300) // Many workarounds are required for VC6.
+#define FASTDLGT_VC6
+#pragma warning(disable:4786) // disable this ridiculous warning
+#endif
+
+#endif
+
+// Does the compiler uses Microsoft's member function pointer structure?
+// If so, it needs special treatment.
+// Metrowerks CodeWarrior, Intel, and CodePlay fraudulently define Microsoft's
+// identifier, _MSC_VER. We need to filter Metrowerks out.
+#if defined(_MSC_VER) && !defined(__MWERKS__)
+#define FASTDLGT_MICROSOFT_MFP
+
+#if !defined(__VECTOR_C)
+// CodePlay doesn't have the __single/multi/virtual_inheritance keywords
+#define FASTDLGT_HASINHERITANCE_KEYWORDS
+#endif
+#endif
+
+// Does it allow function declarator syntax? The following compilers are known to work:
+#if defined(FASTDLGT_ISMSVC) && (_MSC_VER >=1310) // VC 7.1
+#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
+#endif
+
+// Gcc(2.95+), and versions of Digital Mars, Intel and Comeau in common use.
+#if defined (__DMC__) || defined(__GNUC__) || defined(__ICL) || defined(__COMO__)
+#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
+#endif
+
+// It works on Metrowerks MWCC 3.2.2. From boost.Config it should work on earlier ones too.
+#if defined (__MWERKS__)
+#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
+#endif
+
+#ifdef __GNUC__ // Workaround GCC bug #8271
+ // At present, GCC doesn't recognize constness of MFPs in templates
+#define FASTDELEGATE_GCC_BUG_8271
+#endif
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// General tricks used in this code
+//
+// (a) Error messages are generated by typdefing an array of negative size to
+// generate compile-time errors.
+// (b) Warning messages on MSVC are generated by declaring unused variables, and
+// enabling the "variable XXX is never used" warning.
+// (c) Unions are used in a few compiler-specific cases to perform illegal casts.
+// (d) For Microsoft and Intel, when adjusting the 'this' pointer, it's cast to
+// (char *) first to ensure that the correct number of *bytes* are added.
+//
+////////////////////////////////////////////////////////////////////////////////
+// Helper templates
+//
+////////////////////////////////////////////////////////////////////////////////
+
+
+namespace detail // we'll hide the implementation details in a nested namespace.
+{
+
+// implicit_cast< >
+// I believe this was originally going to be in the C++ standard but
+// was left out by accident. It's even milder than static_cast.
+// I use it instead of static_cast<> to emphasize that I'm not doing
+// anything nasty.
+// Usage is identical to static_cast<>
+template <class OutputClass, class InputClass>
+inline OutputClass implicit_cast(InputClass input)
+{
+ return input;
+}
+
+// horrible_cast< >
+// This is truly evil. It completely subverts C++'s type system, allowing you
+// to cast from any class to any other class. Technically, using a union
+// to perform the cast is undefined behaviour (even in C). But we can see if
+// it is OK by checking that the union is the same size as each of its members.
+// horrible_cast<> should only be used for compiler-specific workarounds.
+// Usage is identical to reinterpret_cast<>.
+
+// This union is declared outside the horrible_cast because BCC 5.5.1
+// can't inline a function with a nested class, and gives a warning.
+template <class OutputClass, class InputClass>
+union horrible_union
+{
+ OutputClass out;
+ InputClass in;
+};
+
+template <class OutputClass, class InputClass>
+inline OutputClass horrible_cast(const InputClass input)
+{
+ horrible_union<OutputClass, InputClass> u;
+ // Cause a compile-time error if in, out and u are not the same size.
+ // If the compile fails here, it means the compiler has peculiar
+ // unions which would prevent the cast from working.
+ typedef int ERROR_CantUseHorrible_cast[sizeof(InputClass)==sizeof(u)
+ && sizeof(InputClass)==sizeof(OutputClass) ? 1 : -1];
+ u.in = input;
+ return u.out;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Workarounds
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// Backwards compatibility: This macro used to be necessary in the virtual inheritance
+// case for Intel and Microsoft. Now it just forward-declares the class.
+#define FASTDELEGATEDECLARE(CLASSNAME) class CLASSNAME;
+
+// Prevent use of the static function hack with the DOS medium model.
+#ifdef __MEDIUM__
+#undef FASTDELEGATE_USESTATICFUNCTIONHACK
+#endif
+
+// DefaultVoid - a workaround for 'void' templates in VC6.
+//
+// (1) VC6 and earlier do not allow 'void' as a default template argument.
+// (2) They also doesn't allow you to return 'void' from a function.
+//
+// Workaround for (1): Declare a dummy type 'DefaultVoid' which we use
+// when we'd like to use 'void'. We convert it into 'void' and back
+// using the templates DefaultVoidToVoid<> and VoidToDefaultVoid<>.
+// Workaround for (2): On VC6, the code for calling a void function is
+// identical to the code for calling a non-void function in which the
+// return value is never used, provided the return value is returned
+// in the EAX register, rather than on the stack.
+// This is true for most fundamental types such as int, enum, void *.
+// Const void * is the safest option since it doesn't participate
+// in any automatic conversions. But on a 16-bit compiler it might
+// cause extra code to be generated, so we disable it for all compilers
+// except for VC6 (and VC5).
+#ifdef FASTDLGT_VC6
+// VC6 workaround
+typedef const void * DefaultVoid;
+#else
+// On any other compiler, just use a normal void.
+typedef void DefaultVoid;
+#endif
+
+// Translate from 'DefaultVoid' to 'void'.
+// Everything else is unchanged
+template <class T>
+struct DefaultVoidToVoid { typedef T type; };
+
+template <>
+struct DefaultVoidToVoid<DefaultVoid> { typedef void type; };
+
+// Translate from 'void' into 'DefaultVoid'
+// Everything else is unchanged
+template <class T>
+struct VoidToDefaultVoid { typedef T type; };
+
+template <>
+struct VoidToDefaultVoid<void> { typedef DefaultVoid type; };
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Fast Delegates, part 1:
+//
+// Conversion of member function pointer to a standard form
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// GenericClass is a fake class, ONLY used to provide a type.
+// It is vitally important that it is never defined, so that the compiler doesn't
+// think it can optimize the invocation. For example, Borland generates simpler
+// code if it knows the class only uses single inheritance.
+
+// Compilers using Microsoft's structure need to be treated as a special case.
+#ifdef FASTDLGT_MICROSOFT_MFP
+
+#ifdef FASTDLGT_HASINHERITANCE_KEYWORDS
+ // For Microsoft and Intel, we want to ensure that it's the most efficient type of MFP
+ // (4 bytes), even when the /vmg option is used. Declaring an empty class
+ // would give 16 byte pointers in this case....
+ class __single_inheritance GenericClass;
+#endif
+ // ...but for Codeplay, an empty class *always* gives 4 byte pointers.
+ // If compiled with the /clr option ("managed C++"), the JIT compiler thinks
+ // it needs to load GenericClass before it can call any of its functions,
+ // (compiles OK but crashes at runtime!), so we need to declare an
+ // empty class to make it happy.
+ // Codeplay and VC4 can't cope with the unknown_inheritance case either.
+ class GenericClass {};
+#else
+ class GenericClass;
+#endif
+
+// The size of a single inheritance member function pointer.
+const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (GenericClass::*)());
+
+// SimplifyMemFunc< >::Convert()
+//
+// A template function that converts an arbitrary member function pointer into the
+// simplest possible form of member function pointer, using a supplied 'this' pointer.
+// According to the standard, this can be done legally with reinterpret_cast<>.
+// For (non-standard) compilers which use member function pointers which vary in size
+// depending on the class, we need to use knowledge of the internal structure of a
+// member function pointer, as used by the compiler. Template specialization is used
+// to distinguish between the sizes. Because some compilers don't support partial
+// template specialisation, I use full specialisation of a wrapper struct.
+
+// general case -- don't know how to convert it. Force a compile failure
+template <int N>
+struct SimplifyMemFunc
+{
+ template <class X, class XFuncType, class GenericMemFuncType>
+ inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
+ GenericMemFuncType &bound_func)
+ {
+ // Unsupported member function type -- force a compile failure.
+ // (it's illegal to have a array with negative size).
+ typedef char ERROR_Unsupported_member_function_pointer_on_this_compiler[N-100];
+ return 0;
+ }
+};
+
+// For compilers where all member func ptrs are the same size, everything goes here.
+// For non-standard compilers, only single_inheritance classes go here.
+template <>
+struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE>
+{
+ template <class X, class XFuncType, class GenericMemFuncType>
+ inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
+ GenericMemFuncType &bound_func)
+ {
+#if defined __DMC__
+ // Digital Mars doesn't allow you to cast between abitrary PMF's,
+ // even though the standard says you can. The 32-bit compiler lets you
+ // static_cast through an int, but the DOS compiler doesn't.
+ bound_func = horrible_cast<GenericMemFuncType>(function_to_bind);
+#else
+ bound_func = reinterpret_cast<GenericMemFuncType>(function_to_bind);
+#endif
+ return reinterpret_cast<GenericClass *>(pthis);
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Fast Delegates, part 1b:
+//
+// Workarounds for Microsoft and Intel
+//
+////////////////////////////////////////////////////////////////////////////////
+
+
+// Compilers with member function pointers which violate the standard (MSVC, Intel, Codeplay),
+// need to be treated as a special case.
+#ifdef FASTDLGT_MICROSOFT_MFP
+
+// We use unions to perform horrible_casts. I would like to use #pragma pack(push, 1)
+// at the start of each function for extra safety, but VC6 seems to ICE
+// intermittently if you do this inside a template.
+
+// __multiple_inheritance classes go here
+// Nasty hack for Microsoft and Intel (IA32 and Itanium)
+template<>
+struct SimplifyMemFunc< SINGLE_MEMFUNCPTR_SIZE + sizeof(int) >
+{
+ template <class X, class XFuncType, class GenericMemFuncType>
+ inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
+ GenericMemFuncType &bound_func)
+ {
+ // We need to use a horrible_cast to do this conversion.
+ // In MSVC, a multiple inheritance member pointer is internally defined as:
+ union
+ {
+ XFuncType func;
+ struct
+ {
+ GenericMemFuncType funcaddress; // points to the actual member function
+ int delta; // #BYTES to be added to the 'this' pointer
+ }s;
+ } u;
+ // Check that the horrible_cast will work
+ typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s)? 1 : -1];
+ u.func = function_to_bind;
+ bound_func = u.s.funcaddress;
+ return reinterpret_cast<GenericClass *>(reinterpret_cast<char *>(pthis) + u.s.delta);
+ }
+};
+
+// virtual inheritance is a real nuisance. It's inefficient and complicated.
+// On MSVC and Intel, there isn't enough information in the pointer itself to
+// enable conversion to a closure pointer. Earlier versions of this code didn't
+// work for all cases, and generated a compile-time error instead.
+// But a very clever hack invented by John M. Dlugosz solves this problem.
+// My code is somewhat different to his: I have no asm code, and I make no
+// assumptions about the calling convention that is used.
+
+// In VC++ and ICL, a virtual_inheritance member pointer
+// is internally defined as:
+struct MicrosoftVirtualMFP
+{
+ void (GenericClass::*codeptr)(); // points to the actual member function
+ int delta; // #bytes to be added to the 'this' pointer
+ int vtable_index; // or 0 if no virtual inheritance
+};
+// The CRUCIAL feature of Microsoft/Intel MFPs which we exploit is that the
+// m_codeptr member is *always* called, regardless of the values of the other
+// members. (This is *not* true for other compilers, eg GCC, which obtain the
+// function address from the vtable if a virtual function is being called).
+// Dlugosz's trick is to make the codeptr point to a probe function which
+// returns the 'this' pointer that was used.
+
+// Define a generic class that uses virtual inheritance.
+// It has a trival member function that returns the value of the 'this' pointer.
+struct GenericVirtualClass : virtual public GenericClass
+{
+ typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)();
+ GenericVirtualClass * GetThis() { return this; }
+};
+
+// __virtual_inheritance classes go here
+#ifdef _MSC_VER
+#pragma warning( disable : 4121 )
+#endif
+
+template <>
+struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE + 2*sizeof(int) >
+{
+ template <class X, class XFuncType, class GenericMemFuncType>
+ inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
+ GenericMemFuncType &bound_func)
+ {
+ union
+ {
+ XFuncType func;
+ GenericClass* (X::*ProbeFunc)();
+ MicrosoftVirtualMFP s;
+ } u;
+ u.func = function_to_bind;
+ bound_func = reinterpret_cast<GenericMemFuncType>(u.s.codeptr);
+ union
+ {
+ GenericVirtualClass::ProbePtrType virtfunc;
+ MicrosoftVirtualMFP s;
+ } u2;
+ // Check that the horrible_cast<>s will work
+ typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s)
+ && sizeof(function_to_bind)==sizeof(u.ProbeFunc)
+ && sizeof(u2.virtfunc)==sizeof(u2.s) ? 1 : -1];
+ // Unfortunately, taking the address of a MF prevents it from being inlined, so
+ // this next line can't be completely optimised away by the compiler.
+ u2.virtfunc = &GenericVirtualClass::GetThis;
+ u.s.codeptr = u2.s.codeptr;
+ return (pthis->*u.ProbeFunc)();
+ }
+};
+#ifdef _MSC_VER
+#pragma warning( default : 4121 )
+#endif
+
+#if (_MSC_VER <1300)
+
+// Nasty hack for Microsoft Visual C++ 6.0
+// unknown_inheritance classes go here
+// There is a compiler bug in MSVC6 which generates incorrect code in this case!!
+template <>
+struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE + 3*sizeof(int) >
+{
+ template <class X, class XFuncType, class GenericMemFuncType>
+ inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
+ GenericMemFuncType &bound_func)
+ {
+ // There is an apalling but obscure compiler bug in MSVC6 and earlier:
+ // vtable_index and 'vtordisp' are always set to 0 in the
+ // unknown_inheritance case!
+ // This means that an incorrect function could be called!!!
+ // Compiling with the /vmg option leads to potentially incorrect code.
+ // This is probably the reason that the IDE has a user interface for specifying
+ // the /vmg option, but it is disabled - you can only specify /vmg on
+ // the command line. In VC1.5 and earlier, the compiler would ICE if it ever
+ // encountered this situation.
+ // It is OK to use the /vmg option if /vmm or /vms is specified.
+
+ // Fortunately, the wrong function is only called in very obscure cases.
+ // It only occurs when a derived class overrides a virtual function declared
+ // in a virtual base class, and the member function
+ // points to the *Derived* version of that function. The problem can be
+ // completely averted in 100% of cases by using the *Base class* for the
+ // member fpointer. Ie, if you use the base class as an interface, you'll
+ // stay out of trouble.
+ // Occasionally, you might want to point directly to a derived class function
+ // that isn't an override of a base class. In this case, both vtable_index
+ // and 'vtordisp' are zero, but a virtual_inheritance pointer will be generated.
+ // We can generate correct code in this case. To prevent an incorrect call from
+ // ever being made, on MSVC6 we generate a warning, and call a function to
+ // make the program crash instantly.
+ typedef char ERROR_VC6CompilerBug[-100];
+ return 0;
+ }
+};
+
+
+#else
+
+// Nasty hack for Microsoft and Intel (IA32 and Itanium)
+// unknown_inheritance classes go here
+// This is probably the ugliest bit of code I've ever written. Look at the casts!
+// There is a compiler bug in MSVC6 which prevents it from using this code.
+template <>
+struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE + 3*sizeof(int) >
+{
+ template <class X, class XFuncType, class GenericMemFuncType>
+ inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
+ GenericMemFuncType &bound_func)
+ {
+ // The member function pointer is 16 bytes long. We can't use a normal cast, but
+ // we can use a union to do the conversion.
+ union
+ {
+ XFuncType func;
+ // In VC++ and ICL, an unknown_inheritance member pointer
+ // is internally defined as:
+ struct
+ {
+ GenericMemFuncType funcaddress; // points to the actual member function
+ int delta; // #bytes to be added to the 'this' pointer
+ int vtordisp; // #bytes to add to 'this' to find the vtable
+ int vtable_index; // or 0 if no virtual inheritance
+ } s;
+ } u;
+ // Check that the horrible_cast will work
+ typedef int ERROR_CantUsehorrible_cast[sizeof(XFuncType)==sizeof(u.s)? 1 : -1];
+ u.func = function_to_bind;
+ bound_func = u.s.funcaddress;
+ int virtual_delta = 0;
+ if (u.s.vtable_index)
+ { // Virtual inheritance is used
+ // First, get to the vtable.
+ // It is 'vtordisp' bytes from the start of the class.
+ const int * vtable = *reinterpret_cast<const int *const*>(
+ reinterpret_cast<const char *>(pthis) + u.s.vtordisp );
+
+ // 'vtable_index' tells us where in the table we should be looking.
+ virtual_delta = u.s.vtordisp + *reinterpret_cast<const int *>(
+ reinterpret_cast<const char *>(vtable) + u.s.vtable_index);
+ }
+ // The int at 'virtual_delta' gives us the amount to add to 'this'.
+ // Finally we can add the three components together. Phew!
+ return reinterpret_cast<GenericClass *>(
+ reinterpret_cast<char *>(pthis) + u.s.delta + virtual_delta);
+ };
+};
+#endif // MSVC 7 and greater
+
+#endif // MS/Intel hacks
+
+} // namespace detail
+
+////////////////////////////////////////////////////////////////////////////////
+// Fast Delegates, part 2:
+//
+// Define the delegate storage, and cope with static functions
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// CUtlAbstractDelegate -- an opaque structure which can hold an arbitary delegate.
+// It knows nothing about the calling convention or number of arguments used by
+// the function pointed to.
+// It supplies comparison operators so that it can be stored in STL collections.
+// It cannot be set to anything other than null, nor invoked directly:
+// it must be converted to a specific delegate.
+
+// Implementation:
+// There are two possible implementations: the Safe method and the Evil method.
+// CUtlAbstractDelegate - Safe version
+//
+// This implementation is standard-compliant, but a bit tricky.
+// A static function pointer is stored inside the class.
+// Here are the valid values:
+// +-- Static pointer --+--pThis --+-- pMemFunc-+-- Meaning------+
+// | 0 | 0 | 0 | Empty |
+// | !=0 |(dontcare)| Invoker | Static function|
+// | 0 | !=0 | !=0* | Method call |
+// +--------------------+----------+------------+----------------+
+// * For Metrowerks, this can be 0. (first virtual function in a
+// single_inheritance class).
+// When stored stored inside a specific delegate, the 'dontcare' entries are replaced
+// with a reference to the delegate itself. This complicates the = and == operators
+// for the delegate class.
+
+// CUtlAbstractDelegate - Evil version
+//
+// For compilers where data pointers are at least as big as code pointers, it is
+// possible to store the function pointer in the this pointer, using another
+// horrible_cast. In this case the CUtlAbstractDelegate implementation is simple:
+// +--pThis --+-- pMemFunc-+-- Meaning---------------------+
+// | 0 | 0 | Empty |
+// | !=0 | !=0* | Static function or method call|
+// +----------+------------+-------------------------------+
+// * For Metrowerks, this can be 0. (first virtual function in a
+// single_inheritance class).
+// Note that the Sun C++ and MSVC documentation explicitly state that they
+// support static_cast between void * and function pointers.
+
+class CUtlAbstractDelegate
+{
+protected:
+ // the data is protected, not private, because many
+ // compilers have problems with template friends.
+ typedef void (detail::GenericClass::*GenericMemFuncType)(); // arbitrary MFP.
+ detail::GenericClass *m_pthis;
+ GenericMemFuncType m_pFunction;
+
+#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
+ typedef void (*GenericFuncPtr)(); // arbitrary code pointer
+ GenericFuncPtr m_pStaticFunction;
+#endif
+
+public:
+#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
+ CUtlAbstractDelegate() : m_pthis(0), m_pFunction(0), m_pStaticFunction(0) {};
+ void Clear()
+ {
+ m_pthis=0; m_pFunction=0; m_pStaticFunction=0;
+ }
+#else
+ CUtlAbstractDelegate() : m_pthis(0), m_pFunction(0) {};
+ void Clear() { m_pthis=0; m_pFunction=0; }
+#endif
+public:
+#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
+ inline bool IsEqual (const CUtlAbstractDelegate &x) const
+ {
+ // We have to cope with the static function pointers as a special case
+ if (m_pFunction!=x.m_pFunction)
+ return false;
+ // the static function ptrs must either both be equal, or both be 0.
+ if (m_pStaticFunction!=x.m_pStaticFunction)
+ return false;
+ if (m_pStaticFunction!=0)
+ return m_pthis==x.m_pthis;
+ else
+ return true;
+ }
+#else // Evil Method
+ inline bool IsEqual (const CUtlAbstractDelegate &x) const
+ {
+ return m_pthis==x.m_pthis && m_pFunction==x.m_pFunction;
+ }
+#endif
+ // Provide a strict weak ordering for DelegateMementos.
+ inline bool IsLess(const CUtlAbstractDelegate &right) const
+ {
+ // deal with static function pointers first
+#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
+ if (m_pStaticFunction !=0 || right.m_pStaticFunction!=0)
+ return m_pStaticFunction < right.m_pStaticFunction;
+#endif
+ if (m_pthis !=right.m_pthis)
+ return m_pthis < right.m_pthis;
+ // There are no ordering operators for member function pointers,
+ // but we can fake one by comparing each byte. The resulting ordering is
+ // arbitrary (and compiler-dependent), but it permits storage in ordered STL containers.
+ return memcmp(&m_pFunction, &right.m_pFunction, sizeof(m_pFunction)) < 0;
+
+ }
+ // BUGFIX (Mar 2005):
+ // We can't just compare m_pFunction because on Metrowerks,
+ // m_pFunction can be zero even if the delegate is not empty!
+ inline bool operator ! () const // Is it bound to anything?
+ {
+ return m_pthis==0 && m_pFunction==0;
+ }
+ inline bool IsEmpty() const // Is it bound to anything?
+ {
+ return m_pthis==0 && m_pFunction==0;
+ }
+public:
+ CUtlAbstractDelegate & operator = (const CUtlAbstractDelegate &right)
+ {
+ SetMementoFrom(right);
+ return *this;
+ }
+ inline bool operator <(const CUtlAbstractDelegate &right)
+ {
+ return IsLess(right);
+ }
+ inline bool operator >(const CUtlAbstractDelegate &right)
+ {
+ return right.IsLess(*this);
+ }
+ CUtlAbstractDelegate (const CUtlAbstractDelegate &right) :
+ m_pFunction(right.m_pFunction), m_pthis(right.m_pthis)
+#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
+ , m_pStaticFunction (right.m_pStaticFunction)
+#endif
+ {}
+
+ // Only use this if you really know what you're doing.
+ // It's used in cases where I've cached off a delegate previously
+ void UnsafeThisPointerSlam( void *pThis )
+ {
+ m_pthis = (detail::GenericClass*)( pThis );
+ }
+
+ void *UnsafeGetThisPtr()
+ {
+ return m_pthis;
+ }
+
+protected:
+ void SetMementoFrom(const CUtlAbstractDelegate &right)
+ {
+ m_pFunction = right.m_pFunction;
+ m_pthis = right.m_pthis;
+#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
+ m_pStaticFunction = right.m_pStaticFunction;
+#endif
+ }
+};
+
+
+// ClosurePtr<>
+//
+// A private wrapper class that adds function signatures to CUtlAbstractDelegate.
+// It's the class that does most of the actual work.
+// The signatures are specified by:
+// GenericMemFunc: must be a type of GenericClass member function pointer.
+// StaticFuncPtr: must be a type of function pointer with the same signature
+// as GenericMemFunc.
+// UnvoidStaticFuncPtr: is the same as StaticFuncPtr, except on VC6
+// where it never returns void (returns DefaultVoid instead).
+
+// An outer class, FastDelegateN<>, handles the invoking and creates the
+// necessary typedefs.
+// This class does everything else.
+
+namespace detail
+{
+
+template < class GenericMemFunc, class StaticFuncPtr, class UnvoidStaticFuncPtr>
+class ClosurePtr : public CUtlAbstractDelegate
+{
+public:
+ // These functions are for setting the delegate to a member function.
+
+ // Here's the clever bit: we convert an arbitrary member function into a
+ // standard form. XMemFunc should be a member function of class X, but I can't
+ // enforce that here. It needs to be enforced by the wrapper class.
+ template < class X, class XMemFunc >
+ inline void bindmemfunc(X *pthis, XMemFunc function_to_bind )
+ {
+ m_pthis = SimplifyMemFunc< sizeof(function_to_bind) >
+ ::Convert(pthis, function_to_bind, m_pFunction);
+#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
+ m_pStaticFunction = 0;
+#endif
+ }
+ // For const member functions, we only need a const class pointer.
+ // Since we know that the member function is const, it's safe to
+ // remove the const qualifier from the 'this' pointer with a const_cast.
+ // VC6 has problems if we just overload 'bindmemfunc', so we give it a different name.
+ template < class X, class XMemFunc>
+ inline void bindconstmemfunc(const X *pthis, XMemFunc function_to_bind)
+ {
+ m_pthis= SimplifyMemFunc< sizeof(function_to_bind) >
+ ::Convert(const_cast<X*>(pthis), function_to_bind, m_pFunction);
+#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
+ m_pStaticFunction = 0;
+#endif
+ }
+#ifdef FASTDELEGATE_GCC_BUG_8271 // At present, GCC doesn't recognize constness of MFPs in templates
+ template < class X, class XMemFunc>
+ inline void bindmemfunc(const X *pthis, XMemFunc function_to_bind)
+ {
+ bindconstmemfunc(pthis, function_to_bind);
+#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
+ m_pStaticFunction = 0;
+#endif
+ }
+#endif
+ // These functions are required for invoking the stored function
+ inline GenericClass *GetClosureThis() const { return m_pthis; }
+ inline GenericMemFunc GetClosureMemPtr() const { return reinterpret_cast<GenericMemFunc>(m_pFunction); }
+
+// There are a few ways of dealing with static function pointers.
+// There's a standard-compliant, but tricky method.
+// There's also a straightforward hack, that won't work on DOS compilers using the
+// medium memory model. It's so evil that I can't recommend it, but I've
+// implemented it anyway because it produces very nice asm code.
+
+#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
+
+// ClosurePtr<> - Safe version
+//
+// This implementation is standard-compliant, but a bit tricky.
+// I store the function pointer inside the class, and the delegate then
+// points to itself. Whenever the delegate is copied, these self-references
+// must be transformed, and this complicates the = and == operators.
+public:
+ // The next two functions are for operator ==, =, and the copy constructor.
+ // We may need to convert the m_pthis pointers, so that
+ // they remain as self-references.
+ template< class DerivedClass >
+ inline void CopyFrom (DerivedClass *pParent, const CUtlAbstractDelegate &x)
+ {
+ SetMementoFrom(x);
+ if (m_pStaticFunction!=0)
+ {
+ // transform self references...
+ m_pthis=reinterpret_cast<GenericClass *>(pParent);
+ }
+ }
+ // For static functions, the 'static_function_invoker' class in the parent
+ // will be called. The parent then needs to call GetStaticFunction() to find out
+ // the actual function to invoke.
+ template < class DerivedClass, class ParentInvokerSig >
+ inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker,
+ StaticFuncPtr function_to_bind )
+ {
+ if (function_to_bind==0)
+ { // cope with assignment to 0
+ m_pFunction=0;
+ }
+ else
+ {
+ bindmemfunc(pParent, static_function_invoker);
+ }
+ m_pStaticFunction=reinterpret_cast<GenericFuncPtr>(function_to_bind);
+ }
+ inline UnvoidStaticFuncPtr GetStaticFunction() const
+ {
+ return reinterpret_cast<UnvoidStaticFuncPtr>(m_pStaticFunction);
+ }
+#else
+
+// ClosurePtr<> - Evil version
+//
+// For compilers where data pointers are at least as big as code pointers, it is
+// possible to store the function pointer in the this pointer, using another
+// horrible_cast. Invocation isn't any faster, but it saves 4 bytes, and
+// speeds up comparison and assignment. If C++ provided direct language support
+// for delegates, they would produce asm code that was almost identical to this.
+// Note that the Sun C++ and MSVC documentation explicitly state that they
+// support static_cast between void * and function pointers.
+
+ template< class DerivedClass >
+ inline void CopyFrom (DerivedClass *pParent, const CUtlAbstractDelegate &right)
+ {
+ pParent;
+ SetMementoFrom(right);
+ }
+ // For static functions, the 'static_function_invoker' class in the parent
+ // will be called. The parent then needs to call GetStaticFunction() to find out
+ // the actual function to invoke.
+ // ******** EVIL, EVIL CODE! *******
+ template < class DerivedClass, class ParentInvokerSig>
+ inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker,
+ StaticFuncPtr function_to_bind)
+ {
+ if (function_to_bind==0)
+ { // cope with assignment to 0
+ m_pFunction=0;
+ }
+ else
+ {
+ // We'll be ignoring the 'this' pointer, but we need to make sure we pass
+ // a valid value to bindmemfunc().
+ bindmemfunc(pParent, static_function_invoker);
+ }
+
+ // WARNING! Evil hack. We store the function in the 'this' pointer!
+ // Ensure that there's a compilation failure if function pointers
+ // and data pointers have different sizes.
+ // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK.
+ typedef int ERROR_CantUseEvilMethod[sizeof(GenericClass *)==sizeof(function_to_bind) ? 1 : -1];
+ m_pthis = horrible_cast<GenericClass *>(function_to_bind);
+ // MSVC, SunC++ and DMC accept the following (non-standard) code:
+// m_pthis = static_cast<GenericClass *>(static_cast<void *>(function_to_bind));
+ // BCC32, Comeau and DMC accept this method. MSVC7.1 needs __int64 instead of long
+// m_pthis = reinterpret_cast<GenericClass *>(reinterpret_cast<long>(function_to_bind));
+ }
+ // ******** EVIL, EVIL CODE! *******
+ // This function will be called with an invalid 'this' pointer!!
+ // We're just returning the 'this' pointer, converted into
+ // a function pointer!
+ inline UnvoidStaticFuncPtr GetStaticFunction() const
+ {
+ // Ensure that there's a compilation failure if function pointers
+ // and data pointers have different sizes.
+ // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK.
+ typedef int ERROR_CantUseEvilMethod[sizeof(UnvoidStaticFuncPtr)==sizeof(this) ? 1 : -1];
+ return horrible_cast<UnvoidStaticFuncPtr>(this);
+ }
+#endif // !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
+
+ // Does the closure contain this static function?
+ inline bool IsEqualToStaticFuncPtr(StaticFuncPtr funcptr)
+ {
+ if (funcptr==0) return IsEmpty();
+ // For the Evil method, if it doesn't actually contain a static function, this will return an arbitrary
+ // value that is not equal to any valid function pointer.
+ else return funcptr==reinterpret_cast<StaticFuncPtr>(GetStaticFunction());
+ }
+};
+
+
+} // namespace detail
+
+////////////////////////////////////////////////////////////////////////////////
+// Fast Delegates, part 3:
+//
+// Wrapper classes to ensure type safety
+//
+////////////////////////////////////////////////////////////////////////////////
+
+
+// Once we have the member function conversion templates, it's easy to make the
+// wrapper classes. So that they will work with as many compilers as possible,
+// the classes are of the form
+// FastDelegate3<int, char *, double>
+// They can cope with any combination of parameters. The max number of parameters
+// allowed is 8, but it is trivial to increase this limit.
+// Note that we need to treat const member functions seperately.
+// All this class does is to enforce type safety, and invoke the delegate with
+// the correct list of parameters.
+
+// Because of the weird rule about the class of derived member function pointers,
+// you sometimes need to apply a downcast to the 'this' pointer.
+// This is the reason for the use of "implicit_cast<X*>(pthis)" in the code below.
+// If CDerivedClass is derived from CBaseClass, but doesn't override SimpleVirtualFunction,
+// without this trick you'd need to write:
+// MyDelegate(static_cast<CBaseClass *>(&d), &CDerivedClass::SimpleVirtualFunction);
+// but with the trick you can write
+// MyDelegate(&d, &CDerivedClass::SimpleVirtualFunction);
+
+// RetType is the type the compiler uses in compiling the template. For VC6,
+// it cannot be void. DesiredRetType is the real type which is returned from
+// all of the functions. It can be void.
+
+// Implicit conversion to "bool" is achieved using the safe_bool idiom,
+// using member data pointers (MDP). This allows "if (dg)..." syntax
+// Because some compilers (eg codeplay) don't have a unique value for a zero
+// MDP, an extra padding member is added to the SafeBool struct.
+// Some compilers (eg VC6) won't implicitly convert from 0 to an MDP, so
+// in that case the static function constructor is not made explicit; this
+// allows "if (dg==0) ..." to compile.
+
+//N=0
+template<class RetType=detail::DefaultVoid>
+class FastDelegate0
+{
+private:
+ typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
+ typedef DesiredRetType (*StaticFunctionPtr)();
+ typedef RetType (*UnvoidStaticFunctionPtr)();
+ typedef RetType (detail::GenericClass::*GenericMemFn)();
+ typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
+ ClosureType m_Closure;
+public:
+ // Typedefs to aid generic programming
+ typedef FastDelegate0 type;
+
+ // Construction and comparison functions
+ FastDelegate0() { Clear(); }
+ FastDelegate0(const FastDelegate0 &x)
+ {
+ m_Closure.CopyFrom(this, x.m_Closure);
+ }
+ void operator = (const FastDelegate0 &x)
+ {
+ m_Closure.CopyFrom(this, x.m_Closure);
+ }
+ bool operator ==(const FastDelegate0 &x) const
+ {
+ return m_Closure.IsEqual(x.m_Closure);
+ }
+ bool operator !=(const FastDelegate0 &x) const
+ {
+ return !m_Closure.IsEqual(x.m_Closure);
+ }
+ bool operator <(const FastDelegate0 &x) const
+ {
+ return m_Closure.IsLess(x.m_Closure);
+ }
+ bool operator >(const FastDelegate0 &x) const
+ {
+ return x.m_Closure.IsLess(m_Closure);
+ }
+ // Binding to non-const member functions
+ template < class X, class Y >
+ FastDelegate0(Y *pthis, DesiredRetType (X::* function_to_bind)() )
+ {
+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
+ }
+ template < class X, class Y >
+ inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)())
+ {
+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
+ }
+ // Binding to const member functions.
+ template < class X, class Y >
+ FastDelegate0(const Y *pthis, DesiredRetType (X::* function_to_bind)() const)
+ {
+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);
+ }
+ template < class X, class Y >
+ inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)() const)
+ {
+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);
+ }
+ // Static functions. We convert them into a member function call.
+ // This constructor also provides implicit conversion
+ FastDelegate0(DesiredRetType (*function_to_bind)() )
+ {
+ Bind(function_to_bind);
+ }
+ // for efficiency, prevent creation of a temporary
+ void operator = (DesiredRetType (*function_to_bind)() )
+ {
+ Bind(function_to_bind);
+ }
+ inline void Bind(DesiredRetType (*function_to_bind)())
+ {
+ m_Closure.bindstaticfunc(this, &FastDelegate0::InvokeStaticFunction,
+ function_to_bind);
+ }
+ // Invoke the delegate
+ RetType operator() () const
+ {
+ return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))();
+ }
+ // Implicit conversion to "bool" using the safe_bool idiom
+private:
+ typedef struct SafeBoolStruct
+ {
+ int a_data_pointer_to_this_is_0_on_buggy_compilers;
+ StaticFunctionPtr m_nonzero;
+ } UselessTypedef;
+ typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
+public:
+ operator unspecified_bool_type() const
+ {
+ return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
+ }
+ // necessary to allow ==0 to work despite the safe_bool idiom
+ inline bool operator==(StaticFunctionPtr funcptr)
+ {
+ return m_Closure.IsEqualToStaticFuncPtr(funcptr);
+ }
+ inline bool operator!=(StaticFunctionPtr funcptr)
+ {
+ return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
+ }
+ inline bool operator ! () const
+ { // Is it bound to anything?
+ return !m_Closure;
+ }
+ inline bool IsEmpty() const
+ {
+ return !m_Closure;
+ }
+ void Clear() { m_Closure.Clear();}
+ // Conversion to and from the CUtlAbstractDelegate storage class
+ const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; }
+ void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); }
+
+private: // Invoker for static functions
+ RetType InvokeStaticFunction() const
+ {
+ return (*(m_Closure.GetStaticFunction()))();
+ }
+};
+
+//N=1
+template<class Param1, class RetType=detail::DefaultVoid>
+class FastDelegate1
+{
+private:
+ typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
+ typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1);
+ typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1);
+ typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1);
+ typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
+ ClosureType m_Closure;
+public:
+ // Typedefs to aid generic programming
+ typedef FastDelegate1 type;
+
+ // Construction and comparison functions
+ FastDelegate1() { Clear(); }
+ FastDelegate1(const FastDelegate1 &x)
+ {
+ m_Closure.CopyFrom(this, x.m_Closure);
+ }
+ void operator = (const FastDelegate1 &x)
+ {
+ m_Closure.CopyFrom(this, x.m_Closure);
+ }
+ bool operator ==(const FastDelegate1 &x) const
+ {
+ return m_Closure.IsEqual(x.m_Closure);
+ }
+ bool operator !=(const FastDelegate1 &x) const
+ {
+ return !m_Closure.IsEqual(x.m_Closure);
+ }
+ bool operator <(const FastDelegate1 &x) const
+ {
+ return m_Closure.IsLess(x.m_Closure);
+ }
+ bool operator >(const FastDelegate1 &x) const
+ {
+ return x.m_Closure.IsLess(m_Closure);
+ }
+ // Binding to non-const member functions
+ template < class X, class Y >
+ FastDelegate1(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) )
+ {
+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
+ }
+ template < class X, class Y >
+ inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1))
+ {
+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
+ }
+ // Binding to const member functions.
+ template < class X, class Y >
+ FastDelegate1(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const)
+ {
+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);
+ }
+ template < class X, class Y >
+ inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const)
+ {
+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);
+ }
+ // Static functions. We convert them into a member function call.
+ // This constructor also provides implicit conversion
+ FastDelegate1(DesiredRetType (*function_to_bind)(Param1 p1) )
+ {
+ Bind(function_to_bind);
+ }
+ // for efficiency, prevent creation of a temporary
+ void operator = (DesiredRetType (*function_to_bind)(Param1 p1) )
+ {
+ Bind(function_to_bind);
+ }
+ inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1))
+ {
+ m_Closure.bindstaticfunc(this, &FastDelegate1::InvokeStaticFunction,
+ function_to_bind);
+ }
+ // Invoke the delegate
+ RetType operator() (Param1 p1) const
+ {
+ return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1);
+ }
+ // Implicit conversion to "bool" using the safe_bool idiom
+private:
+ typedef struct SafeBoolStruct
+ {
+ int a_data_pointer_to_this_is_0_on_buggy_compilers;
+ StaticFunctionPtr m_nonzero;
+ } UselessTypedef;
+ typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
+public:
+ operator unspecified_bool_type() const
+ {
+ return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
+ }
+ // necessary to allow ==0 to work despite the safe_bool idiom
+ inline bool operator==(StaticFunctionPtr funcptr)
+ {
+ return m_Closure.IsEqualToStaticFuncPtr(funcptr);
+ }
+ inline bool operator!=(StaticFunctionPtr funcptr)
+ {
+ return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
+ }
+ inline bool operator ! () const
+ { // Is it bound to anything?
+ return !m_Closure;
+ }
+ inline bool IsEmpty() const
+ {
+ return !m_Closure;
+ }
+ void Clear() { m_Closure.Clear();}
+ // Conversion to and from the CUtlAbstractDelegate storage class
+ const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; }
+ void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); }
+
+private: // Invoker for static functions
+ RetType InvokeStaticFunction(Param1 p1) const
+ {
+ return (*(m_Closure.GetStaticFunction()))(p1);
+ }
+};
+
+//N=2
+template<class Param1, class Param2, class RetType=detail::DefaultVoid>
+class FastDelegate2
+{
+private:
+ typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
+ typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2);
+ typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2);
+ typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2);
+ typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
+ ClosureType m_Closure;
+public:
+ // Typedefs to aid generic programming
+ typedef FastDelegate2 type;
+
+ // Construction and comparison functions
+ FastDelegate2() { Clear(); }
+ FastDelegate2(const FastDelegate2 &x)
+ {
+ m_Closure.CopyFrom(this, x.m_Closure);
+ }
+ void operator = (const FastDelegate2 &x)
+ {
+ m_Closure.CopyFrom(this, x.m_Closure);
+ }
+ bool operator ==(const FastDelegate2 &x) const
+ {
+ return m_Closure.IsEqual(x.m_Closure);
+ }
+ bool operator !=(const FastDelegate2 &x) const
+ {
+ return !m_Closure.IsEqual(x.m_Closure);
+ }
+ bool operator <(const FastDelegate2 &x) const
+ {
+ return m_Closure.IsLess(x.m_Closure);
+ }
+ bool operator >(const FastDelegate2 &x) const
+ {
+ return x.m_Closure.IsLess(m_Closure);
+ }
+ // Binding to non-const member functions
+ template < class X, class Y >
+ FastDelegate2(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) )
+ {
+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
+ }
+ template < class X, class Y >
+ inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2))
+ {
+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
+ }
+ // Binding to const member functions.
+ template < class X, class Y >
+ FastDelegate2(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const)
+ {
+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);
+ }
+ template < class X, class Y >
+ inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const)
+ {
+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);
+ }
+ // Static functions. We convert them into a member function call.
+ // This constructor also provides implicit conversion
+ FastDelegate2(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) )
+ {
+ Bind(function_to_bind);
+ }
+ // for efficiency, prevent creation of a temporary
+ void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) )
+ {
+ Bind(function_to_bind);
+ }
+ inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2))
+ {
+ m_Closure.bindstaticfunc(this, &FastDelegate2::InvokeStaticFunction,
+ function_to_bind);
+ }
+ // Invoke the delegate
+ RetType operator() (Param1 p1, Param2 p2) const
+ {
+ return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2);
+ }
+ // Implicit conversion to "bool" using the safe_bool idiom
+private:
+ typedef struct SafeBoolStruct
+ {
+ int a_data_pointer_to_this_is_0_on_buggy_compilers;
+ StaticFunctionPtr m_nonzero;
+ } UselessTypedef;
+ typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
+public:
+ operator unspecified_bool_type() const
+ {
+ return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
+ }
+ // necessary to allow ==0 to work despite the safe_bool idiom
+ inline bool operator==(StaticFunctionPtr funcptr)
+ {
+ return m_Closure.IsEqualToStaticFuncPtr(funcptr);
+ }
+ inline bool operator!=(StaticFunctionPtr funcptr)
+ {
+ return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
+ }
+ inline bool operator ! () const
+ { // Is it bound to anything?
+ return !m_Closure;
+ }
+ inline bool IsEmpty() const
+ {
+ return !m_Closure;
+ }
+ void Clear() { m_Closure.Clear();}
+ // Conversion to and from the CUtlAbstractDelegate storage class
+ const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; }
+ void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); }
+
+private: // Invoker for static functions
+ RetType InvokeStaticFunction(Param1 p1, Param2 p2) const
+ {
+ return (*(m_Closure.GetStaticFunction()))(p1, p2);
+ }
+};
+
+//N=3
+template<class Param1, class Param2, class Param3, class RetType=detail::DefaultVoid>
+class FastDelegate3
+{
+private:
+ typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
+ typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3);
+ typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3);
+ typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3);
+ typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
+ ClosureType m_Closure;
+public:
+ // Typedefs to aid generic programming
+ typedef FastDelegate3 type;
+
+ // Construction and comparison functions
+ FastDelegate3() { Clear(); }
+ FastDelegate3(const FastDelegate3 &x)
+ {
+ m_Closure.CopyFrom(this, x.m_Closure);
+ }
+ void operator = (const FastDelegate3 &x)
+ {
+ m_Closure.CopyFrom(this, x.m_Closure);
+ }
+ bool operator ==(const FastDelegate3 &x) const
+ {
+ return m_Closure.IsEqual(x.m_Closure);
+ }
+ bool operator !=(const FastDelegate3 &x) const
+ {
+ return !m_Closure.IsEqual(x.m_Closure);
+ }
+ bool operator <(const FastDelegate3 &x) const
+ {
+ return m_Closure.IsLess(x.m_Closure);
+ }
+ bool operator >(const FastDelegate3 &x) const
+ {
+ return x.m_Closure.IsLess(m_Closure);
+ }
+ // Binding to non-const member functions
+ template < class X, class Y >
+ FastDelegate3(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) )
+ {
+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
+ }
+ template < class X, class Y >
+ inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3))
+ {
+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
+ }
+ // Binding to const member functions.
+ template < class X, class Y >
+ FastDelegate3(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const)
+ {
+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);
+ }
+ template < class X, class Y >
+ inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const)
+ {
+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);
+ }
+ // Static functions. We convert them into a member function call.
+ // This constructor also provides implicit conversion
+ FastDelegate3(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) )
+ {
+ Bind(function_to_bind);
+ }
+ // for efficiency, prevent creation of a temporary
+ void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) )
+ {
+ Bind(function_to_bind);
+ }
+ inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3))
+ {
+ m_Closure.bindstaticfunc(this, &FastDelegate3::InvokeStaticFunction,
+ function_to_bind);
+ }
+ // Invoke the delegate
+ RetType operator() (Param1 p1, Param2 p2, Param3 p3) const
+ {
+ return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3);
+ }
+ // Implicit conversion to "bool" using the safe_bool idiom
+private:
+ typedef struct SafeBoolStruct
+ {
+ int a_data_pointer_to_this_is_0_on_buggy_compilers;
+ StaticFunctionPtr m_nonzero;
+ } UselessTypedef;
+ typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
+public:
+ operator unspecified_bool_type() const
+ {
+ return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
+ }
+ // necessary to allow ==0 to work despite the safe_bool idiom
+ inline bool operator==(StaticFunctionPtr funcptr)
+ {
+ return m_Closure.IsEqualToStaticFuncPtr(funcptr);
+ }
+ inline bool operator!=(StaticFunctionPtr funcptr)
+ {
+ return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
+ }
+ inline bool operator ! () const
+ { // Is it bound to anything?
+ return !m_Closure;
+ }
+ inline bool IsEmpty() const
+ {
+ return !m_Closure;
+ }
+ void Clear() { m_Closure.Clear();}
+ // Conversion to and from the CUtlAbstractDelegate storage class
+ const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; }
+ void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); }
+
+private: // Invoker for static functions
+ RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3) const
+ {
+ return (*(m_Closure.GetStaticFunction()))(p1, p2, p3);
+ }
+};
+
+//N=4
+template<class Param1, class Param2, class Param3, class Param4, class RetType=detail::DefaultVoid>
+class FastDelegate4
+{
+private:
+ typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
+ typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
+ typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
+ typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
+ typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
+ ClosureType m_Closure;
+public:
+ // Typedefs to aid generic programming
+ typedef FastDelegate4 type;
+
+ // Construction and comparison functions
+ FastDelegate4() { Clear(); }
+ FastDelegate4(const FastDelegate4 &x)
+ {
+ m_Closure.CopyFrom(this, x.m_Closure);
+ }
+ void operator = (const FastDelegate4 &x)
+ {
+ m_Closure.CopyFrom(this, x.m_Closure);
+ }
+ bool operator ==(const FastDelegate4 &x) const
+ {
+ return m_Closure.IsEqual(x.m_Closure);
+ }
+ bool operator !=(const FastDelegate4 &x) const
+ {
+ return !m_Closure.IsEqual(x.m_Closure);
+ }
+ bool operator <(const FastDelegate4 &x) const
+ {
+ return m_Closure.IsLess(x.m_Closure);
+ }
+ bool operator >(const FastDelegate4 &x) const
+ {
+ return x.m_Closure.IsLess(m_Closure);
+ }
+ // Binding to non-const member functions
+ template < class X, class Y >
+ FastDelegate4(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) )
+ {
+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
+ }
+ template < class X, class Y >
+ inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4))
+ {
+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
+ }
+ // Binding to const member functions.
+ template < class X, class Y >
+ FastDelegate4(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const)
+ {
+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);
+ }
+ template < class X, class Y >
+ inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const)
+ {
+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);
+ }
+ // Static functions. We convert them into a member function call.
+ // This constructor also provides implicit conversion
+ FastDelegate4(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) )
+ {
+ Bind(function_to_bind);
+ }
+ // for efficiency, prevent creation of a temporary
+ void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) )
+ {
+ Bind(function_to_bind);
+ }
+ inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4))
+ {
+ m_Closure.bindstaticfunc(this, &FastDelegate4::InvokeStaticFunction,
+ function_to_bind);
+ }
+ // Invoke the delegate
+ RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4) const
+ {
+ return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4);
+ }
+ // Implicit conversion to "bool" using the safe_bool idiom
+private:
+ typedef struct SafeBoolStruct
+ {
+ int a_data_pointer_to_this_is_0_on_buggy_compilers;
+ StaticFunctionPtr m_nonzero;
+ } UselessTypedef;
+ typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
+public:
+ operator unspecified_bool_type() const
+ {
+ return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
+ }
+ // necessary to allow ==0 to work despite the safe_bool idiom
+ inline bool operator==(StaticFunctionPtr funcptr)
+ {
+ return m_Closure.IsEqualToStaticFuncPtr(funcptr);
+ }
+ inline bool operator!=(StaticFunctionPtr funcptr)
+ {
+ return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
+ }
+ inline bool operator ! () const
+ { // Is it bound to anything?
+ return !m_Closure;
+ }
+ inline bool IsEmpty() const
+ {
+ return !m_Closure;
+ }
+ void Clear() { m_Closure.Clear();}
+ // Conversion to and from the CUtlAbstractDelegate storage class
+ const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; }
+ void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); }
+
+private: // Invoker for static functions
+ RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const
+ {
+ return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4);
+ }
+};
+
+//N=5
+template<class Param1, class Param2, class Param3, class Param4, class Param5, class RetType=detail::DefaultVoid>
+class FastDelegate5
+{
+private:
+ typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
+ typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
+ typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
+ typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
+ typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
+ ClosureType m_Closure;
+public:
+ // Typedefs to aid generic programming
+ typedef FastDelegate5 type;
+
+ // Construction and comparison functions
+ FastDelegate5() { Clear(); }
+ FastDelegate5(const FastDelegate5 &x)
+ {
+ m_Closure.CopyFrom(this, x.m_Closure);
+ }
+ void operator = (const FastDelegate5 &x)
+ {
+ m_Closure.CopyFrom(this, x.m_Closure);
+ }
+ bool operator ==(const FastDelegate5 &x) const
+ {
+ return m_Closure.IsEqual(x.m_Closure);
+ }
+ bool operator !=(const FastDelegate5 &x) const
+ {
+ return !m_Closure.IsEqual(x.m_Closure);
+ }
+ bool operator <(const FastDelegate5 &x) const
+ {
+ return m_Closure.IsLess(x.m_Closure);
+ }
+ bool operator >(const FastDelegate5 &x) const
+ {
+ return x.m_Closure.IsLess(m_Closure);
+ }
+ // Binding to non-const member functions
+ template < class X, class Y >
+ FastDelegate5(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) )
+ {
+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
+ }
+ template < class X, class Y >
+ inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5))
+ {
+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
+ }
+ // Binding to const member functions.
+ template < class X, class Y >
+ FastDelegate5(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const)
+ {
+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);
+ }
+ template < class X, class Y >
+ inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const)
+ {
+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);
+ }
+ // Static functions. We convert them into a member function call.
+ // This constructor also provides implicit conversion
+ FastDelegate5(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) )
+ {
+ Bind(function_to_bind);
+ }
+ // for efficiency, prevent creation of a temporary
+ void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) )
+ {
+ Bind(function_to_bind);
+ }
+ inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5))
+ {
+ m_Closure.bindstaticfunc(this, &FastDelegate5::InvokeStaticFunction,
+ function_to_bind);
+ }
+ // Invoke the delegate
+ RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const
+ {
+ return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5);
+ }
+ // Implicit conversion to "bool" using the safe_bool idiom
+private:
+ typedef struct SafeBoolStruct
+ {
+ int a_data_pointer_to_this_is_0_on_buggy_compilers;
+ StaticFunctionPtr m_nonzero;
+ } UselessTypedef;
+ typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
+public:
+ operator unspecified_bool_type() const
+ {
+ return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
+ }
+ // necessary to allow ==0 to work despite the safe_bool idiom
+ inline bool operator==(StaticFunctionPtr funcptr)
+ {
+ return m_Closure.IsEqualToStaticFuncPtr(funcptr);
+ }
+ inline bool operator!=(StaticFunctionPtr funcptr)
+ {
+ return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
+ }
+ inline bool operator ! () const
+ { // Is it bound to anything?
+ return !m_Closure;
+ }
+ inline bool IsEmpty() const
+ {
+ return !m_Closure;
+ }
+ void Clear() { m_Closure.Clear();}
+ // Conversion to and from the CUtlAbstractDelegate storage class
+ const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; }
+ void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); }
+
+private: // Invoker for static functions
+ RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const
+ {
+ return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5);
+ }
+};
+
+//N=6
+template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType=detail::DefaultVoid>
+class FastDelegate6
+{
+private:
+ typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
+ typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
+ typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
+ typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
+ typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
+ ClosureType m_Closure;
+public:
+ // Typedefs to aid generic programming
+ typedef FastDelegate6 type;
+
+ // Construction and comparison functions
+ FastDelegate6() { Clear(); }
+ FastDelegate6(const FastDelegate6 &x)
+ {
+ m_Closure.CopyFrom(this, x.m_Closure);
+ }
+ void operator = (const FastDelegate6 &x)
+ {
+ m_Closure.CopyFrom(this, x.m_Closure);
+ }
+ bool operator ==(const FastDelegate6 &x) const
+ {
+ return m_Closure.IsEqual(x.m_Closure);
+ }
+ bool operator !=(const FastDelegate6 &x) const
+ {
+ return !m_Closure.IsEqual(x.m_Closure);
+ }
+ bool operator <(const FastDelegate6 &x) const
+ {
+ return m_Closure.IsLess(x.m_Closure);
+ }
+ bool operator >(const FastDelegate6 &x) const
+ {
+ return x.m_Closure.IsLess(m_Closure);
+ }
+ // Binding to non-const member functions
+ template < class X, class Y >
+ FastDelegate6(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) )
+ {
+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
+ }
+ template < class X, class Y >
+ inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6))
+ {
+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
+ }
+ // Binding to const member functions.
+ template < class X, class Y >
+ FastDelegate6(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const)
+ {
+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);
+ }
+ template < class X, class Y >
+ inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const)
+ {
+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);
+ }
+ // Static functions. We convert them into a member function call.
+ // This constructor also provides implicit conversion
+ FastDelegate6(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) )
+ {
+ Bind(function_to_bind);
+ }
+ // for efficiency, prevent creation of a temporary
+ void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) )
+ {
+ Bind(function_to_bind);
+ }
+ inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6))
+ {
+ m_Closure.bindstaticfunc(this, &FastDelegate6::InvokeStaticFunction,
+ function_to_bind);
+ }
+ // Invoke the delegate
+ RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const
+ {
+ return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6);
+ }
+ // Implicit conversion to "bool" using the safe_bool idiom
+private:
+ typedef struct SafeBoolStruct
+ {
+ int a_data_pointer_to_this_is_0_on_buggy_compilers;
+ StaticFunctionPtr m_nonzero;
+ } UselessTypedef;
+ typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
+public:
+ operator unspecified_bool_type() const
+ {
+ return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
+ }
+ // necessary to allow ==0 to work despite the safe_bool idiom
+ inline bool operator==(StaticFunctionPtr funcptr)
+ {
+ return m_Closure.IsEqualToStaticFuncPtr(funcptr);
+ }
+ inline bool operator!=(StaticFunctionPtr funcptr)
+ {
+ return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
+ }
+ inline bool operator ! () const
+ { // Is it bound to anything?
+ return !m_Closure;
+ }
+ inline bool IsEmpty() const
+ {
+ return !m_Closure;
+ }
+ void Clear() { m_Closure.Clear();}
+ // Conversion to and from the CUtlAbstractDelegate storage class
+ const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; }
+ void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); }
+
+private: // Invoker for static functions
+ RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const
+ {
+ return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6);
+ }
+};
+
+//N=7
+template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType=detail::DefaultVoid>
+class FastDelegate7
+{
+private:
+ typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
+ typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
+ typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
+ typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
+ typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
+ ClosureType m_Closure;
+public:
+ // Typedefs to aid generic programming
+ typedef FastDelegate7 type;
+
+ // Construction and comparison functions
+ FastDelegate7() { Clear(); }
+ FastDelegate7(const FastDelegate7 &x)
+ {
+ m_Closure.CopyFrom(this, x.m_Closure);
+ }
+ void operator = (const FastDelegate7 &x)
+ {
+ m_Closure.CopyFrom(this, x.m_Closure);
+ }
+ bool operator ==(const FastDelegate7 &x) const
+ {
+ return m_Closure.IsEqual(x.m_Closure);
+ }
+ bool operator !=(const FastDelegate7 &x) const
+ {
+ return !m_Closure.IsEqual(x.m_Closure);
+ }
+ bool operator <(const FastDelegate7 &x) const
+ {
+ return m_Closure.IsLess(x.m_Closure);
+ }
+ bool operator >(const FastDelegate7 &x) const
+ {
+ return x.m_Closure.IsLess(m_Closure);
+ }
+ // Binding to non-const member functions
+ template < class X, class Y >
+ FastDelegate7(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) )
+ {
+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
+ }
+ template < class X, class Y >
+ inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7))
+ {
+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
+ }
+ // Binding to const member functions.
+ template < class X, class Y >
+ FastDelegate7(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const)
+ {
+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);
+ }
+ template < class X, class Y >
+ inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const)
+ {
+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);
+ }
+ // Static functions. We convert them into a member function call.
+ // This constructor also provides implicit conversion
+ FastDelegate7(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) )
+ {
+ Bind(function_to_bind);
+ }
+ // for efficiency, prevent creation of a temporary
+ void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) )
+ {
+ Bind(function_to_bind);
+ }
+ inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7))
+ {
+ m_Closure.bindstaticfunc(this, &FastDelegate7::InvokeStaticFunction,
+ function_to_bind);
+ }
+ // Invoke the delegate
+ RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const
+ {
+ return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7);
+ }
+ // Implicit conversion to "bool" using the safe_bool idiom
+private:
+ typedef struct SafeBoolStruct
+ {
+ int a_data_pointer_to_this_is_0_on_buggy_compilers;
+ StaticFunctionPtr m_nonzero;
+ } UselessTypedef;
+ typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
+public:
+ operator unspecified_bool_type() const
+ {
+ return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
+ }
+ // necessary to allow ==0 to work despite the safe_bool idiom
+ inline bool operator==(StaticFunctionPtr funcptr)
+ {
+ return m_Closure.IsEqualToStaticFuncPtr(funcptr);
+ }
+ inline bool operator!=(StaticFunctionPtr funcptr)
+ {
+ return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
+ }
+ inline bool operator ! () const
+ { // Is it bound to anything?
+ return !m_Closure;
+ }
+ inline bool IsEmpty() const
+ {
+ return !m_Closure;
+ }
+ void Clear() { m_Closure.Clear();}
+ // Conversion to and from the CUtlAbstractDelegate storage class
+ const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; }
+ void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); }
+
+private: // Invoker for static functions
+ RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const
+ {
+ return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7);
+ }
+};
+
+//N=8
+template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType=detail::DefaultVoid>
+class FastDelegate8
+{
+private:
+ typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
+ typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
+ typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
+ typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
+ typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
+ ClosureType m_Closure;
+public:
+ // Typedefs to aid generic programming
+ typedef FastDelegate8 type;
+
+ // Construction and comparison functions
+ FastDelegate8() { Clear(); }
+ FastDelegate8(const FastDelegate8 &x)
+ {
+ m_Closure.CopyFrom(this, x.m_Closure);
+ }
+ void operator = (const FastDelegate8 &x)
+ {
+ m_Closure.CopyFrom(this, x.m_Closure);
+ }
+ bool operator ==(const FastDelegate8 &x) const
+ {
+ return m_Closure.IsEqual(x.m_Closure);
+ }
+ bool operator !=(const FastDelegate8 &x) const
+ {
+ return !m_Closure.IsEqual(x.m_Closure);
+ }
+ bool operator <(const FastDelegate8 &x) const
+ {
+ return m_Closure.IsLess(x.m_Closure);
+ }
+ bool operator >(const FastDelegate8 &x) const
+ {
+ return x.m_Closure.IsLess(m_Closure);
+ }
+ // Binding to non-const member functions
+ template < class X, class Y >
+ FastDelegate8(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) )
+ {
+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
+ }
+ template < class X, class Y >
+ inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8))
+ {
+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind);
+ }
+ // Binding to const member functions.
+ template < class X, class Y >
+ FastDelegate8(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const)
+ {
+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind);
+ }
+ template < class X, class Y >
+ inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const)
+ {
+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind);
+ }
+ // Static functions. We convert them into a member function call.
+ // This constructor also provides implicit conversion
+ FastDelegate8(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) )
+ {
+ Bind(function_to_bind);
+ }
+ // for efficiency, prevent creation of a temporary
+ void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) )
+ {
+ Bind(function_to_bind);
+ }
+ inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8))
+ {
+ m_Closure.bindstaticfunc(this, &FastDelegate8::InvokeStaticFunction,
+ function_to_bind);
+ }
+ // Invoke the delegate
+ RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const
+ {
+ return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8);
+ }
+ // Implicit conversion to "bool" using the safe_bool idiom
+private:
+ typedef struct SafeBoolStruct
+ {
+ int a_data_pointer_to_this_is_0_on_buggy_compilers;
+ StaticFunctionPtr m_nonzero;
+ } UselessTypedef;
+ typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
+public:
+ operator unspecified_bool_type() const
+ {
+ return IsEmpty()? 0: &SafeBoolStruct::m_nonzero;
+ }
+ // necessary to allow ==0 to work despite the safe_bool idiom
+ inline bool operator==(StaticFunctionPtr funcptr)
+ {
+ return m_Closure.IsEqualToStaticFuncPtr(funcptr);
+ }
+ inline bool operator!=(StaticFunctionPtr funcptr)
+ {
+ return !m_Closure.IsEqualToStaticFuncPtr(funcptr);
+ }
+ inline bool operator ! () const
+ { // Is it bound to anything?
+ return !m_Closure;
+ }
+ inline bool IsEmpty() const
+ {
+ return !m_Closure;
+ }
+ void Clear() { m_Closure.Clear();}
+ // Conversion to and from the CUtlAbstractDelegate storage class
+ const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; }
+ void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); }
+
+private: // Invoker for static functions
+ RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const
+ {
+ return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8);
+ }
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Fast Delegates, part 4:
+//
+// CUtlDelegate<> class (Original author: Jody Hagins)
+// Allows boost::function style syntax like:
+// CUtlDelegate< double (int, long) >
+// instead of:
+// FastDelegate2< int, long, double >
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
+
+// Declare CUtlDelegate as a class template. It will be specialized
+// later for all number of arguments.
+template <typename Signature>
+class CUtlDelegate;
+
+//N=0
+// Specialization to allow use of
+// CUtlDelegate< R ( ) >
+// instead of
+// FastDelegate0 < R >
+template<typename R>
+class CUtlDelegate< R ( ) >
+ // Inherit from FastDelegate0 so that it can be treated just like a FastDelegate0
+ : public FastDelegate0 < R >
+{
+public:
+ // Make using the base type a bit easier via typedef.
+ typedef FastDelegate0 < R > BaseType;
+
+ // Allow users access to the specific type of this delegate.
+ typedef CUtlDelegate SelfType;
+
+ // Mimic the base class constructors.
+ CUtlDelegate() : BaseType() { }
+
+ template < class X, class Y >
+ CUtlDelegate(Y * pthis, R (X::* function_to_bind)( ))
+ : BaseType(pthis, function_to_bind)
+ { }
+
+ template < class X, class Y >
+ CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( ) const)
+ : BaseType(pthis, function_to_bind)
+ { }
+
+ CUtlDelegate(R (*function_to_bind)( ))
+ : BaseType(function_to_bind)
+ { }
+
+ void operator = (const BaseType &x)
+ {
+ *static_cast<BaseType*>(this) = x;
+ }
+};
+
+//N=1
+// Specialization to allow use of
+// CUtlDelegate< R ( Param1 ) >
+// instead of
+// FastDelegate1 < Param1, R >
+template<typename R, class Param1>
+class CUtlDelegate< R ( Param1 ) >
+ // Inherit from FastDelegate1 so that it can be treated just like a FastDelegate1
+ : public FastDelegate1 < Param1, R >
+{
+ public:
+ // Make using the base type a bit easier via typedef.
+ typedef FastDelegate1 < Param1, R > BaseType;
+
+ // Allow users access to the specific type of this delegate.
+ typedef CUtlDelegate SelfType;
+
+ // Mimic the base class constructors.
+ CUtlDelegate() : BaseType() { }
+
+ template < class X, class Y >
+ CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1 ))
+ : BaseType(pthis, function_to_bind)
+ { }
+
+ template < class X, class Y >
+ CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1 ) const)
+ : BaseType(pthis, function_to_bind)
+ { }
+
+ CUtlDelegate(R (*function_to_bind)( Param1 p1 ))
+ : BaseType(function_to_bind)
+ { }
+
+ void operator = (const BaseType &x)
+ {
+ *static_cast<BaseType*>(this) = x;
+ }
+};
+
+//N=2
+// Specialization to allow use of
+// CUtlDelegate< R ( Param1, Param2 ) >
+// instead of
+// FastDelegate2 < Param1, Param2, R >
+template<typename R, class Param1, class Param2>
+class CUtlDelegate< R ( Param1, Param2 ) >
+ // Inherit from FastDelegate2 so that it can be treated just like a FastDelegate2
+ : public FastDelegate2 < Param1, Param2, R >
+{
+ public:
+ // Make using the base type a bit easier via typedef.
+ typedef FastDelegate2 < Param1, Param2, R > BaseType;
+
+ // Allow users access to the specific type of this delegate.
+ typedef CUtlDelegate SelfType;
+
+ // Mimic the base class constructors.
+ CUtlDelegate() : BaseType() { }
+
+ template < class X, class Y >
+ CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2 ))
+ : BaseType(pthis, function_to_bind)
+ { }
+
+ template < class X, class Y >
+ CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2 ) const)
+ : BaseType(pthis, function_to_bind)
+ { }
+
+ CUtlDelegate(R (*function_to_bind)( Param1 p1, Param2 p2 ))
+ : BaseType(function_to_bind)
+ { }
+
+ void operator = (const BaseType &x)
+ {
+ *static_cast<BaseType*>(this) = x;
+ }
+};
+
+//N=3
+// Specialization to allow use of
+// CUtlDelegate< R ( Param1, Param2, Param3 ) >
+// instead of
+// FastDelegate3 < Param1, Param2, Param3, R >
+template<typename R, class Param1, class Param2, class Param3>
+class CUtlDelegate< R ( Param1, Param2, Param3 ) >
+ // Inherit from FastDelegate3 so that it can be treated just like a FastDelegate3
+ : public FastDelegate3 < Param1, Param2, Param3, R >
+{
+public:
+ // Make using the base type a bit easier via typedef.
+ typedef FastDelegate3 < Param1, Param2, Param3, R > BaseType;
+
+ // Allow users access to the specific type of this delegate.
+ typedef CUtlDelegate SelfType;
+
+ // Mimic the base class constructors.
+ CUtlDelegate() : BaseType() { }
+
+ template < class X, class Y >
+ CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ))
+ : BaseType(pthis, function_to_bind)
+ { }
+
+ template < class X, class Y >
+ CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ) const)
+ : BaseType(pthis, function_to_bind)
+ { }
+
+ CUtlDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ))
+ : BaseType(function_to_bind)
+ { }
+
+ void operator = (const BaseType &x)
+ {
+ *static_cast<BaseType*>(this) = x;
+ }
+};
+
+//N=4
+// Specialization to allow use of
+// CUtlDelegate< R ( Param1, Param2, Param3, Param4 ) >
+// instead of
+// FastDelegate4 < Param1, Param2, Param3, Param4, R >
+template<typename R, class Param1, class Param2, class Param3, class Param4>
+class CUtlDelegate< R ( Param1, Param2, Param3, Param4 ) >
+ // Inherit from FastDelegate4 so that it can be treated just like a FastDelegate4
+ : public FastDelegate4 < Param1, Param2, Param3, Param4, R >
+{
+public:
+ // Make using the base type a bit easier via typedef.
+ typedef FastDelegate4 < Param1, Param2, Param3, Param4, R > BaseType;
+
+ // Allow users access to the specific type of this delegate.
+ typedef CUtlDelegate SelfType;
+
+ // Mimic the base class constructors.
+ CUtlDelegate() : BaseType() { }
+
+ template < class X, class Y >
+ CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ))
+ : BaseType(pthis, function_to_bind)
+ { }
+
+ template < class X, class Y >
+ CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) const)
+ : BaseType(pthis, function_to_bind)
+ { }
+
+ CUtlDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ))
+ : BaseType(function_to_bind)
+ { }
+
+ void operator = (const BaseType &x)
+ {
+ *static_cast<BaseType*>(this) = x;
+ }
+};
+
+//N=5
+// Specialization to allow use of
+// CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) >
+// instead of
+// FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R >
+template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5>
+class CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) >
+ // Inherit from FastDelegate5 so that it can be treated just like a FastDelegate5
+ : public FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R >
+{
+public:
+ // Make using the base type a bit easier via typedef.
+ typedef FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > BaseType;
+
+ // Allow users access to the specific type of this delegate.
+ typedef CUtlDelegate SelfType;
+
+ // Mimic the base class constructors.
+ CUtlDelegate() : BaseType() { }
+
+ template < class X, class Y >
+ CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ))
+ : BaseType(pthis, function_to_bind)
+ { }
+
+ template < class X, class Y >
+ CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) const)
+ : BaseType(pthis, function_to_bind)
+ { }
+
+ CUtlDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ))
+ : BaseType(function_to_bind)
+ { }
+
+ void operator = (const BaseType &x)
+ {
+ *static_cast<BaseType*>(this) = x;
+ }
+};
+
+//N=6
+// Specialization to allow use of
+// CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) >
+// instead of
+// FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R >
+template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6>
+class CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) >
+ // Inherit from FastDelegate6 so that it can be treated just like a FastDelegate6
+ : public FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R >
+{
+public:
+ // Make using the base type a bit easier via typedef.
+ typedef FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > BaseType;
+
+ // Allow users access to the specific type of this delegate.
+ typedef CUtlDelegate SelfType;
+
+ // Mimic the base class constructors.
+ CUtlDelegate() : BaseType() { }
+
+ template < class X, class Y >
+ CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ))
+ : BaseType(pthis, function_to_bind)
+ { }
+
+ template < class X, class Y >
+ CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) const)
+ : BaseType(pthis, function_to_bind)
+ { }
+
+ CUtlDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ))
+ : BaseType(function_to_bind)
+ { }
+
+ void operator = (const BaseType &x)
+ {
+ *static_cast<BaseType*>(this) = x;
+ }
+};
+
+//N=7
+// Specialization to allow use of
+// CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >
+// instead of
+// FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R >
+template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7>
+class CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >
+ // Inherit from FastDelegate7 so that it can be treated just like a FastDelegate7
+ : public FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R >
+{
+public:
+ // Make using the base type a bit easier via typedef.
+ typedef FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > BaseType;
+
+ // Allow users access to the specific type of this delegate.
+ typedef CUtlDelegate SelfType;
+
+ // Mimic the base class constructors.
+ CUtlDelegate() : BaseType() { }
+
+ template < class X, class Y >
+ CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ))
+ : BaseType(pthis, function_to_bind)
+ { }
+
+ template < class X, class Y >
+ CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) const)
+ : BaseType(pthis, function_to_bind)
+ { }
+
+ CUtlDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ))
+ : BaseType(function_to_bind)
+ { }
+
+ void operator = (const BaseType &x)
+ {
+ *static_cast<BaseType*>(this) = x;
+ }
+};
+
+//N=8
+// Specialization to allow use of
+// CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >
+// instead of
+// FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R >
+template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8>
+class CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >
+ // Inherit from FastDelegate8 so that it can be treated just like a FastDelegate8
+ : public FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R >
+{
+public:
+ // Make using the base type a bit easier via typedef.
+ typedef FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > BaseType;
+
+ // Allow users access to the specific type of this delegate.
+ typedef CUtlDelegate SelfType;
+
+ // Mimic the base class constructors.
+ CUtlDelegate() : BaseType() { }
+
+ template < class X, class Y >
+ CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ))
+ : BaseType(pthis, function_to_bind)
+ { }
+
+ template < class X, class Y >
+ CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) const)
+ : BaseType(pthis, function_to_bind)
+ { }
+
+ CUtlDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ))
+ : BaseType(function_to_bind)
+ { }
+
+ void operator = (const BaseType &x)
+ {
+ *static_cast<BaseType*>(this) = x;
+ }
+};
+
+
+#endif //FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
+
+////////////////////////////////////////////////////////////////////////////////
+// Fast Delegates, part 5:
+//
+// UtlMakeDelegate() helper function
+//
+// UtlMakeDelegate(&x, &X::func) returns a fastdelegate of the type
+// necessary for calling x.func() with the correct number of arguments.
+// This makes it possible to eliminate many typedefs from user code.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// Also declare overloads of a UtlMakeDelegate() global function to
+// reduce the need for typedefs.
+// We need seperate overloads for const and non-const member functions.
+// Also, because of the weird rule about the class of derived member function pointers,
+// implicit downcasts may need to be applied later to the 'this' pointer.
+// That's why two classes (X and Y) appear in the definitions. Y must be implicitly
+// castable to X.
+
+// Workaround for VC6. VC6 needs void return types converted into DefaultVoid.
+// GCC 3.2 and later won't compile this unless it's preceded by 'typename',
+// but VC6 doesn't allow 'typename' in this context.
+// So, I have to use a macro.
+
+#ifdef FASTDLGT_VC6
+#define FASTDLGT_RETTYPE detail::VoidToDefaultVoid<RetType>::type
+#else
+#define FASTDLGT_RETTYPE RetType
+#endif
+
+
+//N=0
+template <class X, class Y, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( ) > UtlMakeDelegate(Y* x, RetType (X::*func)())
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( ) >(x, func);
+}
+
+template <class X, class Y, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( ) > UtlMakeDelegate(Y* x, RetType (X::*func)() const)
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( ) >(x, func);
+}
+
+template < class RetType >
+CUtlDelegate< FASTDLGT_RETTYPE ( ) > UtlMakeDelegate( RetType (*func)())
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( ) >( func );
+}
+
+//N=1
+template <class X, class Y, class Param1, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1))
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1 ) >(x, func);
+}
+
+template <class X, class Y, class Param1, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1) const)
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1 ) >(x, func);
+}
+
+template < class Param1, class RetType >
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1 ) > UtlMakeDelegate( RetType (*func)(Param1 p1))
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1 ) >( func );
+}
+
+
+//N=2
+template <class X, class Y, class Param1, class Param2, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2))
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2 ) >(x, func);
+}
+
+template <class X, class Y, class Param1, class Param2, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2) const)
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2 ) >(x, func);
+}
+
+template <class Param1, class Param2, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2 ) > UtlMakeDelegate( RetType (*func)(Param1 p1, Param2 p2))
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2 ) >(func);
+}
+
+//N=3
+template <class X, class Y, class Param1, class Param2, class Param3, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3))
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3 ) >(x, func);
+}
+
+template <class X, class Y, class Param1, class Param2, class Param3, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3) const)
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3 ) >(x, func);
+}
+
+template <class Param1, class Param2, class Param3, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3 ) > UtlMakeDelegate( RetType (*func)(Param1 p1, Param2 p2, Param3 p3))
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3 ) >(func);
+}
+
+//N=4
+template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4))
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4 ) >(x, func);
+}
+
+template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const)
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4 ) >(x, func);
+}
+
+template <class Param1, class Param2, class Param3, class Param4, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4 ) > UtlMakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4))
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4 ) >(func);
+}
+
+//N=5
+template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5))
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5 ) >(x, func);
+}
+
+template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const)
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5 ) >(x, func);
+}
+
+template <class Param1, class Param2, class Param3, class Param4, class Param5, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5 ) > UtlMakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5))
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5 ) >(func);
+}
+
+//N=6
+template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6))
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6 ) >(x, func);
+}
+
+template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const)
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6 ) >(x, func);
+}
+
+template <class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6 ) > UtlMakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6))
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6 ) >(func);
+}
+
+//N=7
+template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7))
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >(x, func);
+}
+
+template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const)
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >(x, func);
+}
+
+template <class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > UtlMakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7))
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >(func);
+}
+
+//N=8
+template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8))
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >(x, func);
+}
+
+template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const)
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >(x, func);
+}
+
+template <class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType>
+CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > UtlMakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8))
+{
+ return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >(func);
+}
+
+
+// clean up after ourselves...
+#undef FASTDLGT_RETTYPE
+
+#endif // !defined(UTLDELEGATEIMPL_H)
+
diff --git a/mp/src/public/tier1/utldict.h b/mp/src/public/tier1/utldict.h
index b4268e90..cb0455a5 100644
--- a/mp/src/public/tier1/utldict.h
+++ b/mp/src/public/tier1/utldict.h
@@ -1,358 +1,358 @@
-//========= Copyright 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;
-
- // Number of allocated slots
- I MaxElement() 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;
- bool HasElement( 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();
-}
-
-//-----------------------------------------------------------------------------
-// Number of allocated slots
-//-----------------------------------------------------------------------------
-template <class T, class I>
-inline I CUtlDict<T, I>::MaxElement() const
-{
- return m_Elements.MaxElement();
-}
-
-//-----------------------------------------------------------------------------
-// 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() )
- {
- free( (void *)m_Elements.Key( index ) );
- 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() )
- {
- free( (void *)m_Elements.Key( index ) );
- 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();
-}
-
-//-----------------------------------------------------------------------------
-// returns true if we already have this node
-//-----------------------------------------------------------------------------
-template <class T, class I>
-bool CUtlDict<T, I>::HasElement( const char *pName ) const
-{
- if ( pName )
- return m_Elements.IsValidIndex( m_Elements.Find( pName ) );
- else
- return false;
-}
-
-
-//-----------------------------------------------------------------------------
-// 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
+//========= Copyright 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;
+
+ // Number of allocated slots
+ I MaxElement() 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;
+ bool HasElement( 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();
+}
+
+//-----------------------------------------------------------------------------
+// Number of allocated slots
+//-----------------------------------------------------------------------------
+template <class T, class I>
+inline I CUtlDict<T, I>::MaxElement() const
+{
+ return m_Elements.MaxElement();
+}
+
+//-----------------------------------------------------------------------------
+// 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() )
+ {
+ free( (void *)m_Elements.Key( index ) );
+ 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() )
+ {
+ free( (void *)m_Elements.Key( index ) );
+ 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();
+}
+
+//-----------------------------------------------------------------------------
+// returns true if we already have this node
+//-----------------------------------------------------------------------------
+template <class T, class I>
+bool CUtlDict<T, I>::HasElement( const char *pName ) const
+{
+ if ( pName )
+ return m_Elements.IsValidIndex( m_Elements.Find( pName ) );
+ else
+ return false;
+}
+
+
+//-----------------------------------------------------------------------------
+// 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/mp/src/public/tier1/utlenvelope.h b/mp/src/public/tier1/utlenvelope.h
index 8c8c4f79..3de254a3 100644
--- a/mp/src/public/tier1/utlenvelope.h
+++ b/mp/src/public/tier1/utlenvelope.h
@@ -1,241 +1,241 @@
-//========= Copyright 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
+//========= Copyright 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/mp/src/public/tier1/utlfixedmemory.h b/mp/src/public/tier1/utlfixedmemory.h
index 3d92d679..6ff8c19b 100644
--- a/mp/src/public/tier1/utlfixedmemory.h
+++ b/mp/src/public/tier1/utlfixedmemory.h
@@ -1,354 +1,354 @@
-//========= Copyright 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;
- intp 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();
- }
- intp GetIndex( const Iterator_t &it ) const
- {
- Assert( IsValidIterator( it ) );
- if ( !IsValidIterator( it ) )
- return InvalidIndex();
-
- return ( intp )( HeaderToBlock( it.m_pBlockHeader ) + it.m_nIndex );
- }
- bool IsIdxAfter( intp 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, INVALID_INDEX ); }
-
- // element access
- T& operator[]( intp i );
- const T& operator[]( intp i ) const;
- T& Element( intp i );
- const T& Element( intp i ) const;
-
- // Can we use this index?
- bool IsIdxValid( intp i ) const;
-
- // Specify the invalid ('null') index that we'll only return on failure
- static const intp INVALID_INDEX = 0; // For use with COMPILE_TIME_ASSERT
- static intp 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( intp 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;
- intp 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[]( intp i )
-{
- Assert( IsIdxValid(i) );
- return *( T* )i;
-}
-
-template< class T >
-inline const T& CUtlFixedMemory<T>::operator[]( intp i ) const
-{
- Assert( IsIdxValid(i) );
- return *( T* )i;
-}
-
-template< class T >
-inline T& CUtlFixedMemory<T>::Element( intp i )
-{
- Assert( IsIdxValid(i) );
- return *( T* )i;
-}
-
-template< class T >
-inline const T& CUtlFixedMemory<T>::Element( intp 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( intp 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
+//========= Copyright 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;
+ intp 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();
+ }
+ intp GetIndex( const Iterator_t &it ) const
+ {
+ Assert( IsValidIterator( it ) );
+ if ( !IsValidIterator( it ) )
+ return InvalidIndex();
+
+ return ( intp )( HeaderToBlock( it.m_pBlockHeader ) + it.m_nIndex );
+ }
+ bool IsIdxAfter( intp 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, INVALID_INDEX ); }
+
+ // element access
+ T& operator[]( intp i );
+ const T& operator[]( intp i ) const;
+ T& Element( intp i );
+ const T& Element( intp i ) const;
+
+ // Can we use this index?
+ bool IsIdxValid( intp i ) const;
+
+ // Specify the invalid ('null') index that we'll only return on failure
+ static const intp INVALID_INDEX = 0; // For use with COMPILE_TIME_ASSERT
+ static intp 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( intp 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;
+ intp 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[]( intp i )
+{
+ Assert( IsIdxValid(i) );
+ return *( T* )i;
+}
+
+template< class T >
+inline const T& CUtlFixedMemory<T>::operator[]( intp i ) const
+{
+ Assert( IsIdxValid(i) );
+ return *( T* )i;
+}
+
+template< class T >
+inline T& CUtlFixedMemory<T>::Element( intp i )
+{
+ Assert( IsIdxValid(i) );
+ return *( T* )i;
+}
+
+template< class T >
+inline const T& CUtlFixedMemory<T>::Element( intp 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( intp 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/mp/src/public/tier1/utlflags.h b/mp/src/public/tier1/utlflags.h
index f18f1e15..e225b438 100644
--- a/mp/src/public/tier1/utlflags.h
+++ b/mp/src/public/tier1/utlflags.h
@@ -1,124 +1,124 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Simple class to make it easier to deal with flags
-//
-//=============================================================================
-
-#ifndef UTLFLAGS_H
-#define UTLFLAGS_H
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include "tier0/dbg.h"
-
-
-//-----------------------------------------------------------------------------
-// Simple class to make it easier to deal with flags
-//-----------------------------------------------------------------------------
-template< class T >
-class CUtlFlags
-{
-public:
- CUtlFlags( int nInitialFlags = 0 );
-
- // Flag setting
- void SetFlag( int nFlagMask );
- void SetFlag( int nFlagMask, bool bEnable );
-
- // Flag clearing
- void ClearFlag( int nFlagMask );
- void ClearAllFlags();
- bool IsFlagSet( int nFlagMask ) const;
-
- // Is any flag set?
- bool IsAnyFlagSet() const;
-
-private:
- T m_nFlags;
-};
-
-
-//-----------------------------------------------------------------------------
-// Constructor
-//-----------------------------------------------------------------------------
-template< class T >
-CUtlFlags<T>::CUtlFlags( int nInitialFlags )
-{
- // Makes sure we didn't truncate
- Assert( nInitialFlags == (T)nInitialFlags );
-
- m_nFlags = (T)nInitialFlags;
-}
-
-
-//-----------------------------------------------------------------------------
-// Set flags
-//-----------------------------------------------------------------------------
-template< class T >
-void CUtlFlags<T>::SetFlag( int nFlagMask )
-{
- // Makes sure we didn't truncate
- Assert( nFlagMask == (T)nFlagMask );
-
- m_nFlags |= (T)nFlagMask;
-}
-
-template< class T >
-void CUtlFlags<T>::SetFlag( int nFlagMask, bool bEnable )
-{
- // Makes sure we didn't truncate
- Assert( nFlagMask == (T)nFlagMask );
-
- if ( bEnable )
- {
- m_nFlags |= (T)nFlagMask;
- }
- else
- {
- m_nFlags &= ~((T)nFlagMask);
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Clear flags
-//-----------------------------------------------------------------------------
-template< class T >
-void CUtlFlags<T>::ClearFlag( int nFlagMask )
-{
- // Makes sure we didn't truncate
- Assert( nFlagMask == (T)nFlagMask );
- m_nFlags &= ~((T)nFlagMask);
-}
-
-template< class T >
-void CUtlFlags<T>::ClearAllFlags()
-{
- m_nFlags = 0;
-}
-
-
-//-----------------------------------------------------------------------------
-// Is a flag set?
-//-----------------------------------------------------------------------------
-template< class T >
-bool CUtlFlags<T>::IsFlagSet( int nFlagMask ) const
-{
- // Makes sure we didn't truncate
- Assert( nFlagMask == (T)nFlagMask );
- return ( m_nFlags & nFlagMask ) != 0;
-}
-
-
-//-----------------------------------------------------------------------------
-// Is any flag set?
-//-----------------------------------------------------------------------------
-template< class T >
-bool CUtlFlags<T>::IsAnyFlagSet() const
-{
- return m_nFlags != 0;
-}
-
-
-#endif // UTLFLAGS_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Simple class to make it easier to deal with flags
+//
+//=============================================================================
+
+#ifndef UTLFLAGS_H
+#define UTLFLAGS_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/dbg.h"
+
+
+//-----------------------------------------------------------------------------
+// Simple class to make it easier to deal with flags
+//-----------------------------------------------------------------------------
+template< class T >
+class CUtlFlags
+{
+public:
+ CUtlFlags( int nInitialFlags = 0 );
+
+ // Flag setting
+ void SetFlag( int nFlagMask );
+ void SetFlag( int nFlagMask, bool bEnable );
+
+ // Flag clearing
+ void ClearFlag( int nFlagMask );
+ void ClearAllFlags();
+ bool IsFlagSet( int nFlagMask ) const;
+
+ // Is any flag set?
+ bool IsAnyFlagSet() const;
+
+private:
+ T m_nFlags;
+};
+
+
+//-----------------------------------------------------------------------------
+// Constructor
+//-----------------------------------------------------------------------------
+template< class T >
+CUtlFlags<T>::CUtlFlags( int nInitialFlags )
+{
+ // Makes sure we didn't truncate
+ Assert( nInitialFlags == (T)nInitialFlags );
+
+ m_nFlags = (T)nInitialFlags;
+}
+
+
+//-----------------------------------------------------------------------------
+// Set flags
+//-----------------------------------------------------------------------------
+template< class T >
+void CUtlFlags<T>::SetFlag( int nFlagMask )
+{
+ // Makes sure we didn't truncate
+ Assert( nFlagMask == (T)nFlagMask );
+
+ m_nFlags |= (T)nFlagMask;
+}
+
+template< class T >
+void CUtlFlags<T>::SetFlag( int nFlagMask, bool bEnable )
+{
+ // Makes sure we didn't truncate
+ Assert( nFlagMask == (T)nFlagMask );
+
+ if ( bEnable )
+ {
+ m_nFlags |= (T)nFlagMask;
+ }
+ else
+ {
+ m_nFlags &= ~((T)nFlagMask);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Clear flags
+//-----------------------------------------------------------------------------
+template< class T >
+void CUtlFlags<T>::ClearFlag( int nFlagMask )
+{
+ // Makes sure we didn't truncate
+ Assert( nFlagMask == (T)nFlagMask );
+ m_nFlags &= ~((T)nFlagMask);
+}
+
+template< class T >
+void CUtlFlags<T>::ClearAllFlags()
+{
+ m_nFlags = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Is a flag set?
+//-----------------------------------------------------------------------------
+template< class T >
+bool CUtlFlags<T>::IsFlagSet( int nFlagMask ) const
+{
+ // Makes sure we didn't truncate
+ Assert( nFlagMask == (T)nFlagMask );
+ return ( m_nFlags & nFlagMask ) != 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Is any flag set?
+//-----------------------------------------------------------------------------
+template< class T >
+bool CUtlFlags<T>::IsAnyFlagSet() const
+{
+ return m_nFlags != 0;
+}
+
+
+#endif // UTLFLAGS_H
diff --git a/mp/src/public/tier1/utlhandletable.h b/mp/src/public/tier1/utlhandletable.h
index 5d9c46fc..22f54357 100644
--- a/mp/src/public/tier1/utlhandletable.h
+++ b/mp/src/public/tier1/utlhandletable.h
@@ -1,586 +1,586 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-//=============================================================================
-
-#ifndef UTLHANDLETABLE_H
-#define UTLHANDLETABLE_H
-
-#ifdef _WIN32
-#pragma once
-#endif
-
-
-#include "tier1/utlvector.h"
-#include "tier1/utlqueue.h"
-
-
-//-----------------------------------------------------------------------------
-// Handles are 32 bits. Invalid handles are all 1s
-//-----------------------------------------------------------------------------
-typedef unsigned int UtlHandle_t;
-#define UTLHANDLE_INVALID ((UtlHandle_t)~0)
-
-
-//-----------------------------------------------------------------------------
-// Purpose: This is a table used to allocate handles
-// HandleBits specifies the max # of simultaneously allocated handles.
-// An extra bit is used for the validity state
-// The rest of the 32 bits are used for a serial number
-//-----------------------------------------------------------------------------
-template< class T, int HandleBits >
-class CUtlHandleTable
-{
-public:
- CUtlHandleTable();
-
- // Allocate, deallocate handles
- UtlHandle_t AddHandle();
- void RemoveHandle( UtlHandle_t h );
-
- // Set/get handle values
- void SetHandle( UtlHandle_t h, T *pData );
- T *GetHandle( UtlHandle_t h ) const;
- T *GetHandle( UtlHandle_t h, bool checkValidity ) const;
-
- // Is a handle valid?
- bool IsHandleValid( UtlHandle_t h ) const;
-
- // Iterate over handles; they may not be valid
- unsigned int GetValidHandleCount() const;
- unsigned int GetHandleCount() const;
- UtlHandle_t GetHandleFromIndex( int i ) const;
- int GetIndexFromHandle( UtlHandle_t h ) const;
-
- void MarkHandleInvalid( UtlHandle_t h );
- void MarkHandleValid( UtlHandle_t h );
-
-private:
- struct HandleType_t
- {
- HandleType_t( unsigned int i, unsigned int s ) : nIndex( i ), nSerial( s )
- {
- Assert( i < ( 1 << HandleBits ) );
- Assert( s < ( 1 << ( 31 - HandleBits ) ) );
- }
- unsigned int nIndex : HandleBits;
- unsigned int nSerial : 31 - HandleBits;
- };
-
- struct EntryType_t
- {
- EntryType_t() : m_nSerial( 0 ), nInvalid( 0 ), m_pData( 0 ) {}
- unsigned int m_nSerial : 31;
- unsigned int nInvalid : 1;
- T *m_pData;
- };
-
- static unsigned int GetSerialNumber( UtlHandle_t handle );
- static unsigned int GetListIndex( UtlHandle_t handle );
- static UtlHandle_t CreateHandle( unsigned int nSerial, unsigned int nIndex );
- const EntryType_t *GetEntry( UtlHandle_t handle, bool checkValidity ) const;
-
- unsigned int m_nValidHandles;
- CUtlVector< EntryType_t > m_list;
- CUtlQueue< int > m_unused;
-};
-
-
-//-----------------------------------------------------------------------------
-// Constructor, destructor
-//-----------------------------------------------------------------------------
-template< class T, int HandleBits >
-CUtlHandleTable<T, HandleBits>::CUtlHandleTable() : m_nValidHandles( 0 )
-{
-}
-
-
-//-----------------------------------------------------------------------------
-// Allocate, deallocate handles
-//-----------------------------------------------------------------------------
-template< class T, int HandleBits >
-UtlHandle_t CUtlHandleTable<T, HandleBits>::AddHandle()
-{
- unsigned int nIndex = ( m_unused.Count() > 0 ) ? m_unused.RemoveAtHead() : m_list.AddToTail();
-
- EntryType_t &entry = m_list[ nIndex ];
- entry.nInvalid = 0;
- entry.m_pData = NULL;
-
- ++m_nValidHandles;
-
- return CreateHandle( entry.m_nSerial, nIndex );
-}
-
-template< class T, int HandleBits >
-void CUtlHandleTable<T, HandleBits>::RemoveHandle( UtlHandle_t handle )
-{
- unsigned int nIndex = GetListIndex( handle );
- Assert( nIndex < ( unsigned int )m_list.Count() );
- if ( nIndex >= ( unsigned int )m_list.Count() )
- return;
-
- EntryType_t &entry = m_list[ nIndex ];
- ++entry.m_nSerial; // mark old serial# invalid
- if ( !entry.nInvalid )
- {
- entry.nInvalid = 1;
- --m_nValidHandles;
- }
- entry.m_pData = NULL;
-
-
- // If a handle has been used this many times, then we need to take it out of service, otherwise if the
- // serial # wraps around we'll possibly revalidate old handles and they'll start to point at the wrong objects. Unlikely, but possible.
- bool bStopUsing = ( entry.m_nSerial >= ( (1 << ( 31 - HandleBits ) ) - 1 ) );
- if ( !bStopUsing )
- {
- m_unused.Insert( nIndex );
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Set/get handle values
-//-----------------------------------------------------------------------------
-template< class T, int HandleBits >
-void CUtlHandleTable<T, HandleBits>::SetHandle( UtlHandle_t handle, T *pData )
-{
- EntryType_t *entry = const_cast< EntryType_t* >( GetEntry( handle, false ) );
- Assert( entry );
- if ( entry == NULL )
- return;
-
- // Validate the handle
- if ( entry->nInvalid )
- {
- ++m_nValidHandles;
- entry->nInvalid = 0;
- }
- entry->m_pData = pData;
-}
-
-template< class T, int HandleBits >
-T *CUtlHandleTable<T, HandleBits>::GetHandle( UtlHandle_t handle ) const
-{
- const EntryType_t *entry = GetEntry( handle, true );
- return entry ? entry->m_pData : NULL;
-}
-
-template< class T, int HandleBits >
-T *CUtlHandleTable<T, HandleBits>::GetHandle( UtlHandle_t handle, bool checkValidity ) const
-{
- const EntryType_t *entry = GetEntry( handle, checkValidity );
- return entry ? entry->m_pData : NULL;
-}
-
-
-//-----------------------------------------------------------------------------
-// Is a handle valid?
-//-----------------------------------------------------------------------------
-template< class T, int HandleBits >
-bool CUtlHandleTable<T, HandleBits>::IsHandleValid( UtlHandle_t handle ) const
-{
- if ( handle == UTLHANDLE_INVALID )
- return false;
-
- unsigned int nIndex = GetListIndex( handle );
- AssertOnce( nIndex < ( unsigned int )m_list.Count() );
- if ( nIndex >= ( unsigned int )m_list.Count() )
- return false;
-
- const EntryType_t &entry = m_list[ nIndex ];
- if ( entry.m_nSerial != GetSerialNumber( handle ) )
- return false;
-
- if ( 1 == entry.nInvalid )
- return false;
-
- return true;
-}
-
-
-//-----------------------------------------------------------------------------
-// Current max handle
-//-----------------------------------------------------------------------------
-template< class T, int HandleBits >
-unsigned int CUtlHandleTable<T, HandleBits>::GetValidHandleCount() const
-{
- return m_nValidHandles;
-}
-
-template< class T, int HandleBits >
-unsigned int CUtlHandleTable<T, HandleBits>::GetHandleCount() const
-{
- return m_list.Count();
-}
-
-template< class T, int HandleBits >
-UtlHandle_t CUtlHandleTable<T, HandleBits>::GetHandleFromIndex( int i ) const
-{
- if ( m_list[i].m_pData )
- return CreateHandle( m_list[i].m_nSerial, i );
- return UTLHANDLE_INVALID;
-}
-
-template< class T, int HandleBits >
-int CUtlHandleTable<T, HandleBits>::GetIndexFromHandle( UtlHandle_t h ) const
-{
- if ( h == UTLHANDLE_INVALID )
- return -1;
-
- return GetListIndex( h );
-}
-
-
-
-//-----------------------------------------------------------------------------
-// Cracking handles into indices + serial numbers
-//-----------------------------------------------------------------------------
-template< class T, int HandleBits >
-unsigned int CUtlHandleTable<T, HandleBits>::GetSerialNumber( UtlHandle_t handle )
-{
- return ( ( HandleType_t* )&handle )->nSerial;
-}
-
-template< class T, int HandleBits >
-unsigned int CUtlHandleTable<T, HandleBits>::GetListIndex( UtlHandle_t handle )
-{
- return ( ( HandleType_t* )&handle )->nIndex;
-}
-
-template< class T, int HandleBits >
-UtlHandle_t CUtlHandleTable<T, HandleBits>::CreateHandle( unsigned int nSerial, unsigned int nIndex )
-{
- HandleType_t h( nIndex, nSerial );
- return *( UtlHandle_t* )&h;
-}
-
-
-//-----------------------------------------------------------------------------
-// Looks up a entry by handle
-//-----------------------------------------------------------------------------
-template< class T, int HandleBits >
-const typename CUtlHandleTable<T, HandleBits>::EntryType_t *CUtlHandleTable<T, HandleBits>::GetEntry( UtlHandle_t handle, bool checkValidity ) const
-{
- if ( handle == UTLHANDLE_INVALID )
- return NULL;
-
- unsigned int nIndex = GetListIndex( handle );
- Assert( nIndex < ( unsigned int )m_list.Count() );
- if ( nIndex >= ( unsigned int )m_list.Count() )
- return NULL;
-
- const EntryType_t &entry = m_list[ nIndex ];
- if ( entry.m_nSerial != GetSerialNumber( handle ) )
- return NULL;
-
- if ( checkValidity &&
- ( 1 == entry.nInvalid ) )
- return NULL;
-
- return &entry;
-}
-
-template< class T, int HandleBits >
-void CUtlHandleTable<T, HandleBits>::MarkHandleInvalid( UtlHandle_t handle )
-{
- if ( handle == UTLHANDLE_INVALID )
- return;
-
- unsigned int nIndex = GetListIndex( handle );
- Assert( nIndex < ( unsigned int )m_list.Count() );
- if ( nIndex >= ( unsigned int )m_list.Count() )
- return;
-
- EntryType_t &entry = m_list[ nIndex ];
- if ( entry.m_nSerial != GetSerialNumber( handle ) )
- return;
-
- if ( !entry.nInvalid )
- {
- --m_nValidHandles;
- entry.nInvalid = 1;
- }
-}
-
-template< class T, int HandleBits >
-void CUtlHandleTable<T, HandleBits>::MarkHandleValid( UtlHandle_t handle )
-{
- if ( handle == UTLHANDLE_INVALID )
- return;
-
- unsigned int nIndex = GetListIndex( handle );
- Assert( nIndex < ( unsigned int )m_list.Count() );
- if ( nIndex >= ( unsigned int )m_list.Count() )
- return;
-
- EntryType_t &entry = m_list[ nIndex ];
- if ( entry.m_nSerial != GetSerialNumber( handle ) )
- return;
-
- if ( entry.nInvalid )
- {
- ++m_nValidHandles;
- entry.nInvalid = 0;
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Handle wrapper. Assumes 2 things
-// 1) That class T has a non-static method called GetHandle which returns a UtlHandle_t
-// 2) That class T has a static method called GetPtrFromHandle which returns a T* given a UtlHandle_t
-// 3) That class T has a static method called IsHandleValid which accepts a UtlHandle_t
-//-----------------------------------------------------------------------------
-template< class T >
-class CUtlHandle
-{
-public:
- // Constructors
- CUtlHandle();
- explicit CUtlHandle( T *pObject );
- CUtlHandle( UtlHandle_t h );
- CUtlHandle( const CUtlHandle<T> &h );
-
- // Assignment
- void Set( T *pObject );
- void Set( UtlHandle_t h );
- const CUtlHandle<T> &operator=( UtlHandle_t h );
- const CUtlHandle<T> &operator=( T *pObject );
-
- // Retrieval
- T *Get();
- const T* Get() const;
-
- // Is the handle valid?
- bool IsValid() const;
-
- // Casting
- operator T*();
- operator UtlHandle_t();
- operator bool();
- T* operator->();
- const T* operator->() const;
-
- // Equality
- bool operator==( CUtlHandle<T> h ) const;
- bool operator==( T *pObject ) const;
- bool operator==( UtlHandle_t h ) const;
- bool operator!=( CUtlHandle<T> h ) const;
- bool operator!=( T *pObject ) const;
- bool operator!=( UtlHandle_t h ) const;
-
-private:
- UtlHandle_t m_handle;
-};
-
-
-//-----------------------------------------------------------------------------
-// Constructors
-//-----------------------------------------------------------------------------
-template< class T >
-CUtlHandle<T>::CUtlHandle() : m_handle( UTLHANDLE_INVALID )
-{
-}
-
-template< class T >
-CUtlHandle<T>::CUtlHandle( T *pObject )
-{
- Set( pObject );
-}
-
-template< class T >
-CUtlHandle<T>::CUtlHandle( UtlHandle_t h )
-{
- m_handle = h;
-}
-
-template< class T >
-CUtlHandle<T>::CUtlHandle( const CUtlHandle<T> &h )
-{
- m_handle = h.m_handle;
-}
-
-
-//-----------------------------------------------------------------------------
-// Assignment
-//-----------------------------------------------------------------------------
-template< class T >
-void CUtlHandle<T>::Set( T *pObject )
-{
- // Assumes T has a member function GetHandle
- m_handle = pObject ? pObject->GetHandle() : UTLHANDLE_INVALID;
-}
-
-template< class T >
-void CUtlHandle<T>::Set( UtlHandle_t h )
-{
- m_handle = h;
-}
-
-template< class T >
-const CUtlHandle<T> &CUtlHandle<T>::operator=( UtlHandle_t h )
-{
- Set( h );
- return *this;
-}
-
-template< class T >
-const CUtlHandle<T> &CUtlHandle<T>::operator=( T *pObject )
-{
- Set( pObject );
- return *this;
-}
-
-
-//-----------------------------------------------------------------------------
-// Is the handle valid?
-//-----------------------------------------------------------------------------
-template< class T >
-bool CUtlHandle<T>::IsValid() const
-{
- // Assumes T has a static member function IsHandleValid
- return T::IsHandleValid( m_handle );
-}
-
-
-//-----------------------------------------------------------------------------
-// Retrieval
-//-----------------------------------------------------------------------------
-template< class T >
-T *CUtlHandle<T>::Get()
-{
- // Assumes T has a static member function GetPtrFromHandle
- return T::GetPtrFromHandle( m_handle );
-}
-
-template< class T >
-const T* CUtlHandle<T>::Get() const
-{
- // Assumes T has a static member function GetPtrFromHandle
- return T::GetPtrFromHandle( m_handle );
-}
-
-
-//-----------------------------------------------------------------------------
-// Casting
-//-----------------------------------------------------------------------------
-template< class T >
-CUtlHandle<T>::operator T*()
-{
- return Get();
-}
-
-template< class T >
-CUtlHandle<T>::operator UtlHandle_t()
-{
- return m_handle;
-}
-
-template< class T >
-T* CUtlHandle<T>::operator->()
-{
- return Get();
-}
-
-template< class T >
-const T* CUtlHandle<T>::operator->() const
-{
- return Get();
-}
-
-template< class T >
-CUtlHandle<T>::operator bool()
-{
- return m_handle != UTLHANDLE_INVALID;
-}
-
-
-//-----------------------------------------------------------------------------
-// Equality
-//-----------------------------------------------------------------------------
-template< class T >
-bool CUtlHandle<T>::operator==( CUtlHandle<T> h ) const
-{
- return m_handle == h.m_handle;
-}
-
-template< class T >
-bool CUtlHandle<T>::operator==( T *pObject ) const
-{
- UtlHandle_t h = pObject ? pObject->GetHandle() : UTLHANDLE_INVALID;
- return m_handle == h;
-}
-
-template< class T >
-bool CUtlHandle<T>::operator==( UtlHandle_t h ) const
-{
- return m_handle == h;
-}
-
-template< class T >
-bool CUtlHandle<T>::operator!=( CUtlHandle<T> h ) const
-{
- return m_handle != h.m_handle;
-}
-
-template< class T >
-bool CUtlHandle<T>::operator!=( T *pObject ) const
-{
- UtlHandle_t h = pObject ? pObject->GetHandle() : UTLHANDLE_INVALID;
- return m_handle != h;
-}
-
-template< class T >
-bool CUtlHandle<T>::operator!=( UtlHandle_t h ) const
-{
- return m_handle != h;
-}
-
-
-//-----------------------------------------------------------------------------
-// Add this macro to a class definition to hook in handles for it!
-//-----------------------------------------------------------------------------
-#define DECLARE_HANDLES( _className, _handleBitCount ) \
- public: \
- UtlHandle_t GetHandle() \
- { \
- return m_Handle; \
- } \
- static _className* GetPtrFromHandle( UtlHandle_t h ) \
- { \
- return m_HandleTable.GetHandle( h ); \
- } \
- static bool IsHandleValid( UtlHandle_t h ) \
- { \
- return m_HandleTable.IsHandleValid( h ); \
- } \
- private: \
- UtlHandle_t m_Handle; \
- static CUtlHandleTable< _className, _handleBitCount > m_HandleTable
-
-
-//-----------------------------------------------------------------------------
-// Add this macro to a .cpp file to hook in handles for it!
-//-----------------------------------------------------------------------------
-#define IMPLEMENT_HANDLES( _className, _handleBitCount ) \
- CUtlHandleTable< _className, _handleBitCount > _className::m_HandleTable;
-
-
-//-----------------------------------------------------------------------------
-// Add these macro to the class constructor + destructor
-//-----------------------------------------------------------------------------
-#define CONSTRUCT_HANDLE( ) \
- m_Handle = m_HandleTable.AddHandle(); \
- m_HandleTable.SetHandle( m_Handle, this )
-
-#define DESTRUCT_HANDLE() \
- m_HandleTable.RemoveHandle( m_Handle ); \
- m_Handle = UTLHANDLE_INVALID
-
-
-
-#endif // UTLHANDLETABLE_H
-
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef UTLHANDLETABLE_H
+#define UTLHANDLETABLE_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#include "tier1/utlvector.h"
+#include "tier1/utlqueue.h"
+
+
+//-----------------------------------------------------------------------------
+// Handles are 32 bits. Invalid handles are all 1s
+//-----------------------------------------------------------------------------
+typedef unsigned int UtlHandle_t;
+#define UTLHANDLE_INVALID ((UtlHandle_t)~0)
+
+
+//-----------------------------------------------------------------------------
+// Purpose: This is a table used to allocate handles
+// HandleBits specifies the max # of simultaneously allocated handles.
+// An extra bit is used for the validity state
+// The rest of the 32 bits are used for a serial number
+//-----------------------------------------------------------------------------
+template< class T, int HandleBits >
+class CUtlHandleTable
+{
+public:
+ CUtlHandleTable();
+
+ // Allocate, deallocate handles
+ UtlHandle_t AddHandle();
+ void RemoveHandle( UtlHandle_t h );
+
+ // Set/get handle values
+ void SetHandle( UtlHandle_t h, T *pData );
+ T *GetHandle( UtlHandle_t h ) const;
+ T *GetHandle( UtlHandle_t h, bool checkValidity ) const;
+
+ // Is a handle valid?
+ bool IsHandleValid( UtlHandle_t h ) const;
+
+ // Iterate over handles; they may not be valid
+ unsigned int GetValidHandleCount() const;
+ unsigned int GetHandleCount() const;
+ UtlHandle_t GetHandleFromIndex( int i ) const;
+ int GetIndexFromHandle( UtlHandle_t h ) const;
+
+ void MarkHandleInvalid( UtlHandle_t h );
+ void MarkHandleValid( UtlHandle_t h );
+
+private:
+ struct HandleType_t
+ {
+ HandleType_t( unsigned int i, unsigned int s ) : nIndex( i ), nSerial( s )
+ {
+ Assert( i < ( 1 << HandleBits ) );
+ Assert( s < ( 1 << ( 31 - HandleBits ) ) );
+ }
+ unsigned int nIndex : HandleBits;
+ unsigned int nSerial : 31 - HandleBits;
+ };
+
+ struct EntryType_t
+ {
+ EntryType_t() : m_nSerial( 0 ), nInvalid( 0 ), m_pData( 0 ) {}
+ unsigned int m_nSerial : 31;
+ unsigned int nInvalid : 1;
+ T *m_pData;
+ };
+
+ static unsigned int GetSerialNumber( UtlHandle_t handle );
+ static unsigned int GetListIndex( UtlHandle_t handle );
+ static UtlHandle_t CreateHandle( unsigned int nSerial, unsigned int nIndex );
+ const EntryType_t *GetEntry( UtlHandle_t handle, bool checkValidity ) const;
+
+ unsigned int m_nValidHandles;
+ CUtlVector< EntryType_t > m_list;
+ CUtlQueue< int > m_unused;
+};
+
+
+//-----------------------------------------------------------------------------
+// Constructor, destructor
+//-----------------------------------------------------------------------------
+template< class T, int HandleBits >
+CUtlHandleTable<T, HandleBits>::CUtlHandleTable() : m_nValidHandles( 0 )
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Allocate, deallocate handles
+//-----------------------------------------------------------------------------
+template< class T, int HandleBits >
+UtlHandle_t CUtlHandleTable<T, HandleBits>::AddHandle()
+{
+ unsigned int nIndex = ( m_unused.Count() > 0 ) ? m_unused.RemoveAtHead() : m_list.AddToTail();
+
+ EntryType_t &entry = m_list[ nIndex ];
+ entry.nInvalid = 0;
+ entry.m_pData = NULL;
+
+ ++m_nValidHandles;
+
+ return CreateHandle( entry.m_nSerial, nIndex );
+}
+
+template< class T, int HandleBits >
+void CUtlHandleTable<T, HandleBits>::RemoveHandle( UtlHandle_t handle )
+{
+ unsigned int nIndex = GetListIndex( handle );
+ Assert( nIndex < ( unsigned int )m_list.Count() );
+ if ( nIndex >= ( unsigned int )m_list.Count() )
+ return;
+
+ EntryType_t &entry = m_list[ nIndex ];
+ ++entry.m_nSerial; // mark old serial# invalid
+ if ( !entry.nInvalid )
+ {
+ entry.nInvalid = 1;
+ --m_nValidHandles;
+ }
+ entry.m_pData = NULL;
+
+
+ // If a handle has been used this many times, then we need to take it out of service, otherwise if the
+ // serial # wraps around we'll possibly revalidate old handles and they'll start to point at the wrong objects. Unlikely, but possible.
+ bool bStopUsing = ( entry.m_nSerial >= ( (1 << ( 31 - HandleBits ) ) - 1 ) );
+ if ( !bStopUsing )
+ {
+ m_unused.Insert( nIndex );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Set/get handle values
+//-----------------------------------------------------------------------------
+template< class T, int HandleBits >
+void CUtlHandleTable<T, HandleBits>::SetHandle( UtlHandle_t handle, T *pData )
+{
+ EntryType_t *entry = const_cast< EntryType_t* >( GetEntry( handle, false ) );
+ Assert( entry );
+ if ( entry == NULL )
+ return;
+
+ // Validate the handle
+ if ( entry->nInvalid )
+ {
+ ++m_nValidHandles;
+ entry->nInvalid = 0;
+ }
+ entry->m_pData = pData;
+}
+
+template< class T, int HandleBits >
+T *CUtlHandleTable<T, HandleBits>::GetHandle( UtlHandle_t handle ) const
+{
+ const EntryType_t *entry = GetEntry( handle, true );
+ return entry ? entry->m_pData : NULL;
+}
+
+template< class T, int HandleBits >
+T *CUtlHandleTable<T, HandleBits>::GetHandle( UtlHandle_t handle, bool checkValidity ) const
+{
+ const EntryType_t *entry = GetEntry( handle, checkValidity );
+ return entry ? entry->m_pData : NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// Is a handle valid?
+//-----------------------------------------------------------------------------
+template< class T, int HandleBits >
+bool CUtlHandleTable<T, HandleBits>::IsHandleValid( UtlHandle_t handle ) const
+{
+ if ( handle == UTLHANDLE_INVALID )
+ return false;
+
+ unsigned int nIndex = GetListIndex( handle );
+ AssertOnce( nIndex < ( unsigned int )m_list.Count() );
+ if ( nIndex >= ( unsigned int )m_list.Count() )
+ return false;
+
+ const EntryType_t &entry = m_list[ nIndex ];
+ if ( entry.m_nSerial != GetSerialNumber( handle ) )
+ return false;
+
+ if ( 1 == entry.nInvalid )
+ return false;
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Current max handle
+//-----------------------------------------------------------------------------
+template< class T, int HandleBits >
+unsigned int CUtlHandleTable<T, HandleBits>::GetValidHandleCount() const
+{
+ return m_nValidHandles;
+}
+
+template< class T, int HandleBits >
+unsigned int CUtlHandleTable<T, HandleBits>::GetHandleCount() const
+{
+ return m_list.Count();
+}
+
+template< class T, int HandleBits >
+UtlHandle_t CUtlHandleTable<T, HandleBits>::GetHandleFromIndex( int i ) const
+{
+ if ( m_list[i].m_pData )
+ return CreateHandle( m_list[i].m_nSerial, i );
+ return UTLHANDLE_INVALID;
+}
+
+template< class T, int HandleBits >
+int CUtlHandleTable<T, HandleBits>::GetIndexFromHandle( UtlHandle_t h ) const
+{
+ if ( h == UTLHANDLE_INVALID )
+ return -1;
+
+ return GetListIndex( h );
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Cracking handles into indices + serial numbers
+//-----------------------------------------------------------------------------
+template< class T, int HandleBits >
+unsigned int CUtlHandleTable<T, HandleBits>::GetSerialNumber( UtlHandle_t handle )
+{
+ return ( ( HandleType_t* )&handle )->nSerial;
+}
+
+template< class T, int HandleBits >
+unsigned int CUtlHandleTable<T, HandleBits>::GetListIndex( UtlHandle_t handle )
+{
+ return ( ( HandleType_t* )&handle )->nIndex;
+}
+
+template< class T, int HandleBits >
+UtlHandle_t CUtlHandleTable<T, HandleBits>::CreateHandle( unsigned int nSerial, unsigned int nIndex )
+{
+ HandleType_t h( nIndex, nSerial );
+ return *( UtlHandle_t* )&h;
+}
+
+
+//-----------------------------------------------------------------------------
+// Looks up a entry by handle
+//-----------------------------------------------------------------------------
+template< class T, int HandleBits >
+const typename CUtlHandleTable<T, HandleBits>::EntryType_t *CUtlHandleTable<T, HandleBits>::GetEntry( UtlHandle_t handle, bool checkValidity ) const
+{
+ if ( handle == UTLHANDLE_INVALID )
+ return NULL;
+
+ unsigned int nIndex = GetListIndex( handle );
+ Assert( nIndex < ( unsigned int )m_list.Count() );
+ if ( nIndex >= ( unsigned int )m_list.Count() )
+ return NULL;
+
+ const EntryType_t &entry = m_list[ nIndex ];
+ if ( entry.m_nSerial != GetSerialNumber( handle ) )
+ return NULL;
+
+ if ( checkValidity &&
+ ( 1 == entry.nInvalid ) )
+ return NULL;
+
+ return &entry;
+}
+
+template< class T, int HandleBits >
+void CUtlHandleTable<T, HandleBits>::MarkHandleInvalid( UtlHandle_t handle )
+{
+ if ( handle == UTLHANDLE_INVALID )
+ return;
+
+ unsigned int nIndex = GetListIndex( handle );
+ Assert( nIndex < ( unsigned int )m_list.Count() );
+ if ( nIndex >= ( unsigned int )m_list.Count() )
+ return;
+
+ EntryType_t &entry = m_list[ nIndex ];
+ if ( entry.m_nSerial != GetSerialNumber( handle ) )
+ return;
+
+ if ( !entry.nInvalid )
+ {
+ --m_nValidHandles;
+ entry.nInvalid = 1;
+ }
+}
+
+template< class T, int HandleBits >
+void CUtlHandleTable<T, HandleBits>::MarkHandleValid( UtlHandle_t handle )
+{
+ if ( handle == UTLHANDLE_INVALID )
+ return;
+
+ unsigned int nIndex = GetListIndex( handle );
+ Assert( nIndex < ( unsigned int )m_list.Count() );
+ if ( nIndex >= ( unsigned int )m_list.Count() )
+ return;
+
+ EntryType_t &entry = m_list[ nIndex ];
+ if ( entry.m_nSerial != GetSerialNumber( handle ) )
+ return;
+
+ if ( entry.nInvalid )
+ {
+ ++m_nValidHandles;
+ entry.nInvalid = 0;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Handle wrapper. Assumes 2 things
+// 1) That class T has a non-static method called GetHandle which returns a UtlHandle_t
+// 2) That class T has a static method called GetPtrFromHandle which returns a T* given a UtlHandle_t
+// 3) That class T has a static method called IsHandleValid which accepts a UtlHandle_t
+//-----------------------------------------------------------------------------
+template< class T >
+class CUtlHandle
+{
+public:
+ // Constructors
+ CUtlHandle();
+ explicit CUtlHandle( T *pObject );
+ CUtlHandle( UtlHandle_t h );
+ CUtlHandle( const CUtlHandle<T> &h );
+
+ // Assignment
+ void Set( T *pObject );
+ void Set( UtlHandle_t h );
+ const CUtlHandle<T> &operator=( UtlHandle_t h );
+ const CUtlHandle<T> &operator=( T *pObject );
+
+ // Retrieval
+ T *Get();
+ const T* Get() const;
+
+ // Is the handle valid?
+ bool IsValid() const;
+
+ // Casting
+ operator T*();
+ operator UtlHandle_t();
+ operator bool();
+ T* operator->();
+ const T* operator->() const;
+
+ // Equality
+ bool operator==( CUtlHandle<T> h ) const;
+ bool operator==( T *pObject ) const;
+ bool operator==( UtlHandle_t h ) const;
+ bool operator!=( CUtlHandle<T> h ) const;
+ bool operator!=( T *pObject ) const;
+ bool operator!=( UtlHandle_t h ) const;
+
+private:
+ UtlHandle_t m_handle;
+};
+
+
+//-----------------------------------------------------------------------------
+// Constructors
+//-----------------------------------------------------------------------------
+template< class T >
+CUtlHandle<T>::CUtlHandle() : m_handle( UTLHANDLE_INVALID )
+{
+}
+
+template< class T >
+CUtlHandle<T>::CUtlHandle( T *pObject )
+{
+ Set( pObject );
+}
+
+template< class T >
+CUtlHandle<T>::CUtlHandle( UtlHandle_t h )
+{
+ m_handle = h;
+}
+
+template< class T >
+CUtlHandle<T>::CUtlHandle( const CUtlHandle<T> &h )
+{
+ m_handle = h.m_handle;
+}
+
+
+//-----------------------------------------------------------------------------
+// Assignment
+//-----------------------------------------------------------------------------
+template< class T >
+void CUtlHandle<T>::Set( T *pObject )
+{
+ // Assumes T has a member function GetHandle
+ m_handle = pObject ? pObject->GetHandle() : UTLHANDLE_INVALID;
+}
+
+template< class T >
+void CUtlHandle<T>::Set( UtlHandle_t h )
+{
+ m_handle = h;
+}
+
+template< class T >
+const CUtlHandle<T> &CUtlHandle<T>::operator=( UtlHandle_t h )
+{
+ Set( h );
+ return *this;
+}
+
+template< class T >
+const CUtlHandle<T> &CUtlHandle<T>::operator=( T *pObject )
+{
+ Set( pObject );
+ return *this;
+}
+
+
+//-----------------------------------------------------------------------------
+// Is the handle valid?
+//-----------------------------------------------------------------------------
+template< class T >
+bool CUtlHandle<T>::IsValid() const
+{
+ // Assumes T has a static member function IsHandleValid
+ return T::IsHandleValid( m_handle );
+}
+
+
+//-----------------------------------------------------------------------------
+// Retrieval
+//-----------------------------------------------------------------------------
+template< class T >
+T *CUtlHandle<T>::Get()
+{
+ // Assumes T has a static member function GetPtrFromHandle
+ return T::GetPtrFromHandle( m_handle );
+}
+
+template< class T >
+const T* CUtlHandle<T>::Get() const
+{
+ // Assumes T has a static member function GetPtrFromHandle
+ return T::GetPtrFromHandle( m_handle );
+}
+
+
+//-----------------------------------------------------------------------------
+// Casting
+//-----------------------------------------------------------------------------
+template< class T >
+CUtlHandle<T>::operator T*()
+{
+ return Get();
+}
+
+template< class T >
+CUtlHandle<T>::operator UtlHandle_t()
+{
+ return m_handle;
+}
+
+template< class T >
+T* CUtlHandle<T>::operator->()
+{
+ return Get();
+}
+
+template< class T >
+const T* CUtlHandle<T>::operator->() const
+{
+ return Get();
+}
+
+template< class T >
+CUtlHandle<T>::operator bool()
+{
+ return m_handle != UTLHANDLE_INVALID;
+}
+
+
+//-----------------------------------------------------------------------------
+// Equality
+//-----------------------------------------------------------------------------
+template< class T >
+bool CUtlHandle<T>::operator==( CUtlHandle<T> h ) const
+{
+ return m_handle == h.m_handle;
+}
+
+template< class T >
+bool CUtlHandle<T>::operator==( T *pObject ) const
+{
+ UtlHandle_t h = pObject ? pObject->GetHandle() : UTLHANDLE_INVALID;
+ return m_handle == h;
+}
+
+template< class T >
+bool CUtlHandle<T>::operator==( UtlHandle_t h ) const
+{
+ return m_handle == h;
+}
+
+template< class T >
+bool CUtlHandle<T>::operator!=( CUtlHandle<T> h ) const
+{
+ return m_handle != h.m_handle;
+}
+
+template< class T >
+bool CUtlHandle<T>::operator!=( T *pObject ) const
+{
+ UtlHandle_t h = pObject ? pObject->GetHandle() : UTLHANDLE_INVALID;
+ return m_handle != h;
+}
+
+template< class T >
+bool CUtlHandle<T>::operator!=( UtlHandle_t h ) const
+{
+ return m_handle != h;
+}
+
+
+//-----------------------------------------------------------------------------
+// Add this macro to a class definition to hook in handles for it!
+//-----------------------------------------------------------------------------
+#define DECLARE_HANDLES( _className, _handleBitCount ) \
+ public: \
+ UtlHandle_t GetHandle() \
+ { \
+ return m_Handle; \
+ } \
+ static _className* GetPtrFromHandle( UtlHandle_t h ) \
+ { \
+ return m_HandleTable.GetHandle( h ); \
+ } \
+ static bool IsHandleValid( UtlHandle_t h ) \
+ { \
+ return m_HandleTable.IsHandleValid( h ); \
+ } \
+ private: \
+ UtlHandle_t m_Handle; \
+ static CUtlHandleTable< _className, _handleBitCount > m_HandleTable
+
+
+//-----------------------------------------------------------------------------
+// Add this macro to a .cpp file to hook in handles for it!
+//-----------------------------------------------------------------------------
+#define IMPLEMENT_HANDLES( _className, _handleBitCount ) \
+ CUtlHandleTable< _className, _handleBitCount > _className::m_HandleTable;
+
+
+//-----------------------------------------------------------------------------
+// Add these macro to the class constructor + destructor
+//-----------------------------------------------------------------------------
+#define CONSTRUCT_HANDLE( ) \
+ m_Handle = m_HandleTable.AddHandle(); \
+ m_HandleTable.SetHandle( m_Handle, this )
+
+#define DESTRUCT_HANDLE() \
+ m_HandleTable.RemoveHandle( m_Handle ); \
+ m_Handle = UTLHANDLE_INVALID
+
+
+
+#endif // UTLHANDLETABLE_H
+
diff --git a/mp/src/public/tier1/utlhash.h b/mp/src/public/tier1/utlhash.h
index 72751ffc..7207b597 100644
--- a/mp/src/public/tier1/utlhash.h
+++ b/mp/src/public/tier1/utlhash.h
@@ -1,936 +1,936 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//
-// Serialization/unserialization buffer
-//=============================================================================//
-
-#ifndef UTLHASH_H
-#define UTLHASH_H
-#pragma once
-
-#include <assert.h>
-#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 );
-
-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 )
-{
- 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;
- 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;
-
- 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;
-
- 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;
-
- 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;
-
- 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 );
-}
-
-//=============================================================================
-//
-// 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; }
-
- // Initialize.
- bool Init( int nBucketCount );
-
- // Size.
- int Count( void );
-
- // 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 );
-
- Data &Element( UtlHashFastHandle_t hHash );
- Data const &Element( UtlHashFastHandle_t hHash ) const;
- Data &operator[]( UtlHashFastHandle_t hHash );
- Data const &operator[]( UtlHashFastHandle_t hHash ) const;
-
-//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.
-//-----------------------------------------------------------------------------
-template<class Data, class HashFuncs> inline int CUtlHashFast<Data,HashFuncs>::Count( void )
-{
- 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 )
-{
- // 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 );
-}
-
-//=============================================================================
-//
-// 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;
-}
-
-#endif // UTLHASH_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+// Serialization/unserialization buffer
+//=============================================================================//
+
+#ifndef UTLHASH_H
+#define UTLHASH_H
+#pragma once
+
+#include <assert.h>
+#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 );
+
+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 )
+{
+ 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;
+ 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;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ 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 );
+}
+
+//=============================================================================
+//
+// 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; }
+
+ // Initialize.
+ bool Init( int nBucketCount );
+
+ // Size.
+ int Count( void );
+
+ // 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 );
+
+ Data &Element( UtlHashFastHandle_t hHash );
+ Data const &Element( UtlHashFastHandle_t hHash ) const;
+ Data &operator[]( UtlHashFastHandle_t hHash );
+ Data const &operator[]( UtlHashFastHandle_t hHash ) const;
+
+//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.
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> inline int CUtlHashFast<Data,HashFuncs>::Count( void )
+{
+ 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 )
+{
+ // 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 );
+}
+
+//=============================================================================
+//
+// 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;
+}
+
+#endif // UTLHASH_H
diff --git a/mp/src/public/tier1/utlhashdict.h b/mp/src/public/tier1/utlhashdict.h
index b1ba7ecd..109bb759 100644
--- a/mp/src/public/tier1/utlhashdict.h
+++ b/mp/src/public/tier1/utlhashdict.h
@@ -1,342 +1,342 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-//=============================================================================
-
-#ifndef UTLHASHDICT_H
-#define UTLHASHDICT_H
-
-#if defined( _WIN32 )
-#pragma once
-#endif
-
-#include "tier1/utlhash.h"
-#include "tier1/generichash.h"
-#include "mathlib/mathlib.h"
-
-//-----------------------------------------------------------------------------
-//
-//-----------------------------------------------------------------------------
-template <typename T, bool bCaseInsensitive = true, bool bDupeStrings = true>
-class CUtlHashDict
-{
-public:
- // constructor, destructor
- CUtlHashDict( int bucketCount = 16, int growCount = 0, int initCount = 0 );
- ~CUtlHashDict( );
-
- // gets particular elements
- T& Element( unsigned i );
- const T& Element( unsigned i ) const;
- T& operator[]( unsigned i );
- const T& operator[]( unsigned i ) const;
-
- // gets element names
- char const *GetElementName( unsigned i ) const;
-
- // Number of elements
- int Count() const;
-
- // Checks if a node is valid and in the tree
- bool IsValidIndex( unsigned i ) const;
-
- // Invalid index
- static unsigned InvalidHandle();
-
- // Insert method (inserts in order)
- unsigned Insert( const char *pName, const T &element );
- unsigned Insert( const char *pName );
-
- // Find method
- unsigned Find( const char *pName ) const;
-
- // Remove methods
- void RemoveAt( unsigned i );
- void Remove( const char *pName );
- void RemoveAll( );
-
- // Purge memory
- void Purge();
- void PurgeAndDeleteElements(); // Call delete on each element.
-
- // Iteration methods
- unsigned First() const;
- unsigned Next( unsigned i ) const;
-
-protected:
- struct Entry_t
- {
- const char *pszSymbol;
- T value;
- };
-
- template <bool bCaseInsensitive>
- class CCompare
- {
- public:
- CCompare( int ignored ) {}
-
- bool operator()( const Entry_t &entry1, const Entry_t &entry2 ) const
- {
- return !( ( bCaseInsensitive ) ? stricmp( entry1.pszSymbol, entry2.pszSymbol ) : strcmp( entry1.pszSymbol, entry2.pszSymbol ) );
- }
- };
-
- template <bool bCaseInsensitive>
- class CHash
- {
- public:
- CHash( int ignored ) {}
-
- unsigned operator()( const Entry_t &entry ) const
- {
- return !( ( bCaseInsensitive ) ? HashStringCaseless( entry.pszSymbol ) : HashString( entry.pszSymbol ) );
- }
- };
-
- typedef CUtlHash<Entry_t, CCompare<bCaseInsensitive>, CHash<bCaseInsensitive> > CHashTable;
- CHashTable m_Elements;
- int m_nCount;
-};
-
-//-----------------------------------------------------------------------------
-// constructor, destructor
-//-----------------------------------------------------------------------------
-template <typename T, bool bCaseInsensitive, bool bDupeStrings>
-CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::CUtlHashDict( int bucketCount = 16, int growCount = 0, int initCount = 0 ) :
- m_Elements( SmallestPowerOfTwoGreaterOrEqual(bucketCount), growCount, initCount )
-{
- Assert( SmallestPowerOfTwoGreaterOrEqual(bucketCount) <= 0xffff );
-}
-
-template <typename T, bool bCaseInsensitive, bool bDupeStrings>
-CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::~CUtlHashDict()
-{
- Purge();
-}
-
-//-----------------------------------------------------------------------------
-// gets particular elements
-//-----------------------------------------------------------------------------
-template <typename T, bool bCaseInsensitive, bool bDupeStrings>
-inline T& CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Element( unsigned i )
-{
- return m_Elements[i].value;
-}
-
-template <typename T, bool bCaseInsensitive, bool bDupeStrings>
-inline const T& CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Element( unsigned i ) const
-{
- return m_Elements[i].value;
-}
-
-//-----------------------------------------------------------------------------
-// gets element names
-//-----------------------------------------------------------------------------
-template <typename T, bool bCaseInsensitive, bool bDupeStrings>
-inline char const *CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::GetElementName( unsigned i ) const
-{
- return m_Elements[i].pszSymbol;
-}
-
-template <typename T, bool bCaseInsensitive, bool bDupeStrings>
-inline T& CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::operator[]( unsigned i )
-{
- return m_Elements[i].value;
-}
-
-template <typename T, bool bCaseInsensitive, bool bDupeStrings>
-inline const T & CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::operator[]( unsigned i ) const
-{
- return m_Elements[i].value;
-}
-
-//-----------------------------------------------------------------------------
-// Num elements
-//-----------------------------------------------------------------------------
-template <typename T, bool bCaseInsensitive, bool bDupeStrings>
-inline int CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Count() const
-{
- Assert( m_nCount == m_Elements.Count() );
- return m_nCount;
-}
-
-
-//-----------------------------------------------------------------------------
-// Checks if a node is valid and in the tree
-//-----------------------------------------------------------------------------
-template <typename T, bool bCaseInsensitive, bool bDupeStrings>
-inline bool CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::IsValidIndex( unsigned i ) const
-{
- return m_Elements.IsValidHandle(i);
-}
-
-
-//-----------------------------------------------------------------------------
-// Invalid index
-//-----------------------------------------------------------------------------
-template <typename T, bool bCaseInsensitive, bool bDupeStrings>
-inline unsigned CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::InvalidHandle()
-{
- return CHashTable::InvalidHandle();
-}
-
-
-//-----------------------------------------------------------------------------
-// Delete a node from the tree
-//-----------------------------------------------------------------------------
-template <typename T, bool bCaseInsensitive, bool bDupeStrings>
-void CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::RemoveAt(unsigned elem)
-{
- if ( bDupeStrings )
- {
- free( (void *)m_Elements[elem].pszSymbol );
- }
- m_Elements.Remove(elem);
- m_nCount--;
-}
-
-
-//-----------------------------------------------------------------------------
-// remove a node in the tree
-//-----------------------------------------------------------------------------
-template <typename T, bool bCaseInsensitive, bool bDupeStrings> void CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Remove( const char *search )
-{
- unsigned node = Find( search );
- if (node != InvalidHandle())
- {
- RemoveAt(node);
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Removes all nodes from the tree
-//-----------------------------------------------------------------------------
-template <typename T, bool bCaseInsensitive, bool bDupeStrings>
-void CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::RemoveAll()
-{
- if ( bDupeStrings )
- {
- typename UtlHashHandle_t index = m_Elements.GetFirstHandle();
- while ( index != m_Elements.InvalidHandle() )
- {
- free( (void *)m_Elements[index].pszSymbol );
- index = m_Elements.GetNextHandle( index );
- }
- }
-
- m_Elements.RemoveAll();
- m_nCount = 0;
-}
-
-template <typename T, bool bCaseInsensitive, bool bDupeStrings>
-void CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Purge()
-{
- if ( bDupeStrings )
- {
- typename UtlHashHandle_t index = m_Elements.GetFirstHandle();
- while ( index != m_Elements.InvalidHandle() )
- {
- free( (void *)m_Elements[index].pszSymbol );
- index = m_Elements.GetNextHandle( index );
- }
- }
-
- m_Elements.Purge();
- m_nCount = 0;
-}
-
-
-template <typename T, bool bCaseInsensitive, bool bDupeStrings>
-void CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::PurgeAndDeleteElements()
-{
- // Delete all the elements.
- unsigned index = m_Elements.GetFirstHandle();
- while ( index != m_Elements.InvalidHandle() )
- {
- if ( bDupeStrings )
- {
- free( (void *)m_Elements[index].pszSymbol );
- }
- delete m_Elements[index].value;
- index = m_Elements.GetNextHandle( index );
- }
-
- m_Elements.RemoveAll();
- m_nCount = 0;
-}
-
-
-//-----------------------------------------------------------------------------
-// inserts a node into the tree
-//-----------------------------------------------------------------------------
-template <typename T, bool bCaseInsensitive, bool bDupeStrings>
-unsigned CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Insert( const char *pName, const T &element )
-{
- MEM_ALLOC_CREDIT_CLASS();
- m_nCount++;
- Entry_t entry =
- {
- (bDupeStrings) ? strdup( pName ) : pName,
- element
- };
- bool bInserted;
- unsigned result = m_Elements.Insert( entry, &bInserted );
- if ( bDupeStrings && !bInserted )
- {
- free( (void *)entry.pszSymbol );
- }
- return result;
-}
-
-template <typename T, bool bCaseInsensitive, bool bDupeStrings>
-unsigned CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Insert( const char *pName )
-{
- MEM_ALLOC_CREDIT_CLASS();
- m_nCount++;
- Entry_t entry =
- {
- (bDupeStrings) ? strdup( pName ) : pName
- };
- bool bInserted;
- unsigned result = m_Elements.Insert( entry, &bInserted );
- if ( bDupeStrings && !bInserted )
- {
- free( (void *)entry.pszSymbol );
- }
- return result;
-}
-
-
-//-----------------------------------------------------------------------------
-// finds a node in the tree
-//-----------------------------------------------------------------------------
-template <typename T, bool bCaseInsensitive, bool bDupeStrings>
-unsigned CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Find( const char *pName ) const
-{
- MEM_ALLOC_CREDIT_CLASS();
- if ( pName )
- return m_Elements.Find( *((Entry_t *)&pName) );
- else
- return InvalidHandle();
-}
-
-
-//-----------------------------------------------------------------------------
-// Iteration methods
-//-----------------------------------------------------------------------------
-template <typename T, bool bCaseInsensitive, bool bDupeStrings>
-unsigned CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::First() const
-{
- return m_Elements.GetFirstHandle();
-}
-
-template <typename T, bool bCaseInsensitive, bool bDupeStrings>
-unsigned CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Next( unsigned i ) const
-{
- return m_Elements.GetNextHandle(i);
-}
-
-#endif // UTLHASHDICT_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef UTLHASHDICT_H
+#define UTLHASHDICT_H
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+#include "tier1/utlhash.h"
+#include "tier1/generichash.h"
+#include "mathlib/mathlib.h"
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+template <typename T, bool bCaseInsensitive = true, bool bDupeStrings = true>
+class CUtlHashDict
+{
+public:
+ // constructor, destructor
+ CUtlHashDict( int bucketCount = 16, int growCount = 0, int initCount = 0 );
+ ~CUtlHashDict( );
+
+ // gets particular elements
+ T& Element( unsigned i );
+ const T& Element( unsigned i ) const;
+ T& operator[]( unsigned i );
+ const T& operator[]( unsigned i ) const;
+
+ // gets element names
+ char const *GetElementName( unsigned i ) const;
+
+ // Number of elements
+ int Count() const;
+
+ // Checks if a node is valid and in the tree
+ bool IsValidIndex( unsigned i ) const;
+
+ // Invalid index
+ static unsigned InvalidHandle();
+
+ // Insert method (inserts in order)
+ unsigned Insert( const char *pName, const T &element );
+ unsigned Insert( const char *pName );
+
+ // Find method
+ unsigned Find( const char *pName ) const;
+
+ // Remove methods
+ void RemoveAt( unsigned i );
+ void Remove( const char *pName );
+ void RemoveAll( );
+
+ // Purge memory
+ void Purge();
+ void PurgeAndDeleteElements(); // Call delete on each element.
+
+ // Iteration methods
+ unsigned First() const;
+ unsigned Next( unsigned i ) const;
+
+protected:
+ struct Entry_t
+ {
+ const char *pszSymbol;
+ T value;
+ };
+
+ template <bool bCaseInsensitive>
+ class CCompare
+ {
+ public:
+ CCompare( int ignored ) {}
+
+ bool operator()( const Entry_t &entry1, const Entry_t &entry2 ) const
+ {
+ return !( ( bCaseInsensitive ) ? stricmp( entry1.pszSymbol, entry2.pszSymbol ) : strcmp( entry1.pszSymbol, entry2.pszSymbol ) );
+ }
+ };
+
+ template <bool bCaseInsensitive>
+ class CHash
+ {
+ public:
+ CHash( int ignored ) {}
+
+ unsigned operator()( const Entry_t &entry ) const
+ {
+ return !( ( bCaseInsensitive ) ? HashStringCaseless( entry.pszSymbol ) : HashString( entry.pszSymbol ) );
+ }
+ };
+
+ typedef CUtlHash<Entry_t, CCompare<bCaseInsensitive>, CHash<bCaseInsensitive> > CHashTable;
+ CHashTable m_Elements;
+ int m_nCount;
+};
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+template <typename T, bool bCaseInsensitive, bool bDupeStrings>
+CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::CUtlHashDict( int bucketCount = 16, int growCount = 0, int initCount = 0 ) :
+ m_Elements( SmallestPowerOfTwoGreaterOrEqual(bucketCount), growCount, initCount )
+{
+ Assert( SmallestPowerOfTwoGreaterOrEqual(bucketCount) <= 0xffff );
+}
+
+template <typename T, bool bCaseInsensitive, bool bDupeStrings>
+CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::~CUtlHashDict()
+{
+ Purge();
+}
+
+//-----------------------------------------------------------------------------
+// gets particular elements
+//-----------------------------------------------------------------------------
+template <typename T, bool bCaseInsensitive, bool bDupeStrings>
+inline T& CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Element( unsigned i )
+{
+ return m_Elements[i].value;
+}
+
+template <typename T, bool bCaseInsensitive, bool bDupeStrings>
+inline const T& CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Element( unsigned i ) const
+{
+ return m_Elements[i].value;
+}
+
+//-----------------------------------------------------------------------------
+// gets element names
+//-----------------------------------------------------------------------------
+template <typename T, bool bCaseInsensitive, bool bDupeStrings>
+inline char const *CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::GetElementName( unsigned i ) const
+{
+ return m_Elements[i].pszSymbol;
+}
+
+template <typename T, bool bCaseInsensitive, bool bDupeStrings>
+inline T& CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::operator[]( unsigned i )
+{
+ return m_Elements[i].value;
+}
+
+template <typename T, bool bCaseInsensitive, bool bDupeStrings>
+inline const T & CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::operator[]( unsigned i ) const
+{
+ return m_Elements[i].value;
+}
+
+//-----------------------------------------------------------------------------
+// Num elements
+//-----------------------------------------------------------------------------
+template <typename T, bool bCaseInsensitive, bool bDupeStrings>
+inline int CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Count() const
+{
+ Assert( m_nCount == m_Elements.Count() );
+ return m_nCount;
+}
+
+
+//-----------------------------------------------------------------------------
+// Checks if a node is valid and in the tree
+//-----------------------------------------------------------------------------
+template <typename T, bool bCaseInsensitive, bool bDupeStrings>
+inline bool CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::IsValidIndex( unsigned i ) const
+{
+ return m_Elements.IsValidHandle(i);
+}
+
+
+//-----------------------------------------------------------------------------
+// Invalid index
+//-----------------------------------------------------------------------------
+template <typename T, bool bCaseInsensitive, bool bDupeStrings>
+inline unsigned CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::InvalidHandle()
+{
+ return CHashTable::InvalidHandle();
+}
+
+
+//-----------------------------------------------------------------------------
+// Delete a node from the tree
+//-----------------------------------------------------------------------------
+template <typename T, bool bCaseInsensitive, bool bDupeStrings>
+void CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::RemoveAt(unsigned elem)
+{
+ if ( bDupeStrings )
+ {
+ free( (void *)m_Elements[elem].pszSymbol );
+ }
+ m_Elements.Remove(elem);
+ m_nCount--;
+}
+
+
+//-----------------------------------------------------------------------------
+// remove a node in the tree
+//-----------------------------------------------------------------------------
+template <typename T, bool bCaseInsensitive, bool bDupeStrings> void CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Remove( const char *search )
+{
+ unsigned node = Find( search );
+ if (node != InvalidHandle())
+ {
+ RemoveAt(node);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Removes all nodes from the tree
+//-----------------------------------------------------------------------------
+template <typename T, bool bCaseInsensitive, bool bDupeStrings>
+void CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::RemoveAll()
+{
+ if ( bDupeStrings )
+ {
+ typename UtlHashHandle_t index = m_Elements.GetFirstHandle();
+ while ( index != m_Elements.InvalidHandle() )
+ {
+ free( (void *)m_Elements[index].pszSymbol );
+ index = m_Elements.GetNextHandle( index );
+ }
+ }
+
+ m_Elements.RemoveAll();
+ m_nCount = 0;
+}
+
+template <typename T, bool bCaseInsensitive, bool bDupeStrings>
+void CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Purge()
+{
+ if ( bDupeStrings )
+ {
+ typename UtlHashHandle_t index = m_Elements.GetFirstHandle();
+ while ( index != m_Elements.InvalidHandle() )
+ {
+ free( (void *)m_Elements[index].pszSymbol );
+ index = m_Elements.GetNextHandle( index );
+ }
+ }
+
+ m_Elements.Purge();
+ m_nCount = 0;
+}
+
+
+template <typename T, bool bCaseInsensitive, bool bDupeStrings>
+void CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::PurgeAndDeleteElements()
+{
+ // Delete all the elements.
+ unsigned index = m_Elements.GetFirstHandle();
+ while ( index != m_Elements.InvalidHandle() )
+ {
+ if ( bDupeStrings )
+ {
+ free( (void *)m_Elements[index].pszSymbol );
+ }
+ delete m_Elements[index].value;
+ index = m_Elements.GetNextHandle( index );
+ }
+
+ m_Elements.RemoveAll();
+ m_nCount = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// inserts a node into the tree
+//-----------------------------------------------------------------------------
+template <typename T, bool bCaseInsensitive, bool bDupeStrings>
+unsigned CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Insert( const char *pName, const T &element )
+{
+ MEM_ALLOC_CREDIT_CLASS();
+ m_nCount++;
+ Entry_t entry =
+ {
+ (bDupeStrings) ? strdup( pName ) : pName,
+ element
+ };
+ bool bInserted;
+ unsigned result = m_Elements.Insert( entry, &bInserted );
+ if ( bDupeStrings && !bInserted )
+ {
+ free( (void *)entry.pszSymbol );
+ }
+ return result;
+}
+
+template <typename T, bool bCaseInsensitive, bool bDupeStrings>
+unsigned CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Insert( const char *pName )
+{
+ MEM_ALLOC_CREDIT_CLASS();
+ m_nCount++;
+ Entry_t entry =
+ {
+ (bDupeStrings) ? strdup( pName ) : pName
+ };
+ bool bInserted;
+ unsigned result = m_Elements.Insert( entry, &bInserted );
+ if ( bDupeStrings && !bInserted )
+ {
+ free( (void *)entry.pszSymbol );
+ }
+ return result;
+}
+
+
+//-----------------------------------------------------------------------------
+// finds a node in the tree
+//-----------------------------------------------------------------------------
+template <typename T, bool bCaseInsensitive, bool bDupeStrings>
+unsigned CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Find( const char *pName ) const
+{
+ MEM_ALLOC_CREDIT_CLASS();
+ if ( pName )
+ return m_Elements.Find( *((Entry_t *)&pName) );
+ else
+ return InvalidHandle();
+}
+
+
+//-----------------------------------------------------------------------------
+// Iteration methods
+//-----------------------------------------------------------------------------
+template <typename T, bool bCaseInsensitive, bool bDupeStrings>
+unsigned CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::First() const
+{
+ return m_Elements.GetFirstHandle();
+}
+
+template <typename T, bool bCaseInsensitive, bool bDupeStrings>
+unsigned CUtlHashDict<T, bCaseInsensitive, bDupeStrings>::Next( unsigned i ) const
+{
+ return m_Elements.GetNextHandle(i);
+}
+
+#endif // UTLHASHDICT_H
diff --git a/mp/src/public/tier1/utlhashtable.h b/mp/src/public/tier1/utlhashtable.h
index 051690fc..2517111f 100644
--- a/mp/src/public/tier1/utlhashtable.h
+++ b/mp/src/public/tier1/utlhashtable.h
@@ -1,944 +1,944 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: a fast growable hashtable with stored hashes, L2-friendly behavior.
-// Useful as a string dictionary or a low-overhead set/map for small POD types.
-//
-// Usage notes:
-// - handles are NOT STABLE across element removal! use RemoveAndAdvance()
-// if you are removing elements while iterating through the hashtable.
-// Use CUtlStableHashtable if you need stable handles (less efficient).
-// - Insert() first searches for an existing match and returns it if found
-// - a value type of "empty_t" can be used to eliminate value storage and
-// switch Element() to return const Key references instead of values
-// - an extra user flag bit is accessible via Get/SetUserFlag()
-// - hash function pointer / functor is exposed via GetHashRef()
-// - comparison function pointer / functor is exposed via GetEqualRef()
-// - if your value type cannot be copy-constructed, use key-only Insert()
-// to default-initialize the value and then manipulate it afterwards.
-//
-// Implementation notes:
-// - overall hash table load is kept between .25 and .75
-// - items which would map to the same ideal slot are chained together
-// - chained items are stored sequentially in adjacent free spaces
-// - "root" entries are prioritized over chained entries; if a
-// slot is not occupied by an item in its root position, the table
-// is guaranteed to contain no keys which would hash to that slot.
-// - new items go at the head of the chain (ie, in their root slot)
-// and evict / "bump" any chained entries which occupy that slot
-// - chain-following skips over unused holes and continues examining
-// table entries until a chain entry with FLAG_LAST is encountered
-//
-// CUtlHashtable< uint32 > setOfIntegers;
-// CUtlHashtable< const char* > setOfStringPointers;
-// CUtlHashtable< int, CUtlVector<blah_t> > mapFromIntsToArrays;
-//
-// $NoKeywords: $
-//
-// A closed-form (open addressing) hashtable with linear sequential probing.
-//=============================================================================//
-
-#ifndef UTLHASHTABLE_H
-#define UTLHASHTABLE_H
-#pragma once
-
-#include "utlcommon.h"
-#include "utlmemory.h"
-#include "mathlib/mathlib.h"
-#include "utllinkedlist.h"
-
-//-----------------------------------------------------------------------------
-// Henry Goffin (henryg) was here. Questions? Bugs? Go slap him around a bit.
-//-----------------------------------------------------------------------------
-
-typedef unsigned int UtlHashHandle_t;
-
-#define FOR_EACH_HASHTABLE( table, iter ) \
- for ( UtlHashHandle_t iter = (table).FirstHandle(); iter != (table).InvalidHandle(); iter = (table).NextHandle( iter ) )
-
-// CUtlHashtableEntry selects between 16 and 32 bit storage backing
-// for flags_and_hash depending on the size of the stored types.
-template < typename KeyT, typename ValueT = empty_t >
-class CUtlHashtableEntry
-{
-public:
- typedef CUtlKeyValuePair< KeyT, ValueT > KVPair;
-
- enum { INT16_STORAGE = ( sizeof( KVPair ) <= 2 ) };
- typedef typename CTypeSelect< INT16_STORAGE, int16, int32 >::type storage_t;
-
- enum
- {
- FLAG_FREE = INT16_STORAGE ? 0x8000 : 0x80000000, // must be high bit for IsValid and IdealIndex to work
- FLAG_LAST = INT16_STORAGE ? 0x4000 : 0x40000000,
- MASK_HASH = INT16_STORAGE ? 0x3FFF : 0x3FFFFFFF
- };
-
- storage_t flags_and_hash;
- storage_t data[ ( sizeof(KVPair) + sizeof(storage_t) - 1 ) / sizeof(storage_t) ];
-
- bool IsValid() const { return flags_and_hash >= 0; }
- void MarkInvalid() { int32 flag = FLAG_FREE; flags_and_hash = (storage_t)flag; }
- const KVPair *Raw() const { return reinterpret_cast< const KVPair * >( &data[0] ); }
- const KVPair *operator->() const { Assert( IsValid() ); return reinterpret_cast< const KVPair * >( &data[0] ); }
- KVPair *Raw() { return reinterpret_cast< KVPair * >( &data[0] ); }
- KVPair *operator->() { Assert( IsValid() ); return reinterpret_cast< KVPair * >( &data[0] ); }
-
- // Returns the ideal index of the data in this slot, or all bits set if invalid
- uint32 FORCEINLINE IdealIndex( uint32 slotmask ) const { return IdealIndex( flags_and_hash, slotmask ) | ( (int32)flags_and_hash >> 31 ); }
-
- // Use template tricks to fully define only one function that takes either 16 or 32 bits
- // and performs different logic without using "if ( INT16_STORAGE )", because GCC and MSVC
- // sometimes have trouble removing the constant branch, which is dumb... but whatever.
- // 16-bit hashes are simply too narrow for large hashtables; more mask bits than hash bits!
- // So we duplicate the hash bits. (Note: h *= MASK_HASH+2 is the same as h += h<<HASH_BITS)
- typedef typename CTypeSelect< INT16_STORAGE, int16, undefined_t >::type uint32_if16BitStorage;
- typedef typename CTypeSelect< INT16_STORAGE, undefined_t, int32 >::type uint32_if32BitStorage;
- static FORCEINLINE uint32 IdealIndex( uint32_if16BitStorage h, uint32 m ) { h &= MASK_HASH; h *= MASK_HASH + 2; return h & m; }
- static FORCEINLINE uint32 IdealIndex( uint32_if32BitStorage h, uint32 m ) { return h & m; }
-
- // More efficient than memcpy for the small types that are stored in a hashtable
- void MoveDataFrom( CUtlHashtableEntry &src )
- {
- storage_t * RESTRICT srcData = &src.data[0];
- for ( int i = 0; i < ARRAYSIZE( data ); ++i ) { data[i] = srcData[i]; }
- }
-};
-
-template <typename KeyT, typename ValueT = empty_t, typename KeyHashT = DefaultHashFunctor<KeyT>, typename KeyIsEqualT = DefaultEqualFunctor<KeyT>, typename AlternateKeyT = typename ArgumentTypeInfo<KeyT>::Alt_t >
-class CUtlHashtable
-{
-public:
- typedef UtlHashHandle_t handle_t;
-
-protected:
- typedef CUtlKeyValuePair<KeyT, ValueT> KVPair;
- typedef typename ArgumentTypeInfo<KeyT>::Arg_t KeyArg_t;
- typedef typename ArgumentTypeInfo<ValueT>::Arg_t ValueArg_t;
- typedef typename ArgumentTypeInfo<AlternateKeyT>::Arg_t KeyAlt_t;
- typedef CUtlHashtableEntry< KeyT, ValueT > entry_t;
-
- enum { FLAG_FREE = entry_t::FLAG_FREE };
- enum { FLAG_LAST = entry_t::FLAG_LAST };
- enum { MASK_HASH = entry_t::MASK_HASH };
-
- CUtlMemory< entry_t > m_table;
- int m_nUsed;
- int m_nMinSize;
- bool m_bSizeLocked;
- KeyIsEqualT m_eq;
- KeyHashT m_hash;
-
- // Allocate an empty table and then re-insert all existing entries.
- void DoRealloc( int size );
-
- // Move an existing entry to a free slot, leaving a hole behind
- void BumpEntry( unsigned int idx );
-
- // Insert an unconstructed KVPair at the primary slot
- int DoInsertUnconstructed( unsigned int h, bool allowGrow );
-
- // Implementation for Insert functions, constructs a KVPair
- // with either a default-construted or copy-constructed value
- template <typename KeyParamT> handle_t DoInsert( KeyParamT k, unsigned int h );
- template <typename KeyParamT> handle_t DoInsert( KeyParamT k, typename ArgumentTypeInfo<ValueT>::Arg_t v, unsigned int h, bool* pDidInsert );
- template <typename KeyParamT> handle_t DoInsertNoCheck( KeyParamT k, typename ArgumentTypeInfo<ValueT>::Arg_t v, unsigned int h );
-
- // Key lookup. Can also return previous-in-chain if result is chained.
- template <typename KeyParamT> handle_t DoLookup( KeyParamT x, unsigned int h, handle_t *pPreviousInChain ) const;
-
- // Remove single element by key + hash. Returns the index of the new hole
- // that was created. Returns InvalidHandle() if element was not found.
- template <typename KeyParamT> int DoRemove( KeyParamT x, unsigned int h );
-
- // Friend CUtlStableHashtable so that it can call our Do* functions directly
- template < typename K, typename V, typename S, typename H, typename E, typename A > friend class CUtlStableHashtable;
-
-public:
- explicit CUtlHashtable( int minimumSize = 32 )
- : m_nUsed(0), m_nMinSize(MAX(8, minimumSize)), m_bSizeLocked(false), m_eq(), m_hash() { }
-
- CUtlHashtable( int minimumSize, const KeyHashT &hash, KeyIsEqualT const &eq = KeyIsEqualT() )
- : m_nUsed(0), m_nMinSize(MAX(8, minimumSize)), m_bSizeLocked(false), m_eq(eq), m_hash(hash) { }
-
- CUtlHashtable( entry_t* pMemory, unsigned int nCount, const KeyHashT &hash = KeyHashT(), KeyIsEqualT const &eq = KeyIsEqualT() )
- : m_nUsed(0), m_nMinSize(8), m_bSizeLocked(false), m_eq(eq), m_hash(hash) { SetExternalBuffer( pMemory, nCount ); }
-
- ~CUtlHashtable() { RemoveAll(); }
-
- CUtlHashtable &operator=( CUtlHashtable const &src );
-
- // Set external memory
- void SetExternalBuffer( byte* pRawBuffer, unsigned int nBytes, bool bAssumeOwnership = false, bool bGrowable = false );
- void SetExternalBuffer( entry_t* pBuffer, unsigned int nSize, bool bAssumeOwnership = false, bool bGrowable = false );
-
- // Functor/function-pointer access
- KeyHashT& GetHashRef() { return m_hash; }
- KeyIsEqualT& GetEqualRef() { return m_eq; }
- KeyHashT const &GetHashRef() const { return m_hash; }
- KeyIsEqualT const &GetEqualRef() const { return m_eq; }
-
- // Handle validation
- bool IsValidHandle( handle_t idx ) const { return (unsigned)idx < (unsigned)m_table.Count() && m_table[idx].IsValid(); }
- static handle_t InvalidHandle() { return (handle_t) -1; }
-
- // Iteration functions
- handle_t FirstHandle() const { return NextHandle( (handle_t) -1 ); }
- handle_t NextHandle( handle_t start ) const;
-
- // Returns the number of unique keys in the table
- int Count() const { return m_nUsed; }
-
-
- // Key lookup, returns InvalidHandle() if not found
- handle_t Find( KeyArg_t k ) const { return DoLookup<KeyArg_t>( k, m_hash(k), NULL ); }
- handle_t Find( KeyArg_t k, unsigned int hash) const { Assert( hash == m_hash(k) ); return DoLookup<KeyArg_t>( k, hash, NULL ); }
- // Alternate-type key lookup, returns InvalidHandle() if not found
- handle_t Find( KeyAlt_t k ) const { return DoLookup<KeyAlt_t>( k, m_hash(k), NULL ); }
- handle_t Find( KeyAlt_t k, unsigned int hash) const { Assert( hash == m_hash(k) ); return DoLookup<KeyAlt_t>( k, hash, NULL ); }
-
- // True if the key is in the table
- bool HasElement( KeyArg_t k ) const { return InvalidHandle() != Find( k ); }
- bool HasElement( KeyAlt_t k ) const { return InvalidHandle() != Find( k ); }
-
- // Key insertion or lookup, always returns a valid handle
- handle_t Insert( KeyArg_t k ) { return DoInsert<KeyArg_t>( k, m_hash(k) ); }
- handle_t Insert( KeyArg_t k, ValueArg_t v, bool *pDidInsert = NULL ) { return DoInsert<KeyArg_t>( k, v, m_hash(k), pDidInsert ); }
- handle_t Insert( KeyArg_t k, ValueArg_t v, unsigned int hash, bool *pDidInsert = NULL ) { Assert( hash == m_hash(k) ); return DoInsert<KeyArg_t>( k, v, hash, pDidInsert ); }
- // Alternate-type key insertion or lookup, always returns a valid handle
- handle_t Insert( KeyAlt_t k ) { return DoInsert<KeyAlt_t>( k, m_hash(k) ); }
- handle_t Insert( KeyAlt_t k, ValueArg_t v, bool *pDidInsert = NULL ) { return DoInsert<KeyAlt_t>( k, v, m_hash(k), pDidInsert ); }
- handle_t Insert( KeyAlt_t k, ValueArg_t v, unsigned int hash, bool *pDidInsert = NULL ) { Assert( hash == m_hash(k) ); return DoInsert<KeyAlt_t>( k, v, hash, pDidInsert ); }
-
- // Key removal, returns false if not found
- bool Remove( KeyArg_t k ) { return DoRemove<KeyArg_t>( k, m_hash(k) ) >= 0; }
- bool Remove( KeyArg_t k, unsigned int hash ) { Assert( hash == m_hash(k) ); return DoRemove<KeyArg_t>( k, hash ) >= 0; }
- // Alternate-type key removal, returns false if not found
- bool Remove( KeyAlt_t k ) { return DoRemove<KeyAlt_t>( k, m_hash(k) ) >= 0; }
- bool Remove( KeyAlt_t k, unsigned int hash ) { Assert( hash == m_hash(k) ); return DoRemove<KeyAlt_t>( k, hash ) >= 0; }
-
- // Remove while iterating, returns the next handle for forward iteration
- // Note: aside from this, ALL handles are invalid if an element is removed
- handle_t RemoveAndAdvance( handle_t idx );
-
- // Nuke contents
- void RemoveAll();
-
- // Nuke and release memory.
- void Purge() { RemoveAll(); m_table.Purge(); }
-
- // Reserve table capacity up front to avoid reallocation during insertions
- void Reserve( int expected ) { if ( expected > m_nUsed ) DoRealloc( expected * 4 / 3 ); }
-
- // Shrink to best-fit size, re-insert keys for optimal lookup
- void Compact( bool bMinimal ) { DoRealloc( bMinimal ? m_nUsed : ( m_nUsed * 4 / 3 ) ); }
-
- // Access functions. Note: if ValueT is empty_t, all functions return const keys.
- typedef typename KVPair::ValueReturn_t Element_t;
- KeyT const &Key( handle_t idx ) const { return m_table[idx]->m_key; }
- Element_t const &Element( handle_t idx ) const { return m_table[idx]->GetValue(); }
- Element_t &Element(handle_t idx) { return m_table[idx]->GetValue(); }
- Element_t const &operator[]( handle_t idx ) const { return m_table[idx]->GetValue(); }
- Element_t &operator[]( handle_t idx ) { return m_table[idx]->GetValue(); }
-
- void ReplaceKey( handle_t idx, KeyArg_t k ) { Assert( m_eq( m_table[idx]->m_key, k ) && m_hash( k ) == m_hash( m_table[idx]->m_key ) ); m_table[idx]->m_key = k; }
- void ReplaceKey( handle_t idx, KeyAlt_t k ) { Assert( m_eq( m_table[idx]->m_key, k ) && m_hash( k ) == m_hash( m_table[idx]->m_key ) ); m_table[idx]->m_key = k; }
-
- Element_t const &Get( KeyArg_t k, Element_t const &defaultValue ) const { handle_t h = Find( k ); if ( h != InvalidHandle() ) return Element( h ); return defaultValue; }
- Element_t const &Get( KeyAlt_t k, Element_t const &defaultValue ) const { handle_t h = Find( k ); if ( h != InvalidHandle() ) return Element( h ); return defaultValue; }
-
- Element_t const *GetPtr( KeyArg_t k ) const { handle_t h = Find(k); if ( h != InvalidHandle() ) return &Element( h ); return NULL; }
- Element_t const *GetPtr( KeyAlt_t k ) const { handle_t h = Find(k); if ( h != InvalidHandle() ) return &Element( h ); return NULL; }
- Element_t *GetPtr( KeyArg_t k ) { handle_t h = Find( k ); if ( h != InvalidHandle() ) return &Element( h ); return NULL; }
- Element_t *GetPtr( KeyAlt_t k ) { handle_t h = Find( k ); if ( h != InvalidHandle() ) return &Element( h ); return NULL; }
-
- // Swap memory and contents with another identical hashtable
- // (NOTE: if using function pointers or functors with state,
- // it is up to the caller to ensure that they are compatible!)
- void Swap( CUtlHashtable &other ) { m_table.Swap(other.m_table); ::V_swap(m_nUsed, other.m_nUsed); }
-
-#if _DEBUG
- // Validate the integrity of the hashtable
- void DbgCheckIntegrity() const;
-#endif
-
-private:
- CUtlHashtable(const CUtlHashtable& copyConstructorIsNotImplemented);
-};
-
-
-// Set external memory (raw byte buffer, best-fit)
-template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
-void CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::SetExternalBuffer( byte* pRawBuffer, unsigned int nBytes, bool bAssumeOwnership, bool bGrowable )
-{
- Assert( ((uintptr_t)pRawBuffer % __alignof(int)) == 0 );
- uint32 bestSize = LargestPowerOfTwoLessThanOrEqual( nBytes / sizeof(entry_t) );
- Assert( bestSize != 0 && bestSize*sizeof(entry_t) <= nBytes );
-
- return SetExternalBuffer( (entry_t*) pRawBuffer, bestSize, bAssumeOwnership, bGrowable );
-}
-
-// Set external memory (typechecked, must be power of two)
-template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
-void CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::SetExternalBuffer( entry_t* pBuffer, unsigned int nSize, bool bAssumeOwnership, bool bGrowable )
-{
- Assert( IsPowerOfTwo(nSize) );
- Assert( m_nUsed == 0 );
- for ( uint i = 0; i < nSize; ++i )
- pBuffer[i].MarkInvalid();
- if ( bAssumeOwnership )
- m_table.AssumeMemory( pBuffer, nSize );
- else
- m_table.SetExternalBuffer( pBuffer, nSize );
- m_bSizeLocked = !bGrowable;
-}
-
-// Allocate an empty table and then re-insert all existing entries.
-template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
-void CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::DoRealloc( int size )
-{
- Assert( !m_bSizeLocked );
-
- size = SmallestPowerOfTwoGreaterOrEqual( MAX( m_nMinSize, size ) );
- Assert( size > 0 && (uint)size <= entry_t::IdealIndex( ~0, 0x1FFFFFFF ) ); // reasonable power of 2
- Assert( size > m_nUsed );
-
- CUtlMemory<entry_t> oldTable;
- oldTable.Swap( m_table );
- entry_t * RESTRICT const pOldBase = oldTable.Base();
-
- m_table.EnsureCapacity( size );
- entry_t * const pNewBase = m_table.Base();
- for ( int i = 0; i < size; ++i )
- pNewBase[i].MarkInvalid();
-
- int nLeftToMove = m_nUsed;
- m_nUsed = 0;
- for ( int i = oldTable.Count() - 1; i >= 0; --i )
- {
- if ( pOldBase[i].IsValid() )
- {
- int newIdx = DoInsertUnconstructed( pOldBase[i].flags_and_hash, false );
- pNewBase[newIdx].MoveDataFrom( pOldBase[i] );
- if ( --nLeftToMove == 0 )
- break;
- }
- }
- Assert( nLeftToMove == 0 );
-}
-
-
-// Move an existing entry to a free slot, leaving a hole behind
-template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
-void CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::BumpEntry( unsigned int idx )
-{
- Assert( m_table[idx].IsValid() );
- Assert( m_nUsed < m_table.Count() );
-
- entry_t* table = m_table.Base();
- unsigned int slotmask = m_table.Count()-1;
- unsigned int new_flags_and_hash = table[idx].flags_and_hash & (FLAG_LAST | MASK_HASH);
-
- unsigned int chainid = entry_t::IdealIndex( new_flags_and_hash, slotmask );
-
- // Look for empty slots scanning forward, stripping FLAG_LAST as we go.
- // Note: this potentially strips FLAG_LAST from table[idx] if we pass it
- int newIdx = chainid; // start at ideal slot
- for ( ; ; newIdx = (newIdx + 1) & slotmask )
- {
- if ( table[newIdx].IdealIndex( slotmask ) == chainid )
- {
- if ( table[newIdx].flags_and_hash & FLAG_LAST )
- {
- table[newIdx].flags_and_hash &= ~FLAG_LAST;
- new_flags_and_hash |= FLAG_LAST;
- }
- continue;
- }
- if ( table[newIdx].IsValid() )
- {
- continue;
- }
- break;
- }
-
- // Did we pick something closer to the ideal slot, leaving behind a
- // FLAG_LAST bit on the current slot because we didn't scan past it?
- if ( table[idx].flags_and_hash & FLAG_LAST )
- {
-#ifdef _DEBUG
- Assert( new_flags_and_hash & FLAG_LAST );
- // Verify logic: we must have moved to an earlier slot, right?
- uint offset = ((uint)idx - chainid + slotmask + 1) & slotmask;
- uint newOffset = ((uint)newIdx - chainid + slotmask + 1) & slotmask;
- Assert( newOffset < offset );
-#endif
- // Scan backwards from old to new location, depositing FLAG_LAST on
- // the first match we find. (+slotmask) is the same as (-1) without
- // having to make anyone think about two's complement shenanigans.
- int scan = (idx + slotmask) & slotmask;
- while ( scan != newIdx )
- {
- if ( table[scan].IdealIndex( slotmask ) == chainid )
- {
- table[scan].flags_and_hash |= FLAG_LAST;
- new_flags_and_hash &= ~FLAG_LAST;
- break;
- }
- scan = (scan + slotmask) & slotmask;
- }
- }
-
- // Move entry to the free slot we found, leaving a hole at idx
- table[newIdx].flags_and_hash = new_flags_and_hash;
- table[newIdx].MoveDataFrom( table[idx] );
- table[idx].MarkInvalid();
-}
-
-
-// Insert a value at the root position for that value's hash chain.
-template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
-int CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::DoInsertUnconstructed( unsigned int h, bool allowGrow )
-{
- if ( allowGrow && !m_bSizeLocked )
- {
- // Keep the load factor between .25 and .75
- int newSize = m_nUsed + 1;
- if ( ( newSize*4 < m_table.Count() && m_table.Count() > m_nMinSize*2 ) || newSize*4 > m_table.Count()*3 )
- {
- DoRealloc( newSize * 4 / 3 );
- }
- }
- Assert( m_nUsed < m_table.Count() );
- ++m_nUsed;
-
- entry_t* table = m_table.Base();
- unsigned int slotmask = m_table.Count()-1;
- unsigned int new_flags_and_hash = FLAG_LAST | (h & MASK_HASH);
- unsigned int idx = entry_t::IdealIndex( h, slotmask );
- if ( table[idx].IdealIndex( slotmask ) == idx )
- {
- // There is already an entry in this chain.
- new_flags_and_hash &= ~FLAG_LAST;
- BumpEntry(idx);
- }
- else if ( table[idx].IsValid() )
- {
- // Somebody else is living in our ideal index but does not belong
- // to our entry chain; move it out of the way, start a new chain.
- BumpEntry(idx);
- }
- table[idx].flags_and_hash = new_flags_and_hash;
- return idx;
-}
-
-
-// Key lookup. Can also return previous-in-chain if result is a chained slot.
-template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
-template <typename KeyParamT>
-UtlHashHandle_t CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::DoLookup( KeyParamT x, unsigned int h, handle_t *pPreviousInChain ) const
-{
- if ( m_nUsed == 0 )
- {
- // Empty table.
- return (handle_t) -1;
- }
-
- const entry_t* table = m_table.Base();
- unsigned int slotmask = m_table.Count()-1;
- Assert( m_table.Count() > 0 && (slotmask & m_table.Count()) == 0 );
- unsigned int chainid = entry_t::IdealIndex( h, slotmask );
-
- unsigned int idx = chainid;
- if ( table[idx].IdealIndex( slotmask ) != chainid )
- {
- // Nothing in root position? No match.
- return (handle_t) -1;
- }
-
- // Linear scan until found or end of chain
- handle_t lastIdx = (handle_t) -1;
- while (1)
- {
- // Only examine this slot if it is valid and belongs to our hash chain
- if ( table[idx].IdealIndex( slotmask ) == chainid )
- {
- // Test the full-width hash to avoid unnecessary calls to m_eq()
- if ( ((table[idx].flags_and_hash ^ h) & MASK_HASH) == 0 && m_eq( table[idx]->m_key, x ) )
- {
- // Found match!
- if (pPreviousInChain)
- *pPreviousInChain = lastIdx;
-
- return (handle_t) idx;
- }
-
- if ( table[idx].flags_and_hash & FLAG_LAST )
- {
- // End of chain. No match.
- return (handle_t) -1;
- }
-
- lastIdx = (handle_t) idx;
- }
- idx = (idx + 1) & slotmask;
- }
-}
-
-
-// Key insertion, or return index of existing key if found
-template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
-template <typename KeyParamT>
-UtlHashHandle_t CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::DoInsert( KeyParamT k, unsigned int h )
-{
- handle_t idx = DoLookup<KeyParamT>( k, h, NULL );
- if ( idx == (handle_t) -1 )
- {
- idx = (handle_t) DoInsertUnconstructed( h, true );
- ConstructOneArg( m_table[ idx ].Raw(), k );
- }
- return idx;
-}
-
-// Key insertion, or return index of existing key if found
-template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
-template <typename KeyParamT>
-UtlHashHandle_t CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::DoInsert( KeyParamT k, typename ArgumentTypeInfo<ValueT>::Arg_t v, unsigned int h, bool *pDidInsert )
-{
- handle_t idx = DoLookup<KeyParamT>( k, h, NULL );
- if ( idx == (handle_t) -1 )
- {
- idx = (handle_t) DoInsertUnconstructed( h, true );
- ConstructTwoArg( m_table[ idx ].Raw(), k, v );
- if ( pDidInsert ) *pDidInsert = true;
- }
- else
- {
- if ( pDidInsert ) *pDidInsert = false;
- }
- return idx;
-}
-
-// Key insertion
-template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
-template <typename KeyParamT>
-UtlHashHandle_t CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::DoInsertNoCheck( KeyParamT k, typename ArgumentTypeInfo<ValueT>::Arg_t v, unsigned int h )
-{
- Assert( DoLookup<KeyParamT>( k, h, NULL ) == (handle_t) -1 );
- handle_t idx = (handle_t) DoInsertUnconstructed( h, true );
- ConstructTwoArg( m_table[ idx ].Raw(), k, v );
- return idx;
-}
-
-
-// Remove single element by key + hash. Returns the location of the new empty hole.
-template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
-template <typename KeyParamT>
-int CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::DoRemove( KeyParamT x, unsigned int h )
-{
- unsigned int slotmask = m_table.Count()-1;
- handle_t previous = (handle_t) -1;
- int idx = (int) DoLookup<KeyParamT>( x, h, &previous );
- if (idx == -1)
- {
- return -1;
- }
-
- enum { FAKEFLAG_ROOT = 1 };
- int nLastAndRootFlags = m_table[idx].flags_and_hash & FLAG_LAST;
- nLastAndRootFlags |= ( (uint)idx == m_table[idx].IdealIndex( slotmask ) );
-
- // Remove from table
- m_table[idx].MarkInvalid();
- Destruct( m_table[idx].Raw() );
- --m_nUsed;
-
- if ( nLastAndRootFlags == FLAG_LAST ) // last only, not root
- {
- // This was the end of the chain - mark previous as last.
- // (This isn't the root, so there must be a previous.)
- Assert( previous != (handle_t) -1 );
- m_table[previous].flags_and_hash |= FLAG_LAST;
- }
-
- if ( nLastAndRootFlags == FAKEFLAG_ROOT ) // root only, not last
- {
- // If we are removing the root and there is more to the chain,
- // scan to find the next chain entry and move it to the root.
- unsigned int chainid = entry_t::IdealIndex( h, slotmask );
- unsigned int nextIdx = idx;
- while (1)
- {
- nextIdx = (nextIdx + 1) & slotmask;
- if ( m_table[nextIdx].IdealIndex( slotmask ) == chainid )
- {
- break;
- }
- }
- Assert( !(m_table[nextIdx].flags_and_hash & FLAG_FREE) );
-
- // Leave a hole where the next entry in the chain was.
- m_table[idx].flags_and_hash = m_table[nextIdx].flags_and_hash;
- m_table[idx].MoveDataFrom( m_table[nextIdx] );
- m_table[nextIdx].MarkInvalid();
- return nextIdx;
- }
-
- // The hole is still where the element used to be.
- return idx;
-}
-
-
-// Assignment operator. It's up to the user to make sure that the hash and equality functors match.
-template <typename K, typename V, typename H, typename E, typename A>
-CUtlHashtable<K,V,H,E,A> &CUtlHashtable<K,V,H,E,A>::operator=( CUtlHashtable<K,V,H,E,A> const &src )
-{
- if ( &src != this )
- {
- Assert( !m_bSizeLocked || m_table.Count() >= src.m_nUsed );
- if ( !m_bSizeLocked )
- {
- Purge();
- Reserve(src.m_nUsed);
- }
- else
- {
- RemoveAll();
- }
-
- const entry_t * srcTable = src.m_table.Base();
- for ( int i = src.m_table.Count() - 1; i >= 0; --i )
- {
- if ( srcTable[i].IsValid() )
- {
- // If this assert trips, double-check that both hashtables
- // have the same hash function pointers or hash functor state!
- Assert( m_hash(srcTable[i]->m_key) == src.m_hash(srcTable[i]->m_key) );
- int newIdx = DoInsertUnconstructed( srcTable[i].flags_and_hash , false );
- CopyConstruct( m_table[newIdx].Raw(), *srcTable[i].Raw() ); // copy construct KVPair
- }
- }
- }
- return *this;
-}
-
-// Remove and return the next valid iterator for a forward iteration.
-template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
-UtlHashHandle_t CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::RemoveAndAdvance( UtlHashHandle_t idx )
-{
- Assert( IsValidHandle( idx ) );
-
- // TODO optimize, implement DoRemoveAt that does not need to re-evaluate equality in DoLookup
- int hole = DoRemove< KeyArg_t >( m_table[idx]->m_key, m_table[idx].flags_and_hash & MASK_HASH );
- // DoRemove returns the index of the element that it moved to fill the hole, if any.
- if ( hole <= (int) idx )
- {
- // Didn't fill, or filled from a previously seen element.
- return NextHandle( idx );
- }
- else
- {
- // Do not advance; slot has a new un-iterated value.
- Assert( IsValidHandle(idx) );
- return idx;
- }
-}
-
-// Burn it with fire.
-template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
-void CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::RemoveAll()
-{
- int used = m_nUsed;
- if ( used != 0 )
- {
- entry_t* table = m_table.Base();
- for ( int i = m_table.Count() - 1; i >= 0; --i )
- {
- if ( table[i].IsValid() )
- {
- table[i].MarkInvalid();
- Destruct( table[i].Raw() );
- if ( --used == 0 )
- break;
- }
- }
- m_nUsed = 0;
- }
-}
-
-template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
-UtlHashHandle_t CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::NextHandle( handle_t start ) const
-{
- const entry_t *table = m_table.Base();
- for ( int i = (int)start + 1; i < m_table.Count(); ++i )
- {
- if ( table[i].IsValid() )
- return (handle_t) i;
- }
- return (handle_t) -1;
-}
-
-
-#if _DEBUG
-template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
-void CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::DbgCheckIntegrity() const
-{
- // Stress test the hash table as a test of both container functionality
- // and also the validity of the user's Hash and Equal function objects.
- // NOTE: will fail if function objects require any sort of state!
- CUtlHashtable clone;
- unsigned int bytes = sizeof(entry_t)*max(16,m_table.Count());
- byte* tempbuf = (byte*) malloc(bytes);
- clone.SetExternalBuffer( tempbuf, bytes, false, false );
- clone = *this;
-
- int count = 0, roots = 0, ends = 0;
- int slotmask = m_table.Count() - 1;
- for (int i = 0; i < m_table.Count(); ++i)
- {
- if (!(m_table[i].flags_and_hash & FLAG_FREE)) ++count;
- if (m_table[i].IdealIndex(slotmask) == (uint)i) ++roots;
- if (m_table[i].flags_and_hash & FLAG_LAST) ++ends;
- if (m_table[i].IsValid())
- {
- Assert( Find(m_table[i]->m_key) == (handle_t)i );
- Verify( clone.Remove(m_table[i]->m_key) );
- }
- else
- {
- Assert( m_table[i].flags_and_hash == FLAG_FREE );
- }
- }
- Assert( count == Count() && count >= roots && roots == ends );
- Assert( clone.Count() == 0 );
- clone.Purge();
- free(tempbuf);
-}
-#endif
-
-//-----------------------------------------------------------------------
-// CUtlStableHashtable
-//-----------------------------------------------------------------------
-
-// Stable hashtables are less memory and cache efficient, but can be
-// iterated quickly and their element handles are completely stable.
-// Implemented as a hashtable which only stores indices, and a separate
-// CUtlLinkedList data table which contains key-value pairs; this may
-// change to a more efficient structure in the future if space becomes
-// critical. I have some ideas about that but not the time to implement
-// at the moment. -henryg
-
-// Note: RemoveAndAdvance is slower than in CUtlHashtable because the
-// key needs to be re-hashed under the current implementation.
-
-template <typename KeyT, typename ValueT = empty_t, typename KeyHashT = DefaultHashFunctor<KeyT>, typename KeyIsEqualT = DefaultEqualFunctor<KeyT>, typename IndexStorageT = uint16, typename AlternateKeyT = typename ArgumentTypeInfo<KeyT>::Alt_t >
-class CUtlStableHashtable
-{
-public:
- typedef typename ArgumentTypeInfo<KeyT>::Arg_t KeyArg_t;
- typedef typename ArgumentTypeInfo<ValueT>::Arg_t ValueArg_t;
- typedef typename ArgumentTypeInfo<AlternateKeyT>::Arg_t KeyAlt_t;
- typedef typename CTypeSelect< sizeof( IndexStorageT ) == 2, uint16, uint32 >::type IndexStorage_t;
-
-protected:
- COMPILE_TIME_ASSERT( sizeof( IndexStorage_t ) == sizeof( IndexStorageT ) );
-
- typedef CUtlKeyValuePair< KeyT, ValueT > KVPair;
- struct HashProxy;
- struct EqualProxy;
- struct IndirectIndex;
-
- typedef CUtlHashtable< IndirectIndex, empty_t, HashProxy, EqualProxy, AlternateKeyT > Hashtable_t;
- typedef CUtlLinkedList< KVPair, IndexStorage_t > LinkedList_t;
-
- template <typename KeyArgumentT> bool DoRemove( KeyArgumentT k );
- template <typename KeyArgumentT> UtlHashHandle_t DoFind( KeyArgumentT k ) const;
- template <typename KeyArgumentT> UtlHashHandle_t DoInsert( KeyArgumentT k );
- template <typename KeyArgumentT, typename ValueArgumentT> UtlHashHandle_t DoInsert( KeyArgumentT k, ValueArgumentT v );
-
-public:
-
- KeyHashT &GetHashRef() { return m_table.GetHashRef().m_hash; }
- KeyIsEqualT &GetEqualRef() { return m_table.GetEqualRef().m_eq; }
- KeyHashT const &GetHashRef() const { return m_table.GetHashRef().m_hash; }
- KeyIsEqualT const &GetEqualRef() const { return m_table.GetEqualRef().m_eq; }
-
- UtlHashHandle_t Insert( KeyArg_t k ) { return DoInsert<KeyArg_t>( k ); }
- UtlHashHandle_t Insert( KeyAlt_t k ) { return DoInsert<KeyAlt_t>( k ); }
- UtlHashHandle_t Insert( KeyArg_t k, ValueArg_t v ) { return DoInsert<KeyArg_t, ValueArg_t>( k, v ); }
- UtlHashHandle_t Insert( KeyAlt_t k, ValueArg_t v ) { return DoInsert<KeyAlt_t, ValueArg_t>( k, v ); }
- UtlHashHandle_t Find( KeyArg_t k ) const { return DoFind<KeyArg_t>( k ); }
- UtlHashHandle_t Find( KeyAlt_t k ) const { return DoFind<KeyAlt_t>( k ); }
- bool Remove( KeyArg_t k ) { return DoRemove<KeyArg_t>( k ); }
- bool Remove( KeyAlt_t k ) { return DoRemove<KeyAlt_t>( k ); }
-
- void RemoveAll() { m_table.RemoveAll(); m_data.RemoveAll(); }
- void Purge() { m_table.Purge(); m_data.Purge(); }
- int Count() const { return m_table.Count(); }
-
- typedef typename KVPair::ValueReturn_t Element_t;
- KeyT const &Key( UtlHashHandle_t idx ) const { return m_data[idx].m_key; }
- Element_t const &Element( UtlHashHandle_t idx ) const { return m_data[idx].GetValue(); }
- Element_t &Element( UtlHashHandle_t idx ) { return m_data[idx].GetValue(); }
- Element_t const &operator[]( UtlHashHandle_t idx ) const { return m_data[idx].GetValue(); }
- Element_t &operator[]( UtlHashHandle_t idx ) { return m_data[idx].GetValue(); }
-
- void ReplaceKey( UtlHashHandle_t idx, KeyArg_t k ) { Assert( GetEqualRef()( m_data[idx].m_key, k ) && GetHashRef()( k ) == GetHashRef()( m_data[idx].m_key ) ); m_data[idx].m_key = k; }
- void ReplaceKey( UtlHashHandle_t idx, KeyAlt_t k ) { Assert( GetEqualRef()( m_data[idx].m_key, k ) && GetHashRef()( k ) == GetHashRef()( m_data[idx].m_key ) ); m_data[idx].m_key = k; }
-
- Element_t const &Get( KeyArg_t k, Element_t const &defaultValue ) const { UtlHashHandle_t h = Find( k ); if ( h != InvalidHandle() ) return Element( h ); return defaultValue; }
- Element_t const &Get( KeyAlt_t k, Element_t const &defaultValue ) const { UtlHashHandle_t h = Find( k ); if ( h != InvalidHandle() ) return Element( h ); return defaultValue; }
-
- Element_t const *GetPtr( KeyArg_t k ) const { UtlHashHandle_t h = Find(k); if ( h != InvalidHandle() ) return &Element( h ); return NULL; }
- Element_t const *GetPtr( KeyAlt_t k ) const { UtlHashHandle_t h = Find(k); if ( h != InvalidHandle() ) return &Element( h ); return NULL; }
- Element_t *GetPtr( KeyArg_t k ) { UtlHashHandle_t h = Find( k ); if ( h != InvalidHandle() ) return &Element( h ); return NULL; }
- Element_t *GetPtr( KeyAlt_t k ) { UtlHashHandle_t h = Find( k ); if ( h != InvalidHandle() ) return &Element( h ); return NULL; }
-
- UtlHashHandle_t FirstHandle() const { return ExtendInvalidHandle( m_data.Head() ); }
- UtlHashHandle_t NextHandle( UtlHashHandle_t h ) const { return ExtendInvalidHandle( m_data.Next( h ) ); }
- bool IsValidHandle( UtlHashHandle_t h ) const { return m_data.IsValidIndex( h ); }
- UtlHashHandle_t InvalidHandle() const { return (UtlHashHandle_t)-1; }
-
- UtlHashHandle_t RemoveAndAdvance( UtlHashHandle_t h )
- {
- Assert( m_data.IsValidIndex( h ) );
- m_table.Remove( IndirectIndex( h ) );
- IndexStorage_t next = m_data.Next( h );
- m_data.Remove( h );
- return ExtendInvalidHandle(next);
- }
-
- void Compact( bool bMinimal ) { m_table.Compact( bMinimal ); /*m_data.Compact();*/ }
-
- void Swap( CUtlStableHashtable &other )
- {
- m_table.Swap(other.m_table);
- // XXX swapping CUtlLinkedList by block memory swap, ugh
- char buf[ sizeof(m_data) ];
- memcpy( buf, &m_data, sizeof(m_data) );
- memcpy( &m_data, &other.m_data, sizeof(m_data) );
- memcpy( &other.m_data, buf, sizeof(m_data) );
- }
-
-
-protected:
- // Perform extension of 0xFFFF to 0xFFFFFFFF if necessary. Note: ( a < CONSTANT ) ? 0 : -1 is usually branchless
- static UtlHashHandle_t ExtendInvalidHandle( uint32 x ) { return x; }
- static UtlHashHandle_t ExtendInvalidHandle( uint16 x ) { uint32 a = x; return a | ( ( a < 0xFFFFu ) ? 0 : -1 ); }
-
- struct IndirectIndex
- {
- explicit IndirectIndex(IndexStorage_t i) : m_index(i) { }
- IndexStorage_t m_index;
- };
-
- struct HashProxy
- {
- KeyHashT m_hash;
- unsigned int operator()( IndirectIndex idx ) const
- {
- const ptrdiff_t tableoffset = (uintptr_t)(&((Hashtable_t*)1024)->GetHashRef()) - 1024;
- const ptrdiff_t owneroffset = offsetof(CUtlStableHashtable, m_table) + tableoffset;
- CUtlStableHashtable* pOwner = (CUtlStableHashtable*)((uintptr_t)this - owneroffset);
- return m_hash( pOwner->m_data[ idx.m_index ].m_key );
- }
- unsigned int operator()( KeyArg_t k ) const { return m_hash( k ); }
- unsigned int operator()( KeyAlt_t k ) const { return m_hash( k ); }
- };
-
- struct EqualProxy
- {
- KeyIsEqualT m_eq;
- unsigned int operator()( IndirectIndex lhs, IndirectIndex rhs ) const
- {
- return lhs.m_index == rhs.m_index;
- }
- unsigned int operator()( IndirectIndex lhs, KeyArg_t rhs ) const
- {
- const ptrdiff_t tableoffset = (uintptr_t)(&((Hashtable_t*)1024)->GetEqualRef()) - 1024;
- const ptrdiff_t owneroffset = offsetof(CUtlStableHashtable, m_table) + tableoffset;
- CUtlStableHashtable* pOwner = (CUtlStableHashtable*)((uintptr_t)this - owneroffset);
- return m_eq( pOwner->m_data[ lhs.m_index ].m_key, rhs );
- }
- unsigned int operator()( IndirectIndex lhs, KeyAlt_t rhs ) const
- {
- const ptrdiff_t tableoffset = (uintptr_t)(&((Hashtable_t*)1024)->GetEqualRef()) - 1024;
- const ptrdiff_t owneroffset = offsetof(CUtlStableHashtable, m_table) + tableoffset;
- CUtlStableHashtable* pOwner = (CUtlStableHashtable*)((uintptr_t)this - owneroffset);
- return m_eq( pOwner->m_data[ lhs.m_index ].m_key, rhs );
- }
- };
-
- class CCustomLinkedList : public LinkedList_t
- {
- public:
- int AddToTailUnconstructed()
- {
- IndexStorage_t newNode = this->AllocInternal();
- if ( newNode != this->InvalidIndex() )
- this->LinkToTail( newNode );
- return newNode;
- }
- };
-
- Hashtable_t m_table;
- CCustomLinkedList m_data;
-};
-
-template <typename K, typename V, typename H, typename E, typename S, typename A>
-template <typename KeyArgumentT>
-inline bool CUtlStableHashtable<K,V,H,E,S,A>::DoRemove( KeyArgumentT k )
-{
- unsigned int hash = m_table.GetHashRef()( k );
- UtlHashHandle_t h = m_table.template DoLookup<KeyArgumentT>( k, hash, NULL );
- if ( h == m_table.InvalidHandle() )
- return false;
-
- int idx = m_table[ h ].m_index;
- m_table.template DoRemove<IndirectIndex>( IndirectIndex( idx ), hash );
- m_data.Remove( idx );
- return true;
-}
-
-template <typename K, typename V, typename H, typename E, typename S, typename A>
-template <typename KeyArgumentT>
-inline UtlHashHandle_t CUtlStableHashtable<K,V,H,E,S,A>::DoFind( KeyArgumentT k ) const
-{
- unsigned int hash = m_table.GetHashRef()( k );
- UtlHashHandle_t h = m_table.template DoLookup<KeyArgumentT>( k, hash, NULL );
- if ( h != m_table.InvalidHandle() )
- return m_table[ h ].m_index;
-
- return (UtlHashHandle_t) -1;
-}
-
-template <typename K, typename V, typename H, typename E, typename S, typename A>
-template <typename KeyArgumentT>
-inline UtlHashHandle_t CUtlStableHashtable<K,V,H,E,S,A>::DoInsert( KeyArgumentT k )
-{
- unsigned int hash = m_table.GetHashRef()( k );
- UtlHashHandle_t h = m_table.template DoLookup<KeyArgumentT>( k, hash, NULL );
- if ( h != m_table.InvalidHandle() )
- return m_table[ h ].m_index;
-
- int idx = m_data.AddToTailUnconstructed();
- ConstructOneArg( &m_data[idx], k );
- m_table.template DoInsertNoCheck<IndirectIndex>( IndirectIndex( idx ), empty_t(), hash );
- return idx;
-}
-
-template <typename K, typename V, typename H, typename E, typename S, typename A>
-template <typename KeyArgumentT, typename ValueArgumentT>
-inline UtlHashHandle_t CUtlStableHashtable<K,V,H,E,S,A>::DoInsert( KeyArgumentT k, ValueArgumentT v )
-{
- unsigned int hash = m_table.GetHashRef()( k );
- UtlHashHandle_t h = m_table.template DoLookup<KeyArgumentT>( k, hash, NULL );
- if ( h != m_table.InvalidHandle() )
- return m_table[ h ].m_index;
-
- int idx = m_data.AddToTailUnconstructed();
- ConstructTwoArg( &m_data[idx], k, v );
- m_table.template DoInsertNoCheck<IndirectIndex>( IndirectIndex( idx ), empty_t(), hash );
- return idx;
-}
-
-#endif // UTLHASHTABLE_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: a fast growable hashtable with stored hashes, L2-friendly behavior.
+// Useful as a string dictionary or a low-overhead set/map for small POD types.
+//
+// Usage notes:
+// - handles are NOT STABLE across element removal! use RemoveAndAdvance()
+// if you are removing elements while iterating through the hashtable.
+// Use CUtlStableHashtable if you need stable handles (less efficient).
+// - Insert() first searches for an existing match and returns it if found
+// - a value type of "empty_t" can be used to eliminate value storage and
+// switch Element() to return const Key references instead of values
+// - an extra user flag bit is accessible via Get/SetUserFlag()
+// - hash function pointer / functor is exposed via GetHashRef()
+// - comparison function pointer / functor is exposed via GetEqualRef()
+// - if your value type cannot be copy-constructed, use key-only Insert()
+// to default-initialize the value and then manipulate it afterwards.
+//
+// Implementation notes:
+// - overall hash table load is kept between .25 and .75
+// - items which would map to the same ideal slot are chained together
+// - chained items are stored sequentially in adjacent free spaces
+// - "root" entries are prioritized over chained entries; if a
+// slot is not occupied by an item in its root position, the table
+// is guaranteed to contain no keys which would hash to that slot.
+// - new items go at the head of the chain (ie, in their root slot)
+// and evict / "bump" any chained entries which occupy that slot
+// - chain-following skips over unused holes and continues examining
+// table entries until a chain entry with FLAG_LAST is encountered
+//
+// CUtlHashtable< uint32 > setOfIntegers;
+// CUtlHashtable< const char* > setOfStringPointers;
+// CUtlHashtable< int, CUtlVector<blah_t> > mapFromIntsToArrays;
+//
+// $NoKeywords: $
+//
+// A closed-form (open addressing) hashtable with linear sequential probing.
+//=============================================================================//
+
+#ifndef UTLHASHTABLE_H
+#define UTLHASHTABLE_H
+#pragma once
+
+#include "utlcommon.h"
+#include "utlmemory.h"
+#include "mathlib/mathlib.h"
+#include "utllinkedlist.h"
+
+//-----------------------------------------------------------------------------
+// Henry Goffin (henryg) was here. Questions? Bugs? Go slap him around a bit.
+//-----------------------------------------------------------------------------
+
+typedef unsigned int UtlHashHandle_t;
+
+#define FOR_EACH_HASHTABLE( table, iter ) \
+ for ( UtlHashHandle_t iter = (table).FirstHandle(); iter != (table).InvalidHandle(); iter = (table).NextHandle( iter ) )
+
+// CUtlHashtableEntry selects between 16 and 32 bit storage backing
+// for flags_and_hash depending on the size of the stored types.
+template < typename KeyT, typename ValueT = empty_t >
+class CUtlHashtableEntry
+{
+public:
+ typedef CUtlKeyValuePair< KeyT, ValueT > KVPair;
+
+ enum { INT16_STORAGE = ( sizeof( KVPair ) <= 2 ) };
+ typedef typename CTypeSelect< INT16_STORAGE, int16, int32 >::type storage_t;
+
+ enum
+ {
+ FLAG_FREE = INT16_STORAGE ? 0x8000 : 0x80000000, // must be high bit for IsValid and IdealIndex to work
+ FLAG_LAST = INT16_STORAGE ? 0x4000 : 0x40000000,
+ MASK_HASH = INT16_STORAGE ? 0x3FFF : 0x3FFFFFFF
+ };
+
+ storage_t flags_and_hash;
+ storage_t data[ ( sizeof(KVPair) + sizeof(storage_t) - 1 ) / sizeof(storage_t) ];
+
+ bool IsValid() const { return flags_and_hash >= 0; }
+ void MarkInvalid() { int32 flag = FLAG_FREE; flags_and_hash = (storage_t)flag; }
+ const KVPair *Raw() const { return reinterpret_cast< const KVPair * >( &data[0] ); }
+ const KVPair *operator->() const { Assert( IsValid() ); return reinterpret_cast< const KVPair * >( &data[0] ); }
+ KVPair *Raw() { return reinterpret_cast< KVPair * >( &data[0] ); }
+ KVPair *operator->() { Assert( IsValid() ); return reinterpret_cast< KVPair * >( &data[0] ); }
+
+ // Returns the ideal index of the data in this slot, or all bits set if invalid
+ uint32 FORCEINLINE IdealIndex( uint32 slotmask ) const { return IdealIndex( flags_and_hash, slotmask ) | ( (int32)flags_and_hash >> 31 ); }
+
+ // Use template tricks to fully define only one function that takes either 16 or 32 bits
+ // and performs different logic without using "if ( INT16_STORAGE )", because GCC and MSVC
+ // sometimes have trouble removing the constant branch, which is dumb... but whatever.
+ // 16-bit hashes are simply too narrow for large hashtables; more mask bits than hash bits!
+ // So we duplicate the hash bits. (Note: h *= MASK_HASH+2 is the same as h += h<<HASH_BITS)
+ typedef typename CTypeSelect< INT16_STORAGE, int16, undefined_t >::type uint32_if16BitStorage;
+ typedef typename CTypeSelect< INT16_STORAGE, undefined_t, int32 >::type uint32_if32BitStorage;
+ static FORCEINLINE uint32 IdealIndex( uint32_if16BitStorage h, uint32 m ) { h &= MASK_HASH; h *= MASK_HASH + 2; return h & m; }
+ static FORCEINLINE uint32 IdealIndex( uint32_if32BitStorage h, uint32 m ) { return h & m; }
+
+ // More efficient than memcpy for the small types that are stored in a hashtable
+ void MoveDataFrom( CUtlHashtableEntry &src )
+ {
+ storage_t * RESTRICT srcData = &src.data[0];
+ for ( int i = 0; i < ARRAYSIZE( data ); ++i ) { data[i] = srcData[i]; }
+ }
+};
+
+template <typename KeyT, typename ValueT = empty_t, typename KeyHashT = DefaultHashFunctor<KeyT>, typename KeyIsEqualT = DefaultEqualFunctor<KeyT>, typename AlternateKeyT = typename ArgumentTypeInfo<KeyT>::Alt_t >
+class CUtlHashtable
+{
+public:
+ typedef UtlHashHandle_t handle_t;
+
+protected:
+ typedef CUtlKeyValuePair<KeyT, ValueT> KVPair;
+ typedef typename ArgumentTypeInfo<KeyT>::Arg_t KeyArg_t;
+ typedef typename ArgumentTypeInfo<ValueT>::Arg_t ValueArg_t;
+ typedef typename ArgumentTypeInfo<AlternateKeyT>::Arg_t KeyAlt_t;
+ typedef CUtlHashtableEntry< KeyT, ValueT > entry_t;
+
+ enum { FLAG_FREE = entry_t::FLAG_FREE };
+ enum { FLAG_LAST = entry_t::FLAG_LAST };
+ enum { MASK_HASH = entry_t::MASK_HASH };
+
+ CUtlMemory< entry_t > m_table;
+ int m_nUsed;
+ int m_nMinSize;
+ bool m_bSizeLocked;
+ KeyIsEqualT m_eq;
+ KeyHashT m_hash;
+
+ // Allocate an empty table and then re-insert all existing entries.
+ void DoRealloc( int size );
+
+ // Move an existing entry to a free slot, leaving a hole behind
+ void BumpEntry( unsigned int idx );
+
+ // Insert an unconstructed KVPair at the primary slot
+ int DoInsertUnconstructed( unsigned int h, bool allowGrow );
+
+ // Implementation for Insert functions, constructs a KVPair
+ // with either a default-construted or copy-constructed value
+ template <typename KeyParamT> handle_t DoInsert( KeyParamT k, unsigned int h );
+ template <typename KeyParamT> handle_t DoInsert( KeyParamT k, typename ArgumentTypeInfo<ValueT>::Arg_t v, unsigned int h, bool* pDidInsert );
+ template <typename KeyParamT> handle_t DoInsertNoCheck( KeyParamT k, typename ArgumentTypeInfo<ValueT>::Arg_t v, unsigned int h );
+
+ // Key lookup. Can also return previous-in-chain if result is chained.
+ template <typename KeyParamT> handle_t DoLookup( KeyParamT x, unsigned int h, handle_t *pPreviousInChain ) const;
+
+ // Remove single element by key + hash. Returns the index of the new hole
+ // that was created. Returns InvalidHandle() if element was not found.
+ template <typename KeyParamT> int DoRemove( KeyParamT x, unsigned int h );
+
+ // Friend CUtlStableHashtable so that it can call our Do* functions directly
+ template < typename K, typename V, typename S, typename H, typename E, typename A > friend class CUtlStableHashtable;
+
+public:
+ explicit CUtlHashtable( int minimumSize = 32 )
+ : m_nUsed(0), m_nMinSize(MAX(8, minimumSize)), m_bSizeLocked(false), m_eq(), m_hash() { }
+
+ CUtlHashtable( int minimumSize, const KeyHashT &hash, KeyIsEqualT const &eq = KeyIsEqualT() )
+ : m_nUsed(0), m_nMinSize(MAX(8, minimumSize)), m_bSizeLocked(false), m_eq(eq), m_hash(hash) { }
+
+ CUtlHashtable( entry_t* pMemory, unsigned int nCount, const KeyHashT &hash = KeyHashT(), KeyIsEqualT const &eq = KeyIsEqualT() )
+ : m_nUsed(0), m_nMinSize(8), m_bSizeLocked(false), m_eq(eq), m_hash(hash) { SetExternalBuffer( pMemory, nCount ); }
+
+ ~CUtlHashtable() { RemoveAll(); }
+
+ CUtlHashtable &operator=( CUtlHashtable const &src );
+
+ // Set external memory
+ void SetExternalBuffer( byte* pRawBuffer, unsigned int nBytes, bool bAssumeOwnership = false, bool bGrowable = false );
+ void SetExternalBuffer( entry_t* pBuffer, unsigned int nSize, bool bAssumeOwnership = false, bool bGrowable = false );
+
+ // Functor/function-pointer access
+ KeyHashT& GetHashRef() { return m_hash; }
+ KeyIsEqualT& GetEqualRef() { return m_eq; }
+ KeyHashT const &GetHashRef() const { return m_hash; }
+ KeyIsEqualT const &GetEqualRef() const { return m_eq; }
+
+ // Handle validation
+ bool IsValidHandle( handle_t idx ) const { return (unsigned)idx < (unsigned)m_table.Count() && m_table[idx].IsValid(); }
+ static handle_t InvalidHandle() { return (handle_t) -1; }
+
+ // Iteration functions
+ handle_t FirstHandle() const { return NextHandle( (handle_t) -1 ); }
+ handle_t NextHandle( handle_t start ) const;
+
+ // Returns the number of unique keys in the table
+ int Count() const { return m_nUsed; }
+
+
+ // Key lookup, returns InvalidHandle() if not found
+ handle_t Find( KeyArg_t k ) const { return DoLookup<KeyArg_t>( k, m_hash(k), NULL ); }
+ handle_t Find( KeyArg_t k, unsigned int hash) const { Assert( hash == m_hash(k) ); return DoLookup<KeyArg_t>( k, hash, NULL ); }
+ // Alternate-type key lookup, returns InvalidHandle() if not found
+ handle_t Find( KeyAlt_t k ) const { return DoLookup<KeyAlt_t>( k, m_hash(k), NULL ); }
+ handle_t Find( KeyAlt_t k, unsigned int hash) const { Assert( hash == m_hash(k) ); return DoLookup<KeyAlt_t>( k, hash, NULL ); }
+
+ // True if the key is in the table
+ bool HasElement( KeyArg_t k ) const { return InvalidHandle() != Find( k ); }
+ bool HasElement( KeyAlt_t k ) const { return InvalidHandle() != Find( k ); }
+
+ // Key insertion or lookup, always returns a valid handle
+ handle_t Insert( KeyArg_t k ) { return DoInsert<KeyArg_t>( k, m_hash(k) ); }
+ handle_t Insert( KeyArg_t k, ValueArg_t v, bool *pDidInsert = NULL ) { return DoInsert<KeyArg_t>( k, v, m_hash(k), pDidInsert ); }
+ handle_t Insert( KeyArg_t k, ValueArg_t v, unsigned int hash, bool *pDidInsert = NULL ) { Assert( hash == m_hash(k) ); return DoInsert<KeyArg_t>( k, v, hash, pDidInsert ); }
+ // Alternate-type key insertion or lookup, always returns a valid handle
+ handle_t Insert( KeyAlt_t k ) { return DoInsert<KeyAlt_t>( k, m_hash(k) ); }
+ handle_t Insert( KeyAlt_t k, ValueArg_t v, bool *pDidInsert = NULL ) { return DoInsert<KeyAlt_t>( k, v, m_hash(k), pDidInsert ); }
+ handle_t Insert( KeyAlt_t k, ValueArg_t v, unsigned int hash, bool *pDidInsert = NULL ) { Assert( hash == m_hash(k) ); return DoInsert<KeyAlt_t>( k, v, hash, pDidInsert ); }
+
+ // Key removal, returns false if not found
+ bool Remove( KeyArg_t k ) { return DoRemove<KeyArg_t>( k, m_hash(k) ) >= 0; }
+ bool Remove( KeyArg_t k, unsigned int hash ) { Assert( hash == m_hash(k) ); return DoRemove<KeyArg_t>( k, hash ) >= 0; }
+ // Alternate-type key removal, returns false if not found
+ bool Remove( KeyAlt_t k ) { return DoRemove<KeyAlt_t>( k, m_hash(k) ) >= 0; }
+ bool Remove( KeyAlt_t k, unsigned int hash ) { Assert( hash == m_hash(k) ); return DoRemove<KeyAlt_t>( k, hash ) >= 0; }
+
+ // Remove while iterating, returns the next handle for forward iteration
+ // Note: aside from this, ALL handles are invalid if an element is removed
+ handle_t RemoveAndAdvance( handle_t idx );
+
+ // Nuke contents
+ void RemoveAll();
+
+ // Nuke and release memory.
+ void Purge() { RemoveAll(); m_table.Purge(); }
+
+ // Reserve table capacity up front to avoid reallocation during insertions
+ void Reserve( int expected ) { if ( expected > m_nUsed ) DoRealloc( expected * 4 / 3 ); }
+
+ // Shrink to best-fit size, re-insert keys for optimal lookup
+ void Compact( bool bMinimal ) { DoRealloc( bMinimal ? m_nUsed : ( m_nUsed * 4 / 3 ) ); }
+
+ // Access functions. Note: if ValueT is empty_t, all functions return const keys.
+ typedef typename KVPair::ValueReturn_t Element_t;
+ KeyT const &Key( handle_t idx ) const { return m_table[idx]->m_key; }
+ Element_t const &Element( handle_t idx ) const { return m_table[idx]->GetValue(); }
+ Element_t &Element(handle_t idx) { return m_table[idx]->GetValue(); }
+ Element_t const &operator[]( handle_t idx ) const { return m_table[idx]->GetValue(); }
+ Element_t &operator[]( handle_t idx ) { return m_table[idx]->GetValue(); }
+
+ void ReplaceKey( handle_t idx, KeyArg_t k ) { Assert( m_eq( m_table[idx]->m_key, k ) && m_hash( k ) == m_hash( m_table[idx]->m_key ) ); m_table[idx]->m_key = k; }
+ void ReplaceKey( handle_t idx, KeyAlt_t k ) { Assert( m_eq( m_table[idx]->m_key, k ) && m_hash( k ) == m_hash( m_table[idx]->m_key ) ); m_table[idx]->m_key = k; }
+
+ Element_t const &Get( KeyArg_t k, Element_t const &defaultValue ) const { handle_t h = Find( k ); if ( h != InvalidHandle() ) return Element( h ); return defaultValue; }
+ Element_t const &Get( KeyAlt_t k, Element_t const &defaultValue ) const { handle_t h = Find( k ); if ( h != InvalidHandle() ) return Element( h ); return defaultValue; }
+
+ Element_t const *GetPtr( KeyArg_t k ) const { handle_t h = Find(k); if ( h != InvalidHandle() ) return &Element( h ); return NULL; }
+ Element_t const *GetPtr( KeyAlt_t k ) const { handle_t h = Find(k); if ( h != InvalidHandle() ) return &Element( h ); return NULL; }
+ Element_t *GetPtr( KeyArg_t k ) { handle_t h = Find( k ); if ( h != InvalidHandle() ) return &Element( h ); return NULL; }
+ Element_t *GetPtr( KeyAlt_t k ) { handle_t h = Find( k ); if ( h != InvalidHandle() ) return &Element( h ); return NULL; }
+
+ // Swap memory and contents with another identical hashtable
+ // (NOTE: if using function pointers or functors with state,
+ // it is up to the caller to ensure that they are compatible!)
+ void Swap( CUtlHashtable &other ) { m_table.Swap(other.m_table); ::V_swap(m_nUsed, other.m_nUsed); }
+
+#if _DEBUG
+ // Validate the integrity of the hashtable
+ void DbgCheckIntegrity() const;
+#endif
+
+private:
+ CUtlHashtable(const CUtlHashtable& copyConstructorIsNotImplemented);
+};
+
+
+// Set external memory (raw byte buffer, best-fit)
+template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
+void CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::SetExternalBuffer( byte* pRawBuffer, unsigned int nBytes, bool bAssumeOwnership, bool bGrowable )
+{
+ Assert( ((uintptr_t)pRawBuffer % __alignof(int)) == 0 );
+ uint32 bestSize = LargestPowerOfTwoLessThanOrEqual( nBytes / sizeof(entry_t) );
+ Assert( bestSize != 0 && bestSize*sizeof(entry_t) <= nBytes );
+
+ return SetExternalBuffer( (entry_t*) pRawBuffer, bestSize, bAssumeOwnership, bGrowable );
+}
+
+// Set external memory (typechecked, must be power of two)
+template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
+void CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::SetExternalBuffer( entry_t* pBuffer, unsigned int nSize, bool bAssumeOwnership, bool bGrowable )
+{
+ Assert( IsPowerOfTwo(nSize) );
+ Assert( m_nUsed == 0 );
+ for ( uint i = 0; i < nSize; ++i )
+ pBuffer[i].MarkInvalid();
+ if ( bAssumeOwnership )
+ m_table.AssumeMemory( pBuffer, nSize );
+ else
+ m_table.SetExternalBuffer( pBuffer, nSize );
+ m_bSizeLocked = !bGrowable;
+}
+
+// Allocate an empty table and then re-insert all existing entries.
+template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
+void CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::DoRealloc( int size )
+{
+ Assert( !m_bSizeLocked );
+
+ size = SmallestPowerOfTwoGreaterOrEqual( MAX( m_nMinSize, size ) );
+ Assert( size > 0 && (uint)size <= entry_t::IdealIndex( ~0, 0x1FFFFFFF ) ); // reasonable power of 2
+ Assert( size > m_nUsed );
+
+ CUtlMemory<entry_t> oldTable;
+ oldTable.Swap( m_table );
+ entry_t * RESTRICT const pOldBase = oldTable.Base();
+
+ m_table.EnsureCapacity( size );
+ entry_t * const pNewBase = m_table.Base();
+ for ( int i = 0; i < size; ++i )
+ pNewBase[i].MarkInvalid();
+
+ int nLeftToMove = m_nUsed;
+ m_nUsed = 0;
+ for ( int i = oldTable.Count() - 1; i >= 0; --i )
+ {
+ if ( pOldBase[i].IsValid() )
+ {
+ int newIdx = DoInsertUnconstructed( pOldBase[i].flags_and_hash, false );
+ pNewBase[newIdx].MoveDataFrom( pOldBase[i] );
+ if ( --nLeftToMove == 0 )
+ break;
+ }
+ }
+ Assert( nLeftToMove == 0 );
+}
+
+
+// Move an existing entry to a free slot, leaving a hole behind
+template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
+void CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::BumpEntry( unsigned int idx )
+{
+ Assert( m_table[idx].IsValid() );
+ Assert( m_nUsed < m_table.Count() );
+
+ entry_t* table = m_table.Base();
+ unsigned int slotmask = m_table.Count()-1;
+ unsigned int new_flags_and_hash = table[idx].flags_and_hash & (FLAG_LAST | MASK_HASH);
+
+ unsigned int chainid = entry_t::IdealIndex( new_flags_and_hash, slotmask );
+
+ // Look for empty slots scanning forward, stripping FLAG_LAST as we go.
+ // Note: this potentially strips FLAG_LAST from table[idx] if we pass it
+ int newIdx = chainid; // start at ideal slot
+ for ( ; ; newIdx = (newIdx + 1) & slotmask )
+ {
+ if ( table[newIdx].IdealIndex( slotmask ) == chainid )
+ {
+ if ( table[newIdx].flags_and_hash & FLAG_LAST )
+ {
+ table[newIdx].flags_and_hash &= ~FLAG_LAST;
+ new_flags_and_hash |= FLAG_LAST;
+ }
+ continue;
+ }
+ if ( table[newIdx].IsValid() )
+ {
+ continue;
+ }
+ break;
+ }
+
+ // Did we pick something closer to the ideal slot, leaving behind a
+ // FLAG_LAST bit on the current slot because we didn't scan past it?
+ if ( table[idx].flags_and_hash & FLAG_LAST )
+ {
+#ifdef _DEBUG
+ Assert( new_flags_and_hash & FLAG_LAST );
+ // Verify logic: we must have moved to an earlier slot, right?
+ uint offset = ((uint)idx - chainid + slotmask + 1) & slotmask;
+ uint newOffset = ((uint)newIdx - chainid + slotmask + 1) & slotmask;
+ Assert( newOffset < offset );
+#endif
+ // Scan backwards from old to new location, depositing FLAG_LAST on
+ // the first match we find. (+slotmask) is the same as (-1) without
+ // having to make anyone think about two's complement shenanigans.
+ int scan = (idx + slotmask) & slotmask;
+ while ( scan != newIdx )
+ {
+ if ( table[scan].IdealIndex( slotmask ) == chainid )
+ {
+ table[scan].flags_and_hash |= FLAG_LAST;
+ new_flags_and_hash &= ~FLAG_LAST;
+ break;
+ }
+ scan = (scan + slotmask) & slotmask;
+ }
+ }
+
+ // Move entry to the free slot we found, leaving a hole at idx
+ table[newIdx].flags_and_hash = new_flags_and_hash;
+ table[newIdx].MoveDataFrom( table[idx] );
+ table[idx].MarkInvalid();
+}
+
+
+// Insert a value at the root position for that value's hash chain.
+template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
+int CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::DoInsertUnconstructed( unsigned int h, bool allowGrow )
+{
+ if ( allowGrow && !m_bSizeLocked )
+ {
+ // Keep the load factor between .25 and .75
+ int newSize = m_nUsed + 1;
+ if ( ( newSize*4 < m_table.Count() && m_table.Count() > m_nMinSize*2 ) || newSize*4 > m_table.Count()*3 )
+ {
+ DoRealloc( newSize * 4 / 3 );
+ }
+ }
+ Assert( m_nUsed < m_table.Count() );
+ ++m_nUsed;
+
+ entry_t* table = m_table.Base();
+ unsigned int slotmask = m_table.Count()-1;
+ unsigned int new_flags_and_hash = FLAG_LAST | (h & MASK_HASH);
+ unsigned int idx = entry_t::IdealIndex( h, slotmask );
+ if ( table[idx].IdealIndex( slotmask ) == idx )
+ {
+ // There is already an entry in this chain.
+ new_flags_and_hash &= ~FLAG_LAST;
+ BumpEntry(idx);
+ }
+ else if ( table[idx].IsValid() )
+ {
+ // Somebody else is living in our ideal index but does not belong
+ // to our entry chain; move it out of the way, start a new chain.
+ BumpEntry(idx);
+ }
+ table[idx].flags_and_hash = new_flags_and_hash;
+ return idx;
+}
+
+
+// Key lookup. Can also return previous-in-chain if result is a chained slot.
+template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
+template <typename KeyParamT>
+UtlHashHandle_t CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::DoLookup( KeyParamT x, unsigned int h, handle_t *pPreviousInChain ) const
+{
+ if ( m_nUsed == 0 )
+ {
+ // Empty table.
+ return (handle_t) -1;
+ }
+
+ const entry_t* table = m_table.Base();
+ unsigned int slotmask = m_table.Count()-1;
+ Assert( m_table.Count() > 0 && (slotmask & m_table.Count()) == 0 );
+ unsigned int chainid = entry_t::IdealIndex( h, slotmask );
+
+ unsigned int idx = chainid;
+ if ( table[idx].IdealIndex( slotmask ) != chainid )
+ {
+ // Nothing in root position? No match.
+ return (handle_t) -1;
+ }
+
+ // Linear scan until found or end of chain
+ handle_t lastIdx = (handle_t) -1;
+ while (1)
+ {
+ // Only examine this slot if it is valid and belongs to our hash chain
+ if ( table[idx].IdealIndex( slotmask ) == chainid )
+ {
+ // Test the full-width hash to avoid unnecessary calls to m_eq()
+ if ( ((table[idx].flags_and_hash ^ h) & MASK_HASH) == 0 && m_eq( table[idx]->m_key, x ) )
+ {
+ // Found match!
+ if (pPreviousInChain)
+ *pPreviousInChain = lastIdx;
+
+ return (handle_t) idx;
+ }
+
+ if ( table[idx].flags_and_hash & FLAG_LAST )
+ {
+ // End of chain. No match.
+ return (handle_t) -1;
+ }
+
+ lastIdx = (handle_t) idx;
+ }
+ idx = (idx + 1) & slotmask;
+ }
+}
+
+
+// Key insertion, or return index of existing key if found
+template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
+template <typename KeyParamT>
+UtlHashHandle_t CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::DoInsert( KeyParamT k, unsigned int h )
+{
+ handle_t idx = DoLookup<KeyParamT>( k, h, NULL );
+ if ( idx == (handle_t) -1 )
+ {
+ idx = (handle_t) DoInsertUnconstructed( h, true );
+ ConstructOneArg( m_table[ idx ].Raw(), k );
+ }
+ return idx;
+}
+
+// Key insertion, or return index of existing key if found
+template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
+template <typename KeyParamT>
+UtlHashHandle_t CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::DoInsert( KeyParamT k, typename ArgumentTypeInfo<ValueT>::Arg_t v, unsigned int h, bool *pDidInsert )
+{
+ handle_t idx = DoLookup<KeyParamT>( k, h, NULL );
+ if ( idx == (handle_t) -1 )
+ {
+ idx = (handle_t) DoInsertUnconstructed( h, true );
+ ConstructTwoArg( m_table[ idx ].Raw(), k, v );
+ if ( pDidInsert ) *pDidInsert = true;
+ }
+ else
+ {
+ if ( pDidInsert ) *pDidInsert = false;
+ }
+ return idx;
+}
+
+// Key insertion
+template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
+template <typename KeyParamT>
+UtlHashHandle_t CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::DoInsertNoCheck( KeyParamT k, typename ArgumentTypeInfo<ValueT>::Arg_t v, unsigned int h )
+{
+ Assert( DoLookup<KeyParamT>( k, h, NULL ) == (handle_t) -1 );
+ handle_t idx = (handle_t) DoInsertUnconstructed( h, true );
+ ConstructTwoArg( m_table[ idx ].Raw(), k, v );
+ return idx;
+}
+
+
+// Remove single element by key + hash. Returns the location of the new empty hole.
+template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
+template <typename KeyParamT>
+int CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::DoRemove( KeyParamT x, unsigned int h )
+{
+ unsigned int slotmask = m_table.Count()-1;
+ handle_t previous = (handle_t) -1;
+ int idx = (int) DoLookup<KeyParamT>( x, h, &previous );
+ if (idx == -1)
+ {
+ return -1;
+ }
+
+ enum { FAKEFLAG_ROOT = 1 };
+ int nLastAndRootFlags = m_table[idx].flags_and_hash & FLAG_LAST;
+ nLastAndRootFlags |= ( (uint)idx == m_table[idx].IdealIndex( slotmask ) );
+
+ // Remove from table
+ m_table[idx].MarkInvalid();
+ Destruct( m_table[idx].Raw() );
+ --m_nUsed;
+
+ if ( nLastAndRootFlags == FLAG_LAST ) // last only, not root
+ {
+ // This was the end of the chain - mark previous as last.
+ // (This isn't the root, so there must be a previous.)
+ Assert( previous != (handle_t) -1 );
+ m_table[previous].flags_and_hash |= FLAG_LAST;
+ }
+
+ if ( nLastAndRootFlags == FAKEFLAG_ROOT ) // root only, not last
+ {
+ // If we are removing the root and there is more to the chain,
+ // scan to find the next chain entry and move it to the root.
+ unsigned int chainid = entry_t::IdealIndex( h, slotmask );
+ unsigned int nextIdx = idx;
+ while (1)
+ {
+ nextIdx = (nextIdx + 1) & slotmask;
+ if ( m_table[nextIdx].IdealIndex( slotmask ) == chainid )
+ {
+ break;
+ }
+ }
+ Assert( !(m_table[nextIdx].flags_and_hash & FLAG_FREE) );
+
+ // Leave a hole where the next entry in the chain was.
+ m_table[idx].flags_and_hash = m_table[nextIdx].flags_and_hash;
+ m_table[idx].MoveDataFrom( m_table[nextIdx] );
+ m_table[nextIdx].MarkInvalid();
+ return nextIdx;
+ }
+
+ // The hole is still where the element used to be.
+ return idx;
+}
+
+
+// Assignment operator. It's up to the user to make sure that the hash and equality functors match.
+template <typename K, typename V, typename H, typename E, typename A>
+CUtlHashtable<K,V,H,E,A> &CUtlHashtable<K,V,H,E,A>::operator=( CUtlHashtable<K,V,H,E,A> const &src )
+{
+ if ( &src != this )
+ {
+ Assert( !m_bSizeLocked || m_table.Count() >= src.m_nUsed );
+ if ( !m_bSizeLocked )
+ {
+ Purge();
+ Reserve(src.m_nUsed);
+ }
+ else
+ {
+ RemoveAll();
+ }
+
+ const entry_t * srcTable = src.m_table.Base();
+ for ( int i = src.m_table.Count() - 1; i >= 0; --i )
+ {
+ if ( srcTable[i].IsValid() )
+ {
+ // If this assert trips, double-check that both hashtables
+ // have the same hash function pointers or hash functor state!
+ Assert( m_hash(srcTable[i]->m_key) == src.m_hash(srcTable[i]->m_key) );
+ int newIdx = DoInsertUnconstructed( srcTable[i].flags_and_hash , false );
+ CopyConstruct( m_table[newIdx].Raw(), *srcTable[i].Raw() ); // copy construct KVPair
+ }
+ }
+ }
+ return *this;
+}
+
+// Remove and return the next valid iterator for a forward iteration.
+template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
+UtlHashHandle_t CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::RemoveAndAdvance( UtlHashHandle_t idx )
+{
+ Assert( IsValidHandle( idx ) );
+
+ // TODO optimize, implement DoRemoveAt that does not need to re-evaluate equality in DoLookup
+ int hole = DoRemove< KeyArg_t >( m_table[idx]->m_key, m_table[idx].flags_and_hash & MASK_HASH );
+ // DoRemove returns the index of the element that it moved to fill the hole, if any.
+ if ( hole <= (int) idx )
+ {
+ // Didn't fill, or filled from a previously seen element.
+ return NextHandle( idx );
+ }
+ else
+ {
+ // Do not advance; slot has a new un-iterated value.
+ Assert( IsValidHandle(idx) );
+ return idx;
+ }
+}
+
+// Burn it with fire.
+template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
+void CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::RemoveAll()
+{
+ int used = m_nUsed;
+ if ( used != 0 )
+ {
+ entry_t* table = m_table.Base();
+ for ( int i = m_table.Count() - 1; i >= 0; --i )
+ {
+ if ( table[i].IsValid() )
+ {
+ table[i].MarkInvalid();
+ Destruct( table[i].Raw() );
+ if ( --used == 0 )
+ break;
+ }
+ }
+ m_nUsed = 0;
+ }
+}
+
+template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
+UtlHashHandle_t CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::NextHandle( handle_t start ) const
+{
+ const entry_t *table = m_table.Base();
+ for ( int i = (int)start + 1; i < m_table.Count(); ++i )
+ {
+ if ( table[i].IsValid() )
+ return (handle_t) i;
+ }
+ return (handle_t) -1;
+}
+
+
+#if _DEBUG
+template <typename KeyT, typename ValueT, typename KeyHashT, typename KeyIsEqualT, typename AltKeyT>
+void CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT>::DbgCheckIntegrity() const
+{
+ // Stress test the hash table as a test of both container functionality
+ // and also the validity of the user's Hash and Equal function objects.
+ // NOTE: will fail if function objects require any sort of state!
+ CUtlHashtable clone;
+ unsigned int bytes = sizeof(entry_t)*max(16,m_table.Count());
+ byte* tempbuf = (byte*) malloc(bytes);
+ clone.SetExternalBuffer( tempbuf, bytes, false, false );
+ clone = *this;
+
+ int count = 0, roots = 0, ends = 0;
+ int slotmask = m_table.Count() - 1;
+ for (int i = 0; i < m_table.Count(); ++i)
+ {
+ if (!(m_table[i].flags_and_hash & FLAG_FREE)) ++count;
+ if (m_table[i].IdealIndex(slotmask) == (uint)i) ++roots;
+ if (m_table[i].flags_and_hash & FLAG_LAST) ++ends;
+ if (m_table[i].IsValid())
+ {
+ Assert( Find(m_table[i]->m_key) == (handle_t)i );
+ Verify( clone.Remove(m_table[i]->m_key) );
+ }
+ else
+ {
+ Assert( m_table[i].flags_and_hash == FLAG_FREE );
+ }
+ }
+ Assert( count == Count() && count >= roots && roots == ends );
+ Assert( clone.Count() == 0 );
+ clone.Purge();
+ free(tempbuf);
+}
+#endif
+
+//-----------------------------------------------------------------------
+// CUtlStableHashtable
+//-----------------------------------------------------------------------
+
+// Stable hashtables are less memory and cache efficient, but can be
+// iterated quickly and their element handles are completely stable.
+// Implemented as a hashtable which only stores indices, and a separate
+// CUtlLinkedList data table which contains key-value pairs; this may
+// change to a more efficient structure in the future if space becomes
+// critical. I have some ideas about that but not the time to implement
+// at the moment. -henryg
+
+// Note: RemoveAndAdvance is slower than in CUtlHashtable because the
+// key needs to be re-hashed under the current implementation.
+
+template <typename KeyT, typename ValueT = empty_t, typename KeyHashT = DefaultHashFunctor<KeyT>, typename KeyIsEqualT = DefaultEqualFunctor<KeyT>, typename IndexStorageT = uint16, typename AlternateKeyT = typename ArgumentTypeInfo<KeyT>::Alt_t >
+class CUtlStableHashtable
+{
+public:
+ typedef typename ArgumentTypeInfo<KeyT>::Arg_t KeyArg_t;
+ typedef typename ArgumentTypeInfo<ValueT>::Arg_t ValueArg_t;
+ typedef typename ArgumentTypeInfo<AlternateKeyT>::Arg_t KeyAlt_t;
+ typedef typename CTypeSelect< sizeof( IndexStorageT ) == 2, uint16, uint32 >::type IndexStorage_t;
+
+protected:
+ COMPILE_TIME_ASSERT( sizeof( IndexStorage_t ) == sizeof( IndexStorageT ) );
+
+ typedef CUtlKeyValuePair< KeyT, ValueT > KVPair;
+ struct HashProxy;
+ struct EqualProxy;
+ struct IndirectIndex;
+
+ typedef CUtlHashtable< IndirectIndex, empty_t, HashProxy, EqualProxy, AlternateKeyT > Hashtable_t;
+ typedef CUtlLinkedList< KVPair, IndexStorage_t > LinkedList_t;
+
+ template <typename KeyArgumentT> bool DoRemove( KeyArgumentT k );
+ template <typename KeyArgumentT> UtlHashHandle_t DoFind( KeyArgumentT k ) const;
+ template <typename KeyArgumentT> UtlHashHandle_t DoInsert( KeyArgumentT k );
+ template <typename KeyArgumentT, typename ValueArgumentT> UtlHashHandle_t DoInsert( KeyArgumentT k, ValueArgumentT v );
+
+public:
+
+ KeyHashT &GetHashRef() { return m_table.GetHashRef().m_hash; }
+ KeyIsEqualT &GetEqualRef() { return m_table.GetEqualRef().m_eq; }
+ KeyHashT const &GetHashRef() const { return m_table.GetHashRef().m_hash; }
+ KeyIsEqualT const &GetEqualRef() const { return m_table.GetEqualRef().m_eq; }
+
+ UtlHashHandle_t Insert( KeyArg_t k ) { return DoInsert<KeyArg_t>( k ); }
+ UtlHashHandle_t Insert( KeyAlt_t k ) { return DoInsert<KeyAlt_t>( k ); }
+ UtlHashHandle_t Insert( KeyArg_t k, ValueArg_t v ) { return DoInsert<KeyArg_t, ValueArg_t>( k, v ); }
+ UtlHashHandle_t Insert( KeyAlt_t k, ValueArg_t v ) { return DoInsert<KeyAlt_t, ValueArg_t>( k, v ); }
+ UtlHashHandle_t Find( KeyArg_t k ) const { return DoFind<KeyArg_t>( k ); }
+ UtlHashHandle_t Find( KeyAlt_t k ) const { return DoFind<KeyAlt_t>( k ); }
+ bool Remove( KeyArg_t k ) { return DoRemove<KeyArg_t>( k ); }
+ bool Remove( KeyAlt_t k ) { return DoRemove<KeyAlt_t>( k ); }
+
+ void RemoveAll() { m_table.RemoveAll(); m_data.RemoveAll(); }
+ void Purge() { m_table.Purge(); m_data.Purge(); }
+ int Count() const { return m_table.Count(); }
+
+ typedef typename KVPair::ValueReturn_t Element_t;
+ KeyT const &Key( UtlHashHandle_t idx ) const { return m_data[idx].m_key; }
+ Element_t const &Element( UtlHashHandle_t idx ) const { return m_data[idx].GetValue(); }
+ Element_t &Element( UtlHashHandle_t idx ) { return m_data[idx].GetValue(); }
+ Element_t const &operator[]( UtlHashHandle_t idx ) const { return m_data[idx].GetValue(); }
+ Element_t &operator[]( UtlHashHandle_t idx ) { return m_data[idx].GetValue(); }
+
+ void ReplaceKey( UtlHashHandle_t idx, KeyArg_t k ) { Assert( GetEqualRef()( m_data[idx].m_key, k ) && GetHashRef()( k ) == GetHashRef()( m_data[idx].m_key ) ); m_data[idx].m_key = k; }
+ void ReplaceKey( UtlHashHandle_t idx, KeyAlt_t k ) { Assert( GetEqualRef()( m_data[idx].m_key, k ) && GetHashRef()( k ) == GetHashRef()( m_data[idx].m_key ) ); m_data[idx].m_key = k; }
+
+ Element_t const &Get( KeyArg_t k, Element_t const &defaultValue ) const { UtlHashHandle_t h = Find( k ); if ( h != InvalidHandle() ) return Element( h ); return defaultValue; }
+ Element_t const &Get( KeyAlt_t k, Element_t const &defaultValue ) const { UtlHashHandle_t h = Find( k ); if ( h != InvalidHandle() ) return Element( h ); return defaultValue; }
+
+ Element_t const *GetPtr( KeyArg_t k ) const { UtlHashHandle_t h = Find(k); if ( h != InvalidHandle() ) return &Element( h ); return NULL; }
+ Element_t const *GetPtr( KeyAlt_t k ) const { UtlHashHandle_t h = Find(k); if ( h != InvalidHandle() ) return &Element( h ); return NULL; }
+ Element_t *GetPtr( KeyArg_t k ) { UtlHashHandle_t h = Find( k ); if ( h != InvalidHandle() ) return &Element( h ); return NULL; }
+ Element_t *GetPtr( KeyAlt_t k ) { UtlHashHandle_t h = Find( k ); if ( h != InvalidHandle() ) return &Element( h ); return NULL; }
+
+ UtlHashHandle_t FirstHandle() const { return ExtendInvalidHandle( m_data.Head() ); }
+ UtlHashHandle_t NextHandle( UtlHashHandle_t h ) const { return ExtendInvalidHandle( m_data.Next( h ) ); }
+ bool IsValidHandle( UtlHashHandle_t h ) const { return m_data.IsValidIndex( h ); }
+ UtlHashHandle_t InvalidHandle() const { return (UtlHashHandle_t)-1; }
+
+ UtlHashHandle_t RemoveAndAdvance( UtlHashHandle_t h )
+ {
+ Assert( m_data.IsValidIndex( h ) );
+ m_table.Remove( IndirectIndex( h ) );
+ IndexStorage_t next = m_data.Next( h );
+ m_data.Remove( h );
+ return ExtendInvalidHandle(next);
+ }
+
+ void Compact( bool bMinimal ) { m_table.Compact( bMinimal ); /*m_data.Compact();*/ }
+
+ void Swap( CUtlStableHashtable &other )
+ {
+ m_table.Swap(other.m_table);
+ // XXX swapping CUtlLinkedList by block memory swap, ugh
+ char buf[ sizeof(m_data) ];
+ memcpy( buf, &m_data, sizeof(m_data) );
+ memcpy( &m_data, &other.m_data, sizeof(m_data) );
+ memcpy( &other.m_data, buf, sizeof(m_data) );
+ }
+
+
+protected:
+ // Perform extension of 0xFFFF to 0xFFFFFFFF if necessary. Note: ( a < CONSTANT ) ? 0 : -1 is usually branchless
+ static UtlHashHandle_t ExtendInvalidHandle( uint32 x ) { return x; }
+ static UtlHashHandle_t ExtendInvalidHandle( uint16 x ) { uint32 a = x; return a | ( ( a < 0xFFFFu ) ? 0 : -1 ); }
+
+ struct IndirectIndex
+ {
+ explicit IndirectIndex(IndexStorage_t i) : m_index(i) { }
+ IndexStorage_t m_index;
+ };
+
+ struct HashProxy
+ {
+ KeyHashT m_hash;
+ unsigned int operator()( IndirectIndex idx ) const
+ {
+ const ptrdiff_t tableoffset = (uintptr_t)(&((Hashtable_t*)1024)->GetHashRef()) - 1024;
+ const ptrdiff_t owneroffset = offsetof(CUtlStableHashtable, m_table) + tableoffset;
+ CUtlStableHashtable* pOwner = (CUtlStableHashtable*)((uintptr_t)this - owneroffset);
+ return m_hash( pOwner->m_data[ idx.m_index ].m_key );
+ }
+ unsigned int operator()( KeyArg_t k ) const { return m_hash( k ); }
+ unsigned int operator()( KeyAlt_t k ) const { return m_hash( k ); }
+ };
+
+ struct EqualProxy
+ {
+ KeyIsEqualT m_eq;
+ unsigned int operator()( IndirectIndex lhs, IndirectIndex rhs ) const
+ {
+ return lhs.m_index == rhs.m_index;
+ }
+ unsigned int operator()( IndirectIndex lhs, KeyArg_t rhs ) const
+ {
+ const ptrdiff_t tableoffset = (uintptr_t)(&((Hashtable_t*)1024)->GetEqualRef()) - 1024;
+ const ptrdiff_t owneroffset = offsetof(CUtlStableHashtable, m_table) + tableoffset;
+ CUtlStableHashtable* pOwner = (CUtlStableHashtable*)((uintptr_t)this - owneroffset);
+ return m_eq( pOwner->m_data[ lhs.m_index ].m_key, rhs );
+ }
+ unsigned int operator()( IndirectIndex lhs, KeyAlt_t rhs ) const
+ {
+ const ptrdiff_t tableoffset = (uintptr_t)(&((Hashtable_t*)1024)->GetEqualRef()) - 1024;
+ const ptrdiff_t owneroffset = offsetof(CUtlStableHashtable, m_table) + tableoffset;
+ CUtlStableHashtable* pOwner = (CUtlStableHashtable*)((uintptr_t)this - owneroffset);
+ return m_eq( pOwner->m_data[ lhs.m_index ].m_key, rhs );
+ }
+ };
+
+ class CCustomLinkedList : public LinkedList_t
+ {
+ public:
+ int AddToTailUnconstructed()
+ {
+ IndexStorage_t newNode = this->AllocInternal();
+ if ( newNode != this->InvalidIndex() )
+ this->LinkToTail( newNode );
+ return newNode;
+ }
+ };
+
+ Hashtable_t m_table;
+ CCustomLinkedList m_data;
+};
+
+template <typename K, typename V, typename H, typename E, typename S, typename A>
+template <typename KeyArgumentT>
+inline bool CUtlStableHashtable<K,V,H,E,S,A>::DoRemove( KeyArgumentT k )
+{
+ unsigned int hash = m_table.GetHashRef()( k );
+ UtlHashHandle_t h = m_table.template DoLookup<KeyArgumentT>( k, hash, NULL );
+ if ( h == m_table.InvalidHandle() )
+ return false;
+
+ int idx = m_table[ h ].m_index;
+ m_table.template DoRemove<IndirectIndex>( IndirectIndex( idx ), hash );
+ m_data.Remove( idx );
+ return true;
+}
+
+template <typename K, typename V, typename H, typename E, typename S, typename A>
+template <typename KeyArgumentT>
+inline UtlHashHandle_t CUtlStableHashtable<K,V,H,E,S,A>::DoFind( KeyArgumentT k ) const
+{
+ unsigned int hash = m_table.GetHashRef()( k );
+ UtlHashHandle_t h = m_table.template DoLookup<KeyArgumentT>( k, hash, NULL );
+ if ( h != m_table.InvalidHandle() )
+ return m_table[ h ].m_index;
+
+ return (UtlHashHandle_t) -1;
+}
+
+template <typename K, typename V, typename H, typename E, typename S, typename A>
+template <typename KeyArgumentT>
+inline UtlHashHandle_t CUtlStableHashtable<K,V,H,E,S,A>::DoInsert( KeyArgumentT k )
+{
+ unsigned int hash = m_table.GetHashRef()( k );
+ UtlHashHandle_t h = m_table.template DoLookup<KeyArgumentT>( k, hash, NULL );
+ if ( h != m_table.InvalidHandle() )
+ return m_table[ h ].m_index;
+
+ int idx = m_data.AddToTailUnconstructed();
+ ConstructOneArg( &m_data[idx], k );
+ m_table.template DoInsertNoCheck<IndirectIndex>( IndirectIndex( idx ), empty_t(), hash );
+ return idx;
+}
+
+template <typename K, typename V, typename H, typename E, typename S, typename A>
+template <typename KeyArgumentT, typename ValueArgumentT>
+inline UtlHashHandle_t CUtlStableHashtable<K,V,H,E,S,A>::DoInsert( KeyArgumentT k, ValueArgumentT v )
+{
+ unsigned int hash = m_table.GetHashRef()( k );
+ UtlHashHandle_t h = m_table.template DoLookup<KeyArgumentT>( k, hash, NULL );
+ if ( h != m_table.InvalidHandle() )
+ return m_table[ h ].m_index;
+
+ int idx = m_data.AddToTailUnconstructed();
+ ConstructTwoArg( &m_data[idx], k, v );
+ m_table.template DoInsertNoCheck<IndirectIndex>( IndirectIndex( idx ), empty_t(), hash );
+ return idx;
+}
+
+#endif // UTLHASHTABLE_H
diff --git a/mp/src/public/tier1/utlintrusivelist.h b/mp/src/public/tier1/utlintrusivelist.h
index 98426f7a..04a39bd9 100644
--- a/mp/src/public/tier1/utlintrusivelist.h
+++ b/mp/src/public/tier1/utlintrusivelist.h
@@ -1,888 +1,888 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Intrusive linked list templates, both for singly and doubly linked lists
-//
-// $Revision: $
-// $NoKeywords: $
-//===========================================================================//
-
-#ifndef UTILINTRUSIVELIST_H
-#define UTILINTRUSIVELIST_H
-
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include "tier0/basetypes.h"
-#include "utlmemory.h"
-#include "tier0/dbg.h"
-
-
-//
-// These templates are used for intrusive linked list classes. Intrusive linked list templates
-// force the structs and classes contained within them to have their own m_pNext, (optionally),
-// m_pPrev, and other fields contained within. All memory management is up to the caller and their
-// classes. No data will ever be copied. Nodes can only exist on one list at a time, because of
-// only having on m_Next field, and manipulating the list while walking it requires that care on
-// the part of the caller. All accessing and searching functions work by passing and returning
-// pointers.
-//
-//
-//
-// naming and field conventions:
-// functions referring to a DList are for doubly linked lists. nodes must have m_pHead and
-// m_pPrev pointer fields.
-// Functions using Priority require an m_Priority field, which must be comparable.
-//
-// Some functions are mean for use with lists which maintain both a head and tail pointer
-// in order to support fast adding to the end.
-
-
-/// validates that the doubly linked list has the proper structure, pointer-wise
-
-namespace IntrusiveList
-{
-#ifdef SUPERSLOW_DEBUG_VERSION
- template<class T> inline void ValidateDList(T *head)
- {
- if (head)
- {
- Assert(head->m_pPrev==0);
- }
- while(head)
- {
- if (head->m_pNext)
- {
- Assert(head->m_pNext->m_pPrev==head);
- }
- if (head->m_pPrev)
- {
- Assert(head->m_pPrev->m_pNext==head);
- }
- head=head->m_pNext;
- }
- }
-#else
- template<class T> inline void ValidateDList(T * /*head*/)
- {
- }
-#endif
-
-
-
-// move a node in a doubly linked list backwards one step.
- template <class T> inline void MoveDNodeBackwards( T *which, T * &head)
- {
- if (which->m_pPrev)
- {
- T *p=which->m_pPrev;
- T *pp=p->m_pPrev;
- T *n=which->m_pNext;
- Assert(p->m_pNext == which);
- if (n)
- {
- Assert(n->m_pPrev==which);
- n->m_pPrev=p;
- }
- if (pp)
- {
- Assert(pp->m_pNext==p);
- pp->m_pNext=which;
- }
- else
- {
- head=which; // this node is the new root!
- }
- which->m_pNext=p;
- which->m_pPrev=pp;
- p->m_pNext=n;
- p->m_pPrev=which;
- }
- ValidateDList(head);
- }
-
-
-
- // removes node 'which' from doubly linked list with 'head'
- template<class T> inline void RemoveFromDList(T * &head, T *which)
- {
- if (which->m_pPrev)
- {
- Assert(which->m_pPrev->m_pNext==which);
- which->m_pPrev->m_pNext=which->m_pNext;
- if (which->m_pNext)
- {
- Assert(which->m_pNext->m_pPrev==which);
- which->m_pNext->m_pPrev=which->m_pPrev;
- }
- }
- else
- {
- if (head==which)
- {
- head=which->m_pNext;
- if (head)
- {
- Assert(head->m_pPrev==which);
- head->m_pPrev=0;
- }
- }
- }
- which->m_pNext=which->m_pPrev=0;
- ValidateDList(head);
-
- }
-
- //checks to see if node is in doubly linked list
- template<class T> bool OnDList(T const *head, T const *which)
- {
- return (head==which) || (which->m_pNext !=0) || (which->m_pPrev !=0);
- }
-
- // add a node to the end of a singly linked list
- template<class T> void AddToDTail(T * & head, T * node)
- {
- node->m_pNext=0;
- if (! head)
- {
- head=node;
- }
- else
- {
- T *ptr=head;
- while(ptr->m_pNext)
- {
- ptr=ptr->m_pNext;
- }
- ptr->m_pNext=node;
- node->m_pPrev=ptr; //
- }
- }
-
- // add a node to end of doubly linked list.
- template<class T> inline void AddToDHead(T * &head, T *which)
- {
- which->m_pNext=head;
- if (head)
- {
- head->m_pPrev=which;
- }
- which->m_pPrev=0;
- head=which;
- ValidateDList(head);
- }
-
- // add a node to front of doubly linked list which maintains a tail ptr
- template<class T> inline void AddToDHeadWithTailPtr(T * &head, T *which, T * &tailptr)
- {
- which->m_pNext=head;
- if (head)
- {
- head->m_pPrev=which;
- }
- else
- {
- tailptr=which;
- }
- which->m_pPrev=0;
- head=which;
- ValidateDList(head);
- }
-
- // add a node to end of doubly linked list which maintains a tail ptr
- template<class T> inline void AddToDTailWithTailPtr(T * &head, T *which, T * & tailptr)
- {
- if (! tailptr)
- {
- Assert(! head);
- which->m_pPrev=which->m_pNext=0;
- tailptr=head=which;
- }
- else
- {
- which->m_pNext=0;
- which->m_pPrev=tailptr;
- tailptr->m_pNext=which;
- tailptr=which;
- }
- ValidateDList( head );
- }
-
- // Remove a node from a dlist , maintaining the tail ptr. node is not 'delete' d
- template<class T> inline void RemoveFromDListWithTailPtr(T * &head, T *which, T * & tailptr)
- {
- if (which==tailptr)
- {
- tailptr=which->m_pPrev;
- }
- if (which->m_pPrev)
- {
- Assert(which->m_pPrev->m_pNext==which);
- which->m_pPrev->m_pNext=which->m_pNext;
- if (which->m_pNext)
- {
- Assert(which->m_pNext->m_pPrev==which);
- which->m_pNext->m_pPrev=which->m_pPrev;
- }
- }
- else
- {
- if (head==which)
- {
- head=which->m_pNext;
- if (head)
- {
- Assert(head->m_pPrev==which);
- head->m_pPrev=0;
- }
- }
- }
- which->m_pNext=which->m_pPrev=0;
- ValidateDList(head);
-
- }
-
- // this function removes a node, and delete's the node
- template<class T> inline void DeleteFromDListWithTailPtr(T * &head, T *which, T * & tailptr)
- {
- T *tmp=which;
- if (which==tailptr)
- {
- tailptr=which->m_pPrev;
- }
- if (which->m_pPrev)
- {
- Assert(which->m_pPrev->m_pNext==which);
- which->m_pPrev->m_pNext=which->m_pNext;
- if (which->m_pNext)
- {
- Assert(which->m_pNext->m_pPrev==which);
- which->m_pNext->m_pPrev=which->m_pPrev;
- }
- }
- else
- {
- if (head==which)
- {
- head=which->m_pNext;
- if (head)
- {
- Assert(head->m_pPrev==which);
- head->m_pPrev=0;
- }
- }
- }
- which->m_pNext=which->m_pPrev=0;
- delete tmp;
- ValidateDList(head);
- }
-
- // Add a node to a d-list, keeping the highest priority nodes first. This is a simple
- // linear search to insert, NOT a O(logn) heap.
- template<class T> inline void AddToDPriority(T * &head, T *which)
- {
- T* prevnode=0;
- for(T *curnode=head;curnode;curnode=curnode->m_pNext)
- {
- if (which->m_Priority>=curnode->m_Priority)
- break;
- prevnode=curnode;
- }
- // now, we have either run out of list, or we have found an
- // element to add this one before
- if (! prevnode)
- {
- AddToDHead(head,which);
- }
- else
- {
- which->m_pNext=prevnode->m_pNext;
- prevnode->m_pNext=which;
- which->m_pPrev=prevnode;
- if (which->m_pNext)
- which->m_pNext->m_pPrev=which;
- }
- }
-
- // same as AddToDPriority, except with reverse order
- template<class T> inline void AddToDPriorityLowestFirst(T * &head, T *which)
- {
- T* prevnode=0;
- for(T *curnode=head;curnode;curnode=curnode->m_pNext)
- {
- if (which->m_Priority<=curnode->m_Priority)
- break;
- prevnode=curnode;
- }
- // now, we have either run out of list, or we have found an
- // element to add this one before
- if (! prevnode)
- {
- AddToDHead(head,which);
- }
- else
- {
- which->m_pNext=prevnode->m_pNext;
- prevnode->m_pNext=which;
- which->m_pPrev=prevnode;
- if (which->m_pNext)
- which->m_pNext->m_pPrev=which;
- }
- }
-
-
- // return a pointer to the last node in a singly-linked (or doubly) list
- template<class T> T * LastNode(T * head)
- {
- if (head)
- {
- while(head->m_pNext)
- {
- head=head->m_pNext;
- }
- }
- return head;
- }
-
-
- // Remove from a singly linked list. no delete called.
- template<class T,class V> void RemoveFromList(T * & head, V *which)
- {
- if (head==which)
- {
- head=which->m_pNext;
- }
- else
- {
- for(T * i=head; i; i=i->m_pNext)
- {
- if (i->m_pNext==which)
- {
- i->m_pNext=which->m_pNext;
- return;
- }
- }
- }
- }
-
- // same as RemoveFromList, but 'delete' is called.
- template<class T,class V> void DeleteFromList(T * & head, V *which)
- {
- T *tmp;
- if (head==which)
- {
- tmp=which->m_pNext;
- delete(head);
- head=tmp;
- }
- else
- {
- for(T * i=head; i; i=i->m_pNext)
- {
- if (i->m_pNext==which)
- {
- tmp=which->m_pNext;
- delete(which);
- i->m_pNext=tmp;
- return;
- }
- }
- }
- }
-
- // find the position in a list of a node. -1 if not found. Linear search.
- // nodes must have comparison functions
- template<class T,class V> int PositionInList(T *head, V *node)
- {
- int pos=0;
- while(head)
- {
- if (head==node) return pos;
- head=head->m_pNext;
- pos++;
- }
- return -1;
- }
-
- // find the Nth node in a list. null if index too high.
- template<class T> T *NthNode(T * head, int idx)
- {
- while(idx && head)
- {
- idx--;
- head=head->m_pNext;
- }
- return head;
- }
-
- //Add a node to the head of a singly-linked
- // Note that the head var passed to this will be modified.
- template<class T,class V> static inline void AddToHead(T * & head, V * node)
- {
- node->m_pNext=head;
- head=node;
- }
-
- //Add a node to the tail of a singly-linked. Not fast
- // Note that the head var passed to this will be modified.
- template<class T,class V> static inline void AddToTail(T * & head, V * node)
- {
- node->m_pNext = NULL;
- if ( ! head )
- head = node;
- else
- {
- T *pLastNode = head;
- while( pLastNode->m_pNext )
- pLastNode = pLastNode->m_pNext;
- pLastNode->m_pNext = node;
- }
- }
-
- //Add a node to the head of a singly-linked list, maintaining a tail pointer
- template<class T,class V> static inline void AddToHead(T * & head, T * &tail,V * node)
- {
- if (! head)
- {
- tail=node;
- }
- node->m_pNext=head;
- head=node;
- }
-
-
-
- // return the node in head before in a singly linked list. returns null if head is empty, n is
- // null, or if n is the first node. not fast.
- template<class T> static inline T * PrevNode(T *head, T *node)
- {
- T *i;
- for(i=head;i;i=i->m_pNext)
- {
- if (i->m_pNext == node)
- break;
- }
- return i;
- }
-
-
- // add a node to the end of a singly linked list. Not fast.
- template<class T,class V> void AddToEnd(T * & head, V * node)
- {
- node->m_pNext=0;
- if (! head)
- {
- head=node;
- }
- else
- {
- T *ptr=head;
- while(ptr->m_pNext)
- {
- ptr=ptr->m_pNext;
- }
- ptr->m_pNext=node;
- }
- }
-
- // add a node to the end of a singly linked list, maintaining a tail pointer.
- // the head and tail pointer can be modified by this routine.
- template<class T,class V> void AddToEndWithTail(T * & head, T * & tail,V * node)
- {
- Assert((head && tail) || ((!head) && (!tail)));
- node->m_pNext=0;
- if (! head)
- {
- head=tail=node;
- }
- else
- {
- tail->m_pNext=node;
- tail=node;
- }
- }
-
- // Add a node to a singly linked list, sorting by the m_Name field
- template<class T> void AddSortedByName(T * & head, T * node)
- {
- if ( (! head) || // empty list?
- (stricmp(node->m_Name,head->m_Name)==-1)) // or we should be first?
- {
- node->m_pNext=head; // make us head
- head=node;
- }
- else
- {
- T *t;
- for(t=head;t->m_pNext;t=t->m_pNext) // find the node we should be before
- if (stricmp(t->m_pNext->m_Name,node->m_Name)>=0)
- break;
- node->m_pNext=t->m_pNext;
- t->m_pNext=node;
- }
- }
-
- // count # of elements in list
- template<class T> int ListLength(T *head)
- {
- int len=0;
- while(head)
- {
- len++;
- head=head->m_pNext;
- }
- return len;
- }
-
- // this will kill a list if the list is of objects which automatically
- // remove themselves from the list when delete is called
- template<class T> void KillList(T * & head)
- {
- while(head)
- {
- delete head;
- }
- }
-
-
- // this will kill all elements in a list if
- // the elements are of a type which does NOT remove itself from
- // the list when the destructor is called.
- template<class T> void DeleteList(T * & head)
- {
- while (head)
- {
- T* tmp=head->m_pNext;
- delete head;
- head=tmp;
- }
- }
-
- // find a named node in any list which has both a Next field and a Name field.
- template <class T> static inline T * FindNamedNode(T * head, char const *name)
- {
- for(;head && stricmp(head->m_Name,name); head=head->m_pNext)
- {
- }
- return head;
- }
-
- template <class T> static inline T * FindNamedNodeCaseSensitive(T * head, char const *name)
- {
- for(;head && strcmp(head->m_Name,name); head=head->m_pNext)
- {
- }
- return head;
- }
-
- // find data in a singly linked list, using equality match on any field
- // usage: FindNodeByField(listptr,data,&list::fieldname)
- template <class T, class U, class V> static inline T * FindNodeByField(T * head, U data, U V::*field)
- {
- while(head)
- {
- if (data==(*head).*field)
- return head;
- head=head->m_pNext;
- }
- return 0;
- }
-
- // find a node and its predecessor, matching on equality of a given field.
- // usage: FindNodeByFieldWithPrev(listptr,data,&list::fieldname, prevptr)
- template <class T, class U, class V> static inline T * FindNodeByFieldWithPrev(T * head, U data, U V::*field, T * & prev)
- {
- prev=0;
- for(T *i=head; i; i=i->m_pNext)
- {
- if(data==(*i).*field)
- return i;
- prev=i;
- }
- prev=0;
- return 0;
- }
-
-
- /// sort a list. comparefn should return 0 if the items are equal, 1 if A goes first, and -1 if A goes last.
- // NOT fast.
- template<class T> void SortList(T * &head, int (*comparefn)(T * a, T * b))
- {
- int didswap=1;
- while(didswap)
- {
- didswap=0;
- T *prev=0;
- for(T *i=head;i && i->m_pNext; i=i->m_pNext)
- {
- /// compare i and i+1
- int rslt=(*comparefn)(i,i->m_pNext);
- if (rslt==-1)
- {
- /// need to swap
- didswap=1;
- T *newfirst=i->m_pNext;
- if (prev)
- {
- prev->m_pNext=newfirst;
- i->m_pNext=newfirst->m_pNext;
- newfirst->m_pNext=i;
- }
- else
- {
- head=i->m_pNext;
- i->m_pNext=newfirst->m_pNext;
- newfirst->m_pNext=i;
- }
- i=newfirst;
- }
- prev=i;
- }
- }
- }
-
- // sort a doubly linked list. NOt fast.
- template <class T> void SortDList(T * & head, int (*comparefn)(T * a, T * b))
- {
- SortList(head,comparefn);
- /// now, regen prev ptrs
- T *prev=0;
- for(T *i=head;i;i=i->m_pNext)
- {
- i->m_pPrev=prev;
- prev=i;
- }
- }
-
- // reverse a singly linked list. not recommended for anything other than valve programming
- // interview :-)
- template <class T> T *ReversedList( T * head )
- {
- T * pNewHead=NULL;
- while( head )
- {
- T *pNext=head->m_pNext;
-#ifdef INTERVIEW_QUESTION
- head->m_pNext=pNewHead;
- pNewHead = head;
-#else
- AddToHead( pNewHead, head );
-#endif
- head = pNext;
- }
- return pNewHead;
- }
-};
-
-// singly linked list
-template<class T> class CUtlIntrusiveList
-{
-public:
- T *m_pHead;
-
- FORCEINLINE T *Head( void ) const
- {
- return m_pHead;
- }
-
- FORCEINLINE CUtlIntrusiveList(void)
- {
- m_pHead = NULL;
- }
-
-
- FORCEINLINE void RemoveAll( void )
- {
- // empty list. doesn't touch nodes at all
- m_pHead = NULL;
- }
- FORCEINLINE void AddToHead( T * node )
- {
- IntrusiveList::AddToHead( m_pHead, node );
- }
-
- FORCEINLINE void AddToTail( T * node )
- {
- IntrusiveList::AddToTail( m_pHead, node );
- }
-
- void RemoveNode(T *which)
- {
- IntrusiveList::RemoveFromList( m_pHead, which );
- }
-
- // this will kill a list if the list is of objects which automatically
- // remove themselves from the list when delete is called
- void KillList( void )
- {
- while(m_pHead)
- {
- delete m_pHead;
- }
- }
-
-
- // return the node in head before in a singly linked list. returns null if head is empty, n is
- // null, or if n is the first node. not fast. Fast for dlists
- T * PrevNode(T *node)
- {
- return IntrusiveList::PrevNode( m_pHead, node );
- }
-
- int NthNode( int n )
- {
- return NthNode( m_pHead, n );
- }
-
- // this will kill all elements in a list if
- // the elements are of a type which does NOT remove itself from
- // the list when the destructor is called.
- void Purge( void )
- {
- while (m_pHead)
- {
- T* tmp=m_pHead->m_pNext;
- delete m_pHead;
- m_pHead=tmp;
- }
- }
-
- int Count( void ) const
- {
- return IntrusiveList::ListLength( m_pHead );
- }
-
- FORCEINLINE T * FindNamedNodeCaseSensitive( char const *pName ) const
- {
- return IntrusiveList::FindNamedNodeCaseSensitive( m_pHead, pName );
-
- }
-
- T *RemoveHead( void )
- {
- if ( m_pHead )
- {
- T *pRet = m_pHead;
- m_pHead = pRet->m_pNext;
- return pRet;
- }
- else
- return NULL;
- }
-};
-
-// doubly linked list
-template<class T> class CUtlIntrusiveDList : public CUtlIntrusiveList<T>
-{
-public:
-
- FORCEINLINE void AddToHead( T * node )
- {
- IntrusiveList::AddToDHead( CUtlIntrusiveList<T>::m_pHead, node );
- }
- FORCEINLINE void AddToTail( T * node )
- {
- IntrusiveList::AddToDTail( CUtlIntrusiveList<T>::m_pHead, node );
- }
-
- void RemoveNode(T *which)
- {
- IntrusiveList::RemoveFromDList( CUtlIntrusiveList<T>::m_pHead, which );
- }
-
- T *RemoveHead( void )
- {
- if ( CUtlIntrusiveList<T>::m_pHead )
- {
- T *pRet = CUtlIntrusiveList<T>::m_pHead;
- CUtlIntrusiveList<T>::m_pHead = CUtlIntrusiveList<T>::m_pHead->m_pNext;
- if ( CUtlIntrusiveList<T>::m_pHead )
- CUtlIntrusiveList<T>::m_pHead->m_pPrev = NULL;
- return pRet;
- }
- else
- return NULL;
- }
-
- T * PrevNode(T *node)
- {
- return ( node )?node->m_Prev:NULL;
- }
-
-};
-
-template<class T> class CUtlIntrusiveDListWithTailPtr : public CUtlIntrusiveDList<T>
-{
-public:
-
- T *m_pTailPtr;
-
- FORCEINLINE CUtlIntrusiveDListWithTailPtr( void ) : CUtlIntrusiveDList<T>()
- {
- m_pTailPtr = NULL;
- }
-
- FORCEINLINE void AddToHead( T * node )
- {
- IntrusiveList::AddToDHeadWithTailPtr( CUtlIntrusiveList<T>::m_pHead, node, m_pTailPtr );
- }
- FORCEINLINE void AddToTail( T * node )
- {
- IntrusiveList::AddToDTailWithTailPtr( CUtlIntrusiveList<T>::m_pHead, node, m_pTailPtr );
- }
-
- void RemoveNode( T *pWhich )
- {
- IntrusiveList::RemoveFromDListWithTailPtr( CUtlIntrusiveList<T>::m_pHead, pWhich, m_pTailPtr );
- }
-
- void Purge( void )
- {
- CUtlIntrusiveList<T>::Purge();
- m_pTailPtr = NULL;
- }
-
- void Kill( void )
- {
- CUtlIntrusiveList<T>::Purge();
- m_pTailPtr = NULL;
- }
-
- T *RemoveHead( void )
- {
- if ( CUtlIntrusiveDList<T>::m_pHead )
- {
- T *pRet = CUtlIntrusiveDList<T>::m_pHead;
- CUtlIntrusiveDList<T>::m_pHead = CUtlIntrusiveDList<T>::m_pHead->m_pNext;
- if ( CUtlIntrusiveDList<T>::m_pHead )
- CUtlIntrusiveDList<T>::m_pHead->m_pPrev = NULL;
- if (! CUtlIntrusiveDList<T>::m_pHead )
- m_pTailPtr = NULL;
- ValidateDList( CUtlIntrusiveDList<T>::m_pHead );
- return pRet;
- }
- else
- return NULL;
- }
-
- T * PrevNode(T *node)
- {
- return ( node )?node->m_Prev:NULL;
- }
-
-};
-
-template<class T> void PrependDListWithTailToDList( CUtlIntrusiveDListWithTailPtr<T> &src,
- CUtlIntrusiveDList<T> &dest )
-{
- if ( src.m_pHead )
- {
- src.m_pTailPtr->m_pNext = dest.m_pHead;
- if ( dest.m_pHead )
- dest.m_pHead->m_pPrev = src.m_pTailPtr;
- dest.m_pHead = src.m_pHead;
- IntrusiveList::ValidateDList( dest.m_pHead );
- }
-}
-
-#endif
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Intrusive linked list templates, both for singly and doubly linked lists
+//
+// $Revision: $
+// $NoKeywords: $
+//===========================================================================//
+
+#ifndef UTILINTRUSIVELIST_H
+#define UTILINTRUSIVELIST_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/basetypes.h"
+#include "utlmemory.h"
+#include "tier0/dbg.h"
+
+
+//
+// These templates are used for intrusive linked list classes. Intrusive linked list templates
+// force the structs and classes contained within them to have their own m_pNext, (optionally),
+// m_pPrev, and other fields contained within. All memory management is up to the caller and their
+// classes. No data will ever be copied. Nodes can only exist on one list at a time, because of
+// only having on m_Next field, and manipulating the list while walking it requires that care on
+// the part of the caller. All accessing and searching functions work by passing and returning
+// pointers.
+//
+//
+//
+// naming and field conventions:
+// functions referring to a DList are for doubly linked lists. nodes must have m_pHead and
+// m_pPrev pointer fields.
+// Functions using Priority require an m_Priority field, which must be comparable.
+//
+// Some functions are mean for use with lists which maintain both a head and tail pointer
+// in order to support fast adding to the end.
+
+
+/// validates that the doubly linked list has the proper structure, pointer-wise
+
+namespace IntrusiveList
+{
+#ifdef SUPERSLOW_DEBUG_VERSION
+ template<class T> inline void ValidateDList(T *head)
+ {
+ if (head)
+ {
+ Assert(head->m_pPrev==0);
+ }
+ while(head)
+ {
+ if (head->m_pNext)
+ {
+ Assert(head->m_pNext->m_pPrev==head);
+ }
+ if (head->m_pPrev)
+ {
+ Assert(head->m_pPrev->m_pNext==head);
+ }
+ head=head->m_pNext;
+ }
+ }
+#else
+ template<class T> inline void ValidateDList(T * /*head*/)
+ {
+ }
+#endif
+
+
+
+// move a node in a doubly linked list backwards one step.
+ template <class T> inline void MoveDNodeBackwards( T *which, T * &head)
+ {
+ if (which->m_pPrev)
+ {
+ T *p=which->m_pPrev;
+ T *pp=p->m_pPrev;
+ T *n=which->m_pNext;
+ Assert(p->m_pNext == which);
+ if (n)
+ {
+ Assert(n->m_pPrev==which);
+ n->m_pPrev=p;
+ }
+ if (pp)
+ {
+ Assert(pp->m_pNext==p);
+ pp->m_pNext=which;
+ }
+ else
+ {
+ head=which; // this node is the new root!
+ }
+ which->m_pNext=p;
+ which->m_pPrev=pp;
+ p->m_pNext=n;
+ p->m_pPrev=which;
+ }
+ ValidateDList(head);
+ }
+
+
+
+ // removes node 'which' from doubly linked list with 'head'
+ template<class T> inline void RemoveFromDList(T * &head, T *which)
+ {
+ if (which->m_pPrev)
+ {
+ Assert(which->m_pPrev->m_pNext==which);
+ which->m_pPrev->m_pNext=which->m_pNext;
+ if (which->m_pNext)
+ {
+ Assert(which->m_pNext->m_pPrev==which);
+ which->m_pNext->m_pPrev=which->m_pPrev;
+ }
+ }
+ else
+ {
+ if (head==which)
+ {
+ head=which->m_pNext;
+ if (head)
+ {
+ Assert(head->m_pPrev==which);
+ head->m_pPrev=0;
+ }
+ }
+ }
+ which->m_pNext=which->m_pPrev=0;
+ ValidateDList(head);
+
+ }
+
+ //checks to see if node is in doubly linked list
+ template<class T> bool OnDList(T const *head, T const *which)
+ {
+ return (head==which) || (which->m_pNext !=0) || (which->m_pPrev !=0);
+ }
+
+ // add a node to the end of a singly linked list
+ template<class T> void AddToDTail(T * & head, T * node)
+ {
+ node->m_pNext=0;
+ if (! head)
+ {
+ head=node;
+ }
+ else
+ {
+ T *ptr=head;
+ while(ptr->m_pNext)
+ {
+ ptr=ptr->m_pNext;
+ }
+ ptr->m_pNext=node;
+ node->m_pPrev=ptr; //
+ }
+ }
+
+ // add a node to end of doubly linked list.
+ template<class T> inline void AddToDHead(T * &head, T *which)
+ {
+ which->m_pNext=head;
+ if (head)
+ {
+ head->m_pPrev=which;
+ }
+ which->m_pPrev=0;
+ head=which;
+ ValidateDList(head);
+ }
+
+ // add a node to front of doubly linked list which maintains a tail ptr
+ template<class T> inline void AddToDHeadWithTailPtr(T * &head, T *which, T * &tailptr)
+ {
+ which->m_pNext=head;
+ if (head)
+ {
+ head->m_pPrev=which;
+ }
+ else
+ {
+ tailptr=which;
+ }
+ which->m_pPrev=0;
+ head=which;
+ ValidateDList(head);
+ }
+
+ // add a node to end of doubly linked list which maintains a tail ptr
+ template<class T> inline void AddToDTailWithTailPtr(T * &head, T *which, T * & tailptr)
+ {
+ if (! tailptr)
+ {
+ Assert(! head);
+ which->m_pPrev=which->m_pNext=0;
+ tailptr=head=which;
+ }
+ else
+ {
+ which->m_pNext=0;
+ which->m_pPrev=tailptr;
+ tailptr->m_pNext=which;
+ tailptr=which;
+ }
+ ValidateDList( head );
+ }
+
+ // Remove a node from a dlist , maintaining the tail ptr. node is not 'delete' d
+ template<class T> inline void RemoveFromDListWithTailPtr(T * &head, T *which, T * & tailptr)
+ {
+ if (which==tailptr)
+ {
+ tailptr=which->m_pPrev;
+ }
+ if (which->m_pPrev)
+ {
+ Assert(which->m_pPrev->m_pNext==which);
+ which->m_pPrev->m_pNext=which->m_pNext;
+ if (which->m_pNext)
+ {
+ Assert(which->m_pNext->m_pPrev==which);
+ which->m_pNext->m_pPrev=which->m_pPrev;
+ }
+ }
+ else
+ {
+ if (head==which)
+ {
+ head=which->m_pNext;
+ if (head)
+ {
+ Assert(head->m_pPrev==which);
+ head->m_pPrev=0;
+ }
+ }
+ }
+ which->m_pNext=which->m_pPrev=0;
+ ValidateDList(head);
+
+ }
+
+ // this function removes a node, and delete's the node
+ template<class T> inline void DeleteFromDListWithTailPtr(T * &head, T *which, T * & tailptr)
+ {
+ T *tmp=which;
+ if (which==tailptr)
+ {
+ tailptr=which->m_pPrev;
+ }
+ if (which->m_pPrev)
+ {
+ Assert(which->m_pPrev->m_pNext==which);
+ which->m_pPrev->m_pNext=which->m_pNext;
+ if (which->m_pNext)
+ {
+ Assert(which->m_pNext->m_pPrev==which);
+ which->m_pNext->m_pPrev=which->m_pPrev;
+ }
+ }
+ else
+ {
+ if (head==which)
+ {
+ head=which->m_pNext;
+ if (head)
+ {
+ Assert(head->m_pPrev==which);
+ head->m_pPrev=0;
+ }
+ }
+ }
+ which->m_pNext=which->m_pPrev=0;
+ delete tmp;
+ ValidateDList(head);
+ }
+
+ // Add a node to a d-list, keeping the highest priority nodes first. This is a simple
+ // linear search to insert, NOT a O(logn) heap.
+ template<class T> inline void AddToDPriority(T * &head, T *which)
+ {
+ T* prevnode=0;
+ for(T *curnode=head;curnode;curnode=curnode->m_pNext)
+ {
+ if (which->m_Priority>=curnode->m_Priority)
+ break;
+ prevnode=curnode;
+ }
+ // now, we have either run out of list, or we have found an
+ // element to add this one before
+ if (! prevnode)
+ {
+ AddToDHead(head,which);
+ }
+ else
+ {
+ which->m_pNext=prevnode->m_pNext;
+ prevnode->m_pNext=which;
+ which->m_pPrev=prevnode;
+ if (which->m_pNext)
+ which->m_pNext->m_pPrev=which;
+ }
+ }
+
+ // same as AddToDPriority, except with reverse order
+ template<class T> inline void AddToDPriorityLowestFirst(T * &head, T *which)
+ {
+ T* prevnode=0;
+ for(T *curnode=head;curnode;curnode=curnode->m_pNext)
+ {
+ if (which->m_Priority<=curnode->m_Priority)
+ break;
+ prevnode=curnode;
+ }
+ // now, we have either run out of list, or we have found an
+ // element to add this one before
+ if (! prevnode)
+ {
+ AddToDHead(head,which);
+ }
+ else
+ {
+ which->m_pNext=prevnode->m_pNext;
+ prevnode->m_pNext=which;
+ which->m_pPrev=prevnode;
+ if (which->m_pNext)
+ which->m_pNext->m_pPrev=which;
+ }
+ }
+
+
+ // return a pointer to the last node in a singly-linked (or doubly) list
+ template<class T> T * LastNode(T * head)
+ {
+ if (head)
+ {
+ while(head->m_pNext)
+ {
+ head=head->m_pNext;
+ }
+ }
+ return head;
+ }
+
+
+ // Remove from a singly linked list. no delete called.
+ template<class T,class V> void RemoveFromList(T * & head, V *which)
+ {
+ if (head==which)
+ {
+ head=which->m_pNext;
+ }
+ else
+ {
+ for(T * i=head; i; i=i->m_pNext)
+ {
+ if (i->m_pNext==which)
+ {
+ i->m_pNext=which->m_pNext;
+ return;
+ }
+ }
+ }
+ }
+
+ // same as RemoveFromList, but 'delete' is called.
+ template<class T,class V> void DeleteFromList(T * & head, V *which)
+ {
+ T *tmp;
+ if (head==which)
+ {
+ tmp=which->m_pNext;
+ delete(head);
+ head=tmp;
+ }
+ else
+ {
+ for(T * i=head; i; i=i->m_pNext)
+ {
+ if (i->m_pNext==which)
+ {
+ tmp=which->m_pNext;
+ delete(which);
+ i->m_pNext=tmp;
+ return;
+ }
+ }
+ }
+ }
+
+ // find the position in a list of a node. -1 if not found. Linear search.
+ // nodes must have comparison functions
+ template<class T,class V> int PositionInList(T *head, V *node)
+ {
+ int pos=0;
+ while(head)
+ {
+ if (head==node) return pos;
+ head=head->m_pNext;
+ pos++;
+ }
+ return -1;
+ }
+
+ // find the Nth node in a list. null if index too high.
+ template<class T> T *NthNode(T * head, int idx)
+ {
+ while(idx && head)
+ {
+ idx--;
+ head=head->m_pNext;
+ }
+ return head;
+ }
+
+ //Add a node to the head of a singly-linked
+ // Note that the head var passed to this will be modified.
+ template<class T,class V> static inline void AddToHead(T * & head, V * node)
+ {
+ node->m_pNext=head;
+ head=node;
+ }
+
+ //Add a node to the tail of a singly-linked. Not fast
+ // Note that the head var passed to this will be modified.
+ template<class T,class V> static inline void AddToTail(T * & head, V * node)
+ {
+ node->m_pNext = NULL;
+ if ( ! head )
+ head = node;
+ else
+ {
+ T *pLastNode = head;
+ while( pLastNode->m_pNext )
+ pLastNode = pLastNode->m_pNext;
+ pLastNode->m_pNext = node;
+ }
+ }
+
+ //Add a node to the head of a singly-linked list, maintaining a tail pointer
+ template<class T,class V> static inline void AddToHead(T * & head, T * &tail,V * node)
+ {
+ if (! head)
+ {
+ tail=node;
+ }
+ node->m_pNext=head;
+ head=node;
+ }
+
+
+
+ // return the node in head before in a singly linked list. returns null if head is empty, n is
+ // null, or if n is the first node. not fast.
+ template<class T> static inline T * PrevNode(T *head, T *node)
+ {
+ T *i;
+ for(i=head;i;i=i->m_pNext)
+ {
+ if (i->m_pNext == node)
+ break;
+ }
+ return i;
+ }
+
+
+ // add a node to the end of a singly linked list. Not fast.
+ template<class T,class V> void AddToEnd(T * & head, V * node)
+ {
+ node->m_pNext=0;
+ if (! head)
+ {
+ head=node;
+ }
+ else
+ {
+ T *ptr=head;
+ while(ptr->m_pNext)
+ {
+ ptr=ptr->m_pNext;
+ }
+ ptr->m_pNext=node;
+ }
+ }
+
+ // add a node to the end of a singly linked list, maintaining a tail pointer.
+ // the head and tail pointer can be modified by this routine.
+ template<class T,class V> void AddToEndWithTail(T * & head, T * & tail,V * node)
+ {
+ Assert((head && tail) || ((!head) && (!tail)));
+ node->m_pNext=0;
+ if (! head)
+ {
+ head=tail=node;
+ }
+ else
+ {
+ tail->m_pNext=node;
+ tail=node;
+ }
+ }
+
+ // Add a node to a singly linked list, sorting by the m_Name field
+ template<class T> void AddSortedByName(T * & head, T * node)
+ {
+ if ( (! head) || // empty list?
+ (stricmp(node->m_Name,head->m_Name)==-1)) // or we should be first?
+ {
+ node->m_pNext=head; // make us head
+ head=node;
+ }
+ else
+ {
+ T *t;
+ for(t=head;t->m_pNext;t=t->m_pNext) // find the node we should be before
+ if (stricmp(t->m_pNext->m_Name,node->m_Name)>=0)
+ break;
+ node->m_pNext=t->m_pNext;
+ t->m_pNext=node;
+ }
+ }
+
+ // count # of elements in list
+ template<class T> int ListLength(T *head)
+ {
+ int len=0;
+ while(head)
+ {
+ len++;
+ head=head->m_pNext;
+ }
+ return len;
+ }
+
+ // this will kill a list if the list is of objects which automatically
+ // remove themselves from the list when delete is called
+ template<class T> void KillList(T * & head)
+ {
+ while(head)
+ {
+ delete head;
+ }
+ }
+
+
+ // this will kill all elements in a list if
+ // the elements are of a type which does NOT remove itself from
+ // the list when the destructor is called.
+ template<class T> void DeleteList(T * & head)
+ {
+ while (head)
+ {
+ T* tmp=head->m_pNext;
+ delete head;
+ head=tmp;
+ }
+ }
+
+ // find a named node in any list which has both a Next field and a Name field.
+ template <class T> static inline T * FindNamedNode(T * head, char const *name)
+ {
+ for(;head && stricmp(head->m_Name,name); head=head->m_pNext)
+ {
+ }
+ return head;
+ }
+
+ template <class T> static inline T * FindNamedNodeCaseSensitive(T * head, char const *name)
+ {
+ for(;head && strcmp(head->m_Name,name); head=head->m_pNext)
+ {
+ }
+ return head;
+ }
+
+ // find data in a singly linked list, using equality match on any field
+ // usage: FindNodeByField(listptr,data,&list::fieldname)
+ template <class T, class U, class V> static inline T * FindNodeByField(T * head, U data, U V::*field)
+ {
+ while(head)
+ {
+ if (data==(*head).*field)
+ return head;
+ head=head->m_pNext;
+ }
+ return 0;
+ }
+
+ // find a node and its predecessor, matching on equality of a given field.
+ // usage: FindNodeByFieldWithPrev(listptr,data,&list::fieldname, prevptr)
+ template <class T, class U, class V> static inline T * FindNodeByFieldWithPrev(T * head, U data, U V::*field, T * & prev)
+ {
+ prev=0;
+ for(T *i=head; i; i=i->m_pNext)
+ {
+ if(data==(*i).*field)
+ return i;
+ prev=i;
+ }
+ prev=0;
+ return 0;
+ }
+
+
+ /// sort a list. comparefn should return 0 if the items are equal, 1 if A goes first, and -1 if A goes last.
+ // NOT fast.
+ template<class T> void SortList(T * &head, int (*comparefn)(T * a, T * b))
+ {
+ int didswap=1;
+ while(didswap)
+ {
+ didswap=0;
+ T *prev=0;
+ for(T *i=head;i && i->m_pNext; i=i->m_pNext)
+ {
+ /// compare i and i+1
+ int rslt=(*comparefn)(i,i->m_pNext);
+ if (rslt==-1)
+ {
+ /// need to swap
+ didswap=1;
+ T *newfirst=i->m_pNext;
+ if (prev)
+ {
+ prev->m_pNext=newfirst;
+ i->m_pNext=newfirst->m_pNext;
+ newfirst->m_pNext=i;
+ }
+ else
+ {
+ head=i->m_pNext;
+ i->m_pNext=newfirst->m_pNext;
+ newfirst->m_pNext=i;
+ }
+ i=newfirst;
+ }
+ prev=i;
+ }
+ }
+ }
+
+ // sort a doubly linked list. NOt fast.
+ template <class T> void SortDList(T * & head, int (*comparefn)(T * a, T * b))
+ {
+ SortList(head,comparefn);
+ /// now, regen prev ptrs
+ T *prev=0;
+ for(T *i=head;i;i=i->m_pNext)
+ {
+ i->m_pPrev=prev;
+ prev=i;
+ }
+ }
+
+ // reverse a singly linked list. not recommended for anything other than valve programming
+ // interview :-)
+ template <class T> T *ReversedList( T * head )
+ {
+ T * pNewHead=NULL;
+ while( head )
+ {
+ T *pNext=head->m_pNext;
+#ifdef INTERVIEW_QUESTION
+ head->m_pNext=pNewHead;
+ pNewHead = head;
+#else
+ AddToHead( pNewHead, head );
+#endif
+ head = pNext;
+ }
+ return pNewHead;
+ }
+};
+
+// singly linked list
+template<class T> class CUtlIntrusiveList
+{
+public:
+ T *m_pHead;
+
+ FORCEINLINE T *Head( void ) const
+ {
+ return m_pHead;
+ }
+
+ FORCEINLINE CUtlIntrusiveList(void)
+ {
+ m_pHead = NULL;
+ }
+
+
+ FORCEINLINE void RemoveAll( void )
+ {
+ // empty list. doesn't touch nodes at all
+ m_pHead = NULL;
+ }
+ FORCEINLINE void AddToHead( T * node )
+ {
+ IntrusiveList::AddToHead( m_pHead, node );
+ }
+
+ FORCEINLINE void AddToTail( T * node )
+ {
+ IntrusiveList::AddToTail( m_pHead, node );
+ }
+
+ void RemoveNode(T *which)
+ {
+ IntrusiveList::RemoveFromList( m_pHead, which );
+ }
+
+ // this will kill a list if the list is of objects which automatically
+ // remove themselves from the list when delete is called
+ void KillList( void )
+ {
+ while(m_pHead)
+ {
+ delete m_pHead;
+ }
+ }
+
+
+ // return the node in head before in a singly linked list. returns null if head is empty, n is
+ // null, or if n is the first node. not fast. Fast for dlists
+ T * PrevNode(T *node)
+ {
+ return IntrusiveList::PrevNode( m_pHead, node );
+ }
+
+ int NthNode( int n )
+ {
+ return NthNode( m_pHead, n );
+ }
+
+ // this will kill all elements in a list if
+ // the elements are of a type which does NOT remove itself from
+ // the list when the destructor is called.
+ void Purge( void )
+ {
+ while (m_pHead)
+ {
+ T* tmp=m_pHead->m_pNext;
+ delete m_pHead;
+ m_pHead=tmp;
+ }
+ }
+
+ int Count( void ) const
+ {
+ return IntrusiveList::ListLength( m_pHead );
+ }
+
+ FORCEINLINE T * FindNamedNodeCaseSensitive( char const *pName ) const
+ {
+ return IntrusiveList::FindNamedNodeCaseSensitive( m_pHead, pName );
+
+ }
+
+ T *RemoveHead( void )
+ {
+ if ( m_pHead )
+ {
+ T *pRet = m_pHead;
+ m_pHead = pRet->m_pNext;
+ return pRet;
+ }
+ else
+ return NULL;
+ }
+};
+
+// doubly linked list
+template<class T> class CUtlIntrusiveDList : public CUtlIntrusiveList<T>
+{
+public:
+
+ FORCEINLINE void AddToHead( T * node )
+ {
+ IntrusiveList::AddToDHead( CUtlIntrusiveList<T>::m_pHead, node );
+ }
+ FORCEINLINE void AddToTail( T * node )
+ {
+ IntrusiveList::AddToDTail( CUtlIntrusiveList<T>::m_pHead, node );
+ }
+
+ void RemoveNode(T *which)
+ {
+ IntrusiveList::RemoveFromDList( CUtlIntrusiveList<T>::m_pHead, which );
+ }
+
+ T *RemoveHead( void )
+ {
+ if ( CUtlIntrusiveList<T>::m_pHead )
+ {
+ T *pRet = CUtlIntrusiveList<T>::m_pHead;
+ CUtlIntrusiveList<T>::m_pHead = CUtlIntrusiveList<T>::m_pHead->m_pNext;
+ if ( CUtlIntrusiveList<T>::m_pHead )
+ CUtlIntrusiveList<T>::m_pHead->m_pPrev = NULL;
+ return pRet;
+ }
+ else
+ return NULL;
+ }
+
+ T * PrevNode(T *node)
+ {
+ return ( node )?node->m_Prev:NULL;
+ }
+
+};
+
+template<class T> class CUtlIntrusiveDListWithTailPtr : public CUtlIntrusiveDList<T>
+{
+public:
+
+ T *m_pTailPtr;
+
+ FORCEINLINE CUtlIntrusiveDListWithTailPtr( void ) : CUtlIntrusiveDList<T>()
+ {
+ m_pTailPtr = NULL;
+ }
+
+ FORCEINLINE void AddToHead( T * node )
+ {
+ IntrusiveList::AddToDHeadWithTailPtr( CUtlIntrusiveList<T>::m_pHead, node, m_pTailPtr );
+ }
+ FORCEINLINE void AddToTail( T * node )
+ {
+ IntrusiveList::AddToDTailWithTailPtr( CUtlIntrusiveList<T>::m_pHead, node, m_pTailPtr );
+ }
+
+ void RemoveNode( T *pWhich )
+ {
+ IntrusiveList::RemoveFromDListWithTailPtr( CUtlIntrusiveList<T>::m_pHead, pWhich, m_pTailPtr );
+ }
+
+ void Purge( void )
+ {
+ CUtlIntrusiveList<T>::Purge();
+ m_pTailPtr = NULL;
+ }
+
+ void Kill( void )
+ {
+ CUtlIntrusiveList<T>::Purge();
+ m_pTailPtr = NULL;
+ }
+
+ T *RemoveHead( void )
+ {
+ if ( CUtlIntrusiveDList<T>::m_pHead )
+ {
+ T *pRet = CUtlIntrusiveDList<T>::m_pHead;
+ CUtlIntrusiveDList<T>::m_pHead = CUtlIntrusiveDList<T>::m_pHead->m_pNext;
+ if ( CUtlIntrusiveDList<T>::m_pHead )
+ CUtlIntrusiveDList<T>::m_pHead->m_pPrev = NULL;
+ if (! CUtlIntrusiveDList<T>::m_pHead )
+ m_pTailPtr = NULL;
+ ValidateDList( CUtlIntrusiveDList<T>::m_pHead );
+ return pRet;
+ }
+ else
+ return NULL;
+ }
+
+ T * PrevNode(T *node)
+ {
+ return ( node )?node->m_Prev:NULL;
+ }
+
+};
+
+template<class T> void PrependDListWithTailToDList( CUtlIntrusiveDListWithTailPtr<T> &src,
+ CUtlIntrusiveDList<T> &dest )
+{
+ if ( src.m_pHead )
+ {
+ src.m_pTailPtr->m_pNext = dest.m_pHead;
+ if ( dest.m_pHead )
+ dest.m_pHead->m_pPrev = src.m_pTailPtr;
+ dest.m_pHead = src.m_pHead;
+ IntrusiveList::ValidateDList( dest.m_pHead );
+ }
+}
+
+#endif
diff --git a/mp/src/public/tier1/utllinkedlist.h b/mp/src/public/tier1/utllinkedlist.h
index ff251268..822f0b36 100644
--- a/mp/src/public/tier1/utllinkedlist.h
+++ b/mp/src/public/tier1/utllinkedlist.h
@@ -1,1286 +1,1286 @@
-//========= Copyright 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(); (listName).IsUtlLinkedList && 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;
- static const bool IsUtlLinkedList = true; // Used to match this at compiletime
-
- // 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 );
-
- // 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;
-
- // STL compatible const_iterator class
- template < typename List_t >
- class _CUtlLinkedList_constiterator_t
- {
- public:
- typedef typename List_t::ElemType_t ElemType_t;
- typedef typename List_t::IndexType_t IndexType_t;
-
- // Default constructor -- gives a currently unusable iterator.
- _CUtlLinkedList_constiterator_t()
- : m_list( 0 )
- , m_index( List_t::InvalidIndex() )
- {
- }
- // Normal constructor.
- _CUtlLinkedList_constiterator_t( const List_t& list, IndexType_t index )
- : m_list( &list )
- , m_index( index )
- {
- }
-
- // Pre-increment operator++. This is the most efficient increment
- // operator so it should always be used.
- _CUtlLinkedList_constiterator_t& operator++()
- {
- m_index = m_list->Next( m_index );
- return *this;
- }
- // Post-increment operator++. This is less efficient than pre-increment.
- _CUtlLinkedList_constiterator_t operator++(int)
- {
- // Copy ourselves.
- _CUtlLinkedList_constiterator_t temp = *this;
- // Increment ourselves.
- ++*this;
- // Return the copy.
- return temp;
- }
-
- // Pre-decrement operator--. This is the most efficient decrement
- // operator so it should always be used.
- _CUtlLinkedList_constiterator_t& operator--()
- {
- Assert( m_index != m_list->Head() );
- if ( m_index == m_list->InvalidIndex() )
- {
- m_index = m_list->Tail();
- }
- else
- {
- m_index = m_list->Previous( m_index );
- }
- return *this;
- }
- // Post-decrement operator--. This is less efficient than post-decrement.
- _CUtlLinkedList_constiterator_t operator--(int)
- {
- // Copy ourselves.
- _CUtlLinkedList_constiterator_t temp = *this;
- // Decrement ourselves.
- --*this;
- // Return the copy.
- return temp;
- }
-
- bool operator==( const _CUtlLinkedList_constiterator_t& other) const
- {
- Assert( m_list == other.m_list );
- return m_index == other.m_index;
- }
-
- bool operator!=( const _CUtlLinkedList_constiterator_t& other) const
- {
- Assert( m_list == other.m_list );
- return m_index != other.m_index;
- }
-
- const ElemType_t& operator*() const
- {
- return m_list->Element( m_index );
- }
-
- const ElemType_t* operator->() const
- {
- return (&**this);
- }
-
- protected:
- // Use a pointer rather than a reference so that we can support
- // assignment of iterators.
- const List_t* m_list;
- IndexType_t m_index;
- };
-
- // STL compatible iterator class, using derivation so that a non-const
- // list can return a const_iterator.
- template < typename List_t >
- class _CUtlLinkedList_iterator_t : public _CUtlLinkedList_constiterator_t< List_t >
- {
- public:
- typedef typename List_t::ElemType_t ElemType_t;
- typedef typename List_t::IndexType_t IndexType_t;
- typedef _CUtlLinkedList_constiterator_t< List_t > Base;
-
- // Default constructor -- gives a currently unusable iterator.
- _CUtlLinkedList_iterator_t()
- {
- }
- // Normal constructor.
- _CUtlLinkedList_iterator_t( const List_t& list, IndexType_t index )
- : _CUtlLinkedList_constiterator_t< List_t >( list, index )
- {
- }
-
- // Pre-increment operator++. This is the most efficient increment
- // operator so it should always be used.
- _CUtlLinkedList_iterator_t& operator++()
- {
- Base::m_index = Base::m_list->Next( Base::m_index );
- return *this;
- }
- // Post-increment operator++. This is less efficient than pre-increment.
- _CUtlLinkedList_iterator_t operator++(int)
- {
- // Copy ourselves.
- _CUtlLinkedList_iterator_t temp = *this;
- // Increment ourselves.
- ++*this;
- // Return the copy.
- return temp;
- }
-
- // Pre-decrement operator--. This is the most efficient decrement
- // operator so it should always be used.
- _CUtlLinkedList_iterator_t& operator--()
- {
- Assert( Base::m_index != Base::m_list->Head() );
- if ( Base::m_index == Base::m_list->InvalidIndex() )
- {
- Base::m_index = Base::m_list->Tail();
- }
- else
- {
- Base::m_index = Base::m_list->Previous( Base::m_index );
- }
- return *this;
- }
- // Post-decrement operator--. This is less efficient than post-decrement.
- _CUtlLinkedList_iterator_t operator--(int)
- {
- // Copy ourselves.
- _CUtlLinkedList_iterator_t temp = *this;
- // Decrement ourselves.
- --*this;
- // Return the copy.
- return temp;
- }
-
- ElemType_t& operator*() const
- {
- // Const_cast to allow sharing the implementation with the
- // base class.
- List_t* pMutableList = const_cast<List_t*>( Base::m_list );
- return pMutableList->Element( Base::m_index );
- }
-
- ElemType_t* operator->() const
- {
- return (&**this);
- }
- };
-
- typedef _CUtlLinkedList_constiterator_t<CUtlLinkedList<T, S, ML, I, M> > const_iterator;
- typedef _CUtlLinkedList_iterator_t<CUtlLinkedList<T, S, ML, I, M> > iterator;
- const_iterator begin() const
- {
- return const_iterator( *this, Head() );
- }
- iterator begin()
- {
- return iterator( *this, Head() );
- }
-
- const_iterator end() const
- {
- return const_iterator( *this, InvalidIndex() );
- }
- iterator end()
- {
- return iterator( *this, InvalidIndex() );
- }
-
- // 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();
- }
-
-private:
- // Faster version of Next that can only be used from tested code internal
- // to this class, such as Find(). It avoids the cost of checking the index
- // validity, which is a big win on debug builds.
- I PrivateNext( I i ) const;
-};
-
-
-// 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, int, true, int, CUtlFixedMemory< UtlLinkedListElem_t< T, int > > >
-{
-public:
- CUtlFixedLinkedList( int growSize = 0, int initSize = 0 )
- : CUtlLinkedList< T, int, true, int, CUtlFixedMemory< UtlLinkedListElem_t< T, int > > >( growSize, initSize ) {}
-
- typedef CUtlLinkedList< T, int, true, int, CUtlFixedMemory< UtlLinkedListElem_t< T, int > > > BaseClass;
- bool IsValidIndex( int i ) const
- {
- if ( !BaseClass::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 ( BaseClass::Memory().IsIdxAfter( i, this->m_LastAlloc ) )
- {
- Assert( 0 );
- return false; // don't read values that have been allocated, but not constructed
- }
-#endif
-
- return ( BaseClass::Memory()[ i ].m_Previous != i ) || ( BaseClass::Memory()[ i ].m_Next == i );
- }
-
-private:
- int MaxElementIndex() const { Assert( 0 ); return BaseClass::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;
-}
-
-template <class T, class S, bool ML, class I, class M>
-inline I CUtlLinkedList<T,S,ML,I,M>::PrivateNext( I i ) const
-{
- 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();
-}
-
-
-//-----------------------------------------------------------------------------
-// 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
-{
- // Cache the invalidIndex to avoid two levels of function calls on each iteration.
- I invalidIndex = InvalidIndex();
- for ( I i=Head(); i != invalidIndex; i = PrivateNext( 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 * RESTRICT 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 RESTRICT
- 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 * RESTRICT 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 * RESTRICT 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
+//========= Copyright 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(); (listName).IsUtlLinkedList && 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;
+ static const bool IsUtlLinkedList = true; // Used to match this at compiletime
+
+ // 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 );
+
+ // 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;
+
+ // STL compatible const_iterator class
+ template < typename List_t >
+ class _CUtlLinkedList_constiterator_t
+ {
+ public:
+ typedef typename List_t::ElemType_t ElemType_t;
+ typedef typename List_t::IndexType_t IndexType_t;
+
+ // Default constructor -- gives a currently unusable iterator.
+ _CUtlLinkedList_constiterator_t()
+ : m_list( 0 )
+ , m_index( List_t::InvalidIndex() )
+ {
+ }
+ // Normal constructor.
+ _CUtlLinkedList_constiterator_t( const List_t& list, IndexType_t index )
+ : m_list( &list )
+ , m_index( index )
+ {
+ }
+
+ // Pre-increment operator++. This is the most efficient increment
+ // operator so it should always be used.
+ _CUtlLinkedList_constiterator_t& operator++()
+ {
+ m_index = m_list->Next( m_index );
+ return *this;
+ }
+ // Post-increment operator++. This is less efficient than pre-increment.
+ _CUtlLinkedList_constiterator_t operator++(int)
+ {
+ // Copy ourselves.
+ _CUtlLinkedList_constiterator_t temp = *this;
+ // Increment ourselves.
+ ++*this;
+ // Return the copy.
+ return temp;
+ }
+
+ // Pre-decrement operator--. This is the most efficient decrement
+ // operator so it should always be used.
+ _CUtlLinkedList_constiterator_t& operator--()
+ {
+ Assert( m_index != m_list->Head() );
+ if ( m_index == m_list->InvalidIndex() )
+ {
+ m_index = m_list->Tail();
+ }
+ else
+ {
+ m_index = m_list->Previous( m_index );
+ }
+ return *this;
+ }
+ // Post-decrement operator--. This is less efficient than post-decrement.
+ _CUtlLinkedList_constiterator_t operator--(int)
+ {
+ // Copy ourselves.
+ _CUtlLinkedList_constiterator_t temp = *this;
+ // Decrement ourselves.
+ --*this;
+ // Return the copy.
+ return temp;
+ }
+
+ bool operator==( const _CUtlLinkedList_constiterator_t& other) const
+ {
+ Assert( m_list == other.m_list );
+ return m_index == other.m_index;
+ }
+
+ bool operator!=( const _CUtlLinkedList_constiterator_t& other) const
+ {
+ Assert( m_list == other.m_list );
+ return m_index != other.m_index;
+ }
+
+ const ElemType_t& operator*() const
+ {
+ return m_list->Element( m_index );
+ }
+
+ const ElemType_t* operator->() const
+ {
+ return (&**this);
+ }
+
+ protected:
+ // Use a pointer rather than a reference so that we can support
+ // assignment of iterators.
+ const List_t* m_list;
+ IndexType_t m_index;
+ };
+
+ // STL compatible iterator class, using derivation so that a non-const
+ // list can return a const_iterator.
+ template < typename List_t >
+ class _CUtlLinkedList_iterator_t : public _CUtlLinkedList_constiterator_t< List_t >
+ {
+ public:
+ typedef typename List_t::ElemType_t ElemType_t;
+ typedef typename List_t::IndexType_t IndexType_t;
+ typedef _CUtlLinkedList_constiterator_t< List_t > Base;
+
+ // Default constructor -- gives a currently unusable iterator.
+ _CUtlLinkedList_iterator_t()
+ {
+ }
+ // Normal constructor.
+ _CUtlLinkedList_iterator_t( const List_t& list, IndexType_t index )
+ : _CUtlLinkedList_constiterator_t< List_t >( list, index )
+ {
+ }
+
+ // Pre-increment operator++. This is the most efficient increment
+ // operator so it should always be used.
+ _CUtlLinkedList_iterator_t& operator++()
+ {
+ Base::m_index = Base::m_list->Next( Base::m_index );
+ return *this;
+ }
+ // Post-increment operator++. This is less efficient than pre-increment.
+ _CUtlLinkedList_iterator_t operator++(int)
+ {
+ // Copy ourselves.
+ _CUtlLinkedList_iterator_t temp = *this;
+ // Increment ourselves.
+ ++*this;
+ // Return the copy.
+ return temp;
+ }
+
+ // Pre-decrement operator--. This is the most efficient decrement
+ // operator so it should always be used.
+ _CUtlLinkedList_iterator_t& operator--()
+ {
+ Assert( Base::m_index != Base::m_list->Head() );
+ if ( Base::m_index == Base::m_list->InvalidIndex() )
+ {
+ Base::m_index = Base::m_list->Tail();
+ }
+ else
+ {
+ Base::m_index = Base::m_list->Previous( Base::m_index );
+ }
+ return *this;
+ }
+ // Post-decrement operator--. This is less efficient than post-decrement.
+ _CUtlLinkedList_iterator_t operator--(int)
+ {
+ // Copy ourselves.
+ _CUtlLinkedList_iterator_t temp = *this;
+ // Decrement ourselves.
+ --*this;
+ // Return the copy.
+ return temp;
+ }
+
+ ElemType_t& operator*() const
+ {
+ // Const_cast to allow sharing the implementation with the
+ // base class.
+ List_t* pMutableList = const_cast<List_t*>( Base::m_list );
+ return pMutableList->Element( Base::m_index );
+ }
+
+ ElemType_t* operator->() const
+ {
+ return (&**this);
+ }
+ };
+
+ typedef _CUtlLinkedList_constiterator_t<CUtlLinkedList<T, S, ML, I, M> > const_iterator;
+ typedef _CUtlLinkedList_iterator_t<CUtlLinkedList<T, S, ML, I, M> > iterator;
+ const_iterator begin() const
+ {
+ return const_iterator( *this, Head() );
+ }
+ iterator begin()
+ {
+ return iterator( *this, Head() );
+ }
+
+ const_iterator end() const
+ {
+ return const_iterator( *this, InvalidIndex() );
+ }
+ iterator end()
+ {
+ return iterator( *this, InvalidIndex() );
+ }
+
+ // 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();
+ }
+
+private:
+ // Faster version of Next that can only be used from tested code internal
+ // to this class, such as Find(). It avoids the cost of checking the index
+ // validity, which is a big win on debug builds.
+ I PrivateNext( I i ) const;
+};
+
+
+// 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, int, true, int, CUtlFixedMemory< UtlLinkedListElem_t< T, int > > >
+{
+public:
+ CUtlFixedLinkedList( int growSize = 0, int initSize = 0 )
+ : CUtlLinkedList< T, int, true, int, CUtlFixedMemory< UtlLinkedListElem_t< T, int > > >( growSize, initSize ) {}
+
+ typedef CUtlLinkedList< T, int, true, int, CUtlFixedMemory< UtlLinkedListElem_t< T, int > > > BaseClass;
+ bool IsValidIndex( int i ) const
+ {
+ if ( !BaseClass::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 ( BaseClass::Memory().IsIdxAfter( i, this->m_LastAlloc ) )
+ {
+ Assert( 0 );
+ return false; // don't read values that have been allocated, but not constructed
+ }
+#endif
+
+ return ( BaseClass::Memory()[ i ].m_Previous != i ) || ( BaseClass::Memory()[ i ].m_Next == i );
+ }
+
+private:
+ int MaxElementIndex() const { Assert( 0 ); return BaseClass::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;
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline I CUtlLinkedList<T,S,ML,I,M>::PrivateNext( I i ) const
+{
+ 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();
+}
+
+
+//-----------------------------------------------------------------------------
+// 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
+{
+ // Cache the invalidIndex to avoid two levels of function calls on each iteration.
+ I invalidIndex = InvalidIndex();
+ for ( I i=Head(); i != invalidIndex; i = PrivateNext( 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 * RESTRICT 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 RESTRICT
+ 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 * RESTRICT 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 * RESTRICT 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/mp/src/public/tier1/utlmap.h b/mp/src/public/tier1/utlmap.h
index e79c7b85..9c08bc04 100644
--- a/mp/src/public/tier1/utlmap.h
+++ b/mp/src/public/tier1/utlmap.h
@@ -1,252 +1,252 @@
-//========= Copyright 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:
- // This enum exists so that FOR_EACH_MAP and FOR_EACH_MAP_FAST cannot accidentally
- // be used on a type that is not a CUtlMap. If the code compiles then all is well.
- // The check for IsUtlMap being true should be free.
- // Using an enum rather than a static const bool ensures that this trick works even
- // with optimizations disabled on gcc.
- enum CompileTimeCheck
- {
- IsUtlMap = 1
- };
-};
-
-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( pmapIn.Key( i ), pmapIn.Element( i ) );
- }
-}
-
-#endif // UTLMAP_H
+//========= Copyright 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:
+ // This enum exists so that FOR_EACH_MAP and FOR_EACH_MAP_FAST cannot accidentally
+ // be used on a type that is not a CUtlMap. If the code compiles then all is well.
+ // The check for IsUtlMap being true should be free.
+ // Using an enum rather than a static const bool ensures that this trick works even
+ // with optimizations disabled on gcc.
+ enum CompileTimeCheck
+ {
+ IsUtlMap = 1
+ };
+};
+
+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( pmapIn.Key( i ), pmapIn.Element( i ) );
+ }
+}
+
+#endif // UTLMAP_H
diff --git a/mp/src/public/tier1/utlmemory.h b/mp/src/public/tier1/utlmemory.h
index 0d20a6ad..2b817bb2 100644
--- a/mp/src/public/tier1/utlmemory.h
+++ b/mp/src/public/tier1/utlmemory.h
@@ -1,1077 +1,1077 @@
-//========= Copyright 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 "mathlib/mathlib.h"
-
-#include "tier0/memalloc.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 );
- // Takes ownership of the passed memory, including freeing it when this buffer is destroyed.
- void AssumeMemory( T *pMemory, int nSize );
-
- // 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?
- // Use unsigned math to improve performance
- bool IsIdxValid( int i ) const { return (size_t)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
- // Use unsigned math and inlined checks to improve performance.
- T& operator[]( int i ) { Assert( (size_t)i < SIZE ); return Base()[i]; }
- const T& operator[]( int i ) const { Assert( (size_t)i < SIZE ); return Base()[i]; }
- T& Element( int i ) { Assert( (size_t)i < SIZE ); return Base()[i]; }
- const T& Element( int i ) const { Assert( (size_t)i < SIZE ); 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 ];
-};
-
-#if defined(POSIX)
-// From Chris Green: Memory is a little fuzzy but I believe this class did
-// something fishy with respect to msize and alignment that was OK under our
-// allocator, the glibc allocator, etc but not the valgrind one (which has no
-// padding because it detects all forms of head/tail overwrite, including
-// writing 1 byte past a 1 byte allocation).
-#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();
-}
-
-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( (void*)pMemory, (void*)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;
-}
-
-
-//-----------------------------------------------------------------------------
-// element access
-//-----------------------------------------------------------------------------
-template< class T, class I >
-inline T& CUtlMemory<T,I>::operator[]( I i )
-{
- // Avoid function calls in the asserts to improve debug build performance
- Assert( m_nGrowSize != EXTERNAL_CONST_BUFFER_MARKER ); //Assert( !IsReadOnly() );
- Assert( (uint32)i < (uint32)m_nAllocationCount );
- return m_pMemory[i];
-}
-
-template< class T, class I >
-inline const T& CUtlMemory<T,I>::operator[]( I i ) const
-{
- // Avoid function calls in the asserts to improve debug build performance
- Assert( (uint32)i < (uint32)m_nAllocationCount );
- return m_pMemory[i];
-}
-
-template< class T, class I >
-inline T& CUtlMemory<T,I>::Element( I i )
-{
- // Avoid function calls in the asserts to improve debug build performance
- Assert( m_nGrowSize != EXTERNAL_CONST_BUFFER_MARKER ); //Assert( !IsReadOnly() );
- Assert( (uint32)i < (uint32)m_nAllocationCount );
- return m_pMemory[i];
-}
-
-template< class T, class I >
-inline const T& CUtlMemory<T,I>::Element( I i ) const
-{
- // Avoid function calls in the asserts to improve debug build performance
- Assert( (uint32)i < (uint32)m_nAllocationCount );
- 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
-{
- // If we always cast 'i' and 'm_nAllocationCount' to unsigned then we can
- // do our range checking with a single comparison instead of two. This gives
- // a modest speedup in debug builds.
- return (uint32)i < (uint32)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
+//========= Copyright 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 "mathlib/mathlib.h"
+
+#include "tier0/memalloc.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 );
+ // Takes ownership of the passed memory, including freeing it when this buffer is destroyed.
+ void AssumeMemory( T *pMemory, int nSize );
+
+ // 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?
+ // Use unsigned math to improve performance
+ bool IsIdxValid( int i ) const { return (size_t)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
+ // Use unsigned math and inlined checks to improve performance.
+ T& operator[]( int i ) { Assert( (size_t)i < SIZE ); return Base()[i]; }
+ const T& operator[]( int i ) const { Assert( (size_t)i < SIZE ); return Base()[i]; }
+ T& Element( int i ) { Assert( (size_t)i < SIZE ); return Base()[i]; }
+ const T& Element( int i ) const { Assert( (size_t)i < SIZE ); 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 ];
+};
+
+#if defined(POSIX)
+// From Chris Green: Memory is a little fuzzy but I believe this class did
+// something fishy with respect to msize and alignment that was OK under our
+// allocator, the glibc allocator, etc but not the valgrind one (which has no
+// padding because it detects all forms of head/tail overwrite, including
+// writing 1 byte past a 1 byte allocation).
+#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();
+}
+
+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( (void*)pMemory, (void*)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;
+}
+
+
+//-----------------------------------------------------------------------------
+// element access
+//-----------------------------------------------------------------------------
+template< class T, class I >
+inline T& CUtlMemory<T,I>::operator[]( I i )
+{
+ // Avoid function calls in the asserts to improve debug build performance
+ Assert( m_nGrowSize != EXTERNAL_CONST_BUFFER_MARKER ); //Assert( !IsReadOnly() );
+ Assert( (uint32)i < (uint32)m_nAllocationCount );
+ return m_pMemory[i];
+}
+
+template< class T, class I >
+inline const T& CUtlMemory<T,I>::operator[]( I i ) const
+{
+ // Avoid function calls in the asserts to improve debug build performance
+ Assert( (uint32)i < (uint32)m_nAllocationCount );
+ return m_pMemory[i];
+}
+
+template< class T, class I >
+inline T& CUtlMemory<T,I>::Element( I i )
+{
+ // Avoid function calls in the asserts to improve debug build performance
+ Assert( m_nGrowSize != EXTERNAL_CONST_BUFFER_MARKER ); //Assert( !IsReadOnly() );
+ Assert( (uint32)i < (uint32)m_nAllocationCount );
+ return m_pMemory[i];
+}
+
+template< class T, class I >
+inline const T& CUtlMemory<T,I>::Element( I i ) const
+{
+ // Avoid function calls in the asserts to improve debug build performance
+ Assert( (uint32)i < (uint32)m_nAllocationCount );
+ 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
+{
+ // If we always cast 'i' and 'm_nAllocationCount' to unsigned then we can
+ // do our range checking with a single comparison instead of two. This gives
+ // a modest speedup in debug builds.
+ return (uint32)i < (uint32)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/mp/src/public/tier1/utlmovingaverage.h b/mp/src/public/tier1/utlmovingaverage.h
index 997b07c9..b91ccb60 100644
--- a/mp/src/public/tier1/utlmovingaverage.h
+++ b/mp/src/public/tier1/utlmovingaverage.h
@@ -1,103 +1,103 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Simple moving average class
-//
-// $NoKeywords: $
-//
-//
-//=============================================================================//
-#ifndef MOVING_AVERAGE_H
-#define MOVING_AVERAGE_H
-
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include "tier0/platform.h"
-#include "tier0/basetypes.h"
-
-template<uint32 TBufferSize> class CUtlMovingAverage
-{
-public:
- CUtlMovingAverage() :
- m_nValuesPushed( 0 ),
- m_flTotal( 0.0f )
- {
- }
-
- void Reset()
- {
- m_nValuesPushed = 0;
- m_flTotal = 0.0f;
- }
-
- uint32 GetTotalValuesPushed() const
- {
- return m_nValuesPushed;
- }
-
- float GetAverage( )
- {
- uint n = MIN( TBufferSize, m_nValuesPushed );
- return n ? ( m_flTotal / static_cast<double>( n ) ) : 0.0f;
- }
-
- void GetAverageAndAbsRange( float *pflOutAverage, float *pflOutAbsRange, float *pflMinTime, float *pflMaxTime )
- {
- if ( m_nValuesPushed == 0 )
- {
- *pflOutAverage = 0;
- *pflOutAbsRange = 0;
- *pflMinTime = 0;
- *pflMaxTime = 0;
- return;
- }
-
- *pflOutAverage = GetAverage();
-
- const int nNumValues = MIN( m_nValuesPushed, TBufferSize );
-
- float flAbsRange = 0;
- float flMinTime = 9e+9;
- float flMaxTime = 0;
-
- for ( int i = 0; i < nNumValues; ++i )
- {
- float flDif = ( m_Buffer[i] - *pflOutAverage );
- flAbsRange = MAX( flAbsRange, abs( flDif ) );
- flMinTime = MIN( flMinTime, m_Buffer[i] );
- flMaxTime = MAX( flMaxTime, m_Buffer[i] );
- }
-
- *pflOutAbsRange = flAbsRange;
- *pflMinTime = flMinTime;
- *pflMaxTime = flMaxTime;
- }
-
- void PushValue( float v )
- {
- uint nIndex = m_nValuesPushed % TBufferSize;
-
- if ( m_nValuesPushed >= TBufferSize )
- {
- m_flTotal = MAX( m_flTotal - m_Buffer[nIndex], 0.0f );
- }
- m_flTotal += v;
-
- m_Buffer[nIndex] = v;
- m_nValuesPushed++;
-
- if ( UINT_MAX == m_nValuesPushed )
- {
- Reset();
- }
- }
-
-private:
- float m_Buffer[TBufferSize];
- uint32 m_nValuesPushed;
-
- double m_flTotal;
-};
-
-#endif // MOVING_AVERAGE_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Simple moving average class
+//
+// $NoKeywords: $
+//
+//
+//=============================================================================//
+#ifndef MOVING_AVERAGE_H
+#define MOVING_AVERAGE_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/platform.h"
+#include "tier0/basetypes.h"
+
+template<uint32 TBufferSize> class CUtlMovingAverage
+{
+public:
+ CUtlMovingAverage() :
+ m_nValuesPushed( 0 ),
+ m_flTotal( 0.0f )
+ {
+ }
+
+ void Reset()
+ {
+ m_nValuesPushed = 0;
+ m_flTotal = 0.0f;
+ }
+
+ uint32 GetTotalValuesPushed() const
+ {
+ return m_nValuesPushed;
+ }
+
+ float GetAverage( )
+ {
+ uint n = MIN( TBufferSize, m_nValuesPushed );
+ return n ? ( m_flTotal / static_cast<double>( n ) ) : 0.0f;
+ }
+
+ void GetAverageAndAbsRange( float *pflOutAverage, float *pflOutAbsRange, float *pflMinTime, float *pflMaxTime )
+ {
+ if ( m_nValuesPushed == 0 )
+ {
+ *pflOutAverage = 0;
+ *pflOutAbsRange = 0;
+ *pflMinTime = 0;
+ *pflMaxTime = 0;
+ return;
+ }
+
+ *pflOutAverage = GetAverage();
+
+ const int nNumValues = MIN( m_nValuesPushed, TBufferSize );
+
+ float flAbsRange = 0;
+ float flMinTime = 9e+9;
+ float flMaxTime = 0;
+
+ for ( int i = 0; i < nNumValues; ++i )
+ {
+ float flDif = ( m_Buffer[i] - *pflOutAverage );
+ flAbsRange = MAX( flAbsRange, abs( flDif ) );
+ flMinTime = MIN( flMinTime, m_Buffer[i] );
+ flMaxTime = MAX( flMaxTime, m_Buffer[i] );
+ }
+
+ *pflOutAbsRange = flAbsRange;
+ *pflMinTime = flMinTime;
+ *pflMaxTime = flMaxTime;
+ }
+
+ void PushValue( float v )
+ {
+ uint nIndex = m_nValuesPushed % TBufferSize;
+
+ if ( m_nValuesPushed >= TBufferSize )
+ {
+ m_flTotal = MAX( m_flTotal - m_Buffer[nIndex], 0.0f );
+ }
+ m_flTotal += v;
+
+ m_Buffer[nIndex] = v;
+ m_nValuesPushed++;
+
+ if ( UINT_MAX == m_nValuesPushed )
+ {
+ Reset();
+ }
+ }
+
+private:
+ float m_Buffer[TBufferSize];
+ uint32 m_nValuesPushed;
+
+ double m_flTotal;
+};
+
+#endif // MOVING_AVERAGE_H
diff --git a/mp/src/public/tier1/utlmultilist.h b/mp/src/public/tier1/utlmultilist.h
index 95df4523..c677746c 100644
--- a/mp/src/public/tier1/utlmultilist.h
+++ b/mp/src/public/tier1/utlmultilist.h
@@ -1,769 +1,769 @@
-//========= Copyright 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
+//========= Copyright 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/mp/src/public/tier1/utlntree.h b/mp/src/public/tier1/utlntree.h
index 7092b605..463b5e16 100644
--- a/mp/src/public/tier1/utlntree.h
+++ b/mp/src/public/tier1/utlntree.h
@@ -1,624 +1,624 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: N-way tree container class
-//
-// $Revision: $
-// $NoKeywords: $
-//=============================================================================//
-
-#ifndef UTLNTREE_H
-#define UTLNTREE_H
-
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include "basetypes.h"
-#include "utlmemory.h"
-#include "tier0/dbg.h"
-
-
-#define INVALID_NTREE_IDX ((I)~0)
-
-//-----------------------------------------------------------------------------
-// class CUtlNTree:
-// 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.
-//-----------------------------------------------------------------------------
-template <class T, class I = unsigned short>
-class CUtlNTree
-{
-public:
- typedef T ElemType_t;
- typedef I IndexType_t;
-
- // constructor, destructor
- CUtlNTree( int growSize = 0, int initSize = 0 );
- CUtlNTree( void *pMemory, int memsize );
- ~CUtlNTree( );
-
- // gets particular elements
- T& Element( I i );
- const T& Element( I i ) const;
- T& operator[]( I i );
- const T& operator[]( I i ) const;
-
- // Make sure we have a particular amount of memory
- void EnsureCapacity( int num );
-
- // Clears the tree, doesn't deallocate memory
- void RemoveAll();
-
- // Memory deallocation
- void Purge();
-
- // Allocation/deallocation methods
- I Alloc( );
- void Free( I elem );
- void FreeSubTree( I elem );
-
- // list modification
- void SetRoot( I root );
- void LinkChildBefore( I parent, I before, I elem );
- void LinkChildAfter( I parent, I after, I elem );
- void Unlink( I elem );
-
- // Alloc + link combined
- I InsertChildBefore( I parent, I before );
- I InsertChildAfter( I parent, I after );
- I InsertChildBefore( I parent, I before, const T &elem );
- I InsertChildAfter( I parent, I after, const T &elem );
-
- // Unlink + free combined
- void Remove( I elem );
- void RemoveSubTree( I elem );
-
- // invalid index
- inline static I InvalidIndex() { return INVALID_NTREE_IDX; }
- inline static size_t ElementSize() { return sizeof(Node_t); }
-
- // list statistics
- int Count() const;
- I MaxElementIndex() const;
-
- // Traversing the list
- I Root() const;
- I FirstChild( I i ) const;
- I PrevSibling( I i ) const;
- I NextSibling( I i ) const;
- I Parent( I i ) const;
-
- // Are nodes in the list or valid?
- bool IsValidIndex( I i ) const;
- bool IsInTree( I i ) const;
-
-protected:
- // What the linked list element looks like
- struct Node_t
- {
- T m_Element;
- I m_Parent;
- I m_FirstChild;
- I m_PrevSibling;
- I m_NextSibling;
-
- private:
- // No copy constructor for these...
- Node_t( const Node_t& );
- };
-
- // constructs the class
- void ConstructList();
-
- // Allocates the element, doesn't call the constructor
- I AllocInternal();
-
- // Gets at the node element....
- Node_t& InternalNode( I i ) { return m_Memory[i]; }
- const Node_t& InternalNode( I i ) const { return m_Memory[i]; }
-
- void ResetDbgInfo()
- {
- m_pElements = m_Memory.Base();
- }
-
- // copy constructors not allowed
- CUtlNTree( CUtlNTree<T, I> const& tree ) { Assert(0); }
-
- CUtlMemory<Node_t> m_Memory;
- I m_Root;
- I m_FirstFree;
- I m_ElementCount; // The number actually in the tree
- I m_MaxElementIndex; // The max index we've ever assigned
-
- // For debugging purposes;
- // it's in release builds so this can be used in libraries correctly
- Node_t *m_pElements;
-};
-
-
-//-----------------------------------------------------------------------------
-// constructor, destructor
-//-----------------------------------------------------------------------------
-
-template <class T, class I>
-CUtlNTree<T,I>::CUtlNTree( int growSize, int initSize ) :
- m_Memory(growSize, initSize)
-{
- ConstructList();
- ResetDbgInfo();
-}
-
-template <class T, class I>
-CUtlNTree<T,I>::CUtlNTree( void* pMemory, int memsize ) :
- m_Memory(pMemory, memsize/sizeof(T))
-{
- ConstructList();
- ResetDbgInfo();
-}
-
-template <class T, class I>
-CUtlNTree<T,I>::~CUtlNTree( )
-{
- RemoveAll();
-}
-
-template <class T, class I>
-void CUtlNTree<T,I>::ConstructList()
-{
- m_Root = InvalidIndex();
- m_FirstFree = InvalidIndex();
- m_ElementCount = m_MaxElementIndex = 0;
-}
-
-
-//-----------------------------------------------------------------------------
-// gets particular elements
-//-----------------------------------------------------------------------------
-template <class T, class I>
-inline T& CUtlNTree<T,I>::Element( I i )
-{
- return m_Memory[i].m_Element;
-}
-
-template <class T, class I>
-inline const T& CUtlNTree<T,I>::Element( I i ) const
-{
- return m_Memory[i].m_Element;
-}
-
-template <class T, class I>
-inline T& CUtlNTree<T,I>::operator[]( I i )
-{
- return m_Memory[i].m_Element;
-}
-
-template <class T, class I>
-inline const T& CUtlNTree<T,I>::operator[]( I i ) const
-{
- return m_Memory[i].m_Element;
-}
-
-
-//-----------------------------------------------------------------------------
-// list statistics
-//-----------------------------------------------------------------------------
-template <class T, class I>
-inline int CUtlNTree<T,I>::Count() const
-{
- return m_ElementCount;
-}
-
-template <class T, class I>
-inline I CUtlNTree<T,I>::MaxElementIndex() const
-{
- return m_MaxElementIndex;
-}
-
-
-//-----------------------------------------------------------------------------
-// Traversing the list
-//-----------------------------------------------------------------------------
-template <class T, class I>
-inline I CUtlNTree<T,I>::Root() const
-{
- return m_Root;
-}
-
-template <class T, class I>
-inline I CUtlNTree<T,I>::FirstChild( I i ) const
-{
- Assert( IsInTree(i) );
- return InternalNode(i).m_FirstChild;
-}
-
-template <class T, class I>
-inline I CUtlNTree<T,I>::PrevSibling( I i ) const
-{
- Assert( IsInTree(i) );
- return InternalNode(i).m_PrevSibling;
-}
-
-template <class T, class I>
-inline I CUtlNTree<T,I>::NextSibling( I i ) const
-{
- Assert( IsInTree(i) );
- return InternalNode(i).m_NextSibling;
-}
-
-template <class T, class I>
-inline I CUtlNTree<T,I>::Parent( I i ) const
-{
- Assert( IsInTree(i) );
- return InternalNode(i).m_Parent;
-}
-
-
-//-----------------------------------------------------------------------------
-// Are nodes in the list or valid?
-//-----------------------------------------------------------------------------
-template <class T, class I>
-inline bool CUtlNTree<T,I>::IsValidIndex( I i ) const
-{
- return (i < m_MaxElementIndex) && (i >= 0);
-}
-
-template <class T, class I>
-inline bool CUtlNTree<T,I>::IsInTree( I i ) const
-{
- return (i < m_MaxElementIndex) && (i >= 0) && (InternalNode(i).m_PrevSibling != i);
-}
-
-
-//-----------------------------------------------------------------------------
-// Makes sure we have enough memory allocated to store a requested # of elements
-//-----------------------------------------------------------------------------
-template< class T, class I >
-void CUtlNTree<T, I>::EnsureCapacity( int num )
-{
- MEM_ALLOC_CREDIT_CLASS();
- m_Memory.EnsureCapacity(num);
- ResetDbgInfo();
-}
-
-
-//-----------------------------------------------------------------------------
-// Deallocate memory
-//-----------------------------------------------------------------------------
-template <class T, class I>
-void CUtlNTree<T,I>::Purge()
-{
- RemoveAll();
- m_Memory.Purge( );
- m_FirstFree = InvalidIndex();
- m_MaxElementIndex = 0;
- ResetDbgInfo();
-}
-
-
-//-----------------------------------------------------------------------------
-// Node allocation/deallocation
-//-----------------------------------------------------------------------------
-template <class T, class I>
-I CUtlNTree<T,I>::AllocInternal( )
-{
- I elem;
- if ( m_FirstFree == INVALID_NTREE_IDX )
- {
- // Nothing in the free list; add.
- // Since nothing is in the free list, m_MaxElementIndex == total # of elements
- // the list knows about.
- if ((int)m_MaxElementIndex == m_Memory.NumAllocated())
- {
- MEM_ALLOC_CREDIT_CLASS();
- m_Memory.Grow();
- }
-
- Assert( m_MaxElementIndex != INVALID_NTREE_IDX );
-
- elem = (I)m_MaxElementIndex;
- ++m_MaxElementIndex;
-
- if ( elem == InvalidIndex() )
- {
- Error("CUtlNTree overflow!\n");
- }
- }
- else
- {
- elem = m_FirstFree;
- m_FirstFree = InternalNode( m_FirstFree ).m_NextSibling;
- }
-
- Node_t &node = InternalNode( elem );
- node.m_NextSibling = node.m_PrevSibling = node.m_Parent = node.m_FirstChild = INVALID_NTREE_IDX;
- ResetDbgInfo();
-
- // one more element baby
- ++m_ElementCount;
-
- return elem;
-}
-
-template <class T, class I>
-I CUtlNTree<T,I>::Alloc( )
-{
- I elem = AllocInternal();
- Construct( &Element(elem) );
- return elem;
-}
-
-template <class T, class I>
-void CUtlNTree<T,I>::Free( I elem )
-{
- Assert( IsInTree( elem ) );
- Unlink( elem );
-
- // If there's children, this will result in leaks. Use FreeSubTree instead.
- Assert( FirstChild( elem ) == INVALID_NTREE_IDX );
-
- Node_t &node = InternalNode( elem );
- Destruct( &node.m_Element );
- node.m_NextSibling = m_FirstFree;
- node.m_PrevSibling = elem; // Marks it as being in the free list
- node.m_Parent = node.m_FirstChild = INVALID_NTREE_IDX;
- m_FirstFree = elem;
-
- // one less element baby
- --m_ElementCount;
-}
-
-template <class T, class I>
-void CUtlNTree<T,I>::FreeSubTree( I elem )
-{
- Assert( IsValidIndex( elem ) );
-
- I child = FirstChild( elem );
- while ( child != INVALID_NTREE_IDX )
- {
- I next = NextSibling( child );
- FreeSubTree( child );
- child = next;
- }
-
- Free( elem );
-}
-
-
-//-----------------------------------------------------------------------------
-// Clears the tree
-//-----------------------------------------------------------------------------
-template <class T, class I>
-void CUtlNTree<T,I>::RemoveAll()
-{
- if ( m_MaxElementIndex == 0 )
- return;
-
- // Put everything into the free list (even unlinked things )
- I prev = InvalidIndex();
- for (int i = (int)m_MaxElementIndex; --i >= 0; prev = (I)i )
- {
- Node_t &node = InternalNode( i );
- if ( IsInTree( i ) )
- {
- Destruct( &node.m_Element );
- }
-
- node.m_NextSibling = prev;
- node.m_PrevSibling = (I)i; // Marks it as being in the free list
- node.m_Parent = node.m_FirstChild = INVALID_NTREE_IDX;
- }
-
- // First free points to the first element
- m_FirstFree = 0;
-
- // Clear everything else out
- m_Root = INVALID_NTREE_IDX;
- m_ElementCount = 0;
-}
-
-
-//-----------------------------------------------------------------------------
-// list modification
-//-----------------------------------------------------------------------------
-template <class T, class I>
-void CUtlNTree<T,I>::SetRoot( I root )
-{
- // Resetting the root while it's got stuff in it is bad...
- Assert( m_Root == InvalidIndex() );
- m_Root = root;
-}
-
-
-//-----------------------------------------------------------------------------
-// Links a node after a particular node
-//-----------------------------------------------------------------------------
-template <class T, class I>
-void CUtlNTree<T,I>::LinkChildAfter( I parent, I after, I elem )
-{
- Assert( IsInTree(elem) );
-
- // Unlink it if it's in the list at the moment
- Unlink(elem);
-
- Node_t& newElem = InternalNode(elem);
- newElem.m_Parent = parent;
- newElem.m_PrevSibling = after;
- if ( after != INVALID_NTREE_IDX )
- {
- Node_t& prevSiblingNode = InternalNode( after );
- newElem.m_NextSibling = prevSiblingNode.m_NextSibling;
- prevSiblingNode.m_NextSibling = elem;
- }
- else
- {
- if ( parent != INVALID_NTREE_IDX )
- {
- Node_t& parentNode = InternalNode( parent );
- newElem.m_NextSibling = parentNode.m_FirstChild;
- parentNode.m_FirstChild = elem;
- }
- else
- {
- newElem.m_NextSibling = m_Root;
- if ( m_Root != INVALID_NTREE_IDX )
- {
- Node_t& rootNode = InternalNode( m_Root );
- rootNode.m_PrevSibling = elem;
- }
- m_Root = elem;
- }
- }
-
- if ( newElem.m_NextSibling != INVALID_NTREE_IDX )
- {
- Node_t& nextSiblingNode = InternalNode( newElem.m_NextSibling );
- nextSiblingNode.m_PrevSibling = elem;
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Links a node before a particular node
-//-----------------------------------------------------------------------------
-template <class T, class I>
-void CUtlNTree<T,I>::LinkChildBefore( I parent, I before, I elem )
-{
- Assert( IsValidIndex(elem) );
-
- if ( before != INVALID_NTREE_IDX )
- {
- LinkChildAfter( parent, InternalNode( before ).m_PrevSibling, elem );
- return;
- }
-
- // NOTE: I made the choice to do an O(n) operation here
- // instead of store more data per node (LastChild).
- // This might not be the right choice. Revisit if we get perf problems.
- I after;
- if ( parent != INVALID_NTREE_IDX )
- {
- after = InternalNode( parent ).m_FirstChild;
- }
- else
- {
- after = m_Root;
- }
-
- if ( after == INVALID_NTREE_IDX )
- {
- LinkChildAfter( parent, after, elem );
- return;
- }
-
- I next = InternalNode( after ).m_NextSibling;
- while ( next != InvalidIndex() )
- {
- after = next;
- next = InternalNode( next ).m_NextSibling;
- }
-
- LinkChildAfter( parent, after, elem );
-}
-
-
-//-----------------------------------------------------------------------------
-// Unlinks a node from the tree
-//-----------------------------------------------------------------------------
-template <class T, class I>
-void CUtlNTree<T,I>::Unlink( I elem )
-{
- Assert( IsInTree(elem) );
-
- Node_t *pOldNode = &InternalNode( elem );
-
- // If we're the first guy, reset the head
- // otherwise, make our previous node's next pointer = our next
- if ( pOldNode->m_PrevSibling != INVALID_NTREE_IDX )
- {
- InternalNode( pOldNode->m_PrevSibling ).m_NextSibling = pOldNode->m_NextSibling;
- }
- else
- {
- if ( pOldNode->m_Parent != INVALID_NTREE_IDX )
- {
- InternalNode( pOldNode->m_Parent ).m_FirstChild = pOldNode->m_NextSibling;
- }
- else if ( m_Root == elem )
- {
- m_Root = pOldNode->m_NextSibling;
- }
- }
-
- // If we're the last guy, reset the tail
- // otherwise, make our next node's prev pointer = our prev
- if ( pOldNode->m_NextSibling != INVALID_NTREE_IDX )
- {
- InternalNode( pOldNode->m_NextSibling ).m_PrevSibling = pOldNode->m_PrevSibling;
- }
-
- // Unlink everything except children
- pOldNode->m_Parent = pOldNode->m_PrevSibling = pOldNode->m_NextSibling = INVALID_NTREE_IDX;
-}
-
-
-//-----------------------------------------------------------------------------
-// Alloc + link combined
-//-----------------------------------------------------------------------------
-template <class T, class I>
-I CUtlNTree<T,I>::InsertChildBefore( I parent, I before )
-{
- I elem = AllocInternal();
- Construct( &Element( elem ) );
- LinkChildBefore( parent, before, elem );
- return elem;
-}
-
-template <class T, class I>
-I CUtlNTree<T,I>::InsertChildAfter( I parent, I after )
-{
- I elem = AllocInternal();
- Construct( &Element( elem ) );
- LinkChildAfter( parent, after, elem );
- return elem;
-}
-
-template <class T, class I>
-I CUtlNTree<T,I>::InsertChildBefore( I parent, I before, const T &data )
-{
- I elem = AllocInternal();
- CopyConstruct( &Element( elem ), data );
- LinkChildBefore( parent, before, elem );
- return elem;
-}
-
-template <class T, class I>
-I CUtlNTree<T,I>::InsertChildAfter( I parent, I after, const T &data )
-{
- I elem = AllocInternal();
- CopyConstruct( &Element( elem ), data );
- LinkChildAfter( parent, after, elem );
- return elem;
-}
-
-
-//-----------------------------------------------------------------------------
-// Unlink + free combined
-//-----------------------------------------------------------------------------
-template <class T, class I>
-void CUtlNTree<T,I>::Remove( I elem )
-{
- Unlink( elem );
- Free( elem );
-}
-
-template <class T, class I>
-void CUtlNTree<T,I>::RemoveSubTree( I elem )
-{
- UnlinkSubTree( elem );
- Free( elem );
-}
-
-
-#endif // UTLNTREE_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: N-way tree container class
+//
+// $Revision: $
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef UTLNTREE_H
+#define UTLNTREE_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "basetypes.h"
+#include "utlmemory.h"
+#include "tier0/dbg.h"
+
+
+#define INVALID_NTREE_IDX ((I)~0)
+
+//-----------------------------------------------------------------------------
+// class CUtlNTree:
+// 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.
+//-----------------------------------------------------------------------------
+template <class T, class I = unsigned short>
+class CUtlNTree
+{
+public:
+ typedef T ElemType_t;
+ typedef I IndexType_t;
+
+ // constructor, destructor
+ CUtlNTree( int growSize = 0, int initSize = 0 );
+ CUtlNTree( void *pMemory, int memsize );
+ ~CUtlNTree( );
+
+ // gets particular elements
+ T& Element( I i );
+ const T& Element( I i ) const;
+ T& operator[]( I i );
+ const T& operator[]( I i ) const;
+
+ // Make sure we have a particular amount of memory
+ void EnsureCapacity( int num );
+
+ // Clears the tree, doesn't deallocate memory
+ void RemoveAll();
+
+ // Memory deallocation
+ void Purge();
+
+ // Allocation/deallocation methods
+ I Alloc( );
+ void Free( I elem );
+ void FreeSubTree( I elem );
+
+ // list modification
+ void SetRoot( I root );
+ void LinkChildBefore( I parent, I before, I elem );
+ void LinkChildAfter( I parent, I after, I elem );
+ void Unlink( I elem );
+
+ // Alloc + link combined
+ I InsertChildBefore( I parent, I before );
+ I InsertChildAfter( I parent, I after );
+ I InsertChildBefore( I parent, I before, const T &elem );
+ I InsertChildAfter( I parent, I after, const T &elem );
+
+ // Unlink + free combined
+ void Remove( I elem );
+ void RemoveSubTree( I elem );
+
+ // invalid index
+ inline static I InvalidIndex() { return INVALID_NTREE_IDX; }
+ inline static size_t ElementSize() { return sizeof(Node_t); }
+
+ // list statistics
+ int Count() const;
+ I MaxElementIndex() const;
+
+ // Traversing the list
+ I Root() const;
+ I FirstChild( I i ) const;
+ I PrevSibling( I i ) const;
+ I NextSibling( I i ) const;
+ I Parent( I i ) const;
+
+ // Are nodes in the list or valid?
+ bool IsValidIndex( I i ) const;
+ bool IsInTree( I i ) const;
+
+protected:
+ // What the linked list element looks like
+ struct Node_t
+ {
+ T m_Element;
+ I m_Parent;
+ I m_FirstChild;
+ I m_PrevSibling;
+ I m_NextSibling;
+
+ private:
+ // No copy constructor for these...
+ Node_t( const Node_t& );
+ };
+
+ // constructs the class
+ void ConstructList();
+
+ // Allocates the element, doesn't call the constructor
+ I AllocInternal();
+
+ // Gets at the node element....
+ Node_t& InternalNode( I i ) { return m_Memory[i]; }
+ const Node_t& InternalNode( I i ) const { return m_Memory[i]; }
+
+ void ResetDbgInfo()
+ {
+ m_pElements = m_Memory.Base();
+ }
+
+ // copy constructors not allowed
+ CUtlNTree( CUtlNTree<T, I> const& tree ) { Assert(0); }
+
+ CUtlMemory<Node_t> m_Memory;
+ I m_Root;
+ I m_FirstFree;
+ I m_ElementCount; // The number actually in the tree
+ I m_MaxElementIndex; // The max index we've ever assigned
+
+ // For debugging purposes;
+ // it's in release builds so this can be used in libraries correctly
+ Node_t *m_pElements;
+};
+
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+
+template <class T, class I>
+CUtlNTree<T,I>::CUtlNTree( int growSize, int initSize ) :
+ m_Memory(growSize, initSize)
+{
+ ConstructList();
+ ResetDbgInfo();
+}
+
+template <class T, class I>
+CUtlNTree<T,I>::CUtlNTree( void* pMemory, int memsize ) :
+ m_Memory(pMemory, memsize/sizeof(T))
+{
+ ConstructList();
+ ResetDbgInfo();
+}
+
+template <class T, class I>
+CUtlNTree<T,I>::~CUtlNTree( )
+{
+ RemoveAll();
+}
+
+template <class T, class I>
+void CUtlNTree<T,I>::ConstructList()
+{
+ m_Root = InvalidIndex();
+ m_FirstFree = InvalidIndex();
+ m_ElementCount = m_MaxElementIndex = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// gets particular elements
+//-----------------------------------------------------------------------------
+template <class T, class I>
+inline T& CUtlNTree<T,I>::Element( I i )
+{
+ return m_Memory[i].m_Element;
+}
+
+template <class T, class I>
+inline const T& CUtlNTree<T,I>::Element( I i ) const
+{
+ return m_Memory[i].m_Element;
+}
+
+template <class T, class I>
+inline T& CUtlNTree<T,I>::operator[]( I i )
+{
+ return m_Memory[i].m_Element;
+}
+
+template <class T, class I>
+inline const T& CUtlNTree<T,I>::operator[]( I i ) const
+{
+ return m_Memory[i].m_Element;
+}
+
+
+//-----------------------------------------------------------------------------
+// list statistics
+//-----------------------------------------------------------------------------
+template <class T, class I>
+inline int CUtlNTree<T,I>::Count() const
+{
+ return m_ElementCount;
+}
+
+template <class T, class I>
+inline I CUtlNTree<T,I>::MaxElementIndex() const
+{
+ return m_MaxElementIndex;
+}
+
+
+//-----------------------------------------------------------------------------
+// Traversing the list
+//-----------------------------------------------------------------------------
+template <class T, class I>
+inline I CUtlNTree<T,I>::Root() const
+{
+ return m_Root;
+}
+
+template <class T, class I>
+inline I CUtlNTree<T,I>::FirstChild( I i ) const
+{
+ Assert( IsInTree(i) );
+ return InternalNode(i).m_FirstChild;
+}
+
+template <class T, class I>
+inline I CUtlNTree<T,I>::PrevSibling( I i ) const
+{
+ Assert( IsInTree(i) );
+ return InternalNode(i).m_PrevSibling;
+}
+
+template <class T, class I>
+inline I CUtlNTree<T,I>::NextSibling( I i ) const
+{
+ Assert( IsInTree(i) );
+ return InternalNode(i).m_NextSibling;
+}
+
+template <class T, class I>
+inline I CUtlNTree<T,I>::Parent( I i ) const
+{
+ Assert( IsInTree(i) );
+ return InternalNode(i).m_Parent;
+}
+
+
+//-----------------------------------------------------------------------------
+// Are nodes in the list or valid?
+//-----------------------------------------------------------------------------
+template <class T, class I>
+inline bool CUtlNTree<T,I>::IsValidIndex( I i ) const
+{
+ return (i < m_MaxElementIndex) && (i >= 0);
+}
+
+template <class T, class I>
+inline bool CUtlNTree<T,I>::IsInTree( I i ) const
+{
+ return (i < m_MaxElementIndex) && (i >= 0) && (InternalNode(i).m_PrevSibling != i);
+}
+
+
+//-----------------------------------------------------------------------------
+// Makes sure we have enough memory allocated to store a requested # of elements
+//-----------------------------------------------------------------------------
+template< class T, class I >
+void CUtlNTree<T, I>::EnsureCapacity( int num )
+{
+ MEM_ALLOC_CREDIT_CLASS();
+ m_Memory.EnsureCapacity(num);
+ ResetDbgInfo();
+}
+
+
+//-----------------------------------------------------------------------------
+// Deallocate memory
+//-----------------------------------------------------------------------------
+template <class T, class I>
+void CUtlNTree<T,I>::Purge()
+{
+ RemoveAll();
+ m_Memory.Purge( );
+ m_FirstFree = InvalidIndex();
+ m_MaxElementIndex = 0;
+ ResetDbgInfo();
+}
+
+
+//-----------------------------------------------------------------------------
+// Node allocation/deallocation
+//-----------------------------------------------------------------------------
+template <class T, class I>
+I CUtlNTree<T,I>::AllocInternal( )
+{
+ I elem;
+ if ( m_FirstFree == INVALID_NTREE_IDX )
+ {
+ // Nothing in the free list; add.
+ // Since nothing is in the free list, m_MaxElementIndex == total # of elements
+ // the list knows about.
+ if ((int)m_MaxElementIndex == m_Memory.NumAllocated())
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ m_Memory.Grow();
+ }
+
+ Assert( m_MaxElementIndex != INVALID_NTREE_IDX );
+
+ elem = (I)m_MaxElementIndex;
+ ++m_MaxElementIndex;
+
+ if ( elem == InvalidIndex() )
+ {
+ Error("CUtlNTree overflow!\n");
+ }
+ }
+ else
+ {
+ elem = m_FirstFree;
+ m_FirstFree = InternalNode( m_FirstFree ).m_NextSibling;
+ }
+
+ Node_t &node = InternalNode( elem );
+ node.m_NextSibling = node.m_PrevSibling = node.m_Parent = node.m_FirstChild = INVALID_NTREE_IDX;
+ ResetDbgInfo();
+
+ // one more element baby
+ ++m_ElementCount;
+
+ return elem;
+}
+
+template <class T, class I>
+I CUtlNTree<T,I>::Alloc( )
+{
+ I elem = AllocInternal();
+ Construct( &Element(elem) );
+ return elem;
+}
+
+template <class T, class I>
+void CUtlNTree<T,I>::Free( I elem )
+{
+ Assert( IsInTree( elem ) );
+ Unlink( elem );
+
+ // If there's children, this will result in leaks. Use FreeSubTree instead.
+ Assert( FirstChild( elem ) == INVALID_NTREE_IDX );
+
+ Node_t &node = InternalNode( elem );
+ Destruct( &node.m_Element );
+ node.m_NextSibling = m_FirstFree;
+ node.m_PrevSibling = elem; // Marks it as being in the free list
+ node.m_Parent = node.m_FirstChild = INVALID_NTREE_IDX;
+ m_FirstFree = elem;
+
+ // one less element baby
+ --m_ElementCount;
+}
+
+template <class T, class I>
+void CUtlNTree<T,I>::FreeSubTree( I elem )
+{
+ Assert( IsValidIndex( elem ) );
+
+ I child = FirstChild( elem );
+ while ( child != INVALID_NTREE_IDX )
+ {
+ I next = NextSibling( child );
+ FreeSubTree( child );
+ child = next;
+ }
+
+ Free( elem );
+}
+
+
+//-----------------------------------------------------------------------------
+// Clears the tree
+//-----------------------------------------------------------------------------
+template <class T, class I>
+void CUtlNTree<T,I>::RemoveAll()
+{
+ if ( m_MaxElementIndex == 0 )
+ return;
+
+ // Put everything into the free list (even unlinked things )
+ I prev = InvalidIndex();
+ for (int i = (int)m_MaxElementIndex; --i >= 0; prev = (I)i )
+ {
+ Node_t &node = InternalNode( i );
+ if ( IsInTree( i ) )
+ {
+ Destruct( &node.m_Element );
+ }
+
+ node.m_NextSibling = prev;
+ node.m_PrevSibling = (I)i; // Marks it as being in the free list
+ node.m_Parent = node.m_FirstChild = INVALID_NTREE_IDX;
+ }
+
+ // First free points to the first element
+ m_FirstFree = 0;
+
+ // Clear everything else out
+ m_Root = INVALID_NTREE_IDX;
+ m_ElementCount = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// list modification
+//-----------------------------------------------------------------------------
+template <class T, class I>
+void CUtlNTree<T,I>::SetRoot( I root )
+{
+ // Resetting the root while it's got stuff in it is bad...
+ Assert( m_Root == InvalidIndex() );
+ m_Root = root;
+}
+
+
+//-----------------------------------------------------------------------------
+// Links a node after a particular node
+//-----------------------------------------------------------------------------
+template <class T, class I>
+void CUtlNTree<T,I>::LinkChildAfter( I parent, I after, I elem )
+{
+ Assert( IsInTree(elem) );
+
+ // Unlink it if it's in the list at the moment
+ Unlink(elem);
+
+ Node_t& newElem = InternalNode(elem);
+ newElem.m_Parent = parent;
+ newElem.m_PrevSibling = after;
+ if ( after != INVALID_NTREE_IDX )
+ {
+ Node_t& prevSiblingNode = InternalNode( after );
+ newElem.m_NextSibling = prevSiblingNode.m_NextSibling;
+ prevSiblingNode.m_NextSibling = elem;
+ }
+ else
+ {
+ if ( parent != INVALID_NTREE_IDX )
+ {
+ Node_t& parentNode = InternalNode( parent );
+ newElem.m_NextSibling = parentNode.m_FirstChild;
+ parentNode.m_FirstChild = elem;
+ }
+ else
+ {
+ newElem.m_NextSibling = m_Root;
+ if ( m_Root != INVALID_NTREE_IDX )
+ {
+ Node_t& rootNode = InternalNode( m_Root );
+ rootNode.m_PrevSibling = elem;
+ }
+ m_Root = elem;
+ }
+ }
+
+ if ( newElem.m_NextSibling != INVALID_NTREE_IDX )
+ {
+ Node_t& nextSiblingNode = InternalNode( newElem.m_NextSibling );
+ nextSiblingNode.m_PrevSibling = elem;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Links a node before a particular node
+//-----------------------------------------------------------------------------
+template <class T, class I>
+void CUtlNTree<T,I>::LinkChildBefore( I parent, I before, I elem )
+{
+ Assert( IsValidIndex(elem) );
+
+ if ( before != INVALID_NTREE_IDX )
+ {
+ LinkChildAfter( parent, InternalNode( before ).m_PrevSibling, elem );
+ return;
+ }
+
+ // NOTE: I made the choice to do an O(n) operation here
+ // instead of store more data per node (LastChild).
+ // This might not be the right choice. Revisit if we get perf problems.
+ I after;
+ if ( parent != INVALID_NTREE_IDX )
+ {
+ after = InternalNode( parent ).m_FirstChild;
+ }
+ else
+ {
+ after = m_Root;
+ }
+
+ if ( after == INVALID_NTREE_IDX )
+ {
+ LinkChildAfter( parent, after, elem );
+ return;
+ }
+
+ I next = InternalNode( after ).m_NextSibling;
+ while ( next != InvalidIndex() )
+ {
+ after = next;
+ next = InternalNode( next ).m_NextSibling;
+ }
+
+ LinkChildAfter( parent, after, elem );
+}
+
+
+//-----------------------------------------------------------------------------
+// Unlinks a node from the tree
+//-----------------------------------------------------------------------------
+template <class T, class I>
+void CUtlNTree<T,I>::Unlink( I elem )
+{
+ Assert( IsInTree(elem) );
+
+ Node_t *pOldNode = &InternalNode( elem );
+
+ // If we're the first guy, reset the head
+ // otherwise, make our previous node's next pointer = our next
+ if ( pOldNode->m_PrevSibling != INVALID_NTREE_IDX )
+ {
+ InternalNode( pOldNode->m_PrevSibling ).m_NextSibling = pOldNode->m_NextSibling;
+ }
+ else
+ {
+ if ( pOldNode->m_Parent != INVALID_NTREE_IDX )
+ {
+ InternalNode( pOldNode->m_Parent ).m_FirstChild = pOldNode->m_NextSibling;
+ }
+ else if ( m_Root == elem )
+ {
+ m_Root = pOldNode->m_NextSibling;
+ }
+ }
+
+ // If we're the last guy, reset the tail
+ // otherwise, make our next node's prev pointer = our prev
+ if ( pOldNode->m_NextSibling != INVALID_NTREE_IDX )
+ {
+ InternalNode( pOldNode->m_NextSibling ).m_PrevSibling = pOldNode->m_PrevSibling;
+ }
+
+ // Unlink everything except children
+ pOldNode->m_Parent = pOldNode->m_PrevSibling = pOldNode->m_NextSibling = INVALID_NTREE_IDX;
+}
+
+
+//-----------------------------------------------------------------------------
+// Alloc + link combined
+//-----------------------------------------------------------------------------
+template <class T, class I>
+I CUtlNTree<T,I>::InsertChildBefore( I parent, I before )
+{
+ I elem = AllocInternal();
+ Construct( &Element( elem ) );
+ LinkChildBefore( parent, before, elem );
+ return elem;
+}
+
+template <class T, class I>
+I CUtlNTree<T,I>::InsertChildAfter( I parent, I after )
+{
+ I elem = AllocInternal();
+ Construct( &Element( elem ) );
+ LinkChildAfter( parent, after, elem );
+ return elem;
+}
+
+template <class T, class I>
+I CUtlNTree<T,I>::InsertChildBefore( I parent, I before, const T &data )
+{
+ I elem = AllocInternal();
+ CopyConstruct( &Element( elem ), data );
+ LinkChildBefore( parent, before, elem );
+ return elem;
+}
+
+template <class T, class I>
+I CUtlNTree<T,I>::InsertChildAfter( I parent, I after, const T &data )
+{
+ I elem = AllocInternal();
+ CopyConstruct( &Element( elem ), data );
+ LinkChildAfter( parent, after, elem );
+ return elem;
+}
+
+
+//-----------------------------------------------------------------------------
+// Unlink + free combined
+//-----------------------------------------------------------------------------
+template <class T, class I>
+void CUtlNTree<T,I>::Remove( I elem )
+{
+ Unlink( elem );
+ Free( elem );
+}
+
+template <class T, class I>
+void CUtlNTree<T,I>::RemoveSubTree( I elem )
+{
+ UnlinkSubTree( elem );
+ Free( elem );
+}
+
+
+#endif // UTLNTREE_H
diff --git a/mp/src/public/tier1/utlobjectreference.h b/mp/src/public/tier1/utlobjectreference.h
index 6ff30213..da9d3033 100644
--- a/mp/src/public/tier1/utlobjectreference.h
+++ b/mp/src/public/tier1/utlobjectreference.h
@@ -1,165 +1,165 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// $Revision: $
-// $NoKeywords: $
-//===========================================================================//
-
-#ifndef UTLOBJECTREFERENCE_H
-#define UTLOBJECTREFERENCE_H
-
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include "tier1/utlintrusivelist.h"
-#include "mathlib/mathlib.h"
-
-
-// Purpose: class for keeping track of all the references that exist to an object. When the object
-// being referenced is freed, all of the references pointing at it will become null.
-//
-// To Use:
-// Add a DECLARE_REFERENCED_CLASS to the class that you want to use CutlReferences with.
-// Replace pointers to that class with CUtlReferences.
-// Check these references for null in appropriate places.
-//
-// NOTE : You can still happily use pointers instead of references where you want to - these
-// pointers will not magically become null like references would, but if you know no one is going
-// to delete the underlying object during a partcular section of code, it doesn't
-// matter. Basically, CUtlReferences don't rely on every use of an object using one.
-
-
-
-
-template<class T> class CUtlReference
-{
-public:
- FORCEINLINE CUtlReference(void)
- {
- m_pNext = m_pPrev = NULL;
- m_pObject = NULL;
- }
-
- FORCEINLINE CUtlReference(T *pObj)
- {
- m_pNext = m_pPrev = NULL;
- AddRef( pObj );
- }
-
- FORCEINLINE ~CUtlReference(void)
- {
- KillRef();
- }
-
- FORCEINLINE void Set(T *pObj)
- {
- if ( m_pObject != pObj )
- {
- KillRef();
- AddRef( pObj );
- }
- }
-
- FORCEINLINE T * operator()(void) const
- {
- return m_pObject;
- }
-
- FORCEINLINE operator T*()
- {
- return m_pObject;
- }
-
- FORCEINLINE operator const T*() const
- {
- return m_pObject;
- }
-
- FORCEINLINE T* operator->()
- {
- return m_pObject;
- }
-
- FORCEINLINE const T* operator->() const
- {
- return m_pObject;
- }
-
- FORCEINLINE CUtlReference &operator=( const CUtlReference& otherRef )
- {
- Set( otherRef.m_pObject );
- return *this;
- }
-
- FORCEINLINE CUtlReference &operator=( T *pObj )
- {
- Set( pObj );
- return *this;
- }
-
-
- FORCEINLINE bool operator==( const CUtlReference& o ) const
- {
- return ( o.m_pObject == m_pObject );
- }
-
-public:
- CUtlReference *m_pNext;
- CUtlReference *m_pPrev;
-
- T *m_pObject;
-
- FORCEINLINE void AddRef( T *pObj )
- {
- m_pObject = pObj;
- if ( pObj )
- {
- pObj->m_References.AddToHead( this );
- }
- }
-
- FORCEINLINE void KillRef(void)
- {
- if ( m_pObject )
- {
- m_pObject->m_References.RemoveNode( this );
- m_pObject = NULL;
- }
- }
-
-};
-
-template<class T> class CUtlReferenceList : public CUtlIntrusiveDList< CUtlReference<T> >
-{
-public:
- ~CUtlReferenceList( void )
- {
- CUtlReference<T> *i = CUtlIntrusiveDList<CUtlReference<T> >::m_pHead;
- while( i )
- {
- CUtlReference<T> *n = i->m_pNext;
- i->m_pNext = NULL;
- i->m_pPrev = NULL;
- i->m_pObject = NULL;
- i = n;
- }
- CUtlIntrusiveDList<CUtlReference<T> >::m_pHead = NULL;
- }
-};
-
-
-//-----------------------------------------------------------------------------
-// Put this macro in classes that are referenced by CUtlReference
-//-----------------------------------------------------------------------------
-#define DECLARE_REFERENCED_CLASS( _className ) \
- private: \
- CUtlReferenceList< _className > m_References; \
- template<class T> friend class CUtlReference;
-
-
-#endif
-
-
-
-
-
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// $Revision: $
+// $NoKeywords: $
+//===========================================================================//
+
+#ifndef UTLOBJECTREFERENCE_H
+#define UTLOBJECTREFERENCE_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier1/utlintrusivelist.h"
+#include "mathlib/mathlib.h"
+
+
+// Purpose: class for keeping track of all the references that exist to an object. When the object
+// being referenced is freed, all of the references pointing at it will become null.
+//
+// To Use:
+// Add a DECLARE_REFERENCED_CLASS to the class that you want to use CutlReferences with.
+// Replace pointers to that class with CUtlReferences.
+// Check these references for null in appropriate places.
+//
+// NOTE : You can still happily use pointers instead of references where you want to - these
+// pointers will not magically become null like references would, but if you know no one is going
+// to delete the underlying object during a partcular section of code, it doesn't
+// matter. Basically, CUtlReferences don't rely on every use of an object using one.
+
+
+
+
+template<class T> class CUtlReference
+{
+public:
+ FORCEINLINE CUtlReference(void)
+ {
+ m_pNext = m_pPrev = NULL;
+ m_pObject = NULL;
+ }
+
+ FORCEINLINE CUtlReference(T *pObj)
+ {
+ m_pNext = m_pPrev = NULL;
+ AddRef( pObj );
+ }
+
+ FORCEINLINE ~CUtlReference(void)
+ {
+ KillRef();
+ }
+
+ FORCEINLINE void Set(T *pObj)
+ {
+ if ( m_pObject != pObj )
+ {
+ KillRef();
+ AddRef( pObj );
+ }
+ }
+
+ FORCEINLINE T * operator()(void) const
+ {
+ return m_pObject;
+ }
+
+ FORCEINLINE operator T*()
+ {
+ return m_pObject;
+ }
+
+ FORCEINLINE operator const T*() const
+ {
+ return m_pObject;
+ }
+
+ FORCEINLINE T* operator->()
+ {
+ return m_pObject;
+ }
+
+ FORCEINLINE const T* operator->() const
+ {
+ return m_pObject;
+ }
+
+ FORCEINLINE CUtlReference &operator=( const CUtlReference& otherRef )
+ {
+ Set( otherRef.m_pObject );
+ return *this;
+ }
+
+ FORCEINLINE CUtlReference &operator=( T *pObj )
+ {
+ Set( pObj );
+ return *this;
+ }
+
+
+ FORCEINLINE bool operator==( const CUtlReference& o ) const
+ {
+ return ( o.m_pObject == m_pObject );
+ }
+
+public:
+ CUtlReference *m_pNext;
+ CUtlReference *m_pPrev;
+
+ T *m_pObject;
+
+ FORCEINLINE void AddRef( T *pObj )
+ {
+ m_pObject = pObj;
+ if ( pObj )
+ {
+ pObj->m_References.AddToHead( this );
+ }
+ }
+
+ FORCEINLINE void KillRef(void)
+ {
+ if ( m_pObject )
+ {
+ m_pObject->m_References.RemoveNode( this );
+ m_pObject = NULL;
+ }
+ }
+
+};
+
+template<class T> class CUtlReferenceList : public CUtlIntrusiveDList< CUtlReference<T> >
+{
+public:
+ ~CUtlReferenceList( void )
+ {
+ CUtlReference<T> *i = CUtlIntrusiveDList<CUtlReference<T> >::m_pHead;
+ while( i )
+ {
+ CUtlReference<T> *n = i->m_pNext;
+ i->m_pNext = NULL;
+ i->m_pPrev = NULL;
+ i->m_pObject = NULL;
+ i = n;
+ }
+ CUtlIntrusiveDList<CUtlReference<T> >::m_pHead = NULL;
+ }
+};
+
+
+//-----------------------------------------------------------------------------
+// Put this macro in classes that are referenced by CUtlReference
+//-----------------------------------------------------------------------------
+#define DECLARE_REFERENCED_CLASS( _className ) \
+ private: \
+ CUtlReferenceList< _className > m_References; \
+ template<class T> friend class CUtlReference;
+
+
+#endif
+
+
+
+
+
diff --git a/mp/src/public/tier1/utlpriorityqueue.h b/mp/src/public/tier1/utlpriorityqueue.h
index cc6935cd..8d3f4573 100644
--- a/mp/src/public/tier1/utlpriorityqueue.h
+++ b/mp/src/public/tier1/utlpriorityqueue.h
@@ -1,198 +1,198 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//=============================================================================//
-
-#ifndef UTLPRIORITYQUEUE_H
-#define UTLPRIORITYQUEUE_H
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include "utlvector.h"
-
-// T is the type stored in the queue, it must include the priority
-// The head of the list contains the element with GREATEST priority
-// configure the LessFunc_t to get the desired queue order
-template< class T >
-class CUtlPriorityQueue
-{
-public:
- // Less func typedef
- // Returns true if the first parameter is "less priority" than the second
- // Items that are "less priority" sort toward the tail of the queue
- typedef bool (*LessFunc_t)( T const&, T const& );
-
- typedef T ElemType_t;
-
- // constructor: lessfunc is required, but may be set after the constructor with
- // SetLessFunc
- CUtlPriorityQueue( int growSize = 0, int initSize = 0, LessFunc_t lessfunc = 0 );
- CUtlPriorityQueue( T *pMemory, int numElements, LessFunc_t lessfunc = 0 );
-
- // gets particular elements
- inline T const& ElementAtHead() const { return m_heap.Element(0); }
-
- inline bool IsValidIndex(int index) { return m_heap.IsValidIndex(index); }
-
- // O(lgn) to rebalance the heap
- void RemoveAtHead();
- void RemoveAt( int index );
-
- // O(lgn) to rebalance heap
- void Insert( T const &element );
- // Sets the less func
- void SetLessFunc( LessFunc_t func );
-
- // Returns the count of elements in the queue
- inline int Count() const { return m_heap.Count(); }
-
- // doesn't deallocate memory
- void RemoveAll() { m_heap.RemoveAll(); }
-
- // Memory deallocation
- void Purge() { m_heap.Purge(); }
-
- inline const T & Element( int index ) const { return m_heap.Element(index); }
-
-protected:
- CUtlVector<T> m_heap;
-
- void Swap( int index1, int index2 );
-
- // Used for sorting.
- LessFunc_t m_LessFunc;
-};
-
-template< class T >
-inline CUtlPriorityQueue<T>::CUtlPriorityQueue( int growSize, int initSize, LessFunc_t lessfunc ) :
- m_heap(growSize, initSize), m_LessFunc(lessfunc)
-{
-}
-
-template< class T >
-inline CUtlPriorityQueue<T>::CUtlPriorityQueue( T *pMemory, int numElements, LessFunc_t lessfunc ) :
- m_heap(pMemory, numElements), m_LessFunc(lessfunc)
-{
-}
-
-template <class T>
-void CUtlPriorityQueue<T>::RemoveAtHead()
-{
- m_heap.FastRemove( 0 );
- int index = 0;
-
- int count = Count();
- if ( !count )
- return;
-
- int half = count/2;
- int larger = index;
- while ( index < half )
- {
- int child = ((index+1) * 2) - 1; // if we wasted an element, this math would be more compact (1 based array)
- if ( child < count )
- {
- // Item has been filtered down to its proper place, terminate.
- if ( m_LessFunc( m_heap[index], m_heap[child] ) )
- {
- // mark the potential swap and check the other child
- larger = child;
- }
- }
- // go to sibling
- child++;
- if ( child < count )
- {
- // If this child is larger, swap it instead
- if ( m_LessFunc( m_heap[larger], m_heap[child] ) )
- larger = child;
- }
-
- if ( larger == index )
- break;
-
- // swap with the larger child
- Swap( index, larger );
- index = larger;
- }
-}
-
-
-template <class T>
-void CUtlPriorityQueue<T>::RemoveAt( int index )
-{
- Assert(m_heap.IsValidIndex(index));
- m_heap.FastRemove( index );
-
- int count = Count();
- if ( !count )
- return;
-
- int half = count/2;
- int larger = index;
- while ( index < half )
- {
- int child = ((index+1) * 2) - 1; // if we wasted an element, this math would be more compact (1 based array)
- if ( child < count )
- {
- // Item has been filtered down to its proper place, terminate.
- if ( m_LessFunc( m_heap[index], m_heap[child] ) )
- {
- // mark the potential swap and check the other child
- larger = child;
- }
- }
- // go to sibling
- child++;
- if ( child < count )
- {
- // If this child is larger, swap it instead
- if ( m_LessFunc( m_heap[larger], m_heap[child] ) )
- larger = child;
- }
-
- if ( larger == index )
- break;
-
- // swap with the larger child
- Swap( index, larger );
- index = larger;
- }
-}
-
-template <class T>
-void CUtlPriorityQueue<T>::Insert( T const &element )
-{
- int index = m_heap.AddToTail();
- m_heap[index] = element;
-
- while ( index != 0 )
- {
- int parent = ((index+1) / 2) - 1;
- if ( m_LessFunc( m_heap[index], m_heap[parent] ) )
- break;
-
- // swap with parent and repeat
- Swap( parent, index );
- index = parent;
- }
-}
-
-template <class T>
-void CUtlPriorityQueue<T>::Swap( int index1, int index2 )
-{
- T tmp = m_heap[index1];
- m_heap[index1] = m_heap[index2];
- m_heap[index2] = tmp;
-}
-
-template <class T>
-void CUtlPriorityQueue<T>::SetLessFunc( LessFunc_t lessfunc )
-{
- m_LessFunc = lessfunc;
-}
-
-#endif // UTLPRIORITYQUEUE_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef UTLPRIORITYQUEUE_H
+#define UTLPRIORITYQUEUE_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "utlvector.h"
+
+// T is the type stored in the queue, it must include the priority
+// The head of the list contains the element with GREATEST priority
+// configure the LessFunc_t to get the desired queue order
+template< class T >
+class CUtlPriorityQueue
+{
+public:
+ // Less func typedef
+ // Returns true if the first parameter is "less priority" than the second
+ // Items that are "less priority" sort toward the tail of the queue
+ typedef bool (*LessFunc_t)( T const&, T const& );
+
+ typedef T ElemType_t;
+
+ // constructor: lessfunc is required, but may be set after the constructor with
+ // SetLessFunc
+ CUtlPriorityQueue( int growSize = 0, int initSize = 0, LessFunc_t lessfunc = 0 );
+ CUtlPriorityQueue( T *pMemory, int numElements, LessFunc_t lessfunc = 0 );
+
+ // gets particular elements
+ inline T const& ElementAtHead() const { return m_heap.Element(0); }
+
+ inline bool IsValidIndex(int index) { return m_heap.IsValidIndex(index); }
+
+ // O(lgn) to rebalance the heap
+ void RemoveAtHead();
+ void RemoveAt( int index );
+
+ // O(lgn) to rebalance heap
+ void Insert( T const &element );
+ // Sets the less func
+ void SetLessFunc( LessFunc_t func );
+
+ // Returns the count of elements in the queue
+ inline int Count() const { return m_heap.Count(); }
+
+ // doesn't deallocate memory
+ void RemoveAll() { m_heap.RemoveAll(); }
+
+ // Memory deallocation
+ void Purge() { m_heap.Purge(); }
+
+ inline const T & Element( int index ) const { return m_heap.Element(index); }
+
+protected:
+ CUtlVector<T> m_heap;
+
+ void Swap( int index1, int index2 );
+
+ // Used for sorting.
+ LessFunc_t m_LessFunc;
+};
+
+template< class T >
+inline CUtlPriorityQueue<T>::CUtlPriorityQueue( int growSize, int initSize, LessFunc_t lessfunc ) :
+ m_heap(growSize, initSize), m_LessFunc(lessfunc)
+{
+}
+
+template< class T >
+inline CUtlPriorityQueue<T>::CUtlPriorityQueue( T *pMemory, int numElements, LessFunc_t lessfunc ) :
+ m_heap(pMemory, numElements), m_LessFunc(lessfunc)
+{
+}
+
+template <class T>
+void CUtlPriorityQueue<T>::RemoveAtHead()
+{
+ m_heap.FastRemove( 0 );
+ int index = 0;
+
+ int count = Count();
+ if ( !count )
+ return;
+
+ int half = count/2;
+ int larger = index;
+ while ( index < half )
+ {
+ int child = ((index+1) * 2) - 1; // if we wasted an element, this math would be more compact (1 based array)
+ if ( child < count )
+ {
+ // Item has been filtered down to its proper place, terminate.
+ if ( m_LessFunc( m_heap[index], m_heap[child] ) )
+ {
+ // mark the potential swap and check the other child
+ larger = child;
+ }
+ }
+ // go to sibling
+ child++;
+ if ( child < count )
+ {
+ // If this child is larger, swap it instead
+ if ( m_LessFunc( m_heap[larger], m_heap[child] ) )
+ larger = child;
+ }
+
+ if ( larger == index )
+ break;
+
+ // swap with the larger child
+ Swap( index, larger );
+ index = larger;
+ }
+}
+
+
+template <class T>
+void CUtlPriorityQueue<T>::RemoveAt( int index )
+{
+ Assert(m_heap.IsValidIndex(index));
+ m_heap.FastRemove( index );
+
+ int count = Count();
+ if ( !count )
+ return;
+
+ int half = count/2;
+ int larger = index;
+ while ( index < half )
+ {
+ int child = ((index+1) * 2) - 1; // if we wasted an element, this math would be more compact (1 based array)
+ if ( child < count )
+ {
+ // Item has been filtered down to its proper place, terminate.
+ if ( m_LessFunc( m_heap[index], m_heap[child] ) )
+ {
+ // mark the potential swap and check the other child
+ larger = child;
+ }
+ }
+ // go to sibling
+ child++;
+ if ( child < count )
+ {
+ // If this child is larger, swap it instead
+ if ( m_LessFunc( m_heap[larger], m_heap[child] ) )
+ larger = child;
+ }
+
+ if ( larger == index )
+ break;
+
+ // swap with the larger child
+ Swap( index, larger );
+ index = larger;
+ }
+}
+
+template <class T>
+void CUtlPriorityQueue<T>::Insert( T const &element )
+{
+ int index = m_heap.AddToTail();
+ m_heap[index] = element;
+
+ while ( index != 0 )
+ {
+ int parent = ((index+1) / 2) - 1;
+ if ( m_LessFunc( m_heap[index], m_heap[parent] ) )
+ break;
+
+ // swap with parent and repeat
+ Swap( parent, index );
+ index = parent;
+ }
+}
+
+template <class T>
+void CUtlPriorityQueue<T>::Swap( int index1, int index2 )
+{
+ T tmp = m_heap[index1];
+ m_heap[index1] = m_heap[index2];
+ m_heap[index2] = tmp;
+}
+
+template <class T>
+void CUtlPriorityQueue<T>::SetLessFunc( LessFunc_t lessfunc )
+{
+ m_LessFunc = lessfunc;
+}
+
+#endif // UTLPRIORITYQUEUE_H
diff --git a/mp/src/public/tier1/utlqueue.h b/mp/src/public/tier1/utlqueue.h
index 30a4fdd4..8624a3db 100644
--- a/mp/src/public/tier1/utlqueue.h
+++ b/mp/src/public/tier1/utlqueue.h
@@ -1,114 +1,114 @@
-//========= Copyright 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 stack
-template< class 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 );
-
- // 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();
-
- // Add a new item to the end of the queue
- void Insert( T const &element );
-
- // checks if an element of this value already exists on the stack, returns true if it does
- bool Check( T const element );
-
- // Returns the count of elements in the stack
- int Count() const { return m_heap.Count(); }
-
- // doesn't deallocate memory
- void RemoveAll() { m_heap.RemoveAll(); }
-
- // Memory deallocation
- void Purge() { m_heap.Purge(); }
-
-protected:
- CUtlVector<T> m_heap;
- T m_current;
-};
-
-template< class T >
-inline CUtlQueue<T>::CUtlQueue( int growSize, int initSize ) :
- m_heap(growSize, initSize)
-{
-}
-
-template< class T >
-inline CUtlQueue<T>::CUtlQueue( T *pMemory, int numElements ) :
- m_heap(pMemory, numElements)
-{
-}
-
-template <class T>
-inline T const& CUtlQueue<T>::RemoveAtHead()
-{
- m_current = m_heap[0];
- m_heap.Remove((int)0);
- return m_current;
-}
-
-template <class T>
-inline T const& CUtlQueue<T>::RemoveAtTail()
-{
- m_current = m_heap[ m_heap.Count() - 1 ];
- m_heap.Remove((int)(m_heap.Count() - 1));
- return m_current;
-}
-
-template <class T>
-inline T const& CUtlQueue<T>::Head()
-{
- m_current = m_heap[0];
- return m_current;
-}
-
-template <class T>
-inline T const& CUtlQueue<T>::Tail()
-{
- m_current = m_heap[ m_heap.Count() - 1 ];
- return m_current;
-}
-
-template <class T>
-void CUtlQueue<T>::Insert( T const &element )
-{
- int index = m_heap.AddToTail();
- m_heap[index] = element;
-}
-
-template <class T>
-bool CUtlQueue<T>::Check( T const element )
-{
- int index = m_heap.Find(element);
- return ( index != -1 );
-}
-
-
-#endif // UTLQUEUE_H
+//========= Copyright 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 stack
+template< class 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 );
+
+ // 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();
+
+ // Add a new item to the end of the queue
+ void Insert( T const &element );
+
+ // checks if an element of this value already exists on the stack, returns true if it does
+ bool Check( T const element );
+
+ // Returns the count of elements in the stack
+ int Count() const { return m_heap.Count(); }
+
+ // doesn't deallocate memory
+ void RemoveAll() { m_heap.RemoveAll(); }
+
+ // Memory deallocation
+ void Purge() { m_heap.Purge(); }
+
+protected:
+ CUtlVector<T> m_heap;
+ T m_current;
+};
+
+template< class T >
+inline CUtlQueue<T>::CUtlQueue( int growSize, int initSize ) :
+ m_heap(growSize, initSize)
+{
+}
+
+template< class T >
+inline CUtlQueue<T>::CUtlQueue( T *pMemory, int numElements ) :
+ m_heap(pMemory, numElements)
+{
+}
+
+template <class T>
+inline T const& CUtlQueue<T>::RemoveAtHead()
+{
+ m_current = m_heap[0];
+ m_heap.Remove((int)0);
+ return m_current;
+}
+
+template <class T>
+inline T const& CUtlQueue<T>::RemoveAtTail()
+{
+ m_current = m_heap[ m_heap.Count() - 1 ];
+ m_heap.Remove((int)(m_heap.Count() - 1));
+ return m_current;
+}
+
+template <class T>
+inline T const& CUtlQueue<T>::Head()
+{
+ m_current = m_heap[0];
+ return m_current;
+}
+
+template <class T>
+inline T const& CUtlQueue<T>::Tail()
+{
+ m_current = m_heap[ m_heap.Count() - 1 ];
+ return m_current;
+}
+
+template <class T>
+void CUtlQueue<T>::Insert( T const &element )
+{
+ int index = m_heap.AddToTail();
+ m_heap[index] = element;
+}
+
+template <class T>
+bool CUtlQueue<T>::Check( T const element )
+{
+ int index = m_heap.Find(element);
+ return ( index != -1 );
+}
+
+
+#endif // UTLQUEUE_H
diff --git a/mp/src/public/tier1/utlrbtree.h b/mp/src/public/tier1/utlrbtree.h
index 6ea22614..70b0d72c 100644
--- a/mp/src/public/tier1/utlrbtree.h
+++ b/mp/src/public/tier1/utlrbtree.h
@@ -1,1588 +1,1588 @@
-//========= Copyright 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"
-#include "tier1/strtools.h"
-
-//-----------------------------------------------------------------------------
-// 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
-
-template <typename T>
-class CDefLess
-{
-public:
- CDefLess() {}
- CDefLess( int i ) {}
- inline bool operator()( const T &lhs, const T &rhs ) const { return ( lhs < rhs ); }
- inline bool operator!() const { return false; }
-};
-
-//-------------------------------------
-
-inline bool StringLessThan( const char * const &lhs, const char * const &rhs) {
- if ( !lhs ) return false;
- if ( !rhs ) return true;
- return ( V_strcmp( lhs, rhs) < 0 );
-}
-
-inline bool CaselessStringLessThan( const char * const &lhs, const char * const &rhs ) {
- if ( !lhs ) return false;
- if ( !rhs ) return true;
- return ( V_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 );
-
- 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
- // it IS safe to do so when using CUtlMemory as the allocator,
- // but we should really remove patterns using this anyways, for safety and generality
- 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)
- 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_Elements( growSize, initSize ),
-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( 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( T ) );
- 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;
- bool leftchild;
-
- 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
-{
- // Don't go into an infinite loop if it's a bad index
- Assert(IsValidIndex(i));
- if ( !IsValidIndex(i) )
- return InvalidIndex();
-
- 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
-{
- // Don't go into an infinite loop if it's a bad index
- Assert(IsValidIndex(i));
- if ( !IsValidIndex(i) )
- return InvalidIndex();
-
- 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;
- bool leftchild;
- 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
+//========= Copyright 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"
+#include "tier1/strtools.h"
+
+//-----------------------------------------------------------------------------
+// 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
+
+template <typename T>
+class CDefLess
+{
+public:
+ CDefLess() {}
+ CDefLess( int i ) {}
+ inline bool operator()( const T &lhs, const T &rhs ) const { return ( lhs < rhs ); }
+ inline bool operator!() const { return false; }
+};
+
+//-------------------------------------
+
+inline bool StringLessThan( const char * const &lhs, const char * const &rhs) {
+ if ( !lhs ) return false;
+ if ( !rhs ) return true;
+ return ( V_strcmp( lhs, rhs) < 0 );
+}
+
+inline bool CaselessStringLessThan( const char * const &lhs, const char * const &rhs ) {
+ if ( !lhs ) return false;
+ if ( !rhs ) return true;
+ return ( V_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 );
+
+ 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
+ // it IS safe to do so when using CUtlMemory as the allocator,
+ // but we should really remove patterns using this anyways, for safety and generality
+ 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)
+ 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_Elements( growSize, initSize ),
+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( 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( T ) );
+ 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;
+ bool leftchild;
+
+ 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
+{
+ // Don't go into an infinite loop if it's a bad index
+ Assert(IsValidIndex(i));
+ if ( !IsValidIndex(i) )
+ return InvalidIndex();
+
+ 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
+{
+ // Don't go into an infinite loop if it's a bad index
+ Assert(IsValidIndex(i));
+ if ( !IsValidIndex(i) )
+ return InvalidIndex();
+
+ 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;
+ bool leftchild;
+ 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/mp/src/public/tier1/utlsoacontainer.h b/mp/src/public/tier1/utlsoacontainer.h
index 55073259..b9440c5f 100644
--- a/mp/src/public/tier1/utlsoacontainer.h
+++ b/mp/src/public/tier1/utlsoacontainer.h
@@ -1,334 +1,334 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//
-// A Fixed-allocation class for maintaining a 1d or 2d or 3d array of data in a structure-of-arrays
-// (SOA) sse-friendly manner.
-// =============================================================================//
-
-#ifndef UTLSOACONTAINER_H
-#define UTLSOACONTAINER_H
-
-#ifdef _WIN32
-#pragma once
-#endif
-
-
-#include "tier0/platform.h"
-#include "tier0/dbg.h"
-#include "tier0/threadtools.h"
-#include "tier1/utlmemory.h"
-#include "tier1/utlblockmemory.h"
-#include "mathlib/ssemath.h"
-
-
-// strided pointers. gives you a class that acts like a pointer, but the ++ and += operators do the
-// right thing
-template<class T> class CStridedPtr
-{
-protected:
- T *m_pData;
- size_t m_nStride;
-
-public:
- FORCEINLINE CStridedPtr<T>( void *pData, size_t nByteStride )
- {
- m_pData = reinterpret_cast<T *>( pData );
- m_nStride = nByteStride / sizeof( T );
- }
-
- FORCEINLINE CStridedPtr<T>( void ) {}
- T *operator->(void) const
- {
- return m_pData;
- }
-
- T & operator*(void) const
- {
- return *m_pData;
- }
-
- FORCEINLINE operator T *(void)
- {
- return m_pData;
- }
-
- FORCEINLINE CStridedPtr<T> & operator++(void)
- {
- m_pData += m_nStride;
- return *this;
- }
-
- FORCEINLINE void operator+=( size_t nNumElements )
- {
- m_pData += nNumElements * m_nStride;
- }
-
-};
-
-template<class T> class CStridedConstPtr
-{
-protected:
- const T *m_pData;
- size_t m_nStride;
-
-public:
- FORCEINLINE CStridedConstPtr<T>( void const *pData, size_t nByteStride )
- {
- m_pData = reinterpret_cast<T const *>( pData );
- m_nStride = nByteStride / sizeof( T );
- }
-
- FORCEINLINE CStridedConstPtr<T>( void ) {}
-
- const T *operator->(void) const
- {
- return m_pData;
- }
-
- const T & operator*(void) const
- {
- return *m_pData;
- }
-
- FORCEINLINE operator const T *(void) const
- {
- return m_pData;
- }
-
- FORCEINLINE CStridedConstPtr<T> &operator++(void)
- {
- m_pData += m_nStride;
- return *this;
- }
- FORCEINLINE void operator+=( size_t nNumElements )
- {
- m_pData += nNumElements*m_nStride;
- }
-};
-
-// allowed field data types. if you change these values, you need to change the tables in the .cpp file
-enum EAttributeDataType
-{
- ATTRDATATYPE_FLOAT = 0, // a float attribute
- ATTRDATATYPE_4V = 1, // vector data type, stored as class FourVectors
- ATTRDATATYPE_INT = 2, // integer. not especially sse-able on
- // all architectures.
- ATTRDATATYPE_POINTER = 3, // a pointer.
- ATTRDATATYPE_NONE = -1, // pad and varargs ender
-};
-
-#define MAX_SOA_FIELDS 32
-
-class CSOAContainer
-{
-
-protected:
- int m_nColumns; // # of rows and columns created with
- int m_nRows;
- int m_nSlices;
-
- int m_nPaddedColumns; // # of columns rounded up for sse
- int m_nNumQuadsPerRow; // # of groups of 4 elements per row
-
- uint8 *m_pDataMemory; // the actual data memory
- uint8 *m_pAttributePtrs[MAX_SOA_FIELDS];
-
- EAttributeDataType m_nDataType[MAX_SOA_FIELDS];
-
- size_t m_nStrideInBytes[MAX_SOA_FIELDS]; // stride from one field datum to another
- size_t m_nRowStrideInBytes[MAX_SOA_FIELDS]; // stride from one row datum to another per field
- size_t m_nSliceStrideInBytes[MAX_SOA_FIELDS]; // stride from one slice datum to another per field
-
-
-
- uint32 m_nFieldPresentMask;
-
- FORCEINLINE void Init( void )
- {
- memset( m_nDataType, 0xff, sizeof( m_nDataType ) );
- m_pDataMemory = 0;
- m_nColumns = m_nPaddedColumns = m_nRows = m_nSlices = 0;
- m_nFieldPresentMask = 0;
- }
-public:
-
-
- CSOAContainer( void ) // an empoty one with no attributes
- {
- Init();
- }
-
- void Purge( void ); // set back to un-initted state, freeing memory
-
- ~CSOAContainer( void );
-
- // easy constructor for 2d using varargs. call like
- // #define ATTR_RED 0
- // #define ATTR_GREEN 1
- // #define ATTR_BLUE 2
- // CSOAContainer myimage( 256, 256, ATTR_RED, ATTRDATATYPE_FLOAT, ATTR_GREEN, ATTRDATATYPE_FLOAT,
- // ATTR_BLUE, ATTRDATATYPE_FLOAT, -1 );
-
- CSOAContainer( int nCols, int nRows, ... );
-
- size_t ElementSize( void ) const; // total bytes per element. not super fast.
-
- // set the data type for an attribute. If you set the data type, but tell it not to allocate,
- // the data type will be set but writes will assert, and reads will give you back zeros.
- FORCEINLINE void SetAttributeType( int nAttrIdx, EAttributeDataType nDataType, bool bAllocateMemory = true )
- {
- Assert( !m_pDataMemory ); // can't change after memory allocated
- Assert( nAttrIdx < MAX_SOA_FIELDS );
- m_nDataType[nAttrIdx] = nDataType;
- if ( ( m_nDataType[nAttrIdx] != ATTRDATATYPE_NONE ) && bAllocateMemory )
- m_nFieldPresentMask |= ( 1 << nAttrIdx );
- else
- m_nFieldPresentMask &= ~( 1 << nAttrIdx );
- }
-
- FORCEINLINE int NumRows( void ) const
- {
- return m_nRows;
- }
-
- FORCEINLINE int NumCols( void ) const
- {
- return m_nColumns;
- }
- FORCEINLINE int NumSlices( void ) const
- {
- return m_nSlices;
- }
-
-
- FORCEINLINE void AssertDataType( int nAttrIdx, EAttributeDataType nDataType ) const
- {
- Assert( nAttrIdx >= 0 );
- Assert( nAttrIdx < MAX_SOA_FIELDS );
- Assert( m_nStrideInBytes[nAttrIdx] );
- }
-
-
- // # of groups of 4 elements per row
- FORCEINLINE int NumQuadsPerRow( void ) const
- {
- return m_nNumQuadsPerRow;
- }
-
- FORCEINLINE int Count( void ) const // for 1d data
- {
- return NumCols();
- }
-
- FORCEINLINE int NumElements( void ) const
- {
- return NumCols() * NumRows() * NumSlices();
- }
-
-
- // how much to step to go from the end of one row to the start of the next one. Basically, how
- // many bytes to add at the end of a row when iterating over the whole 2d array with ++
- FORCEINLINE size_t RowToRowStep( int nAttrIdx ) const
- {
- return 0;
- }
-
- FORCEINLINE void *RowPtr( int nAttributeIdx, int nRowNumber, int nSliceNumber = 0 ) const
- {
- Assert( nRowNumber < m_nRows );
- Assert( nAttributeIdx < MAX_SOA_FIELDS );
- Assert( m_nDataType[nAttributeIdx] != ATTRDATATYPE_NONE );
- Assert( m_nFieldPresentMask & ( 1 << nAttributeIdx ) );
- return m_pAttributePtrs[nAttributeIdx] +
- + nRowNumber * m_nRowStrideInBytes[nAttributeIdx]
- + nSliceNumber * m_nSliceStrideInBytes[nAttributeIdx];
- }
-
- FORCEINLINE void const *ConstRowPtr( int nAttributeIdx, int nRowNumber, int nSliceNumber = 0 ) const
- {
- Assert( nRowNumber < m_nRows );
- Assert( nAttributeIdx < MAX_SOA_FIELDS );
- Assert( m_nDataType[nAttributeIdx] != ATTRDATATYPE_NONE );
- return m_pAttributePtrs[nAttributeIdx]
- + nRowNumber * m_nRowStrideInBytes[nAttributeIdx]
- + nSliceNumber * m_nSliceStrideInBytes[nAttributeIdx];
- }
-
-
- template<class T> FORCEINLINE T *ElementPointer( int nAttributeIdx,
- int nX = 0, int nY = 0, int nZ = 0 ) const
- {
- Assert( nAttributeIdx < MAX_SOA_FIELDS );
- Assert( nX < m_nColumns );
- Assert( nY < m_nRows );
- Assert( nZ < m_nSlices );
- Assert( m_nDataType[nAttributeIdx] != ATTRDATATYPE_NONE );
- Assert( m_nDataType[nAttributeIdx] != ATTRDATATYPE_4V );
- return reinterpret_cast<T *>( m_pAttributePtrs[nAttributeIdx]
- + nX * sizeof( float )
- + nY * m_nRowStrideInBytes[nAttributeIdx]
- + nZ * m_nSliceStrideInBytes[nAttributeIdx]
- );
- }
-
- FORCEINLINE size_t ItemByteStride( int nAttributeIdx ) const
- {
- Assert( nAttributeIdx < MAX_SOA_FIELDS );
- Assert( m_nDataType[nAttributeIdx] != ATTRDATATYPE_NONE );
- return m_nStrideInBytes[ nAttributeIdx ];
- }
-
- // copy the attribute data from another soacontainer. must be compatible geometry
- void CopyAttrFrom( CSOAContainer const &other, int nAttributeIdx );
-
- // copy the attribute data from another attribute. must be compatible data format
- void CopyAttrToAttr( int nSrcAttributeIndex, int nDestAttributeIndex);
-
- // move all the data from one csoacontainer to another, leaving the source empty.
- // this is just a pointer copy.
- FORCEINLINE void MoveDataFrom( CSOAContainer other )
- {
- (*this) = other;
- other.Init();
- }
-
-
-
- void AllocateData( int nNCols, int nNRows, int nSlices = 1 ); // actually allocate the memory and set the pointers up
-
- // arithmetic and data filling functions. All SIMD and hopefully fast
-
- // set all elements of a float attribute to random #s
- void RandomizeAttribute( int nAttr, float flMin, float flMax ) const ;
-
- // fill 2d a rectangle with values interpolated from 4 corner values.
- void FillAttrWithInterpolatedValues( int nAttr, float flValue00, float flValue10, float flValue01, float flValue11 ) const;
- void FillAttrWithInterpolatedValues( int nAttr, Vector flValue00, Vector flValue10,
- Vector const &flValue01, Vector const &flValue11 ) const;
-
-};
-
-class CFltX4AttributeIterator : public CStridedConstPtr<fltx4>
-{
- FORCEINLINE CFltX4AttributeIterator( CSOAContainer const *pContainer, int nAttribute, int nRowNumber = 0 )
- : CStridedConstPtr<fltx4>( pContainer->ConstRowPtr( nAttribute, nRowNumber),
- pContainer->ItemByteStride( nAttribute ) )
- {
- }
-};
-
-class CFltX4AttributeWriteIterator : public CStridedPtr<fltx4>
-{
- FORCEINLINE CFltX4AttributeWriteIterator( CSOAContainer const *pContainer, int nAttribute, int nRowNumber = 0 )
- : CStridedPtr<fltx4>( pContainer->RowPtr( nAttribute, nRowNumber),
- pContainer->ItemByteStride( nAttribute ) )
- {
- }
-
-};
-
-
-#endif
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+// A Fixed-allocation class for maintaining a 1d or 2d or 3d array of data in a structure-of-arrays
+// (SOA) sse-friendly manner.
+// =============================================================================//
+
+#ifndef UTLSOACONTAINER_H
+#define UTLSOACONTAINER_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#include "tier0/platform.h"
+#include "tier0/dbg.h"
+#include "tier0/threadtools.h"
+#include "tier1/utlmemory.h"
+#include "tier1/utlblockmemory.h"
+#include "mathlib/ssemath.h"
+
+
+// strided pointers. gives you a class that acts like a pointer, but the ++ and += operators do the
+// right thing
+template<class T> class CStridedPtr
+{
+protected:
+ T *m_pData;
+ size_t m_nStride;
+
+public:
+ FORCEINLINE CStridedPtr<T>( void *pData, size_t nByteStride )
+ {
+ m_pData = reinterpret_cast<T *>( pData );
+ m_nStride = nByteStride / sizeof( T );
+ }
+
+ FORCEINLINE CStridedPtr<T>( void ) {}
+ T *operator->(void) const
+ {
+ return m_pData;
+ }
+
+ T & operator*(void) const
+ {
+ return *m_pData;
+ }
+
+ FORCEINLINE operator T *(void)
+ {
+ return m_pData;
+ }
+
+ FORCEINLINE CStridedPtr<T> & operator++(void)
+ {
+ m_pData += m_nStride;
+ return *this;
+ }
+
+ FORCEINLINE void operator+=( size_t nNumElements )
+ {
+ m_pData += nNumElements * m_nStride;
+ }
+
+};
+
+template<class T> class CStridedConstPtr
+{
+protected:
+ const T *m_pData;
+ size_t m_nStride;
+
+public:
+ FORCEINLINE CStridedConstPtr<T>( void const *pData, size_t nByteStride )
+ {
+ m_pData = reinterpret_cast<T const *>( pData );
+ m_nStride = nByteStride / sizeof( T );
+ }
+
+ FORCEINLINE CStridedConstPtr<T>( void ) {}
+
+ const T *operator->(void) const
+ {
+ return m_pData;
+ }
+
+ const T & operator*(void) const
+ {
+ return *m_pData;
+ }
+
+ FORCEINLINE operator const T *(void) const
+ {
+ return m_pData;
+ }
+
+ FORCEINLINE CStridedConstPtr<T> &operator++(void)
+ {
+ m_pData += m_nStride;
+ return *this;
+ }
+ FORCEINLINE void operator+=( size_t nNumElements )
+ {
+ m_pData += nNumElements*m_nStride;
+ }
+};
+
+// allowed field data types. if you change these values, you need to change the tables in the .cpp file
+enum EAttributeDataType
+{
+ ATTRDATATYPE_FLOAT = 0, // a float attribute
+ ATTRDATATYPE_4V = 1, // vector data type, stored as class FourVectors
+ ATTRDATATYPE_INT = 2, // integer. not especially sse-able on
+ // all architectures.
+ ATTRDATATYPE_POINTER = 3, // a pointer.
+ ATTRDATATYPE_NONE = -1, // pad and varargs ender
+};
+
+#define MAX_SOA_FIELDS 32
+
+class CSOAContainer
+{
+
+protected:
+ int m_nColumns; // # of rows and columns created with
+ int m_nRows;
+ int m_nSlices;
+
+ int m_nPaddedColumns; // # of columns rounded up for sse
+ int m_nNumQuadsPerRow; // # of groups of 4 elements per row
+
+ uint8 *m_pDataMemory; // the actual data memory
+ uint8 *m_pAttributePtrs[MAX_SOA_FIELDS];
+
+ EAttributeDataType m_nDataType[MAX_SOA_FIELDS];
+
+ size_t m_nStrideInBytes[MAX_SOA_FIELDS]; // stride from one field datum to another
+ size_t m_nRowStrideInBytes[MAX_SOA_FIELDS]; // stride from one row datum to another per field
+ size_t m_nSliceStrideInBytes[MAX_SOA_FIELDS]; // stride from one slice datum to another per field
+
+
+
+ uint32 m_nFieldPresentMask;
+
+ FORCEINLINE void Init( void )
+ {
+ memset( m_nDataType, 0xff, sizeof( m_nDataType ) );
+ m_pDataMemory = 0;
+ m_nColumns = m_nPaddedColumns = m_nRows = m_nSlices = 0;
+ m_nFieldPresentMask = 0;
+ }
+public:
+
+
+ CSOAContainer( void ) // an empoty one with no attributes
+ {
+ Init();
+ }
+
+ void Purge( void ); // set back to un-initted state, freeing memory
+
+ ~CSOAContainer( void );
+
+ // easy constructor for 2d using varargs. call like
+ // #define ATTR_RED 0
+ // #define ATTR_GREEN 1
+ // #define ATTR_BLUE 2
+ // CSOAContainer myimage( 256, 256, ATTR_RED, ATTRDATATYPE_FLOAT, ATTR_GREEN, ATTRDATATYPE_FLOAT,
+ // ATTR_BLUE, ATTRDATATYPE_FLOAT, -1 );
+
+ CSOAContainer( int nCols, int nRows, ... );
+
+ size_t ElementSize( void ) const; // total bytes per element. not super fast.
+
+ // set the data type for an attribute. If you set the data type, but tell it not to allocate,
+ // the data type will be set but writes will assert, and reads will give you back zeros.
+ FORCEINLINE void SetAttributeType( int nAttrIdx, EAttributeDataType nDataType, bool bAllocateMemory = true )
+ {
+ Assert( !m_pDataMemory ); // can't change after memory allocated
+ Assert( nAttrIdx < MAX_SOA_FIELDS );
+ m_nDataType[nAttrIdx] = nDataType;
+ if ( ( m_nDataType[nAttrIdx] != ATTRDATATYPE_NONE ) && bAllocateMemory )
+ m_nFieldPresentMask |= ( 1 << nAttrIdx );
+ else
+ m_nFieldPresentMask &= ~( 1 << nAttrIdx );
+ }
+
+ FORCEINLINE int NumRows( void ) const
+ {
+ return m_nRows;
+ }
+
+ FORCEINLINE int NumCols( void ) const
+ {
+ return m_nColumns;
+ }
+ FORCEINLINE int NumSlices( void ) const
+ {
+ return m_nSlices;
+ }
+
+
+ FORCEINLINE void AssertDataType( int nAttrIdx, EAttributeDataType nDataType ) const
+ {
+ Assert( nAttrIdx >= 0 );
+ Assert( nAttrIdx < MAX_SOA_FIELDS );
+ Assert( m_nStrideInBytes[nAttrIdx] );
+ }
+
+
+ // # of groups of 4 elements per row
+ FORCEINLINE int NumQuadsPerRow( void ) const
+ {
+ return m_nNumQuadsPerRow;
+ }
+
+ FORCEINLINE int Count( void ) const // for 1d data
+ {
+ return NumCols();
+ }
+
+ FORCEINLINE int NumElements( void ) const
+ {
+ return NumCols() * NumRows() * NumSlices();
+ }
+
+
+ // how much to step to go from the end of one row to the start of the next one. Basically, how
+ // many bytes to add at the end of a row when iterating over the whole 2d array with ++
+ FORCEINLINE size_t RowToRowStep( int nAttrIdx ) const
+ {
+ return 0;
+ }
+
+ FORCEINLINE void *RowPtr( int nAttributeIdx, int nRowNumber, int nSliceNumber = 0 ) const
+ {
+ Assert( nRowNumber < m_nRows );
+ Assert( nAttributeIdx < MAX_SOA_FIELDS );
+ Assert( m_nDataType[nAttributeIdx] != ATTRDATATYPE_NONE );
+ Assert( m_nFieldPresentMask & ( 1 << nAttributeIdx ) );
+ return m_pAttributePtrs[nAttributeIdx] +
+ + nRowNumber * m_nRowStrideInBytes[nAttributeIdx]
+ + nSliceNumber * m_nSliceStrideInBytes[nAttributeIdx];
+ }
+
+ FORCEINLINE void const *ConstRowPtr( int nAttributeIdx, int nRowNumber, int nSliceNumber = 0 ) const
+ {
+ Assert( nRowNumber < m_nRows );
+ Assert( nAttributeIdx < MAX_SOA_FIELDS );
+ Assert( m_nDataType[nAttributeIdx] != ATTRDATATYPE_NONE );
+ return m_pAttributePtrs[nAttributeIdx]
+ + nRowNumber * m_nRowStrideInBytes[nAttributeIdx]
+ + nSliceNumber * m_nSliceStrideInBytes[nAttributeIdx];
+ }
+
+
+ template<class T> FORCEINLINE T *ElementPointer( int nAttributeIdx,
+ int nX = 0, int nY = 0, int nZ = 0 ) const
+ {
+ Assert( nAttributeIdx < MAX_SOA_FIELDS );
+ Assert( nX < m_nColumns );
+ Assert( nY < m_nRows );
+ Assert( nZ < m_nSlices );
+ Assert( m_nDataType[nAttributeIdx] != ATTRDATATYPE_NONE );
+ Assert( m_nDataType[nAttributeIdx] != ATTRDATATYPE_4V );
+ return reinterpret_cast<T *>( m_pAttributePtrs[nAttributeIdx]
+ + nX * sizeof( float )
+ + nY * m_nRowStrideInBytes[nAttributeIdx]
+ + nZ * m_nSliceStrideInBytes[nAttributeIdx]
+ );
+ }
+
+ FORCEINLINE size_t ItemByteStride( int nAttributeIdx ) const
+ {
+ Assert( nAttributeIdx < MAX_SOA_FIELDS );
+ Assert( m_nDataType[nAttributeIdx] != ATTRDATATYPE_NONE );
+ return m_nStrideInBytes[ nAttributeIdx ];
+ }
+
+ // copy the attribute data from another soacontainer. must be compatible geometry
+ void CopyAttrFrom( CSOAContainer const &other, int nAttributeIdx );
+
+ // copy the attribute data from another attribute. must be compatible data format
+ void CopyAttrToAttr( int nSrcAttributeIndex, int nDestAttributeIndex);
+
+ // move all the data from one csoacontainer to another, leaving the source empty.
+ // this is just a pointer copy.
+ FORCEINLINE void MoveDataFrom( CSOAContainer other )
+ {
+ (*this) = other;
+ other.Init();
+ }
+
+
+
+ void AllocateData( int nNCols, int nNRows, int nSlices = 1 ); // actually allocate the memory and set the pointers up
+
+ // arithmetic and data filling functions. All SIMD and hopefully fast
+
+ // set all elements of a float attribute to random #s
+ void RandomizeAttribute( int nAttr, float flMin, float flMax ) const ;
+
+ // fill 2d a rectangle with values interpolated from 4 corner values.
+ void FillAttrWithInterpolatedValues( int nAttr, float flValue00, float flValue10, float flValue01, float flValue11 ) const;
+ void FillAttrWithInterpolatedValues( int nAttr, Vector flValue00, Vector flValue10,
+ Vector const &flValue01, Vector const &flValue11 ) const;
+
+};
+
+class CFltX4AttributeIterator : public CStridedConstPtr<fltx4>
+{
+ FORCEINLINE CFltX4AttributeIterator( CSOAContainer const *pContainer, int nAttribute, int nRowNumber = 0 )
+ : CStridedConstPtr<fltx4>( pContainer->ConstRowPtr( nAttribute, nRowNumber),
+ pContainer->ItemByteStride( nAttribute ) )
+ {
+ }
+};
+
+class CFltX4AttributeWriteIterator : public CStridedPtr<fltx4>
+{
+ FORCEINLINE CFltX4AttributeWriteIterator( CSOAContainer const *pContainer, int nAttribute, int nRowNumber = 0 )
+ : CStridedPtr<fltx4>( pContainer->RowPtr( nAttribute, nRowNumber),
+ pContainer->ItemByteStride( nAttribute ) )
+ {
+ }
+
+};
+
+
+#endif
diff --git a/mp/src/public/tier1/utlstack.h b/mp/src/public/tier1/utlstack.h
index 9740effe..a46beb26 100644
--- a/mp/src/public/tier1/utlstack.h
+++ b/mp/src/public/tier1/utlstack.h
@@ -1,331 +1,331 @@
-//========= Copyright 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();
-}
-
+//========= Copyright 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 \ No newline at end of file
diff --git a/mp/src/public/tier1/utlstring.h b/mp/src/public/tier1/utlstring.h
index 26d98338..f425b271 100644
--- a/mp/src/public/tier1/utlstring.h
+++ b/mp/src/public/tier1/utlstring.h
@@ -1,401 +1,401 @@
-//========= Copyright 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"
-
-#if defined( OSX )
-#define wcsdup wcsdup_osx
-inline wchar_t *wcsdup_osx(const wchar_t *pString)
-{
- wchar_t *pMemory;
-
- if (!pString)
- return NULL;
-
- size_t len = (wcslen(pString) + 1);
- if ((pMemory = (wchar_t *)malloc(len * sizeof(wchar_t))) != NULL)
- {
- return wcscpy( pMemory, pString );
- }
-
- return NULL;
-}
-#endif
-
-//-----------------------------------------------------------------------------
-// Base class, containing simple memory management
-//-----------------------------------------------------------------------------
-class CUtlBinaryBlock
-{
-public:
- CUtlBinaryBlock( int growSize = 0, int initSize = 0 );
-
- // 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 ToUpper();
-
- 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 );
-
- // is valid?
- bool IsValid() const;
-
- bool MatchesPattern( const CUtlString &Pattern, int nFlags = 0 ); // case SENSITIVE, use * for wildcard in pattern string
-
- int Format( PRINTF_FORMAT_STRING 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 );
-
- // Grab a substring starting from the left or the right side.
- CUtlString Left( int32 nChars );
- CUtlString Right( int32 nChars );
-
- // Replace all instances of one character with another.
- CUtlString Replace( char cFrom, char cTo );
-
- // Calls right through to V_MakeAbsolutePath.
- CUtlString AbsPath( const char *pStartingDir=NULL );
-
- // Gets the filename (everything except the path.. c:\a\b\c\somefile.txt -> somefile.txt).
- CUtlString UnqualifiedFilename();
-
- // Strips off one directory. Uses V_StripLastDir but strips the last slash also!
- CUtlString DirName();
-
- // 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 bool CUtlString::IsValid() const
-{
- return ( String() != NULL );
-}
-
-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 );
- // Note that this function takes a character count, and does not guarantee null-termination.
- static void Copy( T *out_pOut, const T *pIn, int iLengthInChars );
- static int Compare( const T *pLhs, const T *pRhs );
- static int CaselessCompare( 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();
- static const T *NullDebugString();
-};
-
-template < >
-class StringFuncs<char>
-{
-public:
- static char *Duplicate( const char *pValue ) { return strdup( pValue ); }
- // Note that this function takes a character count, and does not guarantee null-termination.
- static void Copy( OUT_CAP(iLengthInChars) char *out_pOut, const char *pIn, int iLengthInChars ) { strncpy( out_pOut, pIn, iLengthInChars ); }
- static int Compare( const char *pLhs, const char *pRhs ) { return strcmp( pLhs, pRhs ); }
- static int CaselessCompare( const char *pLhs, const char *pRhs ) { return Q_strcasecmp( pLhs, pRhs ); }
- static int Length( const char *pValue ) { return (int)strlen( pValue ); }
- static const char *FindChar( const char *pStr, const char cSearch ) { return strchr( pStr, cSearch ); }
- static const char *EmptyString() { return ""; }
- static const char *NullDebugString() { return "(null)"; }
-};
-
-template < >
-class StringFuncs<wchar_t>
-{
-public:
- static wchar_t *Duplicate( const wchar_t *pValue ) { return wcsdup( pValue ); }
- // Note that this function takes a character count, and does not guarantee null-termination.
- static void Copy( OUT_CAP(iLengthInChars) wchar_t *out_pOut, const wchar_t *pIn, int iLengthInChars ) { wcsncpy( out_pOut, pIn, iLengthInChars ); }
- static int Compare( const wchar_t *pLhs, const wchar_t *pRhs ) { return wcscmp( pLhs, pRhs ); }
- static int CaselessCompare( const wchar_t *pLhs, const wchar_t *pRhs ); // no implementation?
- static int Length( const wchar_t *pValue ) { return (int)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""; }
- static const wchar_t *NullDebugString() { return L"(null)"; }
-};
-
-//-----------------------------------------------------------------------------
-// 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 ) {}
- explicit 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(); }
-
- 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
-{
- // Empty or null RHS?
- if ( !rhs || !rhs[0] )
- return m_pString ? 1 : 0;
-
- // Empty *this, non-empty RHS?
- if ( !m_pString )
- return -1;
-
- // Neither empty
- return StringFuncs<T>::Compare( m_pString, rhs );
-}
-
-typedef CUtlConstStringBase<char> CUtlConstString;
-typedef CUtlConstStringBase<wchar_t> CUtlConstWideString;
-
-//-----------------------------------------------------------------------------
-// Helper functor objects.
-//-----------------------------------------------------------------------------
-
-template < typename T > struct UTLConstStringCaselessStringLessFunctor { bool operator()( const CUtlConstStringBase<T>& a, const char *b ) const { return StringFuncs<T>::CaselessCompare( a.Get(), b ) < 0; } };
-template < typename T > struct UTLConstStringCaselessStringEqualFunctor { bool operator()( const CUtlConstStringBase<T>& a, const char *b ) const { return StringFuncs<T>::CaselessCompare( a.Get(), b ) == 0; } };
-
-
-#endif // UTLSTRING_H
+//========= Copyright 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"
+
+#if defined( OSX )
+#define wcsdup wcsdup_osx
+inline wchar_t *wcsdup_osx(const wchar_t *pString)
+{
+ wchar_t *pMemory;
+
+ if (!pString)
+ return NULL;
+
+ size_t len = (wcslen(pString) + 1);
+ if ((pMemory = (wchar_t *)malloc(len * sizeof(wchar_t))) != NULL)
+ {
+ return wcscpy( pMemory, pString );
+ }
+
+ return NULL;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// Base class, containing simple memory management
+//-----------------------------------------------------------------------------
+class CUtlBinaryBlock
+{
+public:
+ CUtlBinaryBlock( int growSize = 0, int initSize = 0 );
+
+ // 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 ToUpper();
+
+ 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 );
+
+ // is valid?
+ bool IsValid() const;
+
+ bool MatchesPattern( const CUtlString &Pattern, int nFlags = 0 ); // case SENSITIVE, use * for wildcard in pattern string
+
+ int Format( PRINTF_FORMAT_STRING 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 );
+
+ // Grab a substring starting from the left or the right side.
+ CUtlString Left( int32 nChars );
+ CUtlString Right( int32 nChars );
+
+ // Replace all instances of one character with another.
+ CUtlString Replace( char cFrom, char cTo );
+
+ // Calls right through to V_MakeAbsolutePath.
+ CUtlString AbsPath( const char *pStartingDir=NULL );
+
+ // Gets the filename (everything except the path.. c:\a\b\c\somefile.txt -> somefile.txt).
+ CUtlString UnqualifiedFilename();
+
+ // Strips off one directory. Uses V_StripLastDir but strips the last slash also!
+ CUtlString DirName();
+
+ // 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 bool CUtlString::IsValid() const
+{
+ return ( String() != NULL );
+}
+
+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 );
+ // Note that this function takes a character count, and does not guarantee null-termination.
+ static void Copy( T *out_pOut, const T *pIn, int iLengthInChars );
+ static int Compare( const T *pLhs, const T *pRhs );
+ static int CaselessCompare( 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();
+ static const T *NullDebugString();
+};
+
+template < >
+class StringFuncs<char>
+{
+public:
+ static char *Duplicate( const char *pValue ) { return strdup( pValue ); }
+ // Note that this function takes a character count, and does not guarantee null-termination.
+ static void Copy( OUT_CAP(iLengthInChars) char *out_pOut, const char *pIn, int iLengthInChars ) { strncpy( out_pOut, pIn, iLengthInChars ); }
+ static int Compare( const char *pLhs, const char *pRhs ) { return strcmp( pLhs, pRhs ); }
+ static int CaselessCompare( const char *pLhs, const char *pRhs ) { return Q_strcasecmp( pLhs, pRhs ); }
+ static int Length( const char *pValue ) { return (int)strlen( pValue ); }
+ static const char *FindChar( const char *pStr, const char cSearch ) { return strchr( pStr, cSearch ); }
+ static const char *EmptyString() { return ""; }
+ static const char *NullDebugString() { return "(null)"; }
+};
+
+template < >
+class StringFuncs<wchar_t>
+{
+public:
+ static wchar_t *Duplicate( const wchar_t *pValue ) { return wcsdup( pValue ); }
+ // Note that this function takes a character count, and does not guarantee null-termination.
+ static void Copy( OUT_CAP(iLengthInChars) wchar_t *out_pOut, const wchar_t *pIn, int iLengthInChars ) { wcsncpy( out_pOut, pIn, iLengthInChars ); }
+ static int Compare( const wchar_t *pLhs, const wchar_t *pRhs ) { return wcscmp( pLhs, pRhs ); }
+ static int CaselessCompare( const wchar_t *pLhs, const wchar_t *pRhs ); // no implementation?
+ static int Length( const wchar_t *pValue ) { return (int)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""; }
+ static const wchar_t *NullDebugString() { return L"(null)"; }
+};
+
+//-----------------------------------------------------------------------------
+// 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 ) {}
+ explicit 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(); }
+
+ 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
+{
+ // Empty or null RHS?
+ if ( !rhs || !rhs[0] )
+ return m_pString ? 1 : 0;
+
+ // Empty *this, non-empty RHS?
+ if ( !m_pString )
+ return -1;
+
+ // Neither empty
+ return StringFuncs<T>::Compare( m_pString, rhs );
+}
+
+typedef CUtlConstStringBase<char> CUtlConstString;
+typedef CUtlConstStringBase<wchar_t> CUtlConstWideString;
+
+//-----------------------------------------------------------------------------
+// Helper functor objects.
+//-----------------------------------------------------------------------------
+
+template < typename T > struct UTLConstStringCaselessStringLessFunctor { bool operator()( const CUtlConstStringBase<T>& a, const char *b ) const { return StringFuncs<T>::CaselessCompare( a.Get(), b ) < 0; } };
+template < typename T > struct UTLConstStringCaselessStringEqualFunctor { bool operator()( const CUtlConstStringBase<T>& a, const char *b ) const { return StringFuncs<T>::CaselessCompare( a.Get(), b ) == 0; } };
+
+
+#endif // UTLSTRING_H
diff --git a/mp/src/public/tier1/utlsymbol.h b/mp/src/public/tier1/utlsymbol.h
index b169b9ce..e90be466 100644
--- a/mp/src/public/tier1/utlsymbol.h
+++ b/mp/src/public/tier1/utlsymbol.h
@@ -1,269 +1,269 @@
-//========= Copyright 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"
-
-
-//-----------------------------------------------------------------------------
-// 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() 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();
-
-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.
-//-----------------------------------------------------------------------------
-
-class CUtlSymbolTable
-{
-public:
- // constructor, destructor
- CUtlSymbolTable( int growSize = 0, int initSize = 32, 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();
- }
-
-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 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;
-
- friend class CLess;
-};
-
-class CUtlSymbolTableMT : private 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.LockForRead();
- CUtlSymbol result = CUtlSymbolTable::Find( pString );
- m_lock.UnlockRead();
- return result;
- }
-
- const char* String( CUtlSymbol id ) const
- {
- m_lock.LockForRead();
- const char *pszResult = CUtlSymbolTable::String( id );
- m_lock.UnlockRead();
- return pszResult;
- }
-
-private:
-#if defined(WIN32) || defined(_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;
-#define FILENAMEHANDLE_INVALID 0
-
-// 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;
- };
-
- class HashTable;
-
-public:
- CUtlFilenameSymbolTable();
- ~CUtlFilenameSymbolTable();
- 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();
-
-private:
- //CCountedStringPool m_StringPool;
- HashTable* m_Strings;
- mutable CThreadSpinRWLock m_lock;
-};
-
-
-#endif // UTLSYMBOL_H
+//========= Copyright 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"
+
+
+//-----------------------------------------------------------------------------
+// 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() 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();
+
+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.
+//-----------------------------------------------------------------------------
+
+class CUtlSymbolTable
+{
+public:
+ // constructor, destructor
+ CUtlSymbolTable( int growSize = 0, int initSize = 32, 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();
+ }
+
+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 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;
+
+ friend class CLess;
+};
+
+class CUtlSymbolTableMT : private 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.LockForRead();
+ CUtlSymbol result = CUtlSymbolTable::Find( pString );
+ m_lock.UnlockRead();
+ return result;
+ }
+
+ const char* String( CUtlSymbol id ) const
+ {
+ m_lock.LockForRead();
+ const char *pszResult = CUtlSymbolTable::String( id );
+ m_lock.UnlockRead();
+ return pszResult;
+ }
+
+private:
+#if defined(WIN32) || defined(_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;
+#define FILENAMEHANDLE_INVALID 0
+
+// 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;
+ };
+
+ class HashTable;
+
+public:
+ CUtlFilenameSymbolTable();
+ ~CUtlFilenameSymbolTable();
+ 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();
+
+private:
+ //CCountedStringPool m_StringPool;
+ HashTable* m_Strings;
+ mutable CThreadSpinRWLock m_lock;
+};
+
+
+#endif // UTLSYMBOL_H
diff --git a/mp/src/public/tier1/utlsymbollarge.h b/mp/src/public/tier1/utlsymbollarge.h
index 735e32e6..43845404 100644
--- a/mp/src/public/tier1/utlsymbollarge.h
+++ b/mp/src/public/tier1/utlsymbollarge.h
@@ -1,499 +1,499 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Defines a large symbol table (intp sized handles, can store more than 64k strings)
-//
-// $Header: $
-// $NoKeywords: $
-//===========================================================================//
-
-#ifndef UTLSYMBOLLARGE_H
-#define UTLSYMBOLLARGE_H
-
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include "tier0/threadtools.h"
-#include "tier1/utltshash.h"
-#include "tier1/stringpool.h"
-#include "tier0/vprof.h"
-#include "tier1/utltshash.h"
-
-//-----------------------------------------------------------------------------
-// CUtlSymbolTableLarge:
-// description:
-// This class defines a symbol table, which allows us to perform mappings
-// of strings to symbols and back.
-//
-// This class stores the strings in a series of string pools. The returned CUtlSymbolLarge is just a pointer
-// to the string data, the hash precedes it in memory and is used to speed up searching, etc.
-//-----------------------------------------------------------------------------
-
-typedef intp UtlSymLargeId_t;
-
-#define UTL_INVAL_SYMBOL_LARGE ((UtlSymLargeId_t)~0)
-
-class CUtlSymbolLarge
-{
-public:
- // constructor, destructor
- CUtlSymbolLarge()
- {
- u.m_Id = UTL_INVAL_SYMBOL_LARGE;
- }
-
- CUtlSymbolLarge( UtlSymLargeId_t id )
- {
- u.m_Id = id;
- }
- CUtlSymbolLarge( CUtlSymbolLarge const& sym )
- {
- u.m_Id = sym.u.m_Id;
- }
-
- // operator=
- CUtlSymbolLarge& operator=( CUtlSymbolLarge const& src )
- {
- u.m_Id = src.u.m_Id;
- return *this;
- }
-
- // operator==
- bool operator==( CUtlSymbolLarge const& src ) const
- {
- return u.m_Id == src.u.m_Id;
- }
-
- // operator==
- bool operator==( UtlSymLargeId_t const& src ) const
- {
- return u.m_Id == src;
- }
-
- // operator==
- bool operator!=( CUtlSymbolLarge const& src ) const
- {
- return u.m_Id != src.u.m_Id;
- }
-
- // operator==
- bool operator!=( UtlSymLargeId_t const& src ) const
- {
- return u.m_Id != src;
- }
-
- // Gets at the symbol
- operator UtlSymLargeId_t const() const
- {
- return u.m_Id;
- }
-
- // Gets the string associated with the symbol
- inline const char* String( ) const
- {
- if ( u.m_Id == UTL_INVAL_SYMBOL_LARGE )
- return "";
- return u.m_pAsString;
- }
-
- inline bool IsValid() const
- {
- return u.m_Id != UTL_INVAL_SYMBOL_LARGE ? true : false;
- }
-
-private:
- // Disallowed
- CUtlSymbolLarge( const char* pStr ); // they need to go through the table to assign the ptr
- bool operator==( const char* pStr ) const; // disallow since we don't know if the table this is from was case sensitive or not... maybe we don't care
-
- union
- {
- UtlSymLargeId_t m_Id;
- char const *m_pAsString;
- } u;
-};
-
-#define MIN_STRING_POOL_SIZE 2048
-
-inline uint32 CUtlSymbolLarge_Hash( bool CASEINSENSITIVE, const char *pString, int len )
-{
- return ( CASEINSENSITIVE ? HashStringCaseless( pString ) : HashString( pString ) );
-}
-
-typedef uint32 LargeSymbolTableHashDecoration_t;
-
-// The structure consists of the hash immediately followed by the string data
-struct CUtlSymbolTableLargeBaseTreeEntry_t
-{
- LargeSymbolTableHashDecoration_t m_Hash;
- // Variable length string data
- char m_String[1];
-
- bool IsEmpty() const
- {
- return ( ( m_Hash == 0 ) && ( 0 == m_String[0] ) );
- }
-
- char const *String() const
- {
- return (const char *)&m_String[ 0 ];
- }
-
- CUtlSymbolLarge ToSymbol() const
- {
- return reinterpret_cast< UtlSymLargeId_t >( String() );
- }
-
- LargeSymbolTableHashDecoration_t HashValue() const
- {
- return m_Hash;
- }
-};
-
-template< class TreeType, bool CASEINSENSITIVE >
-class CTreeEntryLess
-{
-public:
- CTreeEntryLess( int ignored = 0 ) {} // permits default initialization to NULL in CUtlRBTree
- bool operator!() const { return false; }
- bool operator()( CUtlSymbolTableLargeBaseTreeEntry_t * const &left, CUtlSymbolTableLargeBaseTreeEntry_t * const &right ) const
- {
- // compare the hashes
- if ( left->m_Hash == right->m_Hash )
- {
- // if the hashes match compare the strings
- if ( !CASEINSENSITIVE )
- return strcmp( left->String(), right->String() ) < 0;
- else
- return V_stricmp( left->String(), right->String() ) < 0;
- }
- else
- {
- return left->m_Hash < right->m_Hash;
- }
- }
-};
-
-// For non-threaded versions, simply index into CUtlRBTree
-template< bool CASEINSENSITIVE >
-class CNonThreadsafeTree : public CUtlRBTree<CUtlSymbolTableLargeBaseTreeEntry_t *, intp, CTreeEntryLess< CNonThreadsafeTree< CASEINSENSITIVE >, CASEINSENSITIVE > >
-{
-public:
- typedef CUtlRBTree<CUtlSymbolTableLargeBaseTreeEntry_t *, intp, CTreeEntryLess< CNonThreadsafeTree, CASEINSENSITIVE > > CNonThreadsafeTreeType;
-
- CNonThreadsafeTree() :
- CNonThreadsafeTreeType( 0, 16 )
- {
- }
- inline void Commit()
- {
- // Nothing, only matters for thread-safe tables
- }
- inline int Insert( CUtlSymbolTableLargeBaseTreeEntry_t *entry )
- {
- return CNonThreadsafeTreeType::Insert( entry );
- }
- inline int Find( CUtlSymbolTableLargeBaseTreeEntry_t *entry ) const
- {
- return CNonThreadsafeTreeType::Find( entry );
- }
- inline int InvalidIndex() const
- {
- return CNonThreadsafeTreeType::InvalidIndex();
- }
- inline int GetElements( int nFirstElement, int nCount, CUtlSymbolLarge *pElements ) const
- {
- CUtlVector< CUtlSymbolTableLargeBaseTreeEntry_t * > list;
- list.EnsureCount( nCount );
- for ( int i = 0; i < nCount; ++i )
- {
- pElements[ i ] = CNonThreadsafeTreeType::Element( i )->ToSymbol();
- }
-
- return nCount;
- }
-};
-
-// Since CUtlSymbolTableLargeBaseTreeEntry_t already has the hash
-// contained inside of it, don't need to recompute a hash here
-template < int BUCKET_COUNT, class KEYTYPE, bool CASEINSENSITIVE >
-class CCThreadsafeTreeHashMethod
-{
-public:
- static int Hash( const KEYTYPE &key, int nBucketMask )
- {
- uint32 nHash = key->HashValue();
- return ( nHash & nBucketMask );
- }
-
- static bool Compare( CUtlSymbolTableLargeBaseTreeEntry_t * const &lhs, CUtlSymbolTableLargeBaseTreeEntry_t * const &rhs )
- {
- if ( lhs->m_Hash != rhs->m_Hash )
- return false;
- if ( !CASEINSENSITIVE )
- {
- return ( !Q_strcmp( lhs->String(), rhs->String() ) ? true : false );
- }
-
- return ( !Q_stricmp( lhs->String(), rhs->String() ) ? true : false );
- }
-};
-
-/*
- NOTE: So the only crappy thing about using a CUtlTSHash here is that the KEYTYPE is a CUtlSymbolTableLargeBaseTreeEntry_t ptr which has both the
- hash and the string since with strings there is a good chance of hash collision after you have a fair number of strings so we have to implement
- a Compare method (above) which falls back to strcmp/stricmp if the hashes are equal. This means that all of the data is in the KEYTYPE of the hash and the
- payload doesn't matter. So I made the payload also be a pointer to a CUtlSymbolTableLargeBaseTreeEntry_t since that makes using the API more convenient
-
- TODO: If we have a CUtlTSHash that was all about the existence of the KEYTYPE and didn't require a payload (or template on 'void') then we could eliminate
- 50% of the pointer overhead used for this data structure.
-*/
-
-// Thread safe version is based on the
-template < bool CASEINSENSITIVE >
-class CThreadsafeTree : public CUtlTSHash< CUtlSymbolTableLargeBaseTreeEntry_t *, 2048, CUtlSymbolTableLargeBaseTreeEntry_t *, CCThreadsafeTreeHashMethod< 2048, CUtlSymbolTableLargeBaseTreeEntry_t *, CASEINSENSITIVE > >
-{
-public:
- typedef CUtlTSHash< CUtlSymbolTableLargeBaseTreeEntry_t *, 2048, CUtlSymbolTableLargeBaseTreeEntry_t *, CCThreadsafeTreeHashMethod< 2048, CUtlSymbolTableLargeBaseTreeEntry_t *, CASEINSENSITIVE > > CThreadsafeTreeType;
-
- CThreadsafeTree() :
- CThreadsafeTreeType( 32 )
- {
- }
- inline void Commit()
- {
- CThreadsafeTreeType::Commit();
- }
- inline int Insert( CUtlSymbolTableLargeBaseTreeEntry_t *entry )
- {
- return CThreadsafeTreeType::Insert( entry, entry );
- }
- inline int Find( CUtlSymbolTableLargeBaseTreeEntry_t *entry )
- {
- return CThreadsafeTreeType::Find( entry );
- }
- inline int InvalidIndex() const
- {
- return CThreadsafeTreeType::InvalidHandle();
- }
- inline int GetElements( int nFirstElement, int nCount, CUtlSymbolLarge *pElements ) const
- {
- CUtlVector< UtlTSHashHandle_t > list;
- list.EnsureCount( nCount );
- int c = CThreadsafeTreeType::GetElements( nFirstElement, nCount, list.Base() );
- for ( int i = 0; i < c; ++i )
- {
- pElements[ i ] = CThreadsafeTreeType::Element( list[ i ] )->ToSymbol();
- }
-
- return c;
- }
-};
-
-// Base Class for threaded and non-threaded types
-template < class TreeType, bool CASEINSENSITIVE, size_t POOL_SIZE = MIN_STRING_POOL_SIZE >
-class CUtlSymbolTableLargeBase
-{
-public:
- // constructor, destructor
- CUtlSymbolTableLargeBase();
- ~CUtlSymbolTableLargeBase();
-
- // Finds and/or creates a symbol based on the string
- CUtlSymbolLarge AddString( const char* pString );
-
- // Finds the symbol for pString
- CUtlSymbolLarge Find( const char* pString ) const;
-
- // Remove all symbols in the table.
- void RemoveAll();
-
- int GetNumStrings( void ) const
- {
- return m_Lookup.Count();
- }
-
- void Commit()
- {
- m_Lookup.Commit();
- }
-
- // Returns elements in the table
- int GetElements( int nFirstElement, int nCount, CUtlSymbolLarge *pElements ) const
- {
- return m_Lookup.GetElements( nFirstElement, nCount, pElements );
- }
-
- uint64 GetMemoryUsage() const
- {
- uint64 unBytesUsed = 0u;
-
- for ( int i=0; i < m_StringPools.Count(); i++ )
- {
- StringPool_t *pPool = m_StringPools[i];
-
- unBytesUsed += (uint64)pPool->m_TotalLen;
- }
- return unBytesUsed;
- }
-
-
-protected:
-
- struct StringPool_t
- {
- int m_TotalLen; // How large is
- int m_SpaceUsed;
- char m_Data[1];
- };
-
- TreeType m_Lookup;
-
- // stores the string data
- CUtlVector< StringPool_t * > m_StringPools;
-
-private:
- int FindPoolWithSpace( int len ) const;
-};
-
-//-----------------------------------------------------------------------------
-// constructor, destructor
-//-----------------------------------------------------------------------------
-template < class TreeType, bool CASEINSENSITIVE, size_t POOL_SIZE >
-inline CUtlSymbolTableLargeBase<TreeType, CASEINSENSITIVE, POOL_SIZE >::CUtlSymbolTableLargeBase() :
- m_StringPools( 8 )
-{
-}
-
-template < class TreeType, bool CASEINSENSITIVE, size_t POOL_SIZE >
-inline CUtlSymbolTableLargeBase<TreeType, CASEINSENSITIVE, POOL_SIZE>::~CUtlSymbolTableLargeBase()
-{
- // Release the stringpool string data
- RemoveAll();
-}
-
-template < class TreeType, bool CASEINSENSITIVE, size_t POOL_SIZE >
-inline CUtlSymbolLarge CUtlSymbolTableLargeBase<TreeType, CASEINSENSITIVE, POOL_SIZE>::Find( const char* pString ) const
-{
- VPROF( "CUtlSymbolLarge::Find" );
- if (!pString)
- return CUtlSymbolLarge();
-
- // Passing this special invalid symbol makes the comparison function
- // use the string passed in the context
- int len = Q_strlen( pString ) + 1;
-
- CUtlSymbolTableLargeBaseTreeEntry_t *search = (CUtlSymbolTableLargeBaseTreeEntry_t *)_alloca( len + sizeof( LargeSymbolTableHashDecoration_t ) );
- search->m_Hash = CUtlSymbolLarge_Hash( CASEINSENSITIVE, pString, len );
- Q_memcpy( (char *)&search->m_String[ 0 ], pString, len );
-
- int idx = const_cast< TreeType & >(m_Lookup).Find( search );
-
- if ( idx == m_Lookup.InvalidIndex() )
- return UTL_INVAL_SYMBOL_LARGE;
-
- const CUtlSymbolTableLargeBaseTreeEntry_t *entry = m_Lookup[ idx ];
- return entry->ToSymbol();
-}
-
-template < class TreeType, bool CASEINSENSITIVE, size_t POOL_SIZE >
-inline int CUtlSymbolTableLargeBase<TreeType, CASEINSENSITIVE, POOL_SIZE>::FindPoolWithSpace( int len ) const
-{
- for ( int i=0; i < m_StringPools.Count(); i++ )
- {
- StringPool_t *pPool = m_StringPools[i];
-
- if ( (pPool->m_TotalLen - pPool->m_SpaceUsed) >= len )
- {
- return i;
- }
- }
-
- return -1;
-}
-
-//-----------------------------------------------------------------------------
-// Finds and/or creates a symbol based on the string
-//-----------------------------------------------------------------------------
-template < class TreeType, bool CASEINSENSITIVE, size_t POOL_SIZE >
-inline CUtlSymbolLarge CUtlSymbolTableLargeBase<TreeType, CASEINSENSITIVE, POOL_SIZE>::AddString( const char* pString )
-{
- VPROF("CUtlSymbolLarge::AddString");
- if (!pString)
- return UTL_INVAL_SYMBOL_LARGE;
-
- CUtlSymbolLarge id = Find( pString );
- if ( id != UTL_INVAL_SYMBOL_LARGE )
- return id;
-
- int lenString = Q_strlen(pString) + 1; // length of just the string
- int lenDecorated = lenString + sizeof(LargeSymbolTableHashDecoration_t); // and with its hash decoration
- // make sure that all strings are aligned on 2-byte boundaries so the hashes will read correctly
- // This assert seems to be invalid because LargeSymbolTableHashDecoration_t is always
- // a uint32, by design.
- //COMPILE_TIME_ASSERT(sizeof(LargeSymbolTableHashDecoration_t) == sizeof(intp));
- lenDecorated = ALIGN_VALUE(lenDecorated, sizeof( intp ) );
-
- // Find a pool with space for this string, or allocate a new one.
- int iPool = FindPoolWithSpace( lenDecorated );
- if ( iPool == -1 )
- {
- // Add a new pool.
- int newPoolSize = MAX( lenDecorated + sizeof( StringPool_t ), POOL_SIZE );
- StringPool_t *pPool = (StringPool_t*)malloc( newPoolSize );
-
- pPool->m_TotalLen = newPoolSize - sizeof( StringPool_t );
- pPool->m_SpaceUsed = 0;
- iPool = m_StringPools.AddToTail( pPool );
- }
-
- // Compute a hash
- LargeSymbolTableHashDecoration_t hash = CUtlSymbolLarge_Hash( CASEINSENSITIVE, pString, lenString );
-
- // Copy the string in.
- StringPool_t *pPool = m_StringPools[iPool];
- // Assert( pPool->m_SpaceUsed < 0xFFFF ); // Pool could be bigger than 2k
- // This should never happen, because if we had a string > 64k, it
- // would have been given its entire own pool.
-
- CUtlSymbolTableLargeBaseTreeEntry_t *entry = ( CUtlSymbolTableLargeBaseTreeEntry_t * )&pPool->m_Data[ pPool->m_SpaceUsed ];
-
- pPool->m_SpaceUsed += lenDecorated;
-
- entry->m_Hash = hash;
- char *pText = (char *)&entry->m_String [ 0 ];
- Q_memcpy( pText, pString, lenString );
-
- // insert the string into the database
- MEM_ALLOC_CREDIT();
- int idx = m_Lookup.Insert( entry );
- return m_Lookup.Element( idx )->ToSymbol();
-}
-
-//-----------------------------------------------------------------------------
-// Remove all symbols in the table.
-//-----------------------------------------------------------------------------
-template < class TreeType, bool CASEINSENSITIVE, size_t POOL_SIZE >
-inline void CUtlSymbolTableLargeBase<TreeType, CASEINSENSITIVE, POOL_SIZE>::RemoveAll()
-{
- m_Lookup.Purge();
-
- for ( int i=0; i < m_StringPools.Count(); i++ )
- {
- StringPool_t * pString = m_StringPools[i];
- free( pString );
- }
-
- m_StringPools.RemoveAll();
-}
-
-// Case-sensitive
-typedef CUtlSymbolTableLargeBase< CNonThreadsafeTree< false >, false > CUtlSymbolTableLarge;
-// Case-insensitive
-typedef CUtlSymbolTableLargeBase< CNonThreadsafeTree< true >, true > CUtlSymbolTableLarge_CI;
-// Multi-threaded case-sensitive
-typedef CUtlSymbolTableLargeBase< CThreadsafeTree< false >, false > CUtlSymbolTableLargeMT;
-// Multi-threaded case-insensitive
-typedef CUtlSymbolTableLargeBase< CThreadsafeTree< true >, true > CUtlSymbolTableLargeMT_CI;
-
-#endif // UTLSYMBOLLARGE_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Defines a large symbol table (intp sized handles, can store more than 64k strings)
+//
+// $Header: $
+// $NoKeywords: $
+//===========================================================================//
+
+#ifndef UTLSYMBOLLARGE_H
+#define UTLSYMBOLLARGE_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/threadtools.h"
+#include "tier1/utltshash.h"
+#include "tier1/stringpool.h"
+#include "tier0/vprof.h"
+#include "tier1/utltshash.h"
+
+//-----------------------------------------------------------------------------
+// CUtlSymbolTableLarge:
+// description:
+// This class defines a symbol table, which allows us to perform mappings
+// of strings to symbols and back.
+//
+// This class stores the strings in a series of string pools. The returned CUtlSymbolLarge is just a pointer
+// to the string data, the hash precedes it in memory and is used to speed up searching, etc.
+//-----------------------------------------------------------------------------
+
+typedef intp UtlSymLargeId_t;
+
+#define UTL_INVAL_SYMBOL_LARGE ((UtlSymLargeId_t)~0)
+
+class CUtlSymbolLarge
+{
+public:
+ // constructor, destructor
+ CUtlSymbolLarge()
+ {
+ u.m_Id = UTL_INVAL_SYMBOL_LARGE;
+ }
+
+ CUtlSymbolLarge( UtlSymLargeId_t id )
+ {
+ u.m_Id = id;
+ }
+ CUtlSymbolLarge( CUtlSymbolLarge const& sym )
+ {
+ u.m_Id = sym.u.m_Id;
+ }
+
+ // operator=
+ CUtlSymbolLarge& operator=( CUtlSymbolLarge const& src )
+ {
+ u.m_Id = src.u.m_Id;
+ return *this;
+ }
+
+ // operator==
+ bool operator==( CUtlSymbolLarge const& src ) const
+ {
+ return u.m_Id == src.u.m_Id;
+ }
+
+ // operator==
+ bool operator==( UtlSymLargeId_t const& src ) const
+ {
+ return u.m_Id == src;
+ }
+
+ // operator==
+ bool operator!=( CUtlSymbolLarge const& src ) const
+ {
+ return u.m_Id != src.u.m_Id;
+ }
+
+ // operator==
+ bool operator!=( UtlSymLargeId_t const& src ) const
+ {
+ return u.m_Id != src;
+ }
+
+ // Gets at the symbol
+ operator UtlSymLargeId_t const() const
+ {
+ return u.m_Id;
+ }
+
+ // Gets the string associated with the symbol
+ inline const char* String( ) const
+ {
+ if ( u.m_Id == UTL_INVAL_SYMBOL_LARGE )
+ return "";
+ return u.m_pAsString;
+ }
+
+ inline bool IsValid() const
+ {
+ return u.m_Id != UTL_INVAL_SYMBOL_LARGE ? true : false;
+ }
+
+private:
+ // Disallowed
+ CUtlSymbolLarge( const char* pStr ); // they need to go through the table to assign the ptr
+ bool operator==( const char* pStr ) const; // disallow since we don't know if the table this is from was case sensitive or not... maybe we don't care
+
+ union
+ {
+ UtlSymLargeId_t m_Id;
+ char const *m_pAsString;
+ } u;
+};
+
+#define MIN_STRING_POOL_SIZE 2048
+
+inline uint32 CUtlSymbolLarge_Hash( bool CASEINSENSITIVE, const char *pString, int len )
+{
+ return ( CASEINSENSITIVE ? HashStringCaseless( pString ) : HashString( pString ) );
+}
+
+typedef uint32 LargeSymbolTableHashDecoration_t;
+
+// The structure consists of the hash immediately followed by the string data
+struct CUtlSymbolTableLargeBaseTreeEntry_t
+{
+ LargeSymbolTableHashDecoration_t m_Hash;
+ // Variable length string data
+ char m_String[1];
+
+ bool IsEmpty() const
+ {
+ return ( ( m_Hash == 0 ) && ( 0 == m_String[0] ) );
+ }
+
+ char const *String() const
+ {
+ return (const char *)&m_String[ 0 ];
+ }
+
+ CUtlSymbolLarge ToSymbol() const
+ {
+ return reinterpret_cast< UtlSymLargeId_t >( String() );
+ }
+
+ LargeSymbolTableHashDecoration_t HashValue() const
+ {
+ return m_Hash;
+ }
+};
+
+template< class TreeType, bool CASEINSENSITIVE >
+class CTreeEntryLess
+{
+public:
+ CTreeEntryLess( int ignored = 0 ) {} // permits default initialization to NULL in CUtlRBTree
+ bool operator!() const { return false; }
+ bool operator()( CUtlSymbolTableLargeBaseTreeEntry_t * const &left, CUtlSymbolTableLargeBaseTreeEntry_t * const &right ) const
+ {
+ // compare the hashes
+ if ( left->m_Hash == right->m_Hash )
+ {
+ // if the hashes match compare the strings
+ if ( !CASEINSENSITIVE )
+ return strcmp( left->String(), right->String() ) < 0;
+ else
+ return V_stricmp( left->String(), right->String() ) < 0;
+ }
+ else
+ {
+ return left->m_Hash < right->m_Hash;
+ }
+ }
+};
+
+// For non-threaded versions, simply index into CUtlRBTree
+template< bool CASEINSENSITIVE >
+class CNonThreadsafeTree : public CUtlRBTree<CUtlSymbolTableLargeBaseTreeEntry_t *, intp, CTreeEntryLess< CNonThreadsafeTree< CASEINSENSITIVE >, CASEINSENSITIVE > >
+{
+public:
+ typedef CUtlRBTree<CUtlSymbolTableLargeBaseTreeEntry_t *, intp, CTreeEntryLess< CNonThreadsafeTree, CASEINSENSITIVE > > CNonThreadsafeTreeType;
+
+ CNonThreadsafeTree() :
+ CNonThreadsafeTreeType( 0, 16 )
+ {
+ }
+ inline void Commit()
+ {
+ // Nothing, only matters for thread-safe tables
+ }
+ inline int Insert( CUtlSymbolTableLargeBaseTreeEntry_t *entry )
+ {
+ return CNonThreadsafeTreeType::Insert( entry );
+ }
+ inline int Find( CUtlSymbolTableLargeBaseTreeEntry_t *entry ) const
+ {
+ return CNonThreadsafeTreeType::Find( entry );
+ }
+ inline int InvalidIndex() const
+ {
+ return CNonThreadsafeTreeType::InvalidIndex();
+ }
+ inline int GetElements( int nFirstElement, int nCount, CUtlSymbolLarge *pElements ) const
+ {
+ CUtlVector< CUtlSymbolTableLargeBaseTreeEntry_t * > list;
+ list.EnsureCount( nCount );
+ for ( int i = 0; i < nCount; ++i )
+ {
+ pElements[ i ] = CNonThreadsafeTreeType::Element( i )->ToSymbol();
+ }
+
+ return nCount;
+ }
+};
+
+// Since CUtlSymbolTableLargeBaseTreeEntry_t already has the hash
+// contained inside of it, don't need to recompute a hash here
+template < int BUCKET_COUNT, class KEYTYPE, bool CASEINSENSITIVE >
+class CCThreadsafeTreeHashMethod
+{
+public:
+ static int Hash( const KEYTYPE &key, int nBucketMask )
+ {
+ uint32 nHash = key->HashValue();
+ return ( nHash & nBucketMask );
+ }
+
+ static bool Compare( CUtlSymbolTableLargeBaseTreeEntry_t * const &lhs, CUtlSymbolTableLargeBaseTreeEntry_t * const &rhs )
+ {
+ if ( lhs->m_Hash != rhs->m_Hash )
+ return false;
+ if ( !CASEINSENSITIVE )
+ {
+ return ( !Q_strcmp( lhs->String(), rhs->String() ) ? true : false );
+ }
+
+ return ( !Q_stricmp( lhs->String(), rhs->String() ) ? true : false );
+ }
+};
+
+/*
+ NOTE: So the only crappy thing about using a CUtlTSHash here is that the KEYTYPE is a CUtlSymbolTableLargeBaseTreeEntry_t ptr which has both the
+ hash and the string since with strings there is a good chance of hash collision after you have a fair number of strings so we have to implement
+ a Compare method (above) which falls back to strcmp/stricmp if the hashes are equal. This means that all of the data is in the KEYTYPE of the hash and the
+ payload doesn't matter. So I made the payload also be a pointer to a CUtlSymbolTableLargeBaseTreeEntry_t since that makes using the API more convenient
+
+ TODO: If we have a CUtlTSHash that was all about the existence of the KEYTYPE and didn't require a payload (or template on 'void') then we could eliminate
+ 50% of the pointer overhead used for this data structure.
+*/
+
+// Thread safe version is based on the
+template < bool CASEINSENSITIVE >
+class CThreadsafeTree : public CUtlTSHash< CUtlSymbolTableLargeBaseTreeEntry_t *, 2048, CUtlSymbolTableLargeBaseTreeEntry_t *, CCThreadsafeTreeHashMethod< 2048, CUtlSymbolTableLargeBaseTreeEntry_t *, CASEINSENSITIVE > >
+{
+public:
+ typedef CUtlTSHash< CUtlSymbolTableLargeBaseTreeEntry_t *, 2048, CUtlSymbolTableLargeBaseTreeEntry_t *, CCThreadsafeTreeHashMethod< 2048, CUtlSymbolTableLargeBaseTreeEntry_t *, CASEINSENSITIVE > > CThreadsafeTreeType;
+
+ CThreadsafeTree() :
+ CThreadsafeTreeType( 32 )
+ {
+ }
+ inline void Commit()
+ {
+ CThreadsafeTreeType::Commit();
+ }
+ inline int Insert( CUtlSymbolTableLargeBaseTreeEntry_t *entry )
+ {
+ return CThreadsafeTreeType::Insert( entry, entry );
+ }
+ inline int Find( CUtlSymbolTableLargeBaseTreeEntry_t *entry )
+ {
+ return CThreadsafeTreeType::Find( entry );
+ }
+ inline int InvalidIndex() const
+ {
+ return CThreadsafeTreeType::InvalidHandle();
+ }
+ inline int GetElements( int nFirstElement, int nCount, CUtlSymbolLarge *pElements ) const
+ {
+ CUtlVector< UtlTSHashHandle_t > list;
+ list.EnsureCount( nCount );
+ int c = CThreadsafeTreeType::GetElements( nFirstElement, nCount, list.Base() );
+ for ( int i = 0; i < c; ++i )
+ {
+ pElements[ i ] = CThreadsafeTreeType::Element( list[ i ] )->ToSymbol();
+ }
+
+ return c;
+ }
+};
+
+// Base Class for threaded and non-threaded types
+template < class TreeType, bool CASEINSENSITIVE, size_t POOL_SIZE = MIN_STRING_POOL_SIZE >
+class CUtlSymbolTableLargeBase
+{
+public:
+ // constructor, destructor
+ CUtlSymbolTableLargeBase();
+ ~CUtlSymbolTableLargeBase();
+
+ // Finds and/or creates a symbol based on the string
+ CUtlSymbolLarge AddString( const char* pString );
+
+ // Finds the symbol for pString
+ CUtlSymbolLarge Find( const char* pString ) const;
+
+ // Remove all symbols in the table.
+ void RemoveAll();
+
+ int GetNumStrings( void ) const
+ {
+ return m_Lookup.Count();
+ }
+
+ void Commit()
+ {
+ m_Lookup.Commit();
+ }
+
+ // Returns elements in the table
+ int GetElements( int nFirstElement, int nCount, CUtlSymbolLarge *pElements ) const
+ {
+ return m_Lookup.GetElements( nFirstElement, nCount, pElements );
+ }
+
+ uint64 GetMemoryUsage() const
+ {
+ uint64 unBytesUsed = 0u;
+
+ for ( int i=0; i < m_StringPools.Count(); i++ )
+ {
+ StringPool_t *pPool = m_StringPools[i];
+
+ unBytesUsed += (uint64)pPool->m_TotalLen;
+ }
+ return unBytesUsed;
+ }
+
+
+protected:
+
+ struct StringPool_t
+ {
+ int m_TotalLen; // How large is
+ int m_SpaceUsed;
+ char m_Data[1];
+ };
+
+ TreeType m_Lookup;
+
+ // stores the string data
+ CUtlVector< StringPool_t * > m_StringPools;
+
+private:
+ int FindPoolWithSpace( int len ) const;
+};
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+template < class TreeType, bool CASEINSENSITIVE, size_t POOL_SIZE >
+inline CUtlSymbolTableLargeBase<TreeType, CASEINSENSITIVE, POOL_SIZE >::CUtlSymbolTableLargeBase() :
+ m_StringPools( 8 )
+{
+}
+
+template < class TreeType, bool CASEINSENSITIVE, size_t POOL_SIZE >
+inline CUtlSymbolTableLargeBase<TreeType, CASEINSENSITIVE, POOL_SIZE>::~CUtlSymbolTableLargeBase()
+{
+ // Release the stringpool string data
+ RemoveAll();
+}
+
+template < class TreeType, bool CASEINSENSITIVE, size_t POOL_SIZE >
+inline CUtlSymbolLarge CUtlSymbolTableLargeBase<TreeType, CASEINSENSITIVE, POOL_SIZE>::Find( const char* pString ) const
+{
+ VPROF( "CUtlSymbolLarge::Find" );
+ if (!pString)
+ return CUtlSymbolLarge();
+
+ // Passing this special invalid symbol makes the comparison function
+ // use the string passed in the context
+ int len = Q_strlen( pString ) + 1;
+
+ CUtlSymbolTableLargeBaseTreeEntry_t *search = (CUtlSymbolTableLargeBaseTreeEntry_t *)_alloca( len + sizeof( LargeSymbolTableHashDecoration_t ) );
+ search->m_Hash = CUtlSymbolLarge_Hash( CASEINSENSITIVE, pString, len );
+ Q_memcpy( (char *)&search->m_String[ 0 ], pString, len );
+
+ int idx = const_cast< TreeType & >(m_Lookup).Find( search );
+
+ if ( idx == m_Lookup.InvalidIndex() )
+ return UTL_INVAL_SYMBOL_LARGE;
+
+ const CUtlSymbolTableLargeBaseTreeEntry_t *entry = m_Lookup[ idx ];
+ return entry->ToSymbol();
+}
+
+template < class TreeType, bool CASEINSENSITIVE, size_t POOL_SIZE >
+inline int CUtlSymbolTableLargeBase<TreeType, CASEINSENSITIVE, POOL_SIZE>::FindPoolWithSpace( int len ) const
+{
+ for ( int i=0; i < m_StringPools.Count(); i++ )
+ {
+ StringPool_t *pPool = m_StringPools[i];
+
+ if ( (pPool->m_TotalLen - pPool->m_SpaceUsed) >= len )
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+// Finds and/or creates a symbol based on the string
+//-----------------------------------------------------------------------------
+template < class TreeType, bool CASEINSENSITIVE, size_t POOL_SIZE >
+inline CUtlSymbolLarge CUtlSymbolTableLargeBase<TreeType, CASEINSENSITIVE, POOL_SIZE>::AddString( const char* pString )
+{
+ VPROF("CUtlSymbolLarge::AddString");
+ if (!pString)
+ return UTL_INVAL_SYMBOL_LARGE;
+
+ CUtlSymbolLarge id = Find( pString );
+ if ( id != UTL_INVAL_SYMBOL_LARGE )
+ return id;
+
+ int lenString = Q_strlen(pString) + 1; // length of just the string
+ int lenDecorated = lenString + sizeof(LargeSymbolTableHashDecoration_t); // and with its hash decoration
+ // make sure that all strings are aligned on 2-byte boundaries so the hashes will read correctly
+ // This assert seems to be invalid because LargeSymbolTableHashDecoration_t is always
+ // a uint32, by design.
+ //COMPILE_TIME_ASSERT(sizeof(LargeSymbolTableHashDecoration_t) == sizeof(intp));
+ lenDecorated = ALIGN_VALUE(lenDecorated, sizeof( intp ) );
+
+ // Find a pool with space for this string, or allocate a new one.
+ int iPool = FindPoolWithSpace( lenDecorated );
+ if ( iPool == -1 )
+ {
+ // Add a new pool.
+ int newPoolSize = MAX( lenDecorated + sizeof( StringPool_t ), POOL_SIZE );
+ StringPool_t *pPool = (StringPool_t*)malloc( newPoolSize );
+
+ pPool->m_TotalLen = newPoolSize - sizeof( StringPool_t );
+ pPool->m_SpaceUsed = 0;
+ iPool = m_StringPools.AddToTail( pPool );
+ }
+
+ // Compute a hash
+ LargeSymbolTableHashDecoration_t hash = CUtlSymbolLarge_Hash( CASEINSENSITIVE, pString, lenString );
+
+ // Copy the string in.
+ StringPool_t *pPool = m_StringPools[iPool];
+ // Assert( pPool->m_SpaceUsed < 0xFFFF ); // Pool could be bigger than 2k
+ // This should never happen, because if we had a string > 64k, it
+ // would have been given its entire own pool.
+
+ CUtlSymbolTableLargeBaseTreeEntry_t *entry = ( CUtlSymbolTableLargeBaseTreeEntry_t * )&pPool->m_Data[ pPool->m_SpaceUsed ];
+
+ pPool->m_SpaceUsed += lenDecorated;
+
+ entry->m_Hash = hash;
+ char *pText = (char *)&entry->m_String [ 0 ];
+ Q_memcpy( pText, pString, lenString );
+
+ // insert the string into the database
+ MEM_ALLOC_CREDIT();
+ int idx = m_Lookup.Insert( entry );
+ return m_Lookup.Element( idx )->ToSymbol();
+}
+
+//-----------------------------------------------------------------------------
+// Remove all symbols in the table.
+//-----------------------------------------------------------------------------
+template < class TreeType, bool CASEINSENSITIVE, size_t POOL_SIZE >
+inline void CUtlSymbolTableLargeBase<TreeType, CASEINSENSITIVE, POOL_SIZE>::RemoveAll()
+{
+ m_Lookup.Purge();
+
+ for ( int i=0; i < m_StringPools.Count(); i++ )
+ {
+ StringPool_t * pString = m_StringPools[i];
+ free( pString );
+ }
+
+ m_StringPools.RemoveAll();
+}
+
+// Case-sensitive
+typedef CUtlSymbolTableLargeBase< CNonThreadsafeTree< false >, false > CUtlSymbolTableLarge;
+// Case-insensitive
+typedef CUtlSymbolTableLargeBase< CNonThreadsafeTree< true >, true > CUtlSymbolTableLarge_CI;
+// Multi-threaded case-sensitive
+typedef CUtlSymbolTableLargeBase< CThreadsafeTree< false >, false > CUtlSymbolTableLargeMT;
+// Multi-threaded case-insensitive
+typedef CUtlSymbolTableLargeBase< CThreadsafeTree< true >, true > CUtlSymbolTableLargeMT_CI;
+
+#endif // UTLSYMBOLLARGE_H
diff --git a/mp/src/public/tier1/utltshash.h b/mp/src/public/tier1/utltshash.h
index eb19ae99..9ff4e83f 100644
--- a/mp/src/public/tier1/utltshash.h
+++ b/mp/src/public/tier1/utltshash.h
@@ -1,625 +1,625 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//
-// Thread-safe hash class
-//===========================================================================//
-
-#ifndef UTLTSHASH_H
-#define UTLTSHASH_H
-
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include <limits.h>
-#include "tier0/threadtools.h"
-#include "tier1/mempool.h"
-#include "generichash.h"
-
-
-//=============================================================================
-//
-// Threadsafe Hash
-//
-// Number of buckets must be a power of 2.
-// Key must be intp sized (32-bits on x32, 64-bits on x64)
-// Designed for a usage pattern where the data is semi-static, and there
-// is a well-defined point where we are guaranteed no queries are occurring.
-//
-// Insertions are added into a thread-safe list, and when Commit() is called,
-// the insertions are moved into a lock-free list
-//
-// Elements are never individually removed; clears must occur at a time
-// where we and guaranteed no queries are occurring
-//
-typedef intp UtlTSHashHandle_t;
-
-template < class T >
-abstract_class ITSHashConstructor
-{
-public:
- virtual void Construct( T* pElement ) = 0;
-};
-
-template < class T >
-class CDefaultTSHashConstructor : public ITSHashConstructor< T >
-{
-public:
- virtual void Construct( T* pElement )
- {
- ::Construct( pElement );
- }
-};
-
-template < int BUCKET_COUNT, class KEYTYPE = intp >
-class CUtlTSHashGenericHash
-{
-public:
- static int Hash( const KEYTYPE &key, int nBucketMask )
- {
- int nHash = HashIntConventional( (intp)key );
- if ( BUCKET_COUNT <= USHRT_MAX )
- {
- nHash ^= ( nHash >> 16 );
- }
- if ( BUCKET_COUNT <= UCHAR_MAX )
- {
- nHash ^= ( nHash >> 8 );
- }
- return ( nHash & nBucketMask );
- }
-
- static bool Compare( const KEYTYPE &lhs, const KEYTYPE &rhs )
- {
- return lhs == rhs;
- }
-};
-
-template < int BUCKET_COUNT, class KEYTYPE >
-class CUtlTSHashUseKeyHashMethod
-{
-public:
- static int Hash( const KEYTYPE &key, int nBucketMask )
- {
- uint32 nHash = key.HashValue();
- return ( nHash & nBucketMask );
- }
-
- static bool Compare( const KEYTYPE &lhs, const KEYTYPE &rhs )
- {
- return lhs == rhs;
- }
-};
-
-template< class T, int BUCKET_COUNT, class KEYTYPE = intp, class HashFuncs = CUtlTSHashGenericHash< BUCKET_COUNT, KEYTYPE >, int nAlignment = 0 >
-class CUtlTSHash
-{
-public:
- // Constructor/Deconstructor.
- CUtlTSHash( int nAllocationCount );
- ~CUtlTSHash();
-
- // Invalid handle.
- static UtlTSHashHandle_t InvalidHandle( void ) { return ( UtlTSHashHandle_t )0; }
-
- // Retrieval. Super fast, is thread-safe
- UtlTSHashHandle_t Find( KEYTYPE uiKey );
-
- // Insertion ( find or add ).
- UtlTSHashHandle_t Insert( KEYTYPE uiKey, const T &data, bool *pDidInsert = NULL );
- UtlTSHashHandle_t Insert( KEYTYPE uiKey, ITSHashConstructor<T> *pConstructor, bool *pDidInsert = NULL );
-
- // This insertion method assumes the element is not in the hash table, skips
- UtlTSHashHandle_t FastInsert( KEYTYPE uiKey, const T &data );
- UtlTSHashHandle_t FastInsert( KEYTYPE uiKey, ITSHashConstructor<T> *pConstructor );
-
- // Commit recent insertions, making finding them faster.
- // Only call when you're certain no threads are accessing the hash table
- void Commit( );
-
- // Removal. Only call when you're certain no threads are accessing the hash table
- void FindAndRemove( KEYTYPE uiKey );
- void Remove( UtlTSHashHandle_t hHash ) { FindAndRemove( GetID( hHash ) ); }
- void RemoveAll( void );
- void Purge( void );
-
- // Returns the number of elements in the hash table
- int Count() const;
-
- // Returns elements in the table
- int GetElements( int nFirstElement, int nCount, UtlTSHashHandle_t *pHandles ) const;
-
- // Element access
- T &Element( UtlTSHashHandle_t hHash );
- T const &Element( UtlTSHashHandle_t hHash ) const;
- T &operator[]( UtlTSHashHandle_t hHash );
- T const &operator[]( UtlTSHashHandle_t hHash ) const;
- KEYTYPE GetID( UtlTSHashHandle_t hHash ) const;
-
- // Convert element * to hashHandle
- UtlTSHashHandle_t ElementPtrToHandle( T* pElement ) const;
-
-private:
- // Templatized for memory tracking purposes
- template < typename Data_t >
- struct HashFixedDataInternal_t
- {
- KEYTYPE m_uiKey;
- HashFixedDataInternal_t< Data_t >* m_pNext;
- Data_t m_Data;
- };
-
- typedef HashFixedDataInternal_t<T> HashFixedData_t;
-
- enum
- {
- BUCKET_MASK = BUCKET_COUNT - 1
- };
-
- struct HashBucket_t
- {
- HashFixedData_t *m_pFirst;
- HashFixedData_t *m_pFirstUncommitted;
- CThreadSpinRWLock m_AddLock;
- };
-
- UtlTSHashHandle_t Find( KEYTYPE uiKey, HashFixedData_t *pFirstElement, HashFixedData_t *pLastElement );
- UtlTSHashHandle_t InsertUncommitted( KEYTYPE uiKey, HashBucket_t &bucket );
- CMemoryPoolMT m_EntryMemory;
- HashBucket_t m_aBuckets[BUCKET_COUNT];
- bool m_bNeedsCommit;
-
-#ifdef _DEBUG
- CInterlockedInt m_ContentionCheck;
-#endif
-};
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Constructor
-//-----------------------------------------------------------------------------
-template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
-CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::CUtlTSHash( int nAllocationCount ) :
- m_EntryMemory( sizeof( HashFixedData_t ), nAllocationCount, CUtlMemoryPool::GROW_SLOW, MEM_ALLOC_CLASSNAME( HashFixedData_t ), nAlignment )
-{
-#ifdef _DEBUG
- m_ContentionCheck = 0;
-#endif
- m_bNeedsCommit = false;
- for ( int i = 0; i < BUCKET_COUNT; i++ )
- {
- HashBucket_t &bucket = m_aBuckets[ i ];
- bucket.m_pFirst = NULL;
- bucket.m_pFirstUncommitted = NULL;
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Deconstructor
-//-----------------------------------------------------------------------------
-template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
-CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::~CUtlTSHash()
-{
-#ifdef _DEBUG
- if ( m_ContentionCheck != 0 )
- {
- DebuggerBreak();
- }
-#endif
- Purge();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Destroy dynamically allocated hash data.
-//-----------------------------------------------------------------------------
-template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
-inline void CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::Purge( void )
-{
- RemoveAll();
-}
-
-
-//-----------------------------------------------------------------------------
-// Returns the number of elements in the hash table
-//-----------------------------------------------------------------------------
-template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
-inline int CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::Count() const
-{
- return m_EntryMemory.Count();
-}
-
-
-//-----------------------------------------------------------------------------
-// Returns elements in the table
-//-----------------------------------------------------------------------------
-template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
-int CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::GetElements( int nFirstElement, int nCount, UtlTSHashHandle_t *pHandles ) const
-{
- int nIndex = 0;
- for ( int i = 0; i < BUCKET_COUNT; i++ )
- {
- const HashBucket_t &bucket = m_aBuckets[ i ];
- bucket.m_AddLock.LockForRead( );
- for ( HashFixedData_t *pElement = bucket.m_pFirstUncommitted; pElement; pElement = pElement->m_pNext )
- {
- if ( --nFirstElement >= 0 )
- continue;
-
- pHandles[ nIndex++ ] = (UtlTSHashHandle_t)pElement;
- if ( nIndex >= nCount )
- {
- bucket.m_AddLock.UnlockRead( );
- return nIndex;
- }
- }
- bucket.m_AddLock.UnlockRead( );
- }
- return nIndex;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Insert data into the hash table given its key (KEYTYPE),
-// without a check to see if the element already exists within the tree.
-//-----------------------------------------------------------------------------
-template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
-inline UtlTSHashHandle_t CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::InsertUncommitted( KEYTYPE uiKey, HashBucket_t &bucket )
-{
- m_bNeedsCommit = true;
- HashFixedData_t *pNewElement = static_cast< HashFixedData_t * >( m_EntryMemory.Alloc() );
- pNewElement->m_pNext = bucket.m_pFirstUncommitted;
- bucket.m_pFirstUncommitted = pNewElement;
- pNewElement->m_uiKey = uiKey;
- return (UtlTSHashHandle_t)pNewElement;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Insert data into the hash table given its key, with
-// a check to see if the element already exists within the tree.
-//-----------------------------------------------------------------------------
-template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
-inline UtlTSHashHandle_t CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::Insert( KEYTYPE uiKey, const T &data, bool *pDidInsert )
-{
-#ifdef _DEBUG
- if ( m_ContentionCheck != 0 )
- {
- DebuggerBreak();
- }
-#endif
-
- if ( pDidInsert )
- {
- *pDidInsert = false;
- }
-
- int iBucket = HashFuncs::Hash( uiKey, BUCKET_MASK );
- HashBucket_t &bucket = m_aBuckets[ iBucket ];
-
- // First try lock-free
- UtlTSHashHandle_t h = Find( uiKey );
- if ( h != InvalidHandle() )
- return h;
-
- // Now, try again, but only look in uncommitted elements
- bucket.m_AddLock.LockForWrite( );
-
- h = Find( uiKey, bucket.m_pFirstUncommitted, bucket.m_pFirst );
- if ( h == InvalidHandle() )
- {
- h = InsertUncommitted( uiKey, bucket );
- CopyConstruct( &Element(h), data );
- if ( pDidInsert )
- {
- *pDidInsert = true;
- }
- }
-
- bucket.m_AddLock.UnlockWrite( );
- return h;
-}
-
-template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
-inline UtlTSHashHandle_t CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::Insert( KEYTYPE uiKey, ITSHashConstructor<T> *pConstructor, bool *pDidInsert )
-{
-#ifdef _DEBUG
- if ( m_ContentionCheck != 0 )
- {
- DebuggerBreak();
- }
-#endif
-
- if ( pDidInsert )
- {
- *pDidInsert = false;
- }
-
- // First try lock-free
- UtlTSHashHandle_t h = Find( uiKey );
- if ( h != InvalidHandle() )
- return h;
-
- // Now, try again, but only look in uncommitted elements
- int iBucket = HashFuncs::Hash( uiKey, BUCKET_MASK );
- HashBucket_t &bucket = m_aBuckets[ iBucket ];
- bucket.m_AddLock.LockForWrite( );
-
- h = Find( uiKey, bucket.m_pFirstUncommitted, bucket.m_pFirst );
- if ( h == InvalidHandle() )
- {
- // Useful if non-trivial work needs to happen to make data; don't want to
- // do it and then have to undo it if it turns out we don't need to add it
- h = InsertUncommitted( uiKey, bucket );
- pConstructor->Construct( &Element(h) );
- if ( pDidInsert )
- {
- *pDidInsert = true;
- }
- }
-
- bucket.m_AddLock.UnlockWrite( );
- return h;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Insert data into the hash table given its key
-// without a check to see if the element already exists within the tree.
-//-----------------------------------------------------------------------------
-template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
-inline UtlTSHashHandle_t CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::FastInsert( KEYTYPE uiKey, const T &data )
-{
-#ifdef _DEBUG
- if ( m_ContentionCheck != 0 )
- {
- DebuggerBreak();
- }
-#endif
- int iBucket = HashFuncs::Hash( uiKey, BUCKET_MASK );
- HashBucket_t &bucket = m_aBuckets[ iBucket ];
- bucket.m_AddLock.LockForWrite( );
- UtlTSHashHandle_t h = InsertUncommitted( uiKey, bucket );
- CopyConstruct( &Element(h), data );
- bucket.m_AddLock.UnlockWrite( );
- return h;
-}
-
-template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
-inline UtlTSHashHandle_t CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::FastInsert( KEYTYPE uiKey, ITSHashConstructor<T> *pConstructor )
-{
-#ifdef _DEBUG
- if ( m_ContentionCheck != 0 )
- {
- DebuggerBreak();
- }
-#endif
- int iBucket = HashFuncs::Hash( uiKey, BUCKET_MASK );
- HashBucket_t &bucket = m_aBuckets[ iBucket ];
- bucket.m_AddLock.LockForWrite( );
- UtlTSHashHandle_t h = InsertUncommitted( uiKey, bucket );
- pConstructor->Construct( &Element(h) );
- bucket.m_AddLock.UnlockWrite( );
- return h;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Commits all uncommitted insertions
-//-----------------------------------------------------------------------------
-template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
-inline void CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::Commit( )
-{
- // FIXME: Is this legal? Want this to be lock-free
- if ( !m_bNeedsCommit )
- return;
-
- // This must occur when no queries are occurring
-#ifdef _DEBUG
- m_ContentionCheck++;
-#endif
-
- for ( int i = 0; i < BUCKET_COUNT; i++ )
- {
- HashBucket_t &bucket = m_aBuckets[ i ];
- bucket.m_AddLock.LockForRead( );
- bucket.m_pFirst = bucket.m_pFirstUncommitted;
- bucket.m_AddLock.UnlockRead( );
- }
-
- m_bNeedsCommit = false;
-
-#ifdef _DEBUG
- m_ContentionCheck--;
-#endif
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Remove a single element from the hash
-//-----------------------------------------------------------------------------
-template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
-inline void CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::FindAndRemove( KEYTYPE uiKey )
-{
- if ( m_EntryMemory.Count() == 0 )
- return;
-
- // This must occur when no queries are occurring
-#ifdef _DEBUG
- m_ContentionCheck++;
-#endif
-
- int iBucket = HashFuncs::Hash( uiKey, BUCKET_MASK );
- HashBucket_t &bucket = m_aBuckets[ iBucket ];
- bucket.m_AddLock.LockForWrite( );
-
- HashFixedData_t *pPrev = NULL;
- for ( HashFixedData_t *pElement = bucket.m_pFirstUncommitted; pElement; pPrev = pElement, pElement = pElement->m_pNext )
- {
- if ( !HashFuncs::Compare( pElement->m_uiKey, uiKey ) )
- continue;
-
- if ( pPrev )
- {
- pPrev->m_pNext = pElement->m_pNext;
- }
- else
- {
- bucket.m_pFirstUncommitted = pElement->m_pNext;
- }
-
- if ( bucket.m_pFirst == pElement )
- {
- bucket.m_pFirst = bucket.m_pFirst->m_pNext;
- }
-
- Destruct( &pElement->m_Data );
-
-#ifdef _DEBUG
- memset( pElement, 0xDD, sizeof(HashFixedData_t) );
-#endif
-
- m_EntryMemory.Free( pElement );
-
- break;
- }
-
- bucket.m_AddLock.UnlockWrite( );
-
-#ifdef _DEBUG
- m_ContentionCheck--;
-#endif
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Remove all elements from the hash
-//-----------------------------------------------------------------------------
-template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
-inline void CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::RemoveAll( void )
-{
- m_bNeedsCommit = false;
- if ( m_EntryMemory.Count() == 0 )
- return;
-
- // This must occur when no queries are occurring
-#ifdef _DEBUG
- m_ContentionCheck++;
-#endif
-
- for ( int i = 0; i < BUCKET_COUNT; i++ )
- {
- HashBucket_t &bucket = m_aBuckets[ i ];
-
- bucket.m_AddLock.LockForWrite( );
-
- for ( HashFixedData_t *pElement = bucket.m_pFirstUncommitted; pElement; pElement = pElement->m_pNext )
- {
- Destruct( &pElement->m_Data );
- }
-
- bucket.m_pFirst = NULL;
- bucket.m_pFirstUncommitted = NULL;
- bucket.m_AddLock.UnlockWrite( );
- }
-
- m_EntryMemory.Clear();
-
-#ifdef _DEBUG
- m_ContentionCheck--;
-#endif
-}
-
-//-----------------------------------------------------------------------------
-// Finds an element, but only in the committed elements
-//-----------------------------------------------------------------------------
-template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
-inline UtlTSHashHandle_t CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::Find( KEYTYPE uiKey, HashFixedData_t *pFirstElement, HashFixedData_t *pLastElement )
-{
-#ifdef _DEBUG
- if ( m_ContentionCheck != 0 )
- {
- DebuggerBreak();
- }
-#endif
-
- for ( HashFixedData_t *pElement = pFirstElement; pElement != pLastElement; pElement = pElement->m_pNext )
- {
- if ( HashFuncs::Compare( pElement->m_uiKey, uiKey ) )
- return (UtlTSHashHandle_t)pElement;
- }
- return InvalidHandle();
-}
-
-
-//-----------------------------------------------------------------------------
-// Finds an element, but only in the committed elements
-//-----------------------------------------------------------------------------
-template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
-inline UtlTSHashHandle_t CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::Find( KEYTYPE uiKey )
-{
- int iBucket = HashFuncs::Hash( uiKey, BUCKET_MASK );
- const HashBucket_t &bucket = m_aBuckets[iBucket];
- UtlTSHashHandle_t h = Find( uiKey, bucket.m_pFirst, NULL );
- if ( h != InvalidHandle() )
- return h;
-
- // Didn't find it in the fast ( committed ) list. Let's try the slow ( uncommitted ) one
- bucket.m_AddLock.LockForRead( );
- h = Find( uiKey, bucket.m_pFirstUncommitted, bucket.m_pFirst );
- bucket.m_AddLock.UnlockRead( );
-
- return h;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Return data given a hash handle.
-//-----------------------------------------------------------------------------
-template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
-inline T &CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::Element( UtlTSHashHandle_t hHash )
-{
- return ((HashFixedData_t *)hHash)->m_Data;
-}
-
-template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
-inline T const &CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::Element( UtlTSHashHandle_t hHash ) const
-{
- return ((HashFixedData_t *)hHash)->m_Data;
-}
-
-template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
-inline T &CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::operator[]( UtlTSHashHandle_t hHash )
-{
- return ((HashFixedData_t *)hHash)->m_Data;
-}
-
-template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
-inline T const &CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::operator[]( UtlTSHashHandle_t hHash ) const
-{
- return ((HashFixedData_t *)hHash)->m_Data;
-}
-
-
-template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
-inline KEYTYPE CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::GetID( UtlTSHashHandle_t hHash ) const
-{
- return ((HashFixedData_t *)hHash)->m_uiKey;
-}
-
-
-// Convert element * to hashHandle
-template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
-inline UtlTSHashHandle_t CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::ElementPtrToHandle( T* pElement ) const
-{
- Assert( pElement );
- HashFixedData_t *pFixedData = (HashFixedData_t*)( (uint8*)pElement - offsetof( HashFixedData_t, m_Data ) );
- Assert( m_EntryMemory.IsAllocationWithinPool( pFixedData ) );
- return (UtlTSHashHandle_t)pFixedData;
-}
-
-
-#endif // UTLTSHASH_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+// Thread-safe hash class
+//===========================================================================//
+
+#ifndef UTLTSHASH_H
+#define UTLTSHASH_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include <limits.h>
+#include "tier0/threadtools.h"
+#include "tier1/mempool.h"
+#include "generichash.h"
+
+
+//=============================================================================
+//
+// Threadsafe Hash
+//
+// Number of buckets must be a power of 2.
+// Key must be intp sized (32-bits on x32, 64-bits on x64)
+// Designed for a usage pattern where the data is semi-static, and there
+// is a well-defined point where we are guaranteed no queries are occurring.
+//
+// Insertions are added into a thread-safe list, and when Commit() is called,
+// the insertions are moved into a lock-free list
+//
+// Elements are never individually removed; clears must occur at a time
+// where we and guaranteed no queries are occurring
+//
+typedef intp UtlTSHashHandle_t;
+
+template < class T >
+abstract_class ITSHashConstructor
+{
+public:
+ virtual void Construct( T* pElement ) = 0;
+};
+
+template < class T >
+class CDefaultTSHashConstructor : public ITSHashConstructor< T >
+{
+public:
+ virtual void Construct( T* pElement )
+ {
+ ::Construct( pElement );
+ }
+};
+
+template < int BUCKET_COUNT, class KEYTYPE = intp >
+class CUtlTSHashGenericHash
+{
+public:
+ static int Hash( const KEYTYPE &key, int nBucketMask )
+ {
+ int nHash = HashIntConventional( (intp)key );
+ if ( BUCKET_COUNT <= USHRT_MAX )
+ {
+ nHash ^= ( nHash >> 16 );
+ }
+ if ( BUCKET_COUNT <= UCHAR_MAX )
+ {
+ nHash ^= ( nHash >> 8 );
+ }
+ return ( nHash & nBucketMask );
+ }
+
+ static bool Compare( const KEYTYPE &lhs, const KEYTYPE &rhs )
+ {
+ return lhs == rhs;
+ }
+};
+
+template < int BUCKET_COUNT, class KEYTYPE >
+class CUtlTSHashUseKeyHashMethod
+{
+public:
+ static int Hash( const KEYTYPE &key, int nBucketMask )
+ {
+ uint32 nHash = key.HashValue();
+ return ( nHash & nBucketMask );
+ }
+
+ static bool Compare( const KEYTYPE &lhs, const KEYTYPE &rhs )
+ {
+ return lhs == rhs;
+ }
+};
+
+template< class T, int BUCKET_COUNT, class KEYTYPE = intp, class HashFuncs = CUtlTSHashGenericHash< BUCKET_COUNT, KEYTYPE >, int nAlignment = 0 >
+class CUtlTSHash
+{
+public:
+ // Constructor/Deconstructor.
+ CUtlTSHash( int nAllocationCount );
+ ~CUtlTSHash();
+
+ // Invalid handle.
+ static UtlTSHashHandle_t InvalidHandle( void ) { return ( UtlTSHashHandle_t )0; }
+
+ // Retrieval. Super fast, is thread-safe
+ UtlTSHashHandle_t Find( KEYTYPE uiKey );
+
+ // Insertion ( find or add ).
+ UtlTSHashHandle_t Insert( KEYTYPE uiKey, const T &data, bool *pDidInsert = NULL );
+ UtlTSHashHandle_t Insert( KEYTYPE uiKey, ITSHashConstructor<T> *pConstructor, bool *pDidInsert = NULL );
+
+ // This insertion method assumes the element is not in the hash table, skips
+ UtlTSHashHandle_t FastInsert( KEYTYPE uiKey, const T &data );
+ UtlTSHashHandle_t FastInsert( KEYTYPE uiKey, ITSHashConstructor<T> *pConstructor );
+
+ // Commit recent insertions, making finding them faster.
+ // Only call when you're certain no threads are accessing the hash table
+ void Commit( );
+
+ // Removal. Only call when you're certain no threads are accessing the hash table
+ void FindAndRemove( KEYTYPE uiKey );
+ void Remove( UtlTSHashHandle_t hHash ) { FindAndRemove( GetID( hHash ) ); }
+ void RemoveAll( void );
+ void Purge( void );
+
+ // Returns the number of elements in the hash table
+ int Count() const;
+
+ // Returns elements in the table
+ int GetElements( int nFirstElement, int nCount, UtlTSHashHandle_t *pHandles ) const;
+
+ // Element access
+ T &Element( UtlTSHashHandle_t hHash );
+ T const &Element( UtlTSHashHandle_t hHash ) const;
+ T &operator[]( UtlTSHashHandle_t hHash );
+ T const &operator[]( UtlTSHashHandle_t hHash ) const;
+ KEYTYPE GetID( UtlTSHashHandle_t hHash ) const;
+
+ // Convert element * to hashHandle
+ UtlTSHashHandle_t ElementPtrToHandle( T* pElement ) const;
+
+private:
+ // Templatized for memory tracking purposes
+ template < typename Data_t >
+ struct HashFixedDataInternal_t
+ {
+ KEYTYPE m_uiKey;
+ HashFixedDataInternal_t< Data_t >* m_pNext;
+ Data_t m_Data;
+ };
+
+ typedef HashFixedDataInternal_t<T> HashFixedData_t;
+
+ enum
+ {
+ BUCKET_MASK = BUCKET_COUNT - 1
+ };
+
+ struct HashBucket_t
+ {
+ HashFixedData_t *m_pFirst;
+ HashFixedData_t *m_pFirstUncommitted;
+ CThreadSpinRWLock m_AddLock;
+ };
+
+ UtlTSHashHandle_t Find( KEYTYPE uiKey, HashFixedData_t *pFirstElement, HashFixedData_t *pLastElement );
+ UtlTSHashHandle_t InsertUncommitted( KEYTYPE uiKey, HashBucket_t &bucket );
+ CMemoryPoolMT m_EntryMemory;
+ HashBucket_t m_aBuckets[BUCKET_COUNT];
+ bool m_bNeedsCommit;
+
+#ifdef _DEBUG
+ CInterlockedInt m_ContentionCheck;
+#endif
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
+CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::CUtlTSHash( int nAllocationCount ) :
+ m_EntryMemory( sizeof( HashFixedData_t ), nAllocationCount, CUtlMemoryPool::GROW_SLOW, MEM_ALLOC_CLASSNAME( HashFixedData_t ), nAlignment )
+{
+#ifdef _DEBUG
+ m_ContentionCheck = 0;
+#endif
+ m_bNeedsCommit = false;
+ for ( int i = 0; i < BUCKET_COUNT; i++ )
+ {
+ HashBucket_t &bucket = m_aBuckets[ i ];
+ bucket.m_pFirst = NULL;
+ bucket.m_pFirstUncommitted = NULL;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Deconstructor
+//-----------------------------------------------------------------------------
+template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
+CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::~CUtlTSHash()
+{
+#ifdef _DEBUG
+ if ( m_ContentionCheck != 0 )
+ {
+ DebuggerBreak();
+ }
+#endif
+ Purge();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Destroy dynamically allocated hash data.
+//-----------------------------------------------------------------------------
+template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
+inline void CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::Purge( void )
+{
+ RemoveAll();
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns the number of elements in the hash table
+//-----------------------------------------------------------------------------
+template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
+inline int CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::Count() const
+{
+ return m_EntryMemory.Count();
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns elements in the table
+//-----------------------------------------------------------------------------
+template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
+int CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::GetElements( int nFirstElement, int nCount, UtlTSHashHandle_t *pHandles ) const
+{
+ int nIndex = 0;
+ for ( int i = 0; i < BUCKET_COUNT; i++ )
+ {
+ const HashBucket_t &bucket = m_aBuckets[ i ];
+ bucket.m_AddLock.LockForRead( );
+ for ( HashFixedData_t *pElement = bucket.m_pFirstUncommitted; pElement; pElement = pElement->m_pNext )
+ {
+ if ( --nFirstElement >= 0 )
+ continue;
+
+ pHandles[ nIndex++ ] = (UtlTSHashHandle_t)pElement;
+ if ( nIndex >= nCount )
+ {
+ bucket.m_AddLock.UnlockRead( );
+ return nIndex;
+ }
+ }
+ bucket.m_AddLock.UnlockRead( );
+ }
+ return nIndex;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Insert data into the hash table given its key (KEYTYPE),
+// without a check to see if the element already exists within the tree.
+//-----------------------------------------------------------------------------
+template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
+inline UtlTSHashHandle_t CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::InsertUncommitted( KEYTYPE uiKey, HashBucket_t &bucket )
+{
+ m_bNeedsCommit = true;
+ HashFixedData_t *pNewElement = static_cast< HashFixedData_t * >( m_EntryMemory.Alloc() );
+ pNewElement->m_pNext = bucket.m_pFirstUncommitted;
+ bucket.m_pFirstUncommitted = pNewElement;
+ pNewElement->m_uiKey = uiKey;
+ return (UtlTSHashHandle_t)pNewElement;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Insert data into the hash table given its key, with
+// a check to see if the element already exists within the tree.
+//-----------------------------------------------------------------------------
+template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
+inline UtlTSHashHandle_t CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::Insert( KEYTYPE uiKey, const T &data, bool *pDidInsert )
+{
+#ifdef _DEBUG
+ if ( m_ContentionCheck != 0 )
+ {
+ DebuggerBreak();
+ }
+#endif
+
+ if ( pDidInsert )
+ {
+ *pDidInsert = false;
+ }
+
+ int iBucket = HashFuncs::Hash( uiKey, BUCKET_MASK );
+ HashBucket_t &bucket = m_aBuckets[ iBucket ];
+
+ // First try lock-free
+ UtlTSHashHandle_t h = Find( uiKey );
+ if ( h != InvalidHandle() )
+ return h;
+
+ // Now, try again, but only look in uncommitted elements
+ bucket.m_AddLock.LockForWrite( );
+
+ h = Find( uiKey, bucket.m_pFirstUncommitted, bucket.m_pFirst );
+ if ( h == InvalidHandle() )
+ {
+ h = InsertUncommitted( uiKey, bucket );
+ CopyConstruct( &Element(h), data );
+ if ( pDidInsert )
+ {
+ *pDidInsert = true;
+ }
+ }
+
+ bucket.m_AddLock.UnlockWrite( );
+ return h;
+}
+
+template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
+inline UtlTSHashHandle_t CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::Insert( KEYTYPE uiKey, ITSHashConstructor<T> *pConstructor, bool *pDidInsert )
+{
+#ifdef _DEBUG
+ if ( m_ContentionCheck != 0 )
+ {
+ DebuggerBreak();
+ }
+#endif
+
+ if ( pDidInsert )
+ {
+ *pDidInsert = false;
+ }
+
+ // First try lock-free
+ UtlTSHashHandle_t h = Find( uiKey );
+ if ( h != InvalidHandle() )
+ return h;
+
+ // Now, try again, but only look in uncommitted elements
+ int iBucket = HashFuncs::Hash( uiKey, BUCKET_MASK );
+ HashBucket_t &bucket = m_aBuckets[ iBucket ];
+ bucket.m_AddLock.LockForWrite( );
+
+ h = Find( uiKey, bucket.m_pFirstUncommitted, bucket.m_pFirst );
+ if ( h == InvalidHandle() )
+ {
+ // Useful if non-trivial work needs to happen to make data; don't want to
+ // do it and then have to undo it if it turns out we don't need to add it
+ h = InsertUncommitted( uiKey, bucket );
+ pConstructor->Construct( &Element(h) );
+ if ( pDidInsert )
+ {
+ *pDidInsert = true;
+ }
+ }
+
+ bucket.m_AddLock.UnlockWrite( );
+ return h;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Insert data into the hash table given its key
+// without a check to see if the element already exists within the tree.
+//-----------------------------------------------------------------------------
+template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
+inline UtlTSHashHandle_t CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::FastInsert( KEYTYPE uiKey, const T &data )
+{
+#ifdef _DEBUG
+ if ( m_ContentionCheck != 0 )
+ {
+ DebuggerBreak();
+ }
+#endif
+ int iBucket = HashFuncs::Hash( uiKey, BUCKET_MASK );
+ HashBucket_t &bucket = m_aBuckets[ iBucket ];
+ bucket.m_AddLock.LockForWrite( );
+ UtlTSHashHandle_t h = InsertUncommitted( uiKey, bucket );
+ CopyConstruct( &Element(h), data );
+ bucket.m_AddLock.UnlockWrite( );
+ return h;
+}
+
+template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
+inline UtlTSHashHandle_t CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::FastInsert( KEYTYPE uiKey, ITSHashConstructor<T> *pConstructor )
+{
+#ifdef _DEBUG
+ if ( m_ContentionCheck != 0 )
+ {
+ DebuggerBreak();
+ }
+#endif
+ int iBucket = HashFuncs::Hash( uiKey, BUCKET_MASK );
+ HashBucket_t &bucket = m_aBuckets[ iBucket ];
+ bucket.m_AddLock.LockForWrite( );
+ UtlTSHashHandle_t h = InsertUncommitted( uiKey, bucket );
+ pConstructor->Construct( &Element(h) );
+ bucket.m_AddLock.UnlockWrite( );
+ return h;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Commits all uncommitted insertions
+//-----------------------------------------------------------------------------
+template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
+inline void CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::Commit( )
+{
+ // FIXME: Is this legal? Want this to be lock-free
+ if ( !m_bNeedsCommit )
+ return;
+
+ // This must occur when no queries are occurring
+#ifdef _DEBUG
+ m_ContentionCheck++;
+#endif
+
+ for ( int i = 0; i < BUCKET_COUNT; i++ )
+ {
+ HashBucket_t &bucket = m_aBuckets[ i ];
+ bucket.m_AddLock.LockForRead( );
+ bucket.m_pFirst = bucket.m_pFirstUncommitted;
+ bucket.m_AddLock.UnlockRead( );
+ }
+
+ m_bNeedsCommit = false;
+
+#ifdef _DEBUG
+ m_ContentionCheck--;
+#endif
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Remove a single element from the hash
+//-----------------------------------------------------------------------------
+template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
+inline void CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::FindAndRemove( KEYTYPE uiKey )
+{
+ if ( m_EntryMemory.Count() == 0 )
+ return;
+
+ // This must occur when no queries are occurring
+#ifdef _DEBUG
+ m_ContentionCheck++;
+#endif
+
+ int iBucket = HashFuncs::Hash( uiKey, BUCKET_MASK );
+ HashBucket_t &bucket = m_aBuckets[ iBucket ];
+ bucket.m_AddLock.LockForWrite( );
+
+ HashFixedData_t *pPrev = NULL;
+ for ( HashFixedData_t *pElement = bucket.m_pFirstUncommitted; pElement; pPrev = pElement, pElement = pElement->m_pNext )
+ {
+ if ( !HashFuncs::Compare( pElement->m_uiKey, uiKey ) )
+ continue;
+
+ if ( pPrev )
+ {
+ pPrev->m_pNext = pElement->m_pNext;
+ }
+ else
+ {
+ bucket.m_pFirstUncommitted = pElement->m_pNext;
+ }
+
+ if ( bucket.m_pFirst == pElement )
+ {
+ bucket.m_pFirst = bucket.m_pFirst->m_pNext;
+ }
+
+ Destruct( &pElement->m_Data );
+
+#ifdef _DEBUG
+ memset( pElement, 0xDD, sizeof(HashFixedData_t) );
+#endif
+
+ m_EntryMemory.Free( pElement );
+
+ break;
+ }
+
+ bucket.m_AddLock.UnlockWrite( );
+
+#ifdef _DEBUG
+ m_ContentionCheck--;
+#endif
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Remove all elements from the hash
+//-----------------------------------------------------------------------------
+template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
+inline void CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::RemoveAll( void )
+{
+ m_bNeedsCommit = false;
+ if ( m_EntryMemory.Count() == 0 )
+ return;
+
+ // This must occur when no queries are occurring
+#ifdef _DEBUG
+ m_ContentionCheck++;
+#endif
+
+ for ( int i = 0; i < BUCKET_COUNT; i++ )
+ {
+ HashBucket_t &bucket = m_aBuckets[ i ];
+
+ bucket.m_AddLock.LockForWrite( );
+
+ for ( HashFixedData_t *pElement = bucket.m_pFirstUncommitted; pElement; pElement = pElement->m_pNext )
+ {
+ Destruct( &pElement->m_Data );
+ }
+
+ bucket.m_pFirst = NULL;
+ bucket.m_pFirstUncommitted = NULL;
+ bucket.m_AddLock.UnlockWrite( );
+ }
+
+ m_EntryMemory.Clear();
+
+#ifdef _DEBUG
+ m_ContentionCheck--;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Finds an element, but only in the committed elements
+//-----------------------------------------------------------------------------
+template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
+inline UtlTSHashHandle_t CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::Find( KEYTYPE uiKey, HashFixedData_t *pFirstElement, HashFixedData_t *pLastElement )
+{
+#ifdef _DEBUG
+ if ( m_ContentionCheck != 0 )
+ {
+ DebuggerBreak();
+ }
+#endif
+
+ for ( HashFixedData_t *pElement = pFirstElement; pElement != pLastElement; pElement = pElement->m_pNext )
+ {
+ if ( HashFuncs::Compare( pElement->m_uiKey, uiKey ) )
+ return (UtlTSHashHandle_t)pElement;
+ }
+ return InvalidHandle();
+}
+
+
+//-----------------------------------------------------------------------------
+// Finds an element, but only in the committed elements
+//-----------------------------------------------------------------------------
+template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
+inline UtlTSHashHandle_t CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::Find( KEYTYPE uiKey )
+{
+ int iBucket = HashFuncs::Hash( uiKey, BUCKET_MASK );
+ const HashBucket_t &bucket = m_aBuckets[iBucket];
+ UtlTSHashHandle_t h = Find( uiKey, bucket.m_pFirst, NULL );
+ if ( h != InvalidHandle() )
+ return h;
+
+ // Didn't find it in the fast ( committed ) list. Let's try the slow ( uncommitted ) one
+ bucket.m_AddLock.LockForRead( );
+ h = Find( uiKey, bucket.m_pFirstUncommitted, bucket.m_pFirst );
+ bucket.m_AddLock.UnlockRead( );
+
+ return h;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Return data given a hash handle.
+//-----------------------------------------------------------------------------
+template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
+inline T &CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::Element( UtlTSHashHandle_t hHash )
+{
+ return ((HashFixedData_t *)hHash)->m_Data;
+}
+
+template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
+inline T const &CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::Element( UtlTSHashHandle_t hHash ) const
+{
+ return ((HashFixedData_t *)hHash)->m_Data;
+}
+
+template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
+inline T &CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::operator[]( UtlTSHashHandle_t hHash )
+{
+ return ((HashFixedData_t *)hHash)->m_Data;
+}
+
+template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
+inline T const &CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::operator[]( UtlTSHashHandle_t hHash ) const
+{
+ return ((HashFixedData_t *)hHash)->m_Data;
+}
+
+
+template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
+inline KEYTYPE CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::GetID( UtlTSHashHandle_t hHash ) const
+{
+ return ((HashFixedData_t *)hHash)->m_uiKey;
+}
+
+
+// Convert element * to hashHandle
+template<class T, int BUCKET_COUNT, class KEYTYPE, class HashFuncs, int nAlignment>
+inline UtlTSHashHandle_t CUtlTSHash<T,BUCKET_COUNT,KEYTYPE,HashFuncs,nAlignment>::ElementPtrToHandle( T* pElement ) const
+{
+ Assert( pElement );
+ HashFixedData_t *pFixedData = (HashFixedData_t*)( (uint8*)pElement - offsetof( HashFixedData_t, m_Data ) );
+ Assert( m_EntryMemory.IsAllocationWithinPool( pFixedData ) );
+ return (UtlTSHashHandle_t)pFixedData;
+}
+
+
+#endif // UTLTSHASH_H
diff --git a/mp/src/public/tier1/utlvector.h b/mp/src/public/tier1/utlvector.h
index 3b8dd0ee..1f2fe6e1 100644
--- a/mp/src/public/tier1/utlvector.h
+++ b/mp/src/public/tier1/utlvector.h
@@ -1,1210 +1,1210 @@
-//========= Copyright 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;
- typedef T* iterator;
- typedef const T* const_iterator;
-
- // constructor, destructor
- explicit CUtlVector( int growSize = 0, int initSize = 0 );
- explicit 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;
-
- // STL compatible member functions. These allow easier use of std::sort
- // and they are forward compatible with the C++ 11 range-based for loops.
- iterator begin() { return Base(); }
- const_iterator begin() const { return Base(); }
- iterator end() { return Base() + Count(); }
- const_iterator end() const { return Base() + Count(); }
-
- // 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
- // SIZE IS DEPRECATED!
- int Count() const;
- int Size() const; // don't use me!
-
- // 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, const T *pToCopy=NULL );
- int InsertMultipleBefore( int elem, int num, const T *pToCopy=NULL ); // If pToCopy is set, then it's an array of length 'num' and
- 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;
-
- 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 *) );
-
-#ifdef DBGFLAG_VALIDATE
- void Validate( CValidator &validator, char *pchName ); // Validate our internal structures
-#endif // DBGFLAG_VALIDATE
-
-protected:
- // 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:
- // Can't copy this unless we explicitly do it!
- // Use CCopyableUtlVector<T> to get this functionality
- CUtlVector( CUtlVector const& vec );
-};
-
-
-// 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:
- explicit CUtlBlockVector( int growSize = 0, int initSize = 0 )
- : CUtlVector< T, CUtlBlockMemory< T, int > >( growSize, initSize ) {}
-
-private:
- // Private and unimplemented because iterator semantics are not currently supported
- // on CUtlBlockVector, due to its non-contiguous allocations.
- // typename is require to disambiguate iterator as a type versus other possibilities.
- typedef CUtlVector< T, CUtlBlockMemory< T, int > > Base;
- typename Base::iterator begin();
- typename Base::const_iterator begin() const;
- typename Base::iterator end();
- typename Base::const_iterator end() const;
-};
-
-//-----------------------------------------------------------------------------
-// The CUtlVectorFixed class:
-// A array class with a fixed allocation scheme
-//-----------------------------------------------------------------------------
-
-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
- explicit CUtlVectorMT( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
- explicit 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
- explicit CUtlVectorFixed( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
- explicit 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
- explicit 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
- explicit CUtlVectorConservative( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
- explicit 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[0];
- };
-
- 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))
- {
- Q_memmove( &Element(elem), &Element(elem+num), numToMove * sizeof(T) );
-
-#ifdef _DEBUG
- Q_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< typename T, typename A = CUtlMemory<T> >
-class CCopyableUtlVector : public CUtlVector< T, A >
-{
- typedef CUtlVector< T, A > BaseClass;
-public:
- explicit CCopyableUtlVector( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
- explicit CCopyableUtlVector( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
- virtual ~CCopyableUtlVector() {}
- CCopyableUtlVector( CCopyableUtlVector const& vec ) { this->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 )
-{
- // Do an inline unsigned check for maximum debug-build performance.
- Assert( (unsigned)i < (unsigned)m_Size );
- return m_Memory[ i ];
-}
-
-template< typename T, class A >
-inline const T& CUtlVector<T, A>::operator[]( int i ) const
-{
- // Do an inline unsigned check for maximum debug-build performance.
- Assert( (unsigned)i < (unsigned)m_Size );
- return m_Memory[ i ];
-}
-
-template< typename T, class A >
-inline T& CUtlVector<T, A>::Element( int i )
-{
- // Do an inline unsigned check for maximum debug-build performance.
- Assert( (unsigned)i < (unsigned)m_Size );
- return m_Memory[ i ];
-}
-
-template< typename T, class A >
-inline const T& CUtlVector<T, A>::Element( int i ) const
-{
- // Do an inline unsigned check for maximum debug-build performance.
- Assert( (unsigned)i < (unsigned)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>::Size() const
-{
- return m_Size;
-}
-
-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 ) );
- }
- }
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// 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))
- Q_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))
- {
- Q_memmove( &Element(elem), &Element(elem+num), numToMove * sizeof(T) );
-
-#ifdef _DEBUG
- Q_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, 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.
- AddMultipleToTail( src.Count() );
-
- // Copy the elements.
- for ( int i=0; i < src.Count(); i++ )
- {
- (*this)[base + i] = src[i];
- }
-
- return base;
-}
-
-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
- for (int i = 0; i < num; ++i )
- Construct( &Element( elem+i ) );
-
- // Copy stuff in?
- if ( pToInsert )
- {
- for ( int i=0; i < num; i++ )
- {
- 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 >
-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( reinterpret_cast<void*>( &Element(elem) ), reinterpret_cast<void*>( &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 );
- }
-
- inline void PurgeAndDeleteElements()
- {
- for( int i=0; i < m_Size; i++ )
- {
- delete [] Element(i);
- }
- Purge();
- }
-
- ~CUtlStringList( void )
- {
- this->PurgeAndDeleteElements();
- }
-};
-
-
-
-// <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
+//========= Copyright 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;
+ typedef T* iterator;
+ typedef const T* const_iterator;
+
+ // constructor, destructor
+ explicit CUtlVector( int growSize = 0, int initSize = 0 );
+ explicit 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;
+
+ // STL compatible member functions. These allow easier use of std::sort
+ // and they are forward compatible with the C++ 11 range-based for loops.
+ iterator begin() { return Base(); }
+ const_iterator begin() const { return Base(); }
+ iterator end() { return Base() + Count(); }
+ const_iterator end() const { return Base() + Count(); }
+
+ // 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
+ // SIZE IS DEPRECATED!
+ int Count() const;
+ int Size() const; // don't use me!
+
+ // 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, const T *pToCopy=NULL );
+ int InsertMultipleBefore( int elem, int num, const T *pToCopy=NULL ); // If pToCopy is set, then it's an array of length 'num' and
+ 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;
+
+ 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 *) );
+
+#ifdef DBGFLAG_VALIDATE
+ void Validate( CValidator &validator, char *pchName ); // Validate our internal structures
+#endif // DBGFLAG_VALIDATE
+
+protected:
+ // 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:
+ // Can't copy this unless we explicitly do it!
+ // Use CCopyableUtlVector<T> to get this functionality
+ CUtlVector( CUtlVector const& vec );
+};
+
+
+// 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:
+ explicit CUtlBlockVector( int growSize = 0, int initSize = 0 )
+ : CUtlVector< T, CUtlBlockMemory< T, int > >( growSize, initSize ) {}
+
+private:
+ // Private and unimplemented because iterator semantics are not currently supported
+ // on CUtlBlockVector, due to its non-contiguous allocations.
+ // typename is require to disambiguate iterator as a type versus other possibilities.
+ typedef CUtlVector< T, CUtlBlockMemory< T, int > > Base;
+ typename Base::iterator begin();
+ typename Base::const_iterator begin() const;
+ typename Base::iterator end();
+ typename Base::const_iterator end() const;
+};
+
+//-----------------------------------------------------------------------------
+// The CUtlVectorFixed class:
+// A array class with a fixed allocation scheme
+//-----------------------------------------------------------------------------
+
+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
+ explicit CUtlVectorMT( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
+ explicit 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
+ explicit CUtlVectorFixed( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
+ explicit 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
+ explicit 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
+ explicit CUtlVectorConservative( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
+ explicit 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[0];
+ };
+
+ 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))
+ {
+ Q_memmove( &Element(elem), &Element(elem+num), numToMove * sizeof(T) );
+
+#ifdef _DEBUG
+ Q_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< typename T, typename A = CUtlMemory<T> >
+class CCopyableUtlVector : public CUtlVector< T, A >
+{
+ typedef CUtlVector< T, A > BaseClass;
+public:
+ explicit CCopyableUtlVector( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
+ explicit CCopyableUtlVector( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
+ virtual ~CCopyableUtlVector() {}
+ CCopyableUtlVector( CCopyableUtlVector const& vec ) { this->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 )
+{
+ // Do an inline unsigned check for maximum debug-build performance.
+ Assert( (unsigned)i < (unsigned)m_Size );
+ return m_Memory[ i ];
+}
+
+template< typename T, class A >
+inline const T& CUtlVector<T, A>::operator[]( int i ) const
+{
+ // Do an inline unsigned check for maximum debug-build performance.
+ Assert( (unsigned)i < (unsigned)m_Size );
+ return m_Memory[ i ];
+}
+
+template< typename T, class A >
+inline T& CUtlVector<T, A>::Element( int i )
+{
+ // Do an inline unsigned check for maximum debug-build performance.
+ Assert( (unsigned)i < (unsigned)m_Size );
+ return m_Memory[ i ];
+}
+
+template< typename T, class A >
+inline const T& CUtlVector<T, A>::Element( int i ) const
+{
+ // Do an inline unsigned check for maximum debug-build performance.
+ Assert( (unsigned)i < (unsigned)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>::Size() const
+{
+ return m_Size;
+}
+
+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 ) );
+ }
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// 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))
+ Q_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))
+ {
+ Q_memmove( &Element(elem), &Element(elem+num), numToMove * sizeof(T) );
+
+#ifdef _DEBUG
+ Q_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, 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.
+ AddMultipleToTail( src.Count() );
+
+ // Copy the elements.
+ for ( int i=0; i < src.Count(); i++ )
+ {
+ (*this)[base + i] = src[i];
+ }
+
+ return base;
+}
+
+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
+ for (int i = 0; i < num; ++i )
+ Construct( &Element( elem+i ) );
+
+ // Copy stuff in?
+ if ( pToInsert )
+ {
+ for ( int i=0; i < num; i++ )
+ {
+ 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 >
+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( reinterpret_cast<void*>( &Element(elem) ), reinterpret_cast<void*>( &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 );
+ }
+
+ inline void PurgeAndDeleteElements()
+ {
+ for( int i=0; i < m_Size; i++ )
+ {
+ delete [] Element(i);
+ }
+ Purge();
+ }
+
+ ~CUtlStringList( void )
+ {
+ this->PurgeAndDeleteElements();
+ }
+};
+
+
+
+// <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