1
0
mirror of https://github.com/alliedmodders/hl2sdk.git synced 2025-09-19 20:16:10 +08:00

Added most recent version of unmodified HL2 SDK for Orange Box engine

This commit is contained in:
Scott Ehlert
2008-09-15 01:07:45 -05:00
commit 055f5cd168
2907 changed files with 1271781 additions and 0 deletions

View File

@ -0,0 +1,160 @@
//===== Copyright <20> 1996-2006, 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 );
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;
// 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

357
public/tier1/KeyValues.h Normal file
View File

@ -0,0 +1,357 @@
//========= Copyright <20> 1996-2005, 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"
class IBaseFileSystem;
class CUtlBuffer;
class Color;
typedef void * FileHandle_t;
//-----------------------------------------------------------------------------
// 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 '"' charater 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 charater in key names.
//-----------------------------------------------------------------------------
class KeyValues
{
public:
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 ) {}
inline ~AutoDelete( void ) { if( m_pKeyValues ) m_pKeyValues->deleteThis(); }
inline void Assign( KeyValues *pKeyValues ) { m_pKeyValues = 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;
// File access. Set UsesEscapeSequences true, if resource file/buffer uses Escape Sequences (eg \n, \t)
void UsesEscapeSequences(bool state); // default false
bool LoadFromFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL );
bool SaveToFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL);
// Read from a buffer... Note that the buffer must be null terminated
bool LoadFromBuffer( char const *resourceName, const char *pBuffer, IBaseFileSystem* pFileSystem = NULL, const char *pPathID = NULL );
// 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(); // returns the first subkey in the list
KeyValues *GetNextKey(); // returns the next subkey
void SetNextKey( KeyValues * pDat);
//
// These functions can be used to treat it like a true key/values tree instead of
// confusing values with keys.
//
// So if you wanted to iterate all subkeys, then all values, it would look like this:
// for ( KeyValues *pKey = pRoot->GetFirstTrueSubKey(); pKey; pKey = pKey->GetNextTrueSubKey() )
// {
// Msg( "Key name: %s\n", pKey->GetName() );
// }
// for ( KeyValues *pValue = pRoot->GetFirstValue(); pKey; pKey = pKey->GetNextValue() )
// {
// Msg( "Int value: %d\n", pValue->GetInt() ); // Assuming pValue->GetDataType() == TYPE_INT...
// }
KeyValues* GetFirstTrueSubKey();
KeyValues* GetNextTrueSubKey();
KeyValues* GetFirstValue(); // When you get a value back, you can use GetX and pass in NULL to get the value.
KeyValues* GetNextValue();
// Data access
int GetInt( const char *keyName = NULL, int defaultValue = 0 );
uint64 GetUint64( const char *keyName = NULL, uint64 defaultValue = 0 );
float GetFloat( const char *keyName = NULL, float defaultValue = 0.0f );
const char *GetString( const char *keyName = NULL, const char *defaultValue = "" );
const wchar_t *GetWString( const char *keyName = NULL, const wchar_t *defaultValue = L"" );
void *GetPtr( const char *keyName = NULL, void *defaultValue = (void*)0 );
Color GetColor( const char *keyName = NULL /* 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);
// Memory allocation (optimized)
void *operator new( unsigned int iAllocSize );
void *operator new( unsigned int iAllocSize, int nBlockUse, const char *pFileName, int nLine );
void operator delete( void *pMem );
void operator delete( void *pMem, int nBlockUse, const char *pFileName, int nLine );
KeyValues& operator=( KeyValues& src );
// Adds a chain... if we don't find stuff in this keyvalue, we'll look
// in the one we're chained to.
void ChainKeyValue( KeyValues* pChain );
void RecursiveSaveToFile( CUtlBuffer& buf, int indentLevel );
bool WriteAsBinary( CUtlBuffer &buffer );
bool ReadAsBinary( CUtlBuffer &buffer );
// Allocate & create a new copy of the keys
KeyValues *MakeCopy( void ) const;
// Make a new copy of all subkeys, add them all to the passed-in keyvalues
void CopySubkeys( KeyValues *pParent ) const;
// Clear out all subkeys, and the current value
void Clear( void );
// Data type
enum types_t
{
TYPE_NONE = 0,
TYPE_STRING,
TYPE_INT,
TYPE_FLOAT,
TYPE_PTR,
TYPE_WSTRING,
TYPE_COLOR,
TYPE_UINT64,
TYPE_NUMTYPES,
};
types_t GetDataType(const char *keyName = NULL);
// Virtual deletion function - ensures that KeyValues object is deleted from correct heap
void deleteThis();
void SetStringValue( char const *strValue );
// unpack a key values list into a structure
void UnpackIntoStructure( struct KeyValuesUnpackStructure const *pUnpackTable, void *pDest );
// Process conditional keys for widescreen support.
bool ProcessResolutionKeys( const char *pResString );
private:
KeyValues( KeyValues& ); // prevent copy constructor being used
// prevent delete being called except through deleteThis()
~KeyValues();
KeyValues* CreateKey( const char *keyName );
void RecursiveCopyKeyValues( KeyValues& src );
void RemoveEverything();
// void RecursiveSaveToFile( IBaseFileSystem *filesystem, CUtlBuffer &buffer, int indentLevel );
// void WriteConvertedString( CUtlBuffer &buffer, const char *pszString );
// NOTE: If both filesystem and pBuf are non-null, it'll save to both of them.
// If filesystem is null, it'll ignore f.
void RecursiveSaveToFile( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, int indentLevel );
void WriteConvertedString( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, const char *pszString );
void RecursiveLoadFromBuffer( char const *resourceName, CUtlBuffer &buf );
// 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 );
void RecursiveMergeKeyValues( KeyValues *baseKV );
// NOTE: If both filesystem and pBuf are non-null, it'll save to both of them.
// If filesystem is null, it'll ignore f.
void InternalWrite( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, const void *pData, int len );
void Init();
const char * ReadToken( CUtlBuffer &buf, bool &wasQuoted, bool &wasConditional );
void WriteIndents( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, int indentLevel );
void FreeAllocatedValue();
void AllocateValueBlock(int size);
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 unused[2];
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
};
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 );
#endif // KEYVALUES_H

View File

@ -0,0 +1,311 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// $Header: $
// $NoKeywords: $
//
// A growable array class that keeps all elements in order using binary search
//===========================================================================//
#ifndef UTLSORTVECTOR_H
#define UTLSORTVECTOR_H
#ifdef _WIN32
#pragma once
#endif
#include "utlvector.h"
//-----------------------------------------------------------------------------
// class CUtlSortVector:
// description:
// This in an sorted order-preserving vector. Items may be inserted or removed
// at any point in the vector. When an item is inserted, all elements are
// moved down by one element using memmove. When an item is removed, all
// elements are shifted back down. Items are searched for in the vector
// using a binary search technique. Clients must pass in a Less() function
// into the constructor of the vector to determine the sort order.
//-----------------------------------------------------------------------------
#ifndef _WIN32
// gcc has no qsort_s, so i need to use a static var to hold the sort context. this makes cutlsortvector _not_ thread sfae under linux
extern void *g_pUtlSortVectorQSortContext;
#endif
template <class T, class LessFunc>
class CUtlSortVector : public CUtlVector<T>
{
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>
CUtlSortVector<T, LessFunc>::CUtlSortVector( int nGrowSize, int initSize ) :
m_pLessContext(NULL), CUtlVector<T>( nGrowSize, initSize ), m_bNeedsSort( false )
{
}
template <class T, class LessFunc>
CUtlSortVector<T, LessFunc>::CUtlSortVector( T* pMemory, int numElements ) :
m_pLessContext(NULL), CUtlVector<T>( pMemory, numElements ), m_bNeedsSort( false )
{
}
//-----------------------------------------------------------------------------
// Allows methods to set a context to be used with the less function..
//-----------------------------------------------------------------------------
template <class T, class LessFunc>
void CUtlSortVector<T, LessFunc>::SetLessContext( void *pCtx )
{
m_pLessContext = pCtx;
}
//-----------------------------------------------------------------------------
// grows the vector
//-----------------------------------------------------------------------------
template <class T, class LessFunc>
int CUtlSortVector<T, LessFunc>::Insert( const T& src )
{
AssertFatal( !m_bNeedsSort );
int pos = FindLessOrEqual( src ) + 1;
GrowVector();
ShiftElementsRight(pos);
CopyConstruct<T>( &Element(pos), src );
return pos;
}
template <class T, class LessFunc>
int CUtlSortVector<T, LessFunc>::InsertNoSort( const T& src )
{
m_bNeedsSort = true;
int lastElement = CUtlVector<T>::m_Size;
// Just stick the new element at the end of the vector, but don't do a sort
GrowVector();
ShiftElementsRight(lastElement);
CopyConstruct( &Element(lastElement), src );
return lastElement;
}
template <class T, class LessFunc>
void CUtlSortVector<T, LessFunc>::QuickSort( LessFunc& less, int nLower, int nUpper )
{
#ifdef _WIN32
typedef int (__cdecl *QSortCompareFunc_t)(void *context, const void *, const void *);
if ( 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 ( Count() > 1 )
{
QSortContext_t ctx;
ctx.m_pLessContext = m_pLessContext;
ctx.m_pLessFunc = &less;
g_pUtlSortVectorQSortContext = &ctx;
qsort( Base(), Count(), sizeof(T), (QSortCompareFunc_t)&CUtlSortVector<T, LessFunc>::CompareHelper );
}
#endif
}
template <class T, class LessFunc>
void CUtlSortVector<T, LessFunc>::RedoSort( bool bForceSort /*= false */ )
{
if ( !m_bNeedsSort && !bForceSort )
return;
m_bNeedsSort = false;
LessFunc less;
QuickSort( less, 0, Count() - 1 );
}
//-----------------------------------------------------------------------------
// finds a particular element
//-----------------------------------------------------------------------------
template <class T, class LessFunc>
int CUtlSortVector<T, LessFunc>::Find( const T& src ) const
{
AssertFatal( !m_bNeedsSort );
LessFunc less;
int start = 0, end = Count() - 1;
while (start <= end)
{
int mid = (start + end) >> 1;
if ( less.Less( Element(mid), src, m_pLessContext ) )
{
start = mid + 1;
}
else if ( less.Less( src, Element(mid), m_pLessContext ) )
{
end = mid - 1;
}
else
{
return mid;
}
}
return -1;
}
//-----------------------------------------------------------------------------
// finds a particular element
//-----------------------------------------------------------------------------
template <class T, class LessFunc>
int CUtlSortVector<T, LessFunc>::FindLessOrEqual( const T& src ) const
{
AssertFatal( !m_bNeedsSort );
LessFunc less;
int start = 0, end = Count() - 1;
while (start <= end)
{
int mid = (start + end) >> 1;
if ( less.Less( Element(mid), src, m_pLessContext ) )
{
start = mid + 1;
}
else if ( less.Less( src, Element(mid), m_pLessContext ) )
{
end = mid - 1;
}
else
{
return mid;
}
}
return end;
}
template <class T, class LessFunc>
int CUtlSortVector<T, LessFunc>::FindLess( const T& src ) const
{
AssertFatal( !m_bNeedsSort );
LessFunc less;
int start = 0, end = Count() - 1;
while (start <= end)
{
int mid = (start + end) >> 1;
if ( less.Less( Element(mid), src, m_pLessContext ) )
{
start = mid + 1;
}
else
{
end = mid - 1;
}
}
return end;
}
//-----------------------------------------------------------------------------
// Removes a particular element
//-----------------------------------------------------------------------------
template <class T, class LessFunc>
void CUtlSortVector<T, LessFunc>::Remove( const T& search )
{
AssertFatal( !m_bNeedsSort );
int pos = Find(search);
if (pos != -1)
{
CUtlVector<T>::Remove(pos);
}
}
template <class T, class LessFunc>
void CUtlSortVector<T, LessFunc>::Remove( int i )
{
CUtlVector<T>::Remove( i );
}
#endif // UTLSORTVECTOR_H

View File

@ -0,0 +1,99 @@
//===== Copyright <20> 1996-2005, 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

1500
public/tier1/bitbuf.h Normal file

File diff suppressed because it is too large Load Diff

249
public/tier1/byteswap.h Normal file
View File

@ -0,0 +1,249 @@
//========= Copyright <20> 1996-2006, Valve LLC, All rights reserved. ============
//
// Purpose: Low level byte swapping routines.
//
// $NoKeywords: $
//=============================================================================
#ifndef BYTESWAP_H
#define BYTESWAP_H
#if defined(_WIN32)
#pragma once
#endif
#include "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 */

203
public/tier1/callqueue.h Normal file
View File

@ -0,0 +1,203 @@
//========== Copyright <20> 2006, 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

View File

@ -0,0 +1,43 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: Shared code for parsing / searching for characters in a string
// using lookup tables
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//===========================================================================//
#ifndef CHARACTERSET_H
#define CHARACTERSET_H
#ifdef _WIN32
#pragma once
#endif
struct characterset_t
{
char set[256];
};
// This is essentially a strpbrk() using a precalculated lookup table
//-----------------------------------------------------------------------------
// Purpose: builds a simple lookup table of a group of important characters
// Input : *pSetBuffer - pointer to the buffer for the group
// *pSetString - list of characters to flag
//-----------------------------------------------------------------------------
extern void CharacterSetBuild( characterset_t *pSetBuffer, const char *pSetString );
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pSetBuffer - pre-build group buffer
// character - character to lookup
// Output : int - 1 if the character was in the set
//-----------------------------------------------------------------------------
#define IN_CHARACTERSET( SetBuffer, character ) ((SetBuffer).set[(character)])
#endif // CHARACTERSET_H

