Merge remote-tracking branch 'refs/remotes/origin/master' into enet_wip_nothing_to_see_here

This commit is contained in:
Lynix
2017-06-09 01:47:33 +02:00
46 changed files with 2949 additions and 2752 deletions

View File

@@ -49,6 +49,7 @@
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Core/File.hpp>
#include <Nazara/Core/FileLogger.hpp>
#include <Nazara/Core/Flags.hpp>
#include <Nazara/Core/Functor.hpp>
#include <Nazara/Core/GuillotineBinPack.hpp>
#include <Nazara/Core/HandledObject.hpp>

View File

@@ -54,12 +54,20 @@ namespace Nz
private:
BitField m_value;
};
// Little hack to have them in both Nz and global scope
namespace DetailFlagOperators
{
template<typename E> constexpr std::enable_if_t<EnumAsFlags<E>::value, Flags<E>> operator~(E lhs);
template<typename E> constexpr std::enable_if_t<EnumAsFlags<E>::value, Flags<E>> operator|(E lhs, E rhs);
template<typename E> constexpr std::enable_if_t<EnumAsFlags<E>::value, Flags<E>> operator&(E lhs, E rhs);
template<typename E> constexpr std::enable_if_t<EnumAsFlags<E>::value, Flags<E>> operator^(E lhs, E rhs);
}
using namespace DetailFlagOperators;
}
template<typename E> constexpr std::enable_if_t<Nz::EnumAsFlags<E>::value, Nz::Flags<E>> operator~(E lhs);
template<typename E> constexpr std::enable_if_t<Nz::EnumAsFlags<E>::value, Nz::Flags<E>> operator|(E lhs, E rhs);
template<typename E> constexpr std::enable_if_t<Nz::EnumAsFlags<E>::value, Nz::Flags<E>> operator&(E lhs, E rhs);
template<typename E> constexpr std::enable_if_t<Nz::EnumAsFlags<E>::value, Nz::Flags<E>> operator^(E lhs, E rhs);
using namespace Nz::DetailFlagOperators;
#include <Nazara/Core/Flags.inl>

View File

@@ -209,67 +209,71 @@ namespace Nz
{
return 1U << static_cast<BitField>(enumValue);
}
}
/*!
* \brief Override binary NOT operator on enum to turns into a Flags object.
* \return A Flags object with reversed bits.
*
* \param lhs Enumeration value to reverse.
*
* Returns a Flags object with all state enabled except for the enum one.
*/
template<typename E>
constexpr std::enable_if_t<Nz::EnumAsFlags<E>::value, Nz::Flags<E>> operator~(E lhs)
{
return ~Nz::Flags<E>(lhs);
}
/*!
* \brief Override binary OR operator on enum to turns into a Flags object.
* \return A Flags object with combined enum states.
*
* \param lhs First enumeration value to combine.
* \param rhs Second enumeration value to combine.
*
* Returns a Flags object with combined states from the two enumeration values.
*/
template<typename E>
constexpr std::enable_if_t<Nz::EnumAsFlags<E>::value, Nz::Flags<E>> operator|(E lhs, E rhs)
{
return Nz::Flags<E>(lhs) | rhs;
}
namespace DetailFlagOperators
{
/*!
* \brief Override binary NOT operator on enum to turns into a Flags object.
* \return A Flags object with reversed bits.
*
* \param lhs Enumeration value to reverse.
*
* Returns a Flags object with all state enabled except for the enum one.
*/
template<typename E>
constexpr std::enable_if_t<EnumAsFlags<E>::value, Flags<E>> operator~(E lhs)
{
return ~Flags<E>(lhs);
}
/*!
* \brief Override binary AND operator on enum to turns into a Flags object.
* \return A Flags object with compare enum states.
*
* \param lhs First enumeration value to compare.
* \param rhs Second enumeration value to compare.
*
* Returns a Flags object with compared states from the two enumeration values.
* In this case, only one flag will be enabled if both enumeration values are the same.
*/
template<typename E>
constexpr std::enable_if_t<Nz::EnumAsFlags<E>::value, Nz::Flags<E>> operator&(E lhs, E rhs)
{
return Nz::Flags<E>(lhs) & rhs;
}
/*!
* \brief Override binary OR operator on enum to turns into a Flags object.
* \return A Flags object with combined enum states.
*
* \param lhs First enumeration value to combine.
* \param rhs Second enumeration value to combine.
*
* Returns a Flags object with combined states from the two enumeration values.
*/
template<typename E>
constexpr std::enable_if_t<EnumAsFlags<E>::value, Flags<E>> operator|(E lhs, E rhs)
{
return Flags<E>(lhs) | rhs;
}
/*!
* \brief Override binary XOR operator on enum to turns into a Flags object.
* \return A Flags object with XORed enum states.
*
* \param lhs First enumeration value to compare.
* \param rhs Second enumeration value to compare.
*
* Returns a Flags object with XORed states from the two enumeration values.
* In this case, two flags will be enabled if both the enumeration values are different.
*/
template<typename E>
constexpr std::enable_if_t<Nz::EnumAsFlags<E>::value, Nz::Flags<E>> operator^(E lhs, E rhs)
{
return Nz::Flags<E>(lhs) ^ rhs;
/*!
* \brief Override binary AND operator on enum to turns into a Flags object.
* \return A Flags object with compare enum states.
*
* \param lhs First enumeration value to compare.
* \param rhs Second enumeration value to compare.
*
* Returns a Flags object with compared states from the two enumeration values.
* In this case, only one flag will be enabled if both enumeration values are the same.
*/
template<typename E>
constexpr std::enable_if_t<EnumAsFlags<E>::value, Flags<E>> operator&(E lhs, E rhs)
{
return Flags<E>(lhs) & rhs;
}
/*!
* \brief Override binary XOR operator on enum to turns into a Flags object.
* \return A Flags object with XORed enum states.
*
* \param lhs First enumeration value to compare.
* \param rhs Second enumeration value to compare.
*
* Returns a Flags object with XORed states from the two enumeration values.
* In this case, two flags will be enabled if both the enumeration values are different.
*/
template<typename E>
constexpr std::enable_if_t<EnumAsFlags<E>::value, Flags<E>> operator^(E lhs, E rhs)
{
return Flags<E>(lhs) ^ rhs;
}
}
}
#include <Nazara/Core/DebugOff.hpp>

View File

@@ -33,6 +33,8 @@
#include <Nazara/Lua/Enums.hpp>
#include <Nazara/Lua/Lua.hpp>
#include <Nazara/Lua/LuaClass.hpp>
#include <Nazara/Lua/LuaCoroutine.hpp>
#include <Nazara/Lua/LuaInstance.hpp>
#include <Nazara/Lua/LuaState.hpp>
#endif // NAZARA_GLOBAL_LUA_HPP

View File

@@ -26,13 +26,13 @@ namespace Nz
friend class LuaClass;
public:
using ClassFunc = std::function<int(LuaInstance& lua, T& instance, std::size_t argumentCount)>;
using ClassIndexFunc = std::function<bool(LuaInstance& lua, T& instance)>;
using ConstructorFunc = std::function<bool(LuaInstance& lua, T* instance, std::size_t argumentCount)>;
using ClassFunc = std::function<int(LuaState& state, T& instance, std::size_t argumentCount)>;
using ClassIndexFunc = std::function<bool(LuaState& state, T& instance)>;
using ConstructorFunc = std::function<bool(LuaState& state, T* instance, std::size_t argumentCount)>;
template<typename P> using ConvertToParent = std::function<P*(T*)>;
using FinalizerFunc = std::function<bool(LuaInstance& lua, T& instance)>;
using StaticIndexFunc = std::function<bool(LuaInstance& lua)>;
using StaticFunc = std::function<int(LuaInstance& lua)>;
using FinalizerFunc = std::function<bool(LuaState& state, T& instance)>;
using StaticIndexFunc = std::function<bool(LuaState& state)>;
using StaticFunc = std::function<int(LuaState& state)>;
LuaClass() = default;
LuaClass(const String& name);
@@ -54,9 +54,9 @@ namespace Nz
void Reset();
void Reset(const String& name);
void Register(LuaInstance& lua);
void Register(LuaState& state);
void PushGlobalTable(LuaInstance& lua);
void PushGlobalTable(LuaState& state);
void SetConstructor(ConstructorFunc constructor);
void SetFinalizer(FinalizerFunc finalizer);
@@ -69,18 +69,18 @@ namespace Nz
template<typename U, bool HasDestructor>
friend struct LuaClassImplFinalizerSetupProxy;
void PushClassInfo(LuaInstance& lua);
void SetupConstructor(LuaInstance& lua);
void SetupDefaultToString(LuaInstance& lua);
void SetupFinalizer(LuaInstance& lua);
void SetupGetter(LuaInstance& lua, LuaCFunction proxy);
void SetupGlobalTable(LuaInstance& lua);
void SetupMetatable(LuaInstance& lua);
void SetupMethod(LuaInstance& lua, LuaCFunction proxy, const String& name, std::size_t methodIndex);
void SetupSetter(LuaInstance& lua, LuaCFunction proxy);
void PushClassInfo(LuaState& state);
void SetupConstructor(LuaState& state);
void SetupDefaultToString(LuaState& state);
void SetupFinalizer(LuaState& state);
void SetupGetter(LuaState& state, LuaCFunction proxy);
void SetupGlobalTable(LuaState& state);
void SetupMetatable(LuaState& state);
void SetupMethod(LuaState& state, LuaCFunction proxy, const String& name, std::size_t methodIndex);
void SetupSetter(LuaState& state, LuaCFunction proxy);
using ParentFunc = std::function<void(LuaInstance& lua, T* instance)>;
using InstanceGetter = std::function<T*(LuaInstance& lua)>;
using ParentFunc = std::function<void(LuaState& state, T* instance)>;
using InstanceGetter = std::function<T*(LuaState& state)>;
struct ClassInfo
{
@@ -98,17 +98,17 @@ namespace Nz
int globalTableRef = -1;
};
static int ConstructorProxy(lua_State* state);
static int FinalizerProxy(lua_State* state);
static int InfoDestructor(lua_State* state);
static void Get(const std::shared_ptr<ClassInfo>& info, LuaInstance& lua, T* instance);
static int GetterProxy(lua_State* state);
static int MethodProxy(lua_State* state);
static int SetterProxy(lua_State* state);
static int StaticGetterProxy(lua_State* state);
static int StaticMethodProxy(lua_State* state);
static int StaticSetterProxy(lua_State* state);
static int ToStringProxy(lua_State* state);
static int ConstructorProxy(lua_State* internalState);
static int FinalizerProxy(lua_State* internalState);
static int InfoDestructor(lua_State* internalState);
static void Get(const std::shared_ptr<ClassInfo>& info, LuaState& state, T* instance);
static int GetterProxy(lua_State* internalState);
static int MethodProxy(lua_State* internalState);
static int SetterProxy(lua_State* internalState);
static int StaticGetterProxy(lua_State* internalState);
static int StaticMethodProxy(lua_State* internalState);
static int StaticSetterProxy(lua_State* internalState);
static int ToStringProxy(lua_State* internalState);
std::map<String, ClassFunc> m_methods;
std::map<String, StaticFunc> m_staticMethods;

View File

