1
0
mirror of https://github.com/alliedmodders/hl2sdk.git synced 2024-12-23 01:59:43 +08:00

Added SDK changes for Dark Messiah engine.

This commit is contained in:
Scott Ehlert 2009-02-17 03:02:00 -06:00
parent f57b1bd008
commit 292352ea2d
21 changed files with 457 additions and 1645 deletions

Binary file not shown.

View File

@ -1,18 +1,9 @@
*********
* About *
*********
This version of the Source/Half-Life 2 SDK attempts to provide support for GCC 4.x and remove as many
warnings as possible when compiling under Windows or Linux. In addition, the -fpermissive option has
been removed from the Linux makefiles and -Wall has been added.
This version of the Source SDK is meant only for compiling server plugins for
the engine that runs Might and Magic: Dark Messiah Multiplayer. An official SDK
is not available and will likely never be released.
*********
* Notes *
*********
1. The file "Makefile.mod" located in the linux_sdk directory has been renamed to "Makefile.game" in
order to avoid potential conflicts with the Modula-2 compiler. GNU Make may issue an error about the
file with its original name and try to execute m2c (the Modula-2 compiler program).
2. Makefiles for choreoobjects_i486.a, mathlib_i486.a, and tier1_i486.a have been added in the linux_sdk
directory to ease compiling of these static libraries on Linux if it ever becomes necessary.
3. The SDK does not currently compile with GCC 4.2. This will be addressed in the future.
This is a modified version of the Episode One SDK. Changes to it were reverse
engineered from the Dark Messiah engine and game binaries.

View File

@ -72,8 +72,6 @@ class IServerEntity;
#define FL_EDICT_CHANGED (1<<0) // Game DLL sets this when the entity state changes
// Mutually exclusive with FL_EDICT_PARTIAL_CHANGE.
#define FL_EDICT_FREE (1<<1) // this edict if free for reuse
#define FL_EDICT_FULL (1<<2) // this is a full server entity
@ -82,82 +80,10 @@ class IServerEntity;
#define FL_EDICT_DONTSEND (1<<4) // don't transmit this entity
#define FL_EDICT_PVSCHECK (1<<5) // always transmit entity, but cull against PVS
// Used by local network backdoor.
#define FL_EDICT_PENDING_DORMANT_CHECK (1<<6)
// This is always set at the same time EFL_DIRTY_PVS_INFORMATION is set, but it
// gets cleared in a different place.
#define FL_EDICT_DIRTY_PVS_INFORMATION (1<<7)
// This is used internally to edict_t to remember that it's carrying a
// "full change list" - all its properties might have changed their value.
#define FL_FULL_EDICT_CHANGED (1<<8)
// Max # of variable changes we'll track in an entity before we treat it
// like they all changed.
#define MAX_CHANGE_OFFSETS 19
#define MAX_EDICT_CHANGE_INFOS 100
class CEdictChangeInfo
{
public:
// Edicts remember the offsets of properties that change
unsigned short m_ChangeOffsets[MAX_CHANGE_OFFSETS];
unsigned short m_nChangeOffsets;
};
// Shared between engine and game DLL.
class CSharedEdictChangeInfo
{
public:
CSharedEdictChangeInfo()
{
m_iSerialNumber = 1;
}
// Matched against edict_t::m_iChangeInfoSerialNumber to determine if its
// change info is valid.
unsigned short m_iSerialNumber;
CEdictChangeInfo m_ChangeInfos[MAX_EDICT_CHANGE_INFOS];
unsigned short m_nChangeInfos; // How many are in use this frame.
};
extern CSharedEdictChangeInfo *g_pSharedChangeInfo;
class IChangeInfoAccessor
{
public:
inline void SetChangeInfo( unsigned short info )
{
m_iChangeInfo = info;
}
inline void SetChangeInfoSerialNumber( unsigned short sn )
{
m_iChangeInfoSerialNumber = sn;
}
inline unsigned short GetChangeInfo() const
{
return m_iChangeInfo;
}
inline unsigned short GetChangeInfoSerialNumber() const
{
return m_iChangeInfoSerialNumber;
}
private:
unsigned short m_iChangeInfo;
unsigned short m_iChangeInfoSerialNumber;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
// NOTE: YOU CAN'T CHANGE THE LAYOUT OR SIZE OF CBASEEDICT AND REMAIN COMPATIBLE WITH HL2_VC6!!!!!
class CBaseEdict
{
public:
@ -183,24 +109,14 @@ public:
bool HasStateChanged() const;
void ClearStateChanged();
void StateChanged();
void StateChanged( unsigned short offset );
void ClearTransmitState();
void SetChangeInfo( unsigned short info );
void SetChangeInfoSerialNumber( unsigned short sn );
unsigned short GetChangeInfo() const;
unsigned short GetChangeInfoSerialNumber() const;
public:
// NOTE: this is in the edict instead of being accessed by a virtual because the engine needs fast access to it.
// NOTE: YOU CAN'T CHANGE THE LAYOUT OR SIZE OF CBASEEDICT AND REMAIN COMPATIBLE WITH HL2_VC6!!!!!
#ifdef _XBOX
unsigned short m_fStateFlags;
#else
int m_fStateFlags;
#endif
// NOTE: this is in the edict instead of being accessed by a virtual because the engine needs fast access to it.
int m_NetworkSerialNumber; // Game DLL sets this when it gets a serial number for its EHANDLE.
@ -212,18 +128,6 @@ protected:
IServerUnknown *m_pUnk;
public:
IChangeInfoAccessor *GetChangeAccessor(); // The engine implements this and the game .dll implements as
const IChangeInfoAccessor *GetChangeAccessor() const; // The engine implements this and the game .dll implements as
// as callback through to the engine!!!
// NOTE: YOU CAN'T CHANGE THE LAYOUT OR SIZE OF CBASEEDICT AND REMAIN COMPATIBLE WITH HL2_VC6!!!!!
// This breaks HL2_VC6!!!!!
// References a CEdictChangeInfo with a list of modified network props.
//unsigned short m_iChangeInfo;
//unsigned short m_iChangeInfoSerialNumber;
friend void InitializeEntityDLLFields( edict_t *pEdict );
};
@ -253,73 +157,14 @@ inline bool CBaseEdict::HasStateChanged() const
inline void CBaseEdict::ClearStateChanged()
{
m_fStateFlags &= ~(FL_EDICT_CHANGED | FL_FULL_EDICT_CHANGED);
SetChangeInfoSerialNumber( 0 );
m_fStateFlags &= ~FL_EDICT_CHANGED;
}
inline void CBaseEdict::StateChanged()
{
// Note: this should only happen for properties in data tables that used some
// kind of pointer dereference. If the data is directly offsetable
m_fStateFlags |= (FL_EDICT_CHANGED | FL_FULL_EDICT_CHANGED);
SetChangeInfoSerialNumber( 0 );
}
inline void CBaseEdict::StateChanged( unsigned short offset )
{
if ( m_fStateFlags & FL_FULL_EDICT_CHANGED )
return;
m_fStateFlags |= FL_EDICT_CHANGED;
IChangeInfoAccessor *accessor = GetChangeAccessor();
if ( accessor->GetChangeInfoSerialNumber() == g_pSharedChangeInfo->m_iSerialNumber )
{
// Ok, I still own this one.
CEdictChangeInfo *p = &g_pSharedChangeInfo->m_ChangeInfos[accessor->GetChangeInfo()];
// Now add this offset to our list of changed variables.
for ( unsigned short i=0; i < p->m_nChangeOffsets; i++ )
if ( p->m_ChangeOffsets[i] == offset )
return;
if ( p->m_nChangeOffsets == MAX_CHANGE_OFFSETS )
{
// Invalidate our change info.
accessor->SetChangeInfoSerialNumber( 0 );
m_fStateFlags |= FL_FULL_EDICT_CHANGED; // So we don't get in here again.
}
else
{
p->m_ChangeOffsets[p->m_nChangeOffsets++] = offset;
}
}
else
{
if ( g_pSharedChangeInfo->m_nChangeInfos == MAX_EDICT_CHANGE_INFOS )
{
// Shucks.. have to mark the edict as fully changed because we don't have room to remember this change.
accessor->SetChangeInfoSerialNumber( 0 );
m_fStateFlags |= FL_FULL_EDICT_CHANGED;
}
else
{
// Get a new CEdictChangeInfo and fill it out.
accessor->SetChangeInfo( g_pSharedChangeInfo->m_nChangeInfos );
g_pSharedChangeInfo->m_nChangeInfos++;
accessor->SetChangeInfoSerialNumber( g_pSharedChangeInfo->m_iSerialNumber );
CEdictChangeInfo *p = &g_pSharedChangeInfo->m_ChangeInfos[accessor->GetChangeInfo()];
p->m_ChangeOffsets[0] = offset;
p->m_nChangeOffsets = 1;
}
}
}
inline void CBaseEdict::SetFree()
{
m_fStateFlags |= FL_EDICT_FREE;
@ -381,25 +226,6 @@ inline const char * CBaseEdict::GetClassName() const
return m_pNetworkable->GetClassName();
}
inline void CBaseEdict::SetChangeInfo( unsigned short info )
{
GetChangeAccessor()->SetChangeInfo( info );
}
inline void CBaseEdict::SetChangeInfoSerialNumber( unsigned short sn )
{
GetChangeAccessor()->SetChangeInfoSerialNumber( sn );
}
inline unsigned short CBaseEdict::GetChangeInfo() const
{
return GetChangeAccessor()->GetChangeInfo();
}
inline unsigned short CBaseEdict::GetChangeInfoSerialNumber() const
{
return GetChangeAccessor()->GetChangeInfoSerialNumber();
}
//-----------------------------------------------------------------------------
// Purpose: The engine's internal representation of an entity, including some
@ -424,5 +250,4 @@ inline ICollideable *edict_t::GetCollideable()
return NULL;
}
#endif // EDICT_H

View File