View File

@ -0,0 +1,31 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Generic CRC functions
//
// $NoKeywords: $
//=============================================================================//
#ifndef CHECKSUM_CRC_H
#define CHECKSUM_CRC_H
#ifdef _WIN32
#pragma once
#endif
typedef unsigned long 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

View File

@ -0,0 +1,33 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Generic MD5 hashing algo
//
//=============================================================================//
#ifndef CHECKSUM_MD5_H
#define CHECKSUM_MD5_H
#ifdef _WIN32
#pragma once
#endif
// 16 bytes == 128 bit digest
#define MD5_DIGEST_LENGTH 16
// MD5 Hash
typedef struct
{
unsigned int buf[4];
unsigned int bits[2];
unsigned char in[64];
} MD5Context_t;
void MD5Init( MD5Context_t *context );
void MD5Update( MD5Context_t *context, unsigned char const *buf, unsigned int len );
void MD5Final( unsigned char digest[ MD5_DIGEST_LENGTH ], MD5Context_t *context );
char *MD5_Print(unsigned char *digest, int hashlen );
unsigned int MD5_PseudoRandom(unsigned int nSeed);
#endif // CHECKSUM_MD5_H

671
public/tier1/convar.h Normal file
View File

@ -0,0 +1,671 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $NoKeywords: $
//===========================================================================//
#ifndef CONVAR_H
#define CONVAR_H
#if _WIN32
#pragma once
#endif
#include "tier0/dbg.h"
#include "tier1/iconvar.h"
#include "tier1/utlvector.h"
#include "tier1/utlstring.h"
#include "icvar.h"
#ifdef _WIN32
#define FORCEINLINE_CVAR FORCEINLINE
#elif _LINUX
#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;
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();
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

View File

@ -0,0 +1,53 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Helper class for cvars that have restrictions on their value.
//
//=============================================================================//
#ifndef CONVAR_SERVERBOUNDED_H
#define CONVAR_SERVERBOUNDED_H
#ifdef _WIN32
#pragma once
#endif
// This class is used to virtualize a ConVar's value, so the client can restrict its
// value while connected to a server. When using this across modules, it's important
// to dynamic_cast it to a ConVar_ServerBounded or you won't get the restricted value.
//
// NOTE: FCVAR_USERINFO vars are not virtualized before they are sent to the server
// (we have no way to detect if the virtualized value would change), so
// if you want to use a bounded cvar's value on the server, you must rebound it
// the same way the client does.
class ConVar_ServerBounded : public ConVar
{
public:
ConVar_ServerBounded( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString )
: ConVar( pName, pDefaultValue, flags, pHelpString )
{
}
ConVar_ServerBounded( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, FnChangeCallback_t callback )
: ConVar( pName, pDefaultValue, flags, pHelpString, callback )
{
}
ConVar_ServerBounded( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax )
: ConVar( pName, pDefaultValue, flags, pHelpString, bMin, fMin, bMax, fMax ) {}
// You must implement GetFloat.
virtual float GetFloat() const = 0;
// You can optionally implement these.
virtual int GetInt() const { return (int)GetFloat(); }
virtual bool GetBool() const { return ( GetInt() != 0 ); }
// Use this to get the underlying cvar's value.
float GetBaseFloatValue() const
{
return ConVar::GetFloat();
}
};
#endif // CONVAR_SERVERBOUNDED_H

277
public/tier1/datamanager.h Normal file
View File

@ -0,0 +1,277 @@
//========= Copyright <20> 1996-2005, 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

99
public/tier1/delegates.h Normal file
View File

@ -0,0 +1,99 @@
//========== Copyright <20> 2005, 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

29
public/tier1/diff.h Normal file
View File

@ -0,0 +1,29 @@
//========= Copyright <20> 1996-2005, 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

82
public/tier1/fmtstr.h Normal file
View File

@ -0,0 +1,82 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: A simple class for performing safe and in-expression sprintf-style
// string formatting
//
// $NoKeywords: $
//=============================================================================//
#ifndef FMTSTR_H
#define FMTSTR_H
#include <stdarg.h>
#include <stdio.h>
#include "tier0/platform.h"
#include "tier1/strtools.h"
#if defined( _WIN32 )
#pragma once
#endif
//=============================================================================
// using macro to be compatable with GCC
#define FmtStrVSNPrintf( szBuf, nBufSize, ppszFormat ) \
do \
{ \
int result; \
va_list arg_ptr; \
\
va_start(arg_ptr, (*(ppszFormat))); \
result = Q_vsnprintf((szBuf), (nBufSize)-1, (*(ppszFormat)), arg_ptr); \
va_end(arg_ptr); \
\
(szBuf)[(nBufSize)-1] = 0; \
} \
while (0)
//-----------------------------------------------------------------------------
//
// Purpose: String formatter with specified size
//
template <int SIZE_BUF>
class CFmtStrN
{
public:
CFmtStrN() { m_szBuf[0] = 0; }
// Standard C formatting
CFmtStrN(const char *pszFormat, ...) { FmtStrVSNPrintf(m_szBuf, SIZE_BUF, &pszFormat); }
// Use this for pass-through formatting
CFmtStrN(const char ** ppszFormat, ...) { FmtStrVSNPrintf(m_szBuf, SIZE_BUF, ppszFormat); }
// Explicit reformat
const char *sprintf(const char *pszFormat, ...) { FmtStrVSNPrintf(m_szBuf, SIZE_BUF, &pszFormat); return m_szBuf; }
// Use this for pass-through formatting
void VSprintf(const char **ppszFormat, ...) { FmtStrVSNPrintf(m_szBuf, SIZE_BUF, ppszFormat); }
// Use for access
operator const char *() const { return m_szBuf; }
char *Access() { return m_szBuf; }
void Clear() { m_szBuf[0] = 0; }
private:
char m_szBuf[SIZE_BUF];
};
//-----------------------------------------------------------------------------
//
// Purpose: Default-sized string formatter
//
#define FMTSTR_STD_LEN 256
typedef CFmtStrN<FMTSTR_STD_LEN> CFmtStr;
//=============================================================================
#endif // FMTSTR_H

617
public/tier1/functors.h Normal file
View File

@ -0,0 +1,617 @@
//========== Copyright © 2006, Valve Corporation, All rights reserved. ========
//
// Purpose: Implements a generic infrastucture for functors combining
// a number of techniques to provide transparent parameter type
// deduction and packaging. Supports both member and non-member functions.
//
// See also: http://en.wikipedia.org/wiki/Function_object
//
// Note that getting into the guts of this file is not for the
// feint of heart. The core concept here is that the compiler can
// figure out all the parameter types.
//
// E.g.:
//
// struct CMyClass
// {
// void foo( int i) {}
// };
//
// int bar(int i) { return i; }
//
// CMyClass myInstance;
//
// CFunctor *pFunctor = CreateFunctor( &myInstance, CMyClass::foo, 8675 );
// CFunctor *pFunctor2 = CreateFunctor( &bar, 309 );
//
// void CallEm()
// {
// (*pFunctor)();
// (*pFunctor2)();
// }
//
//=============================================================================
#ifndef FUNCTORS_H
#define FUNCTORS_H
#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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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
}
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

View File

@ -0,0 +1,92 @@
//======= Copyright <20> 2005, , Valve Corporation, All rights reserved. =========
//
// Purpose: Variant Pearson Hash general purpose hashing algorithm described
// by Cargill in C++ Report 1994. Generates a 16-bit result.
//
//=============================================================================
#ifndef GENERICHASH_H
#define GENERICHASH_H
#if defined(_WIN32)
#pragma once
#endif
//-----------------------------------------------------------------------------
unsigned FASTCALL HashString( const char *pszKey );
unsigned FASTCALL HashStringCaseless( const char *pszKey );
unsigned FASTCALL HashStringCaselessConventional( const char *pszKey );
unsigned FASTCALL Hash4( const void *pKey );
unsigned FASTCALL Hash8( const void *pKey );
unsigned FASTCALL Hash12( const void *pKey );
unsigned FASTCALL Hash16( const void *pKey );
unsigned FASTCALL HashBlock( const void *pKey, unsigned size );
unsigned FASTCALL HashInt( const int key );
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 );
}
//-----------------------------------------------------------------------------
#endif /* !GENERICHASH_H */

114
public/tier1/iconvar.h Normal file
View File

@ -0,0 +1,114 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $NoKeywords: $
//===========================================================================//
#ifndef ICONVAR_H
#define ICONVAR_H
#if _WIN32
#pragma once
#endif
#include "tier0/dbg.h"
#include "tier0/platform.h"
#include "tier1/strtools.h"
//-----------------------------------------------------------------------------
// 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_NOT_CONNECTED (1<<22) // cvar cannot be changed by a client that is connected to a server
#define FCVAR_ARCHIVE_XBOX (1<<24) // cvar written to config.cfg on the Xbox
#define FCVAR_SERVER_CAN_EXECUTE (1<<28)// the server is allowed to execute this command on clients via ClientCommand/NET_StringCmd/CBaseClientState::ProcessStringCmd.
#define FCVAR_SERVER_CANNOT_QUERY (1<<29)// If this is set, then the server is not allowed to query this cvar's value (via IServerPluginHelpers::StartQueryCvarValue).
#define FCVAR_CLIENTCMD_CAN_EXECUTE (1<<30) // IVEngineClient::ClientCmd is allowed to execute this command.
// Note: IVEngineClient::ClientCmd_Unrestricted can run any client command.
// #define FCVAR_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<<25)
// #define FCVAR_AVAILABLE (1<<26)
// #define FCVAR_AVAILABLE (1<<27)
// #define FCVAR_AVAILABLE (1<<31)
//-----------------------------------------------------------------------------
// 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

219
public/tier1/interface.h Normal file
View File

@ -0,0 +1,219 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// This header defines the interface convention used in the valve engine.
// To make an interface and expose it:
// 1. The interface must be ALL pure virtuals, and have no data members.
// 2. Define a name for it.
// 3. In its implementation file, use EXPOSE_INTERFACE or EXPOSE_SINGLE_INTERFACE.
// Versioning
// There are two versioning cases that are handled by this:
// 1. You add functions to the end of an interface, so it is binary compatible with the previous interface. In this case,
// you need two EXPOSE_INTERFACEs: one to expose your class as the old interface and one to expose it as the new interface.
// 2. You update an interface so it's not compatible anymore (but you still want to be able to expose the old interface
// for legacy code). In this case, you need to make a new version name for your new interface, and make a wrapper interface and
// expose it for the old interface.
// Static Linking:
// Must mimic unique seperate class 'InterfaceReg' constructors per subsystem.
// Each subsystem can then import and export interfaces as expected.
// This is achieved through unique namespacing 'InterfaceReg' via symbol _SUBSYSTEM.
// Static Linking also needs to generate unique symbols per interface so as to
// provide a 'stitching' method whereby these interface symbols can be referenced
// via the lib's primary module (usually the lib's interface exposure)
// therby stitching all of that lib's code/data together for eventual final exe link inclusion.
#ifndef INTERFACE_H
#define INTERFACE_H
#ifdef _WIN32
#pragma once
#endif
#ifdef _LINUX
#include <dlfcn.h> // dlopen,dlclose, et al
#include <unistd.h>
#define HMODULE void *
#define GetProcAddress dlsym
#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(className, interfaceName, versionName, globalVarName) \
static void* __Create##className##interfaceName##_interface() {return static_cast<interfaceName *>( &globalVarName );} \
static InterfaceReg __g_Create##className##interfaceName##_reg(__Create##className##interfaceName##_interface, versionName);
#else
#define EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, globalVarName) \
namespace _SUBSYSTEM \
{ \
static void* __Create##className##interfaceName##_interface() {return static_cast<interfaceName *>( &globalVarName );} \
static InterfaceReg __g_Create##className##interfaceName##_reg(__Create##className##interfaceName##_interface, versionName); \
}
#endif
// Use this to expose a singleton interface. This creates the global variable for you automatically.
#if !defined(_STATIC_LINKED) || !defined(_SUBSYSTEM)
#define EXPOSE_SINGLE_INTERFACE(className, interfaceName, versionName) \
static className __g_##className##_singleton; \
EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, __g_##className##_singleton)
#else
#define EXPOSE_SINGLE_INTERFACE(className, interfaceName, versionName) \
namespace _SUBSYSTEM \
{ \
static className __g_##className##_singleton; \
} \
EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, __g_##className##_singleton)
#endif
// load/unload components
class CSysModule;
// interface return status
enum
{
IFACE_OK = 0,
IFACE_FAILED
};
//-----------------------------------------------------------------------------
// This function is automatically exported and allows you to access any interfaces exposed with the above macros.
// if pReturnCode is set, it will return one of the following values (IFACE_OK, IFACE_FAILED)
// extend this for other error conditions/code
//-----------------------------------------------------------------------------
DLL_EXPORT void* CreateInterface(const char *pName, int *pReturnCode);
#if defined( _X360 )
DLL_EXPORT void *CreateInterfaceThunk( const char *pName, int *pReturnCode );
#endif
//-----------------------------------------------------------------------------
// UNDONE: This is obsolete, use the module load/unload/get instead!!!
//-----------------------------------------------------------------------------
extern CreateInterfaceFn Sys_GetFactory( CSysModule *pModule );
extern CreateInterfaceFn Sys_GetFactory( const char *pModuleName );
extern CreateInterfaceFn Sys_GetFactoryThis( void );
//-----------------------------------------------------------------------------
// Load & Unload should be called in exactly one place for each module
// The factory for that module should be passed on to dependent components for
// proper versioning.
//-----------------------------------------------------------------------------
extern CSysModule *Sys_LoadModule( const char *pModuleName );
extern void Sys_UnloadModule( CSysModule *pModule );
// 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