@@ -19,9 +19,9 @@ namespace Nz
template<class T>
inline void LuaClass<T>::BindDefaultConstructor()
{
SetConstructor([] (Nz::LuaInstance& lua, T* instance, std::size_t argumentCount)
SetConstructor([] (Nz::LuaState& state, T* instance, std::size_t argumentCount)
{
NazaraUnused(lua);
NazaraUnused(state);
NazaraUnused(argumentCount);
PlacementNew(instance);
@@ -47,14 +47,14 @@ namespace Nz
std::shared_ptr<typename LuaClass<P>::ClassInfo>& parentInfo = parent.m_info;
parentInfo->instanceGetters[m_info->name] = [info = m_info, convertFunc] (LuaInstance& lua) -> P*
parentInfo->instanceGetters[m_info->name] = [info = m_info, convertFunc] (LuaState& state) -> P*
{
return convertFunc(static_cast<T*>(lua.CheckUserdata(1, info->name)));
return convertFunc(static_cast<T*>(state.CheckUserdata(1, info->name)));
};
m_info->parentGetters.emplace_back([parentInfo, convertFunc] (LuaInstance& lua, T* instance)
m_info->parentGetters.emplace_back([parentInfo, convertFunc] (LuaState& state, T* instance)
{
LuaClass<P>::Get(parentInfo, lua, convertFunc(instance));
LuaClass<P>::Get(parentInfo, state, convertFunc(instance));
});
}
@@ -71,30 +71,30 @@ namespace Nz
m_info = std::make_shared<ClassInfo>();
m_info->name = name;
m_info->instanceGetters[m_info->name] = [info = m_info] (LuaInstance& instance)
m_info->instanceGetters[m_info->name] = [info = m_info] (LuaState& state)
{
return static_cast<T*>(instance.CheckUserdata(1, info->name));
return static_cast<T*>(state.CheckUserdata(1, info->name));
};
}
template<class T>
void LuaClass<T>::Register(LuaInstance& lua)
void LuaClass<T>::Register(LuaState& state)
{
PushClassInfo(lua);
PushClassInfo(state);
// Let's create the metatable which will be associated with every instance.
SetupMetatable(lua);
// Let's create the metatable which will be associated with every state.
SetupMetatable(state);
if (m_info->constructor || m_info->staticGetter || m_info->staticSetter || !m_staticMethods.empty())
SetupGlobalTable(lua);
SetupGlobalTable(state);
lua.Pop(); // Pop our ClassInfo, which is now referenced by all our functions
state.Pop(); // Pop our ClassInfo, which is now referenced by all our functions
}
template<class T>
void LuaClass<T>::PushGlobalTable(LuaInstance& lua)
void LuaClass<T>::PushGlobalTable(LuaState& state)
{
lua.PushReference(m_info->globalTableRef);
state.PushReference(m_info->globalTableRef);
}
template<class T>
@@ -127,11 +127,11 @@ namespace Nz
{
typename LuaImplMethodProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
BindMethod(name, [func, handler] (LuaInstance& lua, T& object, std::size_t /*argumentCount*/) -> int
BindMethod(name, [func, handler] (LuaState& state, T& object, std::size_t /*argumentCount*/) -> int
{
handler.ProcessArguments(lua);
handler.ProcessArguments(state);
return handler.Invoke(lua, object, func);
return handler.Invoke(state, object, func);
});
}
@@ -141,11 +141,11 @@ namespace Nz
{
typename LuaImplMethodProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
BindMethod(name, [func, handler] (LuaInstance& lua, T& object, std::size_t /*argumentCount*/) -> int
BindMethod(name, [func, handler] (LuaState& state, T& object, std::size_t /*argumentCount*/) -> int
{
handler.ProcessArguments(lua);
handler.ProcessArguments(state);
return handler.Invoke(lua, object, func);
return handler.Invoke(state, object, func);
});
}
@@ -155,11 +155,11 @@ namespace Nz
{
typename LuaImplMethodProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
BindMethod(name, [func, handler] (LuaInstance& lua, T& object, std::size_t /*argumentCount*/) -> int
BindMethod(name, [func, handler] (LuaState& state, T& object, std::size_t /*argumentCount*/) -> int
{
handler.ProcessArguments(lua);
handler.ProcessArguments(state);
return handler.Invoke(lua, object, func);
return handler.Invoke(state, object, func);
});
}
@@ -169,11 +169,11 @@ namespace Nz
{
typename LuaImplMethodProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
BindMethod(name, [func, handler] (LuaInstance& lua, T& object, std::size_t /*argumentCount*/) -> int
BindMethod(name, [func, handler] (LuaState& state, T& object, std::size_t /*argumentCount*/) -> int
{
handler.ProcessArguments(lua);
handler.ProcessArguments(state);
return handler.Invoke(lua, object, func);
return handler.Invoke(state, object, func);
});
}
@@ -201,11 +201,11 @@ namespace Nz
{
typename LuaImplFunctionProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
BindStaticMethod(name, [func, handler] (LuaInstance& lua) -> int
BindStaticMethod(name, [func, handler] (LuaState& state) -> int
{
handler.ProcessArguments(lua);
handler.ProcessArguments(state);
return handler.Invoke(lua, func);
return handler.Invoke(state, func);
});
}
@@ -216,37 +216,37 @@ namespace Nz
}
template<class T>
void LuaClass<T>::PushClassInfo(LuaInstance& lua)
void LuaClass<T>::PushClassInfo(LuaState& state)
{
// Our ClassInfo has to outlive the LuaClass, because we don't want to force the user to keep the LuaClass alive
// To do that, each Registration creates a tiny shared_ptr wrapper whose life is directly managed by Lua.
// This shared_ptr object gets pushed as a up-value for every proxy function set in the metatable.
// This way, there is no way our ClassInfo gets freed before any instance and the global class gets destroyed.
std::shared_ptr<ClassInfo>* info = static_cast<std::shared_ptr<ClassInfo>*>(lua.PushUserdata(sizeof(std::shared_ptr<ClassInfo>)));
std::shared_ptr<ClassInfo>* info = static_cast<std::shared_ptr<ClassInfo>*>(state.PushUserdata(sizeof(std::shared_ptr<ClassInfo>)));
PlacementNew(info, m_info);
// Setup a tiny metatable to let Lua know how to destroy our ClassInfo
lua.PushTable(0, 1);
lua.PushLightUserdata(info);
lua.PushCFunction(InfoDestructor, 1);
lua.SetField("__gc");
lua.SetMetatable(-2);
state.PushTable(0, 1);
state.PushLightUserdata(info);
state.PushCFunction(InfoDestructor, 1);
state.SetField("__gc");
state.SetMetatable(-2);
}
template<class T>
void LuaClass<T>::SetupConstructor(LuaInstance& lua)
void LuaClass<T>::SetupConstructor(LuaState& state)
{
lua.PushValue(1); // ClassInfo
lua.PushCFunction(ConstructorProxy, 1);
lua.SetField("__call"); // ClassMeta.__call = ConstructorProxy
state.PushValue(1); // ClassInfo
state.PushCFunction(ConstructorProxy, 1);
state.SetField("__call"); // ClassMeta.__call = ConstructorProxy
}
template<class T>
void LuaClass<T>::SetupDefaultToString(LuaInstance& lua)
void LuaClass<T>::SetupDefaultToString(LuaState& state)
{
lua.PushValue(1); // shared_ptr on UserData
lua.PushCFunction(ToStringProxy, 1);
lua.SetField("__tostring");
state.PushValue(1); // shared_ptr on UserData
state.PushCFunction(ToStringProxy, 1);
state.SetField("__tostring");
}
template<typename T, bool HasDestructor>
@@ -255,61 +255,61 @@ namespace Nz
template<typename T>
struct LuaClassImplFinalizerSetupProxy<T, true>
{
static void Setup(LuaInstance& lua)
static void Setup(LuaState& state)
{
lua.PushValue(1); // ClassInfo
lua.PushCFunction(LuaClass<T>::FinalizerProxy, 1);
lua.SetField("__gc");
state.PushValue(1); // ClassInfo
state.PushCFunction(LuaClass<T>::FinalizerProxy, 1);
state.SetField("__gc");
}
};
template<typename T>
struct LuaClassImplFinalizerSetupProxy<T, false>
{
static void Setup(LuaInstance&)
static void Setup(LuaState&)
{
}
};
template<class T>
void LuaClass<T>::SetupFinalizer(LuaInstance& lua)
void LuaClass<T>::SetupFinalizer(LuaState& state)
{
LuaClassImplFinalizerSetupProxy<T, std::is_destructible<T>::value>::Setup(lua);
LuaClassImplFinalizerSetupProxy<T, std::is_destructible<T>::value>::Setup(state);
}
template<class T>
void LuaClass<T>::SetupGetter(LuaInstance& lua, LuaCFunction proxy)
void LuaClass<T>::SetupGetter(LuaState& state, LuaCFunction proxy)
{
lua.PushValue(1); // ClassInfo
lua.PushValue(-2); // Metatable
lua.PushCFunction(proxy, 2);
state.PushValue(1); // ClassInfo
state.PushValue(-2); // Metatable
state.PushCFunction(proxy, 2);
lua.SetField("__index"); // Getter
state.SetField("__index"); // Getter
}
template<class T>
void LuaClass<T>::SetupGlobalTable(LuaInstance& lua)
void LuaClass<T>::SetupGlobalTable(LuaState& state)
{
// Create the global table
lua.PushTable(); // Class = {}
state.PushTable(); // Class = {}
// Create a metatable which will be used for our global table
lua.PushTable(); // ClassMeta = {}
state.PushTable(); // ClassMeta = {}
if (m_info->constructor)
SetupConstructor(lua);
SetupConstructor(state);
if (m_info->staticGetter)
SetupGetter(lua, StaticGetterProxy);
SetupGetter(state, StaticGetterProxy);
else
{
// Optimize by assigning the metatable instead of a search function
lua.PushValue(-1); // Metatable
lua.SetField("__index");
state.PushValue(-1); // Metatable
state.SetField("__index");
}
if (m_info->staticSetter)
SetupSetter(lua, StaticSetterProxy);
SetupSetter(state, StaticSetterProxy);
m_info->staticMethods.reserve(m_staticMethods.size());
for (auto& pair : m_staticMethods)
@@ -317,41 +317,41 @@ namespace Nz
std::size_t methodIndex = m_info->staticMethods.size();
m_info->staticMethods.push_back(pair.second);
SetupMethod(lua, StaticMethodProxy, pair.first, methodIndex);
SetupMethod(state, StaticMethodProxy, pair.first, methodIndex);
}
lua.SetMetatable(-2); // setmetatable(Class, ClassMeta), pops ClassMeta
state.SetMetatable(-2); // setmetatable(Class, ClassMeta), pops ClassMeta
lua.PushValue(-1); // As CreateReference() pops the table, push a copy
m_info->globalTableRef = lua.CreateReference();
state.PushValue(-1); // As CreateReference() pops the table, push a copy
m_info->globalTableRef = state.CreateReference();
lua.SetGlobal(m_info->name); // _G["Class"] = Class
state.SetGlobal(m_info->name); // _G["Class"] = Class
}
template<class T>
void LuaClass<T>::SetupMetatable(LuaInstance& lua)
void LuaClass<T>::SetupMetatable(LuaState& state)
{
if (!lua.NewMetatable(m_info->name))
if (!state.NewMetatable(m_info->name))
NazaraWarning("Class \"" + m_info->name + "\" already registred in this instance");
{
SetupFinalizer(lua);
SetupFinalizer(state);
if (m_info->getter || !m_info->parentGetters.empty())
SetupGetter(lua, GetterProxy);
SetupGetter(state, GetterProxy);
else
{
// Optimize by assigning the metatable instead of a search function
// This is only possible if we have no custom getter nor parent
lua.PushValue(-1); // Metatable
lua.SetField("__index");
state.PushValue(-1); // Metatable
state.SetField("__index");
}
if (m_info->setter)
SetupSetter(lua, SetterProxy);
SetupSetter(state, SetterProxy);
// In case a __tostring method is missing, add a default implementation returning the class name
if (m_methods.find("__tostring") == m_methods.end())
SetupDefaultToString(lua);
SetupDefaultToString(state);
m_info->methods.reserve(m_methods.size());
for (auto& pair : m_methods)
@@ -359,80 +359,80 @@ namespace Nz
std::size_t methodIndex = m_info->methods.size();
m_info->methods.push_back(pair.second);
SetupMethod(lua, MethodProxy, pair.first, methodIndex);
SetupMethod(state, MethodProxy, pair.first, methodIndex);
}
}
lua.Pop(); //< Pops the metatable, it won't be collected before it's referenced by the Lua registry.
state.Pop(); //< Pops the metatable, it won't be collected before it's referenced by the Lua registry.
}
template<class T>
void LuaClass<T>::SetupMethod(LuaInstance& lua, LuaCFunction proxy, const String& name, std::size_t methodIndex)
void LuaClass<T>::SetupMethod(LuaState& state, LuaCFunction proxy, const String& name, std::size_t methodIndex)
{
lua.PushValue(1); // ClassInfo
lua.PushInteger(methodIndex);
lua.PushCFunction(proxy, 2);
state.PushValue(1); // ClassInfo
state.PushInteger(methodIndex);
state.PushCFunction(proxy, 2);
lua.SetField(name); // Method name
state.SetField(name); // Method name
}
template<class T>
void LuaClass<T>::SetupSetter(LuaInstance& lua, LuaCFunction proxy)
void LuaClass<T>::SetupSetter(LuaState& state, LuaCFunction proxy)
{
lua.PushValue(1); // ClassInfo
lua.PushCFunction(proxy, 1);
state.PushValue(1); // ClassInfo
state.PushCFunction(proxy, 1);
lua.SetField("__newindex"); // Setter
state.SetField("__newindex"); // Setter
}
template<class T>
int LuaClass<T>::ConstructorProxy(lua_State* state)
int LuaClass<T>::ConstructorProxy(lua_State* internalState)
{
LuaInstance& lua = *LuaInstance::GetInstance(state);
LuaState state = LuaInstance::GetState(internalState);
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(state.ToUserdata(state.GetIndexOfUpValue(1)));
const ConstructorFunc& constructor = info->constructor;
lua.Remove(1); // On enlève l'argument "table" du stack
state.Remove(1); // On enlève l'argument "table" du stack
std::size_t argCount = lua.GetStackTop();
std::size_t argCount = state.GetStackTop();
T* instance = static_cast<T*>(lua.PushUserdata(sizeof(T)));
T* instance = static_cast<T*>(state.PushUserdata(sizeof(T)));
if (!constructor(lua, instance, argCount))
if (!constructor(state, instance, argCount))
{
lua.Error("Constructor failed");
state.Error("Constructor failed");
return 0; // Normalement jamais exécuté (l'erreur provoquant une exception)
}
lua.SetMetatable(info->name);
state.SetMetatable(info->name);
return 1;
}
template<class T>
int LuaClass<T>::FinalizerProxy(lua_State* state)
int LuaClass<T>::FinalizerProxy(lua_State* internalState)
{
LuaInstance& lua = *LuaInstance::GetInstance(state);
LuaState state = LuaInstance::GetState(internalState);
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(state.ToUserdata(state.GetIndexOfUpValue(1)));
const FinalizerFunc& finalizer = info->finalizer;
T* instance = static_cast<T*>(lua.CheckUserdata(1, info->name));
lua.Remove(1); //< Remove the instance from the Lua stack
T* instance = static_cast<T*>(state.CheckUserdata(1, info->name));
state.Remove(1); //< Remove the instance from the Lua stack
if (!finalizer || finalizer(lua, *instance))
if (!finalizer || finalizer(state, *instance))
instance->~T();
return 0;
}
template<class T>
int LuaClass<T>::InfoDestructor(lua_State* state)
int LuaClass<T>::InfoDestructor(lua_State* internalState)
{
LuaInstance& lua = *LuaInstance::GetInstance(state);
LuaState state = LuaInstance::GetState(internalState);
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
lua.DestroyReference(info->globalTableRef);
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(state.ToUserdata(state.GetIndexOfUpValue(1)));
state.DestroyReference(info->globalTableRef);
using namespace std; // Obligatoire pour le destructeur
info.~shared_ptr(); // Si vous voyez une autre façon de faire, je suis preneur
@@ -441,27 +441,27 @@ namespace Nz
}
template<class T>
void LuaClass<T>::Get(const std::shared_ptr<ClassInfo>& info, LuaInstance& lua, T* instance)
void LuaClass<T>::Get(const std::shared_ptr<ClassInfo>& info, LuaState& state, T* instance)
{
const ClassIndexFunc& getter = info->getter;
if (!getter || !getter(lua, *instance))
if (!getter || !getter(state, *instance))
{
// Query from the metatable
lua.GetMetatable(info->name); //< Metatable
lua.PushValue(2); //< Field
lua.GetTable(); // Metatable[Field]
state.GetMetatable(info->name); //< Metatable
state.PushValue(2); //< Field
state.GetTable(); // Metatable[Field]
lua.Remove(-2); // Remove Metatable
state.Remove(-2); // Remove Metatable
if (!lua.IsValid(-1))
if (!state.IsValid(-1))
{
for (const ParentFunc& parentGetter : info->parentGetters)
{
lua.Pop(); //< Pop the last nil value
state.Pop(); //< Pop the last nil value
parentGetter(lua, instance);
if (lua.IsValid(-1))
parentGetter(state, instance);
if (state.IsValid(-1))
return;
}
}
@@ -469,131 +469,131 @@ namespace Nz
}
template<class T>
int LuaClass<T>::GetterProxy(lua_State* state)
int LuaClass<T>::GetterProxy(lua_State* internalState)
{
LuaInstance& lua = *LuaInstance::GetInstance(state);
LuaState state = LuaInstance::GetState(internalState);
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(state.ToUserdata(state.GetIndexOfUpValue(1)));
T* instance = static_cast<T*>(lua.CheckUserdata(1, info->name));
T* instance = static_cast<T*>(state.CheckUserdata(1, info->name));
Get(info, lua, instance);
Get(info, state, instance);
return 1;
}
template<class T>
int LuaClass<T>::MethodProxy(lua_State* state)
int LuaClass<T>::MethodProxy(lua_State* internalState)
{
LuaInstance& lua = *LuaInstance::GetInstance(state);
LuaState state = LuaInstance::GetState(internalState);
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(state.ToUserdata(state.GetIndexOfUpValue(1)));
T* instance = nullptr;
if (lua.GetMetatable(1))
if (state.GetMetatable(1))
{
LuaType type = lua.GetField("__name");
LuaType type = state.GetField("__name");
if (type == LuaType_String)
{
String name = lua.ToString(-1);
String name = state.ToString(-1);
auto it = info->instanceGetters.find(name);
if (it != info->instanceGetters.end())
instance = it->second(lua);
instance = it->second(state);
}
lua.Pop(2);
state.Pop(2);
}
if (!instance)
{
lua.Error("Method cannot be called without an object");
state.Error("Method cannot be called without an object");
return 0;
}
std::size_t argCount = lua.GetStackTop() - 1U;
std::size_t argCount = state.GetStackTop() - 1U;
unsigned int index = static_cast<unsigned int>(lua.ToInteger(lua.GetIndexOfUpValue(2)));
unsigned int index = static_cast<unsigned int>(state.ToInteger(state.GetIndexOfUpValue(2)));
const ClassFunc& method = info->methods[index];
return method(lua, *instance, argCount);
return method(state, *instance, argCount);
}
template<class T>
int LuaClass<T>::SetterProxy(lua_State* state)
int LuaClass<T>::SetterProxy(lua_State* internalState)
{
LuaInstance& lua = *LuaInstance::GetInstance(state);
LuaState state = LuaInstance::GetState(internalState);
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(state.ToUserdata(state.GetIndexOfUpValue(1)));
const ClassIndexFunc& setter = info->setter;
T& instance = *static_cast<T*>(lua.CheckUserdata(1, info->name));
T& instance = *static_cast<T*>(state.CheckUserdata(1, info->name));
if (!setter(lua, instance))
if (!setter(state, instance))
{
std::size_t length;
const char* str = lua.ToString(2, &length);
const char* str = state.ToString(2, &length);
lua.Error("Class \"" + info->name + "\" has no field \"" + String(str, length) + "\")");
state.Error("Class \"" + info->name + "\" has no field \"" + String(str, length) + "\")");
}
return 1;
}
template<class T>
int LuaClass<T>::StaticGetterProxy(lua_State* state)
int LuaClass<T>::StaticGetterProxy(lua_State* internalState)
{
LuaInstance& lua = *LuaInstance::GetInstance(state);
LuaState state = LuaInstance::GetState(internalState);
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(state.ToUserdata(state.GetIndexOfUpValue(1)));
const StaticIndexFunc& getter = info->staticGetter;
if (!getter(lua))
if (!getter(state))
{
// On accède alors à la table
lua.PushValue(lua.GetIndexOfUpValue(2));
lua.PushValue(-2);
lua.GetTable();
state.PushValue(state.GetIndexOfUpValue(2));
state.PushValue(-2);
state.GetTable();
}
return 1;
}
template<class T>
int LuaClass<T>::StaticMethodProxy(lua_State* state)
int LuaClass<T>::StaticMethodProxy(lua_State* internalState)
{
LuaInstance& lua = *LuaInstance::GetInstance(state);
LuaState state = LuaInstance::GetState(internalState);
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
unsigned int index = static_cast<unsigned int>(lua.ToInteger(lua.GetIndexOfUpValue(2)));
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(state.ToUserdata(state.GetIndexOfUpValue(1)));
unsigned int index = static_cast<unsigned int>(state.ToInteger(state.GetIndexOfUpValue(2)));
const StaticFunc& method = info->staticMethods[index];
return method(lua);
return method(state);
}
template<class T>
int LuaClass<T>::StaticSetterProxy(lua_State* state)
int LuaClass<T>::StaticSetterProxy(lua_State* internalState)
{
LuaInstance& lua = *LuaInstance::GetInstance(state);
LuaState state = LuaInstance::GetState(internalState);
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(state.ToUserdata(state.GetIndexOfUpValue(1)));
const StaticIndexFunc& setter = info->staticSetter;
if (!setter(lua))
if (!setter(state))
{
std::size_t length;
const char* str = lua.ToString(2, &length);
const char* str = state.ToString(2, &length);
lua.Error("Class \"" + info->name + "\" has no static field \"" + String(str, length) + ')');
state.Error("Class \"" + info->name + "\" has no static field \"" + String(str, length) + ')');
}
return 1;
}
template<class T>
int LuaClass<T>::ToStringProxy(lua_State* state)
int LuaClass<T>::ToStringProxy(lua_State* internalState)
{
LuaInstance& lua = *LuaInstance::GetInstance(state);
LuaState state = LuaInstance::GetState(internalState);
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(state.ToUserdata(state.GetIndexOfUpValue(1)));
lua.PushString(info->name);
state.PushString(info->name);
return 1;
}
}

View File

@@ -0,0 +1,44 @@
// Copyright (C) 2017 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
#pragma once
#ifndef NAZARA_LUACOROUTINE_HPP
#define NAZARA_LUACOROUTINE_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Lua/LuaState.hpp>
#include <cstddef>
#include <functional>
namespace Nz
{
class NAZARA_LUA_API LuaCoroutine : public LuaState
{
friend class LuaState;
public:
LuaCoroutine(const LuaCoroutine&) = delete;
inline LuaCoroutine(LuaCoroutine&& instance);
~LuaCoroutine();
bool CanResume() const;
Ternary Resume(unsigned int argCount = 0);
LuaCoroutine& operator=(const LuaCoroutine&) = delete;
inline LuaCoroutine& operator=(LuaCoroutine&& instance);
private:
LuaCoroutine(lua_State* internalState, int refIndex);
bool Run(int argCount, int resultCount) override;
int m_ref;
};
}
#include <Nazara/Lua/LuaCoroutine.inl>
#endif // NAZARA_LUACOROUTINE_HPP

View File

@@ -0,0 +1,25 @@
// Copyright (C) 2017 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 <Nazara/Lua/LuaCoroutine.hpp>
namespace Nz
{
inline LuaCoroutine::LuaCoroutine(LuaCoroutine&& instance) :
LuaState(std::move(instance)),
m_ref(instance.m_ref)
{
instance.m_ref = -1;
}
inline LuaCoroutine& LuaCoroutine::operator=(LuaCoroutine&& instance)
{
LuaState::operator=(std::move(instance));
m_ref = instance.m_ref;
instance.m_ref = -1;
return *this;
}
}

View File

@@ -4,201 +4,42 @@
#pragma once
#ifndef NAZARA_LUASTATE_HPP
#define NAZARA_LUASTATE_HPP
#ifndef NAZARA_LUAINSTANCE_HPP
#define NAZARA_LUAINSTANCE_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Clock.hpp>
#include <Nazara/Core/Stream.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Lua/Config.hpp>
#include <Nazara/Lua/Enums.hpp>
#include <Nazara/Lua/LuaState.hpp>
#include <cstddef>
#include <functional>
struct lua_Debug;
struct lua_State;
namespace Nz
{
class LuaInstance;
using LuaCFunction = int (*)(lua_State* state);
using LuaFunction = std::function<int(LuaInstance& instance)>;
class NAZARA_LUA_API LuaInstance
class NAZARA_LUA_API LuaInstance : public LuaState
{
friend class LuaCoroutine;
friend class LuaState;
public:
LuaInstance();
LuaInstance(const LuaInstance&) = delete;
LuaInstance(LuaInstance&& instance) noexcept;
LuaInstance(LuaInstance&& instance) = default;
~LuaInstance();
void ArgCheck(bool condition, unsigned int argNum, const char* error) const;
void ArgCheck(bool condition, unsigned int argNum, const String& error) const;
int ArgError(unsigned int argNum, const char* error) const;
int ArgError(unsigned int argNum, const String& error) const;
bool Call(unsigned int argCount);
bool Call(unsigned int argCount, unsigned int resultCount);
template<typename T> T Check(int* index) const;
template<typename T> T Check(int* index, T defValue) const;
void CheckAny(int index) const;
bool CheckBoolean(int index) const;
bool CheckBoolean(int index, bool defValue) const;
template<typename T> T CheckBoundInteger(int index) const;
template<typename T> T CheckBoundInteger(int index, T defValue) const;
template<typename T> T CheckField(const char* fieldName, int tableIndex = -1) const;
template<typename T> T CheckField(const String& fieldName, int tableIndex = -1) const;
template<typename T> T CheckField(const char* fieldName, T defValue, int tableIndex = -1) const;
template<typename T> T CheckField(const String& fieldName, T defValue, int tableIndex = -1) const;
long long CheckInteger(int index) const;
long long CheckInteger(int index, long long defValue) const;
template<typename T> T CheckGlobal(const char* fieldName) const;
template<typename T> T CheckGlobal(const String& fieldName) const;
template<typename T> T CheckGlobal(const char* fieldName, T defValue) const;
template<typename T> T CheckGlobal(const String& fieldName, T defValue) const;
double CheckNumber(int index) const;
double CheckNumber(int index, double defValue) const;
void CheckStack(int space, const char* error = nullptr) const;
void CheckStack(int space, const String& error) const;
const char* CheckString(int index, std::size_t* length = nullptr) const;
const char* CheckString(int index, const char* defValue, std::size_t* length = nullptr) const;
void CheckType(int index, LuaType type) const;
void* CheckUserdata(int index, const char* tname) const;
void* CheckUserdata(int index, const String& tname) const;
bool Compare(int index1, int index2, LuaComparison comparison) const;
void Compute(LuaOperation operation) const;
void Concatenate(int count) const;
int CreateReference();
void DestroyReference(int ref);
String DumpStack() const;
void Error(const char* message) const;
void Error(const String& message) const;
bool Execute(const String& code);
bool ExecuteFromFile(const String& filePath);
bool ExecuteFromMemory(const void* data, std::size_t size);
bool ExecuteFromStream(Stream& stream);
int GetAbsIndex(int index) const;
LuaType GetField(const char* fieldName, int tableIndex = -1) const;
LuaType GetField(const String& fieldName, int tableIndex = -1) const;
LuaType GetGlobal(const char* name) const;
LuaType GetGlobal(const String& name) const;
inline lua_State* GetInternalState() const;
inline String GetLastError() const;
inline std::size_t GetMemoryLimit() const;
inline std::size_t GetMemoryUsage() const;
LuaType GetMetatable(const char* tname) const;
LuaType GetMetatable(const String& tname) const;
bool GetMetatable(int index) const;
unsigned int GetStackTop() const;
LuaType GetTable(int index = -2) const;
LuaType GetTableRaw(int index = -2) const;
inline UInt32 GetTimeLimit() const;
LuaType GetType(int index) const;
const char* GetTypeName(LuaType type) const;
void Insert(int index) const;
bool IsOfType(int index, LuaType type) const;
bool IsOfType(int index, const char* tname) const;
bool IsOfType(int index, const String& tname) const;
bool IsValid(int index) const;
long long Length(int index) const;
std::size_t LengthRaw(int index) const;
void MoveTo(LuaInstance* instance, int n) const;
bool NewMetatable(const char* str);
bool NewMetatable(const String& str);
bool Next(int index = -2) const;
void Pop(unsigned int n = 1U) const;
template<typename T> int Push(T arg) const;
template<typename T, typename T2, typename... Args> int Push(T firstArg, T2 secondArg, Args... args) const;
void PushBoolean(bool value) const;
void PushCFunction(LuaCFunction func, unsigned int upvalueCount = 0) const;
template<typename T> void PushField(const char* name, T&& arg, int tableIndex = -2) const;
template<typename T> void PushField(const String& name, T&& arg, int tableIndex = -2) const;
void PushFunction(LuaFunction func) const;
template<typename R, typename... Args, typename... DefArgs> void PushFunction(R(*func)(Args...), DefArgs&&... defArgs) const;
template<typename T> void PushGlobal(const char* name, T&& arg);
template<typename T> void PushGlobal(const String& name, T&& arg);
template<typename T> void PushInstance(const char* tname, const T& instance) const;
template<typename T> void PushInstance(const char* tname, T&& instance) const;
template<typename T, typename... Args> void PushInstance(const char* tname, Args&&... args) const;
void PushInteger(long long value) const;
void PushLightUserdata(void* value) const;
void PushMetatable(const char* str) const;
void PushMetatable(const String& str) const;
void PushNil() const;
void PushNumber(double value) const;
void PushReference(int ref) const;
void PushString(const char* str) const;
void PushString(const char* str, std::size_t size) const;
void PushString(const String& str) const;
void PushTable(std::size_t sequenceElementCount = 0, std::size_t arrayElementCount = 0) const;
void* PushUserdata(std::size_t size) const;
void PushValue(int index) const;
void Remove(int index) const;
void Replace(int index) const;
void SetField(const char* name, int tableIndex = -2) const;
void SetField(const String& name, int tableIndex = -2) const;
void SetGlobal(const char* name);
void SetGlobal(const String& name);
void SetMetatable(const char* tname) const;
void SetMetatable(const String& tname) const;
void SetMetatable(int index) const;
void SetMemoryLimit(std::size_t memoryLimit);
void SetTable(int index = -3) const;
void SetTableRaw(int index = -3) const;
void SetTimeLimit(UInt32 timeLimit);
bool ToBoolean(int index) const;
long long ToInteger(int index, bool* succeeded = nullptr) const;
double ToNumber(int index, bool* succeeded = nullptr) const;
const void* ToPointer(int index) const;
const char* ToString(int index, std::size_t* length = nullptr) const;
void* ToUserdata(int index) const;
void* ToUserdata(int index, const char* tname) const;
void* ToUserdata(int index, const String& tname) const;
LuaInstance& operator=(const LuaInstance&) = delete;
LuaInstance& operator=(LuaInstance&& instance) noexcept;
static int GetIndexOfUpValue(int upValue);
static LuaInstance* GetInstance(lua_State* state);
LuaInstance& operator=(LuaInstance&& instance) = default;
private:
template<typename T> T CheckBounds(int index, long long value) const;
bool Run(int argCount, int resultCount);
static void* MemoryAllocator(void *ud, void *ptr, std::size_t osize, std::size_t nsize);
static int ProxyFunc(lua_State* state);
static void TimeLimiter(lua_State* state, lua_Debug* debug);
static void TimeLimiter(lua_State* internalState, lua_Debug* debug);
std::size_t m_memoryLimit;
std::size_t m_memoryUsage;
UInt32 m_timeLimit;
Clock m_clock;
String m_lastError;
lua_State* m_state;
unsigned int m_level;
};
}
#include <Nazara/Lua/LuaInstance.inl>
#endif // NAZARA_LUASTATE_HPP
#endif // NAZARA_LUAINSTANCE_HPP

View File

@@ -15,783 +15,4 @@
namespace Nz
{
inline lua_State* LuaInstance::GetInternalState() const
{
return m_state;
}
inline String LuaInstance::GetLastError() const
{
return m_lastError;
}
inline std::size_t LuaInstance::GetMemoryLimit() const
{
return m_memoryLimit;
}
inline std::size_t LuaInstance::GetMemoryUsage() const
{
return m_memoryUsage;
}
inline UInt32 LuaInstance::GetTimeLimit() const
{
return m_timeLimit;
}
// Functions args
inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, bool* arg, TypeTag<bool>)
{
*arg = instance.CheckBoolean(index);
return 1;
}
inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, bool* arg, bool defValue, TypeTag<bool>)
{
*arg = instance.CheckBoolean(index, defValue);
return 1;
}
inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, std::string* arg, TypeTag<std::string>)
{
std::size_t strLength = 0;
const char* str = instance.CheckString(index, &strLength);
arg->assign(str, strLength);
return 1;
}
inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, String* arg, TypeTag<String>)
{
std::size_t strLength = 0;
const char* str = instance.CheckString(index, &strLength);
arg->Set(str, strLength);
return 1;
}
template<typename T>
std::enable_if_t<std::is_enum<T>::value && !EnumAsFlags<T>::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, TypeTag<T>)
{
using UnderlyingT = std::underlying_type_t<T>;
return LuaImplQueryArg(instance, index, reinterpret_cast<UnderlyingT*>(arg), TypeTag<UnderlyingT>());
}
template<typename T>
std::enable_if_t<std::is_enum<T>::value && !EnumAsFlags<T>::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, T defValue, TypeTag<T>)
{
using UnderlyingT = std::underlying_type_t<T>;
return LuaImplQueryArg(instance, index, reinterpret_cast<UnderlyingT*>(arg), static_cast<UnderlyingT>(defValue), TypeTag<UnderlyingT>());
}
template<typename T>
std::enable_if_t<std::is_enum<T>::value && EnumAsFlags<T>::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, TypeTag<T>)
{
using UnderlyingT = std::underlying_type_t<T>;
UnderlyingT pot2Val;
unsigned int ret = LuaImplQueryArg(instance, index, &pot2Val, TypeTag<UnderlyingT>());
*arg = static_cast<T>(IntegralLog2Pot(pot2Val));
return ret;
}
template<typename T>
std::enable_if_t<std::is_enum<T>::value && EnumAsFlags<T>::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, T defValue, TypeTag<T>)
{
using UnderlyingT = std::underlying_type_t<T>;
UnderlyingT pot2Val;
unsigned int ret = LuaImplQueryArg(instance, index, &pot2Val, 1U << static_cast<UnderlyingT>(defValue), TypeTag<UnderlyingT>());
*arg = static_cast<T>(IntegralLog2Pot(pot2Val));
return ret;
}
template<typename E>
unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Flags<E>* arg, TypeTag<Flags<E>>)
{
*arg = Flags<E>(instance.CheckBoundInteger<UInt32>(index));
return 1;
}
template<typename T>
std::enable_if_t<std::is_floating_point<T>::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, TypeTag<T>)
{
*arg = static_cast<T>(instance.CheckNumber(index));
return 1;
}
template<typename T>
std::enable_if_t<std::is_floating_point<T>::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, T defValue, TypeTag<T>)
{
*arg = static_cast<T>(instance.CheckNumber(index, static_cast<double>(defValue)));
return 1;
}
template<typename T>
std::enable_if_t<std::is_integral<T>::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, TypeTag<T>)
{
*arg = instance.CheckBoundInteger<T>(index);
return 1;
}
template<typename T>
std::enable_if_t<std::is_integral<T>::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, T defValue, TypeTag<T>)
{
*arg = instance.CheckBoundInteger<T>(index, defValue);
return 1;
}
template<typename T>
std::enable_if_t<!std::is_integral<T>::value && !std::is_enum<T>::value && !std::is_floating_point<T>::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, const T& defValue, TypeTag<T> tag)
{
if (instance.IsValid(index))
return LuaImplQueryArg(instance, index, arg, tag);
else
{
*arg = defValue;
return 1;
}
}
template<typename T>
unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, TypeTag<const T&>)
{
return LuaImplQueryArg(instance, index, arg, TypeTag<T>());
}
template<typename T>
unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, const T& defValue, TypeTag<const T&>)
{
return LuaImplQueryArg(instance, index, arg, defValue, TypeTag<T>());
}
// Function returns
inline int LuaImplReplyVal(const LuaInstance& instance, bool val, TypeTag<bool>)
{
instance.PushBoolean(val);
return 1;
}
inline int LuaImplReplyVal(const LuaInstance& instance, double val, TypeTag<double>)
{
instance.PushNumber(val);
return 1;
}
inline int LuaImplReplyVal(const LuaInstance& instance, float val, TypeTag<float>)
{
instance.PushNumber(val);
return 1;
}
template<typename T>
std::enable_if_t<std::is_enum<T>::value && !EnumAsFlags<T>::value, int> LuaImplReplyVal(const LuaInstance& instance, T val, TypeTag<T>)
{
using EnumT = typename std::underlying_type<T>::type;
return LuaImplReplyVal(instance, static_cast<EnumT>(val), TypeTag<EnumT>());
}
template<typename T>
std::enable_if_t<std::is_enum<T>::value && EnumAsFlags<T>::value, int> LuaImplReplyVal(const LuaInstance& instance, T val, TypeTag<T>)
{
Flags<T> flags(val);
return LuaImplReplyVal(instance, flags, TypeTag<decltype(flags)>());
}
template<typename E>
int LuaImplReplyVal(const LuaInstance& instance, Flags<E> val, TypeTag<Flags<E>>)
{
instance.PushInteger(UInt32(val));
return 1;
}
template<typename T>
std::enable_if_t<std::is_integral<T>::value, int> LuaImplReplyVal(const LuaInstance& instance, T val, TypeTag<T>)
{
instance.PushInteger(val);
return 1;
}
template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value || std::is_enum<T>::value, int> LuaImplReplyVal(const LuaInstance& instance, T val, TypeTag<T&>)
{
return LuaImplReplyVal(instance, val, TypeTag<T>());
}
template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value || std::is_enum<T>::value, int> LuaImplReplyVal(const LuaInstance& instance, T val, TypeTag<const T&>)
{
return LuaImplReplyVal(instance, val, TypeTag<T>());
}
template<typename T>
std::enable_if_t<!std::is_arithmetic<T>::value && !std::is_enum<T>::value, int> LuaImplReplyVal(const LuaInstance& instance, T val, TypeTag<T&>)
{
return LuaImplReplyVal(instance, std::move(val), TypeTag<T>());
}
template<typename T>
std::enable_if_t<!std::is_arithmetic<T>::value && !std::is_enum<T>::value, int> LuaImplReplyVal(const LuaInstance& instance, T val, TypeTag<const T&>)
{
return LuaImplReplyVal(instance, std::move(val), TypeTag<T>());
}
template<typename T>
int LuaImplReplyVal(const LuaInstance& instance, T&& val, TypeTag<T&&>)
{
return LuaImplReplyVal(instance, std::forward<T>(val), TypeTag<T>());
}
inline int LuaImplReplyVal(const LuaInstance& instance, std::string&& val, TypeTag<std::string>)
{
instance.PushString(val.c_str(), val.size());
return 1;
}
template<typename T>
inline int LuaImplReplyVal(const LuaInstance& instance, std::vector<T>&& valContainer, TypeTag<std::vector<T>>)
{
std::size_t index = 1;
instance.PushTable(valContainer.size());
for (T& val : valContainer)
{
instance.PushInteger(index++);
if (LuaImplReplyVal(instance, std::move(val), TypeTag<T>()) != 1)
{
instance.Error("Couldn't create table: type need more than one place to store");
return 0;
}
instance.SetTable();
}
return 1;
}
inline int LuaImplReplyVal(const LuaInstance& instance, ByteArray&& val, TypeTag<ByteArray>)
{
instance.PushString(reinterpret_cast<const char*>(val.GetConstBuffer()), val.GetSize());
return 1;
}
inline int LuaImplReplyVal(const LuaInstance& instance, String&& val, TypeTag<String>)
{
instance.PushString(std::move(val));
return 1;
}
template<typename T1, typename T2>
int LuaImplReplyVal(const LuaInstance& instance, std::pair<T1, T2>&& val, TypeTag<std::pair<T1, T2>>)
{
int retVal = 0;
retVal += LuaImplReplyVal(instance, std::move(val.first), TypeTag<T1>());
retVal += LuaImplReplyVal(instance, std::move(val.second), TypeTag<T2>());
return retVal;
}
template<bool HasDefault>
struct LuaImplArgProcesser;
template<>
struct LuaImplArgProcesser<true>
{
template<std::size_t N, std::size_t FirstDefArg, typename ArgType, typename ArgContainer, typename DefArgContainer>
static unsigned int Process(const LuaInstance& instance, unsigned int argIndex, ArgContainer& args, DefArgContainer& defArgs)
{
return LuaImplQueryArg(instance, argIndex, &std::get<N>(args), std::get<FirstDefArg + std::tuple_size<DefArgContainer>() - N - 1>(defArgs), TypeTag<ArgType>());
}
};
template<>
struct LuaImplArgProcesser<false>
{
template<std::size_t N, std::size_t FirstDefArg, typename ArgType, typename ArgContainer, typename DefArgContainer>
static unsigned int Process(const LuaInstance& instance, unsigned int argIndex, ArgContainer& args, DefArgContainer& defArgs)
{
NazaraUnused(defArgs);
return LuaImplQueryArg(instance, argIndex, &std::get<N>(args), TypeTag<ArgType>());
}
};
template<typename... Args>
class LuaImplFunctionProxy
{
public:
template<typename... DefArgs>
class Impl
{
static constexpr std::size_t ArgCount = sizeof...(Args);
static constexpr std::size_t DefArgCount = sizeof...(DefArgs);
static_assert(ArgCount >= DefArgCount, "There cannot be more default arguments than argument");
static constexpr std::size_t FirstDefArg = ArgCount - DefArgCount;
public:
Impl(DefArgs... defArgs) :
m_defaultArgs(std::forward<DefArgs>(defArgs)...)
{
}
void ProcessArguments(const LuaInstance& instance) const
{
m_index = 1;
ProcessArgs<0, Args...>(instance);
}
int Invoke(const LuaInstance& instance, void(*func)(Args...)) const
{
NazaraUnused(instance);
Apply(func, m_args);
return 0;
}
template<typename Ret>
int Invoke(const LuaInstance& instance, Ret(*func)(Args...)) const
{
return LuaImplReplyVal(instance, std::move(Apply(func, m_args)), TypeTag<decltype(Apply(func, m_args))>());
}
private:
using ArgContainer = std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>;
using DefArgContainer = std::tuple<std::remove_cv_t<std::remove_reference_t<DefArgs>>...>;
template<std::size_t N>
void ProcessArgs(const LuaInstance& instance) const
{
NazaraUnused(instance);
// No argument to process
}
template<std::size_t N, typename ArgType>
void ProcessArgs(const LuaInstance& instance) const
{
LuaImplArgProcesser<(N >= FirstDefArg)>::template Process<N, FirstDefArg, ArgType>(instance, m_index, m_args, m_defaultArgs);
}
template<std::size_t N, typename ArgType1, typename ArgType2, typename... Rest>
void ProcessArgs(const LuaInstance& instance) const
{
ProcessArgs<N, ArgType1>(instance);
ProcessArgs<N + 1, ArgType2, Rest...>(instance);
}
mutable ArgContainer m_args;
DefArgContainer m_defaultArgs;
mutable unsigned int m_index;
};
};
template<typename... Args>
class LuaImplMethodProxy
{
public:
template<typename... DefArgs>
class Impl
{
static constexpr std::size_t ArgCount = sizeof...(Args);
static constexpr std::size_t DefArgCount = sizeof...(DefArgs);
static_assert(ArgCount >= DefArgCount, "There cannot be more default arguments than argument");
static constexpr std::size_t FirstDefArg = ArgCount - DefArgCount;
public:
Impl(DefArgs... defArgs) :
m_defaultArgs(std::forward<DefArgs>(defArgs)...)
{
}
void ProcessArguments(const LuaInstance& instance) const
{
m_index = 2; //< 1 being the instance
ProcessArgs<0, Args...>(instance);
}
template<typename T, typename P>
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaInstance& instance, T& object, void(P::*func)(Args...)) const
{
NazaraUnused(instance);
Apply(object, func, m_args);
return 0;
}
template<typename T, typename P, typename Ret>
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaInstance& instance, T& object, Ret(P::*func)(Args...)) const
{
return LuaImplReplyVal(instance, std::move(Apply(object, func, m_args)), TypeTag<decltype(Apply(object, func, m_args))>());
}
template<typename T, typename P>
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaInstance& instance, T& object, T&(P::*func)(Args...)) const
{
T& r = Apply(object, func, m_args);
if (&r == &object)
{
instance.PushValue(1); //< Userdata
return 1;
}
else
return LuaImplReplyVal(instance, r, TypeTag<T&>());
}
template<typename T, typename P>
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaInstance& instance, const T& object, void(P::*func)(Args...) const) const
{
NazaraUnused(instance);
Apply(object, func, m_args);
return 0;
}
template<typename T, typename P, typename Ret>
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaInstance& instance, const T& object, Ret(P::*func)(Args...) const) const
{
return LuaImplReplyVal(instance, std::move(Apply(object, func, m_args)), TypeTag<decltype(Apply(object, func, m_args))>());
}
template<typename T, typename P>
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaInstance& instance, const T& object, const T&(P::*func)(Args...) const) const
{
const T& r = Apply(object, func, m_args);
if (&r == &object)
{
instance.PushValue(1); //< Userdata
return 1;
}
else
return LuaImplReplyVal(instance, r, TypeTag<T&>());
}
template<typename T, typename P>
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaInstance& instance, T& object, void(P::*func)(Args...)) const
{
if (!object)
{
instance.Error("Invalid object");
return 0;
}
Apply(*object, func, m_args);
return 0;
}
template<typename T, typename P, typename Ret>
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaInstance& instance, T& object, Ret(P::*func)(Args...)) const
{
if (!object)
{
instance.Error("Invalid object");
return 0;
}
return LuaImplReplyVal(instance, std::move(Apply(*object, func, m_args)), TypeTag<decltype(Apply(*object, func, m_args))>());
}
template<typename T, typename P>
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaInstance& instance, T& object, typename PointedType<T>::type&(P::*func)(Args...) const) const
{
if (!object)
{
instance.Error("Invalid object");
return 0;
}
const typename PointedType<T>::type& r = Apply(*object, func, m_args);
if (&r == &*object)
{
instance.PushValue(1); //< Userdata
return 1;
}
else
return LuaImplReplyVal(instance, r, TypeTag<T&>());
}
template<typename T, typename P>
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaInstance& instance, const T& object, void(P::*func)(Args...) const) const
{
if (!object)
{
instance.Error("Invalid object");
return 0;
}
Apply(*object, func, m_args);
return 0;
}
template<typename T, typename P, typename Ret>
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaInstance& instance, const T& object, Ret(P::*func)(Args...) const) const
{
if (!object)
{
instance.Error("Invalid object");
return 0;
}
return LuaImplReplyVal(instance, std::move(Apply(*object, func, m_args)), TypeTag<decltype(Apply(*object, func, m_args))>());
}
template<typename T, typename P>
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaInstance& instance, const T& object, const typename PointedType<T>::type&(P::*func)(Args...) const) const
{
if (!object)
{
instance.Error("Invalid object");
return 0;
}
const typename PointedType<T>::type& r = Apply(*object, func, m_args);
if (&r == &*object)
{
instance.PushValue(1); //< Userdata
return 1;
}
else
return LuaImplReplyVal(instance, r, TypeTag<T&>());
}
private:
using ArgContainer = std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>;
using DefArgContainer = std::tuple<std::remove_cv_t<std::remove_reference_t<DefArgs>>...>;
template<std::size_t N>
void ProcessArgs(const LuaInstance& instance) const
{
NazaraUnused(instance);
// No argument to process
}
template<std::size_t N, typename ArgType>
void ProcessArgs(const LuaInstance& instance) const
{
m_index += LuaImplArgProcesser<(N >= FirstDefArg)>::template Process<N, FirstDefArg, ArgType>(instance, m_index, m_args, m_defaultArgs);
}
template<std::size_t N, typename ArgType1, typename ArgType2, typename... Rest>
void ProcessArgs(const LuaInstance& instance) const
{
ProcessArgs<N, ArgType1>(instance);
ProcessArgs<N + 1, ArgType2, Rest...>(instance);
}
mutable ArgContainer m_args;
DefArgContainer m_defaultArgs;
mutable unsigned int m_index;
};
};
template<typename T>
T LuaInstance::Check(int* index) const
{
NazaraAssert(index, "Invalid index pointer");
T object;
*index += LuaImplQueryArg(*this, *index, &object, TypeTag<T>());
return object;
}
template<typename T>
T LuaInstance::Check(int* index, T defValue) const
{
NazaraAssert(index, "Invalid index pointer");
T object;
*index += LuaImplQueryArg(*this, *index, &object, defValue, TypeTag<T>());
return object;
}
template<typename T>
inline T LuaInstance::CheckBoundInteger(int index) const
{
return CheckBounds<T>(index, CheckInteger(index));
}
template<typename T>
inline T LuaInstance::CheckBoundInteger(int index, T defValue) const
{
return CheckBounds<T>(index, CheckInteger(index, defValue));
}
template<typename T>
T LuaInstance::CheckField(const char* fieldName, int tableIndex) const
{
T object;
GetField(fieldName, tableIndex);
tableIndex += LuaImplQueryArg(*this, -1, &object, TypeTag<T>());
Pop();
return object;
}
template<typename T>
T LuaInstance::CheckField(const String& fieldName, int tableIndex) const
{
return CheckField<T>(fieldName.GetConstBuffer(), tableIndex);
}
template<typename T>
T LuaInstance::CheckField(const char* fieldName, T defValue, int tableIndex) const
{
T object;
GetField(fieldName, tableIndex);
tableIndex += LuaImplQueryArg(*this, -1, &object, defValue, TypeTag<T>());
Pop();
return object;
}
template<typename T>
T LuaInstance::CheckField(const String& fieldName, T defValue, int tableIndex) const
{
return CheckField<T>(fieldName.GetConstBuffer(), defValue, tableIndex);
}
template<typename T>
T LuaInstance::CheckGlobal(const char* fieldName) const
{
T object;
GetGlobal(fieldName);
LuaImplQueryArg(*this, -1, &object, TypeTag<T>());
Pop();
return object;
}
template<typename T>
T LuaInstance::CheckGlobal(const String& fieldName) const
{
return CheckGlobal<T>(fieldName.GetConstBuffer());
}
template<typename T>
T LuaInstance::CheckGlobal(const char* fieldName, T defValue) const
{
T object;
GetGlobal(fieldName);
LuaImplQueryArg(*this, -1, &object, defValue, TypeTag<T>());
Pop();
return object;
}
template<typename T>
T LuaInstance::CheckGlobal(const String& fieldName, T defValue) const
{
return CheckGlobal<T>(fieldName.GetConstBuffer(), defValue);
}
template<typename T>
int LuaInstance::Push(T arg) const
{
return LuaImplReplyVal(*this, std::move(arg), TypeTag<T>());
}
template<typename T, typename T2, typename... Args>
int LuaInstance::Push(T firstArg, T2 secondArg, Args... args) const
{
int valCount = 0;
valCount += Push(std::move(firstArg));
valCount += Push(secondArg, std::forward<Args>(args)...);
return valCount;
}
template<typename T>
void LuaInstance::PushField(const char* name, T&& arg, int tableIndex) const
{
Push<T>(std::forward<T>(arg));
SetField(name, tableIndex);
}
template<typename T>
void LuaInstance::PushField(const String& name, T&& arg, int tableIndex) const
{
PushField(name.GetConstBuffer(), std::forward<T>(arg), tableIndex);
}
template<typename R, typename... Args, typename... DefArgs>
void LuaInstance::PushFunction(R(*func)(Args...), DefArgs&&... defArgs) const
{
typename LuaImplFunctionProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
PushFunction([func, handler] (LuaInstance& lua) -> int
{
handler.ProcessArguments(lua);
return handler.Invoke(lua, func);
});
}
template<typename T>
void LuaInstance::PushGlobal(const char* name, T&& arg)
{
Push<T>(std::forward<T>(arg));
SetGlobal(name);
}
template<typename T>
void LuaInstance::PushGlobal(const String& name, T&& arg)
{
PushGlobal(name.GetConstBuffer(), std::forward<T>(arg));
}
template<typename T>
void LuaInstance::PushInstance(const char* tname, const T& instance) const
{
T* userdata = static_cast<T*>(PushUserdata(sizeof(T)));
PlacementNew(userdata, instance);
SetMetatable(tname);
}
template<typename T>
void LuaInstance::PushInstance(const char* tname, T&& instance) const
{
T* userdata = static_cast<T*>(PushUserdata(sizeof(T)));
PlacementNew(userdata, std::move(instance));
SetMetatable(tname);
}
template<typename T, typename... Args>
void LuaInstance::PushInstance(const char* tname, Args&&... args) const
{
T* userdata = static_cast<T*>(PushUserdata(sizeof(T)));
PlacementNew(userdata, std::forward<Args>(args)...);
SetMetatable(tname);
}
template<typename T>
T LuaInstance::CheckBounds(int index, long long value) const
{
constexpr long long minBounds = std::numeric_limits<T>::min();
constexpr long long maxBounds = std::numeric_limits<T>::max();
if (value < minBounds || value > maxBounds)
{
Nz::StringStream stream;
stream << "Argument #" << index << " is outside value range [" << minBounds << ", " << maxBounds << "] (" << value << ')';
Error(stream);
}
return static_cast<T>(value);
}
}

