mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 00:37:15 +01:00
Added external Sqrat library.
This commit is contained in:
parent
c3b811cfff
commit
08f7f396c9
20
external/Sqrat/License.txt
vendored
Normal file
20
external/Sqrat/License.txt
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
Copyright (c) 2009 Brandon Jones
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
373
external/Sqrat/sqratThread.cpp
vendored
Normal file
373
external/Sqrat/sqratThread.cpp
vendored
Normal file
@ -0,0 +1,373 @@
|
||||
//
|
||||
// SqratThread: Sqrat threading module
|
||||
//
|
||||
|
||||
//
|
||||
// Copyright (c) 2009 Brandon Jones
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
|
||||
//#include "sqratlib/sqratBase.h"
|
||||
#include "sqratThread.h"
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
static HSQAPI sq;
|
||||
|
||||
//
|
||||
// Thread lib utility functions (not visible externally)
|
||||
//
|
||||
|
||||
static SQFloat sqrat_clock() {
|
||||
return ((SQFloat)clock())/(SQFloat)CLOCKS_PER_SEC;
|
||||
}
|
||||
|
||||
static SQInteger sqrat_strlen(const SQChar* str) {
|
||||
#if defined(_UNICODE)
|
||||
return static_cast<SQInteger>(wcslen(str) * sizeof(SQChar));
|
||||
#else
|
||||
return static_cast<SQInteger>(strlen(str) * sizeof(SQChar));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void sqrat_pushtaskarray(HSQUIRRELVM v) {
|
||||
HSQOBJECT taskarray;
|
||||
|
||||
sq->pushroottable(v);
|
||||
sq->pushstring(v,_SC("__sqrat_taskarray__"),-1);
|
||||
if(SQ_FAILED(sq->get(v, -2))) {
|
||||
// Not found, create a new namespace
|
||||
sq->pushstring(v,_SC("__sqrat_taskarray__"),-1);
|
||||
sq->newarray(v, 0);
|
||||
sq->getstackobj(v,-1,&taskarray); // Save namespace for later use
|
||||
sq->newslot(v, -3, 0);
|
||||
sq->pop(v, 1); // pop root table
|
||||
|
||||
sq->pushobject(v, taskarray); // push the newly bound array
|
||||
} else {
|
||||
sq->remove(v, -2); // pop sqrat table
|
||||
}
|
||||
}
|
||||
|
||||
static SQRESULT sqrat_pushclosure(HSQUIRRELVM v, const SQChar* script) {
|
||||
if(SQ_FAILED(sq->compilebuffer(v, script, sqrat_strlen(script), _SC(""), true))) {
|
||||
return SQ_ERROR;
|
||||
}
|
||||
|
||||
sq->pushroottable(v);
|
||||
if(SQ_FAILED(sq->call(v, 1, 0, 1))) {
|
||||
sq->remove(v, -1); // remove compiled closure
|
||||
return SQ_ERROR;
|
||||
}
|
||||
sq->remove(v, -2); // remove compiled closure
|
||||
return SQ_OK;
|
||||
}
|
||||
|
||||
static SQInteger sqrat_schedule_argcall(HSQUIRRELVM v) {
|
||||
SQInteger nparams = sq->gettop(v) - 2; // Get the number of parameters provided
|
||||
|
||||
// The task table is the last argument (free variable), so we can operate on immediately
|
||||
sq->pushstring(v, _SC("args"), -1);
|
||||
|
||||
sq->newarray(v, 0); // Create the array for the arguments
|
||||
|
||||
// Loop through all arguments and push them into the arg array
|
||||
for(SQInteger i = 0; i < nparams; ++i) {
|
||||
sq->push(v, i+2);
|
||||
sq->arrayappend(v, -2);
|
||||
}
|
||||
|
||||
sq->newslot(v, -3, 0); // Push the arg array into the task table
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This is a horrid way to get this functionality in there, but I can't find any alternatives right now.
|
||||
static SQRESULT sqrat_pushsleep(HSQUIRRELVM v) {
|
||||
SQChar* sleep_script = _SC(" \
|
||||
__sqratsleep__ <- function(timeout) { \
|
||||
local begin = clock(); \
|
||||
local now; \
|
||||
do { \
|
||||
::suspend(); \
|
||||
now = clock(); \
|
||||
} while( (now - begin) < timeout ); \
|
||||
} \
|
||||
");
|
||||
|
||||
if(SQ_FAILED(sq->compilebuffer(v, sleep_script, sqrat_strlen(sleep_script), _SC(""), true))) {
|
||||
return SQ_ERROR;
|
||||
}
|
||||
|
||||
sq->pushroottable(v);
|
||||
if(SQ_FAILED(sq->call(v, 1, 0, 1))) {
|
||||
sq->remove(v, -1); // remove compiled closure
|
||||
return SQ_ERROR;
|
||||
}
|
||||
sq->remove(v, -1); // remove compiled closure
|
||||
|
||||
sq->pushroottable(v);
|
||||
sq->pushstring(v, _SC("__sqratsleep__"), -1);
|
||||
SQRESULT res = sq->get(v, -2);
|
||||
|
||||
sq->remove(v, -2); // remove root table
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//
|
||||
// Thread lib main functions
|
||||
//
|
||||
|
||||
static SQRESULT sqrat_sleep(HSQUIRRELVM v, SQFloat timeout) {
|
||||
return sq->suspendvm(v);
|
||||
|
||||
// Get "::suspend"
|
||||
/*HSQOBJECT suspend;
|
||||
sq->pushroottable(v);
|
||||
sq->pushstring(v, _SC("suspend"), -1);
|
||||
if(SQ_FAILED(sq->get(v, -2))) {
|
||||
return SQ_ERROR;
|
||||
}
|
||||
sq->getstackobj(v, -1, &suspend);
|
||||
sq->pop(v, 2);
|
||||
|
||||
// Loop ::suspend until the appropriate time has passed
|
||||
SQFloat timeStart = sqrat_clock();
|
||||
SQFloat timeNow = 0;
|
||||
|
||||
while(timeNow - timeStart < timeout) {
|
||||
sq->pushobject(v, suspend);
|
||||
sq->pushroottable(v);
|
||||
if(SQ_FAILED(sq->call(v, 1, 0, 1))) {
|
||||
return SQ_ERROR;
|
||||
}
|
||||
timeNow = sqrat_clock();
|
||||
}
|
||||
|
||||
return SQ_OK;*/
|
||||
}
|
||||
|
||||
static void sqrat_schedule(HSQUIRRELVM v, SQInteger idx) {
|
||||
HSQOBJECT thread;
|
||||
HSQOBJECT func;
|
||||
HSQOBJECT task;
|
||||
|
||||
sq->getstackobj(v, idx, &func);
|
||||
SQInteger stksize = 256; // TODO: Allow initial stack size to be configurable
|
||||
|
||||
sqrat_pushtaskarray(v); // Push the task array
|
||||
|
||||
// Create the task
|
||||
sq->newtable(v);
|
||||
sq->getstackobj(v, -1, &task);
|
||||
|
||||
// Create the thread and add it to the task table
|
||||
sq->pushstring(v, _SC("thread"), -1);
|
||||
sq->newthread(v, stksize);
|
||||
sq->getstackobj(v, -1, &thread);
|
||||
sq->newslot(v, -3, 0);
|
||||
|
||||
// Push the function to be called onto the thread stack
|
||||
sq->pushobject(v, func);
|
||||
sq->move(thread._unVal.pThread, v, -1);
|
||||
sq->pop(v, 1);
|
||||
|
||||
// Args will be pushed later, in the closure
|
||||
|
||||
sq->arrayappend(v, -2); // Add the task to the task array
|
||||
|
||||
sq->pushobject(v, task); // Push the task object as a free variable for the temporary closure
|
||||
sq->newclosure(v, sqrat_schedule_argcall, 1); // push a temporary closure used to retrieve call args
|
||||
}
|
||||
|
||||
// Wow... this has to be one of the ugliest functions I've ever writter. Ever.
|
||||
// Building complex logic with the squirrel stack really sucks.
|
||||
static void sqrat_run(HSQUIRRELVM v) {
|
||||
|
||||
HSQOBJECT taskArray;
|
||||
HSQOBJECT thread;
|
||||
HSQUIRRELVM threadVm;
|
||||
SQInteger nparams; // Number of parameters to pass to a function
|
||||
SQInteger arrayidx; //Cached index of the task array
|
||||
|
||||
// Push the tasklist
|
||||
sqrat_pushtaskarray(v); // Push the task array to the stack
|
||||
|
||||
sq->getstackobj(v, -1, &taskArray);
|
||||
arrayidx = sq->gettop(v); // Cache the stack location of the task array
|
||||
|
||||
SQInteger tasklistSize = sq->getsize(v, arrayidx); // Query the initial size of the task array
|
||||
do {
|
||||
SQInteger i = 0;
|
||||
|
||||
// This outer while is to allow us to pick up any new tasks that are added during the loop,
|
||||
// but still give us an opportunity to sleep after running through the initial tasks
|
||||
while(i < tasklistSize) {
|
||||
|
||||
for(; i < tasklistSize; ++i) {
|
||||
sq->pushinteger(v, i);
|
||||
if(SQ_FAILED(sq->get(v, -2))) { // Get the task
|
||||
sq->arrayremove(v, -2, i);
|
||||
sq->pop(v, 1);
|
||||
--tasklistSize;
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Now that we have the task, get the thread
|
||||
sq->pushstring(v, _SC("thread"), -1);
|
||||
if(SQ_FAILED(sq->get(v, -2))) {
|
||||
sq->arrayremove(v, -3, i);
|
||||
sq->pop(v, 1);
|
||||
--tasklistSize;
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
sq->getstackobj(v, -1, &thread);
|
||||
sq->pop(v, 1);
|
||||
|
||||
threadVm = thread._unVal.pThread;
|
||||
|
||||
if(sq->getvmstate(threadVm) == SQ_VMSTATE_IDLE) { // New thread? If so we need to call it
|
||||
|
||||
// Function to be called is already pushed to the thread (happens in schedule)
|
||||
sq->pushroottable(threadVm); // Pus the threads root table
|
||||
|
||||
sq->pushstring(v, _SC("args"), -1);
|
||||
if(SQ_FAILED(sq->get(v, -2))) { // Check to see if we have arguments for this thread
|
||||
nparams = 0; // No arguments
|
||||
} else {
|
||||
nparams = sq->getsize(v, -1); // Get the number of args in the arg array
|
||||
|
||||
// Push the arguments onto the thread stack
|
||||
for(SQInteger a = 0; a < nparams; ++a) {
|
||||
sq->pushinteger(v, a);
|
||||
if(SQ_FAILED(sq->get(v, -2))) {
|
||||
sq->pushnull(threadVm); // Is this the best way to handle this?
|
||||
} else {
|
||||
sq->move(threadVm, v, -1);
|
||||
sq->pop(v, 1);
|
||||
}
|
||||
}
|
||||
|
||||
sq->pop(v, 1); // Pop the arg array
|
||||
}
|
||||
|
||||
sq->call(threadVm, nparams+1, 0, 1); // Call the thread
|
||||
|
||||
} else {
|
||||
// If the thread is suspended, wake it up.
|
||||
// This function changed in Squirrel 2.2.3,
|
||||
// removing the last parameter makes it compatible with 2.2.2 and earlier
|
||||
sq->wakeupvm(threadVm, 0, 0, 1, 0);
|
||||
}
|
||||
|
||||
if(sq->getvmstate(threadVm) == SQ_VMSTATE_IDLE) { // Check to see if the thread is finished (idle again)
|
||||
sq->arrayremove(v, -2, i); // Remove the task from the task array
|
||||
|
||||
--tasklistSize; // Adjust the for variables to account for the removal
|
||||
--i;
|
||||
}
|
||||
|
||||
sq->pop(v, 1); // Pop off the task
|
||||
}
|
||||
|
||||
// Yield to system if needed
|
||||
|
||||
tasklistSize = sq->getsize(v, arrayidx); // Get the task
|
||||
|
||||
}
|
||||
|
||||
} while(tasklistSize > 0); // Loop until we have no more pending tasks
|
||||
}
|
||||
|
||||
//
|
||||
// Script interface functions
|
||||
//
|
||||
|
||||
static SQInteger sqratbase_sleep(HSQUIRRELVM v) {
|
||||
SQFloat timeout;
|
||||
sq->getfloat(v, -1, &timeout);
|
||||
sqrat_sleep(v, timeout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SQInteger sqratbase_schedule(HSQUIRRELVM v) {
|
||||
sqrat_schedule(v, -1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static SQInteger sqratbase_run(HSQUIRRELVM v) {
|
||||
sqrat_run(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This is a squirrel only function, since there's really no need to
|
||||
// expose a native api for it. Just use the VM that you would have passed
|
||||
// in anyway!
|
||||
static SQInteger sqratbase_getthread(HSQUIRRELVM v) {
|
||||
// For the record, this way of doing things really sucks.
|
||||
// I would love a better way of retrieving this object!
|
||||
HSQOBJECT threadObj;
|
||||
threadObj._type = OT_THREAD;
|
||||
threadObj._unVal.pThread = v;
|
||||
|
||||
sq->pushobject(v, threadObj);
|
||||
sq->weakref(v, -1);
|
||||
sq->remove(v, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//
|
||||
// Module registration
|
||||
//
|
||||
|
||||
SQRESULT sqmodule_load(HSQUIRRELVM v, HSQAPI api) {
|
||||
|
||||
sq = api;
|
||||
|
||||
sq->pushstring(v, _SC("schedule"), -1);
|
||||
sq->newclosure(v, &sqratbase_schedule, 0);
|
||||
sq->newslot(v, -3, 0);
|
||||
|
||||
sq->pushstring(v, _SC("run"), -1);
|
||||
sq->newclosure(v, &sqratbase_run, 0);
|
||||
sq->newslot(v, -3, 0);
|
||||
|
||||
sq->pushstring(v, _SC("getthread"), -1);
|
||||
sq->newclosure(v, &sqratbase_getthread, 0);
|
||||
sq->newslot(v, -3, 0);
|
||||
|
||||
// Would rather do this...
|
||||
/*sq->pushstring(v, _SC("sleep"), -1);
|
||||
sq->newclosure(v, &sqratbase_sleep, 0);
|
||||
sq->newslot(v, -3, 0);*/
|
||||
|
||||
// Than this...
|
||||
sq->pushstring(v, _SC("sleep"), -1);
|
||||
if(SQ_FAILED(sqrat_pushsleep(v))) {
|
||||
sq->pop(v, 1);
|
||||
} else {
|
||||
sq->newslot(v, -3, 0);
|
||||
}
|
||||
|
||||
return SQ_OK;
|
||||
}
|
308
external/Sqrat/sqratimport.cpp
vendored
Normal file
308
external/Sqrat/sqratimport.cpp
vendored
Normal file
@ -0,0 +1,308 @@
|
||||
//
|
||||
// SqratImport: Supports importing of squirrel modules
|
||||
//
|
||||
|
||||
//
|
||||
// Copyright (c) 2009 Brandon Jones
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
|
||||
#include "sqratimport.h"
|
||||
#include "sqmodule.h"
|
||||
|
||||
//#include "sqratlib/sqratBase.h"
|
||||
#include <sqstdio.h>
|
||||
#include <string>
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#elif defined(__unix)
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#endif
|
||||
|
||||
typedef SQRESULT (*SQMODULELOAD)(HSQUIRRELVM v, HSQAPI sq);
|
||||
|
||||
static HSQAPI sqapi = NULL;
|
||||
|
||||
// Create and populate the HSQAPI structure with function pointers
|
||||
// If new functions are added to the Squirrel API, they should be added here too
|
||||
static HSQAPI sqrat_newapi() {
|
||||
HSQAPI sq = (HSQAPI)sq_malloc(sizeof(sq_api));
|
||||
|
||||
/*vm*/
|
||||
sq->open = sq_open;
|
||||
sq->newthread = sq_newthread;
|
||||
sq->seterrorhandler = sq_seterrorhandler;
|
||||
sq->close = sq_close;
|
||||
sq->setforeignptr = sq_setforeignptr;
|
||||
sq->getforeignptr = sq_getforeignptr;
|
||||
sq->setprintfunc = sq_setprintfunc;
|
||||
sq->getprintfunc = sq_getprintfunc;
|
||||
sq->suspendvm = sq_suspendvm;
|
||||
sq->wakeupvm = sq_wakeupvm;
|
||||
sq->getvmstate = sq_getvmstate;
|
||||
|
||||
/*compiler*/
|
||||
sq->compile = sq_compile;
|
||||
sq->compilebuffer = sq_compilebuffer;
|
||||
sq->enabledebuginfo = sq_enabledebuginfo;
|
||||
sq->notifyallexceptions = sq_notifyallexceptions;
|
||||
sq->setcompilererrorhandler = sq_setcompilererrorhandler;
|
||||
|
||||
/*stack operations*/
|
||||
sq->push = sq_push;
|
||||
sq->pop = sq_pop;
|
||||
sq->poptop = sq_poptop;
|
||||
sq->remove = sq_remove;
|
||||
sq->gettop = sq_gettop;
|
||||
sq->settop = sq_settop;
|
||||
sq->reservestack = sq_reservestack;
|
||||
sq->cmp = sq_cmp;
|
||||
sq->move = sq_move;
|
||||
|
||||
/*object creation handling*/
|
||||
sq->newuserdata = sq_newuserdata;
|
||||
sq->newtable = sq_newtable;
|
||||
sq->newarray = sq_newarray;
|
||||
sq->newclosure = sq_newclosure;
|
||||
sq->setparamscheck = sq_setparamscheck;
|
||||
sq->bindenv = sq_bindenv;
|
||||
sq->pushstring = sq_pushstring;
|
||||
sq->pushfloat = sq_pushfloat;
|
||||
sq->pushinteger = sq_pushinteger;
|
||||
sq->pushbool = sq_pushbool;
|
||||
sq->pushuserpointer = sq_pushuserpointer;
|
||||
sq->pushnull = sq_pushnull;
|
||||
sq->gettype = sq_gettype;
|
||||
sq->getsize = sq_getsize;
|
||||
sq->getbase = sq_getbase;
|
||||
sq->instanceof = sq_instanceof;
|
||||
sq->tostring = sq_tostring;
|
||||
sq->tobool = sq_tobool;
|
||||
sq->getstring = sq_getstring;
|
||||
sq->getinteger = sq_getinteger;
|
||||
sq->getthread = sq_getthread;
|
||||
sq->getbool = sq_getbool;
|
||||
sq->getuserpointer = sq_getuserpointer;
|
||||
sq->getuserdata = sq_getuserdata;
|
||||
sq->settypetag = sq_settypetag;
|
||||
sq->gettypetag = sq_gettypetag;
|
||||
sq->setreleasehook = sq_setreleasehook;
|
||||
sq->getscratchpad = sq_getscratchpad;
|
||||
sq->getclosureinfo = sq_getclosureinfo;
|
||||
sq->setnativeclosurename = sq_setnativeclosurename;
|
||||
sq->setinstanceup = sq_setinstanceup;
|
||||
sq->getinstanceup = sq_getinstanceup;
|
||||
sq->setclassudsize = sq_setclassudsize;
|
||||
sq->newclass = sq_newclass;
|
||||
sq->createinstance = sq_createinstance;
|
||||
sq->setattributes = sq_setattributes;
|
||||
sq->getattributes = sq_getattributes;
|
||||
sq->getclass = sq_getclass;
|
||||
sq->weakref = sq_weakref;
|
||||
sq->getdefaultdelegate = sq_getdefaultdelegate;
|
||||
|
||||
/*object manipulation*/
|
||||
sq->pushroottable = sq_pushroottable;
|
||||
sq->pushregistrytable = sq_pushregistrytable;
|
||||
sq->pushconsttable = sq_pushconsttable;
|
||||
sq->setroottable = sq_setroottable;
|
||||
sq->setconsttable = sq_setconsttable;
|
||||
sq->newslot = sq_newslot;
|
||||
sq->deleteslot = sq_deleteslot;
|
||||
sq->set = sq_set;
|
||||
sq->get = sq_get;
|
||||
sq->rawset = sq_rawset;
|
||||
sq->rawget = sq_rawget;
|
||||
sq->rawdeleteslot = sq_rawdeleteslot;
|
||||
sq->arrayappend = sq_arrayappend;
|
||||
sq->arraypop = sq_arraypop;
|
||||
sq->arrayresize = sq_arrayresize;
|
||||
sq->arrayreverse = sq_arrayreverse;
|
||||
sq->arrayremove = sq_arrayremove;
|
||||
sq->arrayinsert = sq_arrayinsert;
|
||||
sq->setdelegate = sq_setdelegate;
|
||||
sq->getdelegate = sq_getdelegate;
|
||||
sq->clone = sq_clone;
|
||||
sq->setfreevariable = sq_setfreevariable;
|
||||
sq->next = sq_next;
|
||||
sq->getweakrefval = sq_getweakrefval;
|
||||
sq->clear = sq_clear;
|
||||
|
||||
/*calls*/
|
||||
sq->call = sq_call;
|
||||
sq->resume = sq_resume;
|
||||
sq->getlocal = sq_getlocal;
|
||||
sq->getfreevariable = sq_getfreevariable;
|
||||
sq->throwerror = sq_throwerror;
|
||||
sq->reseterror = sq_reseterror;
|
||||
sq->getlasterror = sq_getlasterror;
|
||||
|
||||
/*raw object handling*/
|
||||
sq->getstackobj = sq_getstackobj;
|
||||
sq->pushobject = sq_pushobject;
|
||||
sq->addref = sq_addref;
|
||||
sq->release = sq_release;
|
||||
sq->resetobject = sq_resetobject;
|
||||
sq->objtostring = sq_objtostring;
|
||||
sq->objtobool = sq_objtobool;
|
||||
sq->objtointeger = sq_objtointeger;
|
||||
sq->objtofloat = sq_objtofloat;
|
||||
sq->getobjtypetag = sq_getobjtypetag;
|
||||
|
||||
/*GC*/
|
||||
sq->collectgarbage = sq_collectgarbage;
|
||||
|
||||
/*serialization*/
|
||||
sq->writeclosure = sq_writeclosure;
|
||||
sq->readclosure = sq_readclosure;
|
||||
|
||||
/*mem allocation*/
|
||||
sq->malloc = sq_malloc;
|
||||
sq->realloc = sq_realloc;
|
||||
sq->free = sq_free;
|
||||
|
||||
/*debug*/
|
||||
sq->stackinfos = sq_stackinfos;
|
||||
sq->setdebughook = sq_setdebughook;
|
||||
|
||||
return sq;
|
||||
}
|
||||
|
||||
|
||||
static SQRESULT sqrat_importscript(HSQUIRRELVM v, const SQChar* moduleName) {
|
||||
std::basic_string<SQChar> filename(moduleName);
|
||||
filename += _SC(".nut");
|
||||
if(SQ_FAILED(sqstd_loadfile(v, moduleName, true))) {
|
||||
if(SQ_FAILED(sqstd_loadfile(v, filename.c_str(), true))) {
|
||||
return SQ_ERROR;
|
||||
}
|
||||
}
|
||||
sq_push(v, -2);
|
||||
sq_call(v, 1, false, true);
|
||||
return SQ_OK;
|
||||
}
|
||||
|
||||
static SQRESULT sqrat_importbin(HSQUIRRELVM v, const SQChar* moduleName) {
|
||||
#ifdef SQUNICODE
|
||||
#warning sqrat_importbin() Not Implemented
|
||||
return SQ_ERROR;
|
||||
#else
|
||||
SQMODULELOAD modLoad = 0;
|
||||
|
||||
#if defined(_WIN32)
|
||||
HMODULE mod;
|
||||
mod = GetModuleHandle(moduleName);
|
||||
if(mod == NULL) {
|
||||
mod = LoadLibrary(moduleName);
|
||||
if(mod == NULL) {
|
||||
return SQ_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
modLoad = (SQMODULELOAD)GetProcAddress(mod, "sqmodule_load");
|
||||
if(modLoad == NULL) {
|
||||
FreeLibrary(mod);
|
||||
return SQ_ERROR;
|
||||
}
|
||||
#elif defined(__unix)
|
||||
/* adding .so to moduleName? */
|
||||
void *mod = dlopen(moduleName, RTLD_NOW | RTLD_LOCAL | RTLD_NOLOAD); //RTLD_NOLOAD flag is not specified in POSIX.1-2001..so not the best solution :(
|
||||
if (mod == NULL) {
|
||||
mod = dlopen(moduleName, RTLD_NOW | RTLD_LOCAL);
|
||||
if (mod == NULL)
|
||||
return SQ_ERROR;
|
||||
}
|
||||
modLoad = (SQMODULELOAD) dlsym(mod, "sqmodule_load");
|
||||
if (modLoad == NULL) {
|
||||
dlclose(mod);
|
||||
return SQ_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(sqapi == NULL) {
|
||||
sqapi = sqrat_newapi(); // Caching this for multiple imports is probably a very good idea
|
||||
}
|
||||
|
||||
SQRESULT res = modLoad(v, sqapi);
|
||||
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
SQRESULT sqrat_import(HSQUIRRELVM v) {
|
||||
const SQChar* moduleName;
|
||||
HSQOBJECT table;
|
||||
SQRESULT res = SQ_OK;
|
||||
|
||||
|
||||
sq_getstring(v, -2, &moduleName);
|
||||
sq_getstackobj(v, -1, &table);
|
||||
sq_addref(v, &table);
|
||||
|
||||
sq_settop(v, 0); // Clear Stack
|
||||
sq_pushobject(v, table); // Push the target table onto the stack
|
||||
|
||||
if(SQ_FAILED(sqrat_importscript(v, moduleName))) {
|
||||
res = sqrat_importbin(v, moduleName);
|
||||
}
|
||||
|
||||
sq_settop(v, 0); // Clean up the stack (just in case the module load leaves it messy)
|
||||
sq_pushobject(v, table); // return the target table
|
||||
sq_release(v, &table);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static SQInteger sqratbase_import(HSQUIRRELVM v) {
|
||||
SQInteger args = sq_gettop(v);
|
||||
switch(args) {
|
||||
case 2:
|
||||
sq_pushroottable(v);
|
||||
break;
|
||||
case 3:
|
||||
// should already have the desired table pushed onto the stack
|
||||
break;
|
||||
default:
|
||||
// Error, unexpected number of arguments
|
||||
break;
|
||||
}
|
||||
|
||||
sqrat_import(v);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
SQRESULT sqrat_register_importlib(HSQUIRRELVM v) {
|
||||
sq_pushroottable(v);
|
||||
|
||||
sq_pushstring(v, _SC("import"), -1);
|
||||
sq_newclosure(v, &sqratbase_import, 0);
|
||||
sq_newslot(v, -3, 0);
|
||||
|
||||
sq_pop(v, 1); // pop sqrat table
|
||||
|
||||
return SQ_OK;
|
||||
}
|
199
include/sqmod.h
Normal file
199
include/sqmod.h
Normal file
@ -0,0 +1,199 @@
|
||||
//
|
||||
// SqModule: API used to communicate with and register squirrel modules
|
||||
//
|
||||
|
||||
//
|
||||
// Copyright (c) 2009 Brandon Jones
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
|
||||
#if !defined(_SQ_MODULE_H_)
|
||||
#define _SQ_MODULE_H_
|
||||
|
||||
#include "squirrel.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* HSQAPI */
|
||||
/*
|
||||
Allows modules to interface with squirrel's C api without linking to the squirrel library
|
||||
If new functions are added to the Squirrel API, they should be added here too
|
||||
*/
|
||||
typedef struct {
|
||||
/*vm*/
|
||||
HSQUIRRELVM (*open)(SQInteger initialstacksize);
|
||||
HSQUIRRELVM (*newthread)(HSQUIRRELVM friendvm, SQInteger initialstacksize);
|
||||
void (*seterrorhandler)(HSQUIRRELVM v);
|
||||
void (*close)(HSQUIRRELVM v);
|
||||
void (*setforeignptr)(HSQUIRRELVM v,SQUserPointer p);
|
||||
SQUserPointer (*getforeignptr)(HSQUIRRELVM v);
|
||||
#if SQUIRREL_VERSION_NUMBER >= 300
|
||||
void (*setprintfunc)(HSQUIRRELVM v, SQPRINTFUNCTION printfunc, SQPRINTFUNCTION);
|
||||
#else
|
||||
void (*setprintfunc)(HSQUIRRELVM v, SQPRINTFUNCTION printfunc);
|
||||
#endif
|
||||
SQPRINTFUNCTION (*getprintfunc)(HSQUIRRELVM v);
|
||||
SQRESULT (*suspendvm)(HSQUIRRELVM v);
|
||||
SQRESULT (*wakeupvm)(HSQUIRRELVM v,SQBool resumedret,SQBool retval,SQBool raiseerror,SQBool throwerror);
|
||||
SQInteger (*getvmstate)(HSQUIRRELVM v);
|
||||
|
||||
/*compiler*/
|
||||
SQRESULT (*compile)(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror);
|
||||
SQRESULT (*compilebuffer)(HSQUIRRELVM v,const SQChar *s,SQInteger size,const SQChar *sourcename,SQBool raiseerror);
|
||||
void (*enabledebuginfo)(HSQUIRRELVM v, SQBool enable);
|
||||
void (*notifyallexceptions)(HSQUIRRELVM v, SQBool enable);
|
||||
void (*setcompilererrorhandler)(HSQUIRRELVM v,SQCOMPILERERROR f);
|
||||
|
||||
/*stack operations*/
|
||||
void (*push)(HSQUIRRELVM v,SQInteger idx);
|
||||
void (*pop)(HSQUIRRELVM v,SQInteger nelemstopop);
|
||||
void (*poptop)(HSQUIRRELVM v);
|
||||
void (*remove)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQInteger (*gettop)(HSQUIRRELVM v);
|
||||
void (*settop)(HSQUIRRELVM v,SQInteger newtop);
|
||||
#if SQUIRREL_VERSION_NUMBER >= 300
|
||||
SQRESULT (*reservestack)(HSQUIRRELVM v,SQInteger nsize);
|
||||
#else
|
||||
void (*reservestack)(HSQUIRRELVM v,SQInteger nsize);
|
||||
#endif
|
||||
SQInteger (*cmp)(HSQUIRRELVM v);
|
||||
void (*move)(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx);
|
||||
|
||||
/*object creation handling*/
|
||||
SQUserPointer (*newuserdata)(HSQUIRRELVM v,SQUnsignedInteger size);
|
||||
void (*newtable)(HSQUIRRELVM v);
|
||||
void (*newarray)(HSQUIRRELVM v,SQInteger size);
|
||||
void (*newclosure)(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars);
|
||||
SQRESULT (*setparamscheck)(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask);
|
||||
SQRESULT (*bindenv)(HSQUIRRELVM v,SQInteger idx);
|
||||
void (*pushstring)(HSQUIRRELVM v,const SQChar *s,SQInteger len);
|
||||
void (*pushfloat)(HSQUIRRELVM v,SQFloat f);
|
||||
void (*pushinteger)(HSQUIRRELVM v,SQInteger n);
|
||||
void (*pushbool)(HSQUIRRELVM v,SQBool b);
|
||||
void (*pushuserpointer)(HSQUIRRELVM v,SQUserPointer p);
|
||||
void (*pushnull)(HSQUIRRELVM v);
|
||||
SQObjectType (*gettype)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQInteger (*getsize)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*getbase)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQBool (*instanceof)(HSQUIRRELVM v);
|
||||
#if SQUIRREL_VERSION_NUMBER >= 300
|
||||
SQRESULT (*tostring)(HSQUIRRELVM v,SQInteger idx);
|
||||
#else
|
||||
void (*tostring)(HSQUIRRELVM v,SQInteger idx);
|
||||
#endif
|
||||
void (*tobool)(HSQUIRRELVM v, SQInteger idx, SQBool *b);
|
||||
SQRESULT (*getstring)(HSQUIRRELVM v,SQInteger idx,const SQChar **c);
|
||||
SQRESULT (*getinteger)(HSQUIRRELVM v,SQInteger idx,SQInteger *i);
|
||||
SQRESULT (*getfloat)(HSQUIRRELVM v,SQInteger idx,SQFloat *f);
|
||||
SQRESULT (*getbool)(HSQUIRRELVM v,SQInteger idx,SQBool *b);
|
||||
SQRESULT (*getthread)(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread);
|
||||
SQRESULT (*getuserpointer)(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p);
|
||||
SQRESULT (*getuserdata)(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag);
|
||||
SQRESULT (*settypetag)(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag);
|
||||
SQRESULT (*gettypetag)(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag);
|
||||
void (*setreleasehook)(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook);
|
||||
SQChar* (*getscratchpad)(HSQUIRRELVM v,SQInteger minsize);
|
||||
SQRESULT (*getclosureinfo)(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars);
|
||||
SQRESULT (*setnativeclosurename)(HSQUIRRELVM v,SQInteger idx,const SQChar *name);
|
||||
SQRESULT (*setinstanceup)(HSQUIRRELVM v, SQInteger idx, SQUserPointer p);
|
||||
SQRESULT (*getinstanceup)(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag);
|
||||
SQRESULT (*setclassudsize)(HSQUIRRELVM v, SQInteger idx, SQInteger udsize);
|
||||
SQRESULT (*newclass)(HSQUIRRELVM v,SQBool hasbase);
|
||||
SQRESULT (*createinstance)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*setattributes)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*getattributes)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*getclass)(HSQUIRRELVM v,SQInteger idx);
|
||||
void (*weakref)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*getdefaultdelegate)(HSQUIRRELVM v,SQObjectType t);
|
||||
|
||||
/*object manipulation*/
|
||||
void (*pushroottable)(HSQUIRRELVM v);
|
||||
void (*pushregistrytable)(HSQUIRRELVM v);
|
||||
void (*pushconsttable)(HSQUIRRELVM v);
|
||||
SQRESULT (*setroottable)(HSQUIRRELVM v);
|
||||
SQRESULT (*setconsttable)(HSQUIRRELVM v);
|
||||
SQRESULT (*newslot)(HSQUIRRELVM v, SQInteger idx, SQBool bstatic);
|
||||
SQRESULT (*deleteslot)(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
|
||||
SQRESULT (*set)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*get)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*rawget)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*rawset)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*rawdeleteslot)(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
|
||||
SQRESULT (*arrayappend)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*arraypop)(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
|
||||
SQRESULT (*arrayresize)(HSQUIRRELVM v,SQInteger idx,SQInteger newsize);
|
||||
SQRESULT (*arrayreverse)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*arrayremove)(HSQUIRRELVM v,SQInteger idx,SQInteger itemidx);
|
||||
SQRESULT (*arrayinsert)(HSQUIRRELVM v,SQInteger idx,SQInteger destpos);
|
||||
SQRESULT (*setdelegate)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*getdelegate)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*clone)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*setfreevariable)(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval);
|
||||
SQRESULT (*next)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*getweakrefval)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*clear)(HSQUIRRELVM v,SQInteger idx);
|
||||
|
||||
/*calls*/
|
||||
SQRESULT (*call)(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror);
|
||||
SQRESULT (*resume)(HSQUIRRELVM v,SQBool retval,SQBool raiseerror);
|
||||
const SQChar* (*getlocal)(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx);
|
||||
const SQChar* (*getfreevariable)(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval);
|
||||
SQRESULT (*throwerror)(HSQUIRRELVM v,const SQChar *err);
|
||||
void (*reseterror)(HSQUIRRELVM v);
|
||||
void (*getlasterror)(HSQUIRRELVM v);
|
||||
|
||||
/*raw object handling*/
|
||||
SQRESULT (*getstackobj)(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po);
|
||||
void (*pushobject)(HSQUIRRELVM v,HSQOBJECT obj);
|
||||
void (*addref)(HSQUIRRELVM v,HSQOBJECT *po);
|
||||
SQBool (*release)(HSQUIRRELVM v,HSQOBJECT *po);
|
||||
void (*resetobject)(HSQOBJECT *po);
|
||||
const SQChar* (*objtostring)(const HSQOBJECT *o);
|
||||
SQBool (*objtobool)(const HSQOBJECT *o);
|
||||
SQInteger (*objtointeger)(const HSQOBJECT *o);
|
||||
SQFloat (*objtofloat)(const HSQOBJECT *o);
|
||||
SQRESULT (*getobjtypetag)(const HSQOBJECT *o,SQUserPointer * typetag);
|
||||
|
||||
/*GC*/
|
||||
SQInteger (*collectgarbage)(HSQUIRRELVM v);
|
||||
|
||||
/*serialization*/
|
||||
SQRESULT (*writeclosure)(HSQUIRRELVM vm,SQWRITEFUNC writef,SQUserPointer up);
|
||||
SQRESULT (*readclosure)(HSQUIRRELVM vm,SQREADFUNC readf,SQUserPointer up);
|
||||
|
||||
/*mem allocation*/
|
||||
void* (*malloc)(SQUnsignedInteger size);
|
||||
void* (*realloc)(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize);
|
||||
void (*free)(void *p,SQUnsignedInteger size);
|
||||
|
||||
/*debug*/
|
||||
SQRESULT (*stackinfos)(HSQUIRRELVM v,SQInteger level,SQStackInfos *si);
|
||||
void (*setdebughook)(HSQUIRRELVM v);
|
||||
} sq_api;
|
||||
typedef sq_api* HSQAPI;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*_SQ_MODULE_H_*/
|
200
include/sqmodule.h
Normal file
200
include/sqmodule.h
Normal file
@ -0,0 +1,200 @@
|
||||
//
|
||||
// SqModule: API used to communicate with and register squirrel modules
|
||||
//
|
||||
|
||||
//
|
||||
// Copyright (c) 2009 Brandon Jones
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
|
||||
#if !defined(_SQ_MODULE_H_)
|
||||
#define _SQ_MODULE_H_
|
||||
|
||||
#include "squirrel.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @cond DEV
|
||||
/// Allows modules to interface with Squirrel's C api without linking to the squirrel library
|
||||
/// If new functions are added to the Squirrel API, they should be added here too
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
typedef struct {
|
||||
/*vm*/
|
||||
HSQUIRRELVM (*open)(SQInteger initialstacksize);
|
||||
HSQUIRRELVM (*newthread)(HSQUIRRELVM friendvm, SQInteger initialstacksize);
|
||||
void (*seterrorhandler)(HSQUIRRELVM v);
|
||||
void (*close)(HSQUIRRELVM v);
|
||||
void (*setforeignptr)(HSQUIRRELVM v,SQUserPointer p);
|
||||
SQUserPointer (*getforeignptr)(HSQUIRRELVM v);
|
||||
#if SQUIRREL_VERSION_NUMBER >= 300
|
||||
void (*setprintfunc)(HSQUIRRELVM v, SQPRINTFUNCTION printfunc, SQPRINTFUNCTION);
|
||||
#else
|
||||
void (*setprintfunc)(HSQUIRRELVM v, SQPRINTFUNCTION printfunc);
|
||||
#endif
|
||||
SQPRINTFUNCTION (*getprintfunc)(HSQUIRRELVM v);
|
||||
SQRESULT (*suspendvm)(HSQUIRRELVM v);
|
||||
SQRESULT (*wakeupvm)(HSQUIRRELVM v,SQBool resumedret,SQBool retval,SQBool raiseerror,SQBool throwerror);
|
||||
SQInteger (*getvmstate)(HSQUIRRELVM v);
|
||||
|
||||
/*compiler*/
|
||||
SQRESULT (*compile)(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror);
|
||||
SQRESULT (*compilebuffer)(HSQUIRRELVM v,const SQChar *s,SQInteger size,const SQChar *sourcename,SQBool raiseerror);
|
||||
void (*enabledebuginfo)(HSQUIRRELVM v, SQBool enable);
|
||||
void (*notifyallexceptions)(HSQUIRRELVM v, SQBool enable);
|
||||
void (*setcompilererrorhandler)(HSQUIRRELVM v,SQCOMPILERERROR f);
|
||||
|
||||
/*stack operations*/
|
||||
void (*push)(HSQUIRRELVM v,SQInteger idx);
|
||||
void (*pop)(HSQUIRRELVM v,SQInteger nelemstopop);
|
||||
void (*poptop)(HSQUIRRELVM v);
|
||||
void (*remove)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQInteger (*gettop)(HSQUIRRELVM v);
|
||||
void (*settop)(HSQUIRRELVM v,SQInteger newtop);
|
||||
#if SQUIRREL_VERSION_NUMBER >= 300
|
||||
SQRESULT (*reservestack)(HSQUIRRELVM v,SQInteger nsize);
|
||||
#else
|
||||
void (*reservestack)(HSQUIRRELVM v,SQInteger nsize);
|
||||
#endif
|
||||
SQInteger (*cmp)(HSQUIRRELVM v);
|
||||
void (*move)(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx);
|
||||
|
||||
/*object creation handling*/
|
||||
SQUserPointer (*newuserdata)(HSQUIRRELVM v,SQUnsignedInteger size);
|
||||
void (*newtable)(HSQUIRRELVM v);
|
||||
void (*newarray)(HSQUIRRELVM v,SQInteger size);
|
||||
void (*newclosure)(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars);
|
||||
SQRESULT (*setparamscheck)(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask);
|
||||
SQRESULT (*bindenv)(HSQUIRRELVM v,SQInteger idx);
|
||||
void (*pushstring)(HSQUIRRELVM v,const SQChar *s,SQInteger len);
|
||||
void (*pushfloat)(HSQUIRRELVM v,SQFloat f);
|
||||
void (*pushinteger)(HSQUIRRELVM v,SQInteger n);
|
||||
void (*pushbool)(HSQUIRRELVM v,SQBool b);
|
||||
void (*pushuserpointer)(HSQUIRRELVM v,SQUserPointer p);
|
||||
void (*pushnull)(HSQUIRRELVM v);
|
||||
SQObjectType (*gettype)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQInteger (*getsize)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*getbase)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQBool (*instanceof)(HSQUIRRELVM v);
|
||||
#if SQUIRREL_VERSION_NUMBER >= 300
|
||||
SQRESULT (*tostring)(HSQUIRRELVM v,SQInteger idx);
|
||||
#else
|
||||
void (*tostring)(HSQUIRRELVM v,SQInteger idx);
|
||||
#endif
|
||||
void (*tobool)(HSQUIRRELVM v, SQInteger idx, SQBool *b);
|
||||
SQRESULT (*getstring)(HSQUIRRELVM v,SQInteger idx,const SQChar **c);
|
||||
SQRESULT (*getinteger)(HSQUIRRELVM v,SQInteger idx,SQInteger *i);
|
||||
SQRESULT (*getfloat)(HSQUIRRELVM v,SQInteger idx,SQFloat *f);
|
||||
SQRESULT (*getbool)(HSQUIRRELVM v,SQInteger idx,SQBool *b);
|
||||
SQRESULT (*getthread)(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread);
|
||||
SQRESULT (*getuserpointer)(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p);
|
||||
SQRESULT (*getuserdata)(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag);
|
||||
SQRESULT (*settypetag)(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag);
|
||||
SQRESULT (*gettypetag)(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag);
|
||||
void (*setreleasehook)(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook);
|
||||
SQChar* (*getscratchpad)(HSQUIRRELVM v,SQInteger minsize);
|
||||
SQRESULT (*getclosureinfo)(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars);
|
||||
SQRESULT (*setnativeclosurename)(HSQUIRRELVM v,SQInteger idx,const SQChar *name);
|
||||
SQRESULT (*setinstanceup)(HSQUIRRELVM v, SQInteger idx, SQUserPointer p);
|
||||
SQRESULT (*getinstanceup)(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag);
|
||||
SQRESULT (*setclassudsize)(HSQUIRRELVM v, SQInteger idx, SQInteger udsize);
|
||||
SQRESULT (*newclass)(HSQUIRRELVM v,SQBool hasbase);
|
||||
SQRESULT (*createinstance)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*setattributes)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*getattributes)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*getclass)(HSQUIRRELVM v,SQInteger idx);
|
||||
void (*weakref)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*getdefaultdelegate)(HSQUIRRELVM v,SQObjectType t);
|
||||
|
||||
/*object manipulation*/
|
||||
void (*pushroottable)(HSQUIRRELVM v);
|
||||
void (*pushregistrytable)(HSQUIRRELVM v);
|
||||
void (*pushconsttable)(HSQUIRRELVM v);
|
||||
SQRESULT (*setroottable)(HSQUIRRELVM v);
|
||||
SQRESULT (*setconsttable)(HSQUIRRELVM v);
|
||||
SQRESULT (*newslot)(HSQUIRRELVM v, SQInteger idx, SQBool bstatic);
|
||||
SQRESULT (*deleteslot)(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
|
||||
SQRESULT (*set)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*get)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*rawget)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*rawset)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*rawdeleteslot)(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
|
||||
SQRESULT (*arrayappend)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*arraypop)(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
|
||||
SQRESULT (*arrayresize)(HSQUIRRELVM v,SQInteger idx,SQInteger newsize);
|
||||
SQRESULT (*arrayreverse)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*arrayremove)(HSQUIRRELVM v,SQInteger idx,SQInteger itemidx);
|
||||
SQRESULT (*arrayinsert)(HSQUIRRELVM v,SQInteger idx,SQInteger destpos);
|
||||
SQRESULT (*setdelegate)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*getdelegate)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*clone)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*setfreevariable)(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval);
|
||||
SQRESULT (*next)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*getweakrefval)(HSQUIRRELVM v,SQInteger idx);
|
||||
SQRESULT (*clear)(HSQUIRRELVM v,SQInteger idx);
|
||||
|
||||
/*calls*/
|
||||
SQRESULT (*call)(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror);
|
||||
SQRESULT (*resume)(HSQUIRRELVM v,SQBool retval,SQBool raiseerror);
|
||||
const SQChar* (*getlocal)(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx);
|
||||
const SQChar* (*getfreevariable)(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval);
|
||||
SQRESULT (*throwerror)(HSQUIRRELVM v,const SQChar *err);
|
||||
void (*reseterror)(HSQUIRRELVM v);
|
||||
void (*getlasterror)(HSQUIRRELVM v);
|
||||
|
||||
/*raw object handling*/
|
||||
SQRESULT (*getstackobj)(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po);
|
||||
void (*pushobject)(HSQUIRRELVM v,HSQOBJECT obj);
|
||||
void (*addref)(HSQUIRRELVM v,HSQOBJECT *po);
|
||||
SQBool (*release)(HSQUIRRELVM v,HSQOBJECT *po);
|
||||
void (*resetobject)(HSQOBJECT *po);
|
||||
const SQChar* (*objtostring)(const HSQOBJECT *o);
|
||||
SQBool (*objtobool)(const HSQOBJECT *o);
|
||||
SQInteger (*objtointeger)(const HSQOBJECT *o);
|
||||
SQFloat (*objtofloat)(const HSQOBJECT *o);
|
||||
SQRESULT (*getobjtypetag)(const HSQOBJECT *o,SQUserPointer * typetag);
|
||||
|
||||
/*GC*/
|
||||
SQInteger (*collectgarbage)(HSQUIRRELVM v);
|
||||
|
||||
/*serialization*/
|
||||
SQRESULT (*writeclosure)(HSQUIRRELVM vm,SQWRITEFUNC writef,SQUserPointer up);
|
||||
SQRESULT (*readclosure)(HSQUIRRELVM vm,SQREADFUNC readf,SQUserPointer up);
|
||||
|
||||
/*mem allocation*/
|
||||
void* (*malloc)(SQUnsignedInteger size);
|
||||
void* (*realloc)(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize);
|
||||
void (*free)(void *p,SQUnsignedInteger size);
|
||||
|
||||
/*debug*/
|
||||
SQRESULT (*stackinfos)(HSQUIRRELVM v,SQInteger level,SQStackInfos *si);
|
||||
void (*setdebughook)(HSQUIRRELVM v);
|
||||
} sq_api;
|
||||
typedef sq_api* HSQAPI;
|
||||
/// @endcond
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*_SQ_MODULE_H_*/
|
69
include/sqrat.h
Normal file
69
include/sqrat.h
Normal file
@ -0,0 +1,69 @@
|
||||
//
|
||||
// Sqrat: Squirrel C++ Binding Utility
|
||||
//
|
||||
|
||||
//
|
||||
// Copyright (c) 2009 Brandon Jones
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
|
||||
/*! \mainpage Sqrat Main Page
|
||||
*
|
||||
* \section intro_sec Introduction
|
||||
*
|
||||
* Sqrat is a C++ library for Squirrel that facilitates exposing classes and other native functionality to Squirrel scripts. It models the underlying Squirrel API closely to give access to a wider range of functionality than other binding libraries. In addition to the binding library, Sqrat features a threading library and a module import library.
|
||||
*
|
||||
* \section install_sec Installation
|
||||
*
|
||||
* Sqrat only contains C++ headers so for installation you just need to copy the files in the include directory to some common header path.
|
||||
*
|
||||
* \section sec_faq Frequently Asked Questions
|
||||
*
|
||||
* Q: My application is crashing when I call sq_close. Why is this happening?<br>
|
||||
* A: All Sqrat::Object instances and derived type instances must be destroyed before calling sq_close.
|
||||
*
|
||||
* \section discuss_sec Discussion and User Support
|
||||
*
|
||||
* Discussion about Sqrat happens at the Squirrel language forum, the Bindings section
|
||||
* http://squirrel-lang.org/forums/default.aspx?g=topics&f=4
|
||||
*
|
||||
* \section bug_sec Bug Reporting
|
||||
*
|
||||
* Bug reports or feature enhancement requests and patches can be submitted at the SourceForge Sqrat site
|
||||
* https://sourceforge.net/p/scrat/sqrat/
|
||||
*
|
||||
* You're invited to make documentation suggestions for Sqrat. Together, we can make Sqrat as easy to understand as possible!
|
||||
*/
|
||||
|
||||
#if !defined(_SCRAT_MAIN_H_)
|
||||
#define _SCRAT_MAIN_H_
|
||||
|
||||
#include <squirrel.h>
|
||||
|
||||
#include "sqrat/sqratTable.h"
|
||||
#include "sqrat/sqratClass.h"
|
||||
#include "sqrat/sqratFunction.h"
|
||||
#include "sqrat/sqratConst.h"
|
||||
#include "sqrat/sqratUtil.h"
|
||||
#include "sqrat/sqratScript.h"
|
||||
#include "sqrat/sqratArray.h"
|
||||
|
||||
#endif
|
863
include/sqrat/sqratAllocator.h
Normal file
863
include/sqrat/sqratAllocator.h
Normal file
@ -0,0 +1,863 @@
|
||||
//
|
||||
// SqratAllocator: Custom Class Allocation/Deallocation
|
||||
//
|
||||
|
||||
//
|
||||
// Copyright (c) 2009 Brandon Jones
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
|
||||
#if !defined(_SCRAT_ALLOCATOR_H_)
|
||||
#define _SCRAT_ALLOCATOR_H_
|
||||
|
||||
#include <squirrel.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sqratObject.h"
|
||||
#include "sqratTypes.h"
|
||||
|
||||
namespace Sqrat {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @cond DEV
|
||||
/// utility taken from http://stackoverflow.com/questions/2733377/is-there-a-way-to-test-whether-a-c-class-has-a-default-constructor-other-than/2770326#2770326
|
||||
/// may be obsolete in C++ 11
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template< class T >
|
||||
class is_default_constructible {
|
||||
template<int x>
|
||||
class receive_size{};
|
||||
|
||||
template< class U >
|
||||
static int sfinae( receive_size< sizeof U() > * );
|
||||
|
||||
template< class U >
|
||||
static char sfinae( ... );
|
||||
|
||||
public:
|
||||
enum { value = sizeof( sfinae<T>(0) ) == sizeof(int) };
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// DefaultAllocator is the allocator to use for Class that can both be constructed and copied
|
||||
///
|
||||
/// \tparam C Type of class
|
||||
///
|
||||
/// \remarks
|
||||
/// There is mechanisms defined in this class that allow the Class::Ctor method to work properly (e.g. iNew).
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<class C>
|
||||
class DefaultAllocator {
|
||||
|
||||
template <class T, bool b>
|
||||
struct NewC
|
||||
{
|
||||
T* p;
|
||||
NewC()
|
||||
{
|
||||
p = new T();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct NewC<T, false>
|
||||
{
|
||||
T* p;
|
||||
NewC()
|
||||
{
|
||||
p = 0;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Associates a newly created instance with an object allocated with the new operator (which is automatically deleted)
|
||||
///
|
||||
/// \param vm VM that has an instance object of the correct type at idx
|
||||
/// \param idx Index of the stack that the instance object is at
|
||||
/// \param ptr Should be the return value from a call to the new operator
|
||||
///
|
||||
/// \remarks
|
||||
/// This function should only need to be used when custom constructors are bound with Class::SquirrelFunc.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static void SetInstance(HSQUIRRELVM vm, SQInteger idx, C* ptr)
|
||||
{
|
||||
ClassData<C>* cd = ClassType<C>::getClassData(vm);
|
||||
sq_setinstanceup(vm, idx, new std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >(ptr, cd->instances));
|
||||
sq_setreleasehook(vm, idx, &Delete);
|
||||
sq_getstackobj(vm, idx, &((*cd->instances)[ptr]));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Called by Sqrat to set up an instance on the stack for the template class
|
||||
///
|
||||
/// \param vm VM that has an instance object of the correct type at position 1 in its stack
|
||||
///
|
||||
/// \return Squirrel error code
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static SQInteger New(HSQUIRRELVM vm) {
|
||||
SetInstance(vm, 1, NewC<C, is_default_constructible<C>::value >().p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @cond DEV
|
||||
/// following iNew functions are used only if constructors are bound via Ctor() in Sqrat::Class (safe to ignore)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static SQInteger iNew(HSQUIRRELVM vm) {
|
||||
return New(vm);
|
||||
}
|
||||
|
||||
template <typename A1>
|
||||
static SQInteger iNew(HSQUIRRELVM vm) {
|
||||
SQTRY()
|
||||
Var<A1> a1(vm, 2);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
||||
}
|
||||
SetInstance(vm, 1, new C(
|
||||
a1.value
|
||||
));
|
||||
SQCATCH(vm) {
|
||||
return sq_throwerror(vm, SQWHAT(vm));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
template <typename A1,typename A2>
|
||||
static SQInteger iNew(HSQUIRRELVM vm) {
|
||||
SQTRY()
|
||||
Var<A1> a1(vm, 2);
|
||||
Var<A2> a2(vm, 3);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
||||
}
|
||||
SetInstance(vm, 1, new C(
|
||||
a1.value,
|
||||
a2.value
|
||||
));
|
||||
SQCATCH(vm) {
|
||||
return sq_throwerror(vm, SQWHAT(vm));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
template <typename A1,typename A2,typename A3>
|
||||
static SQInteger iNew(HSQUIRRELVM vm) {
|
||||
SQTRY()
|
||||
Var<A1> a1(vm, 2);
|
||||
Var<A2> a2(vm, 3);
|
||||
Var<A3> a3(vm, 4);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
||||
}
|
||||
SetInstance(vm, 1, new C(
|
||||
a1.value,
|
||||
a2.value,
|
||||
a3.value
|
||||
));
|
||||
SQCATCH(vm) {
|
||||
return sq_throwerror(vm, SQWHAT(vm));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
template <typename A1,typename A2,typename A3,typename A4>
|
||||
static SQInteger iNew(HSQUIRRELVM vm) {
|
||||
SQTRY()
|
||||
Var<A1> a1(vm, 2);
|
||||
Var<A2> a2(vm, 3);
|
||||
Var<A3> a3(vm, 4);
|
||||
Var<A4> a4(vm, 5);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
||||
}
|
||||
SetInstance(vm, 1, new C(
|
||||
a1.value,
|
||||
a2.value,
|
||||
a3.value,
|
||||
a4.value
|
||||
));
|
||||
SQCATCH(vm) {
|
||||
return sq_throwerror(vm, SQWHAT(vm));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
template <typename A1,typename A2,typename A3,typename A4,typename A5>
|
||||
static SQInteger iNew(HSQUIRRELVM vm) {
|
||||
SQTRY()
|
||||
Var<A1> a1(vm, 2);
|
||||
Var<A2> a2(vm, 3);
|
||||
Var<A3> a3(vm, 4);
|
||||
Var<A4> a4(vm, 5);
|
||||
Var<A5> a5(vm, 6);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
||||
}
|
||||
SetInstance(vm, 1, new C(
|
||||
a1.value,
|
||||
a2.value,
|
||||
a3.value,
|
||||
a4.value,
|
||||
a5.value
|
||||
));
|
||||
SQCATCH(vm) {
|
||||
return sq_throwerror(vm, SQWHAT(vm));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
template <typename A1,typename A2,typename A3,typename A4,typename A5,typename A6>
|
||||
static SQInteger iNew(HSQUIRRELVM vm) {
|
||||
SQTRY()
|
||||
Var<A1> a1(vm, 2);
|
||||
Var<A2> a2(vm, 3);
|
||||
Var<A3> a3(vm, 4);
|
||||
Var<A4> a4(vm, 5);
|
||||
Var<A5> a5(vm, 6);
|
||||
Var<A6> a6(vm, 7);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
||||
}
|
||||
SetInstance(vm, 1, new C(
|
||||
a1.value,
|
||||
a2.value,
|
||||
a3.value,
|
||||
a4.value,
|
||||
a5.value,
|
||||
a6.value
|
||||
));
|
||||
SQCATCH(vm) {
|
||||
return sq_throwerror(vm, SQWHAT(vm));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
template <typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7>
|
||||
static SQInteger iNew(HSQUIRRELVM vm) {
|
||||
SQTRY()
|
||||
Var<A1> a1(vm, 2);
|
||||
Var<A2> a2(vm, 3);
|
||||
Var<A3> a3(vm, 4);
|
||||
Var<A4> a4(vm, 5);
|
||||
Var<A5> a5(vm, 6);
|
||||
Var<A6> a6(vm, 7);
|
||||
Var<A7> a7(vm, 8);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
||||
}
|
||||
SetInstance(vm, 1, new C(
|
||||
a1.value,
|
||||
a2.value,
|
||||
a3.value,
|
||||
a4.value,
|
||||
a5.value,
|
||||
a6.value,
|
||||
a7.value
|
||||
));
|
||||
SQCATCH(vm) {
|
||||
return sq_throwerror(vm, SQWHAT(vm));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
template <typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7,typename A8>
|
||||
static SQInteger iNew(HSQUIRRELVM vm) {
|
||||
SQTRY()
|
||||
Var<A1> a1(vm, 2);
|
||||
Var<A2> a2(vm, 3);
|
||||
Var<A3> a3(vm, 4);
|
||||
Var<A4> a4(vm, 5);
|
||||
Var<A5> a5(vm, 6);
|
||||
Var<A6> a6(vm, 7);
|
||||
Var<A7> a7(vm, 8);
|
||||
Var<A8> a8(vm, 9);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
||||
}
|
||||
SetInstance(vm, 1, new C(
|
||||
a1.value,
|
||||
a2.value,
|
||||
a3.value,
|
||||
a4.value,
|
||||
a5.value,
|
||||
a6.value,
|
||||
a7.value,
|
||||
a8.value
|
||||
));
|
||||
SQCATCH(vm) {
|
||||
return sq_throwerror(vm, SQWHAT(vm));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
template <typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7,typename A8,typename A9>
|
||||
static SQInteger iNew(HSQUIRRELVM vm) {
|
||||
SQTRY()
|
||||
Var<A1> a1(vm, 2);
|
||||
Var<A2> a2(vm, 3);
|
||||
Var<A3> a3(vm, 4);
|
||||
Var<A4> a4(vm, 5);
|
||||
Var<A5> a5(vm, 6);
|
||||
Var<A6> a6(vm, 7);
|
||||
Var<A7> a7(vm, 8);
|
||||
Var<A8> a8(vm, 9);
|
||||
Var<A9> a9(vm, 10);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
||||
}
|
||||
SetInstance(vm, 1, new C(
|
||||
a1.value,
|
||||
a2.value,
|
||||
a3.value,
|
||||
a4.value,
|
||||
a5.value,
|
||||
a6.value,
|
||||
a7.value,
|
||||
a8.value,
|
||||
a9.value
|
||||
));
|
||||
SQCATCH(vm) {
|
||||
return sq_throwerror(vm, SQWHAT(vm));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Called by Sqrat to set up the instance at idx on the stack as a copy of a value of the same type
|
||||
///
|
||||
/// \param vm VM that has an instance object of the correct type at idx
|
||||
/// \param idx Index of the stack that the instance object is at
|
||||
/// \param value A pointer to data of the same type as the instance object
|
||||
///
|
||||
/// \return Squirrel error code
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static SQInteger Copy(HSQUIRRELVM vm, SQInteger idx, const void* value) {
|
||||
SetInstance(vm, idx, new C(*static_cast<const C*>(value)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Called by Sqrat to delete an instance's data
|
||||
///
|
||||
/// \param ptr Pointer to the data contained by the instance
|
||||
/// \param size Size of the data contained by the instance
|
||||
///
|
||||
/// \return Squirrel error code
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static SQInteger Delete(SQUserPointer ptr, SQInteger size) {
|
||||
SQUNUSED(size);
|
||||
std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >* instance = reinterpret_cast<std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >*>(ptr);
|
||||
instance->second->erase(instance->first);
|
||||
delete instance->first;
|
||||
delete instance;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// NoConstructor is the allocator to use for Class that can NOT be constructed or copied
|
||||
///
|
||||
/// \tparam C Type of class
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<class C>
|
||||
class NoConstructor {
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Associates a newly created instance with an object allocated with the new operator (which is automatically deleted)
|
||||
///
|
||||
/// \param vm VM that has an instance object of the correct type at idx
|
||||
/// \param idx Index of the stack that the instance object is at
|
||||
/// \param ptr Should be the return value from a call to the new operator
|
||||
///
|
||||
/// \remarks
|
||||
/// This function should only need to be used when custom constructors are bound with Class::SquirrelFunc.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static void SetInstance(HSQUIRRELVM vm, SQInteger idx, C* ptr)
|
||||
{
|
||||
ClassData<C>* cd = ClassType<C>::getClassData(vm);
|
||||
sq_setinstanceup(vm, idx, new std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >(ptr, cd->instance));
|
||||
sq_setreleasehook(vm, idx, &Delete);
|
||||
sq_getstackobj(vm, idx, &((*cd->instances)[ptr]));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Called by Sqrat to set up an instance on the stack for the template class (not allowed in this allocator)
|
||||
///
|
||||
/// \param vm VM that has an instance object of the correct type at position 1 in its stack
|
||||
///
|
||||
/// \return Squirrel error code
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static SQInteger New(HSQUIRRELVM vm) {
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
return sq_throwerror(vm, (ClassType<C>::ClassName() + string(_SC(" constructing is not allowed"))).c_str());
|
||||
#else
|
||||
SQUNUSED(vm);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Called by Sqrat to set up the instance at idx on the stack as a copy of a value of the same type (not used in this allocator)
|
||||
///
|
||||
/// \param vm VM that has an instance object of the correct type at idx
|
||||
/// \param idx Index of the stack that the instance object is at
|
||||
/// \param value A pointer to data of the same type as the instance object
|
||||
///
|
||||
/// \return Squirrel error code
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static SQInteger Copy(HSQUIRRELVM vm, SQInteger idx, const void* value) {
|
||||
SQUNUSED(vm);
|
||||
SQUNUSED(idx);
|
||||
SQUNUSED(value);
|
||||
return sq_throwerror(vm, (ClassType<C>::ClassName() + string(_SC(" cloning is not allowed"))).c_str());
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Called by Sqrat to delete an instance's data
|
||||
///
|
||||
/// \param ptr Pointer to the data contained by the instance
|
||||
/// \param size Size of the data contained by the instance
|
||||
///
|
||||
/// \return Squirrel error code
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static SQInteger Delete(SQUserPointer ptr, SQInteger size) {
|
||||
SQUNUSED(size);
|
||||
std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >* instance = reinterpret_cast<std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >*>(ptr);
|
||||
instance->second->erase(instance->first);
|
||||
delete instance->first;
|
||||
delete instance;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// CopyOnly is the allocator to use for Class that can be copied but not constructed
|
||||
///
|
||||
/// \tparam C Type of class
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<class C>
|
||||
class CopyOnly {
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Associates a newly created instance with an object allocated with the new operator (which is automatically deleted)
|
||||
///
|
||||
/// \param vm VM that has an instance object of the correct type at idx
|
||||
/// \param idx Index of the stack that the instance object is at
|
||||
/// \param ptr Should be the return value from a call to the new operator
|
||||
///
|
||||
/// \remarks
|
||||
/// This function should only need to be used when custom constructors are bound with Class::SquirrelFunc.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static void SetInstance(HSQUIRRELVM vm, SQInteger idx, C* ptr)
|
||||
{
|
||||
ClassData<C>* cd = ClassType<C>::getClassData(vm);
|
||||
sq_setinstanceup(vm, idx, new std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >(ptr, cd->instances));
|
||||
sq_setreleasehook(vm, idx, &Delete);
|
||||
sq_getstackobj(vm, idx, &((*cd->instances)[ptr]));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Called by Sqrat to set up an instance on the stack for the template class (not allowed in this allocator)
|
||||
///
|
||||
/// \param vm VM that has an instance object of the correct type at position 1 in its stack
|
||||
///
|
||||
/// \return Squirrel error code
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static SQInteger New(HSQUIRRELVM vm) {
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
return sq_throwerror(vm, (ClassType<C>::ClassName() + string(_SC(" constructing is not allowed"))).c_str());
|
||||
#else
|
||||
SQUNUSED(vm);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Called by Sqrat to set up the instance at idx on the stack as a copy of a value of the same type
|
||||
///
|
||||
/// \param vm VM that has an instance object of the correct type at idx
|
||||
/// \param idx Index of the stack that the instance object is at
|
||||
/// \param value A pointer to data of the same type as the instance object
|
||||
///
|
||||
/// \return Squirrel error code
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static SQInteger Copy(HSQUIRRELVM vm, SQInteger idx, const void* value) {
|
||||
SetInstance(vm, idx, new C(*static_cast<const C*>(value)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Called by Sqrat to delete an instance's data
|
||||
///
|
||||
/// \param ptr Pointer to the data contained by the instance
|
||||
/// \param size Size of the data contained by the instance
|
||||
///
|
||||
/// \return Squirrel error code
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static SQInteger Delete(SQUserPointer ptr, SQInteger size) {
|
||||
SQUNUSED(size);
|
||||
std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >* instance = reinterpret_cast<std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >*>(ptr);
|
||||
instance->second->erase(instance->first);
|
||||
delete instance->first;
|
||||
delete instance;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// NoCopy is the allocator to use for Class that can be constructed but not copied
|
||||
///
|
||||
/// \tparam C Type of class
|
||||
///
|
||||
/// \remarks
|
||||
/// There is mechanisms defined in this class that allow the Class::Ctor method to work properly (e.g. iNew).
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<class C>
|
||||
class NoCopy {
|
||||
|
||||
template <class T, bool b>
|
||||
struct NewC
|
||||
{
|
||||
T* p;
|
||||
NewC()
|
||||
{
|
||||
p = new T();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct NewC<T, false>
|
||||
{
|
||||
T* p;
|
||||
NewC()
|
||||
{
|
||||
p = 0;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Associates a newly created instance with an object allocated with the new operator (which is automatically deleted)
|
||||
///
|
||||
/// \param vm VM that has an instance object of the correct type at idx
|
||||
/// \param idx Index of the stack that the instance object is at
|
||||
/// \param ptr Should be the return value from a call to the new operator
|
||||
///
|
||||
/// \remarks
|
||||
/// This function should only need to be used when custom constructors are bound with Class::SquirrelFunc.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static void SetInstance(HSQUIRRELVM vm, SQInteger idx, C* ptr)
|
||||
{
|
||||
ClassData<C>* cd = ClassType<C>::getClassData(vm);
|
||||
sq_setinstanceup(vm, idx, new std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >(ptr, cd->instances));
|
||||
sq_setreleasehook(vm, idx, &Delete);
|
||||
sq_getstackobj(vm, idx, &((*cd->instances)[ptr]));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Called by Sqrat to set up an instance on the stack for the template class
|
||||
///
|
||||
/// \param vm VM that has an instance object of the correct type at position 1 in its stack
|
||||
///
|
||||
/// \return Squirrel error code
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static SQInteger New(HSQUIRRELVM vm) {
|
||||
SetInstance(vm, 1, NewC<C, is_default_constructible<C>::value >().p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @cond DEV
|
||||
/// following iNew functions are used only if constructors are bound via Ctor() in Sqrat::Class (safe to ignore)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static SQInteger iNew(HSQUIRRELVM vm) {
|
||||
return New(vm);
|
||||
}
|
||||
|
||||
template <typename A1>
|
||||
static SQInteger iNew(HSQUIRRELVM vm) {
|
||||
SQTRY()
|
||||
Var<A1> a1(vm, 2);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
||||
}
|
||||
SetInstance(vm, 1, new C(
|
||||
a1.value
|
||||
));
|
||||
SQCATCH(vm) {
|
||||
return sq_throwerror(vm, SQWHAT(vm));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
template <typename A1,typename A2>
|
||||
static SQInteger iNew(HSQUIRRELVM vm) {
|
||||
SQTRY()
|
||||
Var<A1> a1(vm, 2);
|
||||
Var<A2> a2(vm, 3);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
||||
}
|
||||
SetInstance(vm, 1, new C(
|
||||
a1.value,
|
||||
a2.value
|
||||
));
|
||||
SQCATCH(vm) {
|
||||
return sq_throwerror(vm, SQWHAT(vm));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
template <typename A1,typename A2,typename A3>
|
||||
static SQInteger iNew(HSQUIRRELVM vm) {
|
||||
SQTRY()
|
||||
Var<A1> a1(vm, 2);
|
||||
Var<A2> a2(vm, 3);
|
||||
Var<A3> a3(vm, 4);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
||||
}
|
||||
SetInstance(vm, 1, new C(
|
||||
a1.value,
|
||||
a2.value,
|
||||
a3.value
|
||||
));
|
||||
SQCATCH(vm) {
|
||||
return sq_throwerror(vm, SQWHAT(vm));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
template <typename A1,typename A2,typename A3,typename A4>
|
||||
static SQInteger iNew(HSQUIRRELVM vm) {
|
||||
SQTRY()
|
||||
Var<A1> a1(vm, 2);
|
||||
Var<A2> a2(vm, 3);
|
||||
Var<A3> a3(vm, 4);
|
||||
Var<A4> a4(vm, 5);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
||||
}
|
||||
SetInstance(vm, 1, new C(
|
||||
a1.value,
|
||||
a2.value,
|
||||
a3.value,
|
||||
a4.value
|
||||
));
|
||||
SQCATCH(vm) {
|
||||
return sq_throwerror(vm, SQWHAT(vm));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
template <typename A1,typename A2,typename A3,typename A4,typename A5>
|
||||
static SQInteger iNew(HSQUIRRELVM vm) {
|
||||
SQTRY()
|
||||
Var<A1> a1(vm, 2);
|
||||
Var<A2> a2(vm, 3);
|
||||
Var<A3> a3(vm, 4);
|
||||
Var<A4> a4(vm, 5);
|
||||
Var<A5> a5(vm, 6);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
||||
}
|
||||
SetInstance(vm, 1, new C(
|
||||
a1.value,
|
||||
a2.value,
|
||||
a3.value,
|
||||
a4.value,
|
||||
a5.value
|
||||
));
|
||||
SQCATCH(vm) {
|
||||
return sq_throwerror(vm, SQWHAT(vm));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
template <typename A1,typename A2,typename A3,typename A4,typename A5,typename A6>
|
||||
static SQInteger iNew(HSQUIRRELVM vm) {
|
||||
SQTRY()
|
||||
Var<A1> a1(vm, 2);
|
||||
Var<A2> a2(vm, 3);
|
||||
Var<A3> a3(vm, 4);
|
||||
Var<A4> a4(vm, 5);
|
||||
Var<A5> a5(vm, 6);
|
||||
Var<A6> a6(vm, 7);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
||||
}
|
||||
SetInstance(vm, 1, new C(
|
||||
a1.value,
|
||||
a2.value,
|
||||
a3.value,
|
||||
a4.value,
|
||||
a5.value,
|
||||
a6.value
|
||||
));
|
||||
SQCATCH(vm) {
|
||||
return sq_throwerror(vm, SQWHAT(vm));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
template <typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7>
|
||||
static SQInteger iNew(HSQUIRRELVM vm) {
|
||||
SQTRY()
|
||||
Var<A1> a1(vm, 2);
|
||||
Var<A2> a2(vm, 3);
|
||||
Var<A3> a3(vm, 4);
|
||||
Var<A4> a4(vm, 5);
|
||||
Var<A5> a5(vm, 6);
|
||||
Var<A6> a6(vm, 7);
|
||||
Var<A7> a7(vm, 8);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
||||
}
|
||||
SetInstance(vm, 1, new C(
|
||||
a1.value,
|
||||
a2.value,
|
||||
a3.value,
|
||||
a4.value,
|
||||
a5.value,
|
||||
a6.value,
|
||||
a7.value
|
||||
));
|
||||
SQCATCH(vm) {
|
||||
return sq_throwerror(vm, SQWHAT(vm));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
template <typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7,typename A8>
|
||||
static SQInteger iNew(HSQUIRRELVM vm) {
|
||||
SQTRY()
|
||||
Var<A1> a1(vm, 2);
|
||||
Var<A2> a2(vm, 3);
|
||||
Var<A3> a3(vm, 4);
|
||||
Var<A4> a4(vm, 5);
|
||||
Var<A5> a5(vm, 6);
|
||||
Var<A6> a6(vm, 7);
|
||||
Var<A7> a7(vm, 8);
|
||||
Var<A8> a8(vm, 9);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
||||
}
|
||||
SetInstance(vm, 1, new C(
|
||||
a1.value,
|
||||
a2.value,
|
||||
a3.value,
|
||||
a4.value,
|
||||
a5.value,
|
||||
a6.value,
|
||||
a7.value,
|
||||
a8.value
|
||||
));
|
||||
SQCATCH(vm) {
|
||||
return sq_throwerror(vm, SQWHAT(vm));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
template <typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7,typename A8,typename A9>
|
||||
static SQInteger iNew(HSQUIRRELVM vm) {
|
||||
SQTRY()
|
||||
Var<A1> a1(vm, 2);
|
||||
Var<A2> a2(vm, 3);
|
||||
Var<A3> a3(vm, 4);
|
||||
Var<A4> a4(vm, 5);
|
||||
Var<A5> a5(vm, 6);
|
||||
Var<A6> a6(vm, 7);
|
||||
Var<A7> a7(vm, 8);
|
||||
Var<A8> a8(vm, 9);
|
||||
Var<A9> a9(vm, 10);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
||||
}
|
||||
SetInstance(vm, 1, new C(
|
||||
a1.value,
|
||||
a2.value,
|
||||
a3.value,
|
||||
a4.value,
|
||||
a5.value,
|
||||
a6.value,
|
||||
a7.value,
|
||||
a8.value,
|
||||
a9.value
|
||||
));
|
||||
SQCATCH(vm) {
|
||||
return sq_throwerror(vm, SQWHAT(vm));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Called by Sqrat to set up the instance at idx on the stack as a copy of a value of the same type (not used in this allocator)
|
||||
///
|
||||
/// \param vm VM that has an instance object of the correct type at idx
|
||||
/// \param idx Index of the stack that the instance object is at
|
||||
/// \param value A pointer to data of the same type as the instance object
|
||||
///
|
||||
/// \return Squirrel error code
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static SQInteger Copy(HSQUIRRELVM vm, SQInteger idx, const void* value) {
|
||||
SQUNUSED(vm);
|
||||
SQUNUSED(idx);
|
||||
SQUNUSED(value);
|
||||
return sq_throwerror(vm, (ClassType<C>::ClassName() + string(_SC(" cloning is not allowed"))).c_str());
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Called by Sqrat to delete an instance's data
|
||||
///
|
||||
/// \param ptr Pointer to the data contained by the instance
|
||||
/// \param size Size of the data contained by the instance
|
||||
///
|
||||
/// \return Squirrel error code
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static SQInteger Delete(SQUserPointer ptr, SQInteger size) {
|
||||
SQUNUSED(size);
|
||||
std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >* instance = reinterpret_cast<std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >*>(ptr);
|
||||
instance->second->erase(instance->first);
|
||||
delete instance->first;
|
||||
delete instance;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
555
include/sqrat/sqratArray.h
Normal file
555
include/sqrat/sqratArray.h
Normal file
@ -0,0 +1,555 @@
|
||||
//
|
||||
// SqratArray: Array Binding
|
||||
//
|
||||
|
||||
//
|
||||
// Copyright 2011 Alston Chen
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
|
||||
#if !defined(_SCRAT_ARRAY_H_)
|
||||
#define _SCRAT_ARRAY_H_
|
||||
|
||||
#include <squirrel.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sqratObject.h"
|
||||
#include "sqratFunction.h"
|
||||
#include "sqratGlobalMethods.h"
|
||||
|
||||
namespace Sqrat {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// The base class for Array that implements almost all of its functionality
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class ArrayBase : public Object {
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Default constructor (null)
|
||||
///
|
||||
/// \param v VM that the array will exist in
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ArrayBase(HSQUIRRELVM v = DefaultVM::Get()) : Object(v, true) {
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Construct the ArrayBase from an Object that already exists
|
||||
///
|
||||
/// \param obj An Object that should already represent a Squirrel array
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ArrayBase(const Object& obj) : Object(obj) {
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Construct the ArrayBase from a HSQOBJECT and HSQUIRRELVM that already exist
|
||||
///
|
||||
/// \param o Squirrel object that should already represent a Squirrel array
|
||||
/// \param v Squirrel VM that contains the Squirrel object given
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ArrayBase(HSQOBJECT o, HSQUIRRELVM v = DefaultVM::Get()) : Object(o, v) {
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binds a Table or Class to the Array (can be used to facilitate namespaces)
|
||||
///
|
||||
/// \param index The index in the array being assigned a Table or Class
|
||||
/// \param obj Table or Class that is being placed in the Array
|
||||
///
|
||||
/// \remarks
|
||||
/// Bind cannot be called "inline" like other functions because it introduces order-of-initialization bugs.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void Bind(const SQInteger index, Object& obj) {
|
||||
sq_pushobject(vm, GetObject());
|
||||
sq_pushinteger(vm, index);
|
||||
sq_pushobject(vm, obj.GetObject());
|
||||
sq_set(vm, -3);
|
||||
sq_pop(vm,1); // pop array
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binds a raw Squirrel closure to the Array
|
||||
///
|
||||
/// \param index The index in the array being assigned a function
|
||||
/// \param func Squirrel function that is being placed in the Array
|
||||
///
|
||||
/// \return The Array itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ArrayBase& SquirrelFunc(const SQInteger index, SQFUNCTION func) {
|
||||
sq_pushobject(vm, GetObject());
|
||||
sq_pushinteger(vm, index);
|
||||
sq_newclosure(vm, func, 0);
|
||||
sq_set(vm, -3);
|
||||
sq_pop(vm,1); // pop array
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Sets an index in the Array to a specific value
|
||||
///
|
||||
/// \param index The index in the array being assigned a value
|
||||
/// \param val Value that is being placed in the Array
|
||||
///
|
||||
/// \tparam V Type of value (usually doesnt need to be defined explicitly)
|
||||
///
|
||||
/// \return The Array itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<class V>
|
||||
ArrayBase& SetValue(const SQInteger index, const V& val) {
|
||||
sq_pushobject(vm, GetObject());
|
||||
sq_pushinteger(vm, index);
|
||||
PushVar(vm, val);
|
||||
sq_set(vm, -3);
|
||||
sq_pop(vm,1); // pop array
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Sets an index in the Array to a specific instance (like a reference)
|
||||
///
|
||||
/// \param index The index in the array being assigned a value
|
||||
/// \param val Pointer to the instance that is being placed in the Array
|
||||
///
|
||||
/// \tparam V Type of instance (usually doesnt need to be defined explicitly)
|
||||
///
|
||||
/// \return The Array itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<class V>
|
||||
ArrayBase& SetInstance(const SQInteger index, V* val) {
|
||||
BindInstance<V>(index, val, false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Sets an index in the Array to a specific function
|
||||
///
|
||||
/// \param index The index in the array being assigned a value
|
||||
/// \param method Function that is being placed in the Array
|
||||
///
|
||||
/// \tparam F Type of function (only define this if you need to choose a certain template specialization or overload)
|
||||
///
|
||||
/// \return The Array itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<class F>
|
||||
ArrayBase& Func(const SQInteger index, F method) {
|
||||
BindFunc(index, &method, sizeof(method), SqGlobalFunc(method));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Returns the element at a given index
|
||||
///
|
||||
/// \param index Index of the element
|
||||
///
|
||||
/// \tparam T Type of element (fails if element is not of this type)
|
||||
///
|
||||
/// \return SharedPtr containing the element (or null if failed)
|
||||
///
|
||||
/// \remarks
|
||||
/// This function MUST have its Error handled if it occurred.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
SharedPtr<T> GetValue(int index)
|
||||
{
|
||||
sq_pushobject(vm, obj);
|
||||
sq_pushinteger(vm, index);
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
if (SQ_FAILED(sq_get(vm, -2))) {
|
||||
sq_pop(vm, 1);
|
||||
SQTHROW(vm, _SC("illegal index"));
|
||||
return SharedPtr<T>();
|
||||
}
|
||||
#else
|
||||
sq_get(vm, -2);
|
||||
#endif
|
||||
SQTRY()
|
||||
Var<SharedPtr<T> > element(vm, -1);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
sq_pop(vm, 2);
|
||||
return SharedPtr<T>();
|
||||
}
|
||||
sq_pop(vm, 2);
|
||||
return element.value;
|
||||
SQCATCH(vm) {
|
||||
#if defined (SCRAT_USE_EXCEPTIONS)
|
||||
SQUNUSED(e); // avoid "unreferenced local variable" warning
|
||||
#endif
|
||||
sq_pop(vm, 2);
|
||||
SQRETHROW(vm);
|
||||
}
|
||||
return SharedPtr<T>(); // avoid "not all control paths return a value" warning
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Gets a Function from an index in the Array
|
||||
///
|
||||
/// \param index The index in the array that contains the Function
|
||||
///
|
||||
/// \return Function found in the Array (null if failed)
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Function GetFunction(const SQInteger index) {
|
||||
HSQOBJECT funcObj;
|
||||
sq_pushobject(vm, GetObject());
|
||||
sq_pushinteger(vm, index);
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
if(SQ_FAILED(sq_get(vm, -2))) {
|
||||
sq_pop(vm, 1);
|
||||
return Function();
|
||||
}
|
||||
SQObjectType value_type = sq_gettype(vm, -1);
|
||||
if (value_type != OT_CLOSURE && value_type != OT_NATIVECLOSURE) {
|
||||
sq_pop(vm, 2);
|
||||
return Function();
|
||||
}
|
||||
#else
|
||||
sq_get(vm, -2);
|
||||
#endif
|
||||
sq_getstackobj(vm, -1, &funcObj);
|
||||
Function ret(vm, GetObject(), funcObj); // must addref before the pop!
|
||||
sq_pop(vm, 2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Fills a C array with the elements of the Array
|
||||
///
|
||||
/// \param array C array to be filled
|
||||
/// \param size The amount of elements to fill the C array with
|
||||
///
|
||||
/// \tparam T Type of elements (fails if any elements in Array are not of this type)
|
||||
///
|
||||
/// \remarks
|
||||
/// This function MUST have its Error handled if it occurred.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
void GetArray(T* array, int size)
|
||||
{
|
||||
HSQOBJECT value = GetObject();
|
||||
sq_pushobject(vm, value);
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
if (size > sq_getsize(vm, -1)) {
|
||||
sq_pop(vm, 1);
|
||||
SQTHROW(vm, _SC("array buffer size too big"));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
sq_pushnull(vm);
|
||||
SQInteger i;
|
||||
while (SQ_SUCCEEDED(sq_next(vm, -2))) {
|
||||
sq_getinteger(vm, -2, &i);
|
||||
if (i >= size) break;
|
||||
SQTRY()
|
||||
Var<const T&> element(vm, -1);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
sq_pop(vm, 4);
|
||||
return;
|
||||
}
|
||||
sq_pop(vm, 2);
|
||||
array[i] = element.value;
|
||||
SQCATCH(vm) {
|
||||
#if defined (SCRAT_USE_EXCEPTIONS)
|
||||
SQUNUSED(e); // avoid "unreferenced local variable" warning
|
||||
#endif
|
||||
sq_pop(vm, 4);
|
||||
SQRETHROW(vm);
|
||||
}
|
||||
}
|
||||
sq_pop(vm, 2); // pops the null iterator and the array object
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Appends a value to the end of the Array
|
||||
///
|
||||
/// \param val Value that is being placed in the Array
|
||||
///
|
||||
/// \tparam V Type of value (usually doesnt need to be defined explicitly)
|
||||
///
|
||||
/// \return The Array itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<class V>
|
||||
ArrayBase& Append(const V& val) {
|
||||
sq_pushobject(vm, GetObject());
|
||||
PushVar(vm, val);
|
||||
sq_arrayappend(vm, -2);
|
||||
sq_pop(vm,1); // pop array
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Appends an instance to the end of the Array (like a reference)
|
||||
///
|
||||
/// \param val Pointer to the instance that is being placed in the Array
|
||||
///
|
||||
/// \tparam V Type of instance (usually doesnt need to be defined explicitly)
|
||||
///
|
||||
/// \return The Array itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<class V>
|
||||
ArrayBase& Append(V* val) {
|
||||
sq_pushobject(vm, GetObject());
|
||||
PushVar(vm, val);
|
||||
sq_arrayappend(vm, -2);
|
||||
sq_pop(vm,1); // pop array
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Inserts a value in a position in the Array
|
||||
///
|
||||
/// \param destpos Index to put the new value in
|
||||
/// \param val Value that is being placed in the Array
|
||||
///
|
||||
/// \tparam V Type of value (usually doesnt need to be defined explicitly)
|
||||
///
|
||||
/// \return The Array itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<class V>
|
||||
ArrayBase& Insert(const SQInteger destpos, const V& val) {
|
||||
sq_pushobject(vm, GetObject());
|
||||
PushVar(vm, val);
|
||||
sq_arrayinsert(vm, -2, destpos);
|
||||
sq_pop(vm,1); // pop array
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Inserts an instance in a position in the Array (like a reference)
|
||||
///
|
||||
/// \param destpos Index to put the new value in
|
||||
/// \param val Pointer to the instance that is being placed in the Array
|
||||
///
|
||||
/// \tparam V Type of instance (usually doesnt need to be defined explicitly)
|
||||
///
|
||||
/// \return The Array itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<class V>
|
||||
ArrayBase& Insert(const SQInteger destpos, V* val) {
|
||||
sq_pushobject(vm, GetObject());
|
||||
PushVar(vm, val);
|
||||
sq_arrayinsert(vm, -2, destpos);
|
||||
sq_pop(vm,1); // pop array
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Removes the last element from the Array
|
||||
///
|
||||
/// \return Object for the element that was removed (null if failed)
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Object Pop() {
|
||||
HSQOBJECT slotObj;
|
||||
sq_pushobject(vm, GetObject());
|
||||
if(SQ_FAILED(sq_arraypop(vm, -1, true))) {
|
||||
sq_pop(vm, 1);
|
||||
return Object(); // Return a NULL object
|
||||
} else {
|
||||
sq_getstackobj(vm, -1, &slotObj);
|
||||
Object ret(slotObj, vm);
|
||||
sq_pop(vm, 2);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Removes an element at a specific index from the Array
|
||||
///
|
||||
/// \param itemidx Index of the element being removed
|
||||
///
|
||||
/// \return The Array itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ArrayBase& Remove(const SQInteger itemidx) {
|
||||
sq_pushobject(vm, GetObject());
|
||||
sq_arrayremove(vm, -1, itemidx);
|
||||
sq_pop(vm,1); // pop array
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Resizes the Array
|
||||
///
|
||||
/// \param newsize Desired size of the Array in number of elements
|
||||
///
|
||||
/// \return The Array itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ArrayBase& Resize(const SQInteger newsize) {
|
||||
sq_pushobject(vm, GetObject());
|
||||
sq_arrayresize(vm, -1, newsize);
|
||||
sq_pop(vm,1); // pop array
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reverses the elements of the array in place
|
||||
///
|
||||
/// \return The Array itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ArrayBase& Reverse() {
|
||||
sq_pushobject(vm, GetObject());
|
||||
sq_arrayreverse(vm, -1);
|
||||
sq_pop(vm,1); // pop array
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Returns the length of the Array
|
||||
///
|
||||
/// \return Length in number of elements
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
SQInteger Length() const
|
||||
{
|
||||
sq_pushobject(vm, obj);
|
||||
SQInteger r = sq_getsize(vm, -1);
|
||||
sq_pop(vm, 1);
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Represents an array in Squirrel
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class Array : public ArrayBase {
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Default constructor (null)
|
||||
///
|
||||
/// \remarks
|
||||
/// The Array is invalid until it is given a VM to exist in.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Array() {
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructs an Array
|
||||
///
|
||||
/// \param v VM to create the Array in
|
||||
/// \param size An optional size hint
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Array(HSQUIRRELVM v, const SQInteger size = 0) : ArrayBase(v) {
|
||||
sq_newarray(vm, size);
|
||||
sq_getstackobj(vm,-1,&obj);
|
||||
sq_addref(vm, &obj);
|
||||
sq_pop(vm,1);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Construct the Array from an Object that already exists
|
||||
///
|
||||
/// \param obj An Object that should already represent a Squirrel array
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Array(const Object& obj) : ArrayBase(obj) {
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Construct the Array from a HSQOBJECT and HSQUIRRELVM that already exist
|
||||
///
|
||||
/// \param o Squirrel object that should already represent a Squirrel array
|
||||
/// \param v Squirrel VM that contains the Squirrel object given
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Array(HSQOBJECT o, HSQUIRRELVM v = DefaultVM::Get()) : ArrayBase(o, v) {
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Used to get and push Array instances to and from the stack as references (arrays are always references in Squirrel)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<>
|
||||
struct Var<Array> {
|
||||
|
||||
Array value; ///< The actual value of get operations
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Attempts to get the value off the stack at idx as an Array
|
||||
///
|
||||
/// \param vm Target VM
|
||||
/// \param idx Index trying to be read
|
||||
///
|
||||
/// \remarks
|
||||
/// This function MUST have its Error handled if it occurred.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Var(HSQUIRRELVM vm, SQInteger idx) {
|
||||
HSQOBJECT obj;
|
||||
sq_resetobject(&obj);
|
||||
sq_getstackobj(vm,idx,&obj);
|
||||
value = Array(obj, vm);
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
SQObjectType value_type = sq_gettype(vm, idx);
|
||||
if (value_type != OT_ARRAY) {
|
||||
SQTHROW(vm, FormatTypeError(vm, idx, _SC("array")));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Called by Sqrat::PushVar to put an Array reference on the stack
|
||||
///
|
||||
/// \param vm Target VM
|
||||
/// \param value Value to push on to the VM's stack
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static void push(HSQUIRRELVM vm, const Array& value) {
|
||||
HSQOBJECT obj;
|
||||
sq_resetobject(&obj);
|
||||
obj = value.GetObject();
|
||||
sq_pushobject(vm,obj);
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Used to get and push Array instances to and from the stack as references (arrays are always references in Squirrel)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<>
|
||||
struct Var<Array&> : Var<Array> {Var(HSQUIRRELVM vm, SQInteger idx) : Var<Array>(vm, idx) {}};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Used to get and push Array instances to and from the stack as references (arrays are always references in Squirrel)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<>
|
||||
struct Var<const Array&> : Var<Array> {Var(HSQUIRRELVM vm, SQInteger idx) : Var<Array>(vm, idx) {}};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
1052
include/sqrat/sqratClass.h
Normal file
1052
include/sqrat/sqratClass.h
Normal file
File diff suppressed because it is too large
Load Diff
250
include/sqrat/sqratClassType.h
Normal file
250
include/sqrat/sqratClassType.h
Normal file
@ -0,0 +1,250 @@
|
||||
//
|
||||
// SqratClassType: Type Translators
|
||||
//
|
||||
|
||||
//
|
||||
// Copyright (c) 2009 Brandon Jones
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
|
||||
#if !defined(_SCRAT_CLASSTYPE_H_)
|
||||
#define _SCRAT_CLASSTYPE_H_
|
||||
|
||||
#include <squirrel.h>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "sqratUtil.h"
|
||||
|
||||
namespace Sqrat
|
||||
{
|
||||
|
||||
/// @cond DEV
|
||||
|
||||
// The copy function for a class
|
||||
typedef SQInteger (*COPYFUNC)(HSQUIRRELVM, SQInteger, const void*);
|
||||
|
||||
// Every Squirrel class instance made by Sqrat has its type tag set to a AbstractStaticClassData object that is unique per C++ class
|
||||
struct AbstractStaticClassData {
|
||||
AbstractStaticClassData() {}
|
||||
virtual ~AbstractStaticClassData() {}
|
||||
virtual SQUserPointer Cast(SQUserPointer ptr, SQUserPointer classType) = 0;
|
||||
AbstractStaticClassData* baseClass;
|
||||
string className;
|
||||
COPYFUNC copyFunc;
|
||||
};
|
||||
|
||||
// StaticClassData keeps track of the nearest base class B and the class associated with itself C in order to cast C++ pointers to the right base class
|
||||
template<class C, class B>
|
||||
struct StaticClassData : public AbstractStaticClassData {
|
||||
virtual SQUserPointer Cast(SQUserPointer ptr, SQUserPointer classType) {
|
||||
if (classType != this) {
|
||||
ptr = baseClass->Cast(static_cast<B*>(static_cast<C*>(ptr)), classType);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
};
|
||||
|
||||
// Every Squirrel class object created by Sqrat in every VM has its own unique ClassData object stored in the registry table of the VM
|
||||
template<class C>
|
||||
struct ClassData {
|
||||
HSQOBJECT classObj;
|
||||
HSQOBJECT getTable;
|
||||
HSQOBJECT setTable;
|
||||
SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> instances;
|
||||
SharedPtr<AbstractStaticClassData> staticData;
|
||||
};
|
||||
|
||||
// Lookup static class data by type_info rather than a template because C++ cannot export generic templates
|
||||
class _ClassType_helper {
|
||||
public:
|
||||
#if defined(SCRAT_IMPORT)
|
||||
static SQRAT_API WeakPtr<AbstractStaticClassData>& _getStaticClassData(const std::type_info* type);
|
||||
#else
|
||||
struct compare_type_info {
|
||||
bool operator ()(const std::type_info* left, const std::type_info* right) const {
|
||||
return left->before(*right) != 0;
|
||||
}
|
||||
};
|
||||
static SQRAT_API WeakPtr<AbstractStaticClassData>& _getStaticClassData(const std::type_info* type) {
|
||||
static std::map<const std::type_info*, WeakPtr<AbstractStaticClassData>, compare_type_info> data;
|
||||
return data[type];
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
// Internal helper class for managing classes
|
||||
template<class C>
|
||||
class ClassType {
|
||||
public:
|
||||
|
||||
static inline ClassData<C>* getClassData(HSQUIRRELVM vm) {
|
||||
sq_pushregistrytable(vm);
|
||||
sq_pushstring(vm, "__classes", -1);
|
||||
#ifndef NDEBUG
|
||||
SQRESULT r = sq_rawget(vm, -2);
|
||||
assert(SQ_SUCCEEDED(r)); // fails if getClassData is called when the data does not exist for the given VM yet (bind the class)
|
||||
#else
|
||||
sq_rawget(vm, -2);
|
||||
#endif
|
||||
sq_pushstring(vm, ClassName().c_str(), -1);
|
||||
#ifndef NDEBUG
|
||||
r = sq_rawget(vm, -2);
|
||||
assert(SQ_SUCCEEDED(r)); // fails if getClassData is called when the data does not exist for the given VM yet (bind the class)
|
||||
#else
|
||||
sq_rawget(vm, -2);
|
||||
#endif
|
||||
ClassData<C>** ud;
|
||||
sq_getuserdata(vm, -1, (SQUserPointer*)&ud, NULL);
|
||||
sq_pop(vm, 3);
|
||||
return *ud;
|
||||
}
|
||||
|
||||
static WeakPtr<AbstractStaticClassData>& getStaticClassData() {
|
||||
return _ClassType_helper::_getStaticClassData(&typeid(C));
|
||||
}
|
||||
|
||||
static inline bool hasClassData(HSQUIRRELVM vm) {
|
||||
if (!getStaticClassData().Expired()) {
|
||||
sq_pushregistrytable(vm);
|
||||
sq_pushstring(vm, "__classes", -1);
|
||||
if (SQ_SUCCEEDED(sq_rawget(vm, -2))) {
|
||||
sq_pushstring(vm, ClassName().c_str(), -1);
|
||||
if (SQ_SUCCEEDED(sq_rawget(vm, -2))) {
|
||||
sq_pop(vm, 3);
|
||||
return true;
|
||||
}
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline AbstractStaticClassData*& BaseClass() {
|
||||
assert(getStaticClassData().Expired() == false); // fails because called before a Sqrat::Class for this type exists
|
||||
return getStaticClassData().Lock()->baseClass;
|
||||
}
|
||||
|
||||
static inline string& ClassName() {
|
||||
assert(getStaticClassData().Expired() == false); // fails because called before a Sqrat::Class for this type exists
|
||||
return getStaticClassData().Lock()->className;
|
||||
}
|
||||
|
||||
static inline COPYFUNC& CopyFunc() {
|
||||
assert(getStaticClassData().Expired() == false); // fails because called before a Sqrat::Class for this type exists
|
||||
return getStaticClassData().Lock()->copyFunc;
|
||||
}
|
||||
|
||||
static SQInteger DeleteInstance(SQUserPointer ptr, SQInteger size) {
|
||||
SQUNUSED(size);
|
||||
std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >* instance = reinterpret_cast<std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >*>(ptr);
|
||||
instance->second->erase(instance->first);
|
||||
delete instance;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void PushInstance(HSQUIRRELVM vm, C* ptr) {
|
||||
if (!ptr) {
|
||||
sq_pushnull(vm);
|
||||
return;
|
||||
}
|
||||
|
||||
ClassData<C>* cd = getClassData(vm);
|
||||
|
||||
typename unordered_map<C*, HSQOBJECT>::type::iterator it = cd->instances->find(ptr);
|
||||
if (it != cd->instances->end()) {
|
||||
sq_pushobject(vm, it->second);
|
||||
return;
|
||||
}
|
||||
|
||||
sq_pushobject(vm, cd->classObj);
|
||||
sq_createinstance(vm, -1);
|
||||
sq_remove(vm, -2);
|
||||
sq_setinstanceup(vm, -1, new std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >(ptr, cd->instances));
|
||||
sq_setreleasehook(vm, -1, &DeleteInstance);
|
||||
sq_getstackobj(vm, -1, &((*cd->instances)[ptr]));
|
||||
}
|
||||
|
||||
static void PushInstanceCopy(HSQUIRRELVM vm, const C& value) {
|
||||
sq_pushobject(vm, getClassData(vm)->classObj);
|
||||
sq_createinstance(vm, -1);
|
||||
sq_remove(vm, -2);
|
||||
#ifndef NDEBUG
|
||||
SQRESULT result = CopyFunc()(vm, -1, &value);
|
||||
assert(SQ_SUCCEEDED(result)); // fails when trying to copy an object defined as non-copyable
|
||||
#else
|
||||
CopyFunc()(vm, -1, &value);
|
||||
#endif
|
||||
}
|
||||
|
||||
static C* GetInstance(HSQUIRRELVM vm, SQInteger idx, bool nullAllowed = false) {
|
||||
AbstractStaticClassData* classType = NULL;
|
||||
std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >* instance = NULL;
|
||||
if (hasClassData(vm)) /* type checking only done if the value has type data else it may be enum */
|
||||
{
|
||||
if (nullAllowed && sq_gettype(vm, idx) == OT_NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
classType = getStaticClassData().Lock().Get();
|
||||
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
if (SQ_FAILED(sq_getinstanceup(vm, idx, (SQUserPointer*)&instance, classType))) {
|
||||
SQTHROW(vm, FormatTypeError(vm, idx, ClassName()));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (instance == NULL) {
|
||||
SQTHROW(vm, _SC("got unconstructed native class (call base.constructor in the constructor of Squirrel classes that extend native classes)"));
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
sq_getinstanceup(vm, idx, (SQUserPointer*)&instance, 0);
|
||||
#endif
|
||||
}
|
||||
else /* value is likely of integral type like enums, cannot return a pointer */
|
||||
{
|
||||
SQTHROW(vm, FormatTypeError(vm, idx, _SC("unknown")));
|
||||
return NULL;
|
||||
}
|
||||
AbstractStaticClassData* actualType;
|
||||
sq_gettypetag(vm, idx, (SQUserPointer*)&actualType);
|
||||
if (actualType == NULL) {
|
||||
SQInteger top = sq_gettop(vm);
|
||||
sq_getclass(vm, idx);
|
||||
while (actualType == NULL) {
|
||||
sq_getbase(vm, -1);
|
||||
sq_gettypetag(vm, -1, (SQUserPointer*)&actualType);
|
||||
}
|
||||
sq_settop(vm, top);
|
||||
}
|
||||
if (classType != actualType) {
|
||||
return static_cast<C*>(actualType->Cast(instance->first, classType));
|
||||
}
|
||||
return static_cast<C*>(instance->first);
|
||||
}
|
||||
};
|
||||
|
||||
/// @endcond
|
||||
|
||||
}
|
||||
|
||||
#endif
|
250
include/sqrat/sqratClassType.h.save-failed
Normal file
250
include/sqrat/sqratClassType.h.save-failed
Normal file
@ -0,0 +1,250 @@
|
||||
//
|
||||
// SqratClassType: Type Translators
|
||||
//
|
||||
|
||||
//
|
||||
// Copyright (c) 2009 Brandon Jones
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
|
||||
#if !defined(_SCRAT_CLASSTYPE_H_)
|
||||
#define _SCRAT_CLASSTYPE_H_
|
||||
|
||||
#include <squirrel.h>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "sqratUtil.h"
|
||||
|
||||
namespace Sqrat
|
||||
{
|
||||
|
||||
/// @cond DEV
|
||||
|
||||
// The copy function for a class
|
||||
typedef SQInteger (*COPYFUNC)(HSQUIRRELVM, SQInteger, const void*);
|
||||
|
||||
// Every Squirrel class instance made by Sqrat has its type tag set to a AbstractStaticClassData object that is unique per C++ class
|
||||
struct AbstractStaticClassData {
|
||||
AbstractStaticClassData() {}
|
||||
virtual ~AbstractStaticClassData() {}
|
||||
virtual SQUserPointer Cast(SQUserPointer ptr, SQUserPointer classType) { printf("Pure Virtual!"); return 0; }
|
||||
AbstractStaticClassData* baseClass;
|
||||
string className;
|
||||
COPYFUNC copyFunc;
|
||||
};
|
||||
|
||||
// StaticClassData keeps track of the nearest base class B and the class associated with itself C in order to cast C++ pointers to the right base class
|
||||
template<class C, class B>
|
||||
struct StaticClassData : public AbstractStaticClassData {
|
||||
virtual SQUserPointer Cast(SQUserPointer ptr, SQUserPointer classType) {
|
||||
if (classType != this) {
|
||||
ptr = baseClass->Cast(static_cast<B*>(static_cast<C*>(ptr)), classType);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
};
|
||||
|
||||
// Every Squirrel class object created by Sqrat in every VM has its own unique ClassData object stored in the registry table of the VM
|
||||
template<class C>
|
||||
struct ClassData {
|
||||
HSQOBJECT classObj;
|
||||
HSQOBJECT getTable;
|
||||
HSQOBJECT setTable;
|
||||
SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> instances;
|
||||
SharedPtr<AbstractStaticClassData> staticData;
|
||||
};
|
||||
|
||||
// Lookup static class data by type_info rather than a template because C++ cannot export generic templates
|
||||
class _ClassType_helper {
|
||||
public:
|
||||
#if defined(SCRAT_IMPORT)
|
||||
static SQRAT_API WeakPtr<AbstractStaticClassData>& _getStaticClassData(const std::type_info* type);
|
||||
#else
|
||||
struct compare_type_info {
|
||||
bool operator ()(const std::type_info* left, const std::type_info* right) const {
|
||||
return left->before(*right) != 0;
|
||||
}
|
||||
};
|
||||
static SQRAT_API WeakPtr<AbstractStaticClassData>& _getStaticClassData(const std::type_info* type) {
|
||||
static std::map<const std::type_info*, WeakPtr<AbstractStaticClassData>, compare_type_info> data;
|
||||
return data[type];
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
// Internal helper class for managing classes
|
||||
template<class C>
|
||||
class ClassType {
|
||||
public:
|
||||
|
||||
static inline ClassData<C>* getClassData(HSQUIRRELVM vm) {
|
||||
sq_pushregistrytable(vm);
|
||||
sq_pushstring(vm, "__classes", -1);
|
||||
#ifndef NDEBUG
|
||||
SQRESULT r = sq_rawget(vm, -2);
|
||||
assert(SQ_SUCCEEDED(r)); // fails if getClassData is called when the data does not exist for the given VM yet (bind the class)
|
||||
#else
|
||||
sq_rawget(vm, -2);
|
||||
#endif
|
||||
sq_pushstring(vm, ClassName().c_str(), -1);
|
||||
#ifndef NDEBUG
|
||||
r = sq_rawget(vm, -2);
|
||||
assert(SQ_SUCCEEDED(r)); // fails if getClassData is called when the data does not exist for the given VM yet (bind the class)
|
||||
#else
|
||||
sq_rawget(vm, -2);
|
||||
#endif
|
||||
ClassData<C>** ud;
|
||||
sq_getuserdata(vm, -1, (SQUserPointer*)&ud, NULL);
|
||||
sq_pop(vm, 3);
|
||||
return *ud;
|
||||
}
|
||||
|
||||
static WeakPtr<AbstractStaticClassData>& getStaticClassData() {
|
||||
return _ClassType_helper::_getStaticClassData(&typeid(C));
|
||||
}
|
||||
|
||||
static inline bool hasClassData(HSQUIRRELVM vm) {
|
||||
if (!getStaticClassData().Expired()) {
|
||||
sq_pushregistrytable(vm);
|
||||
sq_pushstring(vm, "__classes", -1);
|
||||
if (SQ_SUCCEEDED(sq_rawget(vm, -2))) {
|
||||
sq_pushstring(vm, ClassName().c_str(), -1);
|
||||
if (SQ_SUCCEEDED(sq_rawget(vm, -2))) {
|
||||
sq_pop(vm, 3);
|
||||
return true;
|
||||
}
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline AbstractStaticClassData*& BaseClass() {
|
||||
assert(getStaticClassData().Expired() == false); // fails because called before a Sqrat::Class for this type exists
|
||||
return getStaticClassData().Lock()->baseClass;
|
||||
}
|
||||
|
||||
static inline string& ClassName() {
|
||||
assert(getStaticClassData().Expired() == false); // fails because called before a Sqrat::Class for this type exists
|
||||
return getStaticClassData().Lock()->className;
|
||||
}
|
||||
|
||||
static inline COPYFUNC& CopyFunc() {
|
||||
assert(getStaticClassData().Expired() == false); // fails because called before a Sqrat::Class for this type exists
|
||||
return getStaticClassData().Lock()->copyFunc;
|
||||
}
|
||||
|
||||
static SQInteger DeleteInstance(SQUserPointer ptr, SQInteger size) {
|
||||
SQUNUSED(size);
|
||||
std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >* instance = reinterpret_cast<std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >*>(ptr);
|
||||
instance->second->erase(instance->first);
|
||||
delete instance;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void PushInstance(HSQUIRRELVM vm, C* ptr) {
|
||||
if (!ptr) {
|
||||
sq_pushnull(vm);
|
||||
return;
|
||||
}
|
||||
|
||||
ClassData<C>* cd = getClassData(vm);
|
||||
|
||||
typename unordered_map<C*, HSQOBJECT>::type::iterator it = cd->instances->find(ptr);
|
||||
if (it != cd->instances->end()) {
|
||||
sq_pushobject(vm, it->second);
|
||||
return;
|
||||
}
|
||||
|
||||
sq_pushobject(vm, cd->classObj);
|
||||
sq_createinstance(vm, -1);
|
||||
sq_remove(vm, -2);
|
||||
sq_setinstanceup(vm, -1, new std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >(ptr, cd->instances));
|
||||
sq_setreleasehook(vm, -1, &DeleteInstance);
|
||||
sq_getstackobj(vm, -1, &((*cd->instances)[ptr]));
|
||||
}
|
||||
|
||||
static void PushInstanceCopy(HSQUIRRELVM vm, const C& value) {
|
||||
sq_pushobject(vm, getClassData(vm)->classObj);
|
||||
sq_createinstance(vm, -1);
|
||||
sq_remove(vm, -2);
|
||||
#ifndef NDEBUG
|
||||
SQRESULT result = CopyFunc()(vm, -1, &value);
|
||||
assert(SQ_SUCCEEDED(result)); // fails when trying to copy an object defined as non-copyable
|
||||
#else
|
||||
CopyFunc()(vm, -1, &value);
|
||||
#endif
|
||||
}
|
||||
|
||||
static C* GetInstance(HSQUIRRELVM vm, SQInteger idx, bool nullAllowed = false) {
|
||||
AbstractStaticClassData* classType = NULL;
|
||||
std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >* instance = NULL;
|
||||
if (hasClassData(vm)) /* type checking only done if the value has type data else it may be enum */
|
||||
{
|
||||
if (nullAllowed && sq_gettype(vm, idx) == OT_NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
classType = getStaticClassData().Lock().Get();
|
||||
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
if (SQ_FAILED(sq_getinstanceup(vm, idx, (SQUserPointer*)&instance, classType))) {
|
||||
SQTHROW(vm, FormatTypeError(vm, idx, ClassName()));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (instance == NULL) {
|
||||
SQTHROW(vm, _SC("got unconstructed native class (call base.constructor in the constructor of Squirrel classes that extend native classes)"));
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
sq_getinstanceup(vm, idx, (SQUserPointer*)&instance, 0);
|
||||
#endif
|
||||
}
|
||||
else /* value is likely of integral type like enums, cannot return a pointer */
|
||||
{
|
||||
SQTHROW(vm, FormatTypeError(vm, idx, _SC("unknown")));
|
||||
return NULL;
|
||||
}
|
||||
AbstractStaticClassData* actualType;
|
||||
sq_gettypetag(vm, idx, (SQUserPointer*)&actualType);
|
||||
if (actualType == NULL) {
|
||||
SQInteger top = sq_gettop(vm);
|
||||
sq_getclass(vm, idx);
|
||||
while (actualType == NULL) {
|
||||
sq_getbase(vm, -1);
|
||||
sq_gettypetag(vm, -1, (SQUserPointer*)&actualType);
|
||||
}
|
||||
sq_settop(vm, top);
|
||||
}
|
||||
if (classType != actualType) {
|
||||
return static_cast<C*>(actualType->Cast(instance->first, classType));
|
||||
}
|
||||
return static_cast<C*>(instance->first);
|
||||
}
|
||||
};
|
||||
|
||||
/// @endcond
|
||||
|
||||
}
|
||||
|
||||
#endif
|
214
include/sqrat/sqratConst.h
Normal file
214
include/sqrat/sqratConst.h
Normal file
@ -0,0 +1,214 @@
|
||||
//
|
||||
// SqratConst: Constant and Enumeration Binding
|
||||
//
|
||||
|
||||
//
|
||||
// Copyright (c) 2009 Brandon Jones
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
|
||||
#if !defined(_SCRAT_CONST_H_)
|
||||
#define _SCRAT_CONST_H_
|
||||
|
||||
#include <squirrel.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sqratObject.h"
|
||||
|
||||
namespace Sqrat {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Facilitates exposing a C++ enumeration to Squirrel
|
||||
///
|
||||
/// \remarks
|
||||
/// The Enumeration class only facilitates binding C++ enumerations that contain only integers,
|
||||
/// floats, and strings because the Squirrel constant table can only contain these types of
|
||||
/// values. Other types of enumerations can be bound using Class::SetStaticValue instead.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class Enumeration : public Object {
|
||||
public:
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructs the Enumeration object
|
||||
///
|
||||
/// An Enumeration object doesnt do anything on its own.
|
||||
/// It must be told what constant values it contains.
|
||||
/// This is done using Enumeration::Const.
|
||||
/// Then the Enumeration must be exposed to Squirrel.
|
||||
/// This is done by calling ConstTable::Enum with the Enumeration.
|
||||
///
|
||||
/// \param v Squirrel virtual machine to create the Enumeration for
|
||||
/// \param createTable Whether the underlying table that values are bound to is created by the constructor
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Enumeration(HSQUIRRELVM v = DefaultVM::Get(), bool createTable = true) : Object(v, false) {
|
||||
if(createTable) {
|
||||
sq_newtable(vm);
|
||||
sq_getstackobj(vm,-1,&obj);
|
||||
sq_addref(vm, &obj);
|
||||
sq_pop(vm,1);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binds an enumeration value
|
||||
///
|
||||
/// \param name Name of the value as it will appear in Squirrel
|
||||
/// \param val Value to bind
|
||||
///
|
||||
/// \return The Enumeration itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
virtual Enumeration& Const(const SQChar* name, const int val) {
|
||||
BindValue<int>(name, val, false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binds an enumeration value
|
||||
///
|
||||
/// \param name Name of the value as it will appear in Squirrel
|
||||
/// \param val Value to bind
|
||||
///
|
||||
/// \return The Enumeration itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
virtual Enumeration& Const(const SQChar* name, const long long int val) {
|
||||
BindValue<long long int>(name, val, false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binds an enumeration value
|
||||
///
|
||||
/// \param name Name of the value as it will appear in Squirrel
|
||||
/// \param val Value to bind
|
||||
///
|
||||
/// \return The Enumeration itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
virtual Enumeration& Const(const SQChar* name, const float val) {
|
||||
BindValue<float>(name, val, false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binds an enumeration value
|
||||
///
|
||||
/// \param name Name of the value as it will appear in Squirrel
|
||||
/// \param val Value to bind
|
||||
///
|
||||
/// \return The Enumeration itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
virtual Enumeration& Const(const SQChar* name, const SQChar* val) {
|
||||
BindValue<const SQChar*>(name, val, false);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Facilitates exposing a C++ constant to Squirrel
|
||||
///
|
||||
/// \remarks
|
||||
/// The ConstTable class only facilitates binding C++ constants that are integers,
|
||||
/// floats, and strings because the Squirrel constant table can only contain these types of
|
||||
/// values. Other types of constants can be bound using Class::SetStaticValue instead.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class ConstTable : public Enumeration {
|
||||
public:
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructs a ConstTable object to represent the given VM's const table
|
||||
///
|
||||
/// \param v VM to get the ConstTable for
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ConstTable(HSQUIRRELVM v = DefaultVM::Get()) : Enumeration(v, false) {
|
||||
sq_pushconsttable(vm);
|
||||
sq_getstackobj(vm,-1, &obj);
|
||||
sq_pop(v,1); // No addref needed, since the consttable is always around
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binds a constant value
|
||||
///
|
||||
/// \param name Name of the value as it will appear in Squirrel
|
||||
/// \param val Value to bind
|
||||
///
|
||||
/// \return The ConstTable itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
virtual ConstTable& Const(const SQChar* name, const int val) {
|
||||
Enumeration::Const(name, val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binds a constant value
|
||||
///
|
||||
/// \param name Name of the value as it will appear in Squirrel
|
||||
/// \param val Value to bind
|
||||
///
|
||||
/// \return The ConstTable itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
virtual ConstTable& Const(const SQChar* name, const float val) {
|
||||
Enumeration::Const(name, val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binds a constant value
|
||||
///
|
||||
/// \param name Name of the value as it will appear in Squirrel
|
||||
/// \param val Value to bind
|
||||
///
|
||||
/// \return The ConstTable itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
virtual ConstTable& Const(const SQChar* name, const SQChar* val) {
|
||||
Enumeration::Const(name, val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binds an Enumeration to the ConstTable
|
||||
///
|
||||
/// \param name Name of the enumeration as it will appear in Squirrel
|
||||
/// \param en Enumeration to bind
|
||||
///
|
||||
/// \return The ConstTable itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ConstTable& Enum(const SQChar* name, Enumeration& en) {
|
||||
sq_pushobject(vm, GetObject());
|
||||
sq_pushstring(vm, name, -1);
|
||||
sq_pushobject(vm, en.GetObject());
|
||||
sq_newslot(vm, -3, false);
|
||||
sq_pop(vm,1); // pop table
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
2692
include/sqrat/sqratFunction.h
Normal file
2692
include/sqrat/sqratFunction.h
Normal file
File diff suppressed because it is too large
Load Diff
2382
include/sqrat/sqratGlobalMethods.h
Normal file
2382
include/sqrat/sqratGlobalMethods.h
Normal file
File diff suppressed because it is too large
Load Diff
5597
include/sqrat/sqratMemberMethods.h
Normal file
5597
include/sqrat/sqratMemberMethods.h
Normal file
File diff suppressed because it is too large
Load Diff
557
include/sqrat/sqratObject.h
Normal file
557
include/sqrat/sqratObject.h
Normal file
@ -0,0 +1,557 @@
|
||||
//
|
||||
// SqratObject: Referenced Squirrel Object Wrapper
|
||||
//
|
||||
|
||||
//
|
||||
// Copyright (c) 2009 Brandon Jones
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
|
||||
#if !defined(_SCRAT_OBJECT_H_)
|
||||
#define _SCRAT_OBJECT_H_
|
||||
|
||||
#include <squirrel.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sqratAllocator.h"
|
||||
#include "sqratTypes.h"
|
||||
#include "sqratOverloadMethods.h"
|
||||
#include "sqratUtil.h"
|
||||
|
||||
namespace Sqrat {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// The base class for classes that represent Squirrel objects
|
||||
///
|
||||
/// \remarks
|
||||
/// All Object and derived classes MUST be destroyed before calling sq_close or your application will crash when exiting.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class Object {
|
||||
protected:
|
||||
|
||||
/// @cond DEV
|
||||
HSQUIRRELVM vm;
|
||||
HSQOBJECT obj;
|
||||
bool release;
|
||||
|
||||
Object(HSQUIRRELVM v, bool releaseOnDestroy = true) : vm(v), release(releaseOnDestroy) {
|
||||
sq_resetobject(&obj);
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Default constructor (null)
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Object() : vm(0), release(true) {
|
||||
sq_resetobject(&obj);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Copy constructor
|
||||
///
|
||||
/// \param so Object to copy
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Object(const Object& so) : vm(so.vm), obj(so.obj), release(so.release) {
|
||||
sq_addref(vm, &obj);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructs an Object from a Squirrel object
|
||||
///
|
||||
/// \param o Squirrel object
|
||||
/// \param v VM that the object will exist in
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Object(HSQOBJECT o, HSQUIRRELVM v = DefaultVM::Get()) : vm(v), obj(o), release(true) {
|
||||
sq_addref(vm, &obj);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructs an Object from a C++ instance
|
||||
///
|
||||
/// \param instance Pointer to a C++ class instance that has been bound already
|
||||
/// \param v VM that the object will exist in
|
||||
///
|
||||
/// \tparam T Type of instance
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
Object(T* instance, HSQUIRRELVM v = DefaultVM::Get()) : vm(v), release(true) {
|
||||
ClassType<T>::PushInstance(vm, instance);
|
||||
sq_getstackobj(vm, -1, &obj);
|
||||
sq_addref(vm, &obj);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Destructor
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
virtual ~Object() {
|
||||
if(release) {
|
||||
Release();
|
||||
release = false;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment operator
|
||||
///
|
||||
/// \param so Object to copy
|
||||
///
|
||||
/// \return The Object itself
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Object& operator=(const Object& so) {
|
||||
if(release) {
|
||||
Release();
|
||||
}
|
||||
vm = so.vm;
|
||||
obj = so.obj;
|
||||
release = so.release;
|
||||
sq_addref(vm, &GetObject());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Gets the Squirrel VM for this Object (reference)
|
||||
///
|
||||
/// \return Squirrel VM associated with the Object
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
HSQUIRRELVM& GetVM() {
|
||||
return vm;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Gets the Squirrel VM for this Object (copy)
|
||||
///
|
||||
/// \return Squirrel VM associated with the Object
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
HSQUIRRELVM GetVM() const {
|
||||
return vm;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Gets the type of the Object as defined by the Squirrel API
|
||||
///
|
||||
/// \return SQObjectType for the Object
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
SQObjectType GetType() const {
|
||||
return GetObject()._type;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Checks whether the Object is null
|
||||
///
|
||||
/// \return True if the Object currently has a null value, otherwise false
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool IsNull() const {
|
||||
return sq_isnull(GetObject());
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Gets the Squirrel object for this Object (copy)
|
||||
///
|
||||
/// \return Squirrel object
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
virtual HSQOBJECT GetObject() const {
|
||||
return obj;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Gets the Squirrel object for this Object (reference)
|
||||
///
|
||||
/// \return Squirrel object
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
virtual HSQOBJECT& GetObject() {
|
||||
return obj;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Allows the Object to be inputted directly into places that expect a HSQOBJECT
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
operator HSQOBJECT&() {
|
||||
return GetObject();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Sets the Object to null (removing its references to underlying Squirrel objects)
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void Release() {
|
||||
sq_release(vm, &obj);
|
||||
sq_resetobject(&obj);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Attempts to get the value of a slot from the object
|
||||
///
|
||||
/// \param slot Name of the slot
|
||||
///
|
||||
/// \return An Object representing the value of the slot (can be a null object if nothing was found)
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Object GetSlot(const SQChar* slot) const {
|
||||
HSQOBJECT slotObj;
|
||||
sq_pushobject(vm, GetObject());
|
||||
sq_pushstring(vm, slot, -1);
|
||||
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
if(SQ_FAILED(sq_get(vm, -2))) {
|
||||
sq_pop(vm, 1);
|
||||
return Object(vm); // Return a NULL object
|
||||
} else {
|
||||
sq_getstackobj(vm, -1, &slotObj);
|
||||
Object ret(slotObj, vm); // must addref before the pop!
|
||||
sq_pop(vm, 2);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
sq_get(vm, -2);
|
||||
sq_getstackobj(vm, -1, &slotObj);
|
||||
Object ret(slotObj, vm); // must addref before the pop!
|
||||
sq_pop(vm, 2);
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Attempts to get the value of an index from the object
|
||||
///
|
||||
/// \param index Index of the slot
|
||||
///
|
||||
/// \return An Object representing the value of the slot (can be a null object if nothing was found)
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Object GetSlot(SQInteger index) const {
|
||||
HSQOBJECT slotObj;
|
||||
sq_pushobject(vm, GetObject());
|
||||
sq_pushinteger(vm, index);
|
||||
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
if(SQ_FAILED(sq_get(vm, -2))) {
|
||||
sq_pop(vm, 1);
|
||||
return Object(vm); // Return a NULL object
|
||||
} else {
|
||||
sq_getstackobj(vm, -1, &slotObj);
|
||||
Object ret(slotObj, vm); // must addref before the pop!
|
||||
sq_pop(vm, 2);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
sq_get(vm, -2);
|
||||
sq_getstackobj(vm, -1, &slotObj);
|
||||
Object ret(slotObj, vm); // must addref before the pop!
|
||||
sq_pop(vm, 2);
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Casts the object to a certain C++ type
|
||||
///
|
||||
/// \tparam T Type to cast to
|
||||
///
|
||||
/// \return A copy of the value of the Object with the given type
|
||||
///
|
||||
/// \remarks
|
||||
/// This function MUST have its Error handled if it occurred.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <class T>
|
||||
T Cast() const {
|
||||
sq_pushobject(vm, GetObject());
|
||||
T ret = Var<T>(vm, -1).value;
|
||||
sq_pop(vm, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Allows Object to be used like C++ arrays with the [] operator
|
||||
///
|
||||
/// \param slot The slot key
|
||||
///
|
||||
/// \tparam T Type of the slot key (usually doesnt need to be defined explicitly)
|
||||
///
|
||||
/// \return An Object representing the value of the slot (can be a null object if nothing was found)
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <class T>
|
||||
inline Object operator[](T slot)
|
||||
{
|
||||
return GetSlot(slot);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Returns the size of the Object
|
||||
///
|
||||
/// \return Size of Object
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
SQInteger GetSize() const {
|
||||
sq_pushobject(vm, GetObject());
|
||||
SQInteger ret = sq_getsize(vm, -1);
|
||||
sq_pop(vm, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Iterator for going over the slots in the object using Object::Next
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
struct iterator
|
||||
{
|
||||
/// @cond DEV
|
||||
friend class Object;
|
||||
/// @endcond
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Default constructor (null)
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
iterator()
|
||||
{
|
||||
Index = 0;
|
||||
sq_resetobject(&Key);
|
||||
sq_resetobject(&Value);
|
||||
Key._type = OT_NULL;
|
||||
Value._type = OT_NULL;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Returns the string value of the key the iterator is on if possible
|
||||
///
|
||||
/// \return String or NULL
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const SQChar* getName() { return sq_objtostring(&Key); }
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Gets the Squirrel object for the key the iterator is on
|
||||
///
|
||||
/// \return HSQOBJECT representing a key
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
HSQOBJECT getKey() { return Key; }
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Gets the Squirrel object for the value the iterator is on
|
||||
///
|
||||
/// \return HSQOBJECT representing a value
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
HSQOBJECT getValue() { return Value; }
|
||||
private:
|
||||
|
||||
HSQOBJECT Key;
|
||||
HSQOBJECT Value;
|
||||
SQInteger Index;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Used to go through all the slots in an Object (same limitations as sq_next)
|
||||
///
|
||||
/// \param iter An iterator being used for going through the slots
|
||||
///
|
||||
/// \return Whether there is a next slot
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool Next(iterator& iter) const
|
||||
{
|
||||
sq_pushobject(vm,obj);
|
||||
sq_pushinteger(vm,iter.Index);
|
||||
if(SQ_SUCCEEDED(sq_next(vm,-2)))
|
||||
{
|
||||
sq_getstackobj(vm,-1,&iter.Value);
|
||||
sq_getstackobj(vm,-2,&iter.Key);
|
||||
sq_getinteger(vm,-3,&iter.Index);
|
||||
sq_pop(vm,4);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
sq_pop(vm,2);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @cond DEV
|
||||
|
||||
// Bind a function and it's associated Squirrel closure to the object
|
||||
inline void BindFunc(const SQChar* name, void* method, size_t methodSize, SQFUNCTION func, bool staticVar = false) {
|
||||
sq_pushobject(vm, GetObject());
|
||||
sq_pushstring(vm, name, -1);
|
||||
|
||||
SQUserPointer methodPtr = sq_newuserdata(vm, static_cast<SQUnsignedInteger>(methodSize));
|
||||
memcpy(methodPtr, method, methodSize);
|
||||
|
||||
sq_newclosure(vm, func, 1);
|
||||
sq_newslot(vm, -3, staticVar);
|
||||
sq_pop(vm,1); // pop table
|
||||
}
|
||||
|
||||
inline void BindFunc(const SQInteger index, void* method, size_t methodSize, SQFUNCTION func, bool staticVar = false) {
|
||||
sq_pushobject(vm, GetObject());
|
||||
sq_pushinteger(vm, index);
|
||||
|
||||
SQUserPointer methodPtr = sq_newuserdata(vm, static_cast<SQUnsignedInteger>(methodSize));
|
||||
memcpy(methodPtr, method, methodSize);
|
||||
|
||||
sq_newclosure(vm, func, 1);
|
||||
sq_newslot(vm, -3, staticVar);
|
||||
sq_pop(vm,1); // pop table
|
||||
}
|
||||
|
||||
|
||||
// Bind a function and it's associated Squirrel closure to the object
|
||||
inline void BindOverload(const SQChar* name, void* method, size_t methodSize, SQFUNCTION func, SQFUNCTION overload, int argCount, bool staticVar = false) {
|
||||
string overloadName = SqOverloadName::Get(name, argCount);
|
||||
|
||||
sq_pushobject(vm, GetObject());
|
||||
|
||||
// Bind overload handler
|
||||
sq_pushstring(vm, name, -1);
|
||||
sq_pushstring(vm, name, -1); // function name is passed as a free variable
|
||||
sq_newclosure(vm, overload, 1);
|
||||
sq_newslot(vm, -3, staticVar);
|
||||
|
||||
// Bind overloaded function
|
||||
sq_pushstring(vm, overloadName.c_str(), -1);
|
||||
SQUserPointer methodPtr = sq_newuserdata(vm, static_cast<SQUnsignedInteger>(methodSize));
|
||||
memcpy(methodPtr, method, methodSize);
|
||||
sq_newclosure(vm, func, 1);
|
||||
sq_newslot(vm, -3, staticVar);
|
||||
|
||||
sq_pop(vm,1); // pop table
|
||||
}
|
||||
|
||||
// Set the value of a variable on the object. Changes to values set this way are not reciprocated
|
||||
template<class V>
|
||||
inline void BindValue(const SQChar* name, const V& val, bool staticVar = false) {
|
||||
sq_pushobject(vm, GetObject());
|
||||
sq_pushstring(vm, name, -1);
|
||||
PushVar(vm, val);
|
||||
sq_newslot(vm, -3, staticVar);
|
||||
sq_pop(vm,1); // pop table
|
||||
}
|
||||
template<class V>
|
||||
inline void BindValue(const SQInteger index, const V& val, bool staticVar = false) {
|
||||
sq_pushobject(vm, GetObject());
|
||||
sq_pushinteger(vm, index);
|
||||
PushVar(vm, val);
|
||||
sq_newslot(vm, -3, staticVar);
|
||||
sq_pop(vm,1); // pop table
|
||||
}
|
||||
|
||||
// Set the value of an instance on the object. Changes to values set this way are reciprocated back to the source instance
|
||||
template<class V>
|
||||
inline void BindInstance(const SQChar* name, V* val, bool staticVar = false) {
|
||||
sq_pushobject(vm, GetObject());
|
||||
sq_pushstring(vm, name, -1);
|
||||
PushVar(vm, val);
|
||||
sq_newslot(vm, -3, staticVar);
|
||||
sq_pop(vm,1); // pop table
|
||||
}
|
||||
template<class V>
|
||||
inline void BindInstance(const SQInteger index, V* val, bool staticVar = false) {
|
||||
sq_pushobject(vm, GetObject());
|
||||
sq_pushinteger(vm, index);
|
||||
PushVar(vm, val);
|
||||
sq_newslot(vm, -3, staticVar);
|
||||
sq_pop(vm,1); // pop table
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
/// @cond DEV
|
||||
template<>
|
||||
inline void Object::BindValue<int>(const SQChar* name, const int & val, bool staticVar /* = false */) {
|
||||
sq_pushobject(vm, GetObject());
|
||||
sq_pushstring(vm, name, -1);
|
||||
PushVar<int>(vm, val);
|
||||
sq_newslot(vm, -3, staticVar);
|
||||
sq_pop(vm,1); // pop table
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Used to get and push Object instances to and from the stack as references (Object is always a reference)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<>
|
||||
struct Var<Object> {
|
||||
|
||||
Object value; ///< The actual value of get operations
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Attempts to get the value off the stack at idx as an Object
|
||||
///
|
||||
/// \param vm Target VM
|
||||
/// \param idx Index trying to be read
|
||||
///
|
||||
/// \remarks
|
||||
/// This function MUST have its Error handled if it occurred.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Var(HSQUIRRELVM vm, SQInteger idx) {
|
||||
HSQOBJECT sqValue;
|
||||
sq_getstackobj(vm, idx, &sqValue);
|
||||
value = Object(sqValue, vm);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Called by Sqrat::PushVar to put an Object on the stack
|
||||
///
|
||||
/// \param vm Target VM
|
||||
/// \param value Value to push on to the VM's stack
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static void push(HSQUIRRELVM vm, const Object& value) {
|
||||
sq_pushobject(vm, value.GetObject());
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Used to get and push Object instances to and from the stack as references (Object is always a reference)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<>
|
||||
struct Var<Object&> : Var<Object> {Var(HSQUIRRELVM vm, SQInteger idx) : Var<Object>(vm, idx) {}};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Used to get and push Object instances to and from the stack as references (Object is always a reference)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<>
|
||||
struct Var<const Object&> : Var<Object> {Var(HSQUIRRELVM vm, SQInteger idx) : Var<Object>(vm, idx) {}};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
1175
include/sqrat/sqratOverloadMethods.h
Normal file
1175
include/sqrat/sqratOverloadMethods.h
Normal file
File diff suppressed because it is too large
Load Diff
243
include/sqrat/sqratScript.h
Normal file
243
include/sqrat/sqratScript.h
Normal file
@ -0,0 +1,243 @@
|
||||
//
|
||||
// SqratScript: Script Compilation and Execution
|
||||
//
|
||||
|
||||
//
|
||||
// Copyright (c) 2009 Brandon Jones
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
|
||||
#if !defined(_SCRAT_SCRIPT_H_)
|
||||
#define _SCRAT_SCRIPT_H_
|
||||
|
||||
#include <squirrel.h>
|
||||
#include <sqstdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sqratObject.h"
|
||||
|
||||
namespace Sqrat {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Helper class for managing Squirrel scripts
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class Script : public Object {
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Default constructor
|
||||
///
|
||||
/// \param v VM that the Script will be associated with
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Script(HSQUIRRELVM v = DefaultVM::Get()) : Object(v, true) {
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Sets up the Script using a string containing a Squirrel script
|
||||
///
|
||||
/// \param script String containing a file path to a Squirrel script
|
||||
/// \param name Optional string containing the script's name (for errors)
|
||||
///
|
||||
/// \remarks
|
||||
/// This function MUST have its Error handled if it occurred.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void CompileString(const string& script, const string& name = _SC("")) {
|
||||
if(!sq_isnull(obj)) {
|
||||
sq_release(vm, &obj);
|
||||
sq_resetobject(&obj);
|
||||
}
|
||||
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
if(SQ_FAILED(sq_compilebuffer(vm, script.c_str(), static_cast<SQInteger>(script.size() /** sizeof(SQChar)*/), name.c_str(), true))) {
|
||||
SQTHROW(vm, LastErrorString(vm));
|
||||
return;
|
||||
}
|
||||
#else
|
||||
sq_compilebuffer(vm, script.c_str(), static_cast<SQInteger>(script.size() /** sizeof(SQChar)*/), name.c_str(), true);
|
||||
#endif
|
||||
sq_getstackobj(vm,-1,&obj);
|
||||
sq_addref(vm, &obj);
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Sets up the Script using a string containing a Squirrel script
|
||||
///
|
||||
/// \param script String containing a file path to a Squirrel script
|
||||
/// \param errMsg String that is filled with any errors that may occur
|
||||
/// \param name Optional string containing the script's name (for errors)
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool CompileString(const string& script, string& errMsg, const string& name = _SC("")) {
|
||||
if(!sq_isnull(obj)) {
|
||||
sq_release(vm, &obj);
|
||||
sq_resetobject(&obj);
|
||||
}
|
||||
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
if(SQ_FAILED(sq_compilebuffer(vm, script.c_str(), static_cast<SQInteger>(script.size() /** sizeof(SQChar)*/), name.c_str(), true))) {
|
||||
errMsg = LastErrorString(vm);
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
sq_compilebuffer(vm, script.c_str(), static_cast<SQInteger>(script.size() /** sizeof(SQChar)*/), name.c_str(), true);
|
||||
#endif
|
||||
sq_getstackobj(vm,-1,&obj);
|
||||
sq_addref(vm, &obj);
|
||||
sq_pop(vm, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Sets up the Script using a file containing a Squirrel script
|
||||
///
|
||||
/// \param path File path containing a Squirrel script
|
||||
///
|
||||
/// \remarks
|
||||
/// This function MUST have its Error handled if it occurred.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void CompileFile(const string& path) {
|
||||
if(!sq_isnull(obj)) {
|
||||
sq_release(vm, &obj);
|
||||
sq_resetobject(&obj);
|
||||
}
|
||||
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
if(SQ_FAILED(sqstd_loadfile(vm, path.c_str(), true))) {
|
||||
SQTHROW(vm, LastErrorString(vm));
|
||||
return;
|
||||
}
|
||||
#else
|
||||
sqstd_loadfile(vm, path.c_str(), true);
|
||||
#endif
|
||||
sq_getstackobj(vm,-1,&obj);
|
||||
sq_addref(vm, &obj);
|
||||
sq_pop(vm, 1);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Sets up the Script using a file containing a Squirrel script
|
||||
///
|
||||
/// \param path File path containing a Squirrel script
|
||||
/// \param errMsg String that is filled with any errors that may occur
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool CompileFile(const string& path, string& errMsg) {
|
||||
if(!sq_isnull(obj)) {
|
||||
sq_release(vm, &obj);
|
||||
sq_resetobject(&obj);
|
||||
}
|
||||
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
if(SQ_FAILED(sqstd_loadfile(vm, path.c_str(), true))) {
|
||||
errMsg = LastErrorString(vm);
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
sqstd_loadfile(vm, path.c_str(), true);
|
||||
#endif
|
||||
sq_getstackobj(vm,-1,&obj);
|
||||
sq_addref(vm, &obj);
|
||||
sq_pop(vm, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Runs the script
|
||||
///
|
||||
/// \remarks
|
||||
/// This function MUST have its Error handled if it occurred.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void Run() {
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
if(!sq_isnull(obj)) {
|
||||
SQRESULT result;
|
||||
SQInteger top = sq_gettop(vm);
|
||||
sq_pushobject(vm, obj);
|
||||
sq_pushroottable(vm);
|
||||
result = sq_call(vm, 1, false, true);
|
||||
sq_settop(vm, top);
|
||||
if(SQ_FAILED(result)) {
|
||||
SQTHROW(vm, LastErrorString(vm));
|
||||
return;
|
||||
}
|
||||
}
|
||||
#else
|
||||
SQInteger top = sq_gettop(vm);
|
||||
sq_pushobject(vm, obj);
|
||||
sq_pushroottable(vm);
|
||||
sq_call(vm, 1, false, true);
|
||||
sq_settop(vm, top);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Runs the script
|
||||
///
|
||||
/// \param errMsg String that is filled with any errors that may occur
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool Run(string& errMsg) {
|
||||
if(!sq_isnull(obj)) {
|
||||
SQRESULT result;
|
||||
SQInteger top = sq_gettop(vm);
|
||||
sq_pushobject(vm, obj);
|
||||
sq_pushroottable(vm);
|
||||
result = sq_call(vm, 1, false, true);
|
||||
sq_settop(vm, top);
|
||||
if(SQ_FAILED(result)) {
|
||||
errMsg = LastErrorString(vm);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Writes the byte code of the Script to a file
|
||||
///
|
||||
/// \param path File path to write to
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void WriteCompiledFile(const string& path) {
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
if(!sq_isnull(obj)) {
|
||||
sq_pushobject(vm, obj);
|
||||
sqstd_writeclosuretofile(vm, path.c_str());
|
||||
}
|
||||
#else
|
||||
sq_pushobject(vm, obj);
|
||||
sqstd_writeclosuretofile(vm, path.c_str());
|
||||
#endif
|
||||
sq_pop(vm, 1); // needed?
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
541
include/sqrat/sqratTable.h
Normal file
541
include/sqrat/sqratTable.h
Normal file
@ -0,0 +1,541 @@
|
||||
//
|
||||
// SqratTable: Table Binding
|
||||
//
|
||||
|
||||
//
|
||||
// Copyright (c) 2009 Brandon Jones
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
|
||||
#if !defined(_SCRAT_TABLE_H_)
|
||||
#define _SCRAT_TABLE_H_
|
||||
|
||||
#include <squirrel.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sqratObject.h"
|
||||
#include "sqratFunction.h"
|
||||
#include "sqratGlobalMethods.h"
|
||||
|
||||
namespace Sqrat {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// The base class for Table that implements almost all of its functionality
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class TableBase : public Object {
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Default constructor (null)
|
||||
///
|
||||
/// \param v VM that the table will exist in
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
TableBase(HSQUIRRELVM v = DefaultVM::Get()) : Object(v, true) {
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Construct the TableBase from an Object that already exists
|
||||
///
|
||||
/// \param obj An Object that should already represent a Squirrel table
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
TableBase(const Object& obj) : Object(obj) {
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Construct the TableBase from a HSQOBJECT and HSQUIRRELVM that already exist
|
||||
///
|
||||
/// \param o Squirrel object that should already represent a Squirrel table
|
||||
/// \param v Squirrel VM that contains the Squirrel object given
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
TableBase(HSQOBJECT o, HSQUIRRELVM v = DefaultVM::Get()) : Object(o, v) {
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binds a Table or Class to the Table (can be used to facilitate namespaces)
|
||||
///
|
||||
/// \param name The key in the table being assigned a Table or Class
|
||||
/// \param obj Table or Class that is being placed in the table
|
||||
///
|
||||
/// \remarks
|
||||
/// Bind cannot be called "inline" like other functions because it introduces order-of-initialization bugs.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void Bind(const SQChar* name, Object& obj) {
|
||||
sq_pushobject(vm, GetObject());
|
||||
sq_pushstring(vm, name, -1);
|
||||
sq_pushobject(vm, obj.GetObject());
|
||||
sq_newslot(vm, -3, false);
|
||||
sq_pop(vm,1); // pop table
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binds a raw Squirrel closure to the Table
|
||||
///
|
||||
/// \param name The key in the table being assigned a function
|
||||
/// \param func Squirrel function that is being placed in the Table
|
||||
///
|
||||
/// \return The Table itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
TableBase& SquirrelFunc(const SQChar* name, SQFUNCTION func) {
|
||||
sq_pushobject(vm, GetObject());
|
||||
sq_pushstring(vm, name, -1);
|
||||
sq_newclosure(vm, func, 0);
|
||||
sq_newslot(vm, -3, false);
|
||||
sq_pop(vm,1); // pop table
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Sets a key in the Table to a specific value
|
||||
///
|
||||
/// \param name The key in the table being assigned a value
|
||||
/// \param val Value that is being placed in the Table
|
||||
///
|
||||
/// \tparam V Type of value (usually doesnt need to be defined explicitly)
|
||||
///
|
||||
/// \return The Table itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<class V>
|
||||
TableBase& SetValue(const SQChar* name, const V& val) {
|
||||
BindValue<V>(name, val, false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Sets an index in the Table to a specific value
|
||||
///
|
||||
/// \param index The index in the table being assigned a value
|
||||
/// \param val Value that is being placed in the Table
|
||||
///
|
||||
/// \tparam V Type of value (usually doesnt need to be defined explicitly)
|
||||
///
|
||||
/// \return The Table itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<class V>
|
||||
TableBase& SetValue(const SQInteger index, const V& val) {
|
||||
BindValue<V>(index, val, false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Sets a key in the Table to a specific instance (like a reference)
|
||||
///
|
||||
/// \param name The key in the table being assigned a value
|
||||
/// \param val Pointer to the instance that is being placed in the Table
|
||||
///
|
||||
/// \tparam V Type of instance (usually doesnt need to be defined explicitly)
|
||||
///
|
||||
/// \return The Table itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<class V>
|
||||
TableBase& SetInstance(const SQChar* name, V* val) {
|
||||
BindInstance<V>(name, val, false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Sets an index in the Table to a specific instance (like a reference)
|
||||
///
|
||||
/// \param index The index in the table being assigned a value
|
||||
/// \param val Pointer to the instance that is being placed in the Table
|
||||
///
|
||||
/// \tparam V Type of instance (usually doesnt need to be defined explicitly)
|
||||
///
|
||||
/// \return The Table itself so the call can be chained
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<class V>
|
||||
TableBase& SetInstance(const SQInteger index, V* val) {
|
||||
BindInstance<V>(index, val, false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Sets a key in the Table to a specific function
|
||||
///
|
||||
/// \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& Func(const SQChar* name, F method) {
|
||||
BindFunc(name, &method, sizeof(method), SqGlobalFunc(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
|
||||
///
|
||||
/// \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
|
||||
///
|
||||
/// \remarks
|
||||
/// Overloading in Sqrat does not work for functions with the same amount of arguments (just like in Squirrel).
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<class F>
|
||||
TableBase& Overload(const SQChar* name, F method) {
|
||||
BindOverload(name, &method, sizeof(method), SqGlobalOverloadedFunc(method), SqOverloadFunc(method), SqGetArgCount(method));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Checks if the given key exists in the table
|
||||
///
|
||||
/// \param name Key to check
|
||||
///
|
||||
/// \return True on success, otherwise false
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool HasKey(const SQChar* name)
|
||||
{
|
||||
sq_pushobject(vm, obj);
|
||||
sq_pushstring(vm, name, -1);
|
||||
if (SQ_FAILED(sq_get(vm, -2))) {
|
||||
sq_pop(vm, 1);
|
||||
return false;
|
||||
}
|
||||
sq_pop(vm, 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Returns the value at a given key
|
||||
///
|
||||
/// \param name Key of the element
|
||||
///
|
||||
/// \tparam T Type of value (fails if value is not of this type)
|
||||
///
|
||||
/// \return SharedPtr containing the value (or null if failed)
|
||||
///
|
||||
/// \remarks
|
||||
/// This function MUST have its Error handled if it occurred.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
SharedPtr<T> GetValue(const SQChar* name)
|
||||
{
|
||||
sq_pushobject(vm, obj);
|
||||
sq_pushstring(vm, name, -1);
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
if (SQ_FAILED(sq_get(vm, -2))) {
|
||||
sq_pop(vm, 1);
|
||||
SQTHROW(vm, _SC("illegal index"));
|
||||
return SharedPtr<T>();
|
||||
}
|
||||
#else
|
||||
sq_get(vm, -2);
|
||||
#endif
|
||||
SQTRY()
|
||||
Var<SharedPtr<T> > entry(vm, -1);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
sq_pop(vm, 2);
|
||||
return SharedPtr<T>();
|
||||
}
|
||||
sq_pop(vm, 2);
|
||||
return entry.value;
|
||||
SQCATCH(vm) {
|
||||
#if defined (SCRAT_USE_EXCEPTIONS)
|
||||
SQUNUSED(e); // avoid "unreferenced local variable" warning
|
||||
#endif
|
||||
sq_pop(vm, 2);
|
||||
SQRETHROW(vm);
|
||||
}
|
||||
return SharedPtr<T>(); // avoid "not all control paths return a value" warning
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Returns the value at a given index
|
||||
///
|
||||
/// \param index Index of the element
|
||||
///
|
||||
/// \tparam T Type of value (fails if value is not of this type)
|
||||
///
|
||||
/// \return SharedPtr containing the value (or null if failed)
|
||||
///
|
||||
/// \remarks
|
||||
/// This function MUST have its Error handled if it occurred.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
SharedPtr<T> GetValue(int index)
|
||||
{
|
||||
sq_pushobject(vm, obj);
|
||||
sq_pushinteger(vm, index);
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
if (SQ_FAILED(sq_get(vm, -2))) {
|
||||
sq_pop(vm, 1);
|
||||
SQTHROW(vm, _SC("illegal index"));
|
||||
return SharedPtr<T>();
|
||||
}
|
||||
#else
|
||||
sq_get(vm, -2);
|
||||
#endif
|
||||
SQTRY()
|
||||
Var<SharedPtr<T> > entry(vm, -1);
|
||||
SQCATCH_NOEXCEPT(vm) {
|
||||
sq_pop(vm, 2);
|
||||
return SharedPtr<T>();
|
||||
}
|
||||
sq_pop(vm, 2);
|
||||
return entry.value;
|
||||
SQCATCH(vm) {
|
||||
#if defined (SCRAT_USE_EXCEPTIONS)
|
||||
SQUNUSED(e); // avoid "unreferenced local variable" warning
|
||||
#endif
|
||||
sq_pop(vm, 2);
|
||||
SQRETHROW(vm);
|
||||
}
|
||||
return SharedPtr<T>(); // avoid "not all control paths return a value" warning
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Gets a Function from a key in the Table
|
||||
///
|
||||
/// \param name The key in the table that contains the Function
|
||||
///
|
||||
/// \return Function found in the Table (null if failed)
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Function GetFunction(const SQChar* name) {
|
||||
HSQOBJECT funcObj;
|
||||
sq_pushobject(vm, GetObject());
|
||||
sq_pushstring(vm, name, -1);
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
if(SQ_FAILED(sq_get(vm, -2))) {
|
||||
sq_pop(vm, 1);
|
||||
return Function();
|
||||
}
|
||||
SQObjectType value_type = sq_gettype(vm, -1);
|
||||
if (value_type != OT_CLOSURE && value_type != OT_NATIVECLOSURE) {
|
||||
sq_pop(vm, 2);
|
||||
return Function();
|
||||
}
|
||||
#else
|
||||
sq_get(vm, -2);
|
||||
#endif
|
||||
sq_getstackobj(vm, -1, &funcObj);
|
||||
Function ret(vm, GetObject(), funcObj); // must addref before the pop!
|
||||
sq_pop(vm, 2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Gets a Function from an index in the Table
|
||||
///
|
||||
/// \param index The index in the table that contains the Function
|
||||
///
|
||||
/// \return Function found in the Table (null if failed)
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Function GetFunction(const SQInteger index) {
|
||||
HSQOBJECT funcObj;
|
||||
sq_pushobject(vm, GetObject());
|
||||
sq_pushinteger(vm, index);
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
if(SQ_FAILED(sq_get(vm, -2))) {
|
||||
sq_pop(vm, 1);
|
||||
return Function();
|
||||
}
|
||||
SQObjectType value_type = sq_gettype(vm, -1);
|
||||
if (value_type != OT_CLOSURE && value_type != OT_NATIVECLOSURE) {
|
||||
sq_pop(vm, 2);
|
||||
return Function();
|
||||
}
|
||||
#else
|
||||
sq_get(vm, -2);
|
||||
#endif
|
||||
sq_getstackobj(vm, -1, &funcObj);
|
||||
Function ret(vm, GetObject(), funcObj); // must addref before the pop!
|
||||
sq_pop(vm, 2);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Represents a table in Squirrel
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class Table : public TableBase {
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Default constructor (null)
|
||||
///
|
||||
/// \remarks
|
||||
/// The Table is invalid until it is given a VM to exist in.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Table() {
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructs a Table
|
||||
///
|
||||
/// \param v VM to create the Table in
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Table(HSQUIRRELVM v) : TableBase(v) {
|
||||
sq_newtable(vm);
|
||||
sq_getstackobj(vm,-1,&obj);
|
||||
sq_addref(vm, &obj);
|
||||
sq_pop(vm,1);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Construct the Table from an Object that already exists
|
||||
///
|
||||
/// \param obj An Object that should already represent a Squirrel table
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Table(const Object& obj) : TableBase(obj) {
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Construct the Table from a HSQOBJECT and HSQUIRRELVM that already exist
|
||||
///
|
||||
/// \param o Squirrel object that should already represent a Squirrel table
|
||||
/// \param v Squirrel VM that contains the Squirrel object given
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Table(HSQOBJECT o, HSQUIRRELVM v = DefaultVM::Get()) : TableBase(o, v) {
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Table that is a reference to the Squirrel root table for a given VM
|
||||
/// The Squirrel root table is usually where all globals are stored by the Squirrel language.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class RootTable : public TableBase {
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructs a RootTable object to represent the given VM's root table
|
||||
///
|
||||
/// \param v VM to get the RootTable for
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
RootTable(HSQUIRRELVM v = DefaultVM::Get()) : TableBase(v) {
|
||||
sq_pushroottable(vm);
|
||||
sq_getstackobj(vm,-1,&obj);
|
||||
sq_addref(vm, &obj);
|
||||
sq_pop(v,1); // pop root table
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Table that is a reference to the Squirrel registry table for a given VM
|
||||
/// The Squirrel registry table is where non-Squirrel code can store Squirrel objects without worrying about Squirrel code messing with them.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class RegistryTable : public TableBase {
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructs a RegistryTable object to represent the given VM's registry table
|
||||
///
|
||||
/// \param v VM to get the RegistryTable for
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
RegistryTable(HSQUIRRELVM v = DefaultVM::Get()) : TableBase(v) {
|
||||
sq_pushregistrytable(v);
|
||||
sq_getstackobj(vm,-1,&obj);
|
||||
sq_addref(vm, &obj);
|
||||
sq_pop(v,1); // pop the registry table
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Used to get and push Table instances to and from the stack as references (tables are always references in Squirrel)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<>
|
||||
struct Var<Table> {
|
||||
|
||||
Table value; ///< The actual value of get operations
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Attempts to get the value off the stack at idx as a Table
|
||||
///
|
||||
/// \param vm Target VM
|
||||
/// \param idx Index trying to be read
|
||||
///
|
||||
/// \remarks
|
||||
/// This function MUST have its Error handled if it occurred.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Var(HSQUIRRELVM vm, SQInteger idx) {
|
||||
HSQOBJECT obj;
|
||||
sq_resetobject(&obj);
|
||||
sq_getstackobj(vm,idx,&obj);
|
||||
value = Table(obj, vm);
|
||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||
SQObjectType value_type = sq_gettype(vm, idx);
|
||||
if (value_type != OT_TABLE) {
|
||||
SQTHROW(vm, FormatTypeError(vm, idx, _SC("table")));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Called by Sqrat::PushVar to put an Table reference on the stack
|
||||
///
|
||||
/// \param vm Target VM
|
||||
/// \param value Value to push on to the VM's stack
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static void push(HSQUIRRELVM vm, const Table& value) {
|
||||
HSQOBJECT obj;
|
||||
sq_resetobject(&obj);
|
||||
obj = value.GetObject();
|
||||
sq_pushobject(vm,obj);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Used to get and push Table instances to and from the stack as references (tables are always references in Squirrel)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<>
|
||||
struct Var<Table&> : Var<Table> {Var(HSQUIRRELVM vm, SQInteger idx) : Var<Table>(vm, idx) {}};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Used to get and push Table instances to and from the stack as references (tables are always references in Squirrel)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template<>
|
||||
struct Var<const Table&> : Var<Table> {Var(HSQUIRRELVM vm, SQInteger idx) : Var<Table>(vm, idx) {}};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
43
include/sqrat/sqratThread.h
Normal file
43
include/sqrat/sqratThread.h
Normal file
@ -0,0 +1,43 @@
|
||||
//
|
||||
// SqratThread: Sqrat threading module
|
||||
//
|
||||
|
||||
//
|
||||
// Copyright (c) 2009 Brandon Jones
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
|
||||
#if !defined(_SQRAT_THREAD_H_)
|
||||
#define _SQRAT_THREAD_H_
|
||||
|
||||
#include "sqmodule.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
__declspec(dllexport) SQRESULT sqmodule_load(HSQUIRRELVM v, HSQAPI api);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*_SQRAT_THREAD_H_*/
|
1121
include/sqrat/sqratTypes.h
Normal file
1121
include/sqrat/sqratTypes.h
Normal file
File diff suppressed because it is too large
Load Diff
1208
include/sqrat/sqratUtil.h
Normal file
1208
include/sqrat/sqratUtil.h
Normal file
File diff suppressed because it is too large
Load Diff
348
include/sqrat/sqratVM.h
Normal file
348
include/sqrat/sqratVM.h
Normal file
@ -0,0 +1,348 @@
|
||||
//
|
||||
// wrapper for the Squirrel VM under Sqrat
|
||||
//
|
||||
|
||||
//
|
||||
// Copyright (c) 2011 Alston Chen
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
|
||||
#if !defined(_SCRAT_VM_H_)
|
||||
#define _SCRAT_VM_H_
|
||||
|
||||
#include <squirrel.h>
|
||||
#include <sqrat.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sqstdio.h>
|
||||
#include <sqstdblob.h>
|
||||
#include <sqstdmath.h>
|
||||
#include <sqstdsystem.h>
|
||||
#include <sqstdstring.h>
|
||||
|
||||
namespace Sqrat
|
||||
{
|
||||
|
||||
#ifdef SQUNICODE
|
||||
#define scvprintf vwprintf
|
||||
#else
|
||||
#define scvprintf vprintf
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Helper class that wraps a Squirrel virtual machine in a C++ API
|
||||
///
|
||||
/// \remarks
|
||||
/// This class is not currently thread-safe for the case of different VMs running in different threads (all others are)
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class SqratVM
|
||||
{
|
||||
private:
|
||||
|
||||
HSQUIRRELVM m_vm;
|
||||
Sqrat::RootTable* m_rootTable;
|
||||
Sqrat::Script* m_script;
|
||||
Sqrat::string m_lastErrorMsg;
|
||||
|
||||
static void s_addVM(HSQUIRRELVM vm, SqratVM* sqratvm)
|
||||
{
|
||||
// TODO for user: use mutex to lock ms_sqratVMs if necessary for your uses
|
||||
ms_sqratVMs().insert(std::make_pair(vm, sqratvm));
|
||||
}
|
||||
|
||||
static void s_deleteVM(HSQUIRRELVM vm)
|
||||
{
|
||||
// TODO for user: use mutex to lock ms_sqratVMs if necessary for your uses
|
||||
ms_sqratVMs().erase(vm);
|
||||
}
|
||||
|
||||
static SqratVM* s_getVM(HSQUIRRELVM vm)
|
||||
{
|
||||
// TODO for user: use mutex to lock ms_sqratVMs if necessary for your uses
|
||||
return ms_sqratVMs()[vm];
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static SQRAT_API unordered_map<HSQUIRRELVM, SqratVM*>::type& ms_sqratVMs();
|
||||
|
||||
static void printFunc(HSQUIRRELVM /*v*/, const SQChar *s, ...)
|
||||
{
|
||||
va_list vl;
|
||||
va_start(vl, s);
|
||||
scvprintf(s, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
static SQInteger runtimeErrorHandler(HSQUIRRELVM v)
|
||||
{
|
||||
const SQChar *sErr = 0;
|
||||
if(sq_gettop(v) >= 1)
|
||||
{
|
||||
Sqrat::string& errStr = s_getVM(v)->m_lastErrorMsg;
|
||||
if(SQ_SUCCEEDED(sq_getstring(v, 2, &sErr)))
|
||||
{
|
||||
errStr = sErr;
|
||||
}
|
||||
else
|
||||
{
|
||||
errStr = _SC("an unknown runtime error has occured");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void compilerErrorHandler(HSQUIRRELVM v,
|
||||
const SQChar* desc,
|
||||
const SQChar* source,
|
||||
SQInteger line,
|
||||
SQInteger column)
|
||||
{
|
||||
SQChar buf[512];
|
||||
scsprintf(buf, 512, _SC("%s:%d:%d: %s"), source, (int) line, (int) column, desc);
|
||||
buf[sizeof(buf) - 1] = 0;
|
||||
s_getVM(v)->m_lastErrorMsg = buf;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Enumeration representing the different types of errors that may occur within a SqratVM
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
enum ERROR_STATE
|
||||
{
|
||||
SQRAT_NO_ERROR, ///< For when no error has occurred
|
||||
SQRAT_COMPILE_ERROR, ///< For when a script compiling error has occurred
|
||||
SQRAT_RUNTIME_ERROR ///< For when a script running error has occurred
|
||||
};
|
||||
|
||||
static const unsigned char LIB_IO = 0x01; ///< Input/Output library
|
||||
static const unsigned char LIB_BLOB = 0x02; ///< Blob library
|
||||
static const unsigned char LIB_MATH = 0x04; ///< Math library
|
||||
static const unsigned char LIB_SYST = 0x08; ///< System library
|
||||
static const unsigned char LIB_STR = 0x10; ///< String library
|
||||
static const unsigned char LIB_ALL = LIB_IO | LIB_BLOB | LIB_MATH | LIB_SYST | LIB_STR; ///< All libraries
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Default constructor
|
||||
///
|
||||
/// \param initialStackSize Initial size of the execution stack (if the stack is too small it will automatically grow)
|
||||
/// \param libsToLoad Specifies what standard Squirrel libraries should be loaded
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
SqratVM(int initialStackSize = 1024, unsigned char libsToLoad = LIB_ALL): m_vm(sq_open(initialStackSize))
|
||||
, m_rootTable(new Sqrat::RootTable(m_vm))
|
||||
, m_script(new Sqrat::Script(m_vm))
|
||||
, m_lastErrorMsg()
|
||||
{
|
||||
s_addVM(m_vm, this);
|
||||
//register std libs
|
||||
sq_pushroottable(m_vm);
|
||||
if (libsToLoad & LIB_IO)
|
||||
sqstd_register_iolib(m_vm);
|
||||
if (libsToLoad & LIB_BLOB)
|
||||
sqstd_register_bloblib(m_vm);
|
||||
if (libsToLoad & LIB_MATH)
|
||||
sqstd_register_mathlib(m_vm);
|
||||
if (libsToLoad & LIB_SYST)
|
||||
sqstd_register_systemlib(m_vm);
|
||||
if (libsToLoad & LIB_STR)
|
||||
sqstd_register_stringlib(m_vm);
|
||||
sq_pop(m_vm, 1);
|
||||
SetPrintFunc(printFunc, printFunc);
|
||||
SetErrorHandler(runtimeErrorHandler, compilerErrorHandler);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Destructor
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
~SqratVM()
|
||||
{
|
||||
s_deleteVM(m_vm);
|
||||
delete m_script;
|
||||
delete m_rootTable;
|
||||
sq_close(m_vm);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Gets the underlying Squirrel VM
|
||||
///
|
||||
/// \return Underlying Squirrel VM
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
HSQUIRRELVM GetVM()
|
||||
{
|
||||
return m_vm;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Gets the root table for this VM
|
||||
///
|
||||
/// \return RootTable for the VM
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Sqrat::RootTable& GetRootTable()
|
||||
{
|
||||
return *m_rootTable;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Gets the associated Script for this VM
|
||||
///
|
||||
/// \return Script for the VM
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Sqrat::Script& GetScript()
|
||||
{
|
||||
return *m_script;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Gets the error message for the most recent Squirrel error with the VM
|
||||
///
|
||||
/// \return String containing a nice error message
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Sqrat::string GetLastErrorMsg()
|
||||
{
|
||||
return m_lastErrorMsg;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Overwrites the most recent Squirrel error for this VM
|
||||
///
|
||||
/// \param str A nice error message
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void SetLastErrorMsg(const Sqrat::string& str)
|
||||
{
|
||||
m_lastErrorMsg = str;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Sets the print function of the virtual machine (a default one is set in the constructor)
|
||||
///
|
||||
/// \param printFunc A pointer to the print func or NULL to disable the output
|
||||
/// \param errFunc A pointer to the error func or NULL to disable the output
|
||||
///
|
||||
/// \remarks
|
||||
/// The print function is used by the built-in Squirrel print function to output text.
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void SetPrintFunc(SQPRINTFUNCTION printFunc, SQPRINTFUNCTION errFunc)
|
||||
{
|
||||
sq_setprintfunc(m_vm, printFunc, errFunc);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Sets the Squirrel error handlers (both are set to defaults in the constructor)
|
||||
///
|
||||
/// \param runErr A pointer to the runtime error handler func
|
||||
/// \param comErr A pointer to the compile error handler func
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void SetErrorHandler(SQFUNCTION runErr, SQCOMPILERERROR comErr)
|
||||
{
|
||||
sq_newclosure(m_vm, runErr, 0);
|
||||
sq_seterrorhandler(m_vm);
|
||||
sq_setcompilererrorhandler(m_vm, comErr);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Runs a string containing a Squirrel script
|
||||
///
|
||||
/// \param str String containing a Squirrel script
|
||||
///
|
||||
/// \return An ERROR_STATE representing what happened
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ERROR_STATE DoString(const Sqrat::string& str)
|
||||
{
|
||||
Sqrat::string msg;
|
||||
m_lastErrorMsg.clear();
|
||||
if(!m_script->CompileString(str, msg))
|
||||
{
|
||||
if(m_lastErrorMsg.empty())
|
||||
{
|
||||
m_lastErrorMsg = msg;
|
||||
}
|
||||
return SQRAT_COMPILE_ERROR;
|
||||
}
|
||||
if(!m_script->Run(msg))
|
||||
{
|
||||
if(m_lastErrorMsg.empty())
|
||||
{
|
||||
m_lastErrorMsg = msg;
|
||||
}
|
||||
return SQRAT_RUNTIME_ERROR;
|
||||
}
|
||||
return SQRAT_NO_ERROR;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Runs a file containing a Squirrel script
|
||||
///
|
||||
/// \param file File path containing a Squirrel script
|
||||
///
|
||||
/// \return An ERROR_STATE representing what happened
|
||||
///
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ERROR_STATE DoFile(const Sqrat::string& file)
|
||||
{
|
||||
Sqrat::string msg;
|
||||
m_lastErrorMsg.clear();
|
||||
if(!m_script->CompileFile(file, msg))
|
||||
{
|
||||
if(m_lastErrorMsg.empty())
|
||||
{
|
||||
m_lastErrorMsg = msg;
|
||||
}
|
||||
return SQRAT_COMPILE_ERROR;
|
||||
}
|
||||
if(!m_script->Run(msg))
|
||||
{
|
||||
if(m_lastErrorMsg.empty())
|
||||
{
|
||||
m_lastErrorMsg = msg;
|
||||
}
|
||||
return SQRAT_RUNTIME_ERROR;
|
||||
}
|
||||
return SQRAT_NO_ERROR;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#if !defined(SCRAT_IMPORT)
|
||||
inline unordered_map<HSQUIRRELVM, SqratVM*>::type& SqratVM::ms_sqratVMs() {
|
||||
static unordered_map<HSQUIRRELVM, SqratVM*>::type ms;
|
||||
return ms;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
51
include/sqratimport.h
Normal file
51
include/sqratimport.h
Normal file
@ -0,0 +1,51 @@
|
||||
//
|
||||
// SqImport: Supports importing of squirrel modules
|
||||
//
|
||||
|
||||
//
|
||||
// Copyright (c) 2009 Brandon Jones
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
|
||||
#if !defined(_SQ_IMPORT_H_)
|
||||
#define _SQ_IMPORT_H_
|
||||
|
||||
#include <squirrel.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// To be documented...
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
SQUIRREL_API SQRESULT sqrat_import(HSQUIRRELVM v);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// To be documented...
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
SQUIRREL_API SQRESULT sqrat_register_importlib(HSQUIRRELVM v);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*_SQ_IMPORT_H_*/
|
Loading…
Reference in New Issue
Block a user