diff --git a/lib/public/tier1.lib b/lib/public/tier1.lib index 0575c265..7db9f85e 100644 Binary files a/lib/public/tier1.lib and b/lib/public/tier1.lib differ diff --git a/notes.txt b/notes.txt index 14da7cd3..e481bc7c 100644 --- a/notes.txt +++ b/notes.txt @@ -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. diff --git a/public/edict.h b/public/edict.h index 774401a0..6971611a 100644 --- a/public/edict.h +++ b/public/edict.h @@ -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 diff --git a/public/eiface.h b/public/eiface.h index d9d7c679..322820e9 100644 --- a/public/eiface.h +++ b/public/eiface.h @@ -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 @@ -119,6 +124,8 @@ public: // returns -1 if the edict couldn't be found in the list of players. 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; @@ -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 @@ -397,6 +382,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. @@ -437,25 +425,16 @@ 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" diff --git a/public/engine/IEngineSound.h b/public/engine/IEngineSound.h index c6831ec6..a6499a9c 100644 --- a/public/engine/IEngineSound.h +++ b/public/engine/IEngineSound.h @@ -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; }; diff --git a/public/engine/IEngineTrace.h b/public/engine/IEngineTrace.h index 1f376999..bf9783cc 100644 --- a/public/engine/IEngineTrace.h +++ b/public/engine/IEngineTrace.h @@ -141,11 +141,17 @@ 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; @@ -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; diff --git a/public/engine/iserverplugin.h b/public/engine/iserverplugin.h index 699b1dcb..8e6a70db 100644 --- a/public/engine/iserverplugin.h +++ b/public/engine/iserverplugin.h @@ -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 diff --git a/public/engine/ivmodelinfo.h b/public/engine/ivmodelinfo.h index b55403be..19ab31a5 100644 --- a/public/engine/ivmodelinfo.h +++ b/public/engine/ivmodelinfo.h @@ -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 ¶ms ) = 0; - - virtual bool IsUsingFBTexture( const model_t *model ) const = 0; - - virtual const model_t *FindOrLoadModel( const char *name ) const = 0; }; diff --git a/public/filesystem.h b/public/filesystem.h index 0029f332..f37b2e18 100644 --- a/public/filesystem.h +++ b/public/filesystem.h @@ -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" diff --git a/public/filesystem_passthru.h b/public/filesystem_passthru.h index b5c9b19d..a3d6bfb4 100644 --- a/public/filesystem_passthru.h +++ b/public/filesystem_passthru.h @@ -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; }; diff --git a/public/iservernetworkable.h b/public/iservernetworkable.h index 0faa97aa..c5b3f5e7 100644 --- a/public/iservernetworkable.h +++ b/public/iservernetworkable.h @@ -83,6 +83,8 @@ class IServerNetworkable 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; diff --git a/public/tier1/utldict.h b/public/tier1/utldict.h index fa6fc8e3..3522212d 100644 --- a/public/tier1/utldict.h +++ b/public/tier1/utldict.h @@ -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 @@ -33,8 +30,6 @@ public: // at each increment. CUtlDict( bool caseInsensitive = true, int growSize = 0, int initSize = 0 ); ~CUtlDict( ); - - void EnsureCapacity( int ); // gets particular elements T& Element( I i ); @@ -78,38 +73,44 @@ public: I Next( I i ) const; protected: - typedef CUtlMap DictElementMap_t; - DictElementMap_t m_Elements; + 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 +bool CUtlDict::DictLessFunc( const DictElement_t &src1, const DictElement_t &src2 ) +{ + return src1.m_Name < src2.m_Name; +} + + //----------------------------------------------------------------------------- // constructor, destructor //----------------------------------------------------------------------------- template -CUtlDict::CUtlDict( bool caseInsensitive, int growSize, int initSize ) : m_Elements( growSize, initSize ) +CUtlDict::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 CUtlDict::~CUtlDict() { - Purge(); } -template -inline void CUtlDict::EnsureCapacity( int num ) -{ - return m_Elements.EnsureCapacity( num ); -} //----------------------------------------------------------------------------- // gets particular elements @@ -117,13 +118,13 @@ inline void CUtlDict::EnsureCapacity( int num ) template inline T& CUtlDict::Element( I i ) { - return m_Elements[i]; + return m_Elements[i].m_Data; } template inline const T& CUtlDict::Element( I i ) const { - return m_Elements[i]; + return m_Elements[i].m_Data; } //----------------------------------------------------------------------------- @@ -132,13 +133,13 @@ inline const T& CUtlDict::Element( I i ) const template inline char *CUtlDict::GetElementName( I i ) { - return (char *)m_Elements.Key( i ); + return (char *)( m_SymbolTable.String( m_Elements[ i ].m_Name ) ); } template inline char const *CUtlDict::GetElementName( I i ) const { - return m_Elements.Key( i ); + return m_SymbolTable.String( m_Elements[ i ].m_Name ); } template @@ -156,12 +157,11 @@ inline const T & CUtlDict::operator[]( I i ) const template inline void CUtlDict::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::InvalidIndex() template void CUtlDict::RemoveAt(I elem) { - free( (void *)m_Elements.Key( elem ) ); m_Elements.RemoveAt(elem); } @@ -212,9 +211,7 @@ template void CUtlDict::Remove( const char *search ) { I node = Find( search ); if (node != InvalidIndex()) - { RemoveAt(node); - } } @@ -224,20 +221,13 @@ template void CUtlDict::Remove( const char *search ) template void CUtlDict::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 void CUtlDict::Purge() { - RemoveAll(); + m_Elements.RemoveAll(); } @@ -248,8 +238,7 @@ void CUtlDict::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::PurgeAndDeleteElements() template I CUtlDict::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 I CUtlDict::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::Insert( const char *pName ) template I CUtlDict::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::Next( I i ) const return m_Elements.NextInorder(i); } -#include "tier0/memdbgoff.h" - #endif // UTLDICT_H diff --git a/public/tier1/utlmap.h b/public/tier1/utlmap.h index 5df4a2d8..a498930b 100644 --- a/public/tier1/utlmap.h +++ b/public/tier1/utlmap.h @@ -19,8 +19,8 @@ //----------------------------------------------------------------------------- // // Purpose: An associative container. Pretty much identical to std::map. +// Note this class is not thread safe // -//----------------------------------------------------------------------------- template 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,21 +86,18 @@ public: Node_t node; node.key = key; node.elem = insert; + Assert( m_pfnLess ); + KeyLessFunc( m_pfnLess ); return m_Tree.Insert( node ); } - IndexType_t Insert( const KeyType_t &key ) - { - Node_t node; - node.key = key; - return m_Tree.Insert( node ); - } - // Find method IndexType_t Find( const KeyType_t &key ) const { Node_t dummyNode; dummyNode.key = key; + 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 CTree; + typedef CUtlRBTree 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; }; //----------------------------------------------------------------------------- diff --git a/public/tier1/utlrbtree.h b/public/tier1/utlrbtree.h index 334071c0..958b7bfe 100644 --- a/public/tier1/utlrbtree.h +++ b/public/tier1/utlrbtree.h @@ -9,9 +9,8 @@ #ifndef UTLRBTREE_H #define UTLRBTREE_H -#include "tier1/utlmemory.h" -#undef MINMAX_H -#include "minmax.h" +//#include +#include "utlmemory.h" //----------------------------------------------------------------------------- // Tool to generate a default compare function for any type that implements @@ -44,128 +43,164 @@ 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 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 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 +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 &other ); - + // gets particular elements T& Element( I i ); T const &Element( I i ) const; T& operator[]( I i ); T const &operator[]( I i ) const; - + // Gets the root I Root() const; - + // Num elements unsigned int Count() const; - + // Max "size" of the vector I MaxElement() const; - + // Gets the children I Parent( I i ) const; I LeftChild( I i ) const; I RightChild( I i ) const; - + // Tests if a node is a left or right child bool IsLeftChild( I i ) const; bool IsRightChild( I i ) const; - + // Tests if root or leaf bool IsRoot( I i ) const; bool IsLeaf( I i ) const; - + // Checks if a node is valid and in the tree bool IsValidIndex( I i ) const; - + // Checks if the tree as a whole is valid bool IsValid() const; - + // Invalid index static I InvalidIndex(); - + // returns the tree depth (not a very fast operation) int Depth( I node ) const; int Depth() const; - + // Sets the less func - void SetLessFunc( const LessFunc_t &func ); - + 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 ); - + // Iteration I FirstInorder() const; I NextInorder( I i ) const; I PrevInorder( I i ) const; I LastInorder() const; - + I FirstPreorder() const; I NextPreorder( I i ) const; I PrevPreorder( I i ) const; I LastPreorder( ) const; - + I FirstPostorder() const; I NextPostorder( I i ) const; // If you change the search key, this can be used to reinsert the // element into the tree. void Reinsert( I elem ); - - // swap in place - void Swap( CUtlRBTree< T, I, L > &that ); - -private: - // Can't copy the tree this way! - CUtlRBTree& operator=( const CUtlRBTree &other ); + protected: enum NodeColor_t @@ -173,7 +208,7 @@ protected: RED = 0, BLACK }; - + struct Links_t { I m_Left; @@ -181,7 +216,7 @@ protected: I m_Parent; I m_Tag; }; - + struct Node_t : public Links_t { T m_Data; @@ -196,53 +231,49 @@ protected: // Gets at the links Links_t const &Links( I i ) const; Links_t &Links( I i ); - + // Checks if a link is red or black bool IsRed( I i ) const; bool IsBlack( I i ) const; - + // Sets/gets node color NodeColor_t Color( I i ) const; void SetColor( I i, NodeColor_t c ); - + // operations required to preserve tree balance void RotateLeft(I i); void RotateRight(I i); void InsertRebalance(I i); void RemoveRebalance(I i); - + // Insertion, removal I InsertAt( I parent, bool leftchild ); - + // copy constructors not allowed - CUtlRBTree( CUtlRBTree const &tree ); - + CUtlRBTree( CUtlRBTree 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 m_Elements; I m_Root; I m_NumElements; 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 -inline CUtlRBTree::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 +inline CUtlRBTree::CUtlRBTree( int growSize, int initSize, typename CUtlRBTree::MyLessFunc_t lessfunc ) : + m_Elements( growSize, initSize ), + m_LessFunc( lessfunc ), + m_Root( InvalidIndex() ), + m_NumElements( 0 ), m_TotalElements( 0 ), + m_FirstFree( InvalidIndex() ) { ResetDbgInfo(); } -template -inline CUtlRBTree::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 +inline CUtlRBTree::CUtlRBTree( typename CUtlRBTree::MyLessFunc_t lessfunc ) : + m_Elements( 0, 0 ), + m_LessFunc( lessfunc ), + m_Root( InvalidIndex() ), + m_NumElements( 0 ), m_TotalElements( 0 ), + m_FirstFree( InvalidIndex() ) { ResetDbgInfo(); } -template +template inline CUtlRBTree::~CUtlRBTree() { - Purge(); -} - -template -inline void CUtlRBTree::EnsureCapacity( int num ) -{ - return m_Elements.EnsureCapacity( num ); -} - -template -inline void CUtlRBTree::CopyFrom( const CUtlRBTree &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 +template inline T &CUtlRBTree::Element( I i ) { return m_Elements[i].m_Data; } -template +template inline T const &CUtlRBTree::Element( I i ) const { return m_Elements[i].m_Data; } -template +template inline T &CUtlRBTree::operator[]( I i ) { return Element(i); } -template +template inline T const &CUtlRBTree::operator[]( I i ) const { return Element(i); @@ -337,119 +346,116 @@ inline T const &CUtlRBTree::operator[]( I i ) const // Gets the root //----------------------------------------------------------------------------- -template +template inline I CUtlRBTree::Root() const { return m_Root; } - + //----------------------------------------------------------------------------- // Num elements //----------------------------------------------------------------------------- -template +template inline unsigned int CUtlRBTree::Count() const { return (unsigned int)m_NumElements; } - + //----------------------------------------------------------------------------- // Max "size" of the vector //----------------------------------------------------------------------------- -template +template inline I CUtlRBTree::MaxElement() const { return (I)m_TotalElements; } - + //----------------------------------------------------------------------------- // Gets the children //----------------------------------------------------------------------------- -template +template inline I CUtlRBTree::Parent( I i ) const { return Links(i).m_Parent; } -template +template inline I CUtlRBTree::LeftChild( I i ) const { return Links(i).m_Left; } -template +template inline I CUtlRBTree::RightChild( I i ) const { return Links(i).m_Right; } - + //----------------------------------------------------------------------------- // Tests if a node is a left or right child //----------------------------------------------------------------------------- -template +template inline bool CUtlRBTree::IsLeftChild( I i ) const { return LeftChild(Parent(i)) == i; } -template +template inline bool CUtlRBTree::IsRightChild( I i ) const { return RightChild(Parent(i)) == i; } - + //----------------------------------------------------------------------------- // Tests if root or leaf //----------------------------------------------------------------------------- -template +template inline bool CUtlRBTree::IsRoot( I i ) const { return i == m_Root; } -template +template inline bool CUtlRBTree::IsLeaf( I i ) const { return (LeftChild(i) == InvalidIndex()) && (RightChild(i) == InvalidIndex()); } - + //----------------------------------------------------------------------------- // Checks if a node is valid and in the tree //----------------------------------------------------------------------------- -template +template inline bool CUtlRBTree::IsValidIndex( I i ) const { - if ( !m_Elements.IsIdxValid( i ) ) - return false; - return LeftChild(i) != i; } - - + + //----------------------------------------------------------------------------- // Invalid index //----------------------------------------------------------------------------- -template +template inline I CUtlRBTree::InvalidIndex() { return (I)~0; } - + //----------------------------------------------------------------------------- // returns the tree depth (not a very fast operation) //----------------------------------------------------------------------------- -template +template inline int CUtlRBTree::Depth() const { return Depth(Root()); @@ -459,19 +465,19 @@ inline int CUtlRBTree::Depth() const // Sets the children //----------------------------------------------------------------------------- -template +template inline void CUtlRBTree::SetParent( I i, I parent ) { Links(i).m_Parent = parent; } -template +template inline void CUtlRBTree::SetLeftChild( I i, I child ) { Links(i).m_Left = child; } -template +template inline void CUtlRBTree::SetRightChild( I i, I child ) { Links(i).m_Right = child; @@ -481,7 +487,7 @@ inline void CUtlRBTree::SetRightChild( I i, I child ) // Gets at the links //----------------------------------------------------------------------------- -template +template inline typename CUtlRBTree::Links_t const &CUtlRBTree::Links( I i ) const { // Sentinel node, makes life easier @@ -489,12 +495,12 @@ inline typename CUtlRBTree::Links_t const &CUtlRBTree::Links( { InvalidIndex(), InvalidIndex(), InvalidIndex(), CUtlRBTree::BLACK }; - + return (i != InvalidIndex()) ? *(Links_t*)&m_Elements[i] : - *(Links_t*)&s_Sentinel; + *(Links_t*)&s_Sentinel; } -template +template inline typename CUtlRBTree::Links_t &CUtlRBTree::Links( I i ) { Assert(i != InvalidIndex()); @@ -505,13 +511,13 @@ inline typename CUtlRBTree::Links_t &CUtlRBTree::Links( I i ) // Checks if a link is red or black //----------------------------------------------------------------------------- -template +template inline bool CUtlRBTree::IsRed( I i ) const { return (Links(i).m_Tag == RED); } -template +template inline bool CUtlRBTree::IsBlack( I i ) const { return (Links(i).m_Tag == BLACK); @@ -522,13 +528,13 @@ inline bool CUtlRBTree::IsBlack( I i ) const // Sets/gets node color //----------------------------------------------------------------------------- -template +template inline typename CUtlRBTree::NodeColor_t CUtlRBTree::Color( I i ) const { return (NodeColor_t)Links(i).m_Tag; } -template +template inline void CUtlRBTree::SetColor( I i, typename CUtlRBTree::NodeColor_t c ) { Links(i).m_Tag = (I)c; @@ -538,11 +544,11 @@ inline void CUtlRBTree::SetColor( I i, typename CUtlRBTree::No // Allocates/ deallocates nodes //----------------------------------------------------------------------------- -template +template I CUtlRBTree::NewNode() { I newElem; - + // Nothing in the free list; add. if (m_FirstFree == InvalidIndex()) { @@ -558,20 +564,20 @@ I CUtlRBTree::NewNode() newElem = m_FirstFree; m_FirstFree = RightChild(m_FirstFree); } - + #ifdef _DEBUG // reset links to invalid.... Links_t &node = Links(newElem); node.m_Left = node.m_Right = node.m_Parent = InvalidIndex(); #endif - + Construct( &Element(newElem) ); ResetDbgInfo(); - + return newElem; } -template +template void CUtlRBTree::FreeNode( I i ) { Assert( IsValidIndex(i) && (i != InvalidIndex()) ); @@ -586,14 +592,14 @@ void CUtlRBTree::FreeNode( I i ) // Rotates node i to the left //----------------------------------------------------------------------------- -template +template void CUtlRBTree::RotateLeft(I elem) { I rightchild = RightChild(elem); SetRightChild( elem, LeftChild(rightchild) ); if (LeftChild(rightchild) != InvalidIndex()) SetParent( LeftChild(rightchild), elem ); - + if (rightchild != InvalidIndex()) SetParent( rightchild, Parent(elem) ); if (!IsRoot(elem)) @@ -605,7 +611,7 @@ void CUtlRBTree::RotateLeft(I elem) } else m_Root = rightchild; - + SetLeftChild( rightchild, elem ); if (elem != InvalidIndex()) SetParent( elem, rightchild ); @@ -616,14 +622,14 @@ void CUtlRBTree::RotateLeft(I elem) // Rotates node i to the right //----------------------------------------------------------------------------- -template +template void CUtlRBTree::RotateRight(I elem) { I leftchild = LeftChild(elem); SetLeftChild( elem, RightChild(leftchild) ); if (RightChild(leftchild) != InvalidIndex()) SetParent( RightChild(leftchild), elem ); - + if (leftchild != InvalidIndex()) SetParent( leftchild, Parent(elem) ); if (!IsRoot(elem)) @@ -635,7 +641,7 @@ void CUtlRBTree::RotateRight(I elem) } else m_Root = leftchild; - + SetRightChild( leftchild, elem ); if (elem != InvalidIndex()) SetParent( elem, leftchild ); @@ -646,28 +652,28 @@ void CUtlRBTree::RotateRight(I elem) // Rebalances the tree after an insertion //----------------------------------------------------------------------------- -template +template void CUtlRBTree::InsertRebalance(I elem) { while ( !IsRoot(elem) && (Color(Parent(elem)) == RED) ) { I parent = Parent(elem); I grandparent = Parent(parent); - + /* we have a violation */ if (IsLeftChild(parent)) { I uncle = RightChild(grandparent); if (IsRed(uncle)) - { + { /* uncle is RED */ SetColor(parent, BLACK); SetColor(uncle, BLACK); SetColor(grandparent, RED); elem = grandparent; - } + } else - { + { /* uncle is BLACK */ if (IsRightChild(elem)) { @@ -681,22 +687,22 @@ void CUtlRBTree::InsertRebalance(I elem) SetColor(parent, BLACK); SetColor(grandparent, RED); RotateRight(grandparent); - } + } } else { /* mirror image of above code */ I uncle = LeftChild(grandparent); if (IsRed(uncle)) - { + { /* uncle is RED */ SetColor(parent, BLACK); SetColor(uncle, BLACK); SetColor(grandparent, RED); elem = grandparent; - } + } else - { + { /* uncle is BLACK */ if (IsLeftChild(elem)) { @@ -710,7 +716,7 @@ void CUtlRBTree::InsertRebalance(I elem) SetColor(parent, BLACK); SetColor(grandparent, RED); RotateLeft(grandparent); - } + } } } SetColor( m_Root, BLACK ); @@ -721,7 +727,7 @@ void CUtlRBTree::InsertRebalance(I elem) // Insert a node into the tree //----------------------------------------------------------------------------- -template +template I CUtlRBTree::InsertAt( I parent, bool leftchild ) { I i = NewNode(); @@ -730,14 +736,14 @@ I CUtlRBTree::InsertAt( I parent, bool leftchild ) return i; } -template +template void CUtlRBTree::LinkToParent( I i, I parent, bool isLeft ) { Links_t &elem = Links(i); elem.m_Parent = parent; elem.m_Left = elem.m_Right = InvalidIndex(); elem.m_Tag = RED; - + /* insert node in tree */ if (parent != InvalidIndex()) { @@ -750,7 +756,7 @@ void CUtlRBTree::LinkToParent( I i, I parent, bool isLeft ) { m_Root = i; } - + InsertRebalance(i); Assert(IsValid()); @@ -760,42 +766,42 @@ void CUtlRBTree::LinkToParent( I i, I parent, bool isLeft ) // Rebalance the tree after a deletion //----------------------------------------------------------------------------- -template +template void CUtlRBTree::RemoveRebalance(I elem) { while (elem != m_Root && IsBlack(elem)) { I parent = Parent(elem); - + // If elem is the left child of the parent if (elem == LeftChild(parent)) { // Get our sibling I sibling = RightChild(parent); if (IsRed(sibling)) - { + { SetColor(sibling, BLACK); SetColor(parent, RED); RotateLeft(parent); - + // We may have a new parent now parent = Parent(elem); sibling = RightChild(parent); - } + } if ( (IsBlack(LeftChild(sibling))) && (IsBlack(RightChild(sibling))) ) - { + { if (sibling != InvalidIndex()) SetColor(sibling, RED); elem = parent; - } + } else - { + { if (IsBlack(RightChild(sibling))) { SetColor(LeftChild(sibling), BLACK); SetColor(sibling, RED); RotateRight(sibling); - + // rotation may have changed this parent = Parent(elem); sibling = RightChild(parent); @@ -805,36 +811,36 @@ void CUtlRBTree::RemoveRebalance(I elem) SetColor( RightChild(sibling), BLACK ); RotateLeft( parent ); elem = m_Root; - } + } } else { // Elem is the right child of the parent I sibling = LeftChild(parent); if (IsRed(sibling)) - { + { SetColor(sibling, BLACK); SetColor(parent, RED); RotateRight(parent); - + // We may have a new parent now parent = Parent(elem); sibling = LeftChild(parent); - } + } if ( (IsBlack(RightChild(sibling))) && (IsBlack(LeftChild(sibling))) ) - { + { if (sibling != InvalidIndex()) SetColor( sibling, RED ); elem = parent; - } + } else - { + { if (IsBlack(LeftChild(sibling))) { SetColor( RightChild(sibling), BLACK ); SetColor( sibling, RED ); RotateLeft( sibling ); - + // rotation may have changed this parent = Parent(elem); sibling = LeftChild(parent); @@ -844,19 +850,19 @@ void CUtlRBTree::RemoveRebalance(I elem) SetColor( LeftChild(sibling), BLACK ); RotateRight( parent ); elem = m_Root; - } + } } } SetColor( elem, BLACK ); } -template +template void CUtlRBTree::Unlink( I elem ) { if ( elem != InvalidIndex() ) { I x, y; - + if ((LeftChild(elem) == InvalidIndex()) || (RightChild(elem) == InvalidIndex())) { @@ -870,13 +876,13 @@ void CUtlRBTree::Unlink( I elem ) while (LeftChild(y) != InvalidIndex()) y = LeftChild(y); } - + /* x is y's only child */ if (LeftChild(y) != InvalidIndex()) x = LeftChild(y); else x = RightChild(y); - + /* remove y from the parent chain */ if (x != InvalidIndex()) SetParent( x, Parent(y) ); @@ -889,7 +895,7 @@ void CUtlRBTree::Unlink( I elem ) } else m_Root = x; - + // need to store this off now, we'll be resetting y's color NodeColor_t ycolor = Color(y); if (y != elem) @@ -899,29 +905,29 @@ void CUtlRBTree::Unlink( I elem ) SetParent( y, Parent(elem) ); SetRightChild( y, RightChild(elem) ); SetLeftChild( y, LeftChild(elem) ); - + if (!IsRoot(elem)) if (IsLeftChild(elem)) SetLeftChild( Parent(elem), y ); else SetRightChild( Parent(elem), y ); - else - m_Root = y; - - if (LeftChild(y) != InvalidIndex()) - SetParent( LeftChild(y), y ); - if (RightChild(y) != InvalidIndex()) - SetParent( RightChild(y), y ); - - SetColor( y, Color(elem) ); + else + m_Root = y; + + if (LeftChild(y) != InvalidIndex()) + SetParent( LeftChild(y), y ); + if (RightChild(y) != InvalidIndex()) + SetParent( RightChild(y), y ); + + SetColor( y, Color(elem) ); } - + if ((x != InvalidIndex()) && (ycolor == BLACK)) RemoveRebalance(x); } } -template +template void CUtlRBTree::Link( I elem ) { if ( elem != InvalidIndex() ) @@ -939,7 +945,7 @@ void CUtlRBTree::Link( I elem ) // Delete a node from the tree //----------------------------------------------------------------------------- -template +template void CUtlRBTree::RemoveAt(I elem) { if ( elem != InvalidIndex() ) @@ -956,7 +962,7 @@ void CUtlRBTree::RemoveAt(I elem) // remove a node in the tree //----------------------------------------------------------------------------- -template bool CUtlRBTree::Remove( T const &search ) +template bool CUtlRBTree::Remove( T const &search ) { I node = Find( search ); if (node != InvalidIndex()) @@ -972,7 +978,7 @@ template bool CUtlRBTree::Remove( T cons // Removes all nodes from the tree //----------------------------------------------------------------------------- -template +template void CUtlRBTree::RemoveAll() { // Just iterate through the whole list and add to free list @@ -994,32 +1000,12 @@ void CUtlRBTree::RemoveAll() m_NumElements = 0; } -//----------------------------------------------------------------------------- -// Removes all nodes from the tree and purges memory -//----------------------------------------------------------------------------- - -template -void CUtlRBTree::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 +template I CUtlRBTree::FirstInorder() const { I i = m_Root; @@ -1028,11 +1014,11 @@ I CUtlRBTree::FirstInorder() const return i; } -template +template I CUtlRBTree::NextInorder( I i ) const { Assert(IsValidIndex(i)); - + if (RightChild(i) != InvalidIndex()) { i = RightChild(i); @@ -1040,7 +1026,7 @@ I CUtlRBTree::NextInorder( I i ) const i = LeftChild(i); return i; } - + I parent = Parent(i); while (IsRightChild(i)) { @@ -1051,11 +1037,11 @@ I CUtlRBTree::NextInorder( I i ) const return parent; } -template +template I CUtlRBTree::PrevInorder( I i ) const { Assert(IsValidIndex(i)); - + if (LeftChild(i) != InvalidIndex()) { i = LeftChild(i); @@ -1063,7 +1049,7 @@ I CUtlRBTree::PrevInorder( I i ) const i = RightChild(i); return i; } - + I parent = Parent(i); while (IsLeftChild(i)) { @@ -1074,7 +1060,7 @@ I CUtlRBTree::PrevInorder( I i ) const return parent; } -template +template I CUtlRBTree::LastInorder() const { I i = m_Root; @@ -1083,21 +1069,22 @@ I CUtlRBTree::LastInorder() const return i; } -template + +template I CUtlRBTree::FirstPreorder() const { return m_Root; } -template +template I CUtlRBTree::NextPreorder( I i ) const { if (LeftChild(i) != InvalidIndex()) return LeftChild(i); - + if (RightChild(i) != InvalidIndex()) return RightChild(i); - + I parent = Parent(i); while( parent != InvalidIndex()) { @@ -1109,14 +1096,14 @@ I CUtlRBTree::NextPreorder( I i ) const return InvalidIndex(); } -template +template I CUtlRBTree::PrevPreorder( I i ) const { Assert(0); // not implemented yet return InvalidIndex(); } -template +template I CUtlRBTree::LastPreorder() const { I i = m_Root; @@ -1124,7 +1111,7 @@ I CUtlRBTree::LastPreorder() const { while (RightChild(i) != InvalidIndex()) i = RightChild(i); - + if (LeftChild(i) != InvalidIndex()) i = LeftChild(i); else @@ -1133,7 +1120,7 @@ I CUtlRBTree::LastPreorder() const return i; } -template +template I CUtlRBTree::FirstPostorder() const { I i = m_Root; @@ -1147,19 +1134,19 @@ I CUtlRBTree::FirstPostorder() const return i; } -template +template I CUtlRBTree::NextPostorder( I i ) const { I parent = Parent(i); if (parent == InvalidIndex()) return InvalidIndex(); - + if (IsRightChild(i)) return parent; - + if (RightChild(parent) == InvalidIndex()) return parent; - + i = RightChild(parent); while (!IsLeaf(i)) { @@ -1172,7 +1159,7 @@ I CUtlRBTree::NextPostorder( I i ) const } -template +template void CUtlRBTree::Reinsert( I elem ) { Unlink( elem ); @@ -1184,34 +1171,34 @@ void CUtlRBTree::Reinsert( I elem ) // returns the tree depth (not a very fast operation) //----------------------------------------------------------------------------- -template +template int CUtlRBTree::Depth( I node ) const { if (node == InvalidIndex()) return 0; - + 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 +template bool CUtlRBTree::IsValid() const { if ( !Count() ) return true; - + if (( Root() >= MaxElement()) || ( Parent( Root() ) != InvalidIndex() )) goto InvalidTree; - + #ifdef UTLTREE_PARANOID - + // First check to see that mNumEntries matches reality. // count items on the free list int numFree = 0; @@ -1225,7 +1212,7 @@ bool CUtlRBTree::IsValid() const } if (MaxElement() - numFree != Count()) goto InvalidTree; - + // iterate over all elements, looking for validity // based on the self pointers int numFree2 = 0; @@ -1239,35 +1226,35 @@ bool CUtlRBTree::IsValid() const int left = LeftChild(curr); if ((right == left) && (right != InvalidIndex()) ) goto InvalidTree; - + if (right != InvalidIndex()) - { + { if (!IsValidIndex(right)) goto InvalidTree; if (Parent(right) != curr) goto InvalidTree; if (IsRed(curr) && IsRed(right)) goto InvalidTree; - } - + } + if (left != InvalidIndex()) - { + { if (!IsValidIndex(left)) goto InvalidTree; if (Parent(left) != curr) goto InvalidTree; if (IsRed(curr) && IsRed(left)) goto InvalidTree; - } + } } } if (numFree2 != numFree) goto InvalidTree; - + #endif // UTLTREE_PARANOID - + return true; - + InvalidTree: return false; } @@ -1277,11 +1264,13 @@ InvalidTree: // Sets the less func //----------------------------------------------------------------------------- -template -void CUtlRBTree::SetLessFunc( const typename CUtlRBTree::LessFunc_t &func ) +template +void CUtlRBTree::SetLessFunc( typename CUtlRBTree::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,11 +1284,11 @@ void CUtlRBTree::SetLessFunc( const typename CUtlRBTree::LessF //----------------------------------------------------------------------------- // Inserts a node into the tree, doesn't copy the data in. -template -void CUtlRBTree::FindInsertionPosition( T const &insert, I &parent, bool &leftchild ) +template +void CUtlRBTree::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; parent = InvalidIndex(); @@ -1307,7 +1296,7 @@ void CUtlRBTree::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::FindInsertionPosition( T const &insert, I &parent, boo } } -template -I CUtlRBTree::Insert( T const &insert ) +template +I CUtlRBTree::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 -void CUtlRBTree::Insert( const T *pArray, int nItems ) +template +void CUtlRBTree::Insert( const T *pArray, int nItems, void *pLessFuncUserData ) { while ( nItems-- ) { - Insert( *pArray++ ); + Insert( *pArray++, pLessFuncUserData ); } } - -template -I CUtlRBTree::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 -I CUtlRBTree::Find( T const &search ) const -{ - Assert( m_LessFunc ); +template +I CUtlRBTree::Find( T const &search, void *pLessFuncUserData ) const +{ + 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::Find( T const &search ) const } -//----------------------------------------------------------------------------- -// swap in place -//----------------------------------------------------------------------------- -template -void CUtlRBTree::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 diff --git a/public/tier1/utlstring.h b/public/tier1/utlstring.h deleted file mode 100644 index 3b657374..00000000 --- a/public/tier1/utlstring.h +++ /dev/null @@ -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 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 diff --git a/public/tier1/utlsymbol.h b/public/tier1/utlsymbol.h index 9fb2fdb4..7228a7d9 100644 --- a/public/tier1/utlsymbol.h +++ b/public/tier1/utlsymbol.h @@ -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 - { - public: - CTree( int growSize, int initSize ) : CUtlRBTree( 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 > m_Lookup; typedef struct { @@ -163,7 +141,9 @@ protected: // stores the string data CUtlVector 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 ); }; diff --git a/tier1/KeyValues.cpp b/tier1/KeyValues.cpp index 89d22f0b..ae63fefc 100644 --- a/tier1/KeyValues.cpp +++ b/tier1/KeyValues.cpp @@ -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 *)MemAllocScratch(fileSize + 1); - char *buffer = (char*)((IFileSystem *)filesystem)->AllocOptimalReadBuffer( f, bufSize ); - 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; } diff --git a/tier1/tier1-2005.vcproj b/tier1/tier1-2005.vcproj index 18d7ac00..71aeb213 100644 --- a/tier1/tier1-2005.vcproj +++ b/tier1/tier1-2005.vcproj @@ -275,18 +275,10 @@ RelativePath=".\utlbuffer.cpp" > - - - - 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 ); -} diff --git a/tier1/utlsymbol.cpp b/tier1/utlsymbol.cpp index 92b2f2a5..5623e934 100644 --- a/tier1/utlsymbol.cpp +++ b/tier1/utlsymbol.cpp @@ -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,22 +110,29 @@ 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 : - pTable->StringFromIndex( i1 ); - char const* str2 = (i2 == INVALID_STRING_INDEX) ? pTable->m_pUserSearchString : - pTable->StringFromIndex( i2 ); + CUtlSymbolTable *pTable = (CUtlSymbolTable*)pUserData; - if ( !pTable->m_bInsensitive ) - return strcmp( str1, str2 ) < 0; - else - return strcmpi( str1, str2 ) < 0; + 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 strcmp( str1, str2 ) < 0; +} + + +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(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(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; -} - diff --git a/tier1/xboxstubs.cpp b/tier1/xboxstubs.cpp deleted file mode 100644 index a35b7828..00000000 --- a/tier1/xboxstubs.cpp +++ /dev/null @@ -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 -#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