View File

@@ -0,0 +1,197 @@
// Copyright (C) 2017 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
#pragma once
#ifndef NAZARA_LUASTATE_HPP
#define NAZARA_LUASTATE_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Clock.hpp>
#include <Nazara/Core/Stream.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Lua/Config.hpp>
#include <Nazara/Lua/Enums.hpp>
#include <cstddef>
#include <functional>
struct lua_Debug;
struct lua_State;
namespace Nz
{
class LuaCoroutine;
class LuaInstance;
class LuaState;
using LuaCFunction = int (*)(lua_State* internalState);
using LuaFunction = std::function<int(LuaState& state)>;
class NAZARA_LUA_API LuaState
{
public:
LuaState(const LuaState&) = default;
LuaState(LuaState&& instance) noexcept;
~LuaState() = default;
void ArgCheck(bool condition, unsigned int argNum, const char* error) const;
void ArgCheck(bool condition, unsigned int argNum, const String& error) const;
int ArgError(unsigned int argNum, const char* error) const;
int ArgError(unsigned int argNum, const String& error) const;
bool Call(unsigned int argCount);
bool Call(unsigned int argCount, unsigned int resultCount);
template<typename T> T Check(int* index) const;
template<typename T> T Check(int* index, T defValue) const;
void CheckAny(int index) const;
bool CheckBoolean(int index) const;
bool CheckBoolean(int index, bool defValue) const;
template<typename T> T CheckBoundInteger(int index) const;
template<typename T> T CheckBoundInteger(int index, T defValue) const;
template<typename T> T CheckField(const char* fieldName, int tableIndex = -1) const;
template<typename T> T CheckField(const String& fieldName, int tableIndex = -1) const;
template<typename T> T CheckField(const char* fieldName, T defValue, int tableIndex = -1) const;
template<typename T> T CheckField(const String& fieldName, T defValue, int tableIndex = -1) const;
long long CheckInteger(int index) const;
long long CheckInteger(int index, long long defValue) const;
template<typename T> T CheckGlobal(const char* fieldName) const;
template<typename T> T CheckGlobal(const String& fieldName) const;
template<typename T> T CheckGlobal(const char* fieldName, T defValue) const;
template<typename T> T CheckGlobal(const String& fieldName, T defValue) const;
double CheckNumber(int index) const;
double CheckNumber(int index, double defValue) const;
void CheckStack(int space, const char* error = nullptr) const;
void CheckStack(int space, const String& error) const;
const char* CheckString(int index, std::size_t* length = nullptr) const;
const char* CheckString(int index, const char* defValue, std::size_t* length = nullptr) const;
void CheckType(int index, LuaType type) const;
void* CheckUserdata(int index, const char* tname) const;
void* CheckUserdata(int index, const String& tname) const;
bool Compare(int index1, int index2, LuaComparison comparison) const;
void Compute(LuaOperation operation) const;
void Concatenate(int count) const;
int CreateReference();
void DestroyReference(int ref);
String DumpStack() const;
void Error(const char* message) const;
void Error(const String& message) const;
bool Execute(const String& code);
bool ExecuteFromFile(const String& filePath);
bool ExecuteFromMemory(const void* data, std::size_t size);
bool ExecuteFromStream(Stream& stream);
int GetAbsIndex(int index) const;
LuaType GetField(const char* fieldName, int tableIndex = -1) const;
LuaType GetField(const String& fieldName, int tableIndex = -1) const;
LuaType GetGlobal(const char* name) const;
LuaType GetGlobal(const String& name) const;
inline lua_State* GetInternalState() const;
inline String GetLastError() const;
LuaType GetMetatable(const char* tname) const;
LuaType GetMetatable(const String& tname) const;
bool GetMetatable(int index) const;
unsigned int GetStackTop() const;
LuaType GetTable(int index = -2) const;
LuaType GetTableRaw(int index = -2) const;
LuaType GetType(int index) const;
const char* GetTypeName(LuaType type) const;
void Insert(int index) const;
bool IsOfType(int index, LuaType type) const;
bool IsOfType(int index, const char* tname) const;
bool IsOfType(int index, const String& tname) const;
bool IsValid(int index) const;
long long Length(int index) const;
std::size_t LengthRaw(int index) const;
void MoveTo(LuaState* instance, int n) const;
LuaCoroutine NewCoroutine();
bool NewMetatable(const char* str);
bool NewMetatable(const String& str);
bool Next(int index = -2) const;
void Pop(unsigned int n = 1U) const;
template<typename T> int Push(T arg) const;
template<typename T, typename T2, typename... Args> int Push(T firstArg, T2 secondArg, Args... args) const;
void PushBoolean(bool value) const;
void PushCFunction(LuaCFunction func, unsigned int upvalueCount = 0) const;
template<typename T> void PushField(const char* name, T&& arg, int tableIndex = -2) const;
template<typename T> void PushField(const String& name, T&& arg, int tableIndex = -2) const;
void PushFunction(LuaFunction func) const;
template<typename R, typename... Args, typename... DefArgs> void PushFunction(R(*func)(Args...), DefArgs&&... defArgs) const;
template<typename T> void PushGlobal(const char* name, T&& arg);
template<typename T> void PushGlobal(const String& name, T&& arg);
template<typename T> void PushInstance(const char* tname, const T& instance) const;
template<typename T> void PushInstance(const char* tname, T&& instance) const;
template<typename T, typename... Args> void PushInstance(const char* tname, Args&&... args) const;
void PushInteger(long long value) const;
void PushLightUserdata(void* value) const;
void PushMetatable(const char* str) const;
void PushMetatable(const String& str) const;
void PushNil() const;
void PushNumber(double value) const;
void PushReference(int ref) const;
void PushString(const char* str) const;
void PushString(const char* str, std::size_t size) const;
void PushString(const String& str) const;
void PushTable(std::size_t sequenceElementCount = 0, std::size_t arrayElementCount = 0) const;
void* PushUserdata(std::size_t size) const;
void PushValue(int index) const;
void Remove(int index) const;
void Replace(int index) const;
void SetField(const char* name, int tableIndex = -2) const;
void SetField(const String& name, int tableIndex = -2) const;
void SetGlobal(const char* name);
void SetGlobal(const String& name);
void SetMetatable(const char* tname) const;
void SetMetatable(const String& tname) const;
void SetMetatable(int index) const;
void SetTable(int index = -3) const;
void SetTableRaw(int index = -3) const;
bool ToBoolean(int index) const;
long long ToInteger(int index, bool* succeeded = nullptr) const;
double ToNumber(int index, bool* succeeded = nullptr) const;
const void* ToPointer(int index) const;
const char* ToString(int index, std::size_t* length = nullptr) const;
void* ToUserdata(int index) const;
void* ToUserdata(int index, const char* tname) const;
void* ToUserdata(int index, const String& tname) const;
LuaState& operator=(const LuaState&) = default;
LuaState& operator=(LuaState&& instance) noexcept;
static int GetIndexOfUpValue(int upValue);
static LuaInstance& GetInstance(lua_State* internalState);
static inline LuaState GetState(lua_State* internalState);
protected:
LuaState(lua_State* internalState);
template<typename T> T CheckBounds(int index, long long value) const;
virtual bool Run(int argCount, int resultCount);
static int ProxyFunc(lua_State* internalState);
String m_lastError;
lua_State* m_state;
};
}
#include <Nazara/Lua/LuaState.inl>
#endif // NAZARA_LUASTATE_HPP

