1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-07-05 08:27:10 +02:00

Move Squirrel and Sqrat into the root level directory.

Create the initial CMake build scripts.
This commit is contained in:
Sandu Liviu Catalin
2020-03-21 21:39:01 +02:00
parent 7f9d6288b0
commit 44b1cb5d96
78 changed files with 231 additions and 0 deletions

View File

@ -1,73 +0,0 @@
//
// 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_
#ifdef SQMOD_PLUGIN_API
#include <SqAPI.h>
#else
#include <squirrelex.h>
#endif // SQMOD_PLUGIN_API
#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

@ -1,553 +0,0 @@
//
// 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_
#ifdef SQMOD_PLUGIN_API
#include <SqAPI.h>
#else
#include <squirrelex.h>
#endif // SQMOD_PLUGIN_API
#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 > using is_default_constructible = std::is_default_constructible<T>;
/// @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 <class... A>
static SQInteger iNew(HSQUIRRELVM vm) {
try {
SetInstance(vm, 1, ArgFwd<A...>{}.Call(vm, 2, [](HSQUIRRELVM /*vm*/, A... a) -> C * {
return new C(a...);
}));
} catch (const Exception& e) {
return sq_throwerror(vm, e.what());
} catch (...) {
return sq_throwerror(vm, _SC("unknown exception occured"));
}
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;
}
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// NoDestructor is the allocator to use for Class that can NOT be constructed, copied or destructed
///
/// \tparam C Type of class
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class C>
class NoDestructor {
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);
// Only delete our pair instance and leave the actual instance untouched
//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 <class... A>
static SQInteger iNew(HSQUIRRELVM vm) {
try {
SetInstance(vm, 1, ArgFwd<A...>{}.Call(vm, 2, [](HSQUIRRELVM /*vm*/, A... a) -> C * {
return new C(a...);
}));
} catch (const Exception& e) {
return sq_throwerror(vm, e.what());
} catch (...) {
return sq_throwerror(vm, _SC("unknown exception occured"));
}
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

View File

@ -1,691 +0,0 @@
//
// 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_
#ifdef SQMOD_PLUGIN_API
#include <SqAPI.h>
#else
#include <squirrelex.h>
#endif // SQMOD_PLUGIN_API
#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 an Object that already exists
///
/// \param obj An Object that should already represent a Squirrel array
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ArrayBase(Object&& obj) : Object(std::move(obj)) {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy constructor
///
/// \param sa ArrayBase to copy
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ArrayBase(const ArrayBase& sa) : Object(sa) {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Move constructor
///
/// \param sa ArrayBase to move
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ArrayBase(ArrayBase&& sa) : Object(std::move(sa)) {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 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) {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Assignment operator
///
/// \param sa ArrayBase to copy
///
/// \return The ArrayBase itself
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ArrayBase& operator=(const ArrayBase& sa) {
Object::operator = (sa);
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Assignment operator
///
/// \param sa ArrayBase to move
///
/// \return The ArrayBase itself
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ArrayBase& operator=(ArrayBase&& sa) {
Object::operator = (std::move(sa));
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 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, const SQChar* name = nullptr) {
sq_pushobject(vm, GetObject());
sq_pushinteger(vm, index);
sq_newclosure(vm, func, 0);
// Set the closure name (for debug purposes)
if (name) sq_setnativeclosurename(vm, -1, name);
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, const SQChar* name = nullptr) {
BindFunc(index, &method, sizeof(method), SqGlobalFunc(method), name);
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) const
{
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;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Appends values to the end of the Array
///
/// \param func Functor that is continuously called to push values on the stack
///
/// \tparam F Type of functor (usually doesnt need to be defined explicitly)
///
/// \return The Array itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class F>
ArrayBase& AppendFrom(F&& func) {
sq_pushobject(vm, GetObject());
while (func(vm))
{
sq_arrayappend(vm, -2);
}
sq_pop(vm,1); // pop array
return *this;
}
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 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 an Object that already exists
///
/// \param obj An Object that should already represent a Squirrel array
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Array(Object&& obj) : ArrayBase(std::move(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) {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy constructor
///
/// \param sa Array to copy
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Array(const Array& sa) : ArrayBase(sa) {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Move constructor
///
/// \param sa Array to move
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Array(Array&& sa) : ArrayBase(std::move(sa)) {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Assignment operator
///
/// \param sa Array to copy
///
/// \return The Array itself
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Array& operator=(const Array& sa) {
ArrayBase::operator = (sa);
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Assignment operator
///
/// \param sa Array to move
///
/// \return The Array itself
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Array& operator=(Array&& sa) {
ArrayBase::operator = (std::move(sa));
return *this;
}
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 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

View File

@ -1,984 +0,0 @@
//
// SqratClass: Class 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_CLASS_H_)
#define _SCRAT_CLASS_H_
#ifdef SQMOD_PLUGIN_API
#include <SqAPI.h>
#else
#include <squirrelex.h>
#endif // SQMOD_PLUGIN_API
#include <typeinfo>
#include "sqratObject.h"
#include "sqratClassType.h"
#include "sqratMemberMethods.h"
#include "sqratAllocator.h"
#include "sqratTypes.h"
namespace Sqrat
{
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Facilitates exposing a C++ class with no base class to Squirrel
///
/// \tparam C Class type to expose
/// \tparam A An allocator to use when instantiating and destroying class instances of this type in Squirrel
///
/// \remarks
/// DefaultAllocator is used if no allocator is specified. This should be sufficent for most classes,
/// but if specific behavior is desired, it can be overridden. If the class should not be instantiated from
/// Squirrel the NoConstructor allocator may be used. See NoCopy and CopyOnly too.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class C, class A = DefaultAllocator<C> >
class Class : public Object
{
private:
static SQInteger cleanup_hook(SQUserPointer ptr, SQInteger size) {
SQUNUSED(size);
ClassData<C>** ud = reinterpret_cast<ClassData<C>**>(ptr);
delete *ud;
return 0;
}
public:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Constructs the Class object
///
/// A Class object doesnt do anything on its own.
/// It must be told what methods and variables it contains.
/// This is done using Class methods such as Class::Func and Class::Var.
/// Then the Class must be exposed to Squirrel.
/// This is usually done by calling TableBase::Bind on a RootTable with the Class.
///
/// \param v Squirrel virtual machine to create the Class for
/// \param className A necessarily unique name for the class that can appear in error messages
/// \param createClass Should class type data be created? (almost always should be true - don't worry about it)
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Class(HSQUIRRELVM v, const string& className, bool createClass = true) : Object(v, false) {
if (createClass && !ClassType<C>::hasClassData(v)) {
sq_pushregistrytable(v);
sq_pushstring(v, "__classes", -1);
if (SQ_FAILED(sq_rawget(v, -2))) {
sq_newtable(v);
sq_pushstring(v, "__classes", -1);
sq_push(v, -2);
sq_rawset(v, -4);
}
sq_pushstring(v, className.c_str(), -1);
ClassData<C>** ud = reinterpret_cast<ClassData<C>**>(sq_newuserdata(v, sizeof(ClassData<C>*)));
*ud = new ClassData<C>;
sq_setreleasehook(v, -1, &cleanup_hook);
sq_rawset(v, -3);
sq_pop(v, 2);
ClassData<C>* cd = *ud;
if (ClassType<C>::getStaticClassData().Expired()) {
cd->staticData.Init(new StaticClassData<C, void>);
cd->staticData->copyFunc = &A::Copy;
cd->staticData->className = string(className);
cd->staticData->baseClass = NULL;
ClassType<C>::getStaticClassData() = cd->staticData;
} else {
cd->staticData = ClassType<C>::getStaticClassData().Lock();
}
HSQOBJECT& classObj = cd->classObj;
sq_resetobject(&classObj);
sq_newclass(v, false);
sq_getstackobj(v, -1, &classObj);
sq_addref(v, &classObj); // must addref before the pop!
sq_pop(v, 1);
InitClass(cd);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Gets the Squirrel object for this Class (copy)
///
/// \return Squirrel object representing the Squirrel class
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual HSQOBJECT GetObject() const {
return ClassType<C>::getClassData(vm)->classObj;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Gets the Squirrel object for this Class (reference)
///
/// \return Squirrel object representing the Squirrel class
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual HSQOBJECT& GetObject() {
return ClassType<C>::getClassData(vm)->classObj;
}
public:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Assigns a static class slot a value
///
/// \param name Name of the static slot
/// \param val Value to assign
///
/// \tparam V Type of value (usually doesnt need to be defined explicitly)
///
/// \return The Class itself so the call can be chained
///
/// \remarks
/// Static values are read-only in Squirrel.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class V>
Class& SetStaticValue(const SQChar* name, const V& val) {
BindValue<V>(name, val, true);
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Assigns a class slot a value
///
/// \param name Name of the slot
/// \param val Value to assign
///
/// \tparam V Type of value (usually doesnt need to be defined explicitly)
///
/// \return The Class itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class V>
Class& SetValue(const SQChar* name, const V& val) {
BindValue<V>(name, val, false);
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a class variable
///
/// \param name Name of the variable as it will appear in Squirrel
/// \param var Variable to bind
///
/// \tparam V Type of variable (usually doesnt need to be defined explicitly)
///
/// \remarks
/// If V is not a pointer or reference, then it must have a default constructor.
/// See Sqrat::Class::Prop to work around this requirement
///
/// \return The Class itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class V>
Class& Var(const SQChar* name, V C::* var) {
ClassData<C>* cd = ClassType<C>::getClassData(vm);
// Add the getter
BindAccessor(name, &var, sizeof(var), &sqDefaultGet<C, V>, cd->getTable);
// Add the setter
BindAccessor(name, &var, sizeof(var), &sqDefaultSet<C, V>, cd->setTable);
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a class variable without a setter
///
/// \param name Name of the variable as it will appear in Squirrel
/// \param var Variable to bind
///
/// \tparam V Type of variable (usually doesnt need to be defined explicitly)
///
/// \remarks
/// If V is not a pointer or reference, then it must have a default constructor.
/// See Sqrat::Class::Prop to work around this requirement
///
/// \return The Class itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class V>
Class& ConstVar(const SQChar* name, V C::* var) {
ClassData<C>* cd = ClassType<C>::getClassData(vm);
// Add the getter
BindAccessor(name, &var, sizeof(var), &sqDefaultGet<C, V>, cd->getTable);
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Bind a class static variable
///
/// \param name Name of the variable as it will appear in Squirrel
/// \param var Variable to bind
///
/// \tparam V Type of variable (usually doesnt need to be defined explicitly)
///
/// \remarks
/// If V is not a pointer or reference, then it must have a default constructor.
/// See Sqrat::Class::Prop to work around this requirement
///
/// \return The Class itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class V>
Class& StaticVar(const SQChar* name, V* var) {
ClassData<C>* cd = ClassType<C>::getClassData(vm);
// Add the getter
BindAccessor(name, &var, sizeof(var), &sqStaticGet<C, V>, cd->getTable);
// Add the setter
BindAccessor(name, &var, sizeof(var), &sqStaticSet<C, V>, cd->setTable);
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a class property
///
/// \param name Name of the variable as it will appear in Squirrel
/// \param getMethod Getter for the variable
/// \param setMethod Setter for the variable
///
/// \tparam F1 Type of get function (usually doesnt need to be defined explicitly)
/// \tparam F2 Type of set function (usually doesnt need to be defined explicitly)
///
/// \return The Class itself so the call can be chained
///
/// \remarks
/// This method binds setter and getter functions in C++ to Squirrel as if they are a class variable.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class F1, class F2>
Class& Prop(const SQChar* name, F1 getMethod, F2 setMethod) {
ClassData<C>* cd = ClassType<C>::getClassData(vm);
if(getMethod != NULL) {
// Add the getter
BindAccessor(name, &getMethod, sizeof(getMethod), SqMemberOverloadedFunc(getMethod), cd->getTable);
}
if(setMethod != NULL) {
// Add the setter
BindAccessor(name, &setMethod, sizeof(setMethod), SqMemberOverloadedFunc(setMethod), cd->setTable);
}
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a class property (using global functions instead of member functions)
///
/// \param name Name of the variable as it will appear in Squirrel
/// \param getMethod Getter for the variable
/// \param setMethod Setter for the variable
///
/// \tparam F1 Type of get function (usually doesnt need to be defined explicitly)
/// \tparam F2 Type of set function (usually doesnt need to be defined explicitly)
///
/// \return The Class itself so the call can be chained
///
/// \remarks
/// This method binds setter and getter functions in C++ to Squirrel as if they are a class variable.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class F1, class F2>
Class& GlobalProp(const SQChar* name, F1 getMethod, F2 setMethod) {
ClassData<C>* cd = ClassType<C>::getClassData(vm);
if(getMethod != NULL) {
// Add the getter
BindAccessor(name, &getMethod, sizeof(getMethod), SqMemberGlobalOverloadedFunc(getMethod), cd->getTable);
}
if(setMethod != NULL) {
// Add the setter
BindAccessor(name, &setMethod, sizeof(setMethod), SqMemberGlobalOverloadedFunc(setMethod), cd->setTable);
}
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a read-only class property
///
/// \param name Name of the variable as it will appear in Squirrel
/// \param getMethod Getter for the variable
///
/// \tparam F Type of get function (usually doesnt need to be defined explicitly)
///
/// \return The Class itself so the call can be chained
///
/// \remarks
/// This method binds a getter function in C++ to Squirrel as if it is a class variable.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class F>
Class& Prop(const SQChar* name, F getMethod) {
// Add the getter
BindAccessor(name, &getMethod, sizeof(getMethod), SqMemberOverloadedFunc(getMethod), ClassType<C>::getClassData(vm)->getTable);
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a read-only class property (using a global function instead of a member function)
///
/// \param name Name of the variable as it will appear in Squirrel
/// \param getMethod Getter for the variable
///
/// \tparam F Type of get function (usually doesnt need to be defined explicitly)
///
/// \return The Class itself so the call can be chained
///
/// \remarks
/// This method binds a getter function in C++ to Squirrel as if it is a class variable.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class F>
Class& GlobalProp(const SQChar* name, F getMethod) {
// Add the getter
BindAccessor(name, &getMethod, sizeof(getMethod), SqMemberGlobalOverloadedFunc(getMethod), ClassType<C>::getClassData(vm)->getTable);
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a class function
///
/// \param name Name of the function as it will appear in Squirrel
/// \param method Function to bind
///
/// \tparam F Type of function (usually doesnt need to be defined explicitly)
///
/// \return The Class itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class F>
Class& Func(const SQChar* name, F method) {
BindFunc(name, &method, sizeof(method), SqMemberFunc(method));
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a class function with formatting support
///
/// \param name Name of the function as it will appear in Squirrel
/// \param method Function to bind
///
/// \tparam F Type of function (usually doesnt need to be defined explicitly)
///
/// \return The Class itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class F>
Class& FmtFunc(const SQChar* name, F method) {
BindFunc(name, &method, sizeof(method), SqMemberFunc(method));
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a class function with overloading enabled
///
/// \param name Name of the function as it will appear in Squirrel
/// \param method Function to bind
///
/// \tparam F Type of function (usually doesnt need to be defined explicitly)
///
/// \return The Class itself so the call can be chained
///
/// \remarks
/// Overloading in this context means to allow the function name to be used with functions
/// of a different number of arguments. This definition differs from others (e.g. C++'s).
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class F>
Class& Overload(const SQChar* name, F method) {
BindOverload(name, &method, sizeof(method), SqMemberOverloadedFunc(method), SqOverloadFunc(method), SqGetArgCount(method));
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a global function as a class function
///
/// \param name Name of the function as it will appear in Squirrel
/// \param method Function to bind
///
/// \tparam F Type of function (usually doesnt need to be defined explicitly)
///
/// \return The Class itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class F>
Class& GlobalFunc(const SQChar* name, F method) {
BindFunc(name, &method, sizeof(method), SqMemberGlobalFunc(method));
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a global function as a class function with formatting support
///
/// \param name Name of the function as it will appear in Squirrel
/// \param method Function to bind
///
/// \tparam F Type of function (usually doesnt need to be defined explicitly)
///
/// \return The Class itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class F>
Class& GlobalFmtFunc(const SQChar* name, F method) {
BindFunc(name, &method, sizeof(method), SqMemberGlobalFunc(method));
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a static class function
///
/// \param name Name of the function as it will appear in Squirrel
/// \param method Function to bind
///
/// \tparam F Type of function (usually doesnt need to be defined explicitly)
///
/// \return The Class itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class F>
Class& StaticFunc(const SQChar* name, F method) {
BindFunc(name, &method, sizeof(method), SqGlobalFunc(method));
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a static class function with formatting support
///
/// \param name Name of the function as it will appear in Squirrel
/// \param method Function to bind
///
/// \tparam F Type of function (usually doesnt need to be defined explicitly)
///
/// \return The Class itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class F>
Class& StaticFmtFunc(const SQChar* name, F method) {
BindFunc(name, &method, sizeof(method), SqGlobalFunc(method));
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a global function as a class function with overloading enabled
///
/// \param name Name of the function as it will appear in Squirrel
/// \param method Function to bind
///
/// \tparam F Type of function (usually doesnt need to be defined explicitly)
///
/// \return The Class itself so the call can be chained
///
/// \remarks
/// Overloading in this context means to allow the function name to be used with functions
/// of a different number of arguments. This definition differs from others (e.g. C++'s).
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class F>
Class& GlobalOverload(const SQChar* name, F method) {
BindOverload(name, &method, sizeof(method), SqMemberGlobalOverloadedFunc(method), SqOverloadFunc(method), SqGetArgCount(method) - 1);
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a static class function with overloading enabled
///
/// \param name Name of the function as it will appear in Squirrel
/// \param method Function to bind
///
/// \tparam F Type of function (usually doesnt need to be defined explicitly)
///
/// \return The Class itself so the call can be chained
///
/// \remarks
/// Overloading in this context means to allow the function name to be used with functions
/// of a different number of arguments. This definition differs from others (e.g. C++'s).
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class F>
Class& StaticOverload(const SQChar* name, F method) {
BindOverload(name, &method, sizeof(method), SqGlobalOverloadedFunc(method), SqOverloadFunc(method), SqGetArgCount(method));
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a Squirrel function as defined by the Squirrel documentation as a class function
///
/// \param name Name of the function as it will appear in Squirrel
/// \param func Function to bind
///
/// \return The Class itself so the call can be chained
///
/// \remarks
/// Inside of the function, the class instance the function was called with will be at index 1 on the
/// stack and all arguments will be after that index in the order they were given to the function.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Class& SquirrelFunc(const SQChar* name, SQFUNCTION func) {
sq_pushobject(vm, ClassType<C>::getClassData(vm)->classObj);
sq_pushstring(vm, name, -1);
sq_newclosure(vm, func, 0);
// Set the closure name (for debug purposes)
sq_setnativeclosurename(vm, -1, name);
sq_newslot(vm, -3, false);
sq_pop(vm, 1); // pop table
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Gets a Function from a name in the Class
///
/// \param name The name in the class that contains the Function
///
/// \return Function found in the Class (null if failed)
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Function GetFunction(const SQChar* name) {
ClassData<C>* cd = ClassType<C>::getClassData(vm);
HSQOBJECT funcObj;
sq_pushobject(vm, cd->classObj);
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, cd->classObj, funcObj); // must addref before the pop!
sq_pop(vm, 2);
return ret;
}
protected:
/// @cond DEV
static SQInteger ClassWeakref(HSQUIRRELVM vm) {
sq_weakref(vm, -1);
return 1;
}
static SQInteger ClassTypeof(HSQUIRRELVM vm) {
sq_pushstring(vm, ClassType<C>::ClassName().c_str(), -1);
return 1;
}
static SQInteger ClassCloned(HSQUIRRELVM vm) {
SQTRY()
Sqrat::Var<const C*> other(vm, 2);
SQCATCH_NOEXCEPT(vm) {
SQCLEAR(vm);
return SQ_ERROR;
}
#if !defined (SCRAT_NO_ERROR_CHECKING)
return ClassType<C>::CopyFunc()(vm, 1, other.value);
#else
ClassType<C>::CopyFunc()(vm, 1, other.value);
return 0;
#endif
SQCATCH(vm) {
#if defined (SCRAT_USE_EXCEPTIONS)
SQUNUSED(e); // this is to avoid a warning in MSVC
#endif
return SQ_ERROR;
}
}
// Initialize the required data structure for the class
void InitClass(ClassData<C>* cd) {
cd->instances.Init(new typename unordered_map<C*, HSQOBJECT>::type);
// push the class
sq_pushobject(vm, cd->classObj);
// set the typetag of the class
sq_settypetag(vm, -1, cd->staticData.Get());
// add the default constructor
sq_pushstring(vm, _SC("constructor"), -1);
sq_newclosure(vm, &A::New, 0);
// Set the closure name (for debug purposes)
sq_setnativeclosurename(vm, -1, _SC("constructor"));
sq_newslot(vm, -3, false);
// add the set table (static)
HSQOBJECT& setTable = cd->setTable;
sq_resetobject(&setTable);
sq_pushstring(vm, _SC("__setTable"), -1);
sq_newtable(vm);
sq_getstackobj(vm, -1, &setTable);
sq_addref(vm, &setTable);
sq_newslot(vm, -3, true);
// add the get table (static)
HSQOBJECT& getTable = cd->getTable;
sq_resetobject(&getTable);
sq_pushstring(vm, _SC("__getTable"), -1);
sq_newtable(vm);
sq_getstackobj(vm, -1, &getTable);
sq_addref(vm, &getTable);
sq_newslot(vm, -3, true);
// override _set
sq_pushstring(vm, _SC("_set"), -1);
sq_pushobject(vm, setTable); // Push the set table as a free variable
sq_newclosure(vm, &sqVarSet, 1);
// Set the closure name (for debug purposes)
sq_setnativeclosurename(vm, -1, _SC("_set"));
sq_newslot(vm, -3, false);
// override _get
sq_pushstring(vm, _SC("_get"), -1);
sq_pushobject(vm, getTable); // Push the get table as a free variable
sq_newclosure(vm, &sqVarGet, 1);
// Set the closure name (for debug purposes)
sq_setnativeclosurename(vm, -1, _SC("_get"));
sq_newslot(vm, -3, false);
// add weakref (apparently not provided by default)
sq_pushstring(vm, _SC("weakref"), -1);
sq_newclosure(vm, &Class::ClassWeakref, 0);
// Set the closure name (for debug purposes)
sq_setnativeclosurename(vm, -1, _SC("weakref"));
sq_newslot(vm, -3, false);
// add _typeof
sq_pushstring(vm, _SC("_typeof"), -1);
sq_newclosure(vm, &Class::ClassTypeof, 0);
// Set the closure name (for debug purposes)
sq_setnativeclosurename(vm, -1, _SC("_typeof"));
sq_newslot(vm, -3, false);
// add _cloned
sq_pushstring(vm, _SC("_cloned"), -1);
sq_newclosure(vm, &Class::ClassCloned, 0);
// Set the closure name (for debug purposes)
sq_setnativeclosurename(vm, -1, _SC("_cloned"));
sq_newslot(vm, -3, false);
// pop the class
sq_pop(vm, 1);
}
// Helper function used to bind getters and setters
inline void BindAccessor(const SQChar* name, void* var, size_t varSize, SQFUNCTION func, HSQOBJECT table) {
// Push the get or set table
sq_pushobject(vm, table);
sq_pushstring(vm, name, -1);
// Push the variable offset as a free variable
SQUserPointer varPtr = sq_newuserdata(vm, static_cast<SQUnsignedInteger>(varSize));
memcpy(varPtr, var, varSize);
// Create the accessor function
sq_newclosure(vm, func, 1);
// Set the closure name (for debug purposes)
sq_setnativeclosurename(vm, -1, name);
// Add the accessor to the table
sq_newslot(vm, -3, false);
// Pop get/set table
sq_pop(vm, 1);
}
// constructor binding
Class& BindConstructor(SQFUNCTION constructor, SQInteger nParams, const SQChar *name = 0) {
// Decide whether to bind to a class or the root table
bool alternative_global = false;
if (name == 0)
name = _SC("constructor");
else alternative_global = true;
// Generate the overload mangled name
string overloadName;
overloadName.reserve(15);
SqOverloadName::Get(name, nParams, overloadName);
// Should we push a class object?
if (!alternative_global )
sq_pushobject(vm, ClassType<C>::getClassData(vm)->classObj);
// The containing environment is the root table??
else sq_pushroottable(vm);
// Bind overload handler name
sq_pushstring(vm, name, -1);
// function name is passed as a free variable
//sq_pushstring(vm, name, -1);
sq_push(vm, -1); // <- Let's cheat(?) by pushing the same object
sq_newclosure(vm, &OverloadConstructionForwarder, 1);
// Set the closure name (for debug purposes)
sq_setnativeclosurename(vm, -1, name);
// Include it into the object
sq_newslot(vm, -3, false);
// Bind overloaded function
sq_pushstring(vm, overloadName.c_str(), static_cast<SQInteger>(overloadName.size()));
sq_newclosure(vm, constructor, 0);
// Set the closure name (for debug purposes)
sq_setnativeclosurename(vm, -1, overloadName.c_str());
// Include it into the object
sq_newslot(vm, -3, false);
// pop object/environment
sq_pop(vm, 1);
return *this;
}
/// @endcond
public:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a constructor with no arguments (there can only be one constructor of this many arguments for a given name)
///
/// \param name Name of the constructor as it will appear in Squirrel (default value creates a traditional constructor)
///
/// \return The Class itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Class& Ctor(const SQChar *name = 0) {
return BindConstructor(A::iNew, 0, name);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Binds a constructor with 1 or more arguments (there can only be one constructor of this many arguments for a given name)
///
/// \param name Name of the constructor as it will appear in Squirrel (default value creates a traditional constructor)
///
/// \tparam P Type of arguments of the constructor (must be defined explicitly)
///
/// \return The Class itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class... P>
Class& Ctor(const SQChar *name = 0) {
return BindConstructor(A::template iNew<P...>, sizeof...(P), name);
}
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Facilitates exposing a C++ class with a base class to Squirrel
///
/// \tparam C Class type to expose
/// \tparam B Base class type (must already be bound)
/// \tparam A An allocator to use when instantiating and destroying class instances of this type in Squirrel
///
/// \remarks
/// Classes in Squirrel are single-inheritance only, and as such Sqrat only allows for single inheritance as well.
///
/// \remarks
/// DefaultAllocator is used if no allocator is specified. This should be sufficent for most classes,
/// but if specific behavior is desired, it can be overridden. If the class should not be instantiated from
/// Squirrel the NoConstructor allocator may be used. See NoCopy and CopyOnly too.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class C, class B, class A = DefaultAllocator<C> >
class DerivedClass : public Class<C, A>
{
private:
static SQInteger cleanup_hook(SQUserPointer ptr, SQInteger size) {
SQUNUSED(size);
ClassData<C>** ud = reinterpret_cast<ClassData<C>**>(ptr);
delete *ud;
return 0;
}
public:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Constructs the DerivedClass object
///
/// A DerivedClass object doesnt do anything on its own.
/// It must be told what methods and variables it contains.
/// This is done using Class methods such as Class::Func and Class::Var.
/// Then the DerivedClass must be exposed to Squirrel.
/// This is usually done by calling TableBase::Bind on a RootTable with the DerivedClass.
///
/// \param v Squirrel virtual machine to create the DerivedClass for
/// \param className A necessarily unique name for the class that can appear in error messages
///
/// \remarks
/// You MUST bind the base class fully before constructing a derived class.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DerivedClass(HSQUIRRELVM v, const string& className) : Class<C, A>(v, string(), false) {
if (!ClassType<C>::hasClassData(v)) {
sq_pushregistrytable(v);
sq_pushstring(v, "__classes", -1);
if (SQ_FAILED(sq_rawget(v, -2))) {
sq_newtable(v);
sq_pushstring(v, "__classes", -1);
sq_push(v, -2);
sq_rawset(v, -4);
}
sq_pushstring(v, className.c_str(), -1);
ClassData<C>** ud = reinterpret_cast<ClassData<C>**>(sq_newuserdata(v, sizeof(ClassData<C>*)));
*ud = new ClassData<C>;
sq_setreleasehook(v, -1, &cleanup_hook);
sq_rawset(v, -3);
sq_pop(v, 2);
ClassData<B>* bd = ClassType<B>::getClassData(v);
ClassData<C>* cd = *ud;
if (ClassType<C>::getStaticClassData().Expired()) {
cd->staticData.Init(new StaticClassData<C, B>);
cd->staticData->copyFunc = &A::Copy;
cd->staticData->className = string(className);
cd->staticData->baseClass = bd->staticData.Get();
ClassType<C>::getStaticClassData() = cd->staticData;
} else {
cd->staticData = ClassType<C>::getStaticClassData().Lock();
}
HSQOBJECT& classObj = cd->classObj;
sq_resetobject(&classObj);
sq_pushobject(v, bd->classObj);
sq_newclass(v, true);
sq_getstackobj(v, -1, &classObj);
sq_addref(v, &classObj); // must addref before the pop!
sq_pop(v, 1);
InitDerivedClass(v, cd, bd);
}
}
protected:
/// @cond DEV
void InitDerivedClass(HSQUIRRELVM vm, ClassData<C>* cd, ClassData<B>* bd) {
cd->instances.Init(new typename unordered_map<C*, HSQOBJECT>::type);
// push the class
sq_pushobject(vm, cd->classObj);
// set the typetag of the class
sq_settypetag(vm, -1, cd->staticData.Get());
// add the default constructor
sq_pushstring(vm, _SC("constructor"), -1);
sq_newclosure(vm, &A::New, 0);
// Set the closure name (for debug purposes)
sq_setnativeclosurename(vm, -1, _SC("constructor"));
sq_newslot(vm, -3, false);
// clone the base classes set table (static)
HSQOBJECT& setTable = cd->setTable;
sq_resetobject(&setTable);
sq_pushobject(vm, bd->setTable);
sq_pushstring(vm, _SC("__setTable"), -1);
sq_clone(vm, -2);
sq_remove(vm, -3);
sq_getstackobj(vm, -1, &setTable);
sq_addref(vm, &setTable);
sq_newslot(vm, -3, true);
// clone the base classes get table (static)
HSQOBJECT& getTable = cd->getTable;
sq_resetobject(&getTable);
sq_pushobject(vm, bd->getTable);
sq_pushstring(vm, _SC("__getTable"), -1);
sq_clone(vm, -2);
sq_remove(vm, -3);
sq_getstackobj(vm, -1, &getTable);
sq_addref(vm, &getTable);
sq_newslot(vm, -3, true);
// override _set
sq_pushstring(vm, _SC("_set"), -1);
sq_pushobject(vm, setTable); // Push the set table as a free variable
sq_newclosure(vm, sqVarSet, 1);
// Set the closure name (for debug purposes)
sq_setnativeclosurename(vm, -1, _SC("_set"));
sq_newslot(vm, -3, false);
// override _get
sq_pushstring(vm, _SC("_get"), -1);
sq_pushobject(vm, getTable); // Push the get table as a free variable
sq_newclosure(vm, sqVarGet, 1);
// Set the closure name (for debug purposes)
sq_setnativeclosurename(vm, -1, _SC("_get"));
sq_newslot(vm, -3, false);
// add weakref (apparently not provided by default)
sq_pushstring(vm, _SC("weakref"), -1);
sq_newclosure(vm, &Class<C, A>::ClassWeakref, 0);
// Set the closure name (for debug purposes)
sq_setnativeclosurename(vm, -1, _SC("weakref"));
sq_newslot(vm, -3, false);
// add _typeof
sq_pushstring(vm, _SC("_typeof"), -1);
sq_newclosure(vm, &Class<C, A>::ClassTypeof, 0);
// Set the closure name (for debug purposes)
sq_setnativeclosurename(vm, -1, _SC("_typeof"));
sq_newslot(vm, -3, false);
// add _cloned
sq_pushstring(vm, _SC("_cloned"), -1);
sq_newclosure(vm, &Class<C, A>::ClassCloned, 0);
// Set the closure name (for debug purposes)
sq_setnativeclosurename(vm, -1, _SC("_cloned"));
sq_newslot(vm, -3, false);
// pop the class
sq_pop(vm, 1);
}
/// @endcond
};
}
#endif

View File

@ -1,255 +0,0 @@
//
// 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_
#ifdef SQMOD_PLUGIN_API
#include <SqAPI.h>
#else
#include <squirrelex.h>
#endif // SQMOD_PLUGIN_API
#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

@ -1,413 +0,0 @@
//
// 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_
#ifdef SQMOD_PLUGIN_API
#include <SqAPI.h>
#else
#include <squirrelex.h>
#endif // SQMOD_PLUGIN_API
#include <string.h>
#include "sqratObject.h"
namespace Sqrat {
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Helper to remember the type of the constant.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
enum ConstType
{
SQET_STRING = 0,
SQET_INT = 1,
SQET_REAL = 2,
SQET_BOOL = 3
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Helper class that represents an enumeration value. Used to reduce compilation times and executable size.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct EnumElement
{
// The name of the constant
const SQChar * Name;
// The value of the constant
union {
const SQChar * mSTR;
const SQInteger mINT;
const SQFloat mREAL;
const bool mBOOL;
};
// The type of the constant value
const unsigned short Type;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Constructors that can identify the type and perform the proper conversion.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
EnumElement(const SQChar * name, const SQChar * value)
: Name(name), mSTR(value), Type(SQET_STRING)
{ /* ... */ }
EnumElement(const SQChar * name, bool value)
: Name(name), mBOOL(value), Type(SQET_BOOL)
{ /* ... */ }
EnumElement(const SQChar * name, signed char value)
: Name(name), mINT(static_cast< SQInteger >(value)), Type(SQET_INT)
{ /* ... */ }
EnumElement(const SQChar * name, unsigned char value)
: Name(name), mINT(static_cast< SQInteger >(value)), Type(SQET_INT)
{ /* ... */ }
EnumElement(const SQChar * name, signed short value)
: Name(name), mINT(static_cast< SQInteger >(value)), Type(SQET_INT)
{ /* ... */ }
EnumElement(const SQChar * name, unsigned short value)
: Name(name), mINT(static_cast< SQInteger >(value)), Type(SQET_INT)
{ /* ... */ }
EnumElement(const SQChar * name, signed int value)
: Name(name), mINT(static_cast< SQInteger >(value)), Type(SQET_INT)
{ /* ... */ }
EnumElement(const SQChar * name, unsigned int value)
: Name(name), mINT(static_cast< SQInteger >(value)), Type(SQET_INT)
{ /* ... */ }
EnumElement(const SQChar * name, signed long value)
: Name(name), mINT(static_cast< SQInteger >(value)), Type(SQET_INT)
{ /* ... */ }
EnumElement(const SQChar * name, unsigned long value)
: Name(name), mINT(static_cast< SQInteger >(value)), Type(SQET_INT)
{ /* ... */ }
EnumElement(const SQChar * name, signed long long value)
: Name(name), mINT(static_cast< SQInteger >(value)), Type(SQET_INT)
{ /* ... */ }
EnumElement(const SQChar * name, unsigned long long value)
: Name(name), mINT(static_cast< SQInteger >(value)), Type(SQET_INT)
{ /* ... */ }
EnumElement(const SQChar * name, float value)
: Name(name), mREAL(static_cast< SQFloat >(value)), Type(SQET_REAL)
{ /* ... */ }
EnumElement(const SQChar * name, double value)
: Name(name), mREAL(static_cast< SQFloat >(value)), Type(SQET_REAL)
{ /* ... */ }
template < typename T > EnumElement(const SQChar * name, T value)
: Name(name), mINT(static_cast< SQInteger >(value)), Type(SQET_INT)
{ /* ... */ }
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// HHelper class that represents an enumeration. Used to reduce compilation times and executable size.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct EnumElements
{
// The name of the enumeration if this is an enumeration otherwise null
const SQChar * Name;
// The constant values
const EnumElement * Values;
// The number of values
const unsigned int Count;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Constructor that can identify the number of values at compile-time.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template < size_t N > EnumElements(const EnumElement(&values)[N])
: EnumElements(nullptr, values, N)
{ /* ... */ }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Constructor that takes an explicit number of values at run-time.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
EnumElements(const EnumElement * values, unsigned int count)
: EnumElements(nullptr, values, count)
{ /* ... */ }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Constructor that can identify the number of values at compile-time.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template < size_t N > EnumElements(const SQChar * name, const EnumElement(&values)[N])
: EnumElements(name, values, N)
{ /* ... */ }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Constructor that takes an explicit number of values at run-time.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
EnumElements(const SQChar * name, const EnumElement * values, unsigned int count)
: Name(name), Values(values), Count(count)
{ /* ... */ }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Register the managed constants into the specified constants table.
///
/// \remarks
/// The constants table could be either the main constants table or an enumeration.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template < typename T > void Bind(T & table) const
{
for (unsigned int i = 0; i < Count; ++i)
{
switch (Values[i].Type)
{
case SQET_STRING: table.Const(Values[i].Name, Values[i].mSTR); break;
case SQET_INT: table.Const(Values[i].Name, Values[i].mINT); break;
case SQET_REAL: table.Const(Values[i].Name, Values[i].mREAL); break;
case SQET_BOOL: table.Const(Values[i].Name, Values[i].mBOOL); break;
default: SQTHROW(table.GetVM(), "Unknown constant value type");
}
}
}
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 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 double val) {
BindValue<double>(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;
}
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Register a dynamic amount of enumerations into the constants table.
///
/// \remarks
/// The number of enumerations have to be manually specified.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline void RegisterEnumerationsPtr(HSQUIRRELVM vm, const EnumElements * elist, unsigned int count)
{
// Grab a reference to the constants table
ConstTable ct(vm);
// Iterate over the specified enumerations
for (unsigned int i = 0; i < count; ++i)
{
// Validate the enumeration name
if (!(elist[i].Name ) || *(elist[i].Name) == '\0')
{
SQTHROW(vm, _SC("Invalid or empty enumeration name"));
}
// Prepare an enumeration table
Enumeration e(vm);
// Bind the enumeration values
elist[i].Bind(e);
// Bind the enumeration to the constant table
ct.Enum(elist[i].Name, e);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Register a specific amount of enumerations identified at compile-time into the constants table.
///
/// \remarks
/// The number of enumerations will be automatically detected.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template < size_t N > inline void RegisterEnumerations(HSQUIRRELVM vm, const EnumElements(&elist)[N])
{
RegisterEnumerationsPtr(vm, elist, N); // Just forward the information
}
}
#endif

View File

@ -1,339 +0,0 @@
//
// sqratFunction: Squirrel Function Wrapper
//
//
// Copyright (c) 2009 Brandon Jones
// Copyirght 2011 Li-Cheng (Andy) Tai
//
// 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_SQFUNC_H_)
#define _SCRAT_SQFUNC_H_
#ifdef SQMOD_PLUGIN_API
#include <SqAPI.h>
#else
#include <squirrelex.h>
#endif // SQMOD_PLUGIN_API
#include "sqratObject.h"
namespace Sqrat {
// Represents a function in Squirrel
struct Function {
friend class TableBase;
friend class Table;
friend class ArrayBase;
friend struct Var<Function>;
HSQOBJECT mEnv, mObj;
// Default constructor (null)
Function() {
sq_resetobject(&mEnv);
sq_resetobject(&mObj);
}
// Copy constructor
Function(const Function& sf) : mEnv(sf.mEnv), mObj(sf.mObj) {
sq_addref(DefaultVM::Get_(), &mEnv);
sq_addref(DefaultVM::Get_(), &mObj);
}
// Move constructor
Function(Function&& sf) : mEnv(sf.mEnv), mObj(sf.mObj) {
sq_resetobject(&sf.GetEnv());
sq_resetobject(&sf.GetFunc());
}
// Constructs a Function from a slot in an Object
Function(const Object& e, const SQChar* slot) : mEnv(e.GetObject()) {
sq_addref(DefaultVM::Get_(), &mEnv);
Object so = e.GetSlot(slot);
mObj = so.GetObject();
sq_addref(DefaultVM::Get_(), &mObj);
#if !defined (SCRAT_NO_ERROR_CHECKING)
SQObjectType value_type = so.GetType();
if (value_type != OT_CLOSURE && value_type != OT_NATIVECLOSURE) {
// Note that classes can also be considered functions in Squirrel
SQTHROW(DefaultVM::Get_(), _SC("function not found in slot"));
}
#endif
}
// Constructs a Function from a value off the stack at the specified index
// Assumes the Function environment is at index 1.
Function(HSQUIRRELVM vm, SQInteger idx) {
sq_getstackobj(vm, 1, &mEnv);
sq_getstackobj(vm, idx, &mObj);
sq_addref(vm, &mEnv);
sq_addref(vm, &mObj);
#if !defined (SCRAT_NO_ERROR_CHECKING)
SQObjectType value_type = sq_gettype(vm, idx);
if (value_type != OT_CLOSURE && value_type != OT_NATIVECLOSURE) {
SQTHROW(vm, FormatTypeError(vm, idx, _SC("closure")));
}
#endif
}
// Constructs a Function from a value off the stack at the specified index pointed by `idx2`
// Assumes the Function environment is at index pointed by `idx1`
// If `idx1` is null, it defaults to root table
// If `idx1` is an object, it will be used as the environment
// If `idx1` is actually a function/closure then `idx2` is ignored
Function(HSQUIRRELVM vm, SQInteger idx1, SQInteger idx2) : Function() {
Assign(vm, idx1, idx2);
}
// Constructs a Function from two Squirrel objects (one is the environment object and the other is the function object)
Function(HSQUIRRELVM vm, HSQOBJECT e, HSQOBJECT o) : mEnv(e), mObj(o) {
sq_addref(vm, &mEnv);
sq_addref(vm, &mObj);
}
// Destructor
~Function() {
Release();
}
// Copy Assignment operator
Function& operator=(const Function& sf) {
Release();
mEnv = sf.mEnv;
mObj = sf.mObj;
if (!sf.IsNull()) {
sq_addref(DefaultVM::Get_(), &mEnv);
sq_addref(DefaultVM::Get_(), &mObj);
}
return *this;
}
// Move Assignment operator
Function& operator=(Function&& sf) {
Release();
mEnv = sf.mEnv;
mObj = sf.mObj;
sq_resetobject(&sf.GetEnv());
sq_resetobject(&sf.GetFunc());
return *this;
}
// Checks whether the Function is null
bool IsNull() const {
return sq_isnull(mObj);
}
// Gets the Squirrel environment object for this Function (copy)
HSQOBJECT GetEnv() const {
return mEnv;
}
// Gets the Squirrel environment object for this Function (reference)
HSQOBJECT& GetEnv() {
return mEnv;
}
// Gets the Squirrel function object for this Function (copy)
HSQOBJECT GetFunc() const {
return mObj;
}
// Gets the Squirrel function object for this Function (reference)
HSQOBJECT& GetFunc() {
return mObj;
}
// Gets the Squirrel VM for this Function
HSQUIRRELVM GetVM() const {
return DefaultVM::Get_();
}
// Sets the Function to null (removing its references to underlying Squirrel objects)
void Release() {
if(!IsNull()) {
sq_release(DefaultVM::Get_(), &mEnv);
sq_release(DefaultVM::Get_(), &mObj);
sq_resetobject(&mEnv);
sq_resetobject(&mObj);
}
}
// Sets the Function to null (removing its references to underlying Squirrel objects)
// This doesn't call release if the reference count is 1.
// Workaround for some weird squirrel behavior that generates an assert in debug mode.
void ReleaseGently() {
if(!IsNull()) {
sq_release(DefaultVM::Get_(), &mEnv);
if (sq_getrefcount(DefaultVM::Get_(), &mObj) > 1) {
sq_release(DefaultVM::Get_(), &mObj);
}
sq_resetobject(&mEnv);
sq_resetobject(&mObj);
}
}
// Assigns a Function from a value off the stack at the specified index pointed by `idx2`
// Assumes the Function environment is at index pointed by `idx1`
// If `idx1` is null, it defaults to root table
// If `idx1` is an object, it will be used as the environment
// If `idx1` is actually a function/closure then `idx2` is ignored
bool Assign(HSQUIRRELVM vm, SQInteger idx1, SQInteger idx2, bool bind_null=false) {
// Release current callback, if any
Release();
// Tells if the current environment was used
bool cenv = false;
// Retrieve the environment type
const SQObjectType ty1 = sq_gettype(vm, idx1);
// Should we use the root table as the environment?
if (ty1 == OT_NULL) {
sq_pushroottable(vm); // Push it on the stack
sq_getstackobj(vm, -1, &mEnv); // Grab it
sq_poptop(vm); // Clean up the stack
// Should we use current environment?
} else if (ty1 & (_RT_CLOSURE | _RT_NATIVECLOSURE)) {
sq_getstackobj(vm, 1, &mEnv); // `this` as environment
idx2 = idx1; // There is no explicit environment given
cenv = true;
// Is there a specific environment?
} else if (ty1 & (_RT_TABLE | _RT_CLASS | _RT_INSTANCE)) {
sq_getstackobj(vm, idx1, &mEnv); // Grab the given environment
} else {
#if !defined (SCRAT_NO_ERROR_CHECKING)
SQTHROW(vm, FormatTypeError(vm, idx1, _SC("object")));
#else
return cenv;
#endif
}
// Retrieve the callback type
const SQObjectType ty2 = sq_gettype(vm, idx2);
// Can we bind null?
if (bind_null && ty2 == OT_NULL) {
sq_resetobject(&mEnv); // Drop the environment, if any
return cenv; // Just stop knowing this is what we want
// Is the callback is valid?
} else if (ty2 & (_RT_CLOSURE | _RT_NATIVECLOSURE)) {
sq_getstackobj(vm, idx2, &mObj);
// Reference the environment and function
sq_addref(vm, &mEnv);
sq_addref(vm, &mObj);
} else {
sq_resetobject(&mEnv); // Discard obtained environment
#if !defined (SCRAT_NO_ERROR_CHECKING)
SQTHROW(vm, FormatTypeError(vm, idx2, _SC("closure")));
#endif
}
// Return whether current environment was used
return cenv;
}
// Runs the Function and returns its value as a SharedPtr
template<class R, class... Args> SharedPtr<R> Evaluate(Args &&... args) {
static constexpr unsigned ARGC = sizeof...(Args) + 1; // + environment
HSQUIRRELVM vm = DefaultVM::Get_();
SQInteger top = sq_gettop(vm);
// Push the environment followed by the function
sq_pushobject(vm, mObj);
sq_pushobject(vm, mEnv);
// Validate the funtion parameter count
#if !defined (SCRAT_NO_ERROR_CHECKING)
SQInteger nparams;
SQInteger nfreevars;
if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != ARGC)) {
sq_pop(vm, 2);
SQTHROW(vm, _SC("wrong number of parameters"));
return SharedPtr<R>();
}
#endif
// Push the arguments
PushVars(vm, std::forward<Args>(args)...);
#if !defined (SCRAT_NO_ERROR_CHECKING)
SQRESULT result = sq_call(vm, ARGC, true, ErrorHandling::IsEnabled());
//handle an error: pop the stack and throw the exception
if (SQ_FAILED(result)) {
sq_settop(vm, top);
SQTHROW(vm, LastErrorString(vm));
return SharedPtr<R>();
}
#else
sq_call(vm, ARGC, true, ErrorHandling::IsEnabled());
#endif
SharedPtr<R> ret = Var<SharedPtr<R> >(vm, -1).value;
sq_settop(vm, top);
return ret;
}
// Runs the Function
template< class... Args >
void Execute(Args &&... args) {
static constexpr unsigned ARGC = sizeof...(Args) + 1; // + environment
HSQUIRRELVM vm = DefaultVM::Get_();
SQInteger top = sq_gettop(vm);
// Push the environment followed by the function
sq_pushobject(vm, mObj);
sq_pushobject(vm, mEnv);
// Validate the funtion parameter count
#if !defined (SCRAT_NO_ERROR_CHECKING)
SQInteger nparams;
SQInteger nfreevars;
if (SQ_SUCCEEDED(sq_getclosureinfo(vm, -2, &nparams, &nfreevars)) && (nparams != ARGC)) {
sq_pop(vm, 2);
SQTHROW(vm, _SC("wrong number of parameters"));
return;
}
#endif
PushVars(vm, std::forward<Args>(args)...);
#if !defined (SCRAT_NO_ERROR_CHECKING)
SQRESULT result = sq_call(vm, ARGC, false, ErrorHandling::IsEnabled());
sq_settop(vm, top);
//handle an error: throw the exception
if (SQ_FAILED(result)) {
SQTHROW(vm, LastErrorString(vm));
return;
}
#else
sq_call(vm, ARGC, false, ErrorHandling::IsEnabled());
sq_settop(vm, top);
#endif
}
// Runs the Function
template< class... Args > void operator() (Args &&... args) {
Execute(std::forward<Args>(args)...);
}
};
// Used to get and push Function instances to and from the stack as references (functions are always references in Squirrel)
template<> struct Var<Function> {
/// The actual value of get operations
Function value;
// Attempts to get the value off the stack at idx as a Function
// Assumes the Function environment is at index 1.
Var(HSQUIRRELVM vm, SQInteger idx) : value(vm, idx) {
}
// Called by Sqrat::PushVar to put a Function on the stack
static void push(HSQUIRRELVM vm, const Function& value) {
sq_pushobject(vm, value.GetFunc());
}
};
// Used to get and push Function instances to and from the stack as references (functions are always references in Squirrel)
template<> struct Var<Function&> : public Var<Function> {
Var(HSQUIRRELVM vm, SQInteger idx) : Var<Function>(vm, idx)
{
}
};
// Used to get and push Function instances to and from the stack as references (functions are always references in Squirrel)
template<> struct Var<const Function&> : public Var<Function> {
Var(HSQUIRRELVM vm, SQInteger idx) : Var<Function>(vm, idx)
{
}
};
}
#endif

View File

@ -1,205 +0,0 @@
//
// SqratGlobalMethods: Global Methods
//
//
// Copyright (c) 2009 Brandon Jones
// Copyirght 2011 Li-Cheng (Andy) Tai
//
// 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_GLOBAL_METHODS_H_)
#define _SCRAT_GLOBAL_METHODS_H_
#ifdef SQMOD_PLUGIN_API
#include <SqAPI.h>
#else
#include <squirrelex.h>
#endif // SQMOD_PLUGIN_API
#include "sqratTypes.h"
namespace Sqrat {
/// @cond DEV
//
// Squirrel Global Functions
//
template <class R> struct SqGlobalProxy {
template <class... A> static SQInteger Run(HSQUIRRELVM vm, SQInteger idx) {
ArgFwd<A...>{}.Call(vm, idx, [](HSQUIRRELVM vm, A... a) {
typedef R(*M)(A...);
M* method;
sq_getuserdata(vm, -1, reinterpret_cast<SQUserPointer*>(&method), nullptr);
R ret = (*method)(a...);
PushVar(vm, ret);
});
return 1;
}
};
//
// reference return specialization
//
template <class R> struct SqGlobalProxy<R&> {
template <class... A> static SQInteger Run(HSQUIRRELVM vm, SQInteger idx) {
ArgFwd<A...>{}.Call(vm, idx, [](HSQUIRRELVM vm, A... a) {
typedef R&(*M)(A...);
M* method;
sq_getuserdata(vm, -1, reinterpret_cast<SQUserPointer*>(&method), nullptr);
R& ret = (*method)(a...);
PushVarR(vm, ret);
});
return 1;
}
};
//
// void return specialization
//
template <> struct SqGlobalProxy<void> {
template <class... A> static SQInteger Run(HSQUIRRELVM vm, SQInteger idx) {
ArgFwd<A...>{}.Call(vm, idx, [](HSQUIRRELVM vm, A... a) {
typedef void(*M)(A...);
M* method;
sq_getuserdata(vm, -1, reinterpret_cast<SQUserPointer*>(&method), nullptr);
(*method)(a...);
});
return 0;
}
};
template<bool> struct SqGlobalParamCheck {
static inline bool Invalid(SQInteger top, SQInteger count) {
return top != count;
}
};
template<> struct SqGlobalParamCheck<true> {
static inline bool Invalid(SQInteger top, SQInteger count) {
return top < (count - 1);
}
};
//
// Squirrel Global Functions
//
template <class R> struct SqGlobal {
// Function proxy
template <SQInteger startIdx, bool overloaded, class... A> static SQFUNCTION GetProxy() {
return +[](HSQUIRRELVM vm) -> SQInteger {
#if !defined (SCRAT_NO_ERROR_CHECKING)
if (!SQRAT_CONST_CONDITION(overloaded) &&
SqGlobalParamCheck< ArgFwd<A...>::HASFMT >::Invalid(sq_gettop(vm), startIdx + sizeof...(A))) {
return sq_throwerror(vm, _SC("wrong number of parameters"));
}
#endif
try {
return SqGlobalProxy<R>::template Run<A...>(vm, startIdx);
} catch (const Exception& e) {
return sq_throwerror(vm, e.what());
} catch (...) {
return sq_throwerror(vm, _SC("unknown exception occured"));
}
SQ_UNREACHABLE
};
}
};
//
// reference return specialization
//
template <class R> struct SqGlobal<R&> {
// Function proxy
template <SQInteger startIdx, bool overloaded, class... A> static SQFUNCTION GetProxy() {
return +[](HSQUIRRELVM vm) -> SQInteger {
#if !defined (SCRAT_NO_ERROR_CHECKING)
if (!SQRAT_CONST_CONDITION(overloaded) &&
SqGlobalParamCheck< ArgFwd<A...>::HASFMT >::Invalid(sq_gettop(vm), startIdx + sizeof...(A))) {
return sq_throwerror(vm, _SC("wrong number of parameters"));
}
#endif
try {
return SqGlobalProxy<R&>::template Run<A...>(vm, startIdx);
} catch (const Exception& e) {
return sq_throwerror(vm, e.what());
} catch (...) {
return sq_throwerror(vm, _SC("unknown exception occured"));
}
SQ_UNREACHABLE
};
}
};
//
// void return specialization
//
template <> struct SqGlobal<void> {
// Function proxy
template <SQInteger startIdx, bool overloaded, class... A> static SQFUNCTION GetProxy() {
return +[](HSQUIRRELVM vm) -> SQInteger {
#if !defined (SCRAT_NO_ERROR_CHECKING)
if (!SQRAT_CONST_CONDITION(overloaded) &&
SqGlobalParamCheck< ArgFwd<A...>::HASFMT >::Invalid(sq_gettop(vm), startIdx + sizeof...(A))) {
return sq_throwerror(vm, _SC("wrong number of parameters"));
}
#endif
try {
return SqGlobalProxy<void>::Run<A...>(vm, startIdx);
} catch (const Exception& e) {
return sq_throwerror(vm, e.what());
} catch (...) {
return sq_throwerror(vm, _SC("unknown exception occured"));
}
SQ_UNREACHABLE
};
}
};
// Global Function Resolver
template <class R,class... A> SQFUNCTION SqGlobalFunc(R (* /*method*/)(A...)) {
return SqGlobal<R>::template GetProxy<2, false, A...>();
}
// Global Function Resolver
template <class R,class... A> SQFUNCTION SqGlobalFunc(R& (* /*method*/)(A...)) {
return SqGlobal<R&>::template GetProxy<2, false, A...>();
}
// Member Global Function Resolver
template <class R,class T,class... A> SQFUNCTION SqMemberGlobalFunc(R (* /*method*/)(T, A...)) {
return SqGlobal<R>::template GetProxy<1, false, T, A...>();
}
// Member Global Function Resolver
template <class R,class T,class... A> SQFUNCTION SqMemberGlobalFunc(R& (* /*method*/)(T, A...)) {
return SqGlobal<R&>::template GetProxy<1, false, T, A...>();
}
/// @endcond
}
#endif

View File

@ -1,470 +0,0 @@
//
// SqratMemberMethods: Member Methods
//
//
// Copyright (c) 2009 Brandon Jones
// Copyright 2011 Li-Cheng (Andy) Tai
//
// 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_MEMBER_METHODS_H_)
#define _SCRAT_MEMBER_METHODS_H_
#ifdef SQMOD_PLUGIN_API
#include <SqAPI.h>
#else
#include <squirrelex.h>
#endif // SQMOD_PLUGIN_API
#include "sqratTypes.h"
namespace Sqrat {
/// @cond DEV
//
// Squirrel Member Functions
//
template <class C,class R> struct SqMemberProxy {
template <class... A> static SQInteger Run(HSQUIRRELVM vm) {
ArgFwd<A...>{}.Call(vm, 2, [](HSQUIRRELVM vm, A... a) {
typedef R(C::*M)(A...);
C* inst = Var<C*>(vm, 1).value;
M* methodPtr;
sq_getuserdata(vm, -1, reinterpret_cast<SQUserPointer*>(&methodPtr), nullptr);
M method = *methodPtr;
R ret = (inst->*method)(std::forward< A >(a)...);
PushVar(vm, ret);
});
return 1;
}
template <class... A> static SQInteger RunC(HSQUIRRELVM vm) {
ArgFwd<A...>{}.Call(vm, 2, [](HSQUIRRELVM vm, A... a) {
typedef R(C::*M)(A...) const;
C* inst = Var<C*>(vm, 1).value;
M* methodPtr;
sq_getuserdata(vm, -1, reinterpret_cast<SQUserPointer*>(&methodPtr), nullptr);
M method = *methodPtr;
R ret = (inst->*method)(std::forward< A >(a)...);
PushVar(vm, ret);
});
return 1;
}
};
//
// reference return specialization
//
template <class C, class R> struct SqMemberProxy<C,R&> {
template <class... A> static SQInteger Run(HSQUIRRELVM vm) {
ArgFwd<A...>{}.Call(vm, 2, [](HSQUIRRELVM vm, A... a) {
typedef R&(C::*M)(A...);
C* inst = Var<C*>(vm, 1).value;
M* methodPtr;
sq_getuserdata(vm, -1, reinterpret_cast<SQUserPointer*>(&methodPtr), nullptr);
M method = *methodPtr;
R& ret = (inst->*method)(std::forward< A >(a)...);
PushVarR(vm, ret);
});
return 1;
}
template <class... A> static SQInteger RunC(HSQUIRRELVM vm) {
ArgFwd<A...>{}.Call(vm, 2, [](HSQUIRRELVM vm, A... a) {
typedef R&(C::*M)(A...) const;
C* inst = Var<C*>(vm, 1).value;
M* methodPtr;
sq_getuserdata(vm, -1, reinterpret_cast<SQUserPointer*>(&methodPtr), nullptr);
M method = *methodPtr;
R& ret = (inst->*method)(std::forward< A >(a)...);
PushVarR(vm, ret);
});
return 1;
}
};
//
// void return specialization
//
template <class C> struct SqMemberProxy<C, void> {
template <class... A> static SQInteger Run(HSQUIRRELVM vm) {
ArgFwd<A...>{}.Call(vm, 2, [](HSQUIRRELVM vm, A... a) {
typedef void(C::*M)(A...);
C* inst = Var<C*>(vm, 1).value;
M* methodPtr;
sq_getuserdata(vm, -1, reinterpret_cast<SQUserPointer*>(&methodPtr), nullptr);
M method = *methodPtr;
(inst->*method)(std::forward< A >(a)...);
});
return 0;
}
template <class... A> static SQInteger RunC(HSQUIRRELVM vm) {
ArgFwd<A...>{}.Call(vm, 2, [](HSQUIRRELVM vm, A... a) {
typedef void(C::*M)(A...) const;
C* inst = Var<C*>(vm, 1).value;
M* methodPtr;
sq_getuserdata(vm, -1, reinterpret_cast<SQUserPointer*>(&methodPtr), nullptr);
M method = *methodPtr;
(inst->*method)(std::forward< A >(a)...);
});
return 0;
}
};
template<bool> struct SqMemberParamCheck {
static inline bool Invalid(SQInteger top, SQInteger count) {
return top != count;
}
};
template<> struct SqMemberParamCheck<true> {
static inline bool Invalid(SQInteger top, SQInteger count) {
return top < count;
}
};
//
// Squirrel Member Functions
//
template <class C,class R> struct SqMember {
// Function proxy
template <bool overloaded, class... A> static SQFUNCTION GetProxy() {
return +[](HSQUIRRELVM vm) -> SQInteger {
#if !defined (SCRAT_NO_ERROR_CHECKING)
if (!SQRAT_CONST_CONDITION(overloaded) &&
SqGlobalParamCheck< ArgFwd<A...>::HASFMT >::Invalid(sq_gettop(vm), 2 + sizeof...(A))) {
return sq_throwerror(vm, _SC("wrong number of parameters"));
}
#endif
try {
return SqMemberProxy<C, R>:: template Run<A...>(vm);
} catch (const Exception& e) {
return sq_throwerror(vm, e.what());
} catch (...) {
return sq_throwerror(vm, _SC("unknown exception occured"));
}
SQ_UNREACHABLE
};
}
// Function proxy
template <bool overloaded, class... A> static SQFUNCTION GetProxyC() {
return +[](HSQUIRRELVM vm) -> SQInteger {
#if !defined (SCRAT_NO_ERROR_CHECKING)
if (!SQRAT_CONST_CONDITION(overloaded) &&
SqGlobalParamCheck< ArgFwd<A...>::HASFMT >::Invalid(sq_gettop(vm), 2 + sizeof...(A))) {
return sq_throwerror(vm, _SC("wrong number of parameters"));
}
#endif
try {
return SqMemberProxy<C,R>::template RunC<A...>(vm);
} catch (const Exception& e) {
return sq_throwerror(vm, e.what());
} catch (...) {
return sq_throwerror(vm, _SC("unknown exception occured"));
}
SQ_UNREACHABLE
};
}
};
//
// reference return specialization
//
template <class C, class R> struct SqMember<C,R&> {
// Function proxy
template <bool overloaded, class... A> static SQFUNCTION GetProxy() {
return +[](HSQUIRRELVM vm) -> SQInteger {
#if !defined (SCRAT_NO_ERROR_CHECKING)
if (!SQRAT_CONST_CONDITION(overloaded) &&
SqGlobalParamCheck< ArgFwd<A...>::HASFMT >::Invalid(sq_gettop(vm), 2 + sizeof...(A))) {
return sq_throwerror(vm, _SC("wrong number of parameters"));
}
#endif
try {
return SqMemberProxy<C,R&>::template Run<A...>(vm);
} catch (const Exception& e) {
return sq_throwerror(vm, e.what());
} catch (...) {
return sq_throwerror(vm, _SC("unknown exception occured"));
}
SQ_UNREACHABLE
};
}
// Function proxy
template <bool overloaded, class... A> static SQFUNCTION GetProxyC() {
return +[](HSQUIRRELVM vm) -> SQInteger {
#if !defined (SCRAT_NO_ERROR_CHECKING)
if (!SQRAT_CONST_CONDITION(overloaded) &&
SqGlobalParamCheck< ArgFwd<A...>::HASFMT >::Invalid(sq_gettop(vm), 2 + sizeof...(A))) {
return sq_throwerror(vm, _SC("wrong number of parameters"));
}
#endif
try {
return SqMemberProxy<C,R&>::template RunC<A...>(vm);
} catch (const Exception& e) {
return sq_throwerror(vm, e.what());
} catch (...) {
return sq_throwerror(vm, _SC("unknown exception occured"));
}
SQ_UNREACHABLE
};
}
};
//
// void return specialization
//
template <class C> struct SqMember<C, void> {
// Function proxy
template <bool overloaded, class... A> static SQFUNCTION GetProxy() {
return +[](HSQUIRRELVM vm) -> SQInteger {
#if !defined (SCRAT_NO_ERROR_CHECKING)
if (!SQRAT_CONST_CONDITION(overloaded) &&
SqGlobalParamCheck< ArgFwd<A...>::HASFMT >::Invalid(sq_gettop(vm), 2 + sizeof...(A))) {
return sq_throwerror(vm, _SC("wrong number of parameters"));
}
#endif
try {
return SqMemberProxy<C, void>::template Run<A...>(vm);
} catch (const Exception& e) {
return sq_throwerror(vm, e.what());
} catch (...) {
return sq_throwerror(vm, _SC("unknown exception occured"));
}
SQ_UNREACHABLE
};
}
// Function proxy
template <bool overloaded, class... A> static SQFUNCTION GetProxyC() {
return +[](HSQUIRRELVM vm) -> SQInteger {
#if !defined (SCRAT_NO_ERROR_CHECKING)
if (!SQRAT_CONST_CONDITION(overloaded) &&
SqGlobalParamCheck< ArgFwd<A...>::HASFMT >::Invalid(sq_gettop(vm), 2 + sizeof...(A))) {
return sq_throwerror(vm, _SC("wrong number of parameters"));
}
#endif
try {
return SqMemberProxy<C,void>::template RunC<A...>(vm);
} catch (const Exception& e) {
return sq_throwerror(vm, e.what());
} catch (...) {
return sq_throwerror(vm, _SC("unknown exception occured"));
}
SQ_UNREACHABLE
};
}
};
// Member Function Resolver
template <class C, class R,class... A> SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A...)) {
return SqMember<C,R>::template GetProxy<false, A...>();
}
// Member Function Resolver
template <class C, class R,class... A> SQFUNCTION SqMemberFunc(R (C::* /*method*/)(A...) const) {
return SqMember<C,R>::template GetProxyC<false, A...>();
}
// Member Function Resolver
template <class C, class R,class... A> SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A...)) {
return SqMember<C,R&>::template GetProxy<false, A...>();
}
// Member Function Resolver
template <class C, class R,class... A> SQFUNCTION SqMemberFunc(R& (C::* /*method*/)(A...) const) {
return SqMember<C,R&>::template GetProxyC<false, A...>();
}
//
// Variable Get
//
template <class C, class V>
inline SQInteger sqDefaultGet(HSQUIRRELVM vm) {
C* ptr;
SQTRY()
ptr = Var<C*>(vm, 1).value;
SQCATCH_NOEXCEPT(vm) {
SQCLEAR(vm); // clear the previous error
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
}
SQCATCH(vm) {
return sq_throwerror(vm, SQWHAT(vm));
}
typedef V C::*M;
M* memberPtr = nullptr;
sq_getuserdata(vm, -1, (SQUserPointer*)&memberPtr, nullptr); // Get Member...
M member = *memberPtr;
PushVarR(vm, ptr->*member);
return 1;
}
template <class C, class V>
inline SQInteger sqStaticGet(HSQUIRRELVM vm) {
typedef V *M;
M* memberPtr = nullptr;
sq_getuserdata(vm, -1, (SQUserPointer*)&memberPtr, nullptr); // Get Member...
M member = *memberPtr;
PushVarR(vm, *member);
return 1;
}
inline SQInteger sqVarGet(HSQUIRRELVM vm) {
// Find the get method in the get table
sq_push(vm, 2);
#if !defined (SCRAT_NO_ERROR_CHECKING)
if (SQ_FAILED(sq_rawget(vm, -2))) {
#if (SQUIRREL_VERSION_NUMBER>= 200) && (SQUIRREL_VERSION_NUMBER < 300) // Squirrel 2.x
return sq_throwerror(vm, _SC("member variable not found"));
#else // Squirrel 3.x
sq_pushnull(vm);
return sq_throwobject(vm);
#endif
}
#else
sq_rawget(vm, -2);
#endif
// push 'this'
sq_push(vm, 1);
// Call the getter
#if !defined (SCRAT_NO_ERROR_CHECKING)
SQRESULT result = sq_call(vm, 1, true, ErrorHandling::IsEnabled());
if (SQ_FAILED(result)) {
return sq_throwerror(vm, LastErrorString(vm).c_str());
}
#else
sq_call(vm, 1, true, ErrorHandling::IsEnabled());
#endif
return 1;
}
//
// Variable Set
//
template <class C, class V>
inline SQInteger sqDefaultSet(HSQUIRRELVM vm) {
C* ptr;
SQTRY()
ptr = Var<C*>(vm, 1).value;
SQCATCH_NOEXCEPT(vm) {
SQCLEAR(vm); // clear the previous error
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
}
SQCATCH(vm) {
return sq_throwerror(vm, SQWHAT(vm));
}
typedef V C::*M;
M* memberPtr = nullptr;
sq_getuserdata(vm, -1, (SQUserPointer*)&memberPtr, nullptr); // Get Member...
M member = *memberPtr;
SQTRY()
if (is_pointer<V>::value || is_reference<V>::value) {
ptr->*member = Var<V>(vm, 2).value;
} else {
ptr->*member = Var<const V&>(vm, 2).value;
}
SQCATCH_NOEXCEPT(vm) {
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
}
SQCATCH(vm) {
return sq_throwerror(vm, SQWHAT(vm));
}
return 0;
}
template <class C, class V>
inline SQInteger sqStaticSet(HSQUIRRELVM vm) {
typedef V *M;
M* memberPtr = nullptr;
sq_getuserdata(vm, -1, (SQUserPointer*)&memberPtr, nullptr); // Get Member...
M member = *memberPtr;
SQTRY()
if (is_pointer<V>::value || is_reference<V>::value) {
*member = Var<V>(vm, 2).value;
} else {
*member = Var<const V&>(vm, 2).value;
}
SQCATCH_NOEXCEPT(vm) {
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
}
SQCATCH(vm) {
return sq_throwerror(vm, SQWHAT(vm));
}
return 0;
}
inline SQInteger sqVarSet(HSQUIRRELVM vm) {
// Find the set method in the set table
sq_push(vm, 2);
#if !defined (SCRAT_NO_ERROR_CHECKING)
if (SQ_FAILED(sq_rawget(vm, -2))) {
#if (SQUIRREL_VERSION_NUMBER>= 200) && (SQUIRREL_VERSION_NUMBER < 300) // Squirrel 2.x
return sq_throwerror(vm, _SC("member variable not found"));
#else // Squirrel 3.x
sq_pushnull(vm);
return sq_throwobject(vm);
#endif
}
#else
sq_rawget(vm, -2);
#endif
// push 'this'
sq_push(vm, 1);
sq_push(vm, 3);
// Call the setter
#if !defined (SCRAT_NO_ERROR_CHECKING)
SQRESULT result = sq_call(vm, 2, false, ErrorHandling::IsEnabled());
if (SQ_FAILED(result)) {
return sq_throwerror(vm, LastErrorString(vm).c_str());
}
#else
sq_call(vm, 2, false, ErrorHandling::IsEnabled());
#endif
return 0;
}
/// @endcond
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,298 +0,0 @@
//
// SqratOverloadMethods: Overload Methods
//
//
// 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_OVERLOAD_METHODS_H_)
#define _SQRAT_OVERLOAD_METHODS_H_
#ifdef SQMOD_PLUGIN_API
#include <SqAPI.h>
#else
#include <squirrelex.h>
#endif // SQMOD_PLUGIN_API
#include "sqratTypes.h"
#include "sqratUtil.h"
#include "sqratGlobalMethods.h"
#include "sqratMemberMethods.h"
namespace Sqrat {
/// @cond DEV
//
// Overload name generator
//
class SqOverloadName {
public:
static void Get(const SQChar* name, int args, string & out) {
SQChar buf[16] = {'_', 'o'};
unsigned l = I32ToA(args, &buf[2]);
out.append(buf, l+2);
out.push_back('_');
out.append(name);
}
static string Get(const SQChar* name, int args) {
string out;
out.reserve(15);
Get(name, args, out);
return out;
}
};
//
// Don't include the overloaded call forwarder into the templated class
// to avoid duplicating code that doesn't need to be specialized.
//
inline SQInteger OverloadExecutionForwarder(HSQUIRRELVM vm) {
const SQInteger top = sq_gettop(vm);
// Get the argument count
const int argCount = static_cast<int>(top - 2);
// Subtract environment and base name in free variable^
const SQChar* funcName;
SQInteger funcNameSize;
// Get the un-mangled function name (free variable)
sq_getstringandsize(vm, -1, &funcName, &funcNameSize);
// Generate the overload mangled name
string overloadName;
overloadName.reserve(funcNameSize+5);
SqOverloadName::Get(funcName, argCount, overloadName);
// Pop the un-mangled closure name from the stack so we can replace it later
sq_poptop(vm); // `funcName` becomes invalid after this
// Push the overload mangled name on the stack
sq_pushstring(vm, overloadName.c_str(), static_cast<SQInteger>(overloadName.size()));
// Lookup the proper overload and get it on the stack
#if !defined (SCRAT_NO_ERROR_CHECKING)
if (SQ_FAILED(sq_get(vm, 1))) {
sq_settop(vm, top); // keep the stack size intact
return sq_throwerror(vm, _SC("wrong number of parameters"));
}
#else
sq_get(vm, 1);
#endif
SQFUNCTION f = nullptr;
// Get the native closure pointer that we must invoke
SQRESULT res = sq_getnativeclosurepointer(vm, -1, &f);
if (SQ_FAILED(res)) {
return res;
// Make sure a native closure pointer is available
} else if (!f) {
return sq_throwerror(vm, _SC("unable to acquire the proper overload closure"));
}
// Attempt to get the free variable containing the native closure pointer on the stack
sq_getonefreevariable(vm, 0);
// This is simply a hack to implement a direct call and gain some performance
// Since both closures expect a free variable we simply replace the free variable
// containing closure name with the free variable containing the closure pointer
sq_settop(vm, top); // keep the stack size intact before invoking the overload
// Perform a direct call and return the result back to the caller
return f(vm);
}
//
// Don't include the overloaded call forwarder into the templated class
// to avoid duplicating code that doesn't need to be specialized.
//
inline SQInteger OverloadConstructionForwarder(HSQUIRRELVM vm) {
const SQInteger top = sq_gettop(vm);
// Get the argument count
const int argCount = static_cast<int>(top - 2);
// Subtract environment and base name in free variable^
const SQChar* funcName;
SQInteger funcNameSize;
// Get the un-mangled function name (free variable)
sq_getstringandsize(vm, -1, &funcName, &funcNameSize);
// Generate the overload mangled name
string overloadName;
overloadName.reserve(funcNameSize+5);
SqOverloadName::Get(funcName, argCount, overloadName);
// Push the overload mangled name on the stack
sq_pushstring(vm, overloadName.c_str(), static_cast<SQInteger>(overloadName.size()));
// Lookup the proper overload and get it on the stack
#if !defined (SCRAT_NO_ERROR_CHECKING)
if (SQ_FAILED(sq_get(vm, 1))) {
sq_settop(vm, top); // keep the stack size intact
return sq_throwerrorf(vm, _SC("wrong number of parameters. no such constructor overload: `%s`"), overloadName.data());
}
#else
sq_get(vm, 1);
#endif
SQFUNCTION f = nullptr;
// Get the native closure pointer that we must invoke
SQRESULT res = sq_getnativeclosurepointer(vm, -1, &f);
if (SQ_FAILED(res)) {
return res;
// Make sure a native closure pointer is available
} else if (!f) {
return sq_throwerror(vm, _SC("unable to acquire the proper overload closure"));
}
// Restore the stack size by removing the overload closure object
sq_poptop(vm);
// Pop the un-mangled closure name from the stack
// The constructor doesn't expect any free variables
//sq_poptop(vm); // `funcName` becomes invalid after this
// Perform a direct call and store the result
SQRESULT r = f(vm);
// Keep the stack size intact before leaving
sq_settop(vm, top);
// Return the result back to the caller
return r;
}
//
// Squirrel Overload Functions
//
template <class R>
class SqOverload {
public:
static SQInteger Func(HSQUIRRELVM vm) {
return OverloadExecutionForwarder(vm);
}
};
//
// void return specialization
//
template <>
class SqOverload<void> {
public:
static SQInteger Func(HSQUIRRELVM vm) {
return OverloadExecutionForwarder(vm);
}
};
// Global Overloaded Function Resolver
template <class R,class... A> SQFUNCTION SqGlobalOverloadedFunc(R (* /*method*/)(A...)) {
return SqGlobal<R>::template GetProxy<2, true, A...>();
}
// Global Overloaded Function Resolver
template <class R,class... A> SQFUNCTION SqGlobalOverloadedFunc(R& (* /*method*/)(A...)) {
return SqGlobal<R&>::template GetProxy<2, true, A...>();
}
// Member Global Overloaded Function Resolver
template <class R,class T,class... A> SQFUNCTION SqMemberGlobalOverloadedFunc(R (* /*method*/)(T, A...)) {
return SqGlobal<R>::template GetProxy<1, true, T, A...>();
}
// Member Global Overloaded Function Resolver
template <class R,class T,class... A> SQFUNCTION SqMemberGlobalOverloadedFunc(R& (* /*method*/)(T, A...)) {
return SqGlobal<R&>::template GetProxy<1, true, T, A...>();
}
// Member Overloaded Function Resolver
template <class C, class R,class... A> SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A...)) {
return SqMember<C,R>::template GetProxy<true, A...>();
}
// Member Overloaded Function Resolver
template <class C, class R,class... A> SQFUNCTION SqMemberOverloadedFunc(R (C::* /*method*/)(A...) const) {
return SqMember<C,R>::template GetProxyC<true, A...>();
}
// Member Overloaded Function Resolver
template <class C, class R,class... A> SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A...)) {
return SqMember<C,R&>::template GetProxy<true, A...>();
}
// Member Overloaded Function Resolver
template <class C, class R,class... A> SQFUNCTION SqMemberOverloadedFunc(R& (C::* /*method*/)(A...) const) {
return SqMember<C,R&>::template GetProxyC<true, A...>();
}
//
// Overload handler resolver
//
template <class R>
inline SQFUNCTION SqOverloadFunc(R (* /*method*/)) {
return &SqOverload<R>::Func;
}
template <class R, class... A>
inline SQFUNCTION SqOverloadFunc(R (* /*method*/)(A...)) {
return &SqOverload<R>::Func;
}
template <class C, class R>
inline SQFUNCTION SqOverloadFunc(R (C::* /*method*/)) {
return &SqOverload<R>::Func;
}
template <class C, class R>
inline SQFUNCTION SqOverloadFunc(R (C::* /*method*/)() const ) {
return &SqOverload<R>::Func;
}
template <class C, class R, class... A>
inline SQFUNCTION SqOverloadFunc(R (C::* /*method*/)(A...) ) {
return &SqOverload<R>::Func;
}
template <class C, class R, class... A>
inline SQFUNCTION SqOverloadFunc(R (C::* /*method*/)(A...) const ) {
return &SqOverload<R>::Func;
}
//
// Query argument count
//
template <class R, class... Args>
inline int SqGetArgCount(R (* /*method*/)(Args...)) {
return sizeof...(Args);
}
//
// Query member function argument count
//
template <class C, class R, class... Args>
inline int SqGetArgCount(R (C::* /*method*/)(Args...)) {
return sizeof...(Args);
}
//
// Query const member function argument count
//
template <class C, class R, class... Args>
inline int SqGetArgCount(R (C::* /*method*/)(Args...) const) {
return sizeof...(Args);
}
/// @endcond
}
#endif

View File

@ -1,248 +0,0 @@
//
// 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_
#ifdef SQMOD_PLUGIN_API
#include <SqAPI.h>
#else
#include <squirrelex.h>
#include <sqstdio.h>
#endif // SQMOD_PLUGIN_API
#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

View File

@ -1,704 +0,0 @@
//
// 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_
#ifdef SQMOD_PLUGIN_API
#include <SqAPI.h>
#else
#include <squirrelex.h>
#endif // SQMOD_PLUGIN_API
#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 an Object that already exists
///
/// \param obj An Object that should already represent a Squirrel table
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TableBase(Object&& obj) : Object(std::move(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) {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy constructor
///
/// \param st TableBase to copy
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TableBase(const TableBase& st) : Object(st) {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Move constructor
///
/// \param st TableBase to move
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TableBase(TableBase&& st) : Object(std::move(st)) {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Assignment operator
///
/// \param st TableBase to copy
///
/// \return The TableBase itself
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TableBase& operator=(const TableBase& st) {
Object::operator = (st);
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Assignment operator
///
/// \param st TableBase to move
///
/// \return The TableBase itself
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TableBase& operator=(TableBase&& st) {
Object::operator = (std::move(st));
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 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 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, LightObj& 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);
// Set the closure name (for debug purposes)
sq_setnativeclosurename(vm, -1, name);
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 with formatting support
///
/// \param name The key in the table being assigned a value
/// \param method Function that is being placed in the Table
///
/// \tparam F Type of function (only define this if you need to choose a certain template specialization or overload)
///
/// \return The Table itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class F>
TableBase& FmtFunc(const SQChar* name, F method) {
BindFunc(name, &method, sizeof(method), 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 an Object that already exists
///
/// \param obj An Object that should already represent a Squirrel table
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Table(Object&& obj) : TableBase(std::move(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) {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Construct the TableBase with an initial capacity
///
/// \param v VM to create the Table in
/// \param c The initial capacity of the created table
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Table(HSQUIRRELVM v, SQInteger c) : TableBase(v) {
sq_newtableex(vm, c);
sq_getstackobj(vm,-1,&obj);
sq_addref(vm, &obj);
sq_pop(vm,1);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy constructor
///
/// \param st Table to copy
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Table(const Table& st) : TableBase(st) {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Move constructor
///
/// \param st Table to move
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Table(Table&& st) : TableBase(std::move(st)) {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Assignment operator
///
/// \param st Table to copy
///
/// \return The Table itself
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Table& operator=(const Table& st) {
TableBase::operator = (st);
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Assignment operator
///
/// \param st Table to move
///
/// \return The Table itself
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Table& operator=(Table&& st) {
TableBase::operator = (std::move(st));
return *this;
}
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +0,0 @@
/* see copyright notice in squirrel.h */
#ifndef _SQSTD_AUXLIB_H_
#define _SQSTD_AUXLIB_H_
#ifdef __cplusplus
extern "C" {
#endif
SQUIRREL_API void sqstd_seterrorhandlers(HSQUIRRELVM v);
SQUIRREL_API void sqstd_printcallstack(HSQUIRRELVM v);
SQUIRREL_API SQRESULT sqstd_throwerrorf(HSQUIRRELVM v,const SQChar *err,...);
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /* _SQSTD_AUXLIB_H_ */

View File

@ -1,20 +0,0 @@
/* see copyright notice in squirrel.h */
#ifndef _SQSTDBLOB_H_
#define _SQSTDBLOB_H_
#ifdef __cplusplus
extern "C" {
#endif
SQUIRREL_API SQUserPointer sqstd_createblob(HSQUIRRELVM v, SQInteger size);
SQUIRREL_API SQRESULT sqstd_getblob(HSQUIRRELVM v,SQInteger idx,SQUserPointer *ptr);
SQUIRREL_API SQInteger sqstd_getblobsize(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sqstd_register_bloblib(HSQUIRRELVM v);
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*_SQSTDBLOB_H_*/

View File

@ -1,54 +0,0 @@
/* see copyright notice in squirrel.h */
#ifndef _SQSTDIO_H_
#define _SQSTDIO_H_
#ifdef __cplusplus
#define SQSTD_STREAM_TYPE_TAG 0x80000000
struct SQStream {
virtual ~SQStream() {}
virtual SQInteger Read(void *buffer, SQInteger size) = 0;
virtual SQInteger Write(void *buffer, SQInteger size) = 0;
virtual SQInteger Flush() = 0;
virtual SQInteger Tell() = 0;
virtual SQInteger Len() = 0;
virtual SQInteger Seek(SQInteger offset, SQInteger origin) = 0;
virtual bool IsValid() = 0;
virtual bool EOS() = 0;
};
extern "C" {
#endif
#define SQ_SEEK_CUR 0
#define SQ_SEEK_END 1
#define SQ_SEEK_SET 2
typedef void* SQFILE;
SQUIRREL_API SQFILE sqstd_fopen(const SQChar *,const SQChar *);
SQUIRREL_API SQInteger sqstd_fread(SQUserPointer, SQInteger, SQInteger, SQFILE);
SQUIRREL_API SQInteger sqstd_fwrite(const SQUserPointer, SQInteger, SQInteger, SQFILE);
SQUIRREL_API SQInteger sqstd_fseek(SQFILE , SQInteger , SQInteger);
SQUIRREL_API SQInteger sqstd_ftell(SQFILE);
SQUIRREL_API SQInteger sqstd_fflush(SQFILE);
SQUIRREL_API SQInteger sqstd_fclose(SQFILE);
SQUIRREL_API SQInteger sqstd_feof(SQFILE);
SQUIRREL_API SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own);
SQUIRREL_API SQRESULT sqstd_getfile(HSQUIRRELVM v, SQInteger idx, SQFILE *file);
//compiler helpers
SQUIRREL_API SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror);
SQUIRREL_API SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror);
SQUIRREL_API SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename);
SQUIRREL_API SQRESULT sqstd_register_iolib(HSQUIRRELVM v);
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*_SQSTDIO_H_*/

View File

@ -1,15 +0,0 @@
/* see copyright notice in squirrel.h */
#ifndef _SQSTD_MATH_H_
#define _SQSTD_MATH_H_
#ifdef __cplusplus
extern "C" {
#endif
SQUIRREL_API SQRESULT sqstd_register_mathlib(HSQUIRRELVM v);
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*_SQSTD_MATH_H_*/

View File

@ -1,35 +0,0 @@
/* see copyright notice in squirrel.h */
#ifndef _SQSTD_STRING_H_
#define _SQSTD_STRING_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned int SQRexBool;
typedef struct SQRex SQRex;
typedef struct {
const SQChar *begin;
SQInteger len;
} SQRexMatch;
SQUIRREL_API SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error);
SQUIRREL_API void sqstd_rex_free(SQRex *exp);
SQUIRREL_API SQBool sqstd_rex_match(SQRex* exp,const SQChar* text);
SQUIRREL_API SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end);
SQUIRREL_API SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end);
SQUIRREL_API SQInteger sqstd_rex_getsubexpcount(SQRex* exp);
SQUIRREL_API SQBool sqstd_rex_getsubexp(SQRex* exp, SQInteger n, SQRexMatch *subexp);
SQUIRREL_API SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen,SQChar **output);
SQUIRREL_API void sqstd_pushstringf(HSQUIRRELVM v,const SQChar *s,...);
SQUIRREL_API SQRESULT sqstd_register_stringlib(HSQUIRRELVM v);
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*_SQSTD_STRING_H_*/

View File

@ -1,15 +0,0 @@
/* see copyright notice in squirrel.h */
#ifndef _SQSTD_SYSTEMLIB_H_
#define _SQSTD_SYSTEMLIB_H_
#ifdef __cplusplus
extern "C" {
#endif
SQUIRREL_API SQInteger sqstd_register_systemlib(HSQUIRRELVM v);
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /* _SQSTD_SYSTEMLIB_H_ */

View File

@ -1,416 +0,0 @@
/*
Copyright (c) 2003-2017 Alberto Demichelis
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef _SQUIRREL_H_
#define _SQUIRREL_H_
#ifdef _SQ_CONFIG_INCLUDE
#include _SQ_CONFIG_INCLUDE
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifndef SQUIRREL_API
#define SQUIRREL_API extern
#endif
#if (defined(_WIN64) || defined(_LP64))
#ifndef _SQ64
#define _SQ64
#endif
#endif
#define SQTrue (1)
#define SQFalse (0)
struct SQVM;
struct SQTable;
struct SQArray;
struct SQString;
struct SQClosure;
struct SQGenerator;
struct SQNativeClosure;
struct SQUserData;
struct SQFunctionProto;
struct SQRefCounted;
struct SQClass;
struct SQInstance;
struct SQDelegable;
struct SQOuter;
#ifdef _UNICODE
#define SQUNICODE
#endif
#include "sqconfig.h"
#define SQUIRREL_VERSION _SC("Squirrel 3.1 stable")
#define SQUIRREL_COPYRIGHT _SC("Copyright (C) 2003-2017 Alberto Demichelis")
#define SQUIRREL_AUTHOR _SC("Alberto Demichelis")
#define SQUIRREL_VERSION_NUMBER 310
#define SQ_VMSTATE_IDLE 0
#define SQ_VMSTATE_RUNNING 1
#define SQ_VMSTATE_SUSPENDED 2
#define SQUIRREL_EOB 0
#define SQ_BYTECODE_STREAM_TAG 0xFAFA
#define SQOBJECT_REF_COUNTED 0x08000000
#define SQOBJECT_NUMERIC 0x04000000
#define SQOBJECT_DELEGABLE 0x02000000
#define SQOBJECT_CANBEFALSE 0x01000000
#define SQ_MATCHTYPEMASKSTRING (-99999)
#define _RT_MASK 0x00FFFFFF
#define _RAW_TYPE(type) (type&_RT_MASK)
#define _RT_NULL 0x00000001
#define _RT_INTEGER 0x00000002
#define _RT_FLOAT 0x00000004
#define _RT_BOOL 0x00000008
#define _RT_STRING 0x00000010
#define _RT_TABLE 0x00000020
#define _RT_ARRAY 0x00000040
#define _RT_USERDATA 0x00000080
#define _RT_CLOSURE 0x00000100
#define _RT_NATIVECLOSURE 0x00000200
#define _RT_GENERATOR 0x00000400
#define _RT_USERPOINTER 0x00000800
#define _RT_THREAD 0x00001000
#define _RT_FUNCPROTO 0x00002000
#define _RT_CLASS 0x00004000
#define _RT_INSTANCE 0x00008000
#define _RT_WEAKREF 0x00010000
#define _RT_OUTER 0x00020000
typedef enum tagSQObjectType{
OT_NULL = (_RT_NULL|SQOBJECT_CANBEFALSE),
OT_INTEGER = (_RT_INTEGER|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE),
OT_FLOAT = (_RT_FLOAT|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE),
OT_BOOL = (_RT_BOOL|SQOBJECT_CANBEFALSE),
OT_STRING = (_RT_STRING|SQOBJECT_REF_COUNTED),
OT_TABLE = (_RT_TABLE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE),
OT_ARRAY = (_RT_ARRAY|SQOBJECT_REF_COUNTED),
OT_USERDATA = (_RT_USERDATA|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE),
OT_CLOSURE = (_RT_CLOSURE|SQOBJECT_REF_COUNTED),
OT_NATIVECLOSURE = (_RT_NATIVECLOSURE|SQOBJECT_REF_COUNTED),
OT_GENERATOR = (_RT_GENERATOR|SQOBJECT_REF_COUNTED),
OT_USERPOINTER = _RT_USERPOINTER,
OT_THREAD = (_RT_THREAD|SQOBJECT_REF_COUNTED) ,
OT_FUNCPROTO = (_RT_FUNCPROTO|SQOBJECT_REF_COUNTED), //internal usage only
OT_CLASS = (_RT_CLASS|SQOBJECT_REF_COUNTED),
OT_INSTANCE = (_RT_INSTANCE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE),
OT_WEAKREF = (_RT_WEAKREF|SQOBJECT_REF_COUNTED),
OT_OUTER = (_RT_OUTER|SQOBJECT_REF_COUNTED) //internal usage only
}SQObjectType;
#define ISREFCOUNTED(t) (t&SQOBJECT_REF_COUNTED)
typedef union tagSQObjectValue
{
struct SQTable *pTable;
struct SQArray *pArray;
struct SQClosure *pClosure;
struct SQOuter *pOuter;
struct SQGenerator *pGenerator;
struct SQNativeClosure *pNativeClosure;
struct SQString *pString;
struct SQUserData *pUserData;
SQInteger nInteger;
SQFloat fFloat;
SQUserPointer pUserPointer;
struct SQFunctionProto *pFunctionProto;
struct SQRefCounted *pRefCounted;
struct SQDelegable *pDelegable;
struct SQVM *pThread;
struct SQClass *pClass;
struct SQInstance *pInstance;
struct SQWeakRef *pWeakRef;
SQRawObjectVal raw;
}SQObjectValue;
typedef struct tagSQObject
{
SQObjectType _type;
SQObjectValue _unVal;
}SQObject;
typedef struct tagSQMemberHandle{
SQBool _static;
SQInteger _index;
}SQMemberHandle;
typedef struct tagSQStackInfos{
const SQChar* funcname;
const SQChar* source;
SQInteger line;
}SQStackInfos;
typedef struct SQVM* HSQUIRRELVM;
typedef SQObject HSQOBJECT;
typedef SQMemberHandle HSQMEMBERHANDLE;
typedef SQInteger (*SQFUNCTION)(HSQUIRRELVM);
typedef SQInteger (*SQRELEASEHOOK)(SQUserPointer,SQInteger size);
typedef void (*SQCOMPILERERROR)(HSQUIRRELVM,const SQChar * /*desc*/,const SQChar * /*source*/,SQInteger /*line*/,SQInteger /*column*/);
typedef void (*SQPRINTFUNCTION)(HSQUIRRELVM,const SQChar * ,...);
typedef void (*SQDEBUGHOOK)(HSQUIRRELVM /*v*/, SQInteger /*type*/, const SQChar * /*sourcename*/, SQInteger /*line*/, const SQChar * /*funcname*/);
typedef SQInteger (*SQWRITEFUNC)(SQUserPointer,SQUserPointer,SQInteger);
typedef SQInteger (*SQREADFUNC)(SQUserPointer,SQUserPointer,SQInteger);
typedef SQInteger (*SQLEXREADFUNC)(SQUserPointer);
typedef struct tagSQRegFunction{
const SQChar *name;
SQFUNCTION f;
SQInteger nparamscheck;
const SQChar *typemask;
}SQRegFunction;
typedef struct tagSQFunctionInfo {
SQUserPointer funcid;
const SQChar *name;
const SQChar *source;
SQInteger line;
}SQFunctionInfo;
#ifndef SQMOD_PLUGIN_API
/*vm*/
SQUIRREL_API HSQUIRRELVM sq_open(SQInteger initialstacksize);
SQUIRREL_API HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize);
SQUIRREL_API void sq_seterrorhandler(HSQUIRRELVM v);
SQUIRREL_API void sq_close(HSQUIRRELVM v);
SQUIRREL_API void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p);
SQUIRREL_API SQUserPointer sq_getforeignptr(HSQUIRRELVM v);
SQUIRREL_API void sq_setsharedforeignptr(HSQUIRRELVM v,SQUserPointer p);
SQUIRREL_API SQUserPointer sq_getsharedforeignptr(HSQUIRRELVM v);
SQUIRREL_API void sq_setvmreleasehook(HSQUIRRELVM v,SQRELEASEHOOK hook);
SQUIRREL_API SQRELEASEHOOK sq_getvmreleasehook(HSQUIRRELVM v);
SQUIRREL_API void sq_setsharedreleasehook(HSQUIRRELVM v,SQRELEASEHOOK hook);
SQUIRREL_API SQRELEASEHOOK sq_getsharedreleasehook(HSQUIRRELVM v);
SQUIRREL_API void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc,SQPRINTFUNCTION errfunc);
SQUIRREL_API SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v);
SQUIRREL_API SQPRINTFUNCTION sq_geterrorfunc(HSQUIRRELVM v);
SQUIRREL_API SQRESULT sq_suspendvm(HSQUIRRELVM v);
SQUIRREL_API SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool resumedret,SQBool retval,SQBool raiseerror,SQBool throwerror);
SQUIRREL_API SQInteger sq_getvmstate(HSQUIRRELVM v);
SQUIRREL_API SQInteger sq_getversion();
/*compiler*/
SQUIRREL_API SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror);
SQUIRREL_API SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,SQInteger size,const SQChar *sourcename,SQBool raiseerror);
SQUIRREL_API void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable);
SQUIRREL_API void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable);
SQUIRREL_API void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f);
/*stack operations*/
SQUIRREL_API void sq_push(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API void sq_pop(HSQUIRRELVM v,SQInteger nelemstopop);
SQUIRREL_API void sq_poptop(HSQUIRRELVM v);
SQUIRREL_API void sq_remove(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQInteger sq_gettop(HSQUIRRELVM v);
SQUIRREL_API void sq_settop(HSQUIRRELVM v,SQInteger newtop);
SQUIRREL_API SQRESULT sq_reservestack(HSQUIRRELVM v,SQInteger nsize);
SQUIRREL_API SQInteger sq_cmp(HSQUIRRELVM v);
SQUIRREL_API void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx);
/*object creation handling*/
SQUIRREL_API SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size);
SQUIRREL_API void sq_newtable(HSQUIRRELVM v);
SQUIRREL_API void sq_newtableex(HSQUIRRELVM v,SQInteger initialcapacity);
SQUIRREL_API void sq_newarray(HSQUIRRELVM v,SQInteger size);
SQUIRREL_API void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars);
SQUIRREL_API SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask);
SQUIRREL_API SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_setclosureroot(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_getclosureroot(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len);
SQUIRREL_API void sq_pushfloat(HSQUIRRELVM v,SQFloat f);
SQUIRREL_API void sq_pushinteger(HSQUIRRELVM v,SQInteger n);
SQUIRREL_API void sq_pushbool(HSQUIRRELVM v,SQBool b);
SQUIRREL_API void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p);
SQUIRREL_API void sq_pushnull(HSQUIRRELVM v);
SQUIRREL_API void sq_pushthread(HSQUIRRELVM v, HSQUIRRELVM thread);
SQUIRREL_API SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_typeof(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQInteger sq_getsize(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQHash sq_gethash(HSQUIRRELVM v, SQInteger idx);
SQUIRREL_API SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQBool sq_instanceof(HSQUIRRELVM v);
SQUIRREL_API SQRESULT sq_tostring(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b);
SQUIRREL_API SQRESULT sq_getstringandsize(HSQUIRRELVM v,SQInteger idx,const SQChar **c,SQInteger *size);
SQUIRREL_API SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c);
SQUIRREL_API SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i);
SQUIRREL_API SQRESULT sq_getfloat(HSQUIRRELVM v,SQInteger idx,SQFloat *f);
SQUIRREL_API SQRESULT sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool *b);
SQUIRREL_API SQRESULT sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread);
SQUIRREL_API SQRESULT sq_getuserpointer(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p);
SQUIRREL_API SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag);
SQUIRREL_API SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag);
SQUIRREL_API SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag);
SQUIRREL_API void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook);
SQUIRREL_API SQRELEASEHOOK sq_getreleasehook(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize);
SQUIRREL_API SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger level,SQFunctionInfo *fi);
SQUIRREL_API SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQInteger *nparams,SQInteger *nfreevars);
SQUIRREL_API SQRESULT sq_getclosurename(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name);
SQUIRREL_API SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p);
SQUIRREL_API SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag);
SQUIRREL_API SQRESULT sq_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize);
SQUIRREL_API SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase);
SQUIRREL_API SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_setattributes(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API void sq_weakref(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t);
SQUIRREL_API SQRESULT sq_getmemberhandle(HSQUIRRELVM v,SQInteger idx,HSQMEMBERHANDLE *handle);
SQUIRREL_API SQRESULT sq_getbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle);
SQUIRREL_API SQRESULT sq_setbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle);
/*object manipulation*/
SQUIRREL_API void sq_pushroottable(HSQUIRRELVM v);
SQUIRREL_API void sq_pushregistrytable(HSQUIRRELVM v);
SQUIRREL_API void sq_pushconsttable(HSQUIRRELVM v);
SQUIRREL_API SQRESULT sq_setroottable(HSQUIRRELVM v);
SQUIRREL_API SQRESULT sq_setconsttable(HSQUIRRELVM v);
SQUIRREL_API SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic);
SQUIRREL_API SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
SQUIRREL_API SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
SQUIRREL_API SQRESULT sq_newmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic);
SQUIRREL_API SQRESULT sq_rawnewmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic);
SQUIRREL_API SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
SQUIRREL_API SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize);
SQUIRREL_API SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_arrayremove(HSQUIRRELVM v,SQInteger idx,SQInteger itemidx);
SQUIRREL_API SQRESULT sq_arrayinsert(HSQUIRRELVM v,SQInteger idx,SQInteger destpos);
SQUIRREL_API SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_clone(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval);
SQUIRREL_API SQRESULT sq_next(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_getweakrefval(HSQUIRRELVM v,SQInteger idx);
SQUIRREL_API SQRESULT sq_clear(HSQUIRRELVM v,SQInteger idx);
/*calls*/
SQUIRREL_API SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror);
SQUIRREL_API SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror);
SQUIRREL_API const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx);
SQUIRREL_API SQRESULT sq_getcallee(HSQUIRRELVM v);
SQUIRREL_API const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval);
SQUIRREL_API const SQChar *sq_getonefreevariable(HSQUIRRELVM v,SQUnsignedInteger nval);
SQUIRREL_API SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err);
SQUIRREL_API SQRESULT sq_throwobject(HSQUIRRELVM v);
SQUIRREL_API void sq_reseterror(HSQUIRRELVM v);
SQUIRREL_API void sq_getlasterror(HSQUIRRELVM v);
SQUIRREL_API SQRESULT sq_tailcall(HSQUIRRELVM v, SQInteger nparams);
/*raw object handling*/
SQUIRREL_API SQRESULT sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po);
SQUIRREL_API void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj);
SQUIRREL_API void sq_addref(HSQUIRRELVM v,HSQOBJECT *po);
SQUIRREL_API SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po);
SQUIRREL_API SQUnsignedInteger sq_getrefcount(HSQUIRRELVM v,HSQOBJECT *po);
SQUIRREL_API void sq_resetobject(HSQOBJECT *po);
SQUIRREL_API const SQChar *sq_objtostring(const HSQOBJECT *o);
SQUIRREL_API SQBool sq_objtobool(const HSQOBJECT *o);
SQUIRREL_API SQInteger sq_objtointeger(const HSQOBJECT *o);
SQUIRREL_API SQFloat sq_objtofloat(const HSQOBJECT *o);
SQUIRREL_API SQUserPointer sq_objtouserpointer(const HSQOBJECT *o);
SQUIRREL_API SQRESULT sq_getobjtypetag(const HSQOBJECT *o,SQUserPointer * typetag);
SQUIRREL_API SQUnsignedInteger sq_getvmrefcount(HSQUIRRELVM v, const HSQOBJECT *po);
/*GC*/
SQUIRREL_API SQInteger sq_collectgarbage(HSQUIRRELVM v);
SQUIRREL_API SQRESULT sq_resurrectunreachable(HSQUIRRELVM v);
/*serialization*/
SQUIRREL_API SQRESULT sq_writeclosure(HSQUIRRELVM vm,SQWRITEFUNC writef,SQUserPointer up);
SQUIRREL_API SQRESULT sq_readclosure(HSQUIRRELVM vm,SQREADFUNC readf,SQUserPointer up);
/*mem allocation*/
SQUIRREL_API void *sq_malloc(SQUnsignedInteger size);
SQUIRREL_API void *sq_realloc(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize);
SQUIRREL_API void sq_free(void *p,SQUnsignedInteger size);
/*debug*/
SQUIRREL_API SQRESULT sq_stackinfos(HSQUIRRELVM v,SQInteger level,SQStackInfos *si);
SQUIRREL_API void sq_setdebughook(HSQUIRRELVM v);
SQUIRREL_API void sq_setnativedebughook(HSQUIRRELVM v,SQDEBUGHOOK hook);
#endif // SQMOD_PLUGIN_API
/*UTILITY MACRO*/
#define sq_isnumeric(o) ((o)._type&SQOBJECT_NUMERIC)
#define sq_istable(o) ((o)._type==OT_TABLE)
#define sq_isarray(o) ((o)._type==OT_ARRAY)
#define sq_isfunction(o) ((o)._type==OT_FUNCPROTO)
#define sq_isclosure(o) ((o)._type==OT_CLOSURE)
#define sq_isgenerator(o) ((o)._type==OT_GENERATOR)
#define sq_isnativeclosure(o) ((o)._type==OT_NATIVECLOSURE)
#define sq_isstring(o) ((o)._type==OT_STRING)
#define sq_isinteger(o) ((o)._type==OT_INTEGER)
#define sq_isfloat(o) ((o)._type==OT_FLOAT)
#define sq_isuserpointer(o) ((o)._type==OT_USERPOINTER)
#define sq_isuserdata(o) ((o)._type==OT_USERDATA)
#define sq_isthread(o) ((o)._type==OT_THREAD)
#define sq_isnull(o) ((o)._type==OT_NULL)
#define sq_isclass(o) ((o)._type==OT_CLASS)
#define sq_isinstance(o) ((o)._type==OT_INSTANCE)
#define sq_isbool(o) ((o)._type==OT_BOOL)
#define sq_isweakref(o) ((o)._type==OT_WEAKREF)
#define sq_type(o) ((o)._type)
/* deprecated */
#define sq_createslot(v,n) sq_newslot(v,n,SQFalse)
#define SQ_OK (0)
#define SQ_ERROR (-1)
#define SQ_FAILED(res) (res<0)
#define SQ_SUCCEEDED(res) (res>=0)
#ifdef __GNUC__
# define SQ_UNUSED_ARG(x) x __attribute__((__unused__))
#else
# define SQ_UNUSED_ARG(x) x
#endif
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*_SQUIRREL_H_*/

View File

@ -1,25 +0,0 @@
/*
see copyright notice in squirrel.h
*/
#ifndef _SQUIRRELEX_H_
#define _SQUIRRELEX_H_
#include <squirrel.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef SQMOD_PLUGIN_API
SQUIRREL_API SQRESULT sq_throwerrorf(HSQUIRRELVM v,const SQChar *err,...);
SQUIRREL_API void sq_pushstringf(HSQUIRRELVM v,const SQChar *s,...);
SQUIRREL_API SQRESULT sq_getnativeclosurepointer(HSQUIRRELVM v,SQInteger idx,SQFUNCTION *f);
#endif // SQMOD_PLUGIN_API
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*_SQUIRRELEX_H_*/