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

Move Sqrat outside the repository.

This commit is contained in:
Sandu Liviu Catalin 2020-05-26 18:55:43 +03:00
parent f4448aedf6
commit fdefa45a67
18 changed files with 0 additions and 10848 deletions

View File

@ -1,38 +0,0 @@
# Create the Sqrat library
add_library(Sqrat STATIC sqrat.cpp sqrat.h
sqrat/sqratAllocator.h
sqrat/sqratArray.h
sqrat/sqratClass.h
sqrat/sqratConst.h
sqrat/sqratFunction.h
sqrat/sqratGlobalMethods.h
sqrat/sqratMemberMethods.h
sqrat/sqratObject.h
sqrat/sqratOverloadMethods.h
sqrat/sqratScript.h
sqrat/sqratTable.h
sqrat/sqratTypes.h
sqrat/sqratUtil.h
)
# Determine if build mode
if(CMAKE_BUILD_TYPE MATCHES Release)
target_compile_definitions(Sqrat PRIVATE NDEBUG=1)
else()
target_compile_definitions(Sqrat PRIVATE _DEBUG=1)
endif()
# Set library compiler options
target_compile_definitions(Sqrat PUBLIC SCRAT_USE_EXCEPTIONS=1 SCRAT_USE_CXX11_OPTIMIZATIONS=1)
# Switch to plugin-development mode
if(PLUGIN_DEVEL)
target_compile_definitions(Sqrat PUBLIC SQMOD_PLUGIN_API=1)
endif()
# Set specific compiler options
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
#target_compile_options(Sqrat PRIVATE -w
#)
endif()
# Library includes
target_include_directories(Sqrat PUBLIC ${CMAKE_CURRENT_LIST_DIR})
target_include_directories(Sqrat PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
# Link to required libraries
target_link_libraries(Sqrat PUBLIC Squirrel)

View File

@ -1,20 +0,0 @@
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.

View File

@ -1 +0,0 @@
#include <sqrat.h>

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,737 +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 = SqVM()) : 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) noexcept : Object(std::forward< Object >(obj)) {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copy constructor
///
/// \param sa ArrayBase to copy
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ArrayBase(const ArrayBase& sa) : Object(sa) {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Move constructor
///
/// \param sa ArrayBase to move
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ArrayBase(ArrayBase&& sa) noexcept : Object(std::forward< ArrayBase >(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 = SqVM()) : 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) noexcept {
Object::operator = (std::forward< ArrayBase >(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, GetObj());
sq_pushinteger(vm, index);
sq_pushobject(vm, obj.GetObj());
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
/// \param name The name to associate with the function.
///
/// \return The Array itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ArrayBase& SquirrelFunc(const SQInteger index, SQFUNCTION func, const SQChar* name = nullptr) {
sq_pushobject(vm, GetObj());
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;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 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
/// \param name The name to associate with the function.
/// \param pnum Number of parameters the function expects.
/// \param mask Types of parameters the function expects.
///
/// \return The Array itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ArrayBase& SquirrelFunc(const SQInteger index, SQFUNCTION func, SQInteger pnum, const SQChar * mask, const SQChar* name = nullptr) {
sq_pushobject(vm, GetObj());
sq_pushinteger(vm, index);
sq_newclosure(vm, func, 0);
// Set the closure name (for debug purposes)
if (name) sq_setnativeclosurename(vm, -1, name);
// Set parameter validation
sq_setparamscheck(vm, pnum, mask);
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, GetObj());
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, GetObj());
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(GetObj(), funcObj, vm); // 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 = GetObj();
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, GetObj());
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, GetObj());
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, GetObj());
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, GetObj());
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, GetObj());
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, GetObj());
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, GetObj());
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, GetObj());
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, class... A>
ArrayBase& AppendFrom(F&& func, A &&... a) {
sq_pushobject(vm, GetObj());
while (func(vm, std::forward< A >(a)...))
{
sq_arrayappend(vm, -2);
}
sq_pop(vm,1); // pop array
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 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, class... A>
ArrayBase& AppendFromCounted(F&& func, A &&... a) {
sq_pushobject(vm, GetObj());
for (SQInteger i = 0; func(vm, i, std::forward< A >(a)...); ++i)
{
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) noexcept : ArrayBase(std::forward< Object >(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 = SqVM()) : 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) noexcept : ArrayBase(std::forward< Array >(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) noexcept {
ArrayBase::operator = (std::forward< Array >(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.GetObj();
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

File diff suppressed because it is too large Load Diff

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) noexcept // NOLINT(hicpp-member-init,cppcoreguidelines-pro-type-member-init)
: Name(name), mSTR(value), Type(SQET_STRING)
{ /* ... */ }
EnumElement(const SQChar * name, bool value) noexcept // NOLINT(hicpp-member-init,cppcoreguidelines-pro-type-member-init)
: Name(name), mBOOL(value), Type(SQET_BOOL)
{ /* ... */ }
EnumElement(const SQChar * name, signed char value) noexcept // NOLINT(hicpp-member-init,cppcoreguidelines-pro-type-member-init)
: Name(name), mINT(static_cast< SQInteger >(value)), Type(SQET_INT)
{ /* ... */ }
EnumElement(const SQChar * name, unsigned char value) noexcept // NOLINT(hicpp-member-init,cppcoreguidelines-pro-type-member-init)
: Name(name), mINT(static_cast< SQInteger >(value)), Type(SQET_INT)
{ /* ... */ }
EnumElement(const SQChar * name, signed short value) noexcept // NOLINT(hicpp-member-init,cppcoreguidelines-pro-type-member-init)
: Name(name), mINT(static_cast< SQInteger >(value)), Type(SQET_INT)
{ /* ... */ }
EnumElement(const SQChar * name, unsigned short value) noexcept // NOLINT(hicpp-member-init,cppcoreguidelines-pro-type-member-init)
: Name(name), mINT(static_cast< SQInteger >(value)), Type(SQET_INT)
{ /* ... */ }
EnumElement(const SQChar * name, signed int value) noexcept // NOLINT(hicpp-member-init,cppcoreguidelines-pro-type-member-init)
: Name(name), mINT(static_cast< SQInteger >(value)), Type(SQET_INT)
{ /* ... */ }
EnumElement(const SQChar * name, unsigned int value) noexcept // NOLINT(hicpp-member-init,cppcoreguidelines-pro-type-member-init)
: Name(name), mINT(static_cast< SQInteger >(value)), Type(SQET_INT)
{ /* ... */ }
EnumElement(const SQChar * name, signed long value) noexcept // NOLINT(hicpp-member-init,cppcoreguidelines-pro-type-member-init)
: Name(name), mINT(static_cast< SQInteger >(value)), Type(SQET_INT)
{ /* ... */ }
EnumElement(const SQChar * name, unsigned long value) noexcept // NOLINT(hicpp-member-init,cppcoreguidelines-pro-type-member-init)
: Name(name), mINT(static_cast< SQInteger >(value)), Type(SQET_INT)
{ /* ... */ }
EnumElement(const SQChar * name, signed long long value) noexcept // NOLINT(hicpp-member-init,cppcoreguidelines-pro-type-member-init)
: Name(name), mINT(static_cast< SQInteger >(value)), Type(SQET_INT)
{ /* ... */ }
EnumElement(const SQChar * name, unsigned long long value) noexcept // NOLINT(hicpp-member-init,cppcoreguidelines-pro-type-member-init)
: Name(name), mINT(static_cast< SQInteger >(value)), Type(SQET_INT)
{ /* ... */ }
EnumElement(const SQChar * name, float value) noexcept // NOLINT(hicpp-member-init,cppcoreguidelines-pro-type-member-init)
: Name(name), mREAL(static_cast< SQFloat >(value)), Type(SQET_REAL)
{ /* ... */ }
EnumElement(const SQChar * name, double value) noexcept // NOLINT(hicpp-member-init,cppcoreguidelines-pro-type-member-init)
: Name(name), mREAL(static_cast< SQFloat >(value)), Type(SQET_REAL)
{ /* ... */ }
template < typename T > EnumElement(const SQChar * name, T value) noexcept // NOLINT(hicpp-member-init,cppcoreguidelines-pro-type-member-init)
: 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 > explicit EnumElements(const EnumElement(&values)[N]) noexcept
: EnumElements(nullptr, values, N)
{ /* ... */ }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Constructor that takes an explicit number of values at run-time.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
EnumElements(const EnumElement * values, unsigned int count) noexcept
: 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]) noexcept
: 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) noexcept
: 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 = SqVM(), 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 = SqVM()) : 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, GetObj());
sq_pushstring(vm, name, -1);
sq_pushobject(vm, en.GetObj());
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,355 +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& o) : mEnv(o.mEnv), mObj(o.mObj) {
sq_addref(SqVM(), &mEnv);
sq_addref(SqVM(), &mObj);
}
// Move constructor
Function(Function&& o) noexcept : mEnv(o.mEnv), mObj(o.mObj) {
sq_resetobject(&o.mEnv);
sq_resetobject(&o.mObj);
}
// Constructs a Function from a slot in an Object
Function(const Object& e, const SQChar* slot) : mEnv(e.GetObj()) {
sq_addref(SqVM(), &mEnv);
Object so = e.GetSlot(slot);
mObj = so.GetObj();
sq_addref(SqVM(), &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(SqVM(), _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(HSQOBJECT e, HSQOBJECT o, HSQUIRRELVM vm) : mEnv(e), mObj(o) {
sq_addref(vm, &mEnv);
sq_addref(vm, &mObj);
}
// Destructor
~Function() {
Release();
}
// Copy Assignment operator
Function& operator=(const Function& o) {
if (this != &o) {
Release();
mEnv = o.mEnv;
mObj = o.mObj;
sq_addref(SqVM(), &mEnv);
sq_addref(SqVM(), &mObj);
}
return *this;
}
// Move Assignment operator
Function& operator=(Function&& o) noexcept {
if (this != &o) {
Release();
mEnv = o.mEnv;
mObj = o.mObj;
sq_resetobject(&o.mEnv);
sq_resetobject(&o.mObj);
}
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 SqVM();
}
// Sets the Function to null (removing its references to underlying Squirrel objects)
void Release() {
if(!sq_isnull(mEnv)) {
sq_release(SqVM(), &mEnv);
sq_resetobject(&mEnv);
}
if(!sq_isnull(mObj)) {
sq_release(SqVM(), &mObj);
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)) {
if (SQ_FAILED(sq_getstackobj(vm, idx2, &mObj))) return false;
// 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 = SqVM();
const 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)) &&
SqGlobalParamInspect< ArgFwd<Args...>::HASOPT >::Invalid(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 = SqVM();
const 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)) &&
SqGlobalParamInspect< ArgFwd<Args...>::HASOPT >::Invalid(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) {
}
// 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 idx1, SQInteger idx2) : value(vm, idx1, idx2) {
}
// 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)
{
}
Var(HSQUIRRELVM vm, SQInteger idx1, SQInteger idx2) : Var<Function>(vm, idx1, idx2)
{
}
};
// 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)
{
}
Var(HSQUIRRELVM vm, SQInteger idx1, SQInteger idx2) : Var<Function>(vm, idx1, idx2)
{
}
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Helper used to process callback arguments when necessary.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<> struct ArgFwdOptVar<Function, true> : public Var<Function> {
ArgFwdOptVar(HSQUIRRELVM vm, SQInteger idx) : Var<Function>(vm, idx, idx+1) {}
};
template<> struct ArgFwdOptVar<Function&, true> : public Var<Function&> {
ArgFwdOptVar(HSQUIRRELVM vm, SQInteger idx) : Var<Function&>(vm, idx, idx+1) {}
};
template<> struct ArgFwdOptVar<const Function&, true> : public Var<const Function&> {
ArgFwdOptVar(HSQUIRRELVM vm, SQInteger idx) : Var<const Function&>(vm, idx, idx+1) {}
};
}
#endif

