diff --git a/include/sqrat/sqratTypes.h b/include/sqrat/sqratTypes.h index 6a588a4a..e763b837 100644 --- a/include/sqrat/sqratTypes.h +++ b/include/sqrat/sqratTypes.h @@ -1029,7 +1029,7 @@ struct Var { /// /// \param vm Target VM /// \param idx Index trying to be read - /// \param idx Whether to mimmic a format function + /// \param fmt Whether to mimmic a format function /// /// \remarks /// This function MUST have its Error handled if it occurred. @@ -1040,6 +1040,26 @@ struct Var { ErrorToException(vm); } } + // Quick and dirty way to subtract the function pointer from the stack top as to not confuse formatted functions + enum DropFuncPtrOverload { DropFuncPtr }; + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Attempts to get the value off the stack at idx as an StackStrF + /// + /// \param vm Target VM + /// \param idx Index trying to be read + /// \param fmt Whether to mimmic a format function + /// \param top Number of slots to ignore from the stack top + /// + /// \remarks + /// This function MUST have its Error handled if it occurred. + /// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Var(HSQUIRRELVM vm, SQInteger idx, bool fmt, DropFuncPtrOverload /*fpsub*/) : value(vm, idx) { + if (SQ_FAILED(value.Proc(fmt, sq_gettop(vm) - 1))) { + ErrorToException(vm); + } + } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// Called by Sqrat::PushVar to put an StackStrF on the stack @@ -1064,6 +1084,8 @@ template<> struct Var : Var { Var(HSQUIRRELVM vm, SQInteger idx) : Var(vm, idx) {} Var(HSQUIRRELVM vm, SQInteger idx, bool fmt) : Var(vm, idx, fmt) {} + Var(HSQUIRRELVM vm, SQInteger idx, bool fmt, Var::DropFuncPtrOverload /*fpsub*/) + : Var(vm, idx, fmt, Var::DropFuncPtr) {} }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1073,6 +1095,8 @@ template<> struct Var : Var { Var(HSQUIRRELVM vm, SQInteger idx) : Var(vm, idx) {} Var(HSQUIRRELVM vm, SQInteger idx, bool fmt) : Var(vm, idx, fmt) {} + Var(HSQUIRRELVM vm, SQInteger idx, bool fmt, Var::DropFuncPtrOverload /*fpsub*/) + : Var(vm, idx, fmt, Var::DropFuncPtr) {} }; // Non-referencable type definitions @@ -1217,7 +1241,7 @@ template struct ArgFwdFmtVar : Var { ArgFwdFmtVar(HSQUIRRELVM vm, SQInteger idx) : Var(vm, idx) {} }; template struct ArgFwdFmtVar : Var { - ArgFwdFmtVar(HSQUIRRELVM vm, SQInteger idx) : Var(vm, idx, true) {} + ArgFwdFmtVar(HSQUIRRELVM vm, SQInteger idx) : Var(vm, idx, true, Var::DropFuncPtr) {} }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/include/sqrat/sqratUtil.h b/include/sqrat/sqratUtil.h index 53b1edf5..50052262 100644 --- a/include/sqrat/sqratUtil.h +++ b/include/sqrat/sqratUtil.h @@ -1545,6 +1545,15 @@ private: SQInteger m_Top; ///< The top of the stack when this instance was created. }; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// Helper function to transform a negative index into a positive index. +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline SQInteger IndexAbs(SQInteger top, SQInteger idx) +{ + return (idx <= -1) ? (top + idx + 1) : idx; +} + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// Helper structure for retrieving a value from the stack as a string or a formatted string. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1663,7 +1672,7 @@ struct StackStrF ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// Actual implementation. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - SQRESULT Proc(bool fmt = false) + SQRESULT Proc(bool fmt = false, SQInteger top = -1) { // If there's no virtual machine, just ignore the request if (mVM == nullptr) @@ -1677,8 +1686,13 @@ struct StackStrF } // Reset the converted value object sq_resetobject(&mObj); - // Grab the top of the stack - const SQInteger top = sq_gettop(mVM); + // Grab the top of the stack, if necessary + if (top < 0) + { + top = sq_gettop(mVM); + } + // Make the stack index absolute + mIdx = IndexAbs(top, mIdx); // Was the string or value specified? if (top <= (mIdx - 1)) { @@ -1766,7 +1780,7 @@ struct StackStrF /// \param keep Whether to clear the error from the VM /// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -static void ErrorToException(HSQUIRRELVM vm, bool keep = false) { +inline void ErrorToException(HSQUIRRELVM vm, bool keep = false) { // Get the error object on the stack sq_getlasterror(vm); // See if there's an actual error