// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Lua scripting module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include namespace Nz { // Functions args inline bool LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { return instance.CheckBoolean(index); } inline double LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { return instance.CheckNumber(index); } inline float LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { return static_cast(instance.CheckNumber(index)); } template std::enable_if_t::value, T> LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { return static_cast(LuaImplQueryArg(instance, index, TypeTag::type>())); } template std::enable_if_t::value && !std::is_unsigned::value, T> LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { return static_cast(instance.CheckInteger(index)); } template std::enable_if_t::value, T> LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { return static_cast(LuaImplQueryArg(instance, index, TypeTag::type>())); } inline std::string LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { std::size_t strLength = 0; const char* str = instance.CheckString(index, &strLength); return std::string(str, strLength); } inline String LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { std::size_t strLength = 0; const char* str = instance.CheckString(index, &strLength); return String(str, strLength); } template T LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { return LuaImplQueryArg(instance, index, TypeTag()); } // Function returns inline int LuaImplReplyVal(LuaInstance& instance, bool val, TypeTag) { instance.PushBoolean(val); return 1; } inline int LuaImplReplyVal(LuaInstance& instance, double val, TypeTag) { instance.PushNumber(val); return 1; } inline int LuaImplReplyVal(LuaInstance& instance, float val, TypeTag) { instance.PushNumber(val); return 1; } template std::enable_if_t::value, int> LuaImplReplyVal(LuaInstance& instance, T val, TypeTag) { using EnumT = typename std::underlying_type::type; return LuaImplReplyVal(instance, static_cast(val), TypeTag()); } template std::enable_if_t::value && !std::is_unsigned::value, int> LuaImplReplyVal(LuaInstance& instance, T val, TypeTag) { instance.PushInteger(val); return 1; } template std::enable_if_t::value, int> LuaImplReplyVal(LuaInstance& instance, T val, TypeTag) { using SignedT = typename std::make_signed::type; return LuaImplReplyVal(instance, static_cast(val), TypeTag()); } inline int LuaImplReplyVal(LuaInstance& instance, std::string val, TypeTag) { instance.PushString(val.c_str(), val.size()); return 1; } inline int LuaImplReplyVal(LuaInstance& instance, String val, TypeTag) { instance.PushString(std::move(val)); return 1; } template int LuaImplReplyVal(LuaInstance& instance, std::pair val, TypeTag>) { int retVal = 0; retVal += LuaImplReplyVal(instance, std::move(val.first), TypeTag()); retVal += LuaImplReplyVal(instance, std::move(val.second), TypeTag()); return retVal; } template class LuaImplFunctionProxy { public: LuaImplFunctionProxy(LuaInstance& instance) : m_instance(instance) { } template void ProcessArgs() { // No argument to process } template void ProcessArgs() { std::get(m_args) = std::move(LuaImplQueryArg(m_instance, N+1, TypeTag())); } template void ProcessArgs() { ProcessArgs(); ProcessArgs(); } void ProcessArgs() { ProcessArgs<0, Args...>(); } int Invoke(void (*func)(Args...)) { Apply(func, m_args); return 0; } template int Invoke(Ret (*func)(Args...)) { return LuaImplReplyVal(m_instance, std::move(Apply(func, m_args)), TypeTag()); } private: std::tuple>...> m_args; LuaInstance& m_instance; }; template class LuaImplMethodProxy { public: LuaImplMethodProxy(LuaInstance& instance, T& object) : m_instance(instance), m_object(object) { } template void ProcessArgs() { // No argument to process } template void ProcessArgs() { std::get(m_args) = std::move(LuaImplQueryArg(m_instance, N + 1, TypeTag())); } template void ProcessArgs() { ProcessArgs(); ProcessArgs(); } void ProcessArgs() { ProcessArgs<0, Args...>(); } template std::enable_if_t::value, int> Invoke(void(P::*func)(Args...)) { Apply(m_object, func, m_args); return 0; } template std::enable_if_t::value, int> Invoke(Ret(P::*func)(Args...)) { return LuaImplReplyVal(m_instance, std::move(Apply(m_object, func, m_args)), TypeTag()); } template std::enable_if_t::value, int> Invoke(void(P::*func)(Args...) const) { Apply(m_object, func, m_args); return 0; } template std::enable_if_t::value, int> Invoke(Ret(P::*func)(Args...) const) { return LuaImplReplyVal(m_instance, std::move(Apply(m_object, func, m_args)), TypeTag()); } private: std::tuple>...> m_args; LuaInstance& m_instance; T& m_object; }; template T LuaInstance::Check(int index) { return LuaImplQueryArg(*this, index, TypeTag()); } template int LuaInstance::Push(T arg) { return LuaImplReplyVal(*this, std::move(arg), TypeTag()); } template void LuaInstance::PushFunction(R (*func)(Args...)) { PushFunction([func](LuaInstance& instance) -> int { LuaImplFunctionProxy handler(instance); handler.ProcessArgs(); return handler.Invoke(func); }); } }