View File

@ -0,0 +1,42 @@
//========= Copyright <20> 1996-2007, Valve Corporation, All rights reserved. ============//
//
// 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

67
public/tier1/lzss.h Normal file
View File

@ -0,0 +1,67 @@
//========= Copyright <20> 1996-2007, 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
#if !defined( _X360 )
#define LZSS_ID (('S'<<24)|('S'<<16)|('Z'<<8)|('L'))
#else
#define LZSS_ID (('L'<<24)|('Z'<<16)|('S'<<8)|('S'))
#endif
// bind the buffer for correct identification
struct lzss_header_t
{
unsigned int id;
unsigned int actualSize; // always little endian
};
#define DEFAULT_LZSS_WINDOW_SIZE 4096
class CLZSS
{
public:
unsigned char* Compress( unsigned char *pInput, int inputlen, unsigned int *pOutputSize );
unsigned char* CompressNoAlloc( unsigned char *pInput, int inputlen, unsigned char *pOutput, unsigned int *pOutputSize );
unsigned int Uncompress( unsigned char *pInput, unsigned char *pOutput );
bool IsCompressed( unsigned char *pInput );
unsigned int GetActualSize( 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
{
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( 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

541
public/tier1/mempool.h Normal file
View File

@ -0,0 +1,541 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//===========================================================================//
#ifndef MEMPOOL_H
#define MEMPOOL_H
#ifdef _WIN32
#pragma once
#endif
#include "tier0/memalloc.h"
#include "tier0/tslist.h"
#include "tier0/platform.h"
#include "tier1/utlvector.h"
#include "tier1/utlrbtree.h"
//-----------------------------------------------------------------------------
// Purpose: Optimized pool memory allocator
//-----------------------------------------------------------------------------
typedef void (*MemoryPoolReportFunc_t)( char const* pMsg, ... );
class CMemoryPool
{
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.
};
CMemoryPool( int blockSize, int numElements, int growMode = GROW_FAST, const char *pszAllocOwner = NULL, int nAlignment = 0 );
~CMemoryPool();
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];
};
// Resets the pool
void Init();
void AddNewBlob();
void ReportLeaks();
int m_BlockSize;
int m_BlocksPerBlob;
int m_GrowMode; // GROW_ enum.
// FIXME: Change m_ppMemBlob into a growable array?
CBlob m_BlobHead;
void *m_pHeadOfFreeList;
int m_BlocksAllocated;
int m_PeakAlloc;
unsigned short m_nAlignment;
unsigned short m_NumBlobs;
const char * m_pszAllocOwner;
static MemoryPoolReportFunc_t g_ReportFunc;
};
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
class CMemoryPoolMT : public CMemoryPool
{
public:
CMemoryPoolMT(int blockSize, int numElements, int growMode = GROW_FAST, const char *pszAllocOwner = NULL) : CMemoryPool( blockSize, numElements, growMode, pszAllocOwner) {}
void* Alloc() { AUTO_LOCK( m_mutex ); return CMemoryPool::Alloc(); }
void* Alloc( size_t amount ) { AUTO_LOCK( m_mutex ); return CMemoryPool::Alloc( amount ); }
void* AllocZero() { AUTO_LOCK( m_mutex ); return CMemoryPool::AllocZero(); }
void* AllocZero( size_t amount ) { AUTO_LOCK( m_mutex ); return CMemoryPool::AllocZero( amount ); }
void Free(void *pMem) { AUTO_LOCK( m_mutex ); CMemoryPool::Free( pMem ); }
// Frees everything
void Clear() { AUTO_LOCK( m_mutex ); return CMemoryPool::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 CMemoryPool
{
public:
CClassMemoryPool(int numElements, int growMode = GROW_FAST, int nAlignment = 0 ) :
CMemoryPool( sizeof(T), numElements, growMode, MEM_ALLOC_CLASSNAME(T), nAlignment ) {}
T* Alloc();
T* AllocZero();
void Free( T *pMem );
void Clear();
};
//-----------------------------------------------------------------------------
// Specialized pool for aligned data management (e.g., Xbox cubemaps)
//-----------------------------------------------------------------------------
template <int ITEM_SIZE, int ALIGNMENT, int CHUNK_SIZE, class CAllocator, int COMPACT_THRESHOLD = 4 >
class CAlignedMemPool
{
enum
{
BLOCK_SIZE = max( ALIGN_VALUE( ITEM_SIZE, ALIGNMENT ), 8 ),
};
public:
CAlignedMemPool();
void *Alloc();
void Free( void *p );
static int __cdecl CompareChunk( void * const *ppLeft, void * const *ppRight );
void Compact();
int NumTotal() { 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 CMemoryPool) 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*)CMemoryPool::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*)CMemoryPool::AllocZero();
}
if ( pRet )
{
Construct( pRet );
}
return pRet;
}
template< class T >
inline void CClassMemoryPool<T>::Free(T *pMem)
{
if ( pMem )
{
Destruct( pMem );
}
CMemoryPool::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++;
}
}
CMemoryPool::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 CMemoryPool s_Allocator
#define DEFINE_FIXEDSIZE_ALLOCATOR( _class, _initsize, _grow ) \
CMemoryPool _class::s_Allocator(sizeof(_class), _initsize, _grow, #_class " pool")
#define DEFINE_FIXEDSIZE_ALLOCATOR_ALIGNED( _class, _initsize, _grow, _alignment ) \
CMemoryPool _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 CMemoryPool* s_pAllocator
#define DEFINE_FIXEDSIZE_ALLOCATOR_EXTERNAL( _class, _allocator ) \
CMemoryPool* _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

204
public/tier1/memstack.h Normal file
View File

@ -0,0 +1,204 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: A fast stack memory allocator that uses virtual memory if available
//
//=============================================================================//
#ifndef MEMSTACK_H
#define MEMSTACK_H
#if defined( _WIN32 )
#pragma once
#endif
//-----------------------------------------------------------------------------
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); }
static int InvalidIndex() { return -1; }
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

70
public/tier1/netadr.h Normal file
View File

@ -0,0 +1,70 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// netadr.h
#ifndef NETADR_H
#define NETADR_H
#ifdef _WIN32
#pragma once
#endif
#include "tier0/platform.h"
#undef SetPort
typedef enum
{
NA_NULL = 0,
NA_LOOPBACK,
NA_BROADCAST,
NA_IP,
} netadrtype_t;
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 GetIP() const;
bool IsLocalhost() const; // true, if this is the localhost IP
bool IsLoopback() const; // true if engine loopback buffers are used
bool IsReservedAdr() const; // true, if this is a private LAN IP
bool IsValid() const; // ip & port != 0
void SetFromSocket( int hSocket );
// These function names are decorated because the Xbox360 defines macros for ntohl and htonl
unsigned long addr_ntohl() const;
unsigned long addr_htonl() const;
bool operator==(const netadr_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

View File

@ -0,0 +1,12 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: functions to expose CPU capabilities
//
// $NoKeywords: $
//=============================================================================//
bool CheckMMXTechnology(void);
bool CheckSSETechnology(void);
bool CheckSSE2Technology(void);
bool Check3DNowTechnology(void);

View File

@ -0,0 +1,113 @@
//========= Copyright <20> 1996-2005, 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;
}
// 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

385
public/tier1/refcount.h Normal file
View File

