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

Enhance the routine implementation further by allowing it to be used as the environment itself and include a few extra helpers to avoid extra checks and lookups.

This commit is contained in:
Sandu Liviu Catalin 2019-07-26 19:59:34 +03:00
parent aa976c7f89
commit 113d74e868
4 changed files with 102 additions and 16 deletions

View File

@ -16,15 +16,6 @@
namespace SqMod {
namespace Algo {
// ------------------------------------------------------------------------------------------------
#ifdef _WIN32
#define sqmod_stricmp(a,b) stricmp(a,b)
#define sqmod_strnicmp(a,b,n) strnicmp(a,b,n)
#else
#define sqmod_stricmp(a,b) strcasecmp(a,b)
#define sqmod_strnicmp(a,b,n) strncasecmp(a,b,n)
#endif
/* ------------------------------------------------------------------------------------------------
* Returns a pointer to the first occurrence of 'needle' in 'haystack'.
*/

View File

@ -108,8 +108,34 @@ SQInteger Routine::Create(HSQUIRRELVM vm)
SQRESULT res = SQ_OK;
// Prepare an object for the environment
HSQOBJECT env;
// Get the type of the environment object
const SQObjectType etype = sq_gettype(vm, 2);
// Whether to default to the root table
bool use_root = etype == OT_NULL;
// Is the specified environment a boolean (true) value?
if (etype == OT_STRING)
{
// Attempt to generate the string value
StackStrF val(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.Proc()))
{
return val.mRes; // Propagate the error!
}
// If the string is empty or "root" then we use the root table
else if (!val.mLen || sqmod_stricmp(val.mPtr, "root") == 0)
{
use_root = true;
}
// If the string is "self" then we leave it null and default to self
else if (sqmod_stricmp(val.mPtr, "self") == 0)
{
sq_resetobject(&env); // Make sure environment is null
use_root = false; // Just in case
}
}
// Is the specified environment a null value?
if (sq_gettype(vm, 2) == OT_NULL)
if (use_root)
{
// Preserve the stack state
const StackGuard sg(vm);
@ -118,7 +144,8 @@ SQInteger Routine::Create(HSQUIRRELVM vm)
// Attempt to retrieve the table object
res = sq_getstackobj(vm, -1, &env);
}
else
// Should we treat it as a valid environment object?
else if (etype != OT_STRING)
{
sq_getstackobj(vm, 2, &env); // Just retrieve the specified environment
}
@ -250,6 +277,26 @@ bool Routine::IsWithTag(StackStrF & tag)
return false;
}
// ------------------------------------------------------------------------------------------------
bool Routine::TerminateWithTag(StackStrF & tag)
{
// Is the specified tag valid?
if (tag.mPtr != nullptr)
{
// Iterate routine list
for (auto & r : s_Instances)
{
if (!r.mInst.IsNull() && r.mTag.compare(tag.mPtr) == 0)
{
r.Terminate(); // Yup, we're doing this
return true; // A routine was terminated
}
}
}
// Unable to find such routine
return false;
}
/* ------------------------------------------------------------------------------------------------
* Forward the call to process routines.
*/
@ -294,7 +341,7 @@ void Register_Routine(HSQUIRRELVM vm)
.Prop(_SC("Endure"), &Routine::GetEndure, &Routine::SetEndure)
.Prop(_SC("Arguments"), &Routine::GetArguments)
// Member Methods
.FmtFunc(_SC("SetTag"), &Routine::SetTag)
.FmtFunc(_SC("SetTag"), &Routine::ApplyTag)
.Func(_SC("SetData"), &Routine::ApplyData)
.Func(_SC("SetInterval"), &Routine::ApplyInterval)
.Func(_SC("SetIterations"), &Routine::ApplyIterations)
@ -303,11 +350,13 @@ void Register_Routine(HSQUIRRELVM vm)
.Func(_SC("SetEndure"), &Routine::ApplyEndure)
.Func(_SC("Terminate"), &Routine::Terminate)
.Func(_SC("GetArgument"), &Routine::GetArgument)
.Func(_SC("DropEnv"), &Routine::DropEnv)
);
// Global functions
RootTable(vm).SquirrelFunc(_SC("SqRoutine"), &Routine::Create);
RootTable(vm).FmtFunc(_SC("SqFindRoutineByTag"), &Routine::FindByTag);
RootTable(vm).FmtFunc(_SC("SqIsRoutineWithTag"), &Routine::IsWithTag);
RootTable(vm).FmtFunc(_SC("SqTerminateRoutineWithTag"), &Routine::TerminateWithTag);
}
} // Namespace:: SqMod

View File

@ -97,10 +97,19 @@ private:
void Init(HSQOBJECT & env, HSQOBJECT & func, HSQOBJECT & inst, Interval intrv, Iterator itr)
{
// Initialize the callback objects
if (!sq_isnull(env))
{
mEnv = LightObj(env);
}
if (!sq_isnull(func))
{
mFunc = LightObj(func);
}
// Associate with the routine instance
if (!sq_isnull(inst))
{
mInst = LightObj(inst);
}
// Initialize the routine options
mIterations = itr;
mInterval = intrv;
@ -138,7 +147,14 @@ private:
// Push the function on the stack
sq_pushobject(vm, mFunc);
// Push the environment on the stack
sq_pushobject(vm, mEnv);
if (!mEnv.IsNull())
{
sq_pushobject(vm, mEnv); // Push object
}
else
{
sq_pushobject(vm, mInst); // Push self
}
// Push function parameters, if any
for (Uint32 n = 0; n < mArgc; ++n)
{
@ -309,6 +325,10 @@ public:
* Check if a routine with a certain tag exists.
*/
static bool IsWithTag(StackStrF & tag);
/* --------------------------------------------------------------------------------------------
* Check if a routine with a certain tag exists.
*/
static bool TerminateWithTag(StackStrF & tag);
/* --------------------------------------------------------------------------------------------
* Process all active routines and update elapsed time.
*/
@ -389,6 +409,15 @@ public:
GetValid().mTag.assign(tag.mPtr, ClampMin(tag.mLen, 0));
}
/* --------------------------------------------------------------------------------------------
* Modify the associated user tag.
*/
Routine & ApplyTag(StackStrF & tag)
{
SetTag(tag);
return *this;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the environment object.
*/
@ -600,6 +629,14 @@ public:
// Return the requested argument
return GetValid().mArgv[idx];
}
/* --------------------------------------------------------------------------------------------
* Release the environment object and default to self.
*/
void DropEnv()
{
GetValid().mEnv.Release();
}
};
} // Namespace:: SqMod

View File

@ -473,6 +473,15 @@ enum EntityType
#define SQMOD_CONCAT_(a,b) a##b
#define SQMOD_CONCAT(a,b) SQMOD_CONCAT_(a,b)
// ------------------------------------------------------------------------------------------------
#ifdef _WIN32
#define sqmod_stricmp(a,b) stricmp(a,b)
#define sqmod_strnicmp(a,b,n) strnicmp(a,b,n)
#else
#define sqmod_stricmp(a,b) strcasecmp(a,b)
#define sqmod_strnicmp(a,b,n) strncasecmp(a,b,n)
#endif
/* ------------------------------------------------------------------------------------------------
* OS SPECIFFIC OPTIONS
*/