mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 08:47:17 +01:00
f4a11ef825
Consolidated and simplified the module API system. Various other fixes and improvements.
869 lines
30 KiB
C++
869 lines
30 KiB
C++
//
|
|
// 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 <squirrel.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 >
|
|
class is_default_constructible {
|
|
template<int x>
|
|
class receive_size{};
|
|
|
|
template< class U >
|
|
static int sfinae( receive_size< sizeof U() > * );
|
|
|
|
template< class U >
|
|
static char sfinae( ... );
|
|
|
|
public:
|
|
enum { value = sizeof( sfinae<T>(0) ) == sizeof(int) };
|
|
};
|
|
/// @endcond
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// DefaultAllocator is the allocator to use for Class that can both be constructed and copied
|
|
///
|
|
/// \tparam C Type of class
|
|
///
|
|
/// \remarks
|
|
/// There is mechanisms defined in this class that allow the Class::Ctor method to work properly (e.g. iNew).
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
template<class C>
|
|
class DefaultAllocator {
|
|
|
|
template <class T, bool b>
|
|
struct NewC
|
|
{
|
|
T* p;
|
|
NewC()
|
|
{
|
|
p = new T();
|
|
}
|
|
};
|
|
|
|
template <class T>
|
|
struct NewC<T, false>
|
|
{
|
|
T* p;
|
|
NewC()
|
|
{
|
|
p = 0;
|
|
}
|
|
};
|
|
|
|
public:
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// Associates a newly created instance with an object allocated with the new operator (which is automatically deleted)
|
|
///
|
|
/// \param vm VM that has an instance object of the correct type at idx
|
|
/// \param idx Index of the stack that the instance object is at
|
|
/// \param ptr Should be the return value from a call to the new operator
|
|
///
|
|
/// \remarks
|
|
/// This function should only need to be used when custom constructors are bound with Class::SquirrelFunc.
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
static void SetInstance(HSQUIRRELVM vm, SQInteger idx, C* ptr)
|
|
{
|
|
ClassData<C>* cd = ClassType<C>::getClassData(vm);
|
|
sq_setinstanceup(vm, idx, new std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >(ptr, cd->instances));
|
|
sq_setreleasehook(vm, idx, &Delete);
|
|
sq_getstackobj(vm, idx, &((*cd->instances)[ptr]));
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// Called by Sqrat to set up an instance on the stack for the template class
|
|
///
|
|
/// \param vm VM that has an instance object of the correct type at position 1 in its stack
|
|
///
|
|
/// \return Squirrel error code
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
static SQInteger New(HSQUIRRELVM vm) {
|
|
SetInstance(vm, 1, NewC<C, is_default_constructible<C>::value >().p);
|
|
return 0;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// @cond DEV
|
|
/// following iNew functions are used only if constructors are bound via Ctor() in Sqrat::Class (safe to ignore)
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
static SQInteger iNew(HSQUIRRELVM vm) {
|
|
return New(vm);
|
|
}
|
|
|
|
template <typename A1>
|
|
static SQInteger iNew(HSQUIRRELVM vm) {
|
|
SQTRY()
|
|
Var<A1> a1(vm, 2);
|
|
SQCATCH_NOEXCEPT(vm) {
|
|
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
|
}
|
|
SetInstance(vm, 1, new C(
|
|
a1.value
|
|
));
|
|
SQCATCH(vm) {
|
|
return sq_throwerror(vm, SQWHAT(vm));
|
|
}
|
|
return 0;
|
|
}
|
|
template <typename A1,typename A2>
|
|
static SQInteger iNew(HSQUIRRELVM vm) {
|
|
SQTRY()
|
|
Var<A1> a1(vm, 2);
|
|
Var<A2> a2(vm, 3);
|
|
SQCATCH_NOEXCEPT(vm) {
|
|
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
|
}
|
|
SetInstance(vm, 1, new C(
|
|
a1.value,
|
|
a2.value
|
|
));
|
|
SQCATCH(vm) {
|
|
return sq_throwerror(vm, SQWHAT(vm));
|
|
}
|
|
return 0;
|
|
}
|
|
template <typename A1,typename A2,typename A3>
|
|
static SQInteger iNew(HSQUIRRELVM vm) {
|
|
SQTRY()
|
|
Var<A1> a1(vm, 2);
|
|
Var<A2> a2(vm, 3);
|
|
Var<A3> a3(vm, 4);
|
|
SQCATCH_NOEXCEPT(vm) {
|
|
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
|
}
|
|
SetInstance(vm, 1, new C(
|
|
a1.value,
|
|
a2.value,
|
|
a3.value
|
|
));
|
|
SQCATCH(vm) {
|
|
return sq_throwerror(vm, SQWHAT(vm));
|
|
}
|
|
return 0;
|
|
}
|
|
template <typename A1,typename A2,typename A3,typename A4>
|
|
static SQInteger iNew(HSQUIRRELVM vm) {
|
|
SQTRY()
|
|
Var<A1> a1(vm, 2);
|
|
Var<A2> a2(vm, 3);
|
|
Var<A3> a3(vm, 4);
|
|
Var<A4> a4(vm, 5);
|
|
SQCATCH_NOEXCEPT(vm) {
|
|
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
|
}
|
|
SetInstance(vm, 1, new C(
|
|
a1.value,
|
|
a2.value,
|
|
a3.value,
|
|
a4.value
|
|
));
|
|
SQCATCH(vm) {
|
|
return sq_throwerror(vm, SQWHAT(vm));
|
|
}
|
|
return 0;
|
|
}
|
|
template <typename A1,typename A2,typename A3,typename A4,typename A5>
|
|
static SQInteger iNew(HSQUIRRELVM vm) {
|
|
SQTRY()
|
|
Var<A1> a1(vm, 2);
|
|
Var<A2> a2(vm, 3);
|
|
Var<A3> a3(vm, 4);
|
|
Var<A4> a4(vm, 5);
|
|
Var<A5> a5(vm, 6);
|
|
SQCATCH_NOEXCEPT(vm) {
|
|
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
|
}
|
|
SetInstance(vm, 1, new C(
|
|
a1.value,
|
|
a2.value,
|
|
a3.value,
|
|
a4.value,
|
|
a5.value
|
|
));
|
|
SQCATCH(vm) {
|
|
return sq_throwerror(vm, SQWHAT(vm));
|
|
}
|
|
return 0;
|
|
}
|
|
template <typename A1,typename A2,typename A3,typename A4,typename A5,typename A6>
|
|
static SQInteger iNew(HSQUIRRELVM vm) {
|
|
SQTRY()
|
|
Var<A1> a1(vm, 2);
|
|
Var<A2> a2(vm, 3);
|
|
Var<A3> a3(vm, 4);
|
|
Var<A4> a4(vm, 5);
|
|
Var<A5> a5(vm, 6);
|
|
Var<A6> a6(vm, 7);
|
|
SQCATCH_NOEXCEPT(vm) {
|
|
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
|
}
|
|
SetInstance(vm, 1, new C(
|
|
a1.value,
|
|
a2.value,
|
|
a3.value,
|
|
a4.value,
|
|
a5.value,
|
|
a6.value
|
|
));
|
|
SQCATCH(vm) {
|
|
return sq_throwerror(vm, SQWHAT(vm));
|
|
}
|
|
return 0;
|
|
}
|
|
template <typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7>
|
|
static SQInteger iNew(HSQUIRRELVM vm) {
|
|
SQTRY()
|
|
Var<A1> a1(vm, 2);
|
|
Var<A2> a2(vm, 3);
|
|
Var<A3> a3(vm, 4);
|
|
Var<A4> a4(vm, 5);
|
|
Var<A5> a5(vm, 6);
|
|
Var<A6> a6(vm, 7);
|
|
Var<A7> a7(vm, 8);
|
|
SQCATCH_NOEXCEPT(vm) {
|
|
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
|
}
|
|
SetInstance(vm, 1, new C(
|
|
a1.value,
|
|
a2.value,
|
|
a3.value,
|
|
a4.value,
|
|
a5.value,
|
|
a6.value,
|
|
a7.value
|
|
));
|
|
SQCATCH(vm) {
|
|
return sq_throwerror(vm, SQWHAT(vm));
|
|
}
|
|
return 0;
|
|
}
|
|
template <typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7,typename A8>
|
|
static SQInteger iNew(HSQUIRRELVM vm) {
|
|
SQTRY()
|
|
Var<A1> a1(vm, 2);
|
|
Var<A2> a2(vm, 3);
|
|
Var<A3> a3(vm, 4);
|
|
Var<A4> a4(vm, 5);
|
|
Var<A5> a5(vm, 6);
|
|
Var<A6> a6(vm, 7);
|
|
Var<A7> a7(vm, 8);
|
|
Var<A8> a8(vm, 9);
|
|
SQCATCH_NOEXCEPT(vm) {
|
|
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
|
}
|
|
SetInstance(vm, 1, new C(
|
|
a1.value,
|
|
a2.value,
|
|
a3.value,
|
|
a4.value,
|
|
a5.value,
|
|
a6.value,
|
|
a7.value,
|
|
a8.value
|
|
));
|
|
SQCATCH(vm) {
|
|
return sq_throwerror(vm, SQWHAT(vm));
|
|
}
|
|
return 0;
|
|
}
|
|
template <typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7,typename A8,typename A9>
|
|
static SQInteger iNew(HSQUIRRELVM vm) {
|
|
SQTRY()
|
|
Var<A1> a1(vm, 2);
|
|
Var<A2> a2(vm, 3);
|
|
Var<A3> a3(vm, 4);
|
|
Var<A4> a4(vm, 5);
|
|
Var<A5> a5(vm, 6);
|
|
Var<A6> a6(vm, 7);
|
|
Var<A7> a7(vm, 8);
|
|
Var<A8> a8(vm, 9);
|
|
Var<A9> a9(vm, 10);
|
|
SQCATCH_NOEXCEPT(vm) {
|
|
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
|
}
|
|
SetInstance(vm, 1, new C(
|
|
a1.value,
|
|
a2.value,
|
|
a3.value,
|
|
a4.value,
|
|
a5.value,
|
|
a6.value,
|
|
a7.value,
|
|
a8.value,
|
|
a9.value
|
|
));
|
|
SQCATCH(vm) {
|
|
return sq_throwerror(vm, SQWHAT(vm));
|
|
}
|
|
return 0;
|
|
}
|
|
/// @endcond
|
|
|
|
public:
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// Called by Sqrat to set up the instance at idx on the stack as a copy of a value of the same type
|
|
///
|
|
/// \param vm VM that has an instance object of the correct type at idx
|
|
/// \param idx Index of the stack that the instance object is at
|
|
/// \param value A pointer to data of the same type as the instance object
|
|
///
|
|
/// \return Squirrel error code
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
static SQInteger Copy(HSQUIRRELVM vm, SQInteger idx, const void* value) {
|
|
SetInstance(vm, idx, new C(*static_cast<const C*>(value)));
|
|
return 0;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// Called by Sqrat to delete an instance's data
|
|
///
|
|
/// \param ptr Pointer to the data contained by the instance
|
|
/// \param size Size of the data contained by the instance
|
|
///
|
|
/// \return Squirrel error code
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
static SQInteger Delete(SQUserPointer ptr, SQInteger size) {
|
|
SQUNUSED(size);
|
|
std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >* instance = reinterpret_cast<std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >*>(ptr);
|
|
instance->second->erase(instance->first);
|
|
delete instance->first;
|
|
delete instance;
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// NoConstructor is the allocator to use for Class that can NOT be constructed or copied
|
|
///
|
|
/// \tparam C Type of class
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
template<class C>
|
|
class NoConstructor {
|
|
public:
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// Associates a newly created instance with an object allocated with the new operator (which is automatically deleted)
|
|
///
|
|
/// \param vm VM that has an instance object of the correct type at idx
|
|
/// \param idx Index of the stack that the instance object is at
|
|
/// \param ptr Should be the return value from a call to the new operator
|
|
///
|
|
/// \remarks
|
|
/// This function should only need to be used when custom constructors are bound with Class::SquirrelFunc.
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
static void SetInstance(HSQUIRRELVM vm, SQInteger idx, C* ptr)
|
|
{
|
|
ClassData<C>* cd = ClassType<C>::getClassData(vm);
|
|
sq_setinstanceup(vm, idx, new std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >(ptr, cd->instance));
|
|
sq_setreleasehook(vm, idx, &Delete);
|
|
sq_getstackobj(vm, idx, &((*cd->instances)[ptr]));
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// Called by Sqrat to set up an instance on the stack for the template class (not allowed in this allocator)
|
|
///
|
|
/// \param vm VM that has an instance object of the correct type at position 1 in its stack
|
|
///
|
|
/// \return Squirrel error code
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
static SQInteger New(HSQUIRRELVM vm) {
|
|
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
|
return sq_throwerror(vm, (ClassType<C>::ClassName() + string(_SC(" constructing is not allowed"))).c_str());
|
|
#else
|
|
SQUNUSED(vm);
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// Called by Sqrat to set up the instance at idx on the stack as a copy of a value of the same type (not used in this allocator)
|
|
///
|
|
/// \param vm VM that has an instance object of the correct type at idx
|
|
/// \param idx Index of the stack that the instance object is at
|
|
/// \param value A pointer to data of the same type as the instance object
|
|
///
|
|
/// \return Squirrel error code
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
static SQInteger Copy(HSQUIRRELVM vm, SQInteger idx, const void* value) {
|
|
SQUNUSED(vm);
|
|
SQUNUSED(idx);
|
|
SQUNUSED(value);
|
|
return sq_throwerror(vm, (ClassType<C>::ClassName() + string(_SC(" cloning is not allowed"))).c_str());
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// Called by Sqrat to delete an instance's data
|
|
///
|
|
/// \param ptr Pointer to the data contained by the instance
|
|
/// \param size Size of the data contained by the instance
|
|
///
|
|
/// \return Squirrel error code
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
static SQInteger Delete(SQUserPointer ptr, SQInteger size) {
|
|
SQUNUSED(size);
|
|
std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >* instance = reinterpret_cast<std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >*>(ptr);
|
|
instance->second->erase(instance->first);
|
|
delete instance->first;
|
|
delete instance;
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// CopyOnly is the allocator to use for Class that can be copied but not constructed
|
|
///
|
|
/// \tparam C Type of class
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
template<class C>
|
|
class CopyOnly {
|
|
public:
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// Associates a newly created instance with an object allocated with the new operator (which is automatically deleted)
|
|
///
|
|
/// \param vm VM that has an instance object of the correct type at idx
|
|
/// \param idx Index of the stack that the instance object is at
|
|
/// \param ptr Should be the return value from a call to the new operator
|
|
///
|
|
/// \remarks
|
|
/// This function should only need to be used when custom constructors are bound with Class::SquirrelFunc.
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
static void SetInstance(HSQUIRRELVM vm, SQInteger idx, C* ptr)
|
|
{
|
|
ClassData<C>* cd = ClassType<C>::getClassData(vm);
|
|
sq_setinstanceup(vm, idx, new std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >(ptr, cd->instances));
|
|
sq_setreleasehook(vm, idx, &Delete);
|
|
sq_getstackobj(vm, idx, &((*cd->instances)[ptr]));
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// Called by Sqrat to set up an instance on the stack for the template class (not allowed in this allocator)
|
|
///
|
|
/// \param vm VM that has an instance object of the correct type at position 1 in its stack
|
|
///
|
|
/// \return Squirrel error code
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
static SQInteger New(HSQUIRRELVM vm) {
|
|
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
|
return sq_throwerror(vm, (ClassType<C>::ClassName() + string(_SC(" constructing is not allowed"))).c_str());
|
|
#else
|
|
SQUNUSED(vm);
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// Called by Sqrat to set up the instance at idx on the stack as a copy of a value of the same type
|
|
///
|
|
/// \param vm VM that has an instance object of the correct type at idx
|
|
/// \param idx Index of the stack that the instance object is at
|
|
/// \param value A pointer to data of the same type as the instance object
|
|
///
|
|
/// \return Squirrel error code
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
static SQInteger Copy(HSQUIRRELVM vm, SQInteger idx, const void* value) {
|
|
SetInstance(vm, idx, new C(*static_cast<const C*>(value)));
|
|
return 0;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// Called by Sqrat to delete an instance's data
|
|
///
|
|
/// \param ptr Pointer to the data contained by the instance
|
|
/// \param size Size of the data contained by the instance
|
|
///
|
|
/// \return Squirrel error code
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
static SQInteger Delete(SQUserPointer ptr, SQInteger size) {
|
|
SQUNUSED(size);
|
|
std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >* instance = reinterpret_cast<std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >*>(ptr);
|
|
instance->second->erase(instance->first);
|
|
delete instance->first;
|
|
delete instance;
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// NoCopy is the allocator to use for Class that can be constructed but not copied
|
|
///
|
|
/// \tparam C Type of class
|
|
///
|
|
/// \remarks
|
|
/// There is mechanisms defined in this class that allow the Class::Ctor method to work properly (e.g. iNew).
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
template<class C>
|
|
class NoCopy {
|
|
|
|
template <class T, bool b>
|
|
struct NewC
|
|
{
|
|
T* p;
|
|
NewC()
|
|
{
|
|
p = new T();
|
|
}
|
|
};
|
|
|
|
template <class T>
|
|
struct NewC<T, false>
|
|
{
|
|
T* p;
|
|
NewC()
|
|
{
|
|
p = 0;
|
|
}
|
|
};
|
|
|
|
public:
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// Associates a newly created instance with an object allocated with the new operator (which is automatically deleted)
|
|
///
|
|
/// \param vm VM that has an instance object of the correct type at idx
|
|
/// \param idx Index of the stack that the instance object is at
|
|
/// \param ptr Should be the return value from a call to the new operator
|
|
///
|
|
/// \remarks
|
|
/// This function should only need to be used when custom constructors are bound with Class::SquirrelFunc.
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
static void SetInstance(HSQUIRRELVM vm, SQInteger idx, C* ptr)
|
|
{
|
|
ClassData<C>* cd = ClassType<C>::getClassData(vm);
|
|
sq_setinstanceup(vm, idx, new std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >(ptr, cd->instances));
|
|
sq_setreleasehook(vm, idx, &Delete);
|
|
sq_getstackobj(vm, idx, &((*cd->instances)[ptr]));
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// Called by Sqrat to set up an instance on the stack for the template class
|
|
///
|
|
/// \param vm VM that has an instance object of the correct type at position 1 in its stack
|
|
///
|
|
/// \return Squirrel error code
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
static SQInteger New(HSQUIRRELVM vm) {
|
|
SetInstance(vm, 1, NewC<C, is_default_constructible<C>::value >().p);
|
|
return 0;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// @cond DEV
|
|
/// following iNew functions are used only if constructors are bound via Ctor() in Sqrat::Class (safe to ignore)
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
static SQInteger iNew(HSQUIRRELVM vm) {
|
|
return New(vm);
|
|
}
|
|
|
|
template <typename A1>
|
|
static SQInteger iNew(HSQUIRRELVM vm) {
|
|
SQTRY()
|
|
Var<A1> a1(vm, 2);
|
|
SQCATCH_NOEXCEPT(vm) {
|
|
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
|
}
|
|
SetInstance(vm, 1, new C(
|
|
a1.value
|
|
));
|
|
SQCATCH(vm) {
|
|
return sq_throwerror(vm, SQWHAT(vm));
|
|
}
|
|
return 0;
|
|
}
|
|
template <typename A1,typename A2>
|
|
static SQInteger iNew(HSQUIRRELVM vm) {
|
|
SQTRY()
|
|
Var<A1> a1(vm, 2);
|
|
Var<A2> a2(vm, 3);
|
|
SQCATCH_NOEXCEPT(vm) {
|
|
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
|
}
|
|
SetInstance(vm, 1, new C(
|
|
a1.value,
|
|
a2.value
|
|
));
|
|
SQCATCH(vm) {
|
|
return sq_throwerror(vm, SQWHAT(vm));
|
|
}
|
|
return 0;
|
|
}
|
|
template <typename A1,typename A2,typename A3>
|
|
static SQInteger iNew(HSQUIRRELVM vm) {
|
|
SQTRY()
|
|
Var<A1> a1(vm, 2);
|
|
Var<A2> a2(vm, 3);
|
|
Var<A3> a3(vm, 4);
|
|
SQCATCH_NOEXCEPT(vm) {
|
|
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
|
}
|
|
SetInstance(vm, 1, new C(
|
|
a1.value,
|
|
a2.value,
|
|
a3.value
|
|
));
|
|
SQCATCH(vm) {
|
|
return sq_throwerror(vm, SQWHAT(vm));
|
|
}
|
|
return 0;
|
|
}
|
|
template <typename A1,typename A2,typename A3,typename A4>
|
|
static SQInteger iNew(HSQUIRRELVM vm) {
|
|
SQTRY()
|
|
Var<A1> a1(vm, 2);
|
|
Var<A2> a2(vm, 3);
|
|
Var<A3> a3(vm, 4);
|
|
Var<A4> a4(vm, 5);
|
|
SQCATCH_NOEXCEPT(vm) {
|
|
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
|
}
|
|
SetInstance(vm, 1, new C(
|
|
a1.value,
|
|
a2.value,
|
|
a3.value,
|
|
a4.value
|
|
));
|
|
SQCATCH(vm) {
|
|
return sq_throwerror(vm, SQWHAT(vm));
|
|
}
|
|
return 0;
|
|
}
|
|
template <typename A1,typename A2,typename A3,typename A4,typename A5>
|
|
static SQInteger iNew(HSQUIRRELVM vm) {
|
|
SQTRY()
|
|
Var<A1> a1(vm, 2);
|
|
Var<A2> a2(vm, 3);
|
|
Var<A3> a3(vm, 4);
|
|
Var<A4> a4(vm, 5);
|
|
Var<A5> a5(vm, 6);
|
|
SQCATCH_NOEXCEPT(vm) {
|
|
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
|
}
|
|
SetInstance(vm, 1, new C(
|
|
a1.value,
|
|
a2.value,
|
|
a3.value,
|
|
a4.value,
|
|
a5.value
|
|
));
|
|
SQCATCH(vm) {
|
|
return sq_throwerror(vm, SQWHAT(vm));
|
|
}
|
|
return 0;
|
|
}
|
|
template <typename A1,typename A2,typename A3,typename A4,typename A5,typename A6>
|
|
static SQInteger iNew(HSQUIRRELVM vm) {
|
|
SQTRY()
|
|
Var<A1> a1(vm, 2);
|
|
Var<A2> a2(vm, 3);
|
|
Var<A3> a3(vm, 4);
|
|
Var<A4> a4(vm, 5);
|
|
Var<A5> a5(vm, 6);
|
|
Var<A6> a6(vm, 7);
|
|
SQCATCH_NOEXCEPT(vm) {
|
|
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
|
}
|
|
SetInstance(vm, 1, new C(
|
|
a1.value,
|
|
a2.value,
|
|
a3.value,
|
|
a4.value,
|
|
a5.value,
|
|
a6.value
|
|
));
|
|
SQCATCH(vm) {
|
|
return sq_throwerror(vm, SQWHAT(vm));
|
|
}
|
|
return 0;
|
|
}
|
|
template <typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7>
|
|
static SQInteger iNew(HSQUIRRELVM vm) {
|
|
SQTRY()
|
|
Var<A1> a1(vm, 2);
|
|
Var<A2> a2(vm, 3);
|
|
Var<A3> a3(vm, 4);
|
|
Var<A4> a4(vm, 5);
|
|
Var<A5> a5(vm, 6);
|
|
Var<A6> a6(vm, 7);
|
|
Var<A7> a7(vm, 8);
|
|
SQCATCH_NOEXCEPT(vm) {
|
|
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
|
}
|
|
SetInstance(vm, 1, new C(
|
|
a1.value,
|
|
a2.value,
|
|
a3.value,
|
|
a4.value,
|
|
a5.value,
|
|
a6.value,
|
|
a7.value
|
|
));
|
|
SQCATCH(vm) {
|
|
return sq_throwerror(vm, SQWHAT(vm));
|
|
}
|
|
return 0;
|
|
}
|
|
template <typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7,typename A8>
|
|
static SQInteger iNew(HSQUIRRELVM vm) {
|
|
SQTRY()
|
|
Var<A1> a1(vm, 2);
|
|
Var<A2> a2(vm, 3);
|
|
Var<A3> a3(vm, 4);
|
|
Var<A4> a4(vm, 5);
|
|
Var<A5> a5(vm, 6);
|
|
Var<A6> a6(vm, 7);
|
|
Var<A7> a7(vm, 8);
|
|
Var<A8> a8(vm, 9);
|
|
SQCATCH_NOEXCEPT(vm) {
|
|
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
|
}
|
|
SetInstance(vm, 1, new C(
|
|
a1.value,
|
|
a2.value,
|
|
a3.value,
|
|
a4.value,
|
|
a5.value,
|
|
a6.value,
|
|
a7.value,
|
|
a8.value
|
|
));
|
|
SQCATCH(vm) {
|
|
return sq_throwerror(vm, SQWHAT(vm));
|
|
}
|
|
return 0;
|
|
}
|
|
template <typename A1,typename A2,typename A3,typename A4,typename A5,typename A6,typename A7,typename A8,typename A9>
|
|
static SQInteger iNew(HSQUIRRELVM vm) {
|
|
SQTRY()
|
|
Var<A1> a1(vm, 2);
|
|
Var<A2> a2(vm, 3);
|
|
Var<A3> a3(vm, 4);
|
|
Var<A4> a4(vm, 5);
|
|
Var<A5> a5(vm, 6);
|
|
Var<A6> a6(vm, 7);
|
|
Var<A7> a7(vm, 8);
|
|
Var<A8> a8(vm, 9);
|
|
Var<A9> a9(vm, 10);
|
|
SQCATCH_NOEXCEPT(vm) {
|
|
return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm));
|
|
}
|
|
SetInstance(vm, 1, new C(
|
|
a1.value,
|
|
a2.value,
|
|
a3.value,
|
|
a4.value,
|
|
a5.value,
|
|
a6.value,
|
|
a7.value,
|
|
a8.value,
|
|
a9.value
|
|
));
|
|
SQCATCH(vm) {
|
|
return sq_throwerror(vm, SQWHAT(vm));
|
|
}
|
|
return 0;
|
|
}
|
|
/// @endcond
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// Called by Sqrat to set up the instance at idx on the stack as a copy of a value of the same type (not used in this allocator)
|
|
///
|
|
/// \param vm VM that has an instance object of the correct type at idx
|
|
/// \param idx Index of the stack that the instance object is at
|
|
/// \param value A pointer to data of the same type as the instance object
|
|
///
|
|
/// \return Squirrel error code
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
static SQInteger Copy(HSQUIRRELVM vm, SQInteger idx, const void* value) {
|
|
SQUNUSED(vm);
|
|
SQUNUSED(idx);
|
|
SQUNUSED(value);
|
|
return sq_throwerror(vm, (ClassType<C>::ClassName() + string(_SC(" cloning is not allowed"))).c_str());
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/// Called by Sqrat to delete an instance's data
|
|
///
|
|
/// \param ptr Pointer to the data contained by the instance
|
|
/// \param size Size of the data contained by the instance
|
|
///
|
|
/// \return Squirrel error code
|
|
///
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
static SQInteger Delete(SQUserPointer ptr, SQInteger size) {
|
|
SQUNUSED(size);
|
|
std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >* instance = reinterpret_cast<std::pair<C*, SharedPtr<typename unordered_map<C*, HSQOBJECT>::type> >*>(ptr);
|
|
instance->second->erase(instance->first);
|
|
delete instance->first;
|
|
delete instance;
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|