@ -75,8 +75,11 @@ class CStandardSendProxies;
abstract_class IVEngineServer
{
public:
// Tell engine to change level ( "changelevel s1\n" or "changelevel2 s1 s2\n" )
virtual void ChangeLevel( const char *s1, const char *s2 ) = 0;
// Tell engine to change level.
// changelevel s1 (multiplayer)
// changelevel2 s1 s2 bLongLoading (single player)
// changelevel3 s1 s2 video bLongLoading (single player)
virtual void ChangeLevel( const char *s1, const char *s2, const char *video = NULL, bool bLongLoading = false ) = 0;
// Ask engine whether the specified map is a valid map file (exists and has valid version number).
virtual int IsMapValid( const char *filename ) = 0;
@ -87,6 +90,8 @@ public:
// Is in Hammer editing mode?
virtual int IsInEditMode( void ) = 0;
virtual bool Unknown0( void ) = 0;
// Add to the server/client lookup/precache table, the specified string is given a unique index
// NOTE: The indices for PrecacheModel are 1 based
// a 0 returned from those methods indicates the model or sound was not correctly precached
@ -120,6 +125,8 @@ public:
virtual int GetPlayerUserId( const edict_t *e ) = 0;
virtual const char *GetPlayerNetworkIDString( const edict_t *e ) = 0;
virtual int Unknown1( void *a ) = 0;
// Return the current number of used edict slots
virtual int GetEntityCount( void ) = 0;
// Given an edict, returns the entity index
@ -137,6 +144,8 @@ public:
// Remove the specified edict and place back into the free edict list
virtual void RemoveEdict( edict_t *e ) = 0;
virtual void Unknown2( void *a ) = 0;
// Memory allocation for entity class data
virtual void *PvAllocEntPrivateData( long cb ) = 0;
virtual void FreeEntPrivateData( void *pEntity ) = 0;
@ -327,37 +336,13 @@ public:
// than a bunch of individual SetAreaPortalState calls.
virtual void SetAreaPortalStates( const int *portalNumbers, const int *isOpen, int nPortals ) = 0;
// Called when relevant edict state flags change.
virtual void NotifyEdictFlagsChange( int iEdict ) = 0;
// Only valid during CheckTransmit. Also, only the PVS, networked areas, and
// m_pTransmitInfo are valid in the returned strucutre.
virtual const CCheckTransmitInfo* GetPrevCheckTransmitInfo( edict_t *pPlayerEdict ) = 0;
virtual CSharedEdictChangeInfo* GetSharedEdictChangeInfo() = 0;
// Tells the engine we can immdiately re-use all edict indices
// even though we may not have waited enough time
virtual void AllowImmediateEdictReuse( ) = 0;
// Returns true if the engine is an internal build. i.e. is using the internal bugreporter.
virtual bool IsInternalBuild( void ) = 0;
virtual IChangeInfoAccessor *GetChangeAccessor( const edict_t *pEdict ) = 0;
// Call this to find out the value of a cvar on the client.
//
// It is an asynchronous query, and it will call IServerGameDLL::OnQueryCvarValueFinished when
// the value comes in from the client.
//
// Store the return value if you want to match this specific query to the OnQueryCvarValueFinished call.
// Returns InvalidQueryCvarCookie if the entity is invalid.
virtual QueryCvarCookie_t StartQueryCvarValue( edict_t *pPlayerEntity, const char *pName ) = 0;
virtual void Unknown3( void ) = 0;
virtual void *Unknown4( void *, void *) = 0;
virtual bool Unknown5( void ) = 0;
virtual void Unknown6( int ) = 0;
};
#define INTERFACEVERSION_SERVERGAMEDLL_VERSION_4 "ServerGameDLL004"
#define INTERFACEVERSION_SERVERGAMEDLL_VERSION_5 "ServerGameDLL005"
#define INTERFACEVERSION_SERVERGAMEDLL "ServerGameDLL006"
#define INTERFACEVERSION_SERVERGAMEDLL "ServerGameDLL004"
//-----------------------------------------------------------------------------
// Purpose: These are the interfaces that the game .dll exposes to the engine
@ -398,6 +383,9 @@ public:
// Called once during DLL shutdown
virtual void DLLShutdown( void ) = 0;
virtual int Unknown0 ( void ) = 0;
virtual int Unknown1 ( void ) = 0;
// Get the simulation interval (must be compiled with identical values into both client and game .dll for MOD!!!)
// Right now this is only requested at server startup time so it can't be changed on the fly, etc.
virtual float GetTickInterval( void ) const = 0;
@ -438,24 +426,15 @@ public:
// Hand over the StandardSendProxies in the game DLL's module.
virtual CStandardSendProxies* GetStandardSendProxies() = 0;
virtual void Unknown2( int, int, int, int ) = 0;
virtual void Unknown3( void ) = 0;
// Called once during startup for non-dedicated servers, after the game .dll has been loaded and after the client .dll has also been loaded
virtual void PostInit() = 0;
// Called once per frame even when no level is loaded...
virtual void Think( bool finalTick ) = 0;
virtual void GetSaveCommentEx( char *comment, int maxlength, float flMinutes, float flSeconds ) = 0;
#ifdef _XBOX
virtual void GetTitleName( const char *pMapName, char* pTitleBuff, int titleBuffSize ) = 0;
#endif
// * This function is new with version 6 of the interface.
//
// This is called when a query from IVEngineServer::StartQueryCvarValue is finished.
// iCookie is the value returned by IVEngineServer::StartQueryCvarValue.
// Added with version 2 of the interface.
virtual void OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue )
{
}
virtual void Unknown4( void * ) = 0;
};
//-----------------------------------------------------------------------------
@ -570,17 +549,6 @@ public:
// Call periodically to poll steam for a CSER connection
virtual void UpdateConnection( void ) = 0;
// If user has disabled stats tracking, do nothing
virtual bool IsGameStatsLoggingEnabled() = 0;
// Gets a non-personally identifiable unique ID for this steam user, used for tracking total gameplay time across
// multiple stats sessions, but isn't trackable back to their Steam account or id.
// Buffer should be 16 bytes, ID will come back as a hexadecimal string version of a GUID
virtual void GetPseudoUniqueId( char *buf, size_t bufsize ) = 0;
// For determining general % of users running using cyber cafe accounts...
virtual bool IsCyberCafeUser( void ) = 0;
};
#define INTERFACEVERSION_PLUGINHELPERSCHECK "PluginHelpersCheck001"

View File

@ -112,8 +112,6 @@ public:
// Retrieves list of all active sounds
virtual void GetActiveSounds( CUtlVector< SndInfo_t >& sndlist ) = 0;
virtual void PrecacheSentenceGroup( const char *pGroupName ) = 0;
};

View File

@ -141,12 +141,18 @@ public:
// Traces a ray against a particular entity
virtual void ClipRayToEntity( const Ray_t &ray, unsigned int fMask, IHandleEntity *pEnt, trace_t *pTrace ) = 0;
virtual void Unknown0( void *, void *, void *) = 0;
virtual void Unknown1( void *, void *, void *, void *, void *, void *, void *) = 0;
// Traces a ray against a particular entity
virtual void ClipRayToCollideable( const Ray_t &ray, unsigned int fMask, ICollideable *pCollide, trace_t *pTrace ) = 0;
// A version that simply accepts a ray (can work as a traceline or tracehull)
virtual void TraceRay( const Ray_t &ray, unsigned int fMask, ITraceFilter *pTraceFilter, trace_t *pTrace ) = 0;
virtual void Unknown2( void *, void *, void *, void *, void *) = 0;
// A version that sets up the leaf and entity lists and allows you to pass those in for collision.
virtual void SetupLeafAndEntityListRay( const Ray_t &ray, CTraceListData &traceData ) = 0;
virtual void SetupLeafAndEntityListBox( const Vector &vecBoxMin, const Vector &vecBoxMax, CTraceListData &traceData ) = 0;
@ -165,6 +171,8 @@ public:
// Same thing, but enumerate entitys within a box
virtual void EnumerateEntities( const Vector &vecAbsMins, const Vector &vecAbsMaxs, IEntityEnumerator *pEnumerator ) = 0;
virtual int Unknown3( void ) = 0;
// Convert a handle entity to a collideable. Useful inside enumer
virtual ICollideable *GetCollideable( IHandleEntity *pEntity ) = 0;

View File

@ -28,19 +28,7 @@ typedef enum
PLUGIN_STOP, // don't run the game dll function at all
} PLUGIN_RESULT;
typedef enum
{
eQueryCvarValueStatus_ValueIntact=0, // It got the value fine.
eQueryCvarValueStatus_CvarNotFound=1,
eQueryCvarValueStatus_NotACvar=2, // There's a ConCommand, but it's not a ConVar.
eQueryCvarValueStatus_CvarProtected=3 // The cvar was marked with FCVAR_SERVER_CAN_NOT_QUERY, so the server is not allowed to have its value.
} EQueryCvarValueStatus;
typedef int QueryCvarCookie_t;
#define InvalidQueryCvarCookie -1
#define INTERFACEVERSION_ISERVERPLUGINCALLBACKS_VERSION_1 "ISERVERPLUGINCALLBACKS001"
#define INTERFACEVERSION_ISERVERPLUGINCALLBACKS "ISERVERPLUGINCALLBACKS002"
#define INTERFACEVERSION_ISERVERPLUGINCALLBACKS "ISERVERPLUGINCALLBACKS001"
//-----------------------------------------------------------------------------
// Purpose: callbacks the engine exposes to the 3rd party plugins (ala MetaMod)
//-----------------------------------------------------------------------------
@ -99,13 +87,6 @@ public:
// A user has had their network id setup and validated
virtual PLUGIN_RESULT NetworkIDValidated( const char *pszUserName, const char *pszNetworkID ) = 0;
// This is called when a query from IServerPluginHelpers::StartQueryCvarValue is finished.
// iCookie is the value returned by IServerPluginHelpers::StartQueryCvarValue.
// Added with version 2 of the interface.
virtual void OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue )
{
}
};
#define INTERFACEVERSION_ISERVERPLUGINHELPERS "ISERVERPLUGINHELPERS001"
@ -139,15 +120,6 @@ public:
//
virtual void CreateMessage( edict_t *pEntity, DIALOG_TYPE type, KeyValues *data, IServerPluginCallbacks *plugin ) = 0;
virtual void ClientCommand( edict_t *pEntity, const char *cmd ) = 0;
// Call this to find out the value of a cvar on the client.
//
// It is an asynchronous query, and it will call IServerPluginCallbacks::OnQueryCvarValueFinished when
// the value comes in from the client.
//
// Store the return value if you want to match this specific query to the OnQueryCvarValueFinished call.
// Returns InvalidQueryCvarCookie if the entity is invalid.
virtual QueryCvarCookie_t StartQueryCvarValue( edict_t *pEntity, const char *pName ) = 0;
};
#endif //ISERVERPLUGIN_H

View File

@ -99,10 +99,6 @@ public:
// Gets a virtual terrain collision model (creates if necessary)
// NOTE: This may return NULL if the terrain model cannot be virtualized
virtual CPhysCollide *GetCollideForVirtualTerrain( const virtualterrainparams_t &params ) = 0;
virtual bool IsUsingFBTexture( const model_t *model ) const = 0;
virtual const model_t *FindOrLoadModel( const char *name ) const = 0;
};

View File

