diff --git a/include/Nazara/Core/Algorithm.hpp b/include/Nazara/Core/Algorithm.hpp index ba9a31c8b..462175307 100644 --- a/include/Nazara/Core/Algorithm.hpp +++ b/include/Nazara/Core/Algorithm.hpp @@ -12,8 +12,12 @@ #include template auto NzApply(F&& fn, Tuple&& t); +template auto NzApply(O& object, F&& fn, Tuple&& t); template void NzHashCombine(std::size_t& seed, const T& v); +template +struct NzTypeTag {}; + #include #endif // NAZARA_ALGORITHM_CORE_HPP diff --git a/include/Nazara/Core/Algorithm.inl b/include/Nazara/Core/Algorithm.inl index fb393fcf9..859dbb8d9 100644 --- a/include/Nazara/Core/Algorithm.inl +++ b/include/Nazara/Core/Algorithm.inl @@ -9,8 +9,8 @@ #include // http://www.cppsamples.com/common-tasks/apply-tuple-to-function.html -template -auto NzApplyImpl(F&& fn, Tuple&& t, std::index_sequence) +template +auto NzApplyImplFunc(F&& fn, Tuple&& t, std::index_sequence) { return std::forward(fn)(std::get(std::forward(t))...); } @@ -18,11 +18,24 @@ auto NzApplyImpl(F&& fn, Tuple&& t, std::index_sequence) template auto NzApply(F&& fn, Tuple&& t) { - std::size_t constexpr tSize = std::tuple_size::type>::value; + constexpr std::size_t tSize = std::tuple_size::type>::value; - return NzApplyImpl(std::forward(fn), std::forward(t), std::make_index_sequence()); + return NzApplyImplFunc(std::forward(fn), std::forward(t), std::make_index_sequence()); } +template +auto NzApplyImplMethod(O& object, F&& fn, Tuple&& t, std::index_sequence) +{ + return (object .* std::forward(fn))(std::get(std::forward(t))...); +} + +template +auto NzApply(O& object, F&& fn, Tuple&& t) +{ + constexpr std::size_t tSize = std::tuple_size::type>::value; + + return NzApplyImplMethod(object, std::forward(fn), std::forward(t), std::make_index_sequence()); +} // Algorithme venant de CityHash par Google // http://stackoverflow.com/questions/8513911/how-to-create-a-good-hash-combine-with-64-bit-output-inspired-by-boosthash-co template diff --git a/include/Nazara/Lua/LuaInstance.hpp b/include/Nazara/Lua/LuaInstance.hpp index 56658ebe0..cdb3b05cb 100644 --- a/include/Nazara/Lua/LuaInstance.hpp +++ b/include/Nazara/Lua/LuaInstance.hpp @@ -108,8 +108,9 @@ class NAZARA_LUA_API NzLuaInstance : NzNonCopyable void Pop(unsigned int n = 1U); void PushBoolean(bool value); - void PushCFunction(NzLuaCFunction func, int upvalueCount = 0); + void PushCFunction(NzLuaCFunction func, unsigned int upvalueCount = 0); void PushFunction(NzLuaFunction func); + template void PushFunction(R(*func)(Args...)); void PushInteger(long long value); void PushLightUserdata(void* value); void PushMetatable(const char* str); @@ -118,6 +119,7 @@ class NAZARA_LUA_API NzLuaInstance : NzNonCopyable void PushNumber(double value); void PushReference(int ref); void PushString(const char* str); + void PushString(const char* str, unsigned int size); void PushString(const NzString& str); void PushTable(unsigned int sequenceElementCount = 0, unsigned int arrayElementCount = 0); void* PushUserdata(unsigned int size); @@ -165,4 +167,6 @@ class NAZARA_LUA_API NzLuaInstance : NzNonCopyable unsigned int m_level; }; +#include + #endif // NAZARA_LUASTATE_HPP diff --git a/include/Nazara/Lua/LuaInstance.inl b/include/Nazara/Lua/LuaInstance.inl new file mode 100644 index 000000000..f9c9d823e --- /dev/null +++ b/include/Nazara/Lua/LuaInstance.inl @@ -0,0 +1,161 @@ +// 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 + +// Functions args +bool NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag) +{ + return instance.CheckBoolean(index); +} + +double NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag) +{ + return instance.CheckNumber(index); +} + +float NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag) +{ + return instance.CheckNumber(index); +} + +int NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag) +{ + return instance.CheckInteger(index); +} + +std::string NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag) +{ + return instance.CheckString(index); +} + +NzString NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag) +{ + return instance.CheckString(index); +} + +template +T NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag) +{ + return NzLuaImplQueryArg(instance, index, NzTypeTag()); +} + +template +std::enable_if_t::value, T> NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag) +{ + return static_cast(NzLuaImplQueryArg(instance, index, NzTypeTag::type>())); +} + +// Function returns +int NzLuaImplReplyVal(NzLuaInstance& instance, bool&& val, NzTypeTag) +{ + instance.PushBoolean(val); + return 1; +} + +int NzLuaImplReplyVal(NzLuaInstance& instance, double&& val, NzTypeTag) +{ + instance.PushNumber(val); + return 1; +} + +int NzLuaImplReplyVal(NzLuaInstance& instance, float&& val, NzTypeTag) +{ + instance.PushNumber(val); + return 1; +} + +int NzLuaImplReplyVal(NzLuaInstance& instance, int&& val, NzTypeTag) +{ + instance.PushInteger(val); + return 1; +} + +int NzLuaImplReplyVal(NzLuaInstance& instance, std::string&& val, NzTypeTag) +{ + instance.PushString(val.c_str(), val.size()); + return 1; +} + +int NzLuaImplReplyVal(NzLuaInstance& instance, NzString&& val, NzTypeTag) +{ + instance.PushString(std::move(val)); + return 1; +} + +template +int NzLuaImplReplyVal(NzLuaInstance& instance, std::pair&& val, NzTypeTag>) +{ + int retVal = 0; + + retVal += NzLuaImplReplyVal(instance, std::move(val.first), NzTypeTag()); + retVal += NzLuaImplReplyVal(instance, std::move(val.second), NzTypeTag()); + + return retVal; +} + +template +std::enable_if_t::value, int> NzLuaImplReplyVal(NzLuaInstance& instance, T&& val, NzTypeTag) +{ + using SignedT = typename std::make_signed::type; + + return NzLuaImplReplyVal(instance, val, NzTypeTag()); +} + +template +class NzLuaImplFunctionProxy +{ + public: + NzLuaImplFunctionProxy(NzLuaInstance& instance) : + m_instance(instance) + { + } + + template + void ProcessArgs() + { + std::get(m_args) = std::move(NzLuaImplQueryArg(m_instance, N+1, NzTypeTag())); + } + + template + void ProcessArgs() + { + ProcessArgs(); + ProcessArgs(); + } + + void ProcessArgs() + { + ProcessArgs<0, Args...>(); + } + + int Invoke(void (*func)(Args...)) + { + NzApply(func, m_args); + return 0; + } + + template + int Invoke(Ret (*func)(Args...)) + { + return NzLuaImplReplyVal(m_instance, std::move(NzApply(func, m_args)), NzTypeTag()); + } + + private: + NzLuaInstance& m_instance; + std::tuple m_args; +}; + +template +void NzLuaInstance::PushFunction(R(*func)(Args...)) +{ + PushFunction([func](NzLuaInstance& instance) -> int + { + NzLuaImplFunctionProxy handler(instance); + handler.ProcessArgs(); + + return handler.Invoke(func); + }); +} diff --git a/src/Nazara/Lua/LuaInstance.cpp b/src/Nazara/Lua/LuaInstance.cpp index 051ac9dab..fe8c3583b 100644 --- a/src/Nazara/Lua/LuaInstance.cpp +++ b/src/Nazara/Lua/LuaInstance.cpp @@ -624,7 +624,7 @@ void NzLuaInstance::PushBoolean(bool value) lua_pushboolean(m_state, (value) ? 1 : 0); } -void NzLuaInstance::PushCFunction(NzLuaCFunction func, int upvalueCount) +void NzLuaInstance::PushCFunction(NzLuaCFunction func, unsigned int upvalueCount) { lua_pushcclosure(m_state, func, upvalueCount); } @@ -677,6 +677,11 @@ void NzLuaInstance::PushString(const char* str) lua_pushstring(m_state, str); } +void NzLuaInstance::PushString(const char* str, unsigned int size) +{ + lua_pushlstring(m_state, str, size); +} + void NzLuaInstance::PushString(const NzString& str) { lua_pushlstring(m_state, str.GetConstBuffer(), str.GetSize());