1 //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
8 //-----------------------------------------------------------------------------
10 //===========================================================================//
19 #include "tier0/dbg.h"
20 #include "tier1/iconvar.h"
21 #include "tier1/utlvector.h"
22 #include "tier1/utlstring.h"
26 #define FORCEINLINE_CVAR FORCEINLINE
27 #elif defined _LINUX || defined __APPLE__
28 #define FORCEINLINE_CVAR inline
34 //-----------------------------------------------------------------------------
35 // Forward declarations
36 //-----------------------------------------------------------------------------
41 struct characterset_t;
45 //-----------------------------------------------------------------------------
46 // Any executable that wants to use ConVars need to implement one of
47 // these to hook up access to console variables.
48 //-----------------------------------------------------------------------------
49 class IConCommandBaseAccessor
52 // Flags is a combination of FCVAR flags in cvar.h.
53 // hOut is filled in with a handle to the variable.
54 virtual bool RegisterConCommandBase( ConCommandBase *pVar ) = 0;
58 //-----------------------------------------------------------------------------
59 // Helper method for console development
60 //-----------------------------------------------------------------------------
61 #if defined( _X360 ) && !defined( _RETAIL )
62 void ConVar_PublishToVXConsole();
66 //-----------------------------------------------------------------------------
67 // Called when a ConCommand needs to execute
68 //-----------------------------------------------------------------------------
69 typedef void ( *FnCommandCallbackV1_t )( void );
70 typedef void ( *FnCommandCallback_t )( const CCommand &command );
72 #define COMMAND_COMPLETION_MAXITEMS 64
73 #define COMMAND_COMPLETION_ITEM_LENGTH 64
75 //-----------------------------------------------------------------------------
76 // Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
77 //-----------------------------------------------------------------------------
78 typedef int ( *FnCommandCompletionCallback )( const char *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
81 //-----------------------------------------------------------------------------
83 //-----------------------------------------------------------------------------
84 class ICommandCallback
87 virtual void CommandCallback( const CCommand &command ) = 0;
90 class ICommandCompletionCallback
93 virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) = 0;
96 //-----------------------------------------------------------------------------
97 // Purpose: The base console invoked command/cvar interface
98 //-----------------------------------------------------------------------------
103 friend class ConCommand;
104 friend void ConVar_Register( int nCVarFlag, IConCommandBaseAccessor *pAccessor );
105 friend void ConVar_PublishToVXConsole();
107 // FIXME: Remove when ConVar changes are done
108 friend class CDefaultCvar;
111 ConCommandBase( void );
112 ConCommandBase( const char *pName, const char *pHelpString = 0,
115 virtual ~ConCommandBase( void );
117 virtual bool IsCommand( void ) const;
120 virtual bool IsFlagSet( int flag ) const;
122 virtual void AddFlags( int flags );
124 // Return name of cvar
125 virtual const char *GetName( void ) const;
127 // Return help text for cvar
128 virtual const char *GetHelpText( void ) const;
130 // Deal with next pointer
131 const ConCommandBase *GetNext( void ) const;
132 ConCommandBase *GetNext( void );
134 void SetNext(ConCommandBase *pBase)
139 virtual bool IsRegistered( void ) const;
141 // Returns the DLL identifier
142 virtual CVarDLLIdentifier_t GetDLLIdentifier() const;
145 virtual void Create( const char *pName, const char *pHelpString = 0,
148 // Used internally by OneTimeInit to initialize/shutdown
152 // Internal copy routine ( uses new operator from correct module )
153 char *CopyString( const char *from );
156 // Next ConVar in chain
157 // Prior to register, it points to the next convar in the DLL.
158 // Once registered, though, m_pNext is reset to point to the next
159 // convar in the global list
160 ConCommandBase *m_pNext;
162 // Has the cvar been added to the global list?
166 const char *m_pszName;
167 const char *m_pszHelpString;
173 // ConVars add themselves to this list for the executable.
174 // Then ConVar_Register runs through all the console variables
175 // and registers them into a global list stored in vstdlib.dll
176 static ConCommandBase *s_pConCommandBases;
178 // ConVars in this executable use this 'global' to access values.
179 static IConCommandBaseAccessor *s_pAccessor;
180 public: // Hackalicous
181 inline int GetFlags() const
185 inline void SetFlags(int flags)
192 //-----------------------------------------------------------------------------
194 //-----------------------------------------------------------------------------
199 CCommand( int nArgC, const char **ppArgV );
200 bool Tokenize( const char *pCommand, characterset_t *pBreakSet = NULL );
204 const char **ArgV() const;
205 const char *ArgS() const; // All args that occur after the 0th arg, in string form
206 const char *GetCommandString() const; // The entire command in string form, including the 0th arg
207 const char *operator[]( int nIndex ) const; // Gets at arguments
208 const char *Arg( int nIndex ) const; // Gets at arguments
210 // Helper functions to parse arguments to commands.
211 const char* FindArg( const char *pName ) const;
212 int FindArgInt( const char *pName, int nDefaultVal ) const;
214 static int MaxCommandLength();
215 static characterset_t* DefaultBreakSet();
220 COMMAND_MAX_ARGC = 64,
221 COMMAND_MAX_LENGTH = 512,
226 char m_pArgSBuffer[ COMMAND_MAX_LENGTH ];
227 char m_pArgvBuffer[ COMMAND_MAX_LENGTH ];
228 const char* m_ppArgv[ COMMAND_MAX_ARGC ];
231 inline int CCommand::MaxCommandLength()
233 return COMMAND_MAX_LENGTH - 1;
236 inline int CCommand::ArgC() const
241 inline const char **CCommand::ArgV() const
243 return m_nArgc ? (const char**)m_ppArgv : NULL;
246 inline const char *CCommand::ArgS() const
248 return m_nArgv0Size ? &m_pArgSBuffer[m_nArgv0Size] : "";
251 inline const char *CCommand::GetCommandString() const
253 return m_nArgc ? m_pArgSBuffer : "";
256 inline const char *CCommand::Arg( int nIndex ) const
258 // FIXME: Many command handlers appear to not be particularly careful
259 // about checking for valid argc range. For now, we're going to
260 // do the extra check and return an empty string if it's out of range
261 if ( nIndex < 0 || nIndex >= m_nArgc )
263 return m_ppArgv[nIndex];
266 inline const char *CCommand::operator[]( int nIndex ) const
268 return Arg( nIndex );
272 //-----------------------------------------------------------------------------
273 // Purpose: The console invoked command
274 //-----------------------------------------------------------------------------
275 class ConCommand : public ConCommandBase
280 typedef ConCommandBase BaseClass;
282 ConCommand( const char *pName, FnCommandCallbackV1_t callback,
283 const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
284 ConCommand( const char *pName, FnCommandCallback_t callback,
285 const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
286 ConCommand( const char *pName, ICommandCallback *pCallback,
287 const char *pHelpString = 0, int flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 );
289 virtual ~ConCommand( void );
291 virtual bool IsCommand( void ) const;
293 virtual int AutoCompleteSuggest( const char *partial, CUtlVector< CUtlString > &commands );
295 virtual bool CanAutoComplete( void );
297 // Invoke the function
298 virtual void Dispatch( const CCommand &command );
301 // NOTE: To maintain backward compat, we have to be very careful:
302 // All public virtual methods must appear in the same order always
303 // since engine code will be calling into this code, which *does not match*
304 // in the mod code; it's using slightly different, but compatible versions
305 // of this class. Also: Be very careful about adding new fields to this class.
306 // Those fields will not exist in the version of this class that is instanced
309 // Call this function when executing the command
312 FnCommandCallbackV1_t m_fnCommandCallbackV1;
313 FnCommandCallback_t m_fnCommandCallback;
314 ICommandCallback *m_pCommandCallback;
319 FnCommandCompletionCallback m_fnCompletionCallback;
320 ICommandCompletionCallback *m_pCommandCompletionCallback;
323 bool m_bHasCompletionCallback : 1;
324 bool m_bUsingNewCommandCallback : 1;
325 bool m_bUsingCommandCallbackInterface : 1;
326 public: // Hackalicous
327 inline FnCommandCallback_t GetCallback() const
329 return m_fnCommandCallback;
334 //-----------------------------------------------------------------------------
335 // Purpose: A console variable
336 //-----------------------------------------------------------------------------
337 class ConVar : public ConCommandBase, public IConVar
340 friend class ConVarRef;
343 typedef ConCommandBase BaseClass;
345 ConVar( const char *pName, const char *pDefaultValue, int flags = 0);
347 ConVar( const char *pName, const char *pDefaultValue, int flags,
348 const char *pHelpString );
349 ConVar( const char *pName, const char *pDefaultValue, int flags,
350 const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax );
351 ConVar( const char *pName, const char *pDefaultValue, int flags,
352 const char *pHelpString, FnChangeCallback_t callback );
353 ConVar( const char *pName, const char *pDefaultValue, int flags,
354 const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax,
355 FnChangeCallback_t callback );
357 virtual ~ConVar( void );
359 virtual bool IsFlagSet( int flag ) const;
360 virtual const char* GetHelpText( void ) const;
361 virtual bool IsRegistered( void ) const;
362 virtual const char *GetName( void ) const;
363 virtual void AddFlags( int flags );
364 virtual bool IsCommand( void ) const;
366 // Install a change callback (there shouldn't already be one....)
367 void InstallChangeCallback( FnChangeCallback_t callback );
370 FORCEINLINE_CVAR float GetFloat( void ) const;
371 FORCEINLINE_CVAR int GetInt( void ) const;
372 FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); }
373 FORCEINLINE_CVAR char const *GetString( void ) const;
375 // Any function that allocates/frees memory needs to be virtual or else you'll have crashes
376 // from alloc/free across dll/exe boundaries.
378 // These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue).
379 virtual void SetValue( const char *value );
380 virtual void SetValue( float value );
381 virtual void SetValue( int value );
383 // Reset to default value
386 // True if it has a min/max setting
387 bool GetMin( float& minVal ) const;
388 bool GetMax( float& maxVal ) const;
389 const char *GetDefault( void ) const;
392 // Called by CCvar when the value of a var is changing.
393 virtual void InternalSetValue(const char *value);
394 // For CVARs marked FCVAR_NEVER_AS_STRING
395 virtual void InternalSetFloatValue( float fNewValue );
396 virtual void InternalSetIntValue( int nValue );
398 virtual bool ClampValue( float& value );
399 virtual void ChangeStringValue( const char *tempVal, float flOldValue );
401 virtual void Create( const char *pName, const char *pDefaultValue, int flags = 0,
402 const char *pHelpString = 0, bool bMin = false, float fMin = 0.0,
403 bool bMax = false, float fMax = false, FnChangeCallback_t callback = 0 );
405 // Used internally by OneTimeInit to initialize.
410 // This either points to "this" or it points to the original declaration of a ConVar.
411 // This allows ConVars to exist in separate modules, and they all use the first one to be declared.
412 // m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar).
416 const char *m_pszDefaultValue;
419 // Dynamically allocated
433 // Call this function when ConVar changes
434 FnChangeCallback_t m_fnChangeCallback;
435 public: // Hackalicous
436 inline FnChangeCallback_t GetCallback() const
438 return m_fnChangeCallback;
440 inline void SetMin(bool set, float min=0.0)
445 inline void SetMax(bool set, float max=0.0)
453 //-----------------------------------------------------------------------------
454 // Purpose: Return ConVar value as a float
456 //-----------------------------------------------------------------------------
457 FORCEINLINE_CVAR float ConVar::GetFloat( void ) const
459 return m_pParent->m_fValue;
462 //-----------------------------------------------------------------------------
463 // Purpose: Return ConVar value as an int
465 //-----------------------------------------------------------------------------
466 FORCEINLINE_CVAR int ConVar::GetInt( void ) const
468 return m_pParent->m_nValue;
472 //-----------------------------------------------------------------------------
473 // Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
474 // Output : const char *
475 //-----------------------------------------------------------------------------
476 FORCEINLINE_CVAR const char *ConVar::GetString( void ) const
478 if ( m_nFlags & FCVAR_NEVER_AS_STRING )
479 return "FCVAR_NEVER_AS_STRING";
481 return ( m_pParent->m_pszString ) ? m_pParent->m_pszString : "";
485 //-----------------------------------------------------------------------------
486 // Used to read/write convars that already exist (replaces the FindVar method)
487 //-----------------------------------------------------------------------------
491 ConVarRef( const char *pName );
492 ConVarRef( const char *pName, bool bIgnoreMissing );
493 ConVarRef( IConVar *pConVar );
495 void Init( const char *pName, bool bIgnoreMissing );
496 bool IsValid() const;
497 bool IsFlagSet( int nFlags ) const;
498 IConVar *GetLinkedConVar();
501 float GetFloat( void ) const;
502 int GetInt( void ) const;
503 bool GetBool() const { return !!GetInt(); }
504 const char *GetString( void ) const;
506 void SetValue( const char *pValue );
507 void SetValue( float flValue );
508 void SetValue( int nValue );
509 void SetValue( bool bValue );
511 const char *GetName() const;
513 const char *GetDefault() const;
516 // High-speed method to read convar data
518 ConVar *m_pConVarState;
522 //-----------------------------------------------------------------------------
523 // Did we find an existing convar of that name?
524 //-----------------------------------------------------------------------------
525 FORCEINLINE_CVAR bool ConVarRef::IsFlagSet( int nFlags ) const
527 return ( m_pConVar->IsFlagSet( nFlags ) != 0 );
530 FORCEINLINE_CVAR IConVar *ConVarRef::GetLinkedConVar()
535 FORCEINLINE_CVAR const char *ConVarRef::GetName() const
537 return m_pConVar->GetName();
541 //-----------------------------------------------------------------------------
542 // Purpose: Return ConVar value as a float
543 //-----------------------------------------------------------------------------
544 FORCEINLINE_CVAR float ConVarRef::GetFloat( void ) const
546 return m_pConVarState->m_fValue;
549 //-----------------------------------------------------------------------------
550 // Purpose: Return ConVar value as an int
551 //-----------------------------------------------------------------------------
552 FORCEINLINE_CVAR int ConVarRef::GetInt( void ) const
554 return m_pConVarState->m_nValue;
557 //-----------------------------------------------------------------------------
558 // Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
559 //-----------------------------------------------------------------------------
560 FORCEINLINE_CVAR const char *ConVarRef::GetString( void ) const
562 Assert( !IsFlagSet( FCVAR_NEVER_AS_STRING ) );
563 return m_pConVarState->m_pszString;
567 FORCEINLINE_CVAR void ConVarRef::SetValue( const char *pValue )
569 m_pConVar->SetValue( pValue );
572 FORCEINLINE_CVAR void ConVarRef::SetValue( float flValue )
574 m_pConVar->SetValue( flValue );
577 FORCEINLINE_CVAR void ConVarRef::SetValue( int nValue )
579 m_pConVar->SetValue( nValue );
582 FORCEINLINE_CVAR void ConVarRef::SetValue( bool bValue )
584 m_pConVar->SetValue( bValue ? 1 : 0 );
587 FORCEINLINE_CVAR const char *ConVarRef::GetDefault() const
589 return m_pConVarState->m_pszDefaultValue;
593 //-----------------------------------------------------------------------------
594 // Called by the framework to register ConCommands with the ICVar
595 //-----------------------------------------------------------------------------
596 void ConVar_Register( int nCVarFlag = 0, IConCommandBaseAccessor *pAccessor = NULL );
597 void ConVar_Unregister( );
600 //-----------------------------------------------------------------------------
602 //-----------------------------------------------------------------------------
603 void ConVar_PrintFlags( const ConCommandBase *var );
604 void ConVar_PrintDescription( const ConCommandBase *pVar );
607 //-----------------------------------------------------------------------------
608 // Purpose: Utility class to quickly allow ConCommands to call member methods
609 //-----------------------------------------------------------------------------
611 #pragma warning (disable : 4355 )
615 class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, public ICommandCompletionCallback
617 typedef ConCommand BaseClass;
618 typedef void ( T::*FnMemberCommandCallback_t )( const CCommand &command );
619 typedef int ( T::*FnMemberCommandCompletionCallback_t )( const char *pPartial, CUtlVector< CUtlString > &commands );
622 CConCommandMemberAccessor( T* pOwner, const char *pName, FnMemberCommandCallback_t callback, const char *pHelpString = 0,
623 int flags = 0, FnMemberCommandCompletionCallback_t completionFunc = 0 ) :
624 BaseClass( pName, this, pHelpString, flags, ( completionFunc != 0 ) ? this : NULL )
628 m_CompletionFunc = completionFunc;
631 ~CConCommandMemberAccessor()
636 void SetOwner( T* pOwner )
641 virtual void CommandCallback( const CCommand &command )
643 Assert( m_pOwner && m_Func );
644 (m_pOwner->*m_Func)( command );
647 virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands )
649 Assert( m_pOwner && m_CompletionFunc );
650 return (m_pOwner->*m_CompletionFunc)( pPartial, commands );
655 FnMemberCommandCallback_t m_Func;
656 FnMemberCommandCompletionCallback_t m_CompletionFunc;
660 #pragma warning ( default : 4355 )
664 //-----------------------------------------------------------------------------
665 // Purpose: Utility macros to quicky generate a simple console command
666 //-----------------------------------------------------------------------------
667 #define CON_COMMAND( name, description ) \
668 static void name( const CCommand &args ); \
669 static ConCommand name##_command( #name, name, description ); \
670 static void name( const CCommand &args )
672 #define CON_COMMAND_F( name, description, flags ) \
673 static void name( const CCommand &args ); \
674 static ConCommand name##_command( #name, name, description, flags ); \
675 static void name( const CCommand &args )
677 #define CON_COMMAND_F_COMPLETION( name, description, flags, completion ) \
678 static void name( const CCommand &args ); \
679 static ConCommand name##_command( #name, name, description, flags, completion ); \
680 static void name( const CCommand &args )
682 #define CON_COMMAND_EXTERN( name, _funcname, description ) \
683 void _funcname( const CCommand &args ); \
684 static ConCommand name##_command( #name, _funcname, description ); \
685 void _funcname( const CCommand &args )
687 #define CON_COMMAND_EXTERN_F( name, _funcname, description, flags ) \
688 void _funcname( const CCommand &args ); \
689 static ConCommand name##_command( #name, _funcname, description, flags ); \
690 void _funcname( const CCommand &args )
692 #define CON_COMMAND_MEMBER_F( _thisclass, name, _funcname, description, flags ) \
693 void _funcname( const CCommand &args ); \
694 friend class CCommandMemberInitializer_##_funcname; \
695 class CCommandMemberInitializer_##_funcname \
698 CCommandMemberInitializer_##_funcname() : m_ConCommandAccessor( NULL, name, &_thisclass::_funcname, description, flags ) \
700 m_ConCommandAccessor.SetOwner( GET_OUTER( _thisclass, m_##_funcname##_register ) ); \
703 CConCommandMemberAccessor< _thisclass > m_ConCommandAccessor; \
706 CCommandMemberInitializer_##_funcname m_##_funcname##_register; \