View File

@ -1,216 +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);
}
};
template<bool> struct SqGlobalParamInspect {
static inline bool Invalid(SQInteger need, SQInteger have) {
return need != have;
}
};
template<> struct SqGlobalParamInspect<true> {
static inline bool Invalid(SQInteger need, SQInteger have) {
return need < (have - 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...>::HASOPT >::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...>::HASOPT >::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...>::HASOPT >::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...>::HASOPT >::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...>::HASOPT >::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...>::HASOPT >::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...>::HASOPT >::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...>::HASOPT >::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...>::HASOPT >::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 = SqVM()) : 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,746 +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 = SqVM()) : 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) noexcept : Object(std::forward< Object >(obj)) {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Construct the TableBase from an Object that already exists
///
/// \param obj An Object that should already represent a Squirrel table
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TableBase(const LightObj& obj) : Object(obj) {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Construct the TableBase from an Object that already exists
///
/// \param obj An Object that should already represent a Squirrel table
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TableBase(LightObj&& obj) : Object(std::forward< LightObj >(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 = SqVM()) : 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) noexcept : Object(std::forward< TableBase >(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) noexcept {
Object::operator = (std::forward< TableBase >(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, GetObj());
sq_pushstring(vm, name, -1);
sq_pushobject(vm, obj.GetObj());
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, GetObj());
sq_pushstring(vm, name, -1);
sq_pushobject(vm, obj.GetObj());
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, GetObj());
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;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 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
/// \param pnum Number of parameters the function expects.
/// \param mask Types of parameters the function expects.
///
/// \return The Table itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TableBase& SquirrelFunc(const SQChar* name, SQFUNCTION func, SQInteger pnum, const SQChar * mask) {
sq_pushobject(vm, GetObj());
sq_pushstring(vm, name, -1);
sq_newclosure(vm, func, 0);
// Set the closure name (for debug purposes)
sq_setnativeclosurename(vm, -1, name);
// Set parameter validation
sq_setparamscheck(vm, pnum, mask);
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, GetObj());
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(GetObj(), funcObj, vm); // 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, GetObj());
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(GetObj(), funcObj, vm); // must addref before the pop!
sq_pop(vm, 2);
return ret;
}
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Represents a table in Squirrel
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class Table : public TableBase {
public:
using TableBase::TableBase;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Default constructor (null)
///
/// \remarks
/// The Table is invalid until it is given a VM to exist in.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Table() : TableBase() {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 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) noexcept : TableBase(std::forward< Table >(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 = SqVM()) : 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) noexcept : TableBase(std::forward< Table >(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) noexcept {
TableBase::operator = (std::forward< Table >(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:
using TableBase::TableBase;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Constructs a RootTable object to represent the given VM's root table
///
/// \param v VM to get the RootTable for
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
RootTable(HSQUIRRELVM v = SqVM()) : 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:
using TableBase::TableBase;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Constructs a RegistryTable object to represent the given VM's registry table
///
/// \param v VM to get the RegistryTable for
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
RegistryTable(HSQUIRRELVM v = SqVM()) : 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.GetObj();
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