1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 08:47:17 +01:00

Allow the retrieval of the currently executed command from the command system.

Also improve the way errors during the execution are handled and resources are released.
This commit is contained in:
Sandu Liviu Catalin 2016-03-16 19:11:42 +02:00
parent 98b2ddfda6
commit 839c3c3434
2 changed files with 93 additions and 21 deletions

View File

@ -62,6 +62,15 @@ CSStr CmdArgSpecToStr(Uint8 spec)
} }
} }
// ------------------------------------------------------------------------------------------------
CmdManager::Guard::~Guard()
{
// Release the command instance
_Cmd->m_Instance = nullptr;
// Release the reference to the script object
_Cmd->m_Object.Release();
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
CmdManager::CmdManager() CmdManager::CmdManager()
: m_Buffer(512) : m_Buffer(512)
@ -69,8 +78,12 @@ CmdManager::CmdManager()
, m_Invoker(SQMOD_UNKNOWN) , m_Invoker(SQMOD_UNKNOWN)
, m_Command(64, '\0') , m_Command(64, '\0')
, m_Argument(512, '\0') , m_Argument(512, '\0')
, m_Instance(nullptr)
, m_Object()
, m_Argv() , m_Argv()
, m_Argc(0) , m_Argc(0)
, m_OnError()
, m_OnAuth()
{ {
/* ... */ /* ... */
} }
@ -299,10 +312,12 @@ Int32 CmdManager::Run(Int32 invoker, CCStr command)
// Execution failed! // Execution failed!
return -1; return -1;
} }
// Make sure resources are released at the end of this function
Guard g;
// Attempt to find the specified command // Attempt to find the specified command
Object obj = FindByName(m_Command); m_Object = FindByName(m_Command);
// Have we found anything? // Have we found anything?
if (obj.IsNull()) if (m_Object.IsNull())
{ {
// Tell the script callback to deal with the error // Tell the script callback to deal with the error
SqError(CMDERR_UNKNOWN_COMMAND, _SC("Unable to find the specified command"), m_Command); SqError(CMDERR_UNKNOWN_COMMAND, _SC("Unable to find the specified command"), m_Command);
@ -310,31 +325,27 @@ Int32 CmdManager::Run(Int32 invoker, CCStr command)
return -1; return -1;
} }
// Save the command instance // Save the command instance
m_Instance = obj.Cast< CmdListener * >(); m_Instance = m_Object.Cast< CmdListener * >();
// Is the command instance valid? (just in case) // Is the command instance valid? (just in case)
if (!m_Instance) if (!m_Instance)
{ {
// Tell the script callback to deal with the error // Tell the script callback to deal with the error
SqError(CMDERR_UNKNOWN_COMMAND, _SC("Unable to find the specified command"), m_Command.c_str()); SqError(CMDERR_UNKNOWN_COMMAND, _SC("Unable to find the specified command"), m_Command);
// Execution failed! // Execution failed!
return -1; return -1;
} }
// Value returned by the command
Int32 ret = -1;
// Attempt to execute the command // Attempt to execute the command
try try
{ {
ret = Exec(); return Exec();
} }
catch (...) catch (...)
{ {
// Tell the script callback to deal with the error // Tell the script callback to deal with the error
SqError(CMDERR_EXECUTION_FAILED, _SC("Exceptions occurred during execution"), m_Invoker); SqError(CMDERR_EXECUTION_FAILED, _SC("Exceptions occurred during execution"), m_Invoker);
} }
// Release the command instance // Execution failed
m_Instance = nullptr; return -1;
// Return the result
return ret;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -409,10 +420,14 @@ Int32 CmdManager::Exec()
{ {
// Do we have use the argument index as the key? // Do we have use the argument index as the key?
if (m_Instance->m_ArgTags[arg].empty()) if (m_Instance->m_ArgTags[arg].empty())
{
args.SetValue(SQInteger(arg), m_Argv[arg].second); args.SetValue(SQInteger(arg), m_Argv[arg].second);
}
// Nope, we have a name for this argument! // Nope, we have a name for this argument!
else else
{
args.SetValue(m_Instance->m_ArgTags[arg].c_str(), m_Argv[arg].second); args.SetValue(m_Instance->m_ArgTags[arg].c_str(), m_Argv[arg].second);
}
} }
// Attempt to execute the command with the specified arguments // Attempt to execute the command with the specified arguments
try try
@ -433,7 +448,9 @@ Int32 CmdManager::Exec()
Array args(DefaultVM::Get(), m_Argc); Array args(DefaultVM::Get(), m_Argc);
// Copy the arguments into the array // Copy the arguments into the array
for (Uint32 arg = 0; arg < m_Argc; ++arg) for (Uint32 arg = 0; arg < m_Argc; ++arg)
{
args.Bind(SQInteger(arg), m_Argv[arg].second); args.Bind(SQInteger(arg), m_Argv[arg].second);
}
// Attempt to execute the command with the specified arguments // Attempt to execute the command with the specified arguments
try try
{ {
@ -1585,6 +1602,12 @@ static const Object & Cmd_FindByName(CSStr name)
return _Cmd->FindByName(name); return _Cmd->FindByName(name);
} }
// ------------------------------------------------------------------------------------------------
static const Object & Cmd_Current()
{
return _Cmd->Current();
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static Function & Cmd_GetOnError() static Function & Cmd_GetOnError()
{ {
@ -1704,6 +1727,7 @@ void Register_Command(HSQUIRRELVM vm)
cmdns.Func(_SC("Sort"), &Cmd_Sort); cmdns.Func(_SC("Sort"), &Cmd_Sort);
cmdns.Func(_SC("Count"), &Cmd_Count); cmdns.Func(_SC("Count"), &Cmd_Count);
cmdns.Func(_SC("Current"), &Cmd_Current);
cmdns.Func(_SC("FindByName"), &Cmd_FindByName); cmdns.Func(_SC("FindByName"), &Cmd_FindByName);
cmdns.Func(_SC("GetOnError"), &Cmd_GetOnError); cmdns.Func(_SC("GetOnError"), &Cmd_GetOnError);
cmdns.Func(_SC("SetOnError"), &Cmd_SetOnError); cmdns.Func(_SC("SetOnError"), &Cmd_SetOnError);

View File

@ -95,6 +95,45 @@ private:
typedef std::pair< Uint8, Object > CmdArg; typedef std::pair< Uint8, Object > CmdArg;
typedef std::vector< CmdArg > CmdArgs; typedef std::vector< CmdArg > CmdArgs;
/* --------------------------------------------------------------------------------------------
* Helper class implementing RAII to release the command object and instance.
*/
struct Guard
{
/* ----------------------------------------------------------------------------------------
* Default constructor.
*/
Guard() = default;
/* ----------------------------------------------------------------------------------------
* Copy constructor.
*/
Guard(const Guard & o) = delete;
/* ----------------------------------------------------------------------------------------
* Move constructor.
*/
Guard(Guard && o) = delete;
/* ----------------------------------------------------------------------------------------
* Destructor.
*/
~Guard();
/* ----------------------------------------------------------------------------------------
* Copy assignment operator.
*/
Guard & operator = (const Guard & o) = delete;
/* ----------------------------------------------------------------------------------------
* Move assignment operator.
*/
Guard & operator = (Guard && o) = delete;
};
// --------------------------------------------------------------------------------------------
friend class Guard;
/* -------------------------------------------------------------------------------------------- /* --------------------------------------------------------------------------------------------
* Default constructor. * Default constructor.
*/ */
@ -173,6 +212,14 @@ public:
*/ */
const Object & FindByName(const String & name); const Object & FindByName(const String & name);
/* --------------------------------------------------------------------------------------------
* Retrieve the currently active command object.
*/
const Object & Current() const
{
return m_Object;
}
/* -------------------------------------------------------------------------------------------- /* --------------------------------------------------------------------------------------------
* Terminate current session. * Terminate current session.
*/ */
@ -276,22 +323,23 @@ protected:
private: private:
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
Buffer m_Buffer; /* Internal buffer used for parsing commands. */ Buffer m_Buffer; // Internal buffer used for parsing commands.
CmdList m_Commands; /* List of created commands. */ CmdList m_Commands; // List of created commands.
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
Int32 m_Invoker; /* Current command invoker. */ Int32 m_Invoker; // Current command invoker.
String m_Command; /* Current command name. */ String m_Command; // Current command name.
String m_Argument; /* Current command argument. */ String m_Argument; // Current command argument.
CmdListener* m_Instance; /* Current command instance. */ CmdListener* m_Instance; // Current command instance.
Object m_Object; // Current command script object.
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
CmdArgs m_Argv; /* Extracted command arguments. */ CmdArgs m_Argv; // Extracted command arguments.
Uint32 m_Argc; /* Extracted arguments count. */ Uint32 m_Argc; // Extracted arguments count.
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
Function m_OnError; /* Error handler. */ Function m_OnError; // Error handler.
Function m_OnAuth; /* Authentication handler. */ Function m_OnAuth; // Authentication handler.
public: public: