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

Move the plugin Squirrel utilities to the Sqrat binding utility.

Implement registration of functions and methods with string formatting support in the Sqrat binding utility.
Few minor other fixes.
This commit is contained in:
Sandu Liviu Catalin 2016-11-16 11:54:07 +02:00
parent ed599c06dd
commit 0137dfc66f
8 changed files with 5119 additions and 203 deletions

View File

@ -394,6 +394,23 @@ public:
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a class function with formatting support
///
/// \param name Name of the function as it will appear in Squirrel
/// \param method Function to bind
///
/// \tparam F Type of function (usually doesnt need to be defined explicitly)
///
/// \return The Class itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class F>
Class& FmtFunc(const SQChar* name, F method) {
BindFunc(name, &method, sizeof(method), SqMemberFuncFmt(method));
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a class function with overloading enabled
///
@ -432,6 +449,23 @@ public:
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a global function as a class function with formatting support
///
/// \param name Name of the function as it will appear in Squirrel
/// \param method Function to bind
///
/// \tparam F Type of function (usually doesnt need to be defined explicitly)
///
/// \return The Class itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class F>
Class& GlobalFmtFunc(const SQChar* name, F method) {
BindFunc(name, &method, sizeof(method), SqMemberGlobalFmtFunc(method));
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a static class function
///
@ -449,6 +483,23 @@ public:
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a static class function with formatting support
///
/// \param name Name of the function as it will appear in Squirrel
/// \param method Function to bind
///
/// \tparam F Type of function (usually doesnt need to be defined explicitly)
///
/// \return The Class itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class F>
Class& StaticFmtFunc(const SQChar* name, F method) {
BindFunc(name, &method, sizeof(method), SqGlobalFmtFunc(method));
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a global function as a class function with overloading enabled
///

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -250,6 +250,23 @@ public:
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Sets a key in the Table to a specific function with formatting support
///
/// \param name The key in the table being assigned a value
/// \param method Function that is being placed in the Table
///
/// \tparam F Type of function (only define this if you need to choose a certain template specialization or overload)
///
/// \return The Table itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class F>
TableBase& FmtFunc(const SQChar* name, F method) {
BindFunc(name, &method, sizeof(method), SqGlobalFmtFunc(method));
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Sets a key in the Table to a specific function and allows the key to be overloaded with functions of a different amount of arguments
///

View File

@ -1020,6 +1020,74 @@ public:
};
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Used to get and push StackStrF types to and from the stack
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
struct Var<StackStrF &> {
StackStrF value; ///< The actual value of get operations
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Attempts to get the value off the stack at idx as a string
///
/// \param vm Target VM
/// \param idx Index trying to be read
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Var(HSQUIRRELVM vm, SQInteger idx) : value(vm, idx, false) {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Called by Sqrat::PushVar to put a string on the stack
///
/// \param vm Target VM
/// \param value Value to push on to the VM's stack
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void push(HSQUIRRELVM vm, const StackStrF& value) {
if (sq_isstring(value.mObj)) {
sq_pushobject(vm, value.mObj);
} else {
sq_pushstring(vm, value.mPtr, value.mLen);
}
}
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Used to get and push StackStrF types to and from the stack
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
struct Var<const StackStrF&> {
StackStrF value; ///< The actual value of get operations
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Attempts to get the value off the stack at idx as a string
///
/// \param vm Target VM
/// \param idx Index trying to be read
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Var(HSQUIRRELVM vm, SQInteger idx) : value(vm, idx, false) {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Called by Sqrat::PushVar to put a string on the stack
///
/// \param vm Target VM
/// \param value Value to push on to the VM's stack
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void push(HSQUIRRELVM vm, const StackStrF& value) {
if (sq_isstring(value.mObj)) {
sq_pushobject(vm, value.mObj);
} else {
sq_pushstring(vm, value.mPtr, value.mLen);
}
}
};
// Non-referencable type definitions
template<class T> struct is_referencable {static const bool value = true;};

View File

@ -32,6 +32,7 @@
#include <SqAPI.h>
#else
#include <squirrel.h>
#include <sqstdstring.h>
#endif // SQMOD_PLUGIN_API
#include <cassert>
@ -1417,6 +1418,201 @@ public:
}
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Implements RAII to restore the VM stack to it's initial size on function exit.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct StackGuard
{
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Default constructor.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackGuard()
: m_VM(DefaultVM::Get()), m_Top(sq_gettop(m_VM))
{
/* ... */
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Base constructor.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackGuard(HSQUIRRELVM vm)
: m_VM(vm), m_Top(sq_gettop(vm))
{
/* ... */
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy constructor. (disabled)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackGuard(const StackGuard &) = delete;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Move constructor. (disabled)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackGuard(StackGuard &&) = delete;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Destructor.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
~StackGuard()
{
sq_pop(m_VM, sq_gettop(m_VM) - m_Top);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy assignment operator. (disabled)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackGuard & operator = (const StackGuard &) = delete;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Move assignment operator. (disabled)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackGuard & operator = (StackGuard &&) = delete;
private:
HSQUIRRELVM m_VM; ///< The VM where the stack should be restored.
SQInteger m_Top; ///< The top of the stack when this instance was created.
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Helper structure for retrieving a value from the stack as a string or a formatted string.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct StackStrF
{
const SQChar * mPtr; ///< Pointer to the C string that was retrieved.
SQInteger mLen; ///< The string length if it could be retrieved.
SQRESULT mRes; ///< The result of the retrieval attempts.
HSQOBJECT mObj; ///< Strong reference to the string object.
HSQUIRRELVM mVM; ///< The associated virtual machine.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Base constructor.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackStrF(HSQUIRRELVM vm, SQInteger idx, bool fmt = true)
: mPtr(nullptr)
, mLen(-1)
, mRes(SQ_OK)
, mObj()
, mVM(vm)
{
const SQInteger top = sq_gettop(vm);
// Reset the converted value object
sq_resetobject(&mObj);
// Was the string or value specified?
if (top <= (idx - 1))
{
mRes = sq_throwerror(vm, "Missing string or value");
}
// Do we have enough values to call the format function and are we allowed to?
else if ((top - 1) > idx && fmt)
{
// Pointer to the generated string
SQChar * str = nullptr;
// Attempt to generate the specified string format
mRes = sqstd_format(vm, idx, &mLen, &str);
// Did the format succeeded but ended up with a null string pointer?
if (SQ_SUCCEEDED(mRes) && !str)
{
mRes = sq_throwerror(vm, "Unable to generate the string");
}
else
{
mPtr = const_cast< const SQChar * >(str);
}
}
// Is the value on the stack an actual string?
else if (sq_gettype(vm, idx) == OT_STRING)
{
// Obtain a reference to the string object
mRes = sq_getstackobj(vm, idx, &mObj);
// Could we retrieve the object from the stack?
if (SQ_SUCCEEDED(mRes))
{
// Keep a strong reference to the object
sq_addref(vm, &mObj);
// Attempt to retrieve the string value from the stack
mRes = sq_getstringandsize(vm, idx, &mPtr, &mLen);
}
// Did the retrieval succeeded but ended up with a null string pointer?
if (SQ_SUCCEEDED(mRes) && !mPtr)
{
mRes = sq_throwerror(vm, "Unable to retrieve the string");
}
}
// We have to try and convert it to string
else
{
// Attempt to convert the value from the stack to a string
mRes = sq_tostring(vm, idx);
// Could we convert the specified value to string?
if (SQ_SUCCEEDED(mRes))
{
// Obtain a reference to the resulted object
mRes = sq_getstackobj(vm, -1, &mObj);
// Could we retrieve the object from the stack?
if (SQ_SUCCEEDED(mRes))
{
// Keep a strong reference to the object
sq_addref(vm, &mObj);
// Attempt to obtain the string pointer
mRes = sq_getstringandsize(vm, -1, &mPtr, &mLen);
}
}
// Pop a value from the stack regardless of the result
sq_pop(vm, 1);
// Did the retrieval succeeded but ended up with a null string pointer?
if (SQ_SUCCEEDED(mRes) && !mPtr)
{
mRes = sq_throwerror(vm, "Unable to retrieve the value");
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy constructor. (disabled)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackStrF(const StackStrF & o) = delete;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy constructor.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackStrF(StackStrF && o)
: mPtr(o.mPtr)
, mLen(o.mLen)
, mRes(o.mRes)
, mObj(o.mObj)
, mVM(o.mVM)
{
o.mPtr = nullptr;
o.mLen = 0;
o.mRes = SQ_OK;
o.mVM = nullptr;
sq_resetobject(&o.mObj);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Destructor.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
~StackStrF()
{
if (mVM && !sq_isnull(mObj))
{
sq_release(mVM, &mObj);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy constructor. (disabled)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackStrF & operator = (const StackStrF & o) = delete;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Move constructor. (disabled)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
StackStrF & operator = (StackStrF && o) = delete;
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @cond DEV
/// Used internally to get and manipulate the underlying type of variables - retrieved from cppreference.com

View File

@ -1456,119 +1456,6 @@ public:
}
};
/* ------------------------------------------------------------------------------------------------
* Implements RAII to restore the VM stack to it's initial size on function exit.
*/
struct StackGuard
{
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
StackGuard()
: m_VM(DefaultVM::Get()), m_Top(sq_gettop(m_VM))
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
StackGuard(HSQUIRRELVM vm)
: m_VM(vm), m_Top(sq_gettop(vm))
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
StackGuard(const StackGuard &) = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor. (disabled)
*/
StackGuard(StackGuard &&) = delete;
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~StackGuard()
{
sq_pop(m_VM, sq_gettop(m_VM) - m_Top);
}
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
StackGuard & operator = (const StackGuard &) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
StackGuard & operator = (StackGuard &&) = delete;
private:
// --------------------------------------------------------------------------------------------
HSQUIRRELVM m_VM; // The VM where the stack should be restored.
Int32 m_Top; // The top of the stack when this instance was created.
};
/* ------------------------------------------------------------------------------------------------
* Helper structure for retrieving a value from the stack as a string or a formatted string.
*/
struct StackStrF
{
// --------------------------------------------------------------------------------------------
CSStr mPtr; // Pointer to the C string that was retrieved.
SQInteger mLen; // The string length if it could be retrieved.
SQRESULT mRes; // The result of the retrieval attempts.
HSQOBJECT mObj; // Strong reference to the string object.
HSQUIRRELVM mVM; // The associated virtual machine.
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
StackStrF(HSQUIRRELVM vm, SQInteger idx, bool fmt = true);
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
StackStrF(const StackStrF & o) = delete;
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
StackStrF(StackStrF && o)
: mPtr(o.mPtr)
, mLen(o.mLen)
, mRes(o.mRes)
, mObj(o.mObj)
, mVM(o.mVM)
{
o.mPtr = nullptr;
o.mLen = 0;
o.mRes = SQ_OK;
o.mVM = nullptr;
sq_resetobject(&o.mObj);
}
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~StackStrF();
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
StackStrF & operator = (const StackStrF & o) = delete;
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
StackStrF & operator = (StackStrF && o) = delete;
};
/* ------------------------------------------------------------------------------------------------
* Retrieve the string representation of a certain type.
*/

View File

@ -564,96 +564,6 @@ bool ConvNum< bool >::FromStr(CSStr s, Int32 /*base*/)
return (std::strcmp(s, "true") == 0) ? true : false;
}
// --------------------------------------------------------------------------------------------
StackStrF::StackStrF(HSQUIRRELVM vm, SQInteger idx, bool fmt)
: mPtr(nullptr)
, mLen(-1)
, mRes(SQ_OK)
, mObj()
, mVM(vm)
{
const Int32 top = sq_gettop(vm);
// Reset the converted value object
sq_resetobject(&mObj);
// Was the string or value specified?
if (top <= (idx - 1))
{
mRes = sq_throwerror(vm, "Missing string or value");
}
// Do we have enough values to call the format function and are we allowed to?
else if (top > idx && fmt)
{
// Pointer to the generated string
SStr str = nullptr;
// Attempt to generate the specified string format
mRes = sqstd_format(vm, idx, &mLen, &str);
// Did the format succeeded but ended up with a null string pointer?
if (SQ_SUCCEEDED(mRes) && !str)
{
mRes = sq_throwerror(vm, "Unable to generate the string");
}
else
{
mPtr = const_cast< CSStr >(str);
}
}
// Is the value on the stack an actual string?
else if (sq_gettype(vm, idx) == OT_STRING)
{
// Obtain a reference to the string object
mRes = sq_getstackobj(vm, idx, &mObj);
// Could we retrieve the object from the stack?
if (SQ_SUCCEEDED(mRes))
{
// Keep a strong reference to the object
sq_addref(vm, &mObj);
// Attempt to retrieve the string value from the stack
mRes = sq_getstringandsize(vm, idx, &mPtr, &mLen);
}
// Did the retrieval succeeded but ended up with a null string pointer?
if (SQ_SUCCEEDED(mRes) && !mPtr)
{
mRes = sq_throwerror(vm, "Unable to retrieve the string");
}
}
// We have to try and convert it to string
else
{
// Attempt to convert the value from the stack to a string
mRes = sq_tostring(vm, idx);
// Could we convert the specified value to string?
if (SQ_SUCCEEDED(mRes))
{
// Obtain a reference to the resulted object
mRes = sq_getstackobj(vm, -1, &mObj);
// Could we retrieve the object from the stack?
if (SQ_SUCCEEDED(mRes))
{
// Keep a strong reference to the object
sq_addref(vm, &mObj);
// Attempt to obtain the string pointer
mRes = sq_getstringandsize(vm, -1, &mPtr, &mLen);
}
}
// Pop a value from the stack regardless of the result
sq_pop(vm, 1);
// Did the retrieval succeeded but ended up with a null string pointer?
if (SQ_SUCCEEDED(mRes) && !mPtr)
{
mRes = sq_throwerror(vm, "Unable to retrieve the value");
}
}
}
// ------------------------------------------------------------------------------------------------
StackStrF::~StackStrF()
{
if (mVM && !sq_isnull(mObj))
{
sq_release(mVM, &mObj);
}
}
// ------------------------------------------------------------------------------------------------
CSStr SqTypeName(SQObjectType type)
{