@ -0,0 +1,385 @@
//========== Copyright <20> 2005, Valve Corporation, All rights reserved. ========
//
// Purpose: Tools for correctly implementing & handling reference counted
// objects
//
//=============================================================================
#ifndef REFCOUNT_H
#define REFCOUNT_H
#include "tier0/threadtools.h"
#if defined( _WIN32 )
#pragma once
#endif
//-----------------------------------------------------------------------------
// Purpose: Implement a standard reference counted interface. Use of this
// is optional insofar as all the concrete tools only require
// at compile time that the function signatures match.
//-----------------------------------------------------------------------------
class IRefCounted
{
public:
virtual int AddRef() = 0;
virtual int Release() = 0;
};
//-----------------------------------------------------------------------------
// Purpose: Release a pointer and mark it NULL
//-----------------------------------------------------------------------------
template <class REFCOUNTED_ITEM_PTR>
inline int SafeRelease( REFCOUNTED_ITEM_PTR &pRef )
{
// Use funny syntax so that this works on "auto pointers"
REFCOUNTED_ITEM_PTR *ppRef = &pRef;
if ( *ppRef )
{
int result = (*ppRef)->Release();
*ppRef = NULL;
return result;
}
return 0;
}
//-----------------------------------------------------------------------------
// Purpose: Maintain a reference across a scope
//-----------------------------------------------------------------------------
template <class T = IRefCounted>
class CAutoRef
{
public:
CAutoRef( T *pRef )
: m_pRef( pRef )
{
if ( m_pRef )
m_pRef->AddRef();
}
~CAutoRef()
{
if (m_pRef)
m_pRef->Release();
}
private:
T *m_pRef;
};
//-----------------------------------------------------------------------------
// Purpose: Do a an inline AddRef then return the pointer, useful when
// returning an object from a function
//-----------------------------------------------------------------------------
#define RetAddRef( p ) ( (p)->AddRef(), (p) )
#define InlineAddRef( p ) ( (p)->AddRef(), (p) )
//-----------------------------------------------------------------------------
// Purpose: A class to both hold a pointer to an object and its reference.
// Base exists to support other cleanup models
//-----------------------------------------------------------------------------
template <class T>
class CBaseAutoPtr
{
public:
CBaseAutoPtr() : m_pObject(0) {}
CBaseAutoPtr(T *pFrom) : m_pObject(pFrom) {}
operator const void *() const { return m_pObject; }
operator void *() { return m_pObject; }
operator const T *() const { return m_pObject; }
operator const T *() { return m_pObject; }
operator T *() { return m_pObject; }
int operator=( int i ) { AssertMsg( i == 0, "Only NULL allowed on integer assign" ); m_pObject = 0; return 0; }
T * operator=( T *p ) { m_pObject = p; return p; }
bool operator !() const { return ( !m_pObject ); }
bool operator!=( int i ) const { AssertMsg( i == 0, "Only NULL allowed on integer compare" ); return (m_pObject != NULL); }
bool operator==( const void *p ) const { return ( m_pObject == p ); }
bool operator!=( const void *p ) const { return ( m_pObject != p ); }
bool operator==( T *p ) const { return operator==( (void *)p ); }
bool operator!=( T *p ) const { return operator!=( (void *)p ); }
bool operator==( const CBaseAutoPtr<T> &p ) const { return operator==( (const void *)p ); }
bool operator!=( const CBaseAutoPtr<T> &p ) const { return operator!=( (const void *)p ); }
T * operator->() { return m_pObject; }
T & operator *() { return *m_pObject; }
T ** operator &() { return &m_pObject; }
const T * operator->() const { return m_pObject; }
const T & operator *() const { return *m_pObject; }
T * const * operator &() const { return &m_pObject; }
protected:
CBaseAutoPtr( const CBaseAutoPtr<T> &from ) : m_pObject( from.m_pObject ) {}
void operator=( const CBaseAutoPtr<T> &from ) { m_pObject = from.m_pObject; }
T *m_pObject;
};
//---------------------------------------------------------
template <class T>
class CRefPtr : public CBaseAutoPtr<T>
{
typedef CBaseAutoPtr<T> BaseClass;
public:
CRefPtr() {}
CRefPtr( T *pInit ) : BaseClass( pInit ) {}
CRefPtr( const CRefPtr<T> &from ) : BaseClass( from ) {}
~CRefPtr() { if ( BaseClass::m_pObject ) BaseClass::m_pObject->Release(); }
void operator=( const CRefPtr<T> &from ) { BaseClass::operator=( from ); }
int operator=( int i ) { return BaseClass::operator=( i ); }
T *operator=( T *p ) { return BaseClass::operator=( p ); }
operator bool() const { return !BaseClass::operator!(); }
operator bool() { return !BaseClass::operator!(); }
void SafeRelease() { if ( BaseClass::m_pObject ) BaseClass::m_pObject->Release(); BaseClass::m_pObject = 0; }
void AssignAddRef( T *pFrom ) { SafeRelease(); if (pFrom) pFrom->AddRef(); BaseClass::m_pObject = pFrom; }
void AddRefAssignTo( T *&pTo ) { ::SafeRelease( pTo ); if ( BaseClass::m_pObject ) BaseClass::m_pObject->AddRef(); pTo = BaseClass::m_pObject; }
};
//-----------------------------------------------------------------------------
// Purpose: Traits classes defining reference count threading model
//-----------------------------------------------------------------------------
class CRefMT
{
public:
static int Increment( int *p) { return ThreadInterlockedIncrement( (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 = 0, const char *pszName = NULL>
class CRefDebug : public BASE_REFCOUNTED
{
public:
#ifdef _DEBUG
CRefDebug()
{
AssertMsg( GetRefCount() == 1, "Expected initial ref count of 1" );
DevMsg( "%s:create 0x%x\n", ( pszName ) ? pszName : "", this );
}
virtual ~CRefDebug()
{
AssertDevMsg( 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, GetRefCount() + 1 );
return BASE_REFCOUNTED::AddRef();
}
int Release()
{
DevMsg( "%s:(0x%x)->Release() --> %d\n", ( pszName ) ? pszName : "", this, GetRefCount() - 1 );
Assert( GetRefCount() > 0 );
return BASE_REFCOUNTED::Release();
}
#endif
};
//-----------------------------------------------------------------------------
#endif // REFCOUNT_H

279
public/tier1/smartptr.h Normal file
View File

@ -0,0 +1,279 @@
//========= Copyright <20> 1996-2005, 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 ) { Attach( p ); }
~CArrayAutoPtr( void ) { Delete(); }
public:
void Delete( void ) { delete [] Detach(); }
public:
T & operator [] ( int k ) const { return 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

91
public/tier1/stringpool.h Normal file
View File

@ -0,0 +1,91 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef STRINGPOOL_H
#define STRINGPOOL_H
#if defined( _WIN32 )
#pragma once
#endif
#include "utlrbtree.h"
#include "utlvector.h"
//-----------------------------------------------------------------------------
// 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 * CStringPool::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

462
public/tier1/strtools.h Normal file
View File

@ -0,0 +1,462 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
#ifndef TIER1_STRTOOLS_H
#define TIER1_STRTOOLS_H
#include "tier0/platform.h"
#ifdef _WIN32
#pragma once
#elif _LINUX
#include <ctype.h>
#include <wchar.h>
#endif
#include <string.h>
#include <stdlib.h>
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 );
int _V_stricmp ( const char* file, int line, const char *s1, const char *s2 );
char* _V_strstr ( const char* file, int line, const char *s1, const char *search );
char* _V_strupr ( const char* file, int line, char *start );
char* _V_strlower ( const char* file, int line, char *start );
int _V_wcslen ( const char* file, int line, const wchar_t *pwch );
#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_stricmp(s1, s2 ) _V_stricmp (__FILE__, __LINE__, (s1), (s2) )
#define V_strstr(s1, search ) _V_strstr (__FILE__, __LINE__, (s1), (search) )
#define V_strupr(start) _V_strupr (__FILE__, __LINE__, (start))
#define V_strlower(start) _V_strlower (__FILE__, __LINE__, (start))
#define V_wcslen(pwch) _V_wcslen (__FILE__, __LINE__, (pwch))
#else
#ifdef _LINUX
inline char *strupr( char *start )
{
char *str = start;
while( str && *str )
{
*str = (char)toupper(*str);
str++;
}
return start;
}
inline char *strlwr( char *start )
{
char *str = start;
while( str && *str )
{
*str = (char)tolower(*str);
str++;
}
return start;
}
#endif // _LINUX
inline void V_memset (void *dest, int fill, int count) { memset( dest, fill, count ); }
inline void V_memcpy (void *dest, const void *src, int count) { memcpy( dest, src, count ); }
inline void V_memmove (void *dest, const void *src, int count) { memmove( dest, src, count ); }
inline int V_memcmp (const void *m1, const void *m2, int count){ return memcmp( m1, m2, count ); }
inline int V_strlen (const char *str) { return (int) strlen ( str ); }
inline void V_strcpy (char *dest, const char *src) { strcpy( dest, src ); }
inline int V_wcslen(const wchar_t *pwch) { return (int)wcslen(pwch); }
inline char* V_strrchr (const char *s, char c) { return (char*)strrchr( s, c ); }
inline int V_strcmp (const char *s1, const char *s2) { return strcmp( s1, s2 ); }
inline int V_wcscmp (const wchar_t *s1, const wchar_t *s2) { return wcscmp( s1, s2 ); }
inline int V_stricmp( const char *s1, const char *s2 ) { return stricmp( s1, s2 ); }
inline char* V_strstr( const char *s1, const char *search ) { return (char*)strstr( s1, search ); }
inline char* V_strupr (char *start) { return strupr( start ); }
inline char* V_strlower (char *start) { return strlwr( start ); }
#endif
int V_strncmp (const char *s1, const char *s2, int count);
int V_strcasecmp (const char *s1, const char *s2);
int V_strncasecmp (const char *s1, const char *s2, int n);
int V_strnicmp (const char *s1, const char *s2, int n);
int V_atoi (const char *str);
float V_atof (const char *str);
char* V_stristr( char* pStr, const char* pSearch );
const char* V_stristr( const char* pStr, const char* pSearch );
const char* V_strnistr( const char* pStr, const char* pSearch, int n );
const char* V_strnchr( const char* pStr, char c, int n );
// returns string immediately following prefix, (ie str+strlen(prefix)) or NULL if prefix not found
const char *StringAfterPrefix ( const char *str, const char *prefix );
const char *StringAfterPrefixCaseSensitive( const char *str, const char *prefix );
inline bool StringHasPrefix ( const char *str, const char *prefix ) { return StringAfterPrefix ( str, prefix ) != NULL; }
inline bool StringHasPrefixCaseSensitive( const char *str, const char *prefix ) { return StringAfterPrefixCaseSensitive( str, prefix ) != NULL; }
// Normalizes a float string in place.
// (removes leading zeros, trailing zeros after the decimal point, and the decimal point itself where possible)
void V_normalizeFloatString( char* pFloat );
// These are versions of functions that guarantee NULL termination.
//
// maxLen is the maximum number of bytes in the destination string.
// pDest[maxLen-1] is always NULL terminated if pSrc's length is >= maxLen.
//
// This means the last parameter can usually be a sizeof() of a string.
void V_strncpy( char *pDest, const char *pSrc, int maxLen );
int V_snprintf( char *pDest, int destLen, const char *pFormat, ... );
void V_wcsncpy( wchar_t *pDest, wchar_t const *pSrc, int maxLenInBytes );
int V_snwprintf( wchar_t *pDest, int destLen, const wchar_t *pFormat, ... );
#define COPY_ALL_CHARACTERS -1
char *V_strncat(char *, const char *, size_t destBufferSize, int max_chars_to_copy=COPY_ALL_CHARACTERS );
char *V_strnlwr(char *, size_t);
// UNDONE: Find a non-compiler-specific way to do this
#ifdef _WIN32
#ifndef _VA_LIST_DEFINED
#ifdef _M_ALPHA
struct va_list
{
char *a0; /* pointer to first homed integer argument */
int offset; /* byte offset of next parameter */
};
#else // !_M_ALPHA
typedef char * va_list;
#endif // !_M_ALPHA
#define _VA_LIST_DEFINED
#endif // _VA_LIST_DEFINED
#elif _LINUX
#include <stdarg.h>
#endif
#ifdef _WIN32
#define CORRECT_PATH_SEPARATOR '\\'
#define INCORRECT_PATH_SEPARATOR '/'
#elif _LINUX
#define CORRECT_PATH_SEPARATOR '/'
#define INCORRECT_PATH_SEPARATOR '\\'
#endif
int V_vsnprintf( char *pDest, int maxLen, const char *pFormat, va_list params );
// 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, wchar_t *pwchDest, int cubDestSizeInBytes );
int V_UnicodeToUTF8( const wchar_t *pUnicode, char *pUTF8, int cubDestSizeInBytes );
// Functions for converting hexidecimal character strings back into binary data etc.
//
// e.g.,
// int output;
// V_hextobinary( "ffffffff", 8, &output, sizeof( output ) );
// would make output == 0xfffffff or -1
// Similarly,
// char buffer[ 9 ];
// V_binarytohex( &output, sizeof( output ), buffer, sizeof( buffer ) );
// would put "ffffffff" into buffer (note null terminator!!!)
void V_hextobinary( char const *in, int numchars, byte *out, int maxoutputbytes );
void V_binarytohex( const byte *in, int inputbytes, char *out, int outsize );
// Tools for working with filenames
// Extracts the base name of a file (no path, no extension, assumes '/' or '\' as path separator)
void V_FileBase( const char *in, char *out,int maxlen );
// Remove the final characters of ppath if it's '\' or '/'.
void V_StripTrailingSlash( char *ppath );
// Remove any extension from in and return resulting string in out
void V_StripExtension( const char *in, char *out, int outLen );
// Make path end with extension if it doesn't already have an extension
void V_DefaultExtension( char *path, const char *extension, int pathStringLength );
// Strips any current extension from path and ensures that extension is the new extension
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 );
// This removes "./" and "../" from the pathname. pFilename should be a full pathname.
// Returns false if it tries to ".." past the root directory in the drive (in which case
// it is an invalid path).
bool V_RemoveDotSlashes( char *pFilename, char separator = CORRECT_PATH_SEPARATOR );
// If pPath is a relative path, this function makes it into an absolute path
// using the current working directory as the base, or pStartingDir if it's non-NULL.
// Returns false if it runs out of room in the string, or if pPath tries to ".." past the root directory.
void V_MakeAbsolutePath( char *pOut, int outLen, const char *pPath, const char *pStartingDir = NULL );
// Creates a relative path given two full paths
// The first is the full path of the file to make a relative path for.
// The second is the full path of the directory to make the first file relative to
// Returns false if they can't be made relative (on separate drives, for example)
bool V_MakeRelativePath( const char *pFullPath, const char *pDirectory, char *pRelativePath, int nBufLen );
// Fixes up a file name, removing dot slashes, fixing slashes, converting to lowercase, etc.
void V_FixupPathName( char *pOut, size_t nOutLen, const char *pPath );
// Adds a path separator to the end of the string if there isn't one already. Returns false if it would run out of space.
void V_AppendSlash( char *pStr, int strSize );
// Returns true if the path is an absolute path.
bool V_IsAbsolutePath( const char *pPath );
// Scans pIn and replaces all occurences of pMatch with pReplaceWith.
// Writes the result to pOut.
// Returns true if it completed successfully.
// If it would overflow pOut, it fills as much as it can and returns false.
bool V_StrSubst( const char *pIn, const char *pMatch, const char *pReplaceWith,
char *pOut, int outLen, bool bCaseSensitive=false );
// Split the specified string on the specified separator.
// Returns a list of strings separated by pSeparator.
// You are responsible for freeing the contents of outStrings (call outStrings.PurgeAndDeleteElements).
void V_SplitString( const char *pString, const char *pSeparator, CUtlVector<char*, CUtlMemory<char*, int> > &outStrings );
// Just like V_SplitString, but it can use multiple possible separators.
void V_SplitString2( const char *pString, const char **pSeparators, int nSeparators, CUtlVector<char*, CUtlMemory<char*, int> > &outStrings );
// Returns false if the buffer is not large enough to hold the working directory name.
bool V_GetCurrentDirectory( char *pOut, int maxLen );
// Set the working directory thus.
bool V_SetCurrentDirectory( const char *pDirName );
// This function takes a slice out of pStr and stores it in pOut.
// It follows the Python slice convention:
// Negative numbers wrap around the string (-1 references the last character).
// Large numbers are clamped to the end of the string.
void V_StrSlice( const char *pStr, int firstChar, int lastCharNonInclusive, char *pOut, int outSize );
// Chop off the left nChars of a string.
void V_StrLeft( const char *pStr, int nChars, char *pOut, int outSize );
// Chop off the right nChars of a string.
void V_StrRight( const char *pStr, int nChars, char *pOut, int outSize );
// change "special" characters to have their c-style backslash sequence. like \n, \r, \t, ", etc.
// returns a pointer to a newly allocated string, which you must delete[] when finished with.
char *V_AddBackSlashesToSpecialChars( char const *pSrc );
// Force slashes of either type to be = separator character
void V_FixSlashes( char *pname, char separator = CORRECT_PATH_SEPARATOR );
// This function fixes cases of filenames like materials\\blah.vmt or somepath\otherpath\\ and removes the extra double slash.
void V_FixDoubleSlashes( char *pStr );
// Convert multibyte to wchar + back
// Specify -1 for nInSize for null-terminated string
void V_strtowcs( const char *pString, int nInSize, wchar_t *pWString, int nOutSize );
void V_wcstostr( const wchar_t *pWString, int nInSize, char *pString, int nOutSize );
// buffer-safe strcat
inline void V_strcat( char *dest, const char *src, int cchDest )
{
V_strncat( 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( 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;
}
// 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_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_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
#endif // !defined( VSTDLIB_DLL_EXPORT )
#endif // TIER1_STRTOOLS_H

106
public/tier1/tier1.h Normal file
View File

@ -0,0 +1,106 @@
//===== Copyright <20> 2005-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: A higher level link library for general use in the game and tools.
//
//===========================================================================//
#ifndef TIER1_H
#define TIER1_H
#if defined( _WIN32 )
#pragma once
#endif
#include "appframework/IAppSystem.h"
#include "tier1/convar.h"
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
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;
DLL_EXPORT 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 ( IsPrimaryAppSystem() )
{
ConnectTier1Libraries( &factory, 1 );
}
return true;
}
virtual void Disconnect()
{
if ( IsPrimaryAppSystem() )
{
DisconnectTier1Libraries();
}
BaseClass::Disconnect();
}
virtual InitReturnVal_t Init()
{
InitReturnVal_t nRetVal = BaseClass::Init();
if ( nRetVal != INIT_OK )
return nRetVal;
if ( g_pCVar && IsPrimaryAppSystem() )
{
ConVar_Register( ConVarFlag );
}
return INIT_OK;
}
virtual void Shutdown()
{
if ( g_pCVar && IsPrimaryAppSystem() )
{
ConVar_Unregister( );
}
BaseClass::Shutdown( );
}
};
#endif // TIER1_H

105
public/tier1/tokenreader.h Normal file
View File

@ -0,0 +1,105 @@
//========= Copyright <20> 1996-2005, 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
#include <fstream>
#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);
inline TokenReader(TokenReader const &)
{
// prevent vc7 warning. compiler can't generate a copy constructor since descended from
// std::ifstream
assert(0);
}
inline int operator=(TokenReader const &)
{
// prevent vc7 warning. compiler can't generate an assignment operator since descended from
// std::ifstream
assert(0);
}
private:
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

56
public/tier1/uniqueid.h Normal file
View File

@ -0,0 +1,56 @@
//====== Copyright <20> 1996-2005, 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

View File

@ -0,0 +1,381 @@
//========= Copyright <20> 1996-2005, 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();
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( );
}
//-----------------------------------------------------------------------------
// 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

View File

@ -0,0 +1,349 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//
// A growable memory class.
//===========================================================================//
#ifndef UTLBLOCKMEMORY_H
#define UTLBLOCKMEMORY_H
#ifdef _WIN32
#pragma once
#endif
#include "tier0/dbg.h"
#include "tier0/platform.h"
#include "mathlib/mathlib.h"
#include "tier0/memalloc.h"
#include "tier0/memdbgon.h"
#pragma warning (disable:4100)
#pragma warning (disable:4514)
//-----------------------------------------------------------------------------
#ifdef UTLMEMORY_TRACK
#define UTLMEMORY_TRACK_ALLOC() MemAlloc_RegisterAllocation( "Sum of all UtlBlockMemory", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 )
#define UTLMEMORY_TRACK_FREE() if ( !m_pMemory ) ; else MemAlloc_RegisterDeallocation( "Sum of all UtlBlockMemory", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 )
#else
#define UTLMEMORY_TRACK_ALLOC() ((void)0)
#define UTLMEMORY_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 )
{
UTLMEMORY_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;
UTLMEMORY_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 )
{
UTLMEMORY_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 )
{
UTLMEMORY_TRACK_FREE();
free( (void*)m_pMemory[ i ] );
}
m_nBlocks = 0;
UTLMEMORY_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

1028
public/tier1/utlbuffer.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,192 @@
//====== Copyright <20> 1996-2005, 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

320
public/tier1/utldict.h Normal file
View File

@ -0,0 +1,320 @@
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======//
//
// Purpose: A dictionary mapping from symbol to structure
//
// $Header: $
// $NoKeywords: $
//=============================================================================//
#ifndef UTLDICT_H
#define UTLDICT_H
#ifdef _WIN32
#pragma once
#endif
#include "tier0/dbg.h"
#include "tier1/utlmap.h"
// Include this because tons of code was implicitly getting utlsymbol or utlvector via utldict.h
#include "tier1/utlsymbol.h"
#include "tier0/memdbgon.h"
enum EDictCompareType
{
k_eDictCompareTypeCaseSensitive=0,
k_eDictCompareTypeCaseInsensitive=1,
k_eDictCompareTypeFilenames // Slashes and backslashes count as the same character..
};
//-----------------------------------------------------------------------------
// A dictionary mapping from symbol to structure
//-----------------------------------------------------------------------------
template <class T, class I>
class CUtlDict
{
public:
// constructor, destructor
// Left at growSize = 0, the memory will first allocate 1 element and double in size
// at each increment.
CUtlDict( int compareType = k_eDictCompareTypeCaseInsensitive, int growSize = 0, int initSize = 0 );
~CUtlDict( );
void EnsureCapacity( int );
// gets particular elements
T& Element( I i );
const T& Element( I i ) const;
T& operator[]( I i );
const T& operator[]( I i ) const;
// gets element names
char *GetElementName( I i );
char const *GetElementName( I i ) const;
void SetElementName( I i, char const *pName );
// Number of elements
unsigned int Count() const;
// Checks if a node is valid and in the tree
bool IsValidIndex( I i ) const;
// Invalid index
static I InvalidIndex();
// Insert method (inserts in order)
I Insert( const char *pName, const T &element );
I Insert( const char *pName );
// Find method
I Find( const char *pName ) const;
// Remove methods
void RemoveAt( I i );
void Remove( const char *pName );
void RemoveAll( );
// Purge memory
void Purge();
void PurgeAndDeleteElements(); // Call delete on each element.
// Iteration methods
I First() const;
I Next( I i ) const;
protected:
typedef CUtlMap<const char *, T, I> DictElementMap_t;
DictElementMap_t m_Elements;
};
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
template <class T, class I>
CUtlDict<T, I>::CUtlDict( int compareType, int growSize, int initSize ) : m_Elements( growSize, initSize )
{
if ( compareType == k_eDictCompareTypeFilenames )
{
m_Elements.SetLessFunc( CaselessStringLessThanIgnoreSlashes );
}
else if ( compareType == k_eDictCompareTypeCaseInsensitive )
{
m_Elements.SetLessFunc( CaselessStringLessThan );
}
else
{
m_Elements.SetLessFunc( StringLessThan );
}
}
template <class T, class I>
CUtlDict<T, I>::~CUtlDict()
{
Purge();
}
template <class T, class I>
inline void CUtlDict<T, I>::EnsureCapacity( int num )
{
return m_Elements.EnsureCapacity( num );
}
//-----------------------------------------------------------------------------
// gets particular elements
//-----------------------------------------------------------------------------
template <class T, class I>
inline T& CUtlDict<T, I>::Element( I i )
{
return m_Elements[i];
}
template <class T, class I>
inline const T& CUtlDict<T, I>::Element( I i ) const
{
return m_Elements[i];
}
//-----------------------------------------------------------------------------
// gets element names
//-----------------------------------------------------------------------------
template <class T, class I>
inline char *CUtlDict<T, I>::GetElementName( I i )
{
return (char *)m_Elements.Key( i );
}
template <class T, class I>
inline char const *CUtlDict<T, I>::GetElementName( I i ) const
{
return m_Elements.Key( i );
}
template <class T, class I>
inline T& CUtlDict<T, I>::operator[]( I i )
{
return Element(i);
}
template <class T, class I>
inline const T & CUtlDict<T, I>::operator[]( I i ) const
{
return Element(i);
}
template <class T, class I>
inline void CUtlDict<T, I>::SetElementName( I i, char const *pName )
{
MEM_ALLOC_CREDIT_CLASS();
// TODO: This makes a copy of the old element
// TODO: This relies on the rb tree putting the most recently
// removed element at the head of the insert list
free( (void *)m_Elements.Key( i ) );
m_Elements.Reinsert( strdup( pName ), i );
}
//-----------------------------------------------------------------------------
// Num elements
//-----------------------------------------------------------------------------
template <class T, class I>
inline unsigned int CUtlDict<T, I>::Count() const
{
return m_Elements.Count();
}
//-----------------------------------------------------------------------------
// Checks if a node is valid and in the tree
//-----------------------------------------------------------------------------
template <class T, class I>
inline bool CUtlDict<T, I>::IsValidIndex( I i ) const
{
return m_Elements.IsValidIndex(i);
}
//-----------------------------------------------------------------------------
// Invalid index
//-----------------------------------------------------------------------------
template <class T, class I>
inline I CUtlDict<T, I>::InvalidIndex()
{
return DictElementMap_t::InvalidIndex();
}
//-----------------------------------------------------------------------------
// Delete a node from the tree
//-----------------------------------------------------------------------------
template <class T, class I>
void CUtlDict<T, I>::RemoveAt(I elem)
{
free( (void *)m_Elements.Key( elem ) );
m_Elements.RemoveAt(elem);
}
//-----------------------------------------------------------------------------
// remove a node in the tree
//-----------------------------------------------------------------------------
template <class T, class I> void CUtlDict<T, I>::Remove( const char *search )
{
I node = Find( search );
if (node != InvalidIndex())
{
RemoveAt(node);
}
}
//-----------------------------------------------------------------------------
// Removes all nodes from the tree
//-----------------------------------------------------------------------------
template <class T, class I>
void CUtlDict<T, I>::RemoveAll()
{
typename DictElementMap_t::IndexType_t index = m_Elements.FirstInorder();
while ( index != m_Elements.InvalidIndex() )
{
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();
}
//-----------------------------------------------------------------------------
// 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

240
public/tier1/utlenvelope.h Normal file
View File

@ -0,0 +1,240 @@
//========== Copyright <20> 2005, Valve Corporation, All rights reserved. ========
//
// Purpose: A class to wrap data for transport over a boundary like a thread
// or window.
//
//=============================================================================
#include "tier1/utlstring.h"
#include "tier0/basetypes.h"
#ifndef UTLENVELOPE_H
#define UTLENVELOPE_H
#if defined( _WIN32 )
#pragma once
#endif
//-----------------------------------------------------------------------------
class CUtlDataEnvelope
{
public:
CUtlDataEnvelope( const void *pData, int nBytes );
CUtlDataEnvelope( const CUtlDataEnvelope &from );
~CUtlDataEnvelope();
CUtlDataEnvelope &operator=( const CUtlDataEnvelope &from );
operator void *();
operator void *() const;
private:
void Assign( const void *pData, int nBytes );
void Assign( const CUtlDataEnvelope &from );
void Purge();
// TODO: switch to a reference counted array?
union
{
byte *m_pData;
byte m_data[4];
};
int m_nBytes;
};
//-----------------------------------------------------------------------------
template <typename T>
class CUtlEnvelope : protected CUtlDataEnvelope
{
public:
CUtlEnvelope( const T *pData, int nElems = 1 );
CUtlEnvelope( const CUtlEnvelope<T> &from );
CUtlEnvelope<T> &operator=( const CUtlEnvelope<T> &from );
operator T *();
operator T *() const;
operator void *();
operator void *() const;
};
//-----------------------------------------------------------------------------
template <>
class CUtlEnvelope<const char *>
{
public:
CUtlEnvelope( const char *pData )
{
m_string = pData;
}
CUtlEnvelope( const CUtlEnvelope<const char *> &from )
{
m_string = from.m_string;
}
CUtlEnvelope<const char> &operator=( const CUtlEnvelope<const char *> &from )
{
m_string = from.m_string;
}
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 = 1 )
: 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

View File

@ -0,0 +1,356 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//
// A growable memory class.
//===========================================================================//
#ifndef UTLFIXEDMEMORY_H
#define UTLFIXEDMEMORY_H
#ifdef _WIN32
#pragma once
#endif
#include "tier0/dbg.h"
#include "tier0/platform.h"
#include "tier0/memalloc.h"
#include "tier0/memdbgon.h"
#pragma warning (disable:4100)
#pragma warning (disable:4514)
//-----------------------------------------------------------------------------
#ifdef UTLMEMORY_TRACK
#define UTLMEMORY_TRACK_ALLOC() MemAlloc_RegisterAllocation( "Sum of all UtlFixedMemory", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 )
#define UTLMEMORY_TRACK_FREE() if ( !m_pMemory ) ; else MemAlloc_RegisterDeallocation( "Sum of all UtlFixedMemory", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 )
#else
#define UTLMEMORY_TRACK_ALLOC() ((void)0)
#define UTLMEMORY_TRACK_FREE() ((void)0)
#endif
//-----------------------------------------------------------------------------
// The CUtlFixedMemory class:
// A growable memory class that allocates non-sequential blocks, but is indexed sequentially
//-----------------------------------------------------------------------------
template< class T >
class CUtlFixedMemory
{
public:
// constructor, destructor
CUtlFixedMemory( int nGrowSize = 0, int nInitSize = 0 );
~CUtlFixedMemory();
// Set the size by which the memory grows
void Init( int nGrowSize = 0, int nInitSize = 0 );
// here to match CUtlMemory, but only used by ResetDbgInfo, so it can just return NULL
T* Base() { return NULL; }
const T* Base() const { return NULL; }
protected:
struct BlockHeader_t;
public:
class Iterator_t
{
public:
Iterator_t( BlockHeader_t *p, int i ) : m_pBlockHeader( p ), m_nIndex( i ) {}
BlockHeader_t *m_pBlockHeader;
int m_nIndex;
bool operator==( const Iterator_t it ) const { return m_pBlockHeader == it.m_pBlockHeader && m_nIndex == it.m_nIndex; }
bool operator!=( const Iterator_t it ) const { return m_pBlockHeader != it.m_pBlockHeader || m_nIndex != it.m_nIndex; }
};
Iterator_t First() const { return m_pBlocks ? Iterator_t( m_pBlocks, 0 ) : InvalidIterator(); }
Iterator_t Next( const Iterator_t &it ) const
{
Assert( IsValidIterator( it ) );
if ( !IsValidIterator( it ) )
return InvalidIterator();
BlockHeader_t * RESTRICT pHeader = it.m_pBlockHeader;
if ( it.m_nIndex + 1 < pHeader->m_nBlockSize )
return Iterator_t( pHeader, it.m_nIndex + 1 );
return pHeader->m_pNext ? Iterator_t( pHeader->m_pNext, 0 ) : InvalidIterator();
}
int GetIndex( const Iterator_t &it ) const
{
Assert( IsValidIterator( it ) );
if ( !IsValidIterator( it ) )
return InvalidIndex();
return ( int )( HeaderToBlock( it.m_pBlockHeader ) + it.m_nIndex );
}
bool IsIdxAfter( int i, const Iterator_t &it ) const
{
Assert( IsValidIterator( it ) );
if ( !IsValidIterator( it ) )
return false;
if ( IsInBlock( i, it.m_pBlockHeader ) )
return i > GetIndex( it );
for ( BlockHeader_t * RESTRICT pbh = it.m_pBlockHeader->m_pNext; pbh; pbh = pbh->m_pNext )
{
if ( IsInBlock( i, pbh ) )
return true;
}
return false;
}
bool IsValidIterator( const Iterator_t &it ) const { return it.m_pBlockHeader && it.m_nIndex >= 0 && it.m_nIndex < it.m_pBlockHeader->m_nBlockSize; }
Iterator_t InvalidIterator() const { return Iterator_t( NULL, -1 ); }
// element access
T& operator[]( int i );
const T& operator[]( int i ) const;
T& Element( int i );
const T& Element( int i ) const;
// Can we use this index?
bool IsIdxValid( int i ) const;
static int InvalidIndex() { return 0; }
// Size
int NumAllocated() const;
int Count() const { return NumAllocated(); }
// Grows memory by max(num,growsize), and returns the allocation index/ptr
void Grow( int num = 1 );
// Makes sure we've got at least this much memory
void EnsureCapacity( int num );
// Memory deallocation
void Purge();
protected:
// Fast swap - WARNING: Swap invalidates all ptr-based indices!!!
void Swap( CUtlFixedMemory< T > &mem );
bool IsInBlock( int i, BlockHeader_t *pBlockHeader ) const
{
T *p = ( T* )i;
const T *p0 = HeaderToBlock( pBlockHeader );
return p >= p0 && p < p0 + pBlockHeader->m_nBlockSize;
}
struct BlockHeader_t
{
BlockHeader_t *m_pNext;
int m_nBlockSize;
};
const T *HeaderToBlock( const BlockHeader_t *pHeader ) const { return ( T* )( pHeader + 1 ); }
const BlockHeader_t *BlockToHeader( const T *pBlock ) const { return ( BlockHeader_t* )( pBlock ) - 1; }
BlockHeader_t* m_pBlocks;
int m_nAllocationCount;
int m_nGrowSize;
};
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
template< class T >
CUtlFixedMemory<T>::CUtlFixedMemory( int nGrowSize, int nInitAllocationCount )
: m_pBlocks( 0 ), m_nAllocationCount( 0 ), m_nGrowSize( 0 )
{
Init( nGrowSize, nInitAllocationCount );
}
template< class T >
CUtlFixedMemory<T>::~CUtlFixedMemory()
{
Purge();
}
//-----------------------------------------------------------------------------
// Fast swap - WARNING: Swap invalidates all ptr-based indices!!!
//-----------------------------------------------------------------------------
template< class T >
void CUtlFixedMemory<T>::Swap( CUtlFixedMemory< T > &mem )
{
swap( m_pBlocks, mem.m_pBlocks );
swap( m_nAllocationCount, mem.m_nAllocationCount );
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();
if ( nGrowSize == 0)
{
// Compute an allocation which is at least as big as a cache line...
nGrowSize = ( 31 + sizeof( T ) ) / sizeof( T );
}
m_nGrowSize = nGrowSize;
Grow( nInitSize );
}
//-----------------------------------------------------------------------------
// element access
//-----------------------------------------------------------------------------
template< class T >
inline T& CUtlFixedMemory<T>::operator[]( int i )
{
Assert( IsIdxValid(i) );
return *( T* )i;
}
template< class T >
inline const T& CUtlFixedMemory<T>::operator[]( int i ) const
{
Assert( IsIdxValid(i) );
return *( T* )i;
}
template< class T >
inline T& CUtlFixedMemory<T>::Element( int i )
{
Assert( IsIdxValid(i) );
return *( T* )i;
}
template< class T >
inline const T& CUtlFixedMemory<T>::Element( int i ) const
{
Assert( IsIdxValid(i) );
return *( T* )i;
}
//-----------------------------------------------------------------------------
// Size
//-----------------------------------------------------------------------------
template< class T >
inline int CUtlFixedMemory<T>::NumAllocated() const
{
return m_nAllocationCount;
}
//-----------------------------------------------------------------------------
// Is element index valid?
//-----------------------------------------------------------------------------
template< class T >
inline bool CUtlFixedMemory<T>::IsIdxValid( int i ) const
{
#ifdef _DEBUG
for ( BlockHeader_t *pbh = m_pBlocks; pbh; pbh = pbh->m_pNext )
{
if ( IsInBlock( i, pbh ) )
return true;
}
return false;
#else
return i != InvalidIndex();
#endif
}
template< class T >
void CUtlFixedMemory<T>::Grow( int num )
{
if ( num <= 0 )
return;
int nBlockSize = m_nGrowSize;
if ( nBlockSize == 0 )
{
if ( m_nAllocationCount )
{
nBlockSize = m_nAllocationCount;
}
else
{
// Compute an allocation which is at least as big as a cache line...
nBlockSize = ( 31 + sizeof( T ) ) / sizeof( T );
Assert( nBlockSize );
}
}
if ( nBlockSize < num )
{
int n = ( num + nBlockSize -1 ) / nBlockSize;
Assert( n * nBlockSize >= num );
Assert( ( n - 1 ) * nBlockSize < num );
nBlockSize *= n;
}
m_nAllocationCount += nBlockSize;
MEM_ALLOC_CREDIT_CLASS();
BlockHeader_t * RESTRICT pBlockHeader = ( BlockHeader_t* )malloc( sizeof( BlockHeader_t ) + nBlockSize * sizeof( T ) );
if ( !pBlockHeader )
{
Error( "CUtlFixedMemory overflow!\n" );
}
pBlockHeader->m_pNext = NULL;
pBlockHeader->m_nBlockSize = nBlockSize;
if ( !m_pBlocks )
{
m_pBlocks = pBlockHeader;
}
else
{
#if 1 // IsIdxAfter assumes that newly allocated blocks are at the end
BlockHeader_t * RESTRICT pbh = m_pBlocks;
while ( pbh->m_pNext )
{
pbh = pbh->m_pNext;
}
pbh->m_pNext = pBlockHeader;
#else
pBlockHeader = m_pBlocks;
pBlockHeader->m_pNext = m_pBlocks;
#endif
}
}
//-----------------------------------------------------------------------------
// Makes sure we've got at least this much memory
//-----------------------------------------------------------------------------
template< class T >
inline void CUtlFixedMemory<T>::EnsureCapacity( int num )
{
Grow( num - NumAllocated() );
}
//-----------------------------------------------------------------------------
// Memory deallocation
//-----------------------------------------------------------------------------
template< class T >
void CUtlFixedMemory<T>::Purge()
{
if ( !m_pBlocks )
return;
for ( BlockHeader_t *pbh = m_pBlocks; pbh; )
{
BlockHeader_t *pFree = pbh;
pbh = pbh->m_pNext;
free( pFree );
}
m_pBlocks = NULL;
m_nAllocationCount = 0;
}
#include "tier0/memdbgoff.h"
#endif // UTLFIXEDMEMORY_H

124
public/tier1/utlflags.h Normal file
View File

@ -0,0 +1,124 @@
//====== Copyright <20> 1996-2004, 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

View File

@ -0,0 +1,586 @@
//====== Copyright <20> 1996-2004, 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

936
public/tier1/utlhash.h Normal file
View File

@ -0,0 +1,936 @@
//========= Copyright <20> 1996-2005, 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

342
public/tier1/utlhashdict.h Normal file
View File

@ -0,0 +1,342 @@
//========== Copyright <20> 2005, 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

View File

@ -0,0 +1,772 @@
//===== Copyright <20> 1996-2006, 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 "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 fileds 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 meanto 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;
}
}
// 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)
{
for(T *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
{
for(T *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 CUtlIntrusiveList(void)
{
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 )
{
return IntrusiveList::ListLength( m_pHead );
}
};
// 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 * PrevNode(T *node)
{
return ( node )?node->m_Prev:NULL;
}
};
#endif

1018
public/tier1/utllinkedlist.h Normal file

File diff suppressed because it is too large Load Diff

203
public/tier1/utlmap.h Normal file
View File

@ -0,0 +1,203 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Header: $
// $NoKeywords: $
//=============================================================================//
#ifndef UTLMAP_H
#define UTLMAP_H
#ifdef _WIN32
#pragma once
#endif
#include "tier0/dbg.h"
#include "utlrbtree.h"
//-----------------------------------------------------------------------------
//
// Purpose: An associative container. Pretty much identical to std::map.
//
//-----------------------------------------------------------------------------
// This is a useful macro to iterate from start to end in order in a map
#define FOR_EACH_MAP( mapName, iteratorName ) \
for ( int iteratorName = mapName.FirstInorder(); 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; iteratorName < mapName.MaxElement(); ++iteratorName ) if ( !mapName.IsValidIndex( iteratorName ) ) continue; else
template <typename K, typename T, typename I = unsigned short>
class CUtlMap
{
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(); }
// 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;
};
//-----------------------------------------------------------------------------
#endif // UTLMAP_H

925
public/tier1/utlmemory.h Normal file
View File

@ -0,0 +1,925 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//
// A growable memory class.
//===========================================================================//
#ifndef UTLMEMORY_H
#define UTLMEMORY_H
#ifdef _WIN32
#pragma once
#endif
#include "tier0/dbg.h"
#include <string.h>
#include "tier0/platform.h"
#include "tier0/memalloc.h"
#include "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;
static I InvalidIndex() { return ( I )-1; }
// Gets the base address (can change when adding elements!)
T* Base();
const T* Base() const;
// Attaches the buffer to external memory....
void SetExternalBuffer( T* pMemory, int numElements );
void SetExternalBuffer( const T* pMemory, int numElements );
void AssumeMemory( T *pMemory, int nSize );
// 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 ( IsExternallyAllocated() )
{
ConvertToGrowableMemory( m_nMallocGrowSize );
}
BaseClass::Grow( nCount );
}
void EnsureCapacity( int num )
{
if ( CUtlMemory<T>::m_nAllocationCount >= num )
return;
if ( IsExternallyAllocated() )
{
// Can't grow a buffer whose memory was externally allocated
ConvertToGrowableMemory( m_nMallocGrowSize );
}
BaseClass::EnsureCapacity( num );
}
private:
int m_nMallocGrowSize;
T m_pFixedMemory[ SIZE ];
};
//-----------------------------------------------------------------------------
// The CUtlMemoryFixed class:
// A fixed memory class
//-----------------------------------------------------------------------------
template< typename T, size_t SIZE, int nAlignment = 0 >
class CUtlMemoryFixed
{
public:
// constructor, destructor
CUtlMemoryFixed( int nGrowSize = 0, int nInitSize = 0 ) { Assert( nInitSize == 0 || nInitSize == SIZE ); }
CUtlMemoryFixed( T* pMemory, int numElements ) { Assert( 0 ); }
// Can we use this index?
bool IsIdxValid( int i ) const { return (i >= 0) && (i < SIZE); }
static int InvalidIndex() { return -1; }
// Gets the base address
T* Base() { if ( nAlignment == 0 ) return (T*)(&m_Memory[0]); else return (T*)AlignValue( &m_Memory[0], nAlignment ); }
const T* Base() const { if ( nAlignment == 0 ) return (T*)(&m_Memory[0]); else return (T*)AlignValue( &m_Memory[0], nAlignment ); }
// element access
T& operator[]( int i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
const T& operator[]( int i ) const { Assert( IsIdxValid(i) ); return Base()[i]; }
T& Element( int i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
const T& Element( int i ) const { Assert( IsIdxValid(i) ); return Base()[i]; }
// Attaches the buffer to external memory....
void SetExternalBuffer( T* pMemory, int numElements ) { Assert( 0 ); }
// Size
int NumAllocated() const { return SIZE; }
int Count() const { return SIZE; }
// Grows the memory, so that at least allocated + num elements are allocated
void Grow( int num = 1 ) { Assert( 0 ); }
// Makes sure we've got at least this much memory
void EnsureCapacity( int num ) { Assert( num <= SIZE ); }
// Memory deallocation
void Purge() {}
// Purge all but the given number of elements (NOT IMPLEMENTED IN CUtlMemoryFixed)
void Purge( int numElements ) { Assert( 0 ); }
// is the memory externally allocated?
bool IsExternallyAllocated() const { return false; }
// Set the size by which the memory grows
void SetGrowSize( int size ) {}
class Iterator_t
{
public:
Iterator_t( int i ) : index( i ) {}
int index;
bool operator==( const Iterator_t it ) const { return index == it.index; }
bool operator!=( const Iterator_t it ) const { return index != it.index; }
};
Iterator_t First() const { return Iterator_t( IsIdxValid( 0 ) ? 0 : InvalidIndex() ); }
Iterator_t Next( const Iterator_t &it ) const { return Iterator_t( IsIdxValid( it.index + 1 ) ? it.index + 1 : InvalidIndex() ); }
int GetIndex( const Iterator_t &it ) const { return it.index; }
bool IsIdxAfter( int i, const Iterator_t &it ) const { return i > it.index; }
bool IsValidIterator( const Iterator_t &it ) const { return IsIdxValid( it.index ); }
Iterator_t InvalidIterator() const { return Iterator_t( InvalidIndex() ); }
private:
char m_Memory[ SIZE*sizeof(T) + nAlignment ];
};
//-----------------------------------------------------------------------------
// 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 )
{
swap( m_nGrowSize, mem.m_nGrowSize );
swap( m_pMemory, mem.m_pMemory );
swap( m_nAllocationCount, mem.m_nAllocationCount );
}
//-----------------------------------------------------------------------------
// Switches the buffer from an external memory buffer to a reallocatable buffer
//-----------------------------------------------------------------------------
template< class T, class I >
void CUtlMemory<T,I>::ConvertToGrowableMemory( int nGrowSize )
{
if ( !IsExternallyAllocated() )
return;
m_nGrowSize = nGrowSize;
if (m_nAllocationCount)
{
UTLMEMORY_TRACK_ALLOC();
MEM_ALLOC_CREDIT_CLASS();
int nNumBytes = m_nAllocationCount * sizeof(T);
T *pMemory = (T*)malloc( nNumBytes );
memcpy( pMemory, m_pMemory, nNumBytes );
m_pMemory = pMemory;
}
else
{
m_pMemory = NULL;
}
}
//-----------------------------------------------------------------------------
// Attaches the buffer to external memory....
//-----------------------------------------------------------------------------
template< class T, class I >
void CUtlMemory<T,I>::SetExternalBuffer( T* pMemory, int numElements )
{
// Blow away any existing allocated memory
Purge();
m_pMemory = pMemory;
m_nAllocationCount = numElements;
// Indicate that we don't own the memory
m_nGrowSize = EXTERNAL_BUFFER_MARKER;
}
template< class T, class I >
void CUtlMemory<T,I>::SetExternalBuffer( const T* pMemory, int numElements )
{
// Blow away any existing allocated memory
Purge();
m_pMemory = const_cast<T*>( pMemory );
m_nAllocationCount = numElements;
// Indicate that we don't own the memory
m_nGrowSize = EXTERNAL_CONST_BUFFER_MARKER;
}
template< class T, class I >
void CUtlMemory<T,I>::AssumeMemory( T* pMemory, int numElements )
{
// Blow away any existing allocated memory
Purge();
// Simply take the pointer but don't mark us as external
m_pMemory = pMemory;
m_nAllocationCount = numElements;
}
//-----------------------------------------------------------------------------
// element access
//-----------------------------------------------------------------------------
template< class T, class I >
inline T& CUtlMemory<T,I>::operator[]( I i )
{
Assert( !IsReadOnly() );
Assert( IsIdxValid(i) );
return m_pMemory[i];
}
template< class T, class I >
inline const T& CUtlMemory<T,I>::operator[]( I i ) const
{
Assert( IsIdxValid(i) );
return m_pMemory[i];
}
template< class T, class I >
inline T& CUtlMemory<T,I>::Element( I i )
{
Assert( !IsReadOnly() );
Assert( IsIdxValid(i) );
return m_pMemory[i];
}
template< class T, class I >
inline const T& CUtlMemory<T,I>::Element( I i ) const
{
Assert( IsIdxValid(i) );
return m_pMemory[i];
}
//-----------------------------------------------------------------------------
// is the memory externally allocated?
//-----------------------------------------------------------------------------
template< class T, class I >
bool CUtlMemory<T,I>::IsExternallyAllocated() const
{
return (m_nGrowSize < 0);
}
//-----------------------------------------------------------------------------
// is the memory read only?
//-----------------------------------------------------------------------------
template< class T, class I >
bool CUtlMemory<T,I>::IsReadOnly() const
{
return (m_nGrowSize == EXTERNAL_CONST_BUFFER_MARKER);
}
template< class T, class I >
void CUtlMemory<T,I>::SetGrowSize( int nSize )
{
Assert( !IsExternallyAllocated() );
Assert( nSize >= 0 );
m_nGrowSize = nSize;
ValidateGrowSize();
}
//-----------------------------------------------------------------------------
// Gets the base address (can change when adding elements!)
//-----------------------------------------------------------------------------
template< class T, class I >
inline T* CUtlMemory<T,I>::Base()
{
Assert( !IsReadOnly() );
return m_pMemory;
}
template< class T, class I >
inline const T *CUtlMemory<T,I>::Base() const
{
return m_pMemory;
}
//-----------------------------------------------------------------------------
// Size
//-----------------------------------------------------------------------------
template< class T, class I >
inline int CUtlMemory<T,I>::NumAllocated() const
{
return m_nAllocationCount;
}
template< class T, class I >
inline int CUtlMemory<T,I>::Count() const
{
return m_nAllocationCount;
}
//-----------------------------------------------------------------------------
// Is element index valid?
//-----------------------------------------------------------------------------
template< class T, class I >
inline bool CUtlMemory<T,I>::IsIdxValid( I i ) const
{
return ( ((int) i) >= 0 ) && ( ((int) i) < 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();
m_nAllocationCount = UtlMemory_CalcNewAllocationCount( m_nAllocationCount, m_nGrowSize, nAllocationRequested, sizeof(T) );
// if m_nAllocationRequested wraps index type I, recalculate
if ( ( int )( I )m_nAllocationCount < nAllocationRequested )
{
if ( ( int )( I )m_nAllocationCount == 0 && ( int )( I )( m_nAllocationCount - 1 ) >= nAllocationRequested )
{
--m_nAllocationCount; // 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 )m_nAllocationCount < nAllocationRequested )
{
m_nAllocationCount = ( m_nAllocationCount + nAllocationRequested ) / 2;
}
}
}
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;
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 ( 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*)_aligned_realloc( 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*)_aligned_malloc( 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 ( 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*)_aligned_realloc( CUtlMemory<T>::m_pMemory, CUtlMemory<T>::m_nAllocationCount * sizeof(T), nAlignment );
}
else
{
MEM_ALLOC_CREDIT_CLASS();
CUtlMemory<T>::m_pMemory = (T*)_aligned_malloc( CUtlMemory<T>::m_nAllocationCount * sizeof(T), nAlignment );
}
}
//-----------------------------------------------------------------------------
// Memory deallocation
//-----------------------------------------------------------------------------
template< class T, int nAlignment >
void CUtlMemoryAligned<T, nAlignment>::Purge()
{
if ( !IsExternallyAllocated() )
{
if ( CUtlMemory<T>::m_pMemory )
{
UTLMEMORY_TRACK_FREE();
_aligned_free( CUtlMemory<T>::m_pMemory );
CUtlMemory<T>::m_pMemory = 0;
}
CUtlMemory<T>::m_nAllocationCount = 0;
}
}
#include "tier0/memdbgoff.h"
#endif // UTLMEMORY_H

725
public/tier1/utlmultilist.h Normal file
View File

@ -0,0 +1,725 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Multiple linked list container class
//
// $Revision: $
// $NoKeywords: $
//=============================================================================//
#ifndef UTLMULTILIST_H
#define UTLMULTILIST_H
#ifdef _WIN32
#pragma once
#endif
#include "utllinkedlist.h"
// memdbgon must be the last include file in a .h file!!!
#include "tier0/memdbgon.h"
// This is a useful macro to iterate from head to tail in a linked list.
#define FOR_EACH_LL( listName, iteratorName ) \
for( int iteratorName=listName.Head(); iteratorName != listName.InvalidIndex(); iteratorName = listName.Next( iteratorName ) )
//-----------------------------------------------------------------------------
// class 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
{
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 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:
// 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;
};
// 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); }
CUtlMemory<ListElem_t> m_Memory;
CUtlLinkedList<List_t, I> m_List;
I* m_pElementList;
I m_FirstFree;
I m_TotalElements;
I m_MaxElementIndex; // The number allocated
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>::IsValidIndex( I i ) const
{
return (i < m_MaxElementIndex) && (i >= 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
{
return (i < m_MaxElementIndex) && (i >= 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())
{
// 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();
}
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();
// 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();
// 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();
// 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();
// 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

624
public/tier1/utlntree.h Normal file
View File

@ -0,0 +1,624 @@
//========= Copyright <20> 1996-2005, 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((ListElem_t *)pMemory, memsize/sizeof(ListElem_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

View File

@ -0,0 +1,165 @@
//===== Copyright <20> 1996-2006, 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

View File

@ -0,0 +1,198 @@
//========= Copyright <20> 1996-2005, 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

114
public/tier1/utlqueue.h Normal file
View File

@ -0,0 +1,114 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef UTLQUEUE_H
#define UTLQUEUE_H
#ifdef _WIN32
#pragma once
#endif
#include "utlvector.h"
// T is the type stored in the 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();
// put a new item on the stack
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

1557
public/tier1/utlrbtree.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,334 @@
//====== Copyright <20> 1996-2007, 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

331
public/tier1/utlstack.h Normal file
View File

@ -0,0 +1,331 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
// A stack based on a growable array
//=============================================================================//
#ifndef UTLSTACK_H
#define UTLSTACK_H
#include <assert.h>
#include <string.h>
#include "utlmemory.h"
//-----------------------------------------------------------------------------
// The CUtlStack class:
// A growable stack class which doubles in size by default.
// It will always keep all elements consecutive in memory, and may move the
// elements around in memory (via a realloc) when elements are pushed or
// popped. Clients should therefore refer to the elements of the stack
// by index (they should *never* maintain pointers to elements in the stack).
//-----------------------------------------------------------------------------
template< class T, class M = CUtlMemory< T > >
class CUtlStack
{
public:
// constructor, destructor
CUtlStack( int growSize = 0, int initSize = 0 );
~CUtlStack();
void CopyFrom( const CUtlStack<T, M> &from );
// element access
T& operator[]( int i );
T const& operator[]( int i ) const;
T& Element( int i );
T const& Element( int i ) const;
// Gets the base address (can change when adding elements!)
T* Base();
T const* Base() const;
// Looks at the stack top
T& Top();
T const& Top() const;
// Size
int Count() const;
// Is element index valid?
bool IsIdxValid( int i ) const;
// Adds an element, uses default constructor
int Push();
// Adds an element, uses copy constructor
int Push( T const& src );
// Pops the stack
void Pop();
void Pop( T& oldTop );
void PopMultiple( int num );
// Makes sure we have enough memory allocated to store a requested # of elements
void EnsureCapacity( int num );
// Clears the stack, no deallocation
void Clear();
// Memory deallocation
void Purge();
private:
// Grows the stack allocation
void GrowStack();
// For easier access to the elements through the debugger
void ResetDbgInfo();
M m_Memory;
int m_Size;
// For easier access to the elements through the debugger
T* m_pElements;
};
//-----------------------------------------------------------------------------
// For easier access to the elements through the debugger
//-----------------------------------------------------------------------------
template< class T, class M >
inline void CUtlStack<T,M>::ResetDbgInfo()
{
m_pElements = m_Memory.Base();
}
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
template< class T, class M >
CUtlStack<T,M>::CUtlStack( int growSize, int initSize ) :
m_Memory(growSize, initSize), m_Size(0)
{
ResetDbgInfo();
}
template< class T, class M >
CUtlStack<T,M>::~CUtlStack()
{
Purge();
}
//-----------------------------------------------------------------------------
// copy into
//-----------------------------------------------------------------------------
template< class T, class M >
void CUtlStack<T,M>::CopyFrom( const CUtlStack<T, M> &from )
{
Purge();
EnsureCapacity( from.Count() );
for ( int i = 0; i < from.Count(); i++ )
{
Push( from[i] );
}
}
//-----------------------------------------------------------------------------
// element access
//-----------------------------------------------------------------------------
template< class T, class M >
inline T& CUtlStack<T,M>::operator[]( int i )
{
assert( IsIdxValid(i) );
return m_Memory[i];
}
template< class T, class M >
inline T const& CUtlStack<T,M>::operator[]( int i ) const
{
assert( IsIdxValid(i) );
return m_Memory[i];
}
template< class T, class M >
inline T& CUtlStack<T,M>::Element( int i )
{
assert( IsIdxValid(i) );
return m_Memory[i];
}
template< class T, class M >
inline T const& CUtlStack<T,M>::Element( int i ) const
{
assert( IsIdxValid(i) );
return m_Memory[i];
}
//-----------------------------------------------------------------------------
// Gets the base address (can change when adding elements!)
//-----------------------------------------------------------------------------
template< class T, class M >
inline T* CUtlStack<T,M>::Base()
{
return m_Memory.Base();
}
template< class T, class M >
inline T const* CUtlStack<T,M>::Base() const
{
return m_Memory.Base();
}
//-----------------------------------------------------------------------------
// Returns the top of the stack
//-----------------------------------------------------------------------------
template< class T, class M >
inline T& CUtlStack<T,M>::Top()
{
assert( m_Size > 0 );
return Element(m_Size-1);
}
template< class T, class M >
inline T const& CUtlStack<T,M>::Top() const
{
assert( m_Size > 0 );
return Element(m_Size-1);
}
//-----------------------------------------------------------------------------
// Size
//-----------------------------------------------------------------------------
template< class T, class M >
inline int CUtlStack<T,M>::Count() const
{
return m_Size;
}
//-----------------------------------------------------------------------------
// Is element index valid?
//-----------------------------------------------------------------------------
template< class T, class M >
inline bool CUtlStack<T,M>::IsIdxValid( int i ) const
{
return (i >= 0) && (i < m_Size);
}
//-----------------------------------------------------------------------------
// Grows the stack
//-----------------------------------------------------------------------------
template< class T, class M >
void CUtlStack<T,M>::GrowStack()
{
if (m_Size >= m_Memory.NumAllocated())
m_Memory.Grow();
++m_Size;
ResetDbgInfo();
}
//-----------------------------------------------------------------------------
// Makes sure we have enough memory allocated to store a requested # of elements
//-----------------------------------------------------------------------------
template< class T, class M >
void CUtlStack<T,M>::EnsureCapacity( int num )
{
m_Memory.EnsureCapacity(num);
ResetDbgInfo();
}
//-----------------------------------------------------------------------------
// Adds an element, uses default constructor
//-----------------------------------------------------------------------------
template< class T, class M >
int CUtlStack<T,M>::Push()
{
GrowStack();
Construct( &Element(m_Size-1) );
return m_Size - 1;
}
//-----------------------------------------------------------------------------
// Adds an element, uses copy constructor
//-----------------------------------------------------------------------------
template< class T, class M >
int CUtlStack<T,M>::Push( T const& src )
{
GrowStack();
CopyConstruct( &Element(m_Size-1), src );
return m_Size - 1;
}
//-----------------------------------------------------------------------------
// Pops the stack
//-----------------------------------------------------------------------------
template< class T, class M >
void CUtlStack<T,M>::Pop()
{
assert( m_Size > 0 );
Destruct( &Element(m_Size-1) );
--m_Size;
}
template< class T, class M >
void CUtlStack<T,M>::Pop( T& oldTop )
{
assert( m_Size > 0 );
oldTop = Top();
Pop();
}
template< class T, class M >
void CUtlStack<T,M>::PopMultiple( int num )
{
assert( m_Size >= num );
for ( int i = 0; i < num; ++i )
Destruct( &Element( m_Size - i - 1 ) );
m_Size -= num;
}
//-----------------------------------------------------------------------------
// Element removal
//-----------------------------------------------------------------------------
template< class T, class M >
void CUtlStack<T,M>::Clear()
{
for (int i = m_Size; --i >= 0; )
Destruct(&Element(i));
m_Size = 0;
}
//-----------------------------------------------------------------------------
// Memory deallocation
//-----------------------------------------------------------------------------
template< class T, class M >
void CUtlStack<T,M>::Purge()
{
Clear();
m_Memory.Purge( );
ResetDbgInfo();
}
#endif // UTLSTACK_H

160
public/tier1/utlstring.h Normal file
View File

@ -0,0 +1,160 @@
//====== Copyright <20> 1996-2004, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#ifndef UTLSTRING_H
#define UTLSTRING_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/utlmemory.h"
//-----------------------------------------------------------------------------
// 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;
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;
}
//-----------------------------------------------------------------------------
// Simple string class.
// NOTE: This is *not* optimal! Use in tools, but not runtime code
//-----------------------------------------------------------------------------
class CUtlString
{
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 );
// 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 )
void SetLength( int nLen );
char *Get();
// 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 ); }
CUtlString &operator+=( const CUtlString &rhs );
CUtlString &operator+=( const char *rhs );
CUtlString &operator+=( char c );
CUtlString &operator+=( int rhs );
CUtlString &operator+=( double rhs );
int Format( const char *pFormat, ... );
private:
CUtlBinaryBlock m_Storage;
};
//-----------------------------------------------------------------------------
// Inline methods
//-----------------------------------------------------------------------------
inline bool CUtlString::IsEmpty() const
{
return Length() == 0;
}
#endif // UTLSTRING_H

261
public/tier1/utlsymbol.h Normal file
View File

@ -0,0 +1,261 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: Defines a symbol table
//
// $Header: $
// $NoKeywords: $
//===========================================================================//
#ifndef UTLSYMBOL_H
#define UTLSYMBOL_H
#ifdef _WIN32
#pragma once
#endif
#include "tier0/threadtools.h"
#include "tier1/utlrbtree.h"
#include "tier1/utlvector.h"
#include "tier1/stringpool.h"
//-----------------------------------------------------------------------------
// forward declarations
//-----------------------------------------------------------------------------
class CUtlSymbolTable;
class CUtlSymbolTableMT;
//-----------------------------------------------------------------------------
// This is a symbol, which is a easier way of dealing with strings.
//-----------------------------------------------------------------------------
typedef unsigned short UtlSymId_t;
#define UTL_INVAL_SYMBOL ((UtlSymId_t)~0)
class CUtlSymbol
{
public:
// constructor, destructor
CUtlSymbol() : m_Id(UTL_INVAL_SYMBOL) {}
CUtlSymbol( UtlSymId_t id ) : m_Id(id) {}
CUtlSymbol( const char* pStr );
CUtlSymbol( CUtlSymbol const& sym ) : m_Id(sym.m_Id) {}
// operator=
CUtlSymbol& operator=( CUtlSymbol const& src ) { m_Id = src.m_Id; return *this; }
// operator==
bool operator==( CUtlSymbol const& src ) const { return m_Id == src.m_Id; }
bool operator==( const char* pStr ) const;
// Is valid?
bool IsValid() const { return m_Id != UTL_INVAL_SYMBOL; }
// Gets at the symbol
operator UtlSymId_t const() 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.LockForWrite();
CUtlSymbol result = CUtlSymbolTable::Find( pString );
m_lock.UnlockWrite();
return result;
}
const char* String( CUtlSymbol id ) const
{
m_lock.LockForRead();
const char *pszResult = CUtlSymbolTable::String( id );
m_lock.UnlockRead();
return pszResult;
}
private:
mutable CThreadSpinRWLock m_lock;
};
//-----------------------------------------------------------------------------
// CUtlFilenameSymbolTable:
// description:
// This class defines a symbol table of individual filenames, stored more
// efficiently than a standard symbol table. Internally filenames are broken
// up into file and path entries, and a file handle class allows convenient
// access to these.
//-----------------------------------------------------------------------------
// The handle is a CUtlSymbol for the dirname and the same for the filename, the accessor
// copies them into a static char buffer for return.
typedef void* FileNameHandle_t;
// Symbol table for more efficiently storing filenames by breaking paths and filenames apart.
// Refactored from BaseFileSystem.h
class CUtlFilenameSymbolTable
{
// Internal representation of a FileHandle_t
// If we get more than 64K filenames, we'll have to revisit...
// Right now CUtlSymbol is a short, so this packs into an int/void * pointer size...
struct FileNameHandleInternal_t
{
FileNameHandleInternal_t()
{
path = 0;
file = 0;
}
// Part before the final '/' character
unsigned short path;
// Part after the final '/', including extension
unsigned short file;
};
public:
FileNameHandle_t FindOrAddFileName( const char *pFileName );
FileNameHandle_t FindFileName( const char *pFileName );
int PathIndex(const FileNameHandle_t &handle) { return (( const FileNameHandleInternal_t * )&handle)->path; }
bool String( const FileNameHandle_t& handle, char *buf, int buflen );
void RemoveAll();
void SpewStrings();
private:
CCountedStringPool m_StringPool;
mutable CThreadSpinRWLock m_lock;
};
#endif // UTLSYMBOL_H

794
public/tier1/utlvector.h Normal file
View File

@ -0,0 +1,794 @@
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======//
//
// Purpose:
//
// $NoKeywords: $
//
// A growable array class that maintains a free list and keeps elements
// in the same location
//=============================================================================//
#ifndef UTLVECTOR_H
#define UTLVECTOR_H
#ifdef _WIN32
#pragma once
#endif
#include <string.h>
#include "tier0/platform.h"
#include "tier0/dbg.h"
#include "tier0/threadtools.h"
#include "tier1/utlmemory.h"
#include "tier1/utlblockmemory.h"
#include "tier1/strtools.h"
#define FOR_EACH_VEC( vecName, iteratorName ) \
for ( int iteratorName = 0; iteratorName < vecName.Count(); iteratorName++ )
//-----------------------------------------------------------------------------
// The CUtlVector class:
// A growable array class which doubles in size by default.
// It will always keep all elements consecutive in memory, and may move the
// elements around in memory (via a PvRealloc) when elements are inserted or
// removed. Clients should therefore refer to the elements of the vector
// by index (they should *never* maintain pointers to elements in the vector).
//-----------------------------------------------------------------------------
template< class T, class A = CUtlMemory<T> >
class CUtlVector
{
typedef A CAllocator;
public:
typedef T ElemType_t;
// constructor, destructor
CUtlVector( int growSize = 0, int initSize = 0 );
CUtlVector( T* pMemory, int allocationCount, int numElements = 0 );
~CUtlVector();
// Copy the array.
CUtlVector<T, A>& operator=( const CUtlVector<T, A> &other );
// element access
T& operator[]( int i );
const T& operator[]( int i ) const;
T& Element( int i );
const T& Element( int i ) const;
T& Head();
const T& Head() const;
T& Tail();
const T& Tail() const;
// Gets the base address (can change when adding elements!)
T* Base() { return m_Memory.Base(); }
const T* Base() const { return m_Memory.Base(); }
// Returns the number of elements in the vector
// 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 );
// 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
void RemoveMultiple( int elem, int num ); // preserves order, shifts elements
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:
// Can't copy this unless we explicitly do it!
CUtlVector( CUtlVector const& vec ) { Assert(0); }
// Grows the vector
void GrowVector( int num = 1 );
// Shifts elements....
void ShiftElementsRight( int elem, int num = 1 );
void ShiftElementsLeft( int elem, int num = 1 );
CAllocator m_Memory;
int m_Size;
// 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();
}
};
// this is kind of ugly, but until C++ gets templatized typedefs in C++0x, it's our only choice
template < class T >
class CUtlBlockVector : public CUtlVector< T, CUtlBlockMemory< T, int > >
{
public:
CUtlBlockVector( int growSize = 0, int initSize = 0 )
: CUtlVector< T, CUtlBlockMemory< T, int > >( growSize, initSize ) {}
};
//-----------------------------------------------------------------------------
// The 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
CUtlVectorMT( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
CUtlVectorMT( typename BaseClass::ElemType_t* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
};
//-----------------------------------------------------------------------------
// The CUtlVectorFixed class:
// A array class with a fixed allocation scheme
//-----------------------------------------------------------------------------
template< class T, size_t MAX_SIZE >
class CUtlVectorFixed : public CUtlVector< T, CUtlMemoryFixed<T, MAX_SIZE > >
{
typedef CUtlVector< T, CUtlMemoryFixed<T, MAX_SIZE > > BaseClass;
public:
// constructor, destructor
CUtlVectorFixed( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
CUtlVectorFixed( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
};
//-----------------------------------------------------------------------------
// The CUtlVectorFixed class:
// A array class with a fixed allocation scheme
//-----------------------------------------------------------------------------
template< class T, size_t MAX_SIZE >
class CUtlVectorFixedGrowable : public CUtlVector< T, CUtlMemoryFixedGrowable<T, MAX_SIZE > >
{
typedef CUtlVector< T, CUtlMemoryFixedGrowable<T, MAX_SIZE > > BaseClass;
public:
// constructor, destructor
CUtlVectorFixedGrowable( int growSize = 0 ) : BaseClass( growSize, MAX_SIZE ) {}
};
//-----------------------------------------------------------------------------
// The CCopyableUtlVector class:
// A array class that allows copy construction (so you can nest a CUtlVector inside of another one of our containers)
// WARNING - this class lets you copy construct which can be an expensive operation if you don't carefully control when it happens
// Only use this when nesting a CUtlVector() inside of another one of our container classes (i.e a CUtlMap)
//-----------------------------------------------------------------------------
template< class T >
class CCopyableUtlVector : public CUtlVector< T, CUtlMemory<T> >
{
typedef CUtlVector< T, CUtlMemory<T> > BaseClass;
public:
CCopyableUtlVector( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
CCopyableUtlVector( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
virtual ~CCopyableUtlVector() {}
CCopyableUtlVector( CCopyableUtlVector const& vec ) { CopyArray( vec.Base(), vec.Count() ); }
};
//-----------------------------------------------------------------------------
// 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 )
{
return m_Memory[ i ];
}
template< typename T, class A >
inline const T& CUtlVector<T, A>::operator[]( int i ) const
{
return m_Memory[ i ];
}
template< typename T, class A >
inline T& CUtlVector<T, A>::Element( int i )
{
return m_Memory[ i ];
}
template< typename T, class A >
inline const T& CUtlVector<T, A>::Element( int i ) const
{
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 )
{
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>::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 );
swap( m_Size, vec.m_Size );
swap( m_pElements, vec.m_pElements );
}
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)
{
memcpy( &Element(elem), &Element(m_Size-1), sizeof(T) );
--m_Size;
}
}
template< typename T, class A >
void CUtlVector<T, A>::Remove( int elem )
{
Destruct( &Element(elem) );
ShiftElementsLeft(elem);
--m_Size;
}
template< typename T, class A >
bool CUtlVector<T, A>::FindAndRemove( const T& src )
{
int elem = Find( src );
if ( elem != -1 )
{
Remove( elem );
return true;
}
return false;
}
template< typename T, class A >
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>::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
#endif // CCVECTOR_H