// // 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 #else #include #endif // SQMOD_PLUGIN_API #include #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 class receive_size{}; template< class U > static int sfinae( receive_size< sizeof U() > * ); template< class U > static char sfinae( ... ); public: enum { value = sizeof( sfinae(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 DefaultAllocator { template struct NewC { T* p; NewC() { p = new T(); } }; template struct NewC { 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* cd = ClassType::getClassData(vm); sq_setinstanceup(vm, idx, new std::pair::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::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 static SQInteger iNew(HSQUIRRELVM vm) { SQTRY() Var 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 static SQInteger iNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var 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 static SQInteger iNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var 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 static SQInteger iNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var 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 static SQInteger iNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); Var 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 static SQInteger iNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); Var a5(vm, 6); Var 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 static SQInteger iNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); Var a5(vm, 6); Var a6(vm, 7); Var 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 static SQInteger iNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); Var a5(vm, 6); Var a6(vm, 7); Var a7(vm, 8); Var 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 static SQInteger iNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); Var a5(vm, 6); Var a6(vm, 7); Var a7(vm, 8); Var a8(vm, 9); Var 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 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// @cond DEV /// following iNew functions are used only if constructors are bound via FmtCtor() in Sqrat::Class (safe to ignore) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static SQInteger iFmtNew(HSQUIRRELVM vm) { SQTRY() StackStrF fmt(vm, 2); // Validate the format if (SQ_FAILED(fmt.Proc(true))) { return fmt.mRes; } SetInstance(vm, 1, new C( fmt )); SQCATCH(vm) { return sq_throwerror(vm, SQWHAT(vm)); } return 0; } template static SQInteger iFmtNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); SQCATCH_NOEXCEPT(vm) { return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); } StackStrF fmt(vm, 3); // Validate the format if (SQ_FAILED(fmt.Proc(true))) { return fmt.mRes; } SetInstance(vm, 1, new C( a1.value, fmt )); SQCATCH(vm) { return sq_throwerror(vm, SQWHAT(vm)); } return 0; } template static SQInteger iFmtNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); SQCATCH_NOEXCEPT(vm) { return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); } const StackStrF fmt(vm, 4, true); // Validate the format if (SQ_FAILED(fmt.mRes)) { return fmt.mRes; } SetInstance(vm, 1, new C( a1.value, a2.value, fmt )); SQCATCH(vm) { return sq_throwerror(vm, SQWHAT(vm)); } return 0; } template static SQInteger iFmtNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); SQCATCH_NOEXCEPT(vm) { return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); } StackStrF fmt(vm, 5); // Validate the format if (SQ_FAILED(fmt.Proc(true))) { return fmt.mRes; } SetInstance(vm, 1, new C( a1.value, a2.value, a3.value, fmt )); SQCATCH(vm) { return sq_throwerror(vm, SQWHAT(vm)); } return 0; } template static SQInteger iFmtNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); SQCATCH_NOEXCEPT(vm) { return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); } StackStrF fmt(vm, 6); // Validate the format if (SQ_FAILED(fmt.Proc(true))) { return fmt.mRes; } SetInstance(vm, 1, new C( a1.value, a2.value, a3.value, a4.value, fmt )); SQCATCH(vm) { return sq_throwerror(vm, SQWHAT(vm)); } return 0; } template static SQInteger iFmtNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); Var a5(vm, 6); SQCATCH_NOEXCEPT(vm) { return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); } const StackStrF fmt(vm, 7, true); // Validate the format if (SQ_FAILED(fmt.mRes)) { return fmt.mRes; } SetInstance(vm, 1, new C( a1.value, a2.value, a3.value, a4.value, a5.value, fmt )); SQCATCH(vm) { return sq_throwerror(vm, SQWHAT(vm)); } return 0; } template static SQInteger iFmtNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); Var a5(vm, 6); Var a6(vm, 7); SQCATCH_NOEXCEPT(vm) { return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); } StackStrF fmt(vm, 8); // Validate the format if (SQ_FAILED(fmt.Proc(true))) { return fmt.mRes; } SetInstance(vm, 1, new C( a1.value, a2.value, a3.value, a4.value, a5.value, a6.value, fmt )); SQCATCH(vm) { return sq_throwerror(vm, SQWHAT(vm)); } return 0; } template static SQInteger iFmtNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); Var a5(vm, 6); Var a6(vm, 7); Var a7(vm, 8); SQCATCH_NOEXCEPT(vm) { return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); } StackStrF fmt(vm, 9); // Validate the format if (SQ_FAILED(fmt.Proc(true))) { return fmt.mRes; } SetInstance(vm, 1, new C( a1.value, a2.value, a3.value, a4.value, a5.value, a6.value, a7.value, fmt )); SQCATCH(vm) { return sq_throwerror(vm, SQWHAT(vm)); } return 0; } template static SQInteger iFmtNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); Var a5(vm, 6); Var a6(vm, 7); Var a7(vm, 8); Var a8(vm, 9); SQCATCH_NOEXCEPT(vm) { return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); } const StackStrF fmt(vm, 10, true); // Validate the format if (SQ_FAILED(fmt.mRes)) { return fmt.mRes; } SetInstance(vm, 1, new C( a1.value, a2.value, a3.value, a4.value, a5.value, a6.value, a7.value, a8.value, fmt )); SQCATCH(vm) { return sq_throwerror(vm, SQWHAT(vm)); } return 0; } template static SQInteger iFmtNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); Var a5(vm, 6); Var a6(vm, 7); Var a7(vm, 8); Var a8(vm, 9); Var a9(vm, 10); SQCATCH_NOEXCEPT(vm) { return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); } const StackStrF fmt(vm, 11, true); // Validate the format if (SQ_FAILED(fmt.mRes)) { return fmt.mRes; } SetInstance(vm, 1, new C( a1.value, a2.value, a3.value, a4.value, a5.value, a6.value, a7.value, a8.value, a9.value, fmt )); 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(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::type> >* instance = reinterpret_cast::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 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* cd = ClassType::getClassData(vm); sq_setinstanceup(vm, idx, new std::pair::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::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::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::type> >* instance = reinterpret_cast::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 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* cd = ClassType::getClassData(vm); sq_setinstanceup(vm, idx, new std::pair::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::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::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::type> >* instance = reinterpret_cast::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 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* cd = ClassType::getClassData(vm); sq_setinstanceup(vm, idx, new std::pair::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::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(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::type> >* instance = reinterpret_cast::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 NoCopy { template struct NewC { T* p; NewC() { p = new T(); } }; template struct NewC { 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* cd = ClassType::getClassData(vm); sq_setinstanceup(vm, idx, new std::pair::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::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 static SQInteger iNew(HSQUIRRELVM vm) { SQTRY() Var 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 static SQInteger iNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var 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 static SQInteger iNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var 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 static SQInteger iNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var 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 static SQInteger iNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); Var 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 static SQInteger iNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); Var a5(vm, 6); Var 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 static SQInteger iNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); Var a5(vm, 6); Var a6(vm, 7); Var 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 static SQInteger iNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); Var a5(vm, 6); Var a6(vm, 7); Var a7(vm, 8); Var 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 static SQInteger iNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); Var a5(vm, 6); Var a6(vm, 7); Var a7(vm, 8); Var a8(vm, 9); Var 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 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// @cond DEV /// following iNew functions are used only if constructors are bound via FmtCtor() in Sqrat::Class (safe to ignore) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static SQInteger iFmtNew(HSQUIRRELVM vm) { SQTRY() StackStrF fmt(vm, 2); // Validate the format if (SQ_FAILED(fmt.Proc(true))) { return fmt.mRes; } SetInstance(vm, 1, new C( fmt )); SQCATCH(vm) { return sq_throwerror(vm, SQWHAT(vm)); } return 0; } template static SQInteger iFmtNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); SQCATCH_NOEXCEPT(vm) { return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); } StackStrF fmt(vm, 3); // Validate the format if (SQ_FAILED(fmt.Proc(true))) { return fmt.mRes; } SetInstance(vm, 1, new C( a1.value, fmt )); SQCATCH(vm) { return sq_throwerror(vm, SQWHAT(vm)); } return 0; } template static SQInteger iFmtNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); SQCATCH_NOEXCEPT(vm) { return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); } const StackStrF fmt(vm, 4, true); // Validate the format if (SQ_FAILED(fmt.mRes)) { return fmt.mRes; } SetInstance(vm, 1, new C( a1.value, a2.value, fmt )); SQCATCH(vm) { return sq_throwerror(vm, SQWHAT(vm)); } return 0; } template static SQInteger iFmtNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); SQCATCH_NOEXCEPT(vm) { return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); } const StackStrF fmt(vm, 5, true); // Validate the format if (SQ_FAILED(fmt.mRes)) { return fmt.mRes; } SetInstance(vm, 1, new C( a1.value, a2.value, a3.value, fmt )); SQCATCH(vm) { return sq_throwerror(vm, SQWHAT(vm)); } return 0; } template static SQInteger iFmtNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); SQCATCH_NOEXCEPT(vm) { return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); } const StackStrF fmt(vm, 6, true); // Validate the format if (SQ_FAILED(fmt.mRes)) { return fmt.mRes; } SetInstance(vm, 1, new C( a1.value, a2.value, a3.value, a4.value, fmt )); SQCATCH(vm) { return sq_throwerror(vm, SQWHAT(vm)); } return 0; } template static SQInteger iFmtNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); Var a5(vm, 6); SQCATCH_NOEXCEPT(vm) { return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); } const StackStrF fmt(vm, 7, true); // Validate the format if (SQ_FAILED(fmt.mRes)) { return fmt.mRes; } SetInstance(vm, 1, new C( a1.value, a2.value, a3.value, a4.value, a5.value, fmt )); SQCATCH(vm) { return sq_throwerror(vm, SQWHAT(vm)); } return 0; } template static SQInteger iFmtNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); Var a5(vm, 6); Var a6(vm, 7); SQCATCH_NOEXCEPT(vm) { return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); } const StackStrF fmt(vm, 8, true); // Validate the format if (SQ_FAILED(fmt.mRes)) { return fmt.mRes; } SetInstance(vm, 1, new C( a1.value, a2.value, a3.value, a4.value, a5.value, a6.value, fmt )); SQCATCH(vm) { return sq_throwerror(vm, SQWHAT(vm)); } return 0; } template static SQInteger iFmtNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); Var a5(vm, 6); Var a6(vm, 7); Var a7(vm, 8); SQCATCH_NOEXCEPT(vm) { return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); } const StackStrF fmt(vm, 9, true); // Validate the format if (SQ_FAILED(fmt.mRes)) { return fmt.mRes; } SetInstance(vm, 1, new C( a1.value, a2.value, a3.value, a4.value, a5.value, a6.value, a7.value, fmt )); SQCATCH(vm) { return sq_throwerror(vm, SQWHAT(vm)); } return 0; } template static SQInteger iFmtNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); Var a5(vm, 6); Var a6(vm, 7); Var a7(vm, 8); Var a8(vm, 9); SQCATCH_NOEXCEPT(vm) { return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); } const StackStrF fmt(vm, 10, true); // Validate the format if (SQ_FAILED(fmt.mRes)) { return fmt.mRes; } SetInstance(vm, 1, new C( a1.value, a2.value, a3.value, a4.value, a5.value, a6.value, a7.value, a8.value, fmt )); SQCATCH(vm) { return sq_throwerror(vm, SQWHAT(vm)); } return 0; } template static SQInteger iFmtNew(HSQUIRRELVM vm) { SQTRY() Var a1(vm, 2); Var a2(vm, 3); Var a3(vm, 4); Var a4(vm, 5); Var a5(vm, 6); Var a6(vm, 7); Var a7(vm, 8); Var a8(vm, 9); Var a9(vm, 10); SQCATCH_NOEXCEPT(vm) { return sq_throwerror(vm, SQWHAT_NOEXCEPT(vm)); } const StackStrF fmt(vm, 11, true); // Validate the format if (SQ_FAILED(fmt.mRes)) { return fmt.mRes; } SetInstance(vm, 1, new C( a1.value, a2.value, a3.value, a4.value, a5.value, a6.value, a7.value, a8.value, a9.value, fmt )); 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::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::type> >* instance = reinterpret_cast::type> >*>(ptr); instance->second->erase(instance->first); delete instance->first; delete instance; return 0; } }; } #endif