// // 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 #else #include #endif // SQMOD_PLUGIN_API #include "sqratTypes.h" namespace Sqrat { /// @cond DEV // // Squirrel Global Functions // template struct SqGlobalProxy { template static SQInteger Run(HSQUIRRELVM vm, SQInteger idx) { ArgPop a(vm, idx); if (SQ_FAILED(a.Proc(sq_gettop(vm) == idx - 1 + static_cast< SQInteger >(sizeof...(A))))) { return a.ProcRes(); } a.Call(vm, [](HSQUIRRELVM vm, A... a) { typedef R(*M)(A...); M* method; sq_getuserdata(vm, -1, reinterpret_cast(&method), nullptr); R ret = (*method)(a...); PushVar(vm, ret); }); return 1; } }; // // reference return specialization // template struct SqGlobalProxy { template static SQInteger Run(HSQUIRRELVM vm, SQInteger idx) { ArgPop a(vm, idx); if (SQ_FAILED(a.Proc(sq_gettop(vm) == idx - 1 + static_cast< SQInteger >(sizeof...(A))))) { return a.ProcRes(); } a.Call(vm, [](HSQUIRRELVM vm, A... a) { typedef R&(*M)(A...); M* method; sq_getuserdata(vm, -1, reinterpret_cast(&method), nullptr); R& ret = (*method)(a...); PushVarR(vm, ret); }); return 1; } }; // // void return specialization // template <> struct SqGlobalProxy { template static SQInteger Run(HSQUIRRELVM vm, SQInteger idx) { ArgPop a(vm, idx); if (SQ_FAILED(a.Proc(sq_gettop(vm) == idx - 1 + static_cast< SQInteger >(sizeof...(A))))) { return a.ProcRes(); } a.Call(vm, [](HSQUIRRELVM vm, A... a) { typedef void(*M)(A...); M* method; sq_getuserdata(vm, -1, reinterpret_cast(&method), nullptr); (*method)(a...); }); return 0; } }; template struct SqGlobalParamCheck { static inline bool Invalid(SQInteger top, SQInteger count) { return top != count; } }; template<> struct SqGlobalParamCheck { static inline bool Invalid(SQInteger top, SQInteger count) { return top < (count - 1); } }; // // Squirrel Global Functions // template struct SqGlobal { // Function proxy template static SQFUNCTION GetProxy() noexcept { return +[](HSQUIRRELVM vm) noexcept -> SQInteger { #if !defined (SCRAT_NO_ERROR_CHECKING) if (!SQRAT_CONST_CONDITION(overloaded) && SqGlobalParamCheck< ArgPop::HASFMT >::Invalid(sq_gettop(vm), startIdx + sizeof...(A))) { return sq_throwerror(vm, _SC("wrong number of parameters")); } #endif try { return SqGlobalProxy::template Run(vm, startIdx); } catch (const Exception& e) { return sq_throwerror(vm, e.what()); } SQ_UNREACHABLE }; } }; // // reference return specialization // template struct SqGlobal { // Function proxy template static SQFUNCTION GetProxy() noexcept { return +[](HSQUIRRELVM vm) noexcept -> SQInteger { #if !defined (SCRAT_NO_ERROR_CHECKING) if (!SQRAT_CONST_CONDITION(overloaded) && SqGlobalParamCheck< ArgPop::HASFMT >::Invalid(sq_gettop(vm), startIdx + sizeof...(A))) { return sq_throwerror(vm, _SC("wrong number of parameters")); } #endif try { return SqGlobalProxy::template Run(vm, startIdx); } catch (const Exception& e) { return sq_throwerror(vm, e.what()); } SQ_UNREACHABLE }; } }; // // void return specialization // template <> struct SqGlobal { // Function proxy template static SQFUNCTION GetProxy() noexcept { return +[](HSQUIRRELVM vm) noexcept -> SQInteger { #if !defined (SCRAT_NO_ERROR_CHECKING) if (!SQRAT_CONST_CONDITION(overloaded) && SqGlobalParamCheck< ArgPop::HASFMT >::Invalid(sq_gettop(vm), startIdx + sizeof...(A))) { return sq_throwerror(vm, _SC("wrong number of parameters")); } #endif try { return SqGlobalProxy::Run(vm, startIdx); } catch (const Exception& e) { return sq_throwerror(vm, e.what()); } SQ_UNREACHABLE }; } }; // Global Function Resolver template SQFUNCTION SqGlobalFunc(R (* /*method*/)(A...)) noexcept { return SqGlobal::template GetProxy<2, false, A...>(); } // Global Function Resolver template SQFUNCTION SqGlobalFunc(R& (* /*method*/)(A...)) noexcept { return SqGlobal::template GetProxy<2, false, A...>(); } // Member Global Function Resolver template SQFUNCTION SqMemberGlobalFunc(R (* /*method*/)(T, A...)) noexcept { return SqGlobal::template GetProxy<1, false, T, A...>(); } // Member Global Function Resolver template SQFUNCTION SqMemberGlobalFunc(R& (* /*method*/)(T, A...)) noexcept { return SqGlobal::template GetProxy<1, false, T, A...>(); } /// @endcond } #endif