@ -32,6 +32,10 @@ typedef int FileFindHandle_t;
typedef void (*FileSystemLoggingFunc_t)( const char *fileName, const char *accessType );
typedef int WaitForResourcesHandle_t;
// 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;
#ifdef _XBOX
typedef void* HANDLE;
@ -86,104 +90,6 @@ enum FileWarningLevel_t
};
// In non-retail builds, enable the file blocking access tracking stuff...
#if defined( TRACK_BLOCKING_IO )
enum FileBlockingWarning_t
{
// Report how long synchronous i/o took to complete
FILESYSTEM_BLOCKING_SYNCHRONOUS = 0,
// Report how long async i/o took to complete if AsyncFileFinished caused it to load via "blocking" i/o
FILESYSTEM_BLOCKING_ASYNCHRONOUS_BLOCK,
// Report how long async i/o took to complete
FILESYSTEM_BLOCKING_ASYNCHRONOUS,
// Report how long the async "callback" took
FILESYSTEM_BLOCKING_CALLBACKTIMING,
FILESYSTEM_BLOCKING_NUMBINS,
};
#pragma pack(1)
class FileBlockingItem
{
public:
enum
{
FB_ACCESS_OPEN = 1,
FB_ACCESS_CLOSE = 2,
FB_ACCESS_READ = 3,
FB_ACCESS_WRITE = 4,
FB_ACCESS_APPEND = 5,
FB_ACCESS_SIZE = 6
};
FileBlockingItem() :
m_ItemType( (FileBlockingWarning_t)0 ),
m_flElapsed( 0.0f ),
m_nAccessType( 0 )
{
SetFileName( NULL );
}
FileBlockingItem( int type, char const *filename, float elapsed, int accessType ) :
m_ItemType( (FileBlockingWarning_t)type ),
m_flElapsed( elapsed ),
m_nAccessType( accessType )
{
SetFileName( filename );
}
void SetFileName( char const *filename )
{
if ( !filename )
{
m_szFilename[ 0 ] = 0;
return;
}
int len = Q_strlen( filename );
if ( len >= sizeof( m_szFilename ) )
{
Q_strncpy( m_szFilename, &filename[ len - sizeof( m_szFilename ) + 1 ], sizeof( m_szFilename ) );
}
else
{
Q_strncpy( m_szFilename, filename, sizeof( m_szFilename ) );
}
}
char const *GetFileName() const
{
return m_szFilename;
}
FileBlockingWarning_t m_ItemType;
float m_flElapsed;
byte m_nAccessType;
private:
char m_szFilename[ 32 ];
};
#pragma pack()
class IBlockingFileItemList
{
public:
// You can't call any of the below calls without locking first
virtual void LockMutex() = 0;
virtual void UnlockMutex() = 0;
virtual int First() const = 0;
virtual int Next( int i ) const = 0;
virtual int InvalidIndex() const = 0;
virtual const FileBlockingItem& Get( int index ) const = 0;
virtual void Reset() = 0;
};
#endif // TRACK_BLOCKING_IO
enum FilesystemMountRetval_t
{
FILESYSTEM_MOUNT_OK = 0,
@ -196,11 +102,6 @@ enum SearchPathAdd_t
PATH_ADD_TO_TAIL, // Last path searched
};
enum FilesystemOpenExFlags_t
{
FSOPEN_UNBUFFERED = ( 1 << 0 ),
};
#define FILESYSTEM_INVALID_HANDLE ( FileHandle_t )0
//-----------------------------------------------------------------------------
@ -554,77 +455,6 @@ public:
// Returns the file system statistics retreived by the implementation. Returns NULL if not supported.
virtual const FileSystemStatistics *GetFilesystemStatistics() = 0;
//--------------------------------------------------------
// Start of new functions after Lost Coast release (7/05)
//--------------------------------------------------------
virtual FileHandle_t OpenEx( const char *pFileName, const char *pOptions, unsigned flags = 0, const char *pathID = 0, char **ppszResolvedFilename = NULL ) = 0;
// Extended version of read provides more context to allow for more optimal reading
virtual int ReadEx( void* pOutput, int sizeDest, int size, FileHandle_t file ) = 0;
virtual int ReadFileEx( const char *pFileName, const char *pPath, void **ppBuf, bool bNullTerminate = false, bool bOptimalAlloc = false, int nMaxBytes = 0, int nStartingByte = 0, FSAllocFunc_t pfnAlloc = NULL ) = 0;
virtual FileNameHandle_t FindFileName( char const *pFileName ) = 0;
#if defined( TRACK_BLOCKING_IO )
virtual void EnableBlockingFileAccessTracking( bool state ) = 0;
virtual bool IsBlockingFileAccessEnabled() const = 0;
virtual IBlockingFileItemList *RetrieveBlockingFileAccessInfo() = 0;
#endif
virtual void PurgePreloadedData() = 0;
virtual void PreloadData() = 0;
// Fixme, we could do these via a string embedded into the compiled data, etc...
enum KeyValuesPreloadType_t
{
TYPE_VMT,
TYPE_SOUNDEMITTER,
TYPE_SOUNDSCAPE,
NUM_PRELOAD_TYPES
};
virtual void LoadCompiledKeyValues( KeyValuesPreloadType_t type, char const *archiveFile ) = 0;
// If the "PreloadedData" hasn't been purged, then this'll try and instance the KeyValues using the fast path of compiled keyvalues loaded during startup.
// Otherwise, it'll just fall through to the regular KeyValues loading routines
virtual KeyValues *LoadKeyValues( KeyValuesPreloadType_t type, char const *filename, char const *pPathID = 0 ) = 0;
virtual bool LoadKeyValues( KeyValues& head, KeyValuesPreloadType_t type, char const *filename, char const *pPathID = 0 ) = 0;
virtual bool ExtractRootKeyName( KeyValuesPreloadType_t type, char *outbuf, size_t bufsize, char const *filename, char const *pPathID = 0 ) = 0;
virtual FSAsyncStatus_t AsyncWrite(const char *pFileName, const void *pSrc, int nSrcBytes, bool bFreeMemory, bool bAppend = false, FSAsyncControl_t *pControl = NULL ) = 0;
// Async read functions with memory blame
FSAsyncStatus_t AsyncReadCreditAlloc( const FileAsyncRequest_t &request, const char *pszFile, int line, FSAsyncControl_t *phControl = NULL ) { return AsyncReadMultipleCreditAlloc( &request, 1, pszFile, line, phControl ); }
virtual FSAsyncStatus_t AsyncReadMultipleCreditAlloc( const FileAsyncRequest_t *pRequests, int nRequests, const char *pszFile, int line, FSAsyncControl_t *phControls = NULL ) = 0;
virtual bool GetFileTypeForFullPath( char const *pFullPath, wchar_t *buf, size_t bufSizeInBytes ) = 0;
//--------------------------------------------------------
//--------------------------------------------------------
virtual bool ReadToBuffer( FileHandle_t hFile, CUtlBuffer &buf, int nMaxBytes = 0, FSAllocFunc_t pfnAlloc = NULL ) = 0;
//--------------------------------------------------------
// Optimal IO operations
//--------------------------------------------------------
virtual bool GetOptimalIOConstraints( FileHandle_t hFile, unsigned *pOffsetAlign, unsigned *pSizeAlign, unsigned *pBufferAlign ) = 0;
inline unsigned GetOptimalReadSize( FileHandle_t hFile, unsigned nLogicalSize );
virtual void *AllocOptimalReadBuffer( FileHandle_t hFile, unsigned nSize = 0, unsigned nOffset = 0 ) = 0;
virtual void FreeOptimalReadBuffer( void * ) = 0;
//--------------------------------------------------------
//
//--------------------------------------------------------
virtual void BeginMapAccess() = 0;
virtual void EndMapAccess() = 0;
// Returns true on success, otherwise false if it can't be resolved
virtual bool FullPathToRelativePathEx( const char *pFullpath, const char *pPathId, char *pRelative, int maxlen ) = 0;
virtual int GetPathIndex( const FileNameHandle_t &handle ) = 0;
virtual long GetPathTime( const char *pPath, const char *pPathID ) = 0;
};
//-----------------------------------------------------------------------------
@ -662,19 +492,6 @@ private:
//-----------------------------------------------------------------------------
inline unsigned IFileSystem::GetOptimalReadSize( FileHandle_t hFile, unsigned nLogicalSize )
{
unsigned align;
if ( IsPC() && GetOptimalIOConstraints( hFile, &align, NULL, NULL ) )
return AlignValue( nLogicalSize, align );
else if ( IsXbox() )
return AlignValue( nLogicalSize, 512 );
else
return nLogicalSize;
}
//-----------------------------------------------------------------------------
// We include this here so it'll catch compile errors in VMPI early.
#include "filesystem_passthru.h"

View File

@ -139,7 +139,6 @@ public:
virtual void AddLoggingFunc( void (*pfnLogFunc)( const char *fileName, const char *accessType ) ){ m_pFileSystemPassThru->AddLoggingFunc( pfnLogFunc ); }
virtual void RemoveLoggingFunc( FileSystemLoggingFunc_t logFunc ) { m_pFileSystemPassThru->RemoveLoggingFunc( logFunc ); }
virtual FSAsyncStatus_t AsyncReadMultiple( const FileAsyncRequest_t *pRequests, int nRequests, FSAsyncControl_t *pControls ) { return m_pFileSystemPassThru->AsyncReadMultiple( pRequests, nRequests, pControls ); }
virtual FSAsyncStatus_t AsyncReadMultipleCreditAlloc( const FileAsyncRequest_t *pRequests, int nRequests, const char *pszFile, int line, FSAsyncControl_t *pControls ) { return m_pFileSystemPassThru->AsyncReadMultipleCreditAlloc( pRequests, nRequests, pszFile, line, pControls ); }
virtual FSAsyncStatus_t AsyncFinish(FSAsyncControl_t hControl, bool wait) { return m_pFileSystemPassThru->AsyncFinish( hControl, wait ); }
virtual FSAsyncStatus_t AsyncGetResult( FSAsyncControl_t hControl, void **ppData, int *pSize ) { return m_pFileSystemPassThru->AsyncGetResult( hControl, ppData, pSize ); }
virtual FSAsyncStatus_t AsyncAbort(FSAsyncControl_t hControl) { return m_pFileSystemPassThru->AsyncAbort( hControl ); }
@ -158,7 +157,6 @@ public:
virtual bool IsFileImmediatelyAvailable(const char *pFileName) { return m_pFileSystemPassThru->IsFileImmediatelyAvailable( pFileName ); }
virtual void GetLocalCopy( const char *pFileName ) { m_pFileSystemPassThru->GetLocalCopy( pFileName ); }
virtual FileNameHandle_t FindOrAddFileName( char const *pFileName ) { return m_pFileSystemPassThru->FindOrAddFileName( pFileName ); }
virtual FileNameHandle_t FindFileName( char const *pFileName ) { return m_pFileSystemPassThru->FindFileName( pFileName ); }
virtual bool String( const FileNameHandle_t& handle, char *buf, int buflen ) { return m_pFileSystemPassThru->String( handle, buf, buflen ); }
virtual bool IsOk2( FileHandle_t file ) { return IsOk(file); }
virtual void RemoveSearchPaths( const char *szPathID ) { m_pFileSystemPassThru->RemoveSearchPaths( szPathID ); }
@ -173,7 +171,6 @@ public:
virtual void MarkPathIDByRequestOnly( const char *pPathID, bool bRequestOnly ) { m_pFileSystemPassThru->MarkPathIDByRequestOnly( pPathID, bRequestOnly ); }
virtual bool AddPackFile( const char *fullpath, const char *pathID ) { return m_pFileSystemPassThru->AddPackFile( fullpath, pathID ); }
virtual FSAsyncStatus_t AsyncAppend(const char *pFileName, const void *pSrc, int nSrcBytes, bool bFreeMemory, FSAsyncControl_t *pControl ) { return m_pFileSystemPassThru->AsyncAppend( pFileName, pSrc, nSrcBytes, bFreeMemory, pControl); }
virtual FSAsyncStatus_t AsyncWrite(const char *pFileName, const void *pSrc, int nSrcBytes, bool bFreeMemory, bool bAppend, FSAsyncControl_t *pControl ) { return m_pFileSystemPassThru->AsyncWrite( pFileName, pSrc, nSrcBytes, bFreeMemory, bAppend, pControl); }
virtual FSAsyncStatus_t AsyncAppendFile(const char *pDestFileName, const char *pSrcFileName, FSAsyncControl_t *pControl ) { return m_pFileSystemPassThru->AsyncAppendFile(pDestFileName, pSrcFileName, pControl); }
virtual void AsyncFinishAll( int iToPriority ) { m_pFileSystemPassThru->AsyncFinishAll(iToPriority); }
virtual void AsyncFinishAllWrites() { m_pFileSystemPassThru->AsyncFinishAllWrites(); }
@ -183,41 +180,6 @@ public:
virtual const char *RelativePathToFullPath( const char *pFileName, const char *pPathID, char *pLocalPath, int localPathBufferSize ) { return m_pFileSystemPassThru->RelativePathToFullPath( pFileName, pPathID, pLocalPath, localPathBufferSize ); }
virtual int GetSearchPath( const char *pathID, bool bGetPackFiles, char *pPath, int nMaxLen ) { return m_pFileSystemPassThru->GetSearchPath( pathID, bGetPackFiles, pPath, nMaxLen ); }
virtual FileHandle_t OpenEx( const char *pFileName, const char *pOptions, unsigned flags = 0, const char *pathID = 0, char **ppszResolvedFilename = NULL ) { return m_pFileSystemPassThru->OpenEx( pFileName, pOptions, flags, pathID, ppszResolvedFilename );}
virtual int ReadEx( void* pOutput, int destSize, int size, FileHandle_t file ) { return m_pFileSystemPassThru->ReadEx( pOutput, destSize, size, file ); }
virtual int ReadFileEx( const char *pFileName, const char *pPath, void **ppBuf, bool bNullTerminate, bool bOptimalAlloc, int nMaxBytes = 0, int nStartingByte = 0, FSAllocFunc_t pfnAlloc = NULL ) { return m_pFileSystemPassThru->ReadFileEx( pFileName, pPath, ppBuf, bNullTerminate, bOptimalAlloc, nMaxBytes, nStartingByte, pfnAlloc ); }
#if defined( TRACK_BLOCKING_IO )
virtual void EnableBlockingFileAccessTracking( bool state ) { m_pFileSystemPassThru->EnableBlockingFileAccessTracking( state ); }
virtual bool IsBlockingFileAccessEnabled() const { return m_pFileSystemPassThru->IsBlockingFileAccessEnabled(); }
virtual IBlockingFileItemList *RetrieveBlockingFileAccessInfo() { return m_pFileSystemPassThru->RetrieveBlockingFileAccessInfo(); }
#endif
virtual void PurgePreloadedData() {}
virtual void PreloadData() {}
virtual void LoadCompiledKeyValues( KeyValuesPreloadType_t type, char const *archiveFile ) { m_pFileSystemPassThru->LoadCompiledKeyValues( type, archiveFile ); }
// If the "PreloadedData" hasn't been purged, then this'll try and instance the KeyValues using the fast path of compiled keyvalues loaded during startup.
// Otherwise, it'll just fall through to the regular KeyValues loading routines
virtual KeyValues *LoadKeyValues( KeyValuesPreloadType_t type, char const *filename, char const *pPathID = 0 ) { return m_pFileSystemPassThru->LoadKeyValues( type, filename, pPathID ); }
virtual bool LoadKeyValues( KeyValues& head, KeyValuesPreloadType_t type, char const *filename, char const *pPathID = 0 ) { return m_pFileSystemPassThru->LoadKeyValues( head, type, filename, pPathID ); }
virtual bool ExtractRootKeyName( KeyValuesPreloadType_t type, char *outbuf, size_t bufsize, char const *filename, char const *pPathID = 0 ) { return m_pFileSystemPassThru->ExtractRootKeyName( type, outbuf, bufsize, filename, pPathID ); }
virtual bool GetFileTypeForFullPath( char const *pFullPath, wchar_t *buf, size_t bufSizeInBytes ) { return m_pFileSystemPassThru->GetFileTypeForFullPath( pFullPath, buf, bufSizeInBytes ); }
virtual bool GetOptimalIOConstraints( FileHandle_t hFile, unsigned *pOffsetAlign, unsigned *pSizeAlign, unsigned *pBufferAlign ) { return m_pFileSystemPassThru->GetOptimalIOConstraints( hFile, pOffsetAlign, pSizeAlign, pBufferAlign ); }
virtual void *AllocOptimalReadBuffer( FileHandle_t hFile, unsigned nSize, unsigned nOffset ) { return m_pFileSystemPassThru->AllocOptimalReadBuffer( hFile, nOffset, nSize ); }
virtual void FreeOptimalReadBuffer( void *p ) { m_pFileSystemPassThru->FreeOptimalReadBuffer( p ); }
virtual void BeginMapAccess() { m_pFileSystemPassThru->BeginMapAccess(); }
virtual void EndMapAccess() { m_pFileSystemPassThru->EndMapAccess(); }
virtual bool ReadToBuffer( FileHandle_t hFile, CUtlBuffer &buf, int nMaxBytes = 0, FSAllocFunc_t pfnAlloc = NULL ) { return m_pFileSystemPassThru->ReadToBuffer( hFile, buf, nMaxBytes, pfnAlloc ); }
virtual bool FullPathToRelativePathEx( const char *pFullPath, const char *pPathId, char *pRelative, int nMaxLen ) { return m_pFileSystemPassThru->FullPathToRelativePathEx( pFullPath, pPathId, pRelative, nMaxLen ); }
virtual int GetPathIndex( const FileNameHandle_t &handle ) { return m_pFileSystemPassThru->GetPathIndex( handle ); }
virtual long GetPathTime( const char *pPath, const char *pPathID ) { return m_pFileSystemPassThru->GetPathTime( pPath, pPathID ); }
protected:
IFileSystem *m_pFileSystemPassThru;
};

