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:
parent
f4448aedf6
commit
fdefa45a67
@ -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)
|
@ -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.
|
@ -1 +0,0 @@
|
||||
#include <sqrat.h>
|
@ -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
|
@ -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
|
@ -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
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
@ -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
|
@ -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
|
@ -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
Loading…
Reference in New Issue
Block a user