From 113d74e8684cece46d8d8a5ad4af98566a5ec7bd Mon Sep 17 00:00:00 2001 From: Sandu Liviu Catalin Date: Fri, 26 Jul 2019 19:59:34 +0300 Subject: [PATCH] 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. --- source/Base/Algo.hpp | 9 ------- source/Misc/Routine.cpp | 55 ++++++++++++++++++++++++++++++++++++++--- source/Misc/Routine.hpp | 45 ++++++++++++++++++++++++++++++--- source/SqBase.hpp | 9 +++++++ 4 files changed, 102 insertions(+), 16 deletions(-) diff --git a/source/Base/Algo.hpp b/source/Base/Algo.hpp index ce0c10da..a5dc1f52 100644 --- a/source/Base/Algo.hpp +++ b/source/Base/Algo.hpp @@ -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'. */ diff --git a/source/Misc/Routine.cpp b/source/Misc/Routine.cpp index 3a61044b..a3865d97 100644 --- a/source/Misc/Routine.cpp +++ b/source/Misc/Routine.cpp @@ -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 diff --git a/source/Misc/Routine.hpp b/source/Misc/Routine.hpp index 442f85f5..0c14e54e 100644 --- a/source/Misc/Routine.hpp +++ b/source/Misc/Routine.hpp @@ -97,10 +97,19 @@ private: void Init(HSQOBJECT & env, HSQOBJECT & func, HSQOBJECT & inst, Interval intrv, Iterator itr) { // Initialize the callback objects - mEnv = LightObj(env); - mFunc = LightObj(func); + if (!sq_isnull(env)) + { + mEnv = LightObj(env); + } + if (!sq_isnull(func)) + { + mFunc = LightObj(func); + } // Associate with the routine instance - mInst = LightObj(inst); + 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 diff --git a/source/SqBase.hpp b/source/SqBase.hpp index 2b7de918..320d12f6 100644 --- a/source/SqBase.hpp +++ b/source/SqBase.hpp @@ -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 */