View File

@ -84,6 +84,8 @@ public:
// Gets at the entity handle associated with the collideable
virtual IHandleEntity *GetEntityHandle() = 0;
virtual void *Unknown() = 0;
// Tell the engine which class this object is.
virtual ServerClass* GetServerClass() = 0;

View File

@ -1,4 +1,4 @@
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: A dictionary mapping from symbol to structure
//
@ -14,12 +14,9 @@
#endif
#include "tier0/dbg.h"
#include "tier1/utlmap.h"
#include "utlrbtree.h"
#include "utlsymbol.h"
// Include this because tons of code was implicitly getting utlsymbol or utlvector via utldict.h
#include "tier1/utlsymbol.h"
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// A dictionary mapping from symbol to structure
@ -34,8 +31,6 @@ public:
CUtlDict( bool caseInsensitive = true, int growSize = 0, int initSize = 0 );
~CUtlDict( );
void EnsureCapacity( int );
// gets particular elements
T& Element( I i );
const T& Element( I i ) const;
@ -78,38 +73,44 @@ public:
I Next( I i ) const;
protected:
typedef CUtlMap<const char *, T, I> DictElementMap_t;
struct DictElement_t
{
CUtlSymbol m_Name;
T m_Data;
};
static bool DictLessFunc( const DictElement_t &src1, const DictElement_t &src2 );
typedef CUtlRBTree< DictElement_t, I > DictElementMap_t;
DictElementMap_t m_Elements;
mutable CUtlSymbolTable m_SymbolTable;
};
//-----------------------------------------------------------------------------
// less function
//-----------------------------------------------------------------------------
template <class T, class I>
bool CUtlDict<T, I>::DictLessFunc( const DictElement_t &src1, const DictElement_t &src2 )
{
return src1.m_Name < src2.m_Name;
}
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
template <class T, class I>
CUtlDict<T, I>::CUtlDict( bool caseInsensitive, int growSize, int initSize ) : m_Elements( growSize, initSize )
CUtlDict<T, I>::CUtlDict( bool caseInsensitive, int growSize, int initSize ) : m_Elements( growSize, initSize, DictLessFunc ),
m_SymbolTable( growSize, initSize, caseInsensitive )
{
if ( caseInsensitive )
{
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
@ -117,13 +118,13 @@ inline void CUtlDict<T, I>::EnsureCapacity( int num )
template <class T, class I>
inline T& CUtlDict<T, I>::Element( I i )
{
return m_Elements[i];
return m_Elements[i].m_Data;
}
template <class T, class I>
inline const T& CUtlDict<T, I>::Element( I i ) const
{
return m_Elements[i];
return m_Elements[i].m_Data;
}
//-----------------------------------------------------------------------------
@ -132,13 +133,13 @@ inline const T& CUtlDict<T, I>::Element( I i ) const
template <class T, class I>
inline char *CUtlDict<T, I>::GetElementName( I i )
{
return (char *)m_Elements.Key( i );
return (char *)( m_SymbolTable.String( m_Elements[ i ].m_Name ) );
}
template <class T, class I>
inline char const *CUtlDict<T, I>::GetElementName( I i ) const
{
return m_Elements.Key( i );
return m_SymbolTable.String( m_Elements[ i ].m_Name );
}
template <class T, class I>
@ -156,12 +157,11 @@ inline const T & CUtlDict<T, I>::operator[]( I i ) const
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 );
m_Elements[ i ].m_Name = m_SymbolTable.AddString( pName );
m_Elements.Reinsert( i );
}
//-----------------------------------------------------------------------------
@ -200,7 +200,6 @@ inline I CUtlDict<T, I>::InvalidIndex()
template <class T, class I>
void CUtlDict<T, I>::RemoveAt(I elem)
{
free( (void *)m_Elements.Key( elem ) );
m_Elements.RemoveAt(elem);
}
@ -212,9 +211,7 @@ template <class T, class I> void CUtlDict<T, I>::Remove( const char *search )
{
I node = Find( search );
if (node != InvalidIndex())
{
RemoveAt(node);
}
}
@ -224,20 +221,13 @@ template <class T, class I> void CUtlDict<T, I>::Remove( const char *search )
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();
m_Elements.RemoveAll();
}
@ -248,8 +238,7 @@ void CUtlDict<T, I>::PurgeAndDeleteElements()
I index = m_Elements.FirstInorder();
while ( index != m_Elements.InvalidIndex() )
{
free( (void *)m_Elements.Key( index ) );
delete m_Elements[index];
delete m_Elements[index].m_Data;
index = m_Elements.NextInorder( index );
}
@ -263,15 +252,20 @@ void CUtlDict<T, I>::PurgeAndDeleteElements()
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 );
DictElement_t elem;
elem.m_Name = m_SymbolTable.AddString( pName );
I idx = m_Elements.Insert( elem );
m_Elements[idx].m_Data = element;
return idx;
}
template <class T, class I>
I CUtlDict<T, I>::Insert( const char *pName )
{
MEM_ALLOC_CREDIT_CLASS();
return m_Elements.Insert( strdup( pName ) );
DictElement_t elem;
elem.m_Name = m_SymbolTable.AddString( pName );
I idx = m_Elements.Insert( elem );
return idx;
}
@ -281,11 +275,10 @@ I CUtlDict<T, I>::Insert( const char *pName )
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();
DictElement_t elem;
elem.m_Name = m_SymbolTable.AddString( pName );
return m_Elements.Find( elem );
}
@ -304,6 +297,4 @@ I CUtlDict<T, I>::Next( I i ) const
return m_Elements.NextInorder(i);
}
#include "tier0/memdbgoff.h"
#endif // UTLDICT_H

View File

@ -19,8 +19,8 @@
//-----------------------------------------------------------------------------
//
// Purpose: An associative container. Pretty much identical to std::map.
// Note this class is not thread safe
//
//-----------------------------------------------------------------------------
template <typename K, typename T, typename I = unsigned short>
class CUtlMap
@ -39,17 +39,17 @@ public:
// 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 ) )
: m_Tree( growSize, initSize, TreeLessFunc )
{
m_pfnLess = lessfunc;
}
CUtlMap( LessFunc_t lessfunc )
: m_Tree( CKeyLess( lessfunc ) )
: m_Tree( TreeLessFunc )
{
m_pfnLess = 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; }
@ -77,7 +77,7 @@ public:
// Sets the less func
void SetLessFunc( LessFunc_t func )
{
m_Tree.SetLessFunc( CKeyLess( func ) );
m_pfnLess = func;
}
// Insert method (inserts in order)
@ -86,13 +86,8 @@ public:
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;
Assert( m_pfnLess );
KeyLessFunc( m_pfnLess );
return m_Tree.Insert( node );
}
@ -101,6 +96,8 @@ public:
{
Node_t dummyNode;
dummyNode.key = key;
Assert( m_pfnLess );
KeyLessFunc( m_pfnLess );
return m_Tree.Find( dummyNode );
}
@ -110,6 +107,8 @@ public:
{
Node_t dummyNode;
dummyNode.key = key;
Assert( m_pfnLess );
KeyLessFunc( m_pfnLess );
return m_Tree.Remove( dummyNode );
}
@ -126,7 +125,7 @@ public:
void Reinsert( const KeyType_t &key, IndexType_t i )
{
m_Tree[i].key = key;
m_Tree.Reinsert(i);
Reinsert(i);
}
IndexType_t InsertOrReplace( const KeyType_t &key, const ElemType_t &insert )
@ -144,44 +143,38 @@ public:
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;
typedef CUtlRBTree<Node_t, I> CTree;
CTree *AccessTree() { return &m_Tree; }
protected:
static bool TreeLessFunc( const Node_t &left, const Node_t &right )
{
return (*KeyLessFunc())( left.key, right.key );
}
static LessFunc_t KeyLessFunc( LessFunc_t pfnNew = NULL )
{
// @Note (toml 12-10-02): This is why the class is not thread safe. The way RB
// tree is implemented, I could see no other efficient
// and portable way to do this. This function local
// static approach is used to not require
// instantiation of a static data member or use
// of Microsoft extensions (_declspec(selectany))
static LessFunc_t pfnLess;
if ( pfnNew != NULL )
pfnLess = pfnNew;
return pfnLess;
}
CTree m_Tree;
LessFunc_t m_pfnLess;
};
//-----------------------------------------------------------------------------

View File