View File

@@ -0,0 +1,792 @@
// Copyright (C) 2017 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 <Nazara/Lua/LuaState.hpp>
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Core/Flags.hpp>
#include <Nazara/Core/MemoryHelper.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <Nazara/Math/Algorithm.hpp>
#include <limits>
#include <string>
#include <vector>
#include <type_traits>
namespace Nz
{
inline LuaState::LuaState(lua_State* internalState) :
m_state(internalState)
{
}
inline lua_State* LuaState::GetInternalState() const
{
return m_state;
}
inline String LuaState::GetLastError() const
{
return m_lastError;
}
// Functions args
inline unsigned int LuaImplQueryArg(const LuaState& instance, int index, bool* arg, TypeTag<bool>)
{
*arg = instance.CheckBoolean(index);
return 1;
}
inline unsigned int LuaImplQueryArg(const LuaState& instance, int index, bool* arg, bool defValue, TypeTag<bool>)
{
*arg = instance.CheckBoolean(index, defValue);
return 1;
}
inline unsigned int LuaImplQueryArg(const LuaState& instance, int index, std::string* arg, TypeTag<std::string>)
{
std::size_t strLength = 0;
const char* str = instance.CheckString(index, &strLength);
arg->assign(str, strLength);
return 1;
}
inline unsigned int LuaImplQueryArg(const LuaState& instance, int index, String* arg, TypeTag<String>)
{
std::size_t strLength = 0;
const char* str = instance.CheckString(index, &strLength);
arg->Set(str, strLength);
return 1;
}
template<typename T>
std::enable_if_t<std::is_enum<T>::value && !EnumAsFlags<T>::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, TypeTag<T>)
{
using UnderlyingT = std::underlying_type_t<T>;
return LuaImplQueryArg(instance, index, reinterpret_cast<UnderlyingT*>(arg), TypeTag<UnderlyingT>());
}
template<typename T>
std::enable_if_t<std::is_enum<T>::value && !EnumAsFlags<T>::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, T defValue, TypeTag<T>)
{
using UnderlyingT = std::underlying_type_t<T>;
return LuaImplQueryArg(instance, index, reinterpret_cast<UnderlyingT*>(arg), static_cast<UnderlyingT>(defValue), TypeTag<UnderlyingT>());
}
template<typename T>
std::enable_if_t<std::is_enum<T>::value && EnumAsFlags<T>::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, TypeTag<T>)
{
using UnderlyingT = std::underlying_type_t<T>;
UnderlyingT pot2Val;
unsigned int ret = LuaImplQueryArg(instance, index, &pot2Val, TypeTag<UnderlyingT>());
*arg = static_cast<T>(IntegralLog2Pot(pot2Val));
return ret;
}
template<typename T>
std::enable_if_t<std::is_enum<T>::value && EnumAsFlags<T>::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, T defValue, TypeTag<T>)
{
using UnderlyingT = std::underlying_type_t<T>;
UnderlyingT pot2Val;
unsigned int ret = LuaImplQueryArg(instance, index, &pot2Val, 1U << static_cast<UnderlyingT>(defValue), TypeTag<UnderlyingT>());
*arg = static_cast<T>(IntegralLog2Pot(pot2Val));
return ret;
}
template<typename E>
unsigned int LuaImplQueryArg(const LuaState& instance, int index, Flags<E>* arg, TypeTag<Flags<E>>)
{
*arg = Flags<E>(instance.CheckBoundInteger<UInt32>(index));
return 1;
}
template<typename T>
std::enable_if_t<std::is_floating_point<T>::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, TypeTag<T>)
{
*arg = static_cast<T>(instance.CheckNumber(index));
return 1;
}
template<typename T>
std::enable_if_t<std::is_floating_point<T>::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, T defValue, TypeTag<T>)
{
*arg = static_cast<T>(instance.CheckNumber(index, static_cast<double>(defValue)));
return 1;
}
template<typename T>
std::enable_if_t<std::is_integral<T>::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, TypeTag<T>)
{
*arg = instance.CheckBoundInteger<T>(index);
return 1;
}
template<typename T>
std::enable_if_t<std::is_integral<T>::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, T defValue, TypeTag<T>)
{
*arg = instance.CheckBoundInteger<T>(index, defValue);
return 1;
}
template<typename T>
std::enable_if_t<!std::is_integral<T>::value && !std::is_enum<T>::value && !std::is_floating_point<T>::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, const T& defValue, TypeTag<T> tag)
{
if (instance.IsValid(index))
return LuaImplQueryArg(instance, index, arg, tag);
else
{
*arg = defValue;
return 1;
}
}
template<typename T>
unsigned int LuaImplQueryArg(const LuaState& instance, int index, T* arg, TypeTag<const T&>)
{
return LuaImplQueryArg(instance, index, arg, TypeTag<T>());
}
template<typename T>
unsigned int LuaImplQueryArg(const LuaState& instance, int index, T* arg, const T& defValue, TypeTag<const T&>)
{
return LuaImplQueryArg(instance, index, arg, defValue, TypeTag<T>());
}
// Function returns
inline int LuaImplReplyVal(const LuaState& instance, bool val, TypeTag<bool>)
{
instance.PushBoolean(val);
return 1;
}
inline int LuaImplReplyVal(const LuaState& instance, double val, TypeTag<double>)
{
instance.PushNumber(val);
return 1;
}
inline int LuaImplReplyVal(const LuaState& instance, float val, TypeTag<float>)
{
instance.PushNumber(val);
return 1;
}
template<typename T>
std::enable_if_t<std::is_enum<T>::value && !EnumAsFlags<T>::value, int> LuaImplReplyVal(const LuaState& instance, T val, TypeTag<T>)
{
using EnumT = typename std::underlying_type<T>::type;
return LuaImplReplyVal(instance, static_cast<EnumT>(val), TypeTag<EnumT>());
}
template<typename T>
std::enable_if_t<std::is_enum<T>::value && EnumAsFlags<T>::value, int> LuaImplReplyVal(const LuaState& instance, T val, TypeTag<T>)
{
Flags<T> flags(val);
return LuaImplReplyVal(instance, flags, TypeTag<decltype(flags)>());
}
template<typename E>
int LuaImplReplyVal(const LuaState& instance, Flags<E> val, TypeTag<Flags<E>>)
{
instance.PushInteger(UInt32(val));
return 1;
}
template<typename T>
std::enable_if_t<std::is_integral<T>::value, int> LuaImplReplyVal(const LuaState& instance, T val, TypeTag<T>)
{
instance.PushInteger(val);
return 1;
}
template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value || std::is_enum<T>::value, int> LuaImplReplyVal(const LuaState& instance, T val, TypeTag<T&>)
{
return LuaImplReplyVal(instance, val, TypeTag<T>());
}
template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value || std::is_enum<T>::value, int> LuaImplReplyVal(const LuaState& instance, T val, TypeTag<const T&>)
{
return LuaImplReplyVal(instance, val, TypeTag<T>());
}
template<typename T>
std::enable_if_t<!std::is_arithmetic<T>::value && !std::is_enum<T>::value, int> LuaImplReplyVal(const LuaState& instance, T val, TypeTag<T&>)
{
return LuaImplReplyVal(instance, std::move(val), TypeTag<T>());
}
template<typename T>
std::enable_if_t<!std::is_arithmetic<T>::value && !std::is_enum<T>::value, int> LuaImplReplyVal(const LuaState& instance, T val, TypeTag<const T&>)
{
return LuaImplReplyVal(instance, std::move(val), TypeTag<T>());
}
template<typename T>
int LuaImplReplyVal(const LuaState& instance, T&& val, TypeTag<T&&>)
{
return LuaImplReplyVal(instance, std::forward<T>(val), TypeTag<T>());
}
inline int LuaImplReplyVal(const LuaState& instance, std::string&& val, TypeTag<std::string>)
{
instance.PushString(val.c_str(), val.size());
return 1;
}
template<typename T>
inline int LuaImplReplyVal(const LuaState& instance, std::vector<T>&& valContainer, TypeTag<std::vector<T>>)
{
std::size_t index = 1;
instance.PushTable(valContainer.size());
for (T& val : valContainer)
{
instance.PushInteger(index++);
if (LuaImplReplyVal(instance, std::move(val), TypeTag<T>()) != 1)
{
instance.Error("Couldn't create table: type need more than one place to store");
return 0;
}
instance.SetTable();
}
return 1;
}
inline int LuaImplReplyVal(const LuaState& instance, ByteArray&& val, TypeTag<ByteArray>)
{
instance.PushString(reinterpret_cast<const char*>(val.GetConstBuffer()), val.GetSize());
return 1;
}
inline int LuaImplReplyVal(const LuaState& instance, String&& val, TypeTag<String>)
{
instance.PushString(std::move(val));
return 1;
}
template<typename T1, typename T2>
int LuaImplReplyVal(const LuaState& instance, std::pair<T1, T2>&& val, TypeTag<std::pair<T1, T2>>)
{
int retVal = 0;
retVal += LuaImplReplyVal(instance, std::move(val.first), TypeTag<T1>());
retVal += LuaImplReplyVal(instance, std::move(val.second), TypeTag<T2>());
return retVal;
}
template<bool HasDefault>
struct LuaImplArgProcesser;
template<>
struct LuaImplArgProcesser<true>
{
template<std::size_t N, std::size_t FirstDefArg, typename ArgType, typename ArgContainer, typename DefArgContainer>
static unsigned int Process(const LuaState& instance, unsigned int argIndex, ArgContainer& args, DefArgContainer& defArgs)
{
return LuaImplQueryArg(instance, argIndex, &std::get<N>(args), std::get<FirstDefArg + std::tuple_size<DefArgContainer>() - N - 1>(defArgs), TypeTag<ArgType>());
}
};
template<>
struct LuaImplArgProcesser<false>
{
template<std::size_t N, std::size_t FirstDefArg, typename ArgType, typename ArgContainer, typename DefArgContainer>
static unsigned int Process(const LuaState& instance, unsigned int argIndex, ArgContainer& args, DefArgContainer& defArgs)
{
NazaraUnused(defArgs);
return LuaImplQueryArg(instance, argIndex, &std::get<N>(args), TypeTag<ArgType>());
}
};
template<typename... Args>
class LuaImplFunctionProxy
{
public:
template<typename... DefArgs>
class Impl
{
static constexpr std::size_t ArgCount = sizeof...(Args);
static constexpr std::size_t DefArgCount = sizeof...(DefArgs);
static_assert(ArgCount >= DefArgCount, "There cannot be more default arguments than argument");
static constexpr std::size_t FirstDefArg = ArgCount - DefArgCount;
public:
Impl(DefArgs... defArgs) :
m_defaultArgs(std::forward<DefArgs>(defArgs)...)
{
}
void ProcessArguments(const LuaState& instance) const
{
m_index = 1;
ProcessArgs<0, Args...>(instance);
}
int Invoke(const LuaState& instance, void(*func)(Args...)) const
{
NazaraUnused(instance);
Apply(func, m_args);
return 0;
}
template<typename Ret>
int Invoke(const LuaState& instance, Ret(*func)(Args...)) const
{
return LuaImplReplyVal(instance, std::move(Apply(func, m_args)), TypeTag<decltype(Apply(func, m_args))>());
}
private:
using ArgContainer = std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>;
using DefArgContainer = std::tuple<std::remove_cv_t<std::remove_reference_t<DefArgs>>...>;
template<std::size_t N>
void ProcessArgs(const LuaState& instance) const
{
NazaraUnused(instance);
// No argument to process
}
template<std::size_t N, typename ArgType>
void ProcessArgs(const LuaState& instance) const
{
LuaImplArgProcesser<(N >= FirstDefArg)>::template Process<N, FirstDefArg, ArgType>(instance, m_index, m_args, m_defaultArgs);
}
template<std::size_t N, typename ArgType1, typename ArgType2, typename... Rest>
void ProcessArgs(const LuaState& instance) const
{
ProcessArgs<N, ArgType1>(instance);
ProcessArgs<N + 1, ArgType2, Rest...>(instance);
}
mutable ArgContainer m_args;
DefArgContainer m_defaultArgs;
mutable unsigned int m_index;
};
};
template<typename... Args>
class LuaImplMethodProxy
{
public:
template<typename... DefArgs>
class Impl
{
static constexpr std::size_t ArgCount = sizeof...(Args);
static constexpr std::size_t DefArgCount = sizeof...(DefArgs);
static_assert(ArgCount >= DefArgCount, "There cannot be more default arguments than argument");
static constexpr std::size_t FirstDefArg = ArgCount - DefArgCount;
public:
Impl(DefArgs... defArgs) :
m_defaultArgs(std::forward<DefArgs>(defArgs)...)
{
}
void ProcessArguments(const LuaState& instance) const
{
m_index = 2; //< 1 being the instance
ProcessArgs<0, Args...>(instance);
}
template<typename T, typename P>
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaState& instance, T& object, void(P::*func)(Args...)) const
{
NazaraUnused(instance);
Apply(object, func, m_args);
return 0;
}
template<typename T, typename P, typename Ret>
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaState& instance, T& object, Ret(P::*func)(Args...)) const
{
return LuaImplReplyVal(instance, std::move(Apply(object, func, m_args)), TypeTag<decltype(Apply(object, func, m_args))>());
}
template<typename T, typename P>
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaState& instance, T& object, T&(P::*func)(Args...)) const
{
T& r = Apply(object, func, m_args);
if (&r == &object)
{
instance.PushValue(1); //< Userdata
return 1;
}
else
return LuaImplReplyVal(instance, r, TypeTag<T&>());
}
template<typename T, typename P>
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaState& instance, const T& object, void(P::*func)(Args...) const) const
{
NazaraUnused(instance);
Apply(object, func, m_args);
return 0;
}
template<typename T, typename P, typename Ret>
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaState& instance, const T& object, Ret(P::*func)(Args...) const) const
{
return LuaImplReplyVal(instance, std::move(Apply(object, func, m_args)), TypeTag<decltype(Apply(object, func, m_args))>());
}
template<typename T, typename P>
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaState& instance, const T& object, const T&(P::*func)(Args...) const) const
{
const T& r = Apply(object, func, m_args);
if (&r == &object)
{
instance.PushValue(1); //< Userdata
return 1;
}
else
return LuaImplReplyVal(instance, r, TypeTag<T&>());
}
template<typename T, typename P>
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaState& instance, T& object, void(P::*func)(Args...)) const
{
if (!object)
{
instance.Error("Invalid object");
return 0;
}
Apply(*object, func, m_args);
return 0;
}
template<typename T, typename P, typename Ret>
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaState& instance, T& object, Ret(P::*func)(Args...)) const
{
if (!object)
{
instance.Error("Invalid object");
return 0;
}
return LuaImplReplyVal(instance, std::move(Apply(*object, func, m_args)), TypeTag<decltype(Apply(*object, func, m_args))>());
}
template<typename T, typename P>
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaState& instance, T& object, typename PointedType<T>::type&(P::*func)(Args...) const) const
{
if (!object)
{
instance.Error("Invalid object");
return 0;
}
const typename PointedType<T>::type& r = Apply(*object, func, m_args);
if (&r == &*object)
{
instance.PushValue(1); //< Userdata
return 1;
}
else
return LuaImplReplyVal(instance, r, TypeTag<T&>());
}
template<typename T, typename P>
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaState& instance, const T& object, void(P::*func)(Args...) const) const
{
if (!object)
{
instance.Error("Invalid object");
return 0;
}
Apply(*object, func, m_args);
return 0;
}
template<typename T, typename P, typename Ret>
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaState& instance, const T& object, Ret(P::*func)(Args...) const) const
{
if (!object)
{
instance.Error("Invalid object");
return 0;
}
return LuaImplReplyVal(instance, std::move(Apply(*object, func, m_args)), TypeTag<decltype(Apply(*object, func, m_args))>());
}
template<typename T, typename P>
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaState& instance, const T& object, const typename PointedType<T>::type&(P::*func)(Args...) const) const
{
if (!object)
{
instance.Error("Invalid object");
return 0;
}
const typename PointedType<T>::type& r = Apply(*object, func, m_args);
if (&r == &*object)
{
instance.PushValue(1); //< Userdata
return 1;
}
else
return LuaImplReplyVal(instance, r, TypeTag<T&>());
}
private:
using ArgContainer = std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>;
using DefArgContainer = std::tuple<std::remove_cv_t<std::remove_reference_t<DefArgs>>...>;
template<std::size_t N>
void ProcessArgs(const LuaState& instance) const
{
NazaraUnused(instance);
// No argument to process
}
template<std::size_t N, typename ArgType>
void ProcessArgs(const LuaState& instance) const
{
m_index += LuaImplArgProcesser<(N >= FirstDefArg)>::template Process<N, FirstDefArg, ArgType>(instance, m_index, m_args, m_defaultArgs);
}
template<std::size_t N, typename ArgType1, typename ArgType2, typename... Rest>
void ProcessArgs(const LuaState& instance) const
{
ProcessArgs<N, ArgType1>(instance);
ProcessArgs<N + 1, ArgType2, Rest...>(instance);
}
mutable ArgContainer m_args;
DefArgContainer m_defaultArgs;
mutable unsigned int m_index;
};
};
template<typename T>
T LuaState::Check(int* index) const
{
NazaraAssert(index, "Invalid index pointer");
T object;
*index += LuaImplQueryArg(*this, *index, &object, TypeTag<T>());
return object;
}
template<typename T>
T LuaState::Check(int* index, T defValue) const
{
NazaraAssert(index, "Invalid index pointer");
T object;
*index += LuaImplQueryArg(*this, *index, &object, defValue, TypeTag<T>());
return object;
}
template<typename T>
inline T LuaState::CheckBoundInteger(int index) const
{
return CheckBounds<T>(index, CheckInteger(index));
}
template<typename T>
inline T LuaState::CheckBoundInteger(int index, T defValue) const
{
return CheckBounds<T>(index, CheckInteger(index, defValue));
}
template<typename T>
T LuaState::CheckField(const char* fieldName, int tableIndex) const
{
T object;
GetField(fieldName, tableIndex);
tableIndex += LuaImplQueryArg(*this, -1, &object, TypeTag<T>());
Pop();
return object;
}
template<typename T>
T LuaState::CheckField(const String& fieldName, int tableIndex) const
{
return CheckField<T>(fieldName.GetConstBuffer(), tableIndex);
}
template<typename T>
T LuaState::CheckField(const char* fieldName, T defValue, int tableIndex) const
{
T object;
GetField(fieldName, tableIndex);
tableIndex += LuaImplQueryArg(*this, -1, &object, defValue, TypeTag<T>());
Pop();
return object;
}
template<typename T>
T LuaState::CheckField(const String& fieldName, T defValue, int tableIndex) const
{
return CheckField<T>(fieldName.GetConstBuffer(), defValue, tableIndex);
}
template<typename T>
T LuaState::CheckGlobal(const char* fieldName) const
{
T object;
GetGlobal(fieldName);
LuaImplQueryArg(*this, -1, &object, TypeTag<T>());
Pop();
return object;
}
template<typename T>
T LuaState::CheckGlobal(const String& fieldName) const
{
return CheckGlobal<T>(fieldName.GetConstBuffer());
}
template<typename T>
T LuaState::CheckGlobal(const char* fieldName, T defValue) const
{
T object;
GetGlobal(fieldName);
LuaImplQueryArg(*this, -1, &object, defValue, TypeTag<T>());
Pop();
return object;
}
template<typename T>
T LuaState::CheckGlobal(const String& fieldName, T defValue) const
{
return CheckGlobal<T>(fieldName.GetConstBuffer(), defValue);
}
template<typename T>
int LuaState::Push(T arg) const
{
return LuaImplReplyVal(*this, std::move(arg), TypeTag<T>());
}
template<typename T, typename T2, typename... Args>
int LuaState::Push(T firstArg, T2 secondArg, Args... args) const
{
int valCount = 0;
valCount += Push(std::move(firstArg));
valCount += Push(secondArg, std::forward<Args>(args)...);
return valCount;
}
template<typename T>
void LuaState::PushField(const char* name, T&& arg, int tableIndex) const
{
Push<T>(std::forward<T>(arg));
SetField(name, tableIndex);
}
template<typename T>
void LuaState::PushField(const String& name, T&& arg, int tableIndex) const
{
PushField(name.GetConstBuffer(), std::forward<T>(arg), tableIndex);
}
template<typename R, typename... Args, typename... DefArgs>
void LuaState::PushFunction(R(*func)(Args...), DefArgs&&... defArgs) const
{
typename LuaImplFunctionProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
PushFunction([func, handler] (LuaState& lua) -> int
{
handler.ProcessArguments(lua);
return handler.Invoke(lua, func);
});
}
template<typename T>
void LuaState::PushGlobal(const char* name, T&& arg)
{
Push<T>(std::forward<T>(arg));
SetGlobal(name);
}
template<typename T>
void LuaState::PushGlobal(const String& name, T&& arg)
{
PushGlobal(name.GetConstBuffer(), std::forward<T>(arg));
}
template<typename T>
void LuaState::PushInstance(const char* tname, const T& instance) const
{
T* userdata = static_cast<T*>(PushUserdata(sizeof(T)));
PlacementNew(userdata, instance);
SetMetatable(tname);
}
template<typename T>
void LuaState::PushInstance(const char* tname, T&& instance) const
{
T* userdata = static_cast<T*>(PushUserdata(sizeof(T)));
PlacementNew(userdata, std::move(instance));
SetMetatable(tname);
}
template<typename T, typename... Args>
void LuaState::PushInstance(const char* tname, Args&&... args) const
{
T* userdata = static_cast<T*>(PushUserdata(sizeof(T)));
PlacementNew(userdata, std::forward<Args>(args)...);
SetMetatable(tname);
}
template<typename T>
T LuaState::CheckBounds(int index, long long value) const
{
constexpr long long minBounds = std::numeric_limits<T>::min();
constexpr long long maxBounds = std::numeric_limits<T>::max();
if (value < minBounds || value > maxBounds)
{
Nz::StringStream stream;
stream << "Argument #" << index << " is outside value range [" << minBounds << ", " << maxBounds << "] (" << value << ')';
Error(stream);
}
return static_cast<T>(value);
}
inline LuaState LuaState::GetState(lua_State* internalState)
{
return LuaState(internalState);
}
}

