mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-01-19 03:57:14 +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…
x
Reference in New Issue
Block a user