diff --git a/include/Nazara/Lua/LuaClass.hpp b/include/Nazara/Lua/LuaClass.hpp index 96e271a31..fe592a4aa 100644 --- a/include/Nazara/Lua/LuaClass.hpp +++ b/include/Nazara/Lua/LuaClass.hpp @@ -42,12 +42,13 @@ namespace Nz void SetFinalizer(FinalizerFunc finalizer); void SetGetter(ClassIndexFunc getter); void SetMethod(const String& name, ClassFunc method); - template std::enable_if_t::value> SetMethod(const String& name, R(P::*func)(Args...)); - template std::enable_if_t::value> SetMethod(const String& name, R(P::*func)(Args...) const); + template std::enable_if_t::value> SetMethod(const String& name, R(P::*func)(Args...), DefArgs... defArgs); + template std::enable_if_t::value> SetMethod(const String& name, R(P::*func)(Args...) const, DefArgs... defArgs); + void SetBindMode(LuaBindMode mode); void SetSetter(ClassIndexFunc setter); void SetStaticGetter(StaticIndexFunc getter); void SetStaticMethod(const String& name, StaticFunc func); - template void SetStaticMethod(const String& name, R(*func)(Args...)); + template void SetStaticMethod(const String& name, R(*func)(Args...), DefArgs... defArgs); void SetStaticSetter(StaticIndexFunc getter); private: diff --git a/include/Nazara/Lua/LuaClass.inl b/include/Nazara/Lua/LuaClass.inl index 545fa08ba..b49dd5dcc 100644 --- a/include/Nazara/Lua/LuaClass.inl +++ b/include/Nazara/Lua/LuaClass.inl @@ -176,12 +176,12 @@ namespace Nz } template - template - std::enable_if_t::value> LuaClass::SetMethod(const String& name, R(P::*func)(Args...)) + template + std::enable_if_t::value> LuaClass::SetMethod(const String& name, R(P::*func)(Args...), DefArgs... defArgs) { - SetMethod(name, [func] (LuaInstance& instance, T& object) -> int + SetMethod(name, [func, defArgs...] (LuaInstance& instance, T& object) -> int { - LuaImplMethodProxy handler(instance, object); + LuaImplMethodProxy::Impl handler(instance, object, defArgs...); handler.ProcessArgs(); return handler.Invoke(func); @@ -189,12 +189,12 @@ namespace Nz } template - template - std::enable_if_t::value> LuaClass::SetMethod(const String& name, R(P::*func)(Args...) const) + template + std::enable_if_t::value> LuaClass::SetMethod(const String& name, R(P::*func)(Args...) const, DefArgs... defArgs) { - SetMethod(name, [func] (LuaInstance& instance, T& object) -> int + SetMethod(name, [func, defArgs...] (LuaInstance& instance, T& object) -> int { - LuaImplMethodProxy handler(instance, object); + LuaImplMethodProxy::Impl handler(instance, object, defArgs...); handler.ProcessArgs(); return handler.Invoke(func); @@ -220,12 +220,12 @@ namespace Nz } template - template - void LuaClass::SetStaticMethod(const String& name, R(*func)(Args...)) + template + void LuaClass::SetStaticMethod(const String& name, R(*func)(Args...), DefArgs... defArgs) { - SetStaticMethod(name, [func] (LuaInstance& instance) -> int + SetStaticMethod(name, [func, defArgs...] (LuaInstance& instance) -> int { - LuaImplFunctionProxy handler(instance); + LuaImplFunctionProxy::Impl handler(instance); handler.ProcessArgs(); return handler.Invoke(func); diff --git a/include/Nazara/Lua/LuaInstance.hpp b/include/Nazara/Lua/LuaInstance.hpp index 3a725472a..cdf728c62 100644 --- a/include/Nazara/Lua/LuaInstance.hpp +++ b/include/Nazara/Lua/LuaInstance.hpp @@ -43,6 +43,7 @@ namespace Nz bool Call(unsigned int argCount, unsigned int resultCount); template T Check(int index); + template T Check(int index, T defValue); void CheckAny(int index) const; bool CheckBoolean(int index) const; bool CheckBoolean(int index, bool defValue) const; @@ -115,7 +116,7 @@ namespace Nz void PushBoolean(bool value); void PushCFunction(LuaCFunction func, unsigned int upvalueCount = 0); void PushFunction(LuaFunction func); - template void PushFunction(R(*func)(Args...)); + template void PushFunction(R(*func)(Args...), DefArgs... defArgs); void PushInteger(long long value); void PushLightUserdata(void* value); void PushMetatable(const char* str); diff --git a/include/Nazara/Lua/LuaInstance.inl b/include/Nazara/Lua/LuaInstance.inl index c2153a4e1..8c0f40ac4 100644 --- a/include/Nazara/Lua/LuaInstance.inl +++ b/include/Nazara/Lua/LuaInstance.inl @@ -4,6 +4,7 @@ #include #include +#include namespace Nz { @@ -13,32 +14,68 @@ namespace Nz return instance.CheckBoolean(index); } + inline bool LuaImplQueryArg(LuaInstance& instance, unsigned int index, bool defValue, TypeTag) + { + return instance.CheckBoolean(index, defValue); + } + inline double LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { return instance.CheckNumber(index); } + inline double LuaImplQueryArg(LuaInstance& instance, unsigned int index, double defValue, TypeTag) + { + return instance.CheckNumber(index, defValue); + } + inline float LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { return static_cast(instance.CheckNumber(index)); } + inline float LuaImplQueryArg(LuaInstance& instance, unsigned int index, float defValue, TypeTag) + { + return static_cast(instance.CheckNumber(index, defValue)); + } + 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, T> LuaImplQueryArg(LuaInstance& instance, unsigned int index, T defValue, TypeTag) + { + using UnderlyingT = std::underlying_type_t; + return static_cast(LuaImplQueryArg(instance, index, static_cast(defValue), TypeTag())); + } + 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 && !std::is_unsigned::value, T> LuaImplQueryArg(LuaInstance& instance, unsigned int index, T defValue, TypeTag) + { + return static_cast(instance.CheckInteger(index, defValue)); + } + template std::enable_if_t::value, T> LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { - return static_cast(LuaImplQueryArg(instance, index, TypeTag::type>())); + using SignedT = std::make_signed_t; + return static_cast(LuaImplQueryArg(instance, index, TypeTag())); + } + + template + std::enable_if_t::value, T> LuaImplQueryArg(LuaInstance& instance, unsigned int index, T defValue, TypeTag) + { + using SignedT = std::make_signed_t; + return static_cast(LuaImplQueryArg(instance, index, static_cast(defValue), TypeTag())); } inline std::string LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) @@ -49,6 +86,14 @@ namespace Nz return std::string(str, strLength); } + inline std::string LuaImplQueryArg(LuaInstance& instance, unsigned int index, const std::string& defValue, TypeTag) + { + std::size_t strLength = 0; + const char* str = instance.CheckString(index, defValue.c_str(), &strLength); + + return std::string(str, strLength); + } + inline String LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { std::size_t strLength = 0; @@ -57,12 +102,35 @@ namespace Nz return String(str, strLength); } + inline String LuaImplQueryArg(LuaInstance& instance, unsigned int index, const String& defValue, TypeTag) + { + std::size_t strLength = 0; + const char* str = instance.CheckString(index, defValue.GetConstBuffer(), &strLength); + + return String(str, strLength); + } + template T LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { return LuaImplQueryArg(instance, index, TypeTag()); } + template + T LuaImplQueryArg(LuaInstance& instance, unsigned int index, const T& defValue, TypeTag tag) + { + if (instance.IsValid(index)) + return LuaImplQueryArg(instance, index, tag); + else + return defValue; + } + + template + T LuaImplQueryArg(LuaInstance& instance, unsigned int index, const T& defValue, TypeTag) + { + return LuaImplQueryArg(instance, index, defValue, TypeTag()); + } + // Function returns inline int LuaImplReplyVal(LuaInstance& instance, bool val, TypeTag) { @@ -128,120 +196,181 @@ namespace Nz return retVal; } + template + struct LuaImplArgProcesser; + + template<> + struct LuaImplArgProcesser + { + template + static void Process(LuaInstance& instance, ArgContainer& args, DefArgContainer& defArgs) + { + std::get(args) = std::move(LuaImplQueryArg(instance, N + 1, std::get(defArgs), TypeTag())); + } + }; + + template<> + struct LuaImplArgProcesser + { + template + static void Process(LuaInstance& instance, ArgContainer& args, DefArgContainer& defArgs) + { + NazaraUnused(defArgs); + + std::get(args) = std::move(LuaImplQueryArg(instance, N + 1, TypeTag())); + } + }; + template class LuaImplFunctionProxy { public: - LuaImplFunctionProxy(LuaInstance& instance) : - m_instance(instance) + template + class Impl { - } + static constexpr std::size_t ArgCount = sizeof...(Args); + static constexpr std::size_t DefArgCount = sizeof...(DefArgs); - template - void ProcessArgs() - { - // No argument to process - } + static_assert(ArgCount >= DefArgCount, "There cannot be more default arguments than argument"); - template - void ProcessArgs() - { - std::get(m_args) = std::move(LuaImplQueryArg(m_instance, N+1, TypeTag())); - } + static constexpr std::size_t FirstDefArg = ArgCount - DefArgCount; - template - void ProcessArgs() - { - ProcessArgs(); - ProcessArgs(); - } + public: + Impl(LuaInstance& instance, DefArgs... defArgs) : + m_defaultArgs(std::forward(defArgs)...), + m_instance(instance), + { + } - void ProcessArgs() - { - ProcessArgs<0, Args...>(); - } + void ProcessArgs() + { + ProcessArgs<0, Args...>(); + } - int Invoke(void (*func)(Args...)) - { - Apply(func, m_args); - return 0; - } + 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()); - } + 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; + private: + using ArgContainer = std::tuple>...>; + using DefArgContainer = std::tuple>...>; + + template + void ProcessArgs() + { + // No argument to process + } + + template + void ProcessArgs() + { + using CheckDefValue = typename std::integral_constant= FirstDefArg>; + LuaImplArgProcesser::Process(m_instance, m_args, m_defaultArgs); + } + + template + void ProcessArgs() + { + ProcessArgs(); + ProcessArgs(); + } + + ArgContainer m_args; + DefArgContainer m_defaultArgs; + LuaInstance& m_instance; + }; }; template class LuaImplMethodProxy { public: - LuaImplMethodProxy(LuaInstance& instance, T& object) : - m_instance(instance), - m_object(object) + template + class Impl { - } + static constexpr std::size_t ArgCount = sizeof...(Args); + static constexpr std::size_t DefArgCount = sizeof...(DefArgs); - template - void ProcessArgs() - { - // No argument to process - } + static_assert(ArgCount >= DefArgCount, "There cannot be more default arguments than argument"); - template - void ProcessArgs() - { - std::get(m_args) = std::move(LuaImplQueryArg(m_instance, N + 1, TypeTag())); - } + static constexpr std::size_t FirstDefArg = ArgCount - DefArgCount; - template - void ProcessArgs() - { - ProcessArgs(); - ProcessArgs(); - } + public: + Impl(LuaInstance& instance, T& object, DefArgs... defArgs) : + m_defaultArgs(std::forward(defArgs)...), + m_instance(instance), + m_object(object) + { + } - void ProcessArgs() - { - ProcessArgs<0, Args...>(); - } + 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(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(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(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()); - } + 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; + private: + using ArgContainer = std::tuple>...>; + using DefArgContainer = std::tuple>...>; + + template + void ProcessArgs() + { + // No argument to process + } + + template + void ProcessArgs() + { + using CheckDefValue = typename std::integral_constant= FirstDefArg>; + LuaImplArgProcesser::Process(m_instance, m_args, m_defaultArgs); + } + + template + void ProcessArgs() + { + ProcessArgs(); + ProcessArgs(); + } + + ArgContainer m_args; + DefArgContainer m_defaultArgs; + LuaInstance& m_instance; + T& m_object; + }; }; template @@ -250,18 +379,24 @@ namespace Nz return LuaImplQueryArg(*this, index, TypeTag()); } + template + T LuaInstance::Check(int index, T defValue) + { + return LuaImplQueryArg(*this, index, defValue, TypeTag()); + } + template int LuaInstance::Push(T arg) { return LuaImplReplyVal(*this, std::move(arg), TypeTag()); } - template - void LuaInstance::PushFunction(R (*func)(Args...)) + template + void LuaInstance::PushFunction(R (*func)(Args...), DefArgs... defArgs) { - PushFunction([func](LuaInstance& instance) -> int + PushFunction([func, defArgs...](LuaInstance& instance) -> int { - LuaImplFunctionProxy handler(instance); + LuaImplFunctionProxy::Impl handler(instance); handler.ProcessArgs(); return handler.Invoke(func);