View File

@@ -34,6 +34,7 @@
#include <Nazara/Network/Config.hpp>
#include <Nazara/Network/Enums.hpp>
#include <Nazara/Network/IpAddress.hpp>
#include <Nazara/Network/NetBuffer.hpp>
#include <Nazara/Network/NetPacket.hpp>
#include <Nazara/Network/Network.hpp>
#include <Nazara/Network/RUdpConnection.hpp>

View File

@@ -40,6 +40,7 @@
#include <Nazara/Utility/Config.hpp>
#include <Nazara/Utility/CubemapParams.hpp>
#include <Nazara/Utility/Cursor.hpp>
#include <Nazara/Utility/CursorController.hpp>
#include <Nazara/Utility/Enums.hpp>
#include <Nazara/Utility/Event.hpp>
#include <Nazara/Utility/EventHandler.hpp>
@@ -65,6 +66,7 @@
#include <Nazara/Utility/SimpleTextDrawer.hpp>
#include <Nazara/Utility/SkeletalMesh.hpp>
#include <Nazara/Utility/Skeleton.hpp>
#include <Nazara/Utility/SoftwareBuffer.hpp>
#include <Nazara/Utility/StaticMesh.hpp>
#include <Nazara/Utility/SubMesh.hpp>
#include <Nazara/Utility/TriangleIterator.hpp>

