mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 08:47:17 +01:00
Changes to command manager.
Add a new callback to audit command parameters. Include extra arguments to fail and post callbacks. Refactor code to simplify some cases.
This commit is contained in:
parent
d5bfeced1c
commit
47ff628a46
@ -363,29 +363,46 @@ int32_t Controller::Exec(Context & ctx)
|
|||||||
ctx.mBuffer.At(0) = '\0';
|
ctx.mBuffer.At(0) = '\0';
|
||||||
// Whether the command execution failed
|
// Whether the command execution failed
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
|
// Object with the command arguments
|
||||||
|
LightObj args;
|
||||||
// Do we have to call the command with an associative container?
|
// Do we have to call the command with an associative container?
|
||||||
if (ctx.mInstance->m_Associate)
|
if (ctx.mInstance->m_Associate)
|
||||||
{
|
{
|
||||||
// Create the associative container
|
// Create the associative container
|
||||||
Table args(SqVM());
|
Table tbl(SqVM());
|
||||||
// Copy the arguments into the table
|
// Copy the arguments into the table
|
||||||
for (uint32_t arg = 0; arg < ctx.mArgc; ++arg)
|
for (uint32_t arg = 0; arg < ctx.mArgc; ++arg)
|
||||||
{
|
{
|
||||||
// Do we have use the argument index as the key?
|
// Do we have use the argument index as the key?
|
||||||
if (ctx.mInstance->m_ArgTags[arg].empty())
|
if (ctx.mInstance->m_ArgTags[arg].empty())
|
||||||
{
|
{
|
||||||
args.SetValue(SQInteger(arg), ctx.mArgv[arg].second);
|
tbl.SetValue(SQInteger(arg), ctx.mArgv[arg].second);
|
||||||
}
|
}
|
||||||
// Nope, we have a name for this argument!
|
// Nope, we have a name for this argument!
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
args.SetValue(ctx.mInstance->m_ArgTags[arg].c_str(), ctx.mArgv[arg].second);
|
tbl.SetValue(ctx.mInstance->m_ArgTags[arg].c_str(), ctx.mArgv[arg].second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Attempt to execute the command with the specified arguments
|
// Store the table object into an abstract script object
|
||||||
|
args = LightObj(tbl.GetObj());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Reserve an array for the extracted arguments
|
||||||
|
Array arr(SqVM(), ctx.mArgc);
|
||||||
|
// Copy the arguments into the array
|
||||||
|
for (uint32_t arg = 0; arg < ctx.mArgc; ++arg)
|
||||||
|
{
|
||||||
|
arr.Bind(SQInteger(arg), ctx.mArgv[arg].second);
|
||||||
|
}
|
||||||
|
// Store the table object into an abstract script object
|
||||||
|
args = LightObj(arr.GetObj());
|
||||||
|
}
|
||||||
|
// Allow the user to audit the command parameters
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
result = ctx.mInstance->Execute(ctx.mInvoker, args);
|
result = ctx.mInstance->Audit(ctx.mInvoker, args);
|
||||||
}
|
}
|
||||||
catch (const std::exception & e)
|
catch (const std::exception & e)
|
||||||
{
|
{
|
||||||
@ -394,16 +411,9 @@ int32_t Controller::Exec(Context & ctx)
|
|||||||
// Specify that the command execution failed
|
// Specify that the command execution failed
|
||||||
failed = true;
|
failed = true;
|
||||||
}
|
}
|
||||||
}
|
// Did parameter audit succeeded?
|
||||||
else
|
if (result && !failed)
|
||||||
{
|
{
|
||||||
// Reserve an array for the extracted arguments
|
|
||||||
Array args(SqVM(), ctx.mArgc);
|
|
||||||
// Copy the arguments into the array
|
|
||||||
for (uint32_t arg = 0; arg < ctx.mArgc; ++arg)
|
|
||||||
{
|
|
||||||
args.Bind(SQInteger(arg), ctx.mArgv[arg].second);
|
|
||||||
}
|
|
||||||
// Attempt to execute the command with the specified arguments
|
// Attempt to execute the command with the specified arguments
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -447,15 +457,13 @@ int32_t Controller::Exec(Context & ctx)
|
|||||||
// Was the command aborted explicitly?
|
// Was the command aborted explicitly?
|
||||||
else if (!result)
|
else if (!result)
|
||||||
{
|
{
|
||||||
// Tell the script callback to deal with the error
|
|
||||||
SqError(CMDERR_EXECUTION_ABORTED, _SC("Command execution aborted"), result);
|
|
||||||
// Is there a script callback that handles failures?
|
// Is there a script callback that handles failures?
|
||||||
if (!ctx.mInstance->m_OnFail.IsNull())
|
if (!ctx.mInstance->m_OnFail.IsNull())
|
||||||
{
|
{
|
||||||
// Then attempt to relay the result to that function
|
// Then attempt to relay the result to that function
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ctx.mInstance->m_OnFail.Execute(ctx.mInvoker, result);
|
ctx.mInstance->m_OnFail.Execute(ctx.mInvoker, args, result);
|
||||||
}
|
}
|
||||||
catch (const Poco::Exception& e)
|
catch (const Poco::Exception& e)
|
||||||
{
|
{
|
||||||
@ -468,6 +476,11 @@ int32_t Controller::Exec(Context & ctx)
|
|||||||
SqError(CMDERR_UNRESOLVED_FAILURE, _SC("Unable to resolve command failure"), e.what());
|
SqError(CMDERR_UNRESOLVED_FAILURE, _SC("Unable to resolve command failure"), e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Tell the script callback to deal with the error
|
||||||
|
SqError(CMDERR_EXECUTION_ABORTED, _SC("Command execution aborted"), result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Is there a callback that must be executed after a successful execution?
|
// Is there a callback that must be executed after a successful execution?
|
||||||
else if (!ctx.mInstance->m_OnPost.IsNull())
|
else if (!ctx.mInstance->m_OnPost.IsNull())
|
||||||
@ -475,7 +488,7 @@ int32_t Controller::Exec(Context & ctx)
|
|||||||
// Then attempt to relay the result to that function
|
// Then attempt to relay the result to that function
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ctx.mInstance->m_OnPost.Execute(ctx.mInvoker, result);
|
ctx.mInstance->m_OnPost.Execute(ctx.mInvoker, args, result);
|
||||||
}
|
}
|
||||||
catch (const Poco::Exception& e)
|
catch (const Poco::Exception& e)
|
||||||
{
|
{
|
||||||
@ -1118,6 +1131,7 @@ void Register(HSQUIRRELVM vm)
|
|||||||
.Prop(_SC("MaxArgs"), &Listener::GetMaxArgC, &Listener::SetMaxArgC)
|
.Prop(_SC("MaxArgs"), &Listener::GetMaxArgC, &Listener::SetMaxArgC)
|
||||||
.Prop(_SC("OnExec"), &Listener::GetOnExec)
|
.Prop(_SC("OnExec"), &Listener::GetOnExec)
|
||||||
.Prop(_SC("OnAuth"), &Listener::GetOnAuth)
|
.Prop(_SC("OnAuth"), &Listener::GetOnAuth)
|
||||||
|
.Prop(_SC("OnAudit"), &Listener::GetOnAudit)
|
||||||
.Prop(_SC("OnPost"), &Listener::GetOnPost)
|
.Prop(_SC("OnPost"), &Listener::GetOnPost)
|
||||||
.Prop(_SC("OnFail"), &Listener::GetOnFail)
|
.Prop(_SC("OnFail"), &Listener::GetOnFail)
|
||||||
// Member Methods
|
// Member Methods
|
||||||
@ -1129,6 +1143,7 @@ void Register(HSQUIRRELVM vm)
|
|||||||
.FmtFunc(_SC("SetInfo"), &Listener::SetInfo)
|
.FmtFunc(_SC("SetInfo"), &Listener::SetInfo)
|
||||||
.CbFunc(_SC("BindExec"), &Listener::SetOnExec)
|
.CbFunc(_SC("BindExec"), &Listener::SetOnExec)
|
||||||
.CbFunc(_SC("BindAuth"), &Listener::SetOnAuth)
|
.CbFunc(_SC("BindAuth"), &Listener::SetOnAuth)
|
||||||
|
.CbFunc(_SC("BindAudit"), &Listener::SetOnAudit)
|
||||||
.CbFunc(_SC("BindPost"), &Listener::SetOnPost)
|
.CbFunc(_SC("BindPost"), &Listener::SetOnPost)
|
||||||
.CbFunc(_SC("BindFail"), &Listener::SetOnFail)
|
.CbFunc(_SC("BindFail"), &Listener::SetOnFail)
|
||||||
.Func(_SC("GetArgTag"), &Listener::GetArgTag)
|
.Func(_SC("GetArgTag"), &Listener::GetArgTag)
|
||||||
|
@ -1109,6 +1109,7 @@ public:
|
|||||||
node->m_Data.Release();
|
node->m_Data.Release();
|
||||||
node->m_OnExec.Release();
|
node->m_OnExec.Release();
|
||||||
node->m_OnAuth.Release();
|
node->m_OnAuth.Release();
|
||||||
|
node->m_OnAudit.Release();
|
||||||
node->m_OnPost.Release();
|
node->m_OnPost.Release();
|
||||||
node->m_OnFail.Release();
|
node->m_OnFail.Release();
|
||||||
}
|
}
|
||||||
@ -1118,6 +1119,7 @@ public:
|
|||||||
node->m_Data.Release();
|
node->m_Data.Release();
|
||||||
node->m_OnExec.Release();
|
node->m_OnExec.Release();
|
||||||
node->m_OnAuth.Release();
|
node->m_OnAuth.Release();
|
||||||
|
node->m_OnAudit.Release();
|
||||||
node->m_OnPost.Release();
|
node->m_OnPost.Release();
|
||||||
node->m_OnFail.Release();
|
node->m_OnFail.Release();
|
||||||
}
|
}
|
||||||
@ -1203,6 +1205,7 @@ public:
|
|||||||
, m_Info()
|
, m_Info()
|
||||||
, m_OnExec()
|
, m_OnExec()
|
||||||
, m_OnAuth()
|
, m_OnAuth()
|
||||||
|
, m_OnAudit()
|
||||||
, m_OnPost()
|
, m_OnPost()
|
||||||
, m_OnFail()
|
, m_OnFail()
|
||||||
, m_Authority(ConvTo< int32_t >::From(auth))
|
, m_Authority(ConvTo< int32_t >::From(auth))
|
||||||
@ -1274,6 +1277,7 @@ public:
|
|||||||
// Release callbacks
|
// Release callbacks
|
||||||
m_OnExec.Release();
|
m_OnExec.Release();
|
||||||
m_OnAuth.Release();
|
m_OnAuth.Release();
|
||||||
|
m_OnAudit.Release();
|
||||||
m_OnPost.Release();
|
m_OnPost.Release();
|
||||||
m_OnFail.Release();
|
m_OnFail.Release();
|
||||||
// Is there an element behind us?
|
// Is there an element behind us?
|
||||||
@ -1744,6 +1748,22 @@ public:
|
|||||||
m_OnAuth = std::move(func);
|
m_OnAuth = std::move(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the function that must be called when this command listener needs to validate invocation.
|
||||||
|
*/
|
||||||
|
Function & GetOnAudit()
|
||||||
|
{
|
||||||
|
return m_OnAudit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the function that must be called when this command listener needs to validate invocation.
|
||||||
|
*/
|
||||||
|
void SetOnAudit(Function & func)
|
||||||
|
{
|
||||||
|
m_OnAudit = std::move(func);
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Retrieve the function that must be called when this command listener finished execution.
|
* Retrieve the function that must be called when this command listener finished execution.
|
||||||
*/
|
*/
|
||||||
@ -1890,23 +1910,23 @@ protected:
|
|||||||
typedef String ArgTags[SQMOD_MAX_CMD_ARGS];
|
typedef String ArgTags[SQMOD_MAX_CMD_ARGS];
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Execute the designated callback by passing the arguments in their specified order.
|
* Execute the designated audit callback by passing the arguments in their specified order.
|
||||||
*/
|
*/
|
||||||
SQInteger Execute(const Object & invoker, const Array & args)
|
SQInteger Audit(const Object & invoker, const LightObj & args)
|
||||||
{
|
{
|
||||||
// Attempt to evaluate the specified executer knowing the manager did the validations
|
// Attempt to evaluate the specified executer knowing the manager did the validations
|
||||||
SharedPtr< SQInteger > ret = m_OnExec.Evaluate< SQInteger, const Object &, const Array & >(invoker, args);
|
SharedPtr< SQInteger > ret = m_OnAudit.Evaluate< SQInteger, const Object &, const LightObj & >(invoker, args);
|
||||||
// See if the executer succeeded and return the result or default to failed
|
// See if the executer succeeded and return the result or default to failed
|
||||||
return (!ret ? 0 : *ret);
|
return (!ret ? 0 : *ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
* Execute the designated callback by passing the arguments using an associative container.
|
* Execute the designated callback by passing the arguments in their specified order.
|
||||||
*/
|
*/
|
||||||
SQInteger Execute(const Object & invoker, const Table & args)
|
SQInteger Execute(const Object & invoker, const LightObj & args)
|
||||||
{
|
{
|
||||||
// Attempt to evaluate the specified executer knowing the manager did the validations
|
// Attempt to evaluate the specified executer knowing the manager did the validations
|
||||||
SharedPtr< SQInteger > ret = m_OnExec.Evaluate< SQInteger, const Object &, const Table & >(invoker, args);
|
SharedPtr< SQInteger > ret = m_OnExec.Evaluate< SQInteger, const Object &, const LightObj & >(invoker, args);
|
||||||
// See if the executer succeeded and return the result or default to failed
|
// See if the executer succeeded and return the result or default to failed
|
||||||
return (!ret ? 0 : *ret);
|
return (!ret ? 0 : *ret);
|
||||||
}
|
}
|
||||||
@ -1941,6 +1961,7 @@ private:
|
|||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
Function m_OnExec; // Function to call when the command is executed.
|
Function m_OnExec; // Function to call when the command is executed.
|
||||||
Function m_OnAuth; // Function to call when the invoker must be authenticated.
|
Function m_OnAuth; // Function to call when the invoker must be authenticated.
|
||||||
|
Function m_OnAudit; // Function to call when the parameters must be validated.
|
||||||
Function m_OnPost; // Function to call after the command was successfully executed.
|
Function m_OnPost; // Function to call after the command was successfully executed.
|
||||||
Function m_OnFail; // Function to call after the command execution failed.
|
Function m_OnFail; // Function to call after the command execution failed.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user