@ -9,9 +9,8 @@
#ifndef UTLRBTREE_H
#define UTLRBTREE_H
#include "tier1/utlmemory.h"
#undef MINMAX_H
#include "minmax.h"
//#include <assert.h>
#include "utlmemory.h"
//-----------------------------------------------------------------------------
// Tool to generate a default compare function for any type that implements
@ -44,40 +43,84 @@ void SetDefLessFunc( RBTREE_T &RBTree )
{
#ifdef _WIN32
RBTree.SetLessFunc( DefLessFunc( RBTREE_T::KeyType_t ) );
#elif defined _LINUX
#elif _LINUX
RBTree.SetLessFunc( DefLessFunc( typename RBTREE_T::KeyType_t ) );
#endif
}
template<class T>
class CLessFuncCallerNormal
{
public:
typedef bool (*LessFunc_t)( const T &, const T & );
CLessFuncCallerNormal( LessFunc_t func )
{
m_LessFunc = func;
}
void Init( LessFunc_t func )
{
m_LessFunc = func;
}
inline bool CallLessFunc( const T &a, const T &b, void *pUserData ) const
{
Assert( m_LessFunc );
return m_LessFunc( a, b );
}
LessFunc_t m_LessFunc;
};
template<class T>
class CLessFuncCallerUserData
{
public:
typedef bool (*LessFunc_t)( const T &, const T &, void *pUserData );
CLessFuncCallerUserData( LessFunc_t func )
{
m_LessFunc = func;
}
void Init( LessFunc_t func )
{
m_LessFunc = func;
}
inline bool CallLessFunc( const T &a, const T &b, void *pUserData ) const
{
Assert( m_LessFunc );
return m_LessFunc( a, b, pUserData );
}
LessFunc_t m_LessFunc;
};
//-----------------------------------------------------------------------------
// A red-black binary search tree
//-----------------------------------------------------------------------------
template <class T, class I = unsigned short, typename L = bool (*)( const T &, const T & ) >
template < class T, class I = unsigned short, class L=CLessFuncCallerNormal< T > >
class CUtlRBTree
{
public:
// Less func typedef
// Returns true if the first parameter is "less" than the second
typedef T KeyType_t;
typedef T ElemType_t;
typedef I IndexType_t;
// Less func typedef
// Returns true if the first parameter is "less" than the second
typedef L LessFunc_t;
typedef typename L::LessFunc_t MyLessFunc_t;
// constructor, destructor
// Left at growSize = 0, the memory will first allocate 1 element and double in size
// at each increment.
// LessFunc_t is required, but may be set after the constructor using SetLessFunc() below
CUtlRBTree( int growSize = 0, int initSize = 0, const LessFunc_t &lessfunc = 0 );
CUtlRBTree( const LessFunc_t &lessfunc );
CUtlRBTree( int growSize = 0, int initSize = 0, MyLessFunc_t lessfunc = 0 );
CUtlRBTree( MyLessFunc_t lessfunc );
~CUtlRBTree( );
void EnsureCapacity( int num );
void CopyFrom( const CUtlRBTree<T, I, L> &other );
// gets particular elements
T& Element( I i );
T const &Element( I i ) const;
@ -120,24 +163,22 @@ public:
int Depth() const;
// Sets the less func
void SetLessFunc( const LessFunc_t &func );
void SetLessFunc( MyLessFunc_t func );
// Allocation method
I NewNode();
// Insert method (inserts in order)
I Insert( T const &insert );
void Insert( const T *pArray, int nItems );
I InsertIfNotFound( T const &insert );
I Insert( T const &insert, void *pLessFuncUserData=NULL );
void Insert( const T *pArray, int nItems, void *pLessFuncUserData=NULL );
// Find method
I Find( T const &search ) const;
I Find( T const &search, void *pLessFuncUserData=NULL ) const;
// Remove methods
void RemoveAt( I i );
bool Remove( T const &remove );
void RemoveAll( );
void Purge();
// Allocation, deletion
void FreeNode( I i );
@ -160,12 +201,6 @@ public:
// element into the tree.
void Reinsert( I elem );
// swap in place
void Swap( CUtlRBTree< T, I, L > &that );
private:
// Can't copy the tree this way!
CUtlRBTree<T, I, L>& operator=( const CUtlRBTree<T, I, L> &other );
protected:
enum NodeColor_t
@ -215,17 +250,17 @@ protected:
I InsertAt( I parent, bool leftchild );
// copy constructors not allowed
CUtlRBTree( CUtlRBTree<T, I, L> const &tree );
CUtlRBTree( CUtlRBTree<T, I> const &tree );
// Inserts a node into the tree, doesn't copy the data in.
void FindInsertionPosition( T const &insert, I &parent, bool &leftchild );
void FindInsertionPosition( T const &insert, I &parent, bool &leftchild, void *pLessFuncUserData );
// Remove and add back an element in the tree.
void Unlink( I elem );
void Link( I elem );
// Used for sorting.
LessFunc_t m_LessFunc;
L m_LessFunc;
CUtlMemory<Node_t> m_Elements;
I m_Root;
@ -233,16 +268,12 @@ protected:
I m_FirstFree;
I m_TotalElements;
#if !defined(_XBOX) || defined(_DEBUG)
Node_t* m_pElements;
void ResetDbgInfo()
{
m_pElements = (Node_t*)m_Elements.Base();
}
#else
void ResetDbgInfo() {}
#endif
};
@ -250,78 +281,56 @@ protected:
// constructor, destructor
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
inline CUtlRBTree<T, I, L>::CUtlRBTree( int growSize, int initSize, const LessFunc_t &lessfunc ) :
m_LessFunc( lessfunc ),
m_Elements( growSize, initSize ),
m_Root( InvalidIndex() ),
m_NumElements( 0 ),
m_FirstFree( InvalidIndex() ),
m_TotalElements( 0 )
template <class T, class I, class L>
inline CUtlRBTree<T, I, L>::CUtlRBTree( int growSize, int initSize, typename CUtlRBTree<T, I, L>::MyLessFunc_t lessfunc ) :
m_Elements( growSize, initSize ),
m_LessFunc( lessfunc ),
m_Root( InvalidIndex() ),
m_NumElements( 0 ), m_TotalElements( 0 ),
m_FirstFree( InvalidIndex() )
{
ResetDbgInfo();
}
template <class T, class I, typename L>
inline CUtlRBTree<T, I, L>::CUtlRBTree( const LessFunc_t &lessfunc ) :
m_LessFunc( lessfunc ),
m_Elements( 0, 0 ),
m_Root( InvalidIndex() ),
m_FirstFree( InvalidIndex() ),
m_NumElements( 0 ), m_TotalElements( 0 )
template <class T, class I, class L>
inline CUtlRBTree<T, I, L>::CUtlRBTree( typename CUtlRBTree<T, I, L>::MyLessFunc_t lessfunc ) :
m_Elements( 0, 0 ),
m_LessFunc( lessfunc ),
m_Root( InvalidIndex() ),
m_NumElements( 0 ), m_TotalElements( 0 ),
m_FirstFree( InvalidIndex() )
{
ResetDbgInfo();
}
template <class T, class I, typename L>
template <class T, class I, class L>
inline CUtlRBTree<T, I, L>::~CUtlRBTree()
{
Purge();
}
template <class T, class I, typename L>
inline void CUtlRBTree<T, I, L>::EnsureCapacity( int num )
{
return m_Elements.EnsureCapacity( num );
}
template <class T, class I, typename L>
inline void CUtlRBTree<T, I, L>::CopyFrom( const CUtlRBTree<T, I, L> &other )
{
Purge();
m_Elements.EnsureCapacity( other.m_Elements.Count() );
memcpy( m_Elements.Base(), other.m_Elements.Base(), other.m_Elements.Count() * sizeof( T ) );
m_LessFunc = other.m_LessFunc;
m_Root = other.m_Root;
m_NumElements = other.m_NumElements;
m_FirstFree = other.m_FirstFree;
m_TotalElements = other.m_TotalElements;
ResetDbgInfo();
}
//-----------------------------------------------------------------------------
// gets particular elements
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
inline T &CUtlRBTree<T, I, L>::Element( I i )
{
return m_Elements[i].m_Data;
}
template <class T, class I, typename L>
template <class T, class I, class L>
inline T const &CUtlRBTree<T, I, L>::Element( I i ) const
{
return m_Elements[i].m_Data;
}
template <class T, class I, typename L>
template <class T, class I, class L>
inline T &CUtlRBTree<T, I, L>::operator[]( I i )
{
return Element(i);
}
template <class T, class I, typename L>
template <class T, class I, class L>
inline T const &CUtlRBTree<T, I, L>::operator[]( I i ) const
{
return Element(i);
@ -337,7 +346,7 @@ inline T const &CUtlRBTree<T, I, L>::operator[]( I i ) const
// Gets the root
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
inline I CUtlRBTree<T, I, L>::Root() const
{
return m_Root;
@ -347,7 +356,7 @@ inline I CUtlRBTree<T, I, L>::Root() const
// Num elements
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
inline unsigned int CUtlRBTree<T, I, L>::Count() const
{
return (unsigned int)m_NumElements;
@ -357,7 +366,7 @@ inline unsigned int CUtlRBTree<T, I, L>::Count() const
// Max "size" of the vector
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
inline I CUtlRBTree<T, I, L>::MaxElement() const
{
return (I)m_TotalElements;
@ -368,19 +377,19 @@ inline I CUtlRBTree<T, I, L>::MaxElement() const
// Gets the children
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
inline I CUtlRBTree<T, I, L>::Parent( I i ) const
{
return Links(i).m_Parent;
}
template <class T, class I, typename L>
template <class T, class I, class L>
inline I CUtlRBTree<T, I, L>::LeftChild( I i ) const
{
return Links(i).m_Left;
}
template <class T, class I, typename L>
template <class T, class I, class L>
inline I CUtlRBTree<T, I, L>::RightChild( I i ) const
{
return Links(i).m_Right;
@ -390,13 +399,13 @@ inline I CUtlRBTree<T, I, L>::RightChild( I i ) const
// Tests if a node is a left or right child
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
inline bool CUtlRBTree<T, I, L>::IsLeftChild( I i ) const
{
return LeftChild(Parent(i)) == i;
}
template <class T, class I, typename L>
template <class T, class I, class L>
inline bool CUtlRBTree<T, I, L>::IsRightChild( I i ) const
{
return RightChild(Parent(i)) == i;
@ -407,13 +416,13 @@ inline bool CUtlRBTree<T, I, L>::IsRightChild( I i ) const
// Tests if root or leaf
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
inline bool CUtlRBTree<T, I, L>::IsRoot( I i ) const
{
return i == m_Root;
}
template <class T, class I, typename L>
template <class T, class I, class L>
inline bool CUtlRBTree<T, I, L>::IsLeaf( I i ) const
{
return (LeftChild(i) == InvalidIndex()) && (RightChild(i) == InvalidIndex());
@ -424,12 +433,9 @@ inline bool CUtlRBTree<T, I, L>::IsLeaf( I i ) const
// Checks if a node is valid and in the tree
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
inline bool CUtlRBTree<T, I, L>::IsValidIndex( I i ) const
{
if ( !m_Elements.IsIdxValid( i ) )
return false;
return LeftChild(i) != i;
}
@ -438,7 +444,7 @@ inline bool CUtlRBTree<T, I, L>::IsValidIndex( I i ) const
// Invalid index
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
inline I CUtlRBTree<T, I, L>::InvalidIndex()
{
return (I)~0;
@ -449,7 +455,7 @@ inline I CUtlRBTree<T, I, L>::InvalidIndex()
// returns the tree depth (not a very fast operation)
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
inline int CUtlRBTree<T, I, L>::Depth() const
{
return Depth(Root());
@ -459,19 +465,19 @@ inline int CUtlRBTree<T, I, L>::Depth() const
// Sets the children
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
inline void CUtlRBTree<T, I, L>::SetParent( I i, I parent )
{
Links(i).m_Parent = parent;
}
template <class T, class I, typename L>
template <class T, class I, class L>
inline void CUtlRBTree<T, I, L>::SetLeftChild( I i, I child )
{
Links(i).m_Left = child;
}
template <class T, class I, typename L>
template <class T, class I, class L>
inline void CUtlRBTree<T, I, L>::SetRightChild( I i, I child )
{
Links(i).m_Right = child;
@ -481,7 +487,7 @@ inline void CUtlRBTree<T, I, L>::SetRightChild( I i, I child )
// Gets at the links
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
inline typename CUtlRBTree<T, I, L>::Links_t const &CUtlRBTree<T, I, L>::Links( I i ) const
{
// Sentinel node, makes life easier
@ -494,7 +500,7 @@ inline typename CUtlRBTree<T, I, L>::Links_t const &CUtlRBTree<T, I, L>::Links(
*(Links_t*)&s_Sentinel;
}
template <class T, class I, typename L>
template <class T, class I, class L>
inline typename CUtlRBTree<T, I, L>::Links_t &CUtlRBTree<T, I, L>::Links( I i )
{
Assert(i != InvalidIndex());
@ -505,13 +511,13 @@ inline typename CUtlRBTree<T, I, L>::Links_t &CUtlRBTree<T, I, L>::Links( I i )
// Checks if a link is red or black
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
inline bool CUtlRBTree<T, I, L>::IsRed( I i ) const
{
return (Links(i).m_Tag == RED);
}
template <class T, class I, typename L>
template <class T, class I, class L>
inline bool CUtlRBTree<T, I, L>::IsBlack( I i ) const
{
return (Links(i).m_Tag == BLACK);
@ -522,13 +528,13 @@ inline bool CUtlRBTree<T, I, L>::IsBlack( I i ) const
// Sets/gets node color
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
inline typename CUtlRBTree<T, I, L>::NodeColor_t CUtlRBTree<T, I, L>::Color( I i ) const
{
return (NodeColor_t)Links(i).m_Tag;
}
template <class T, class I, typename L>
template <class T, class I, class L>
inline void CUtlRBTree<T, I, L>::SetColor( I i, typename CUtlRBTree<T, I, L>::NodeColor_t c )
{
Links(i).m_Tag = (I)c;
@ -538,7 +544,7 @@ inline void CUtlRBTree<T, I, L>::SetColor( I i, typename CUtlRBTree<T, I, L>::No
// Allocates/ deallocates nodes
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
I CUtlRBTree<T, I, L>::NewNode()
{
I newElem;
@ -571,7 +577,7 @@ I CUtlRBTree<T, I, L>::NewNode()
return newElem;
}
template <class T, class I, typename L>
template <class T, class I, class L>
void CUtlRBTree<T, I, L>::FreeNode( I i )
{
Assert( IsValidIndex(i) && (i != InvalidIndex()) );
@ -586,7 +592,7 @@ void CUtlRBTree<T, I, L>::FreeNode( I i )
// Rotates node i to the left
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
void CUtlRBTree<T, I, L>::RotateLeft(I elem)
{
I rightchild = RightChild(elem);
@ -616,7 +622,7 @@ void CUtlRBTree<T, I, L>::RotateLeft(I elem)
// Rotates node i to the right
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
void CUtlRBTree<T, I, L>::RotateRight(I elem)
{
I leftchild = LeftChild(elem);
@ -646,7 +652,7 @@ void CUtlRBTree<T, I, L>::RotateRight(I elem)
// Rebalances the tree after an insertion
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
void CUtlRBTree<T, I, L>::InsertRebalance(I elem)
{
while ( !IsRoot(elem) && (Color(Parent(elem)) == RED) )
@ -721,7 +727,7 @@ void CUtlRBTree<T, I, L>::InsertRebalance(I elem)
// Insert a node into the tree
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
I CUtlRBTree<T, I, L>::InsertAt( I parent, bool leftchild )
{
I i = NewNode();
@ -730,7 +736,7 @@ I CUtlRBTree<T, I, L>::InsertAt( I parent, bool leftchild )
return i;
}
template <class T, class I, typename L>
template <class T, class I, class L>
void CUtlRBTree<T, I, L>::LinkToParent( I i, I parent, bool isLeft )
{
Links_t &elem = Links(i);
@ -760,7 +766,7 @@ void CUtlRBTree<T, I, L>::LinkToParent( I i, I parent, bool isLeft )
// Rebalance the tree after a deletion
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
void CUtlRBTree<T, I, L>::RemoveRebalance(I elem)
{
while (elem != m_Root && IsBlack(elem))
@ -850,7 +856,7 @@ void CUtlRBTree<T, I, L>::RemoveRebalance(I elem)
SetColor( elem, BLACK );
}
template <class T, class I, typename L>
template <class T, class I, class L>
void CUtlRBTree<T, I, L>::Unlink( I elem )
{
if ( elem != InvalidIndex() )
@ -921,7 +927,7 @@ void CUtlRBTree<T, I, L>::Unlink( I elem )
}
}
template <class T, class I, typename L>
template <class T, class I, class L>
void CUtlRBTree<T, I, L>::Link( I elem )
{
if ( elem != InvalidIndex() )
@ -939,7 +945,7 @@ void CUtlRBTree<T, I, L>::Link( I elem )
// Delete a node from the tree
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
void CUtlRBTree<T, I, L>::RemoveAt(I elem)
{
if ( elem != InvalidIndex() )
@ -956,7 +962,7 @@ void CUtlRBTree<T, I, L>::RemoveAt(I elem)
// remove a node in the tree
//-----------------------------------------------------------------------------
template <class T, class I, typename L> bool CUtlRBTree<T, I, L>::Remove( T const &search )
template <class T, class I, class L> bool CUtlRBTree<T, I, L>::Remove( T const &search )
{
I node = Find( search );
if (node != InvalidIndex())
@ -972,7 +978,7 @@ template <class T, class I, typename L> bool CUtlRBTree<T, I, L>::Remove( T cons
// Removes all nodes from the tree
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
void CUtlRBTree<T, I, L>::RemoveAll()
{
// Just iterate through the whole list and add to free list
@ -994,32 +1000,12 @@ void CUtlRBTree<T, I, L>::RemoveAll()
m_NumElements = 0;
}
//-----------------------------------------------------------------------------
// Removes all nodes from the tree and purges memory
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
void CUtlRBTree<T, I, L>::Purge()
{
for (int i = (int)m_TotalElements; --i >= 0; )
{
I idx = (I)i;
if (IsValidIndex(idx))
Destruct( &Element(idx) );
}
m_Root = InvalidIndex();
m_NumElements = 0;
m_TotalElements = 0;
m_FirstFree = InvalidIndex();
m_Elements.Purge();
}
//-----------------------------------------------------------------------------
// iteration
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
I CUtlRBTree<T, I, L>::FirstInorder() const
{
I i = m_Root;
@ -1028,7 +1014,7 @@ I CUtlRBTree<T, I, L>::FirstInorder() const
return i;
}
template <class T, class I, typename L>
template <class T, class I, class L>
I CUtlRBTree<T, I, L>::NextInorder( I i ) const
{
Assert(IsValidIndex(i));
@ -1051,7 +1037,7 @@ I CUtlRBTree<T, I, L>::NextInorder( I i ) const
return parent;
}
template <class T, class I, typename L>
template <class T, class I, class L>
I CUtlRBTree<T, I, L>::PrevInorder( I i ) const
{
Assert(IsValidIndex(i));
@ -1074,7 +1060,7 @@ I CUtlRBTree<T, I, L>::PrevInorder( I i ) const
return parent;
}
template <class T, class I, typename L>
template <class T, class I, class L>
I CUtlRBTree<T, I, L>::LastInorder() const
{
I i = m_Root;
@ -1083,13 +1069,14 @@ I CUtlRBTree<T, I, L>::LastInorder() const
return i;
}
template <class T, class I, typename L>
template <class T, class I, class L>
I CUtlRBTree<T, I, L>::FirstPreorder() const
{
return m_Root;
}
template <class T, class I, typename L>
template <class T, class I, class L>
I CUtlRBTree<T, I, L>::NextPreorder( I i ) const
{
if (LeftChild(i) != InvalidIndex())
@ -1109,14 +1096,14 @@ I CUtlRBTree<T, I, L>::NextPreorder( I i ) const
return InvalidIndex();
}
template <class T, class I, typename L>
template <class T, class I, class L>
I CUtlRBTree<T, I, L>::PrevPreorder( I i ) const
{
Assert(0); // not implemented yet
return InvalidIndex();
}
template <class T, class I, typename L>
template <class T, class I, class L>
I CUtlRBTree<T, I, L>::LastPreorder() const
{
I i = m_Root;
@ -1133,7 +1120,7 @@ I CUtlRBTree<T, I, L>::LastPreorder() const
return i;
}
template <class T, class I, typename L>
template <class T, class I, class L>
I CUtlRBTree<T, I, L>::FirstPostorder() const
{
I i = m_Root;
@ -1147,7 +1134,7 @@ I CUtlRBTree<T, I, L>::FirstPostorder() const
return i;
}
template <class T, class I, typename L>
template <class T, class I, class L>
I CUtlRBTree<T, I, L>::NextPostorder( I i ) const
{
I parent = Parent(i);
@ -1172,7 +1159,7 @@ I CUtlRBTree<T, I, L>::NextPostorder( I i ) const
}
template <class T, class I, typename L>
template <class T, class I, class L>
void CUtlRBTree<T, I, L>::Reinsert( I elem )
{
Unlink( elem );
@ -1184,7 +1171,7 @@ void CUtlRBTree<T, I, L>::Reinsert( I elem )
// returns the tree depth (not a very fast operation)
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
int CUtlRBTree<T, I, L>::Depth( I node ) const
{
if (node == InvalidIndex())
@ -1192,16 +1179,16 @@ int CUtlRBTree<T, I, L>::Depth( I node ) const
int depthright = Depth( RightChild(node) );
int depthleft = Depth( LeftChild(node) );
return max(depthright, depthleft) + 1;
}
//-----------------------------------------------------------------------------
// Makes sure the tree is valid after every operation
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
template <class T, class I, class L>
bool CUtlRBTree<T, I, L>::IsValid() const
{
if ( !Count() )
@ -1277,11 +1264,13 @@ InvalidTree:
// Sets the less func
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
void CUtlRBTree<T, I, L>::SetLessFunc( const typename CUtlRBTree<T, I, L>::LessFunc_t &func )
template <class T, class I, class L>
void CUtlRBTree<T, I, L>::SetLessFunc( typename CUtlRBTree<T, I, L>::MyLessFunc_t func )
{
if (!m_LessFunc)
m_LessFunc = func;
if (!m_LessFunc.m_LessFunc)
{
m_LessFunc.Init( func );
}
else
{
// need to re-sort the tree here....
@ -1295,10 +1284,10 @@ void CUtlRBTree<T, I, L>::SetLessFunc( const typename CUtlRBTree<T, I, L>::LessF
//-----------------------------------------------------------------------------
// Inserts a node into the tree, doesn't copy the data in.
template <class T, class I, typename L>
void CUtlRBTree<T, I, L>::FindInsertionPosition( T const &insert, I &parent, bool &leftchild )
template <class T, class I, class L>
void CUtlRBTree<T, I, L>::FindInsertionPosition( T const &insert, I &parent, bool &leftchild, void *pLessFuncUserData )
{
Assert( m_LessFunc );
Assert( m_LessFunc.m_LessFunc );
/* find where node belongs */
I current = m_Root;
@ -1307,7 +1296,7 @@ void CUtlRBTree<T, I, L>::FindInsertionPosition( T const &insert, I &parent, boo
while (current != InvalidIndex())
{
parent = current;
if (m_LessFunc( insert, Element(current) ))
if (m_LessFunc.CallLessFunc( insert, Element(current), pLessFuncUserData ))
{
leftchild = true; current = LeftChild(current);
}
@ -1318,75 +1307,43 @@ void CUtlRBTree<T, I, L>::FindInsertionPosition( T const &insert, I &parent, boo
}
}
template <class T, class I, typename L>
I CUtlRBTree<T, I, L>::Insert( T const &insert )
template <class T, class I, class L>
I CUtlRBTree<T, I, L>::Insert( T const &insert, void *pLessFuncUserData )
{
// use copy constructor to copy it in
I parent;
bool leftchild;
FindInsertionPosition( insert, parent, leftchild );
FindInsertionPosition( insert, parent, leftchild, pLessFuncUserData );
I newNode = InsertAt( parent, leftchild );
CopyConstruct( &Element( newNode ), insert );
return newNode;
}
template <class T, class I, typename L>
void CUtlRBTree<T, I, L>::Insert( const T *pArray, int nItems )
template <class T, class I, class L>
void CUtlRBTree<T, I, L>::Insert( const T *pArray, int nItems, void *pLessFuncUserData )
{
while ( nItems-- )
{
Insert( *pArray++ );
Insert( *pArray++, pLessFuncUserData );
}
}
template <class T, class I, typename L>
I CUtlRBTree<T, I, L>::InsertIfNotFound( T const &insert )
{
// use copy constructor to copy it in
I parent;
bool leftchild;
I current = m_Root;
parent = InvalidIndex();
leftchild = false;
while (current != InvalidIndex())
{
parent = current;
if (m_LessFunc( insert, Element(current) ))
{
leftchild = true; current = LeftChild(current);
}
else if (m_LessFunc( Element(current), insert ))
{
leftchild = false; current = RightChild(current);
}
else
// Match found, no insertion
return InvalidIndex();
}
I newNode = InsertAt( parent, leftchild );
CopyConstruct( &Element( newNode ), insert );
return newNode;
}
//-----------------------------------------------------------------------------
// finds a node in the tree
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
I CUtlRBTree<T, I, L>::Find( T const &search ) const
template <class T, class I, class L>
I CUtlRBTree<T, I, L>::Find( T const &search, void *pLessFuncUserData ) const
{
Assert( m_LessFunc );
Assert( m_LessFunc.m_LessFunc );
I current = m_Root;
while (current != InvalidIndex())
{
if (m_LessFunc( search, Element(current) ))
if (m_LessFunc.CallLessFunc( search, Element(current), pLessFuncUserData ))
current = LeftChild(current);
else if (m_LessFunc( Element(current), search ))
else if (m_LessFunc.CallLessFunc( Element(current), search, pLessFuncUserData ))
current = RightChild(current);
else
break;
@ -1395,20 +1352,7 @@ I CUtlRBTree<T, I, L>::Find( T const &search ) const
}
//-----------------------------------------------------------------------------
// swap in place
//-----------------------------------------------------------------------------
template <class T, class I, typename L>
void CUtlRBTree<T, I, L>::Swap( CUtlRBTree< T, I, L > &that )
{
m_Elements.Swap( that.m_Elements );
swap( m_LessFunc, that.m_LessFunc );
swap( m_Root, that.m_Root );
swap( m_NumElements, that.m_NumElements );
swap( m_FirstFree, that.m_FirstFree );
swap( m_TotalElements, that.m_TotalElements );
swap( m_pElements, that.m_pElements );
}
#endif // UTLRBTREE_H

View File

@ -1,147 +0,0 @@
//====== Copyright © 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();
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;
private:
CUtlBinaryBlock m_Storage;
};
//-----------------------------------------------------------------------------
// Inline methods
//-----------------------------------------------------------------------------
inline bool CUtlString::IsEmpty() const
{
return Length() == 0;
}
#endif // UTLSTRING_H

View File

@ -9,16 +9,14 @@
#ifndef UTLSYMBOL_H
#define UTLSYMBOL_H
#include "tier0/threadtools.h"
#include "tier1/utlrbtree.h"
#include "tier1/utlvector.h"
#include "utlrbtree.h"
#include "utlvector.h"
//-----------------------------------------------------------------------------
// forward declarations
//-----------------------------------------------------------------------------
class CUtlSymbolTable;
class CUtlSymbolTableMT;
//-----------------------------------------------------------------------------
@ -64,10 +62,10 @@ protected:
static void Initialize();
// returns the current symbol table
static CUtlSymbolTableMT* CurrTable();
static CUtlSymbolTable* CurrTable();
// The standard global symbol table
static CUtlSymbolTableMT* s_pSymbolTable;
static CUtlSymbolTable* s_pSymbolTable;
static bool s_bAllowStaticSymbolTable;
@ -131,28 +129,8 @@ protected:
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;
};
friend class CLess;
// 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
};
CTree m_Lookup;
bool m_bInsensitive;
char const* m_pUserSearchString;
CUtlRBTree< CStringPoolIndex, unsigned short, CLessFuncCallerUserData<CStringPoolIndex> > m_Lookup;
typedef struct
{
@ -164,6 +142,8 @@ protected:
// stores the string data
CUtlVector<StringPool_t*> m_StringPools;
// Stored before using the RBTree comparisons.
const char *m_pLessCtxUserString;
private:
@ -172,89 +152,10 @@ private:
const char* StringFromIndex( const CStringPoolIndex &index ) const;
};
class CUtlSymbolTableMT : private CUtlSymbolTable
{
public:
CUtlSymbolTableMT( int growSize = 0, int initSize = 32, bool caseInsensitive = false )
: CUtlSymbolTable( growSize, initSize, caseInsensitive )
{
}
CUtlSymbol AddString( char const* pString )
{
m_mutex.Lock();
CUtlSymbol result = CUtlSymbolTable::AddString( pString );
m_mutex.Unlock();
return result;
}
CUtlSymbol Find( char const* pString )
{
m_mutex.Lock();
CUtlSymbol result = CUtlSymbolTable::Find( pString );
m_mutex.Unlock();
return result;
}
char const* String( CUtlSymbol id ) const
{
m_mutex.Lock();
const char *pszResult = CUtlSymbolTable::String( id );
m_mutex.Unlock();
return pszResult;
}
private:
CThreadMutex m_mutex;
};
//-----------------------------------------------------------------------------
// 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;
};
// Symbol table storing the file names:
CUtlSymbolTableMT m_FileNames;
public:
FileNameHandle_t FindOrAddFileName( char const *pFileName );
FileNameHandle_t FindFileName( char const *pFileName );
int PathIndex(const FileNameHandle_t &handle) { return (( const FileNameHandleInternal_t * )&handle)->path; }
bool String( const FileNameHandle_t& handle, char *buf, int buflen );
// Less function, for sorting strings
static bool SymLess( CStringPoolIndex const& i1, CStringPoolIndex const& i2, void *pUserData );
// case insensitive less function
static bool SymLessi( CStringPoolIndex const& i1, CStringPoolIndex const& i2, void *pUserData );
};

View File

@ -469,24 +469,21 @@ void KeyValues::UsesEscapeSequences(bool state)
bool KeyValues::LoadFromFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID )
{
Assert(filesystem);
#ifndef _LINUX
Assert( IsXbox() || ( IsPC() && _heapchk() == _HEAPOK ) );
#endif
#ifdef _MSC_VER
Assert(_heapchk() == _HEAPOK);
#endif
FileHandle_t f = filesystem->Open(resourceName, "rb", pathID);
if (!f)
return false;
s_LastFileLoadingFrom = (char*)resourceName;
// load file into a null-terminated buffer
int fileSize = filesystem->Size(f);
unsigned bufSize = ((IFileSystem *)filesystem)->GetOptimalReadSize( f, fileSize + 1 );
char *buffer = (char*)((IFileSystem *)filesystem)->AllocOptimalReadBuffer( f, bufSize );
char *buffer = (char *)MemAllocScratch(fileSize + 1);
Assert(buffer);
((IFileSystem *)filesystem)->ReadEx(buffer, bufSize, fileSize, f); // read into local buffer
filesystem->Read(buffer, fileSize, f); // read into local buffer
buffer[fileSize] = 0; // null terminate file as EOF
@ -494,7 +491,7 @@ bool KeyValues::LoadFromFile( IBaseFileSystem *filesystem, const char *resourceN
bool retOK = LoadFromBuffer( resourceName, buffer, filesystem );
((IFileSystem *)filesystem)->FreeOptimalReadBuffer( buffer );
MemFreeScratch();
return retOK;
}

View File

@ -275,18 +275,10 @@
RelativePath=".\utlbuffer.cpp"
>
</File>
<File
RelativePath=".\utlstring.cpp"
>
</File>
<File
RelativePath=".\utlsymbol.cpp"
>
</File>
<File
RelativePath=".\xboxstubs.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"

View File

@ -1,218 +0,0 @@
//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#include "tier1/utlstring.h"
#include "vstdlib/strtools.h"
//-----------------------------------------------------------------------------
// Base class, containing simple memory management
//-----------------------------------------------------------------------------
CUtlBinaryBlock::CUtlBinaryBlock( int growSize, int initSize ) : m_Memory( growSize, initSize )
{
m_nActualLength = 0;
}
CUtlBinaryBlock::CUtlBinaryBlock( void* pMemory, int nSizeInBytes, int nInitialLength ) : m_Memory( (unsigned char*)pMemory, nSizeInBytes )
{
m_nActualLength = nInitialLength;
}
CUtlBinaryBlock::CUtlBinaryBlock( const void* pMemory, int nSizeInBytes ) : m_Memory( (const unsigned char*)pMemory, nSizeInBytes )
{
m_nActualLength = nSizeInBytes;
}
CUtlBinaryBlock::CUtlBinaryBlock( const CUtlBinaryBlock& src )
{
Set( src.Get(), src.Length() );
}
void CUtlBinaryBlock::Get( void *pValue, int nLen ) const
{
Assert( nLen > 0 );
if ( m_nActualLength < nLen )
{
nLen = m_nActualLength;
}
if ( nLen > 0 )
{
memcpy( pValue, m_Memory.Base(), nLen );
}
}
void CUtlBinaryBlock::SetLength( int nLength )
{
Assert( !m_Memory.IsReadOnly() );
m_nActualLength = nLength;
if ( nLength > m_Memory.NumAllocated() )
{
int nOverFlow = nLength - m_Memory.NumAllocated();
m_Memory.Grow( nOverFlow );
// If the reallocation failed, clamp length
if ( nLength > m_Memory.NumAllocated() )
{
m_nActualLength = m_Memory.NumAllocated();
}
}
#ifdef _DEBUG
if ( m_Memory.NumAllocated() > m_nActualLength )
{
memset( ( ( char * )m_Memory.Base() ) + m_nActualLength, 0xEB, m_Memory.NumAllocated() - m_nActualLength );
}
#endif
}
void CUtlBinaryBlock::Set( const void *pValue, int nLen )
{
Assert( !m_Memory.IsReadOnly() );
if ( !pValue )
{
nLen = 0;
}
SetLength( nLen );
if ( m_nActualLength )
{
if ( ( ( const char * )m_Memory.Base() ) >= ( ( const char * )pValue ) + nLen ||
( ( const char * )m_Memory.Base() ) + m_nActualLength <= ( ( const char * )pValue ) )
{
memcpy( m_Memory.Base(), pValue, m_nActualLength );
}
else
{
memmove( m_Memory.Base(), pValue, m_nActualLength );
}
}
}
CUtlBinaryBlock &CUtlBinaryBlock::operator=( const CUtlBinaryBlock &src )
{
Assert( !m_Memory.IsReadOnly() );
Set( src.Get(), src.Length() );
return *this;
}
bool CUtlBinaryBlock::operator==( const CUtlBinaryBlock &src ) const
{
if ( src.Length() != Length() )
return false;
return !memcmp( src.Get(), Get(), Length() );
}
//-----------------------------------------------------------------------------
// Simple string class.
//-----------------------------------------------------------------------------
CUtlString::CUtlString()
{
}
CUtlString::CUtlString( const char *pString )
{
Set( pString );
}
CUtlString::CUtlString( const CUtlString& string )
{
Set( string.Get() );
}
// Attaches the string to external memory. Useful for avoiding a copy
CUtlString::CUtlString( void* pMemory, int nSizeInBytes, int nInitialLength ) : m_Storage( pMemory, nSizeInBytes, nInitialLength )
{
}
CUtlString::CUtlString( const void* pMemory, int nSizeInBytes ) : m_Storage( pMemory, nSizeInBytes )
{
}
void CUtlString::Set( const char *pValue )
{
Assert( !m_Storage.IsReadOnly() );
int nLen = pValue ? Q_strlen(pValue) + 1 : 0;
m_Storage.Set( pValue, nLen );
}
// Returns strlen
int CUtlString::Length() const
{
return m_Storage.Length() ? m_Storage.Length() - 1 : 0;
}
// Sets the length (used to serialize into the buffer )
void CUtlString::SetLength( int nLen )
{
Assert( !m_Storage.IsReadOnly() );
// Add 1 to account for the NULL
m_Storage.SetLength( nLen > 0 ? nLen + 1 : 0 );
}
const char *CUtlString::Get( ) const
{
if ( m_Storage.Length() == 0 )
{
return "";
}
return reinterpret_cast< const char* >( m_Storage.Get() );
}
// Converts to c-strings
CUtlString::operator const char*() const
{
return Get();
}
char *CUtlString::Get()
{
Assert( !m_Storage.IsReadOnly() );
if ( m_Storage.Length() == 0 )
{
// In general, we optimise away small mallocs for empty strings
// but if you ask for the non-const bytes, they must be writable
// so we can't return "" here, like we do for the const version - jd
m_Storage.SetLength( 1 );
m_Storage[ 0 ] = '\0';
}
return reinterpret_cast< char* >( m_Storage.Get() );
}
CUtlString &CUtlString::operator=( const CUtlString &src )
{
Assert( !m_Storage.IsReadOnly() );
m_Storage = src.m_Storage;
return *this;
}
CUtlString &CUtlString::operator=( const char *src )
{
Assert( !m_Storage.IsReadOnly() );
Set( src );
return *this;
}
bool CUtlString::operator==( const CUtlString &src ) const
{
return m_Storage == src.m_Storage;
}
bool CUtlString::operator==( const char *src ) const
{
return ( strcmp( Get(), src ) == 0 );
}

View File

@ -6,17 +6,9 @@
// $NoKeywords: $
//=============================================================================//
#if !defined _XBOX && defined _MSC_VER
#pragma warning (disable:4514)
#endif
#include "utlsymbol.h"
#include "KeyValues.h"
#include "tier0/threadtools.h"
#include "tier0/memdbgon.h"
#include "stringpool.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define INVALID_STRING_INDEX CStringPoolIndex( 0xFFFF, 0xFFFF )
@ -27,7 +19,7 @@
// globals
//-----------------------------------------------------------------------------
CUtlSymbolTableMT* CUtlSymbol::s_pSymbolTable = 0;
CUtlSymbolTable* CUtlSymbol::s_pSymbolTable = 0;
bool CUtlSymbol::s_bAllowStaticSymbolTable = true;
@ -40,17 +32,13 @@ void CUtlSymbol::Initialize()
// If this assert fails, then the module that this call is in has chosen to disallow
// use of the static symbol table. Usually, it's to prevent confusion because it's easy
// to accidentally use the global symbol table when you really want to use a specific one.
#ifndef _XBOX
// xboxissue - need to isolate this concept per lib, otherwise
// can't trap coding mistakes (i.e. unintended global symbol table usage)
Assert( s_bAllowStaticSymbolTable );
#endif
// necessary to allow us to create global symbols
static bool symbolsInitialized = false;
if (!symbolsInitialized)
{
s_pSymbolTable = new CUtlSymbolTableMT;
s_pSymbolTable = new CUtlSymbolTable;
symbolsInitialized = true;
}
}
@ -70,7 +58,7 @@ public:
static CCleanupUtlSymbolTable g_CleanupSymbolTable;
CUtlSymbolTableMT* CUtlSymbol::CurrTable()
CUtlSymbolTable* CUtlSymbol::CurrTable()
{
Initialize();
return s_pSymbolTable;
@ -122,21 +110,28 @@ inline const char* CUtlSymbolTable::StringFromIndex( const CStringPoolIndex &ind
}
bool CUtlSymbolTable::CLess::operator()( const CStringPoolIndex &i1, const CStringPoolIndex &i2 ) const
bool CUtlSymbolTable::SymLess( CStringPoolIndex const& i1, CStringPoolIndex const& i2, void *pUserData )
{
// Need to do pointer math because CUtlSymbolTable is used in CUtlVectors, and hence
// can be arbitrarily moved in memory on a realloc. Yes, this is portable. In reality,
// right now at least, because m_LessFunc is the first member of CUtlRBTree, and m_Lookup
// is the first member of CUtlSymbolTabke, this == pTable
CUtlSymbolTable *pTable = (CUtlSymbolTable *)( (byte *)this - offsetof(CUtlSymbolTable::CTree, m_LessFunc) ) - offsetof(CUtlSymbolTable, m_Lookup );
char const* str1 = (i1 == INVALID_STRING_INDEX) ? pTable->m_pUserSearchString :
CUtlSymbolTable *pTable = (CUtlSymbolTable*)pUserData;
char const* str1 = (i1 == INVALID_STRING_INDEX) ? pTable->m_pLessCtxUserString :
pTable->StringFromIndex( i1 );
char const* str2 = (i2 == INVALID_STRING_INDEX) ? pTable->m_pUserSearchString :
char const* str2 = (i2 == INVALID_STRING_INDEX) ? pTable->m_pLessCtxUserString :
pTable->StringFromIndex( i2 );
if ( !pTable->m_bInsensitive )
return strcmp( str1, str2 ) < 0;
else
}
bool CUtlSymbolTable::SymLessi( CStringPoolIndex const& i1, CStringPoolIndex const& i2, void *pUserData )
{
CUtlSymbolTable *pTable = (CUtlSymbolTable*)pUserData;
char const* str1 = (i1 == INVALID_STRING_INDEX) ? pTable->m_pLessCtxUserString :
pTable->StringFromIndex( i1 );
char const* str2 = (i2 == INVALID_STRING_INDEX) ? pTable->m_pLessCtxUserString :
pTable->StringFromIndex( i2 );
return strcmpi( str1, str2 ) < 0;
}
@ -145,8 +140,12 @@ bool CUtlSymbolTable::CLess::operator()( const CStringPoolIndex &i1, const CStri
//-----------------------------------------------------------------------------
CUtlSymbolTable::CUtlSymbolTable( int growSize, int initSize, bool caseInsensitive ) :
m_Lookup( growSize, initSize ), m_bInsensitive( caseInsensitive ), m_StringPools( 8 )
m_Lookup( growSize, initSize ), m_StringPools( 8 )
{
if ( caseInsensitive )
m_Lookup.SetLessFunc( SymLessi );
else
m_Lookup.SetLessFunc( SymLess );
}
CUtlSymbolTable::~CUtlSymbolTable()
@ -162,16 +161,11 @@ CUtlSymbol CUtlSymbolTable::Find( char const* pString )
return CUtlSymbol();
// Store a special context used to help with insertion
m_pUserSearchString = pString;
m_pLessCtxUserString = pString;
// Passing this special invalid symbol makes the comparison function
// use the string passed in the context
UtlSymId_t idx = m_Lookup.Find( INVALID_STRING_INDEX );
#ifdef _DEBUG
m_pUserSearchString = NULL;
#endif
UtlSymId_t idx = m_Lookup.Find( INVALID_STRING_INDEX, this );
return CUtlSymbol( idx );
}
@ -235,7 +229,7 @@ CUtlSymbol CUtlSymbolTable::AddString( char const* pString )
index.m_iPool = iPool;
index.m_iOffset = iStringOffset;
UtlSymId_t idx = m_Lookup.Insert( index );
UtlSymId_t idx = m_Lookup.Insert( index, this );
return CUtlSymbol( idx );
}
@ -268,103 +262,3 @@ void CUtlSymbolTable::RemoveAll()
m_StringPools.RemoveAll();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pFileName -
// Output : FileNameHandle_t
//-----------------------------------------------------------------------------
FileNameHandle_t CUtlFilenameSymbolTable::FindOrAddFileName( char const *pFileName )
{
if ( !pFileName )
{
return NULL;
}
// Fix slashes and make lower case first..
char fn[ MAX_PATH ];
Q_strncpy( fn, pFileName, sizeof( fn ) );
Q_FixSlashes( fn );
#ifdef _WIN32
strlwr( fn );
#endif
// Split the fn into constituent parts
char basepath[ MAX_PATH ];
Q_ExtractFilePath( fn, basepath, sizeof( basepath ) );
char filename[ MAX_PATH ];
Q_strncpy( filename, fn + Q_strlen( basepath ), sizeof( filename ) );
FileNameHandleInternal_t handle;
handle.path = g_CountedStringPool.ReferenceStringHandle(basepath);
handle.file = g_CountedStringPool.ReferenceStringHandle(filename );
void *h = &handle;
return *reinterpret_cast<FileNameHandle_t *>(h);
}
FileNameHandle_t CUtlFilenameSymbolTable::FindFileName( char const *pFileName )
{
if ( !pFileName )
{
return NULL;
}
// Fix slashes and make lower case first..
char fn[ MAX_PATH ];
Q_strncpy( fn, pFileName, sizeof( fn ) );
Q_FixSlashes( fn );
#ifdef _WIN32
strlwr( fn );
#endif
// Split the fn into constituent parts
char basepath[ MAX_PATH ];
Q_ExtractFilePath( fn, basepath, sizeof( basepath ) );
char filename[ MAX_PATH ];
Q_strncpy( filename, fn + Q_strlen( basepath ), sizeof( filename ) );
FileNameHandleInternal_t handle;
handle.path = g_CountedStringPool.FindStringHandle(basepath);
handle.file = g_CountedStringPool.FindStringHandle(filename);
if( handle.path == 0 || handle.file == 0 )
return NULL;
void *h = &handle;
return *reinterpret_cast<FileNameHandle_t *>(h);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : handle -
// Output : char const
//-----------------------------------------------------------------------------
bool CUtlFilenameSymbolTable::String( const FileNameHandle_t& handle, char *buf, int buflen )
{
buf[ 0 ] = 0;
FileNameHandleInternal_t *internal = ( FileNameHandleInternal_t * )&handle;
if ( !internal )
{
return false;
}
char const *path = g_CountedStringPool.HandleToString(internal->path);
if ( !path )
return false;
Q_strncpy( buf, path, buflen );
char const *fn = g_CountedStringPool.HandleToString(internal->file);
if ( !fn )
{
return false;
}
Q_strncat( buf, fn, buflen, COPY_ALL_CHARACTERS );
return true;
}

View File

@ -1,74 +0,0 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Stubs Xbox functions when compiling for other platforms
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#ifndef _XBOX
#ifdef _WIN32
#include <windows.h>
#elif _LINUX
#define ERROR_GEN_FAILURE 1
#define GetTickCount() Plat_FloatTime()
#else
#error "implement me"
#endif
#include "xbox/xboxstubs.h"
#include "tier0/memdbgon.h"
void XBX_DebugString(xverbose_e verbose, COLORREF color, const char* format, ...)
{
}
void XBX_ProcessEvents( void )
{
}
void XInitDevices( DWORD dwPreallocTypeCount, PXDEVICE_PREALLOC_TYPE PreallocTypes )
{
}
DWORD XGetDevices(PXPP_DEVICE_TYPE DeviceType)
{
return 0;
}
bool XGetDeviceChanges(PXPP_DEVICE_TYPE DeviceType, DWORD *pdwInsertions, DWORD *pdwRemovals)
{
return false;
}
HANDLE XInputOpen(PXPP_DEVICE_TYPE DeviceType, DWORD dwPort, DWORD dwSlot, PXINPUT_POLLING_PARAMETERS pPollingParameters)
{
return 0;
}
void XInputClose(HANDLE hDevice)
{
}
DWORD XInputSetState(HANDLE hDevice, PXINPUT_FEEDBACK pFeedback)
{
return ERROR_GEN_FAILURE;
}
DWORD XInputGetState(HANDLE hDevice, PXINPUT_STATE pState)
{
return ERROR_GEN_FAILURE;
}
DWORD XInputPoll(HANDLE hDevice)
{
return 0;
}
unsigned int XBX_GetSystemTime( void )
{
return (unsigned int)GetTickCount();
}
#endif // _XBOX