View File

@@ -65,7 +65,7 @@ namespace Nz
static inline bool Convert(PixelFormatType srcFormat, PixelFormatType dstFormat, const void* src, void* dst);
static inline bool Convert(PixelFormatType srcFormat, PixelFormatType dstFormat, const void* start, const void* end, void* dst);
static inline bool Flip(PixelFlipping flipping, PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth, const void* src, void* dst);
static bool Flip(PixelFlipping flipping, PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth, const void* src, void* dst);
static inline UInt8 GetBitsPerPixel(PixelFormatType format);
static inline PixelFormatContent GetContent(PixelFormatType format);

View File

@@ -227,102 +227,6 @@ namespace Nz
return true;
}
inline bool PixelFormat::Flip(PixelFlipping flipping, PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth, const void* src, void* dst)
{
#if NAZARA_UTILITY_SAFE
if (!IsValid(format))
{
NazaraError("Invalid pixel format");
return false;
}
#endif
auto it = s_flipFunctions[flipping].find(format);
if (it != s_flipFunctions[flipping].end())
it->second(width, height, depth, reinterpret_cast<const UInt8*>(src), reinterpret_cast<UInt8*>(dst));
else
{
// Flipping générique
#if NAZARA_UTILITY_SAFE
if (IsCompressed(format))
{
NazaraError("No function to flip compressed format");
return false;
}
#endif
UInt8 bpp = GetBytesPerPixel(format);
unsigned int lineStride = width*bpp;
switch (flipping)
{
case PixelFlipping_Horizontally:
{
if (src == dst)
{
for (unsigned int z = 0; z < depth; ++z)
{
UInt8* ptr = reinterpret_cast<UInt8*>(dst) + width*height*z;
for (unsigned int y = 0; y < height/2; ++y)
std::swap_ranges(&ptr[y*lineStride], &ptr[(y+1)*lineStride-1], &ptr[(height-y-1)*lineStride]);
}
}
else
{
for (unsigned int z = 0; z < depth; ++z)
{
const UInt8* srcPtr = reinterpret_cast<const UInt8*>(src);
UInt8* dstPtr = reinterpret_cast<UInt8*>(dst) + (width-1)*height*depth*bpp;
for (unsigned int y = 0; y < height; ++y)
{
std::memcpy(dstPtr, srcPtr, lineStride);
srcPtr += lineStride;
dstPtr -= lineStride;
}
}
}
break;
}
case PixelFlipping_Vertically:
{
if (src == dst)
{
for (unsigned int z = 0; z < depth; ++z)
{
UInt8* ptr = reinterpret_cast<UInt8*>(dst) + width*height*z;
for (unsigned int y = 0; y < height; ++y)
{
for (unsigned int x = 0; x < width/2; ++x)
std::swap_ranges(&ptr[x*bpp], &ptr[(x+1)*bpp], &ptr[(width-x)*bpp]);
ptr += lineStride;
}
}
}
else
{
for (unsigned int z = 0; z < depth; ++z)
{
UInt8* ptr = reinterpret_cast<UInt8*>(dst) + width*height*z;
for (unsigned int y = 0; y < height; ++y)
{
for (unsigned int x = 0; x < width; ++x)
std::memcpy(&ptr[x*bpp], &ptr[(width-x)*bpp], bpp);
ptr += lineStride;
}
}
}
break;
}
}
}
return true;
}
inline UInt8 PixelFormat::GetBitsPerPixel(PixelFormatType format)
{
return s_pixelFormatInfos[format].bitsPerPixel;