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

View File

@ -95,6 +95,45 @@ private:
typedef std::pair< Uint8, Object > CmdArg;
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.
*/
@ -173,6 +212,14 @@ public:
*/
const Object & FindByName(const String & name);
/* --------------------------------------------------------------------------------------------
* Retrieve the currently active command object.
*/
const Object & Current() const
{
return m_Object;
}
/* --------------------------------------------------------------------------------------------
* Terminate current session.
*/
@ -276,22 +323,23 @@ protected:
private:
// --------------------------------------------------------------------------------------------
Buffer m_Buffer; /* Internal buffer used for parsing commands. */
CmdList m_Commands; /* List of created commands. */
Buffer m_Buffer; // Internal buffer used for parsing commands.
CmdList m_Commands; // List of created commands.
// --------------------------------------------------------------------------------------------
Int32 m_Invoker; /* Current command invoker. */
String m_Command; /* Current command name. */
String m_Argument; /* Current command argument. */
CmdListener* m_Instance; /* Current command instance. */
Int32 m_Invoker; // Current command invoker.
String m_Command; // Current command name.
String m_Argument; // Current command argument.
CmdListener* m_Instance; // Current command instance.
Object m_Object; // Current command script object.
// --------------------------------------------------------------------------------------------
CmdArgs m_Argv; /* Extracted command arguments. */
Uint32 m_Argc; /* Extracted arguments count. */
CmdArgs m_Argv; // Extracted command arguments.
Uint32 m_Argc; // Extracted arguments count.
// --------------------------------------------------------------------------------------------
Function m_OnError; /* Error handler. */
Function m_OnAuth; /* Authentication handler. */
Function m_OnError; // Error handler.
Function m_OnAuth; // Authentication handler.
public: