1
0
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:
Sandu Liviu Catalin 2015-11-01 10:06:54 +02:00
parent c3b811cfff
commit 08f7f396c9
24 changed files with 20311 additions and 0 deletions

20
external/Sqrat/License.txt vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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

View 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
View 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

File diff suppressed because it is too large Load Diff

View 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

View 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
View 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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

557
include/sqrat/sqratObject.h Normal file
View 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

File diff suppressed because it is too large Load Diff

243
include/sqrat/sqratScript.h Normal file
View 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
View 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

View 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

File diff suppressed because it is too large Load Diff

1208
include/sqrat/sqratUtil.h Normal file

File diff suppressed because it is too large Load Diff

348
include/sqrat/sqratVM.h Normal file
View 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
View 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_*/