Added Lua module

Former-commit-id: 3f96b9aef8afffb5e8daf460480df2f3b8c37da7
This commit is contained in:
Lynix 2013-04-24 11:51:06 +02:00
parent 3ac0338285
commit 1e256bdf35
11 changed files with 1423 additions and 0 deletions

38
include/Nazara/Lua.hpp Normal file
View File

@ -0,0 +1,38 @@
// This file was automatically generated on 24 Apr 2013 at 11:49:37
/*
Nazara Engine - Lua scripting module
Copyright (C) 2013 Jérôme Leclercq (lynix680@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#ifndef NAZARA_GLOBAL_LUA_HPP
#define NAZARA_GLOBAL_LUA_HPP
#include <Nazara/Lua/Config.hpp>
#include <Nazara/Lua/Enums.hpp>
#include <Nazara/Lua/Lua.hpp>
#include <Nazara/Lua/LuaClass.hpp>
#include <Nazara/Lua/LuaInstance.hpp>
#endif // NAZARA_GLOBAL_LUA_HPP

View File

@ -0,0 +1,38 @@
/*
Nazara Engine - Lua scripting module
Copyright (C) 2013 Jérôme Leclercq (lynix680@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#ifndef NAZARA_CONFIG_LUA_HPP
#define NAZARA_CONFIG_LUA_HPP
/// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci
// Utilise un tracker pour repérer les éventuels leaks (Ralentit l'exécution)
#define NAZARA_LUA_MEMORYLEAKTRACKER 0
// Active les tests de sécurité basés sur le code (Conseillé pour le développement)
#define NAZARA_LUA_SAFE 1
#endif // NAZARA_CONFIG_LUA_HPP

View File

@ -0,0 +1,11 @@
// Copyright (C) 2013 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/Config.hpp>
#if NAZARA_LUA_MEMORYLEAKTRACKER || defined(NAZARA_DEBUG)
#include <Nazara/Core/Debug/MemoryLeakTracker.hpp>
#define delete NzMemoryManager::NextFree(__FILE__, __LINE__), delete
#define new new(__FILE__, __LINE__)
#endif

View File

@ -0,0 +1,8 @@
// Copyright (C) 2013 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
#if NAZARA_LUA_MEMORYLEAKTRACKER || defined(NAZARA_DEBUG)
#undef delete
#undef new
#endif

View File

@ -0,0 +1,48 @@
// Copyright (C) 2013 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_ENUMS_LUA_HPP
#define NAZARA_ENUMS_LUA_HPP
enum nzLuaComparison
{
nzLuaComparison_Equality,
nzLuaComparison_Less,
nzLuaComparison_LessOrEqual,
nzLuaComparison_Max = nzLuaComparison_LessOrEqual
};
enum nzLuaOperation
{
nzLuaOperation_Addition,
nzLuaOperation_Division,
nzLuaOperation_Exponentiation,
nzLuaOperation_Modulo,
nzLuaOperation_Multiplication,
nzLuaOperation_Negation,
nzLuaOperation_Substraction,
nzLuaOperation_Max = nzLuaOperation_Substraction
};
enum nzLuaType
{
nzLuaType_Boolean,
nzLuaType_Function,
nzLuaType_LightUserdata,
nzLuaType_Nil,
nzLuaType_Number,
nzLuaType_None,
nzLuaType_String,
nzLuaType_Table,
nzLuaType_Thread,
nzLuaType_Userdata,
nzLuaType_Max = nzLuaType_Userdata
};
#endif // NAZARA_ENUMS_LUA_HPP

View File

@ -0,0 +1,53 @@
// Copyright (C) 2013 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_LUACLASS_HPP
#define NAZARA_LUACLASS_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Lua/LuaInstance.hpp>
#include <map>
template<class T>
class NzLuaClass : public NzLuaClassImpl
{
public:
using ClassFunc = int (*)(NzLuaInstance& lua, T& instance);
using ClassIndexFunc = bool (*)(NzLuaInstance& lua, T& instance);
using ConstructorFunc = T* (*)(NzLuaInstance& lua);
using FinalizerFunc = bool (*)(NzLuaInstance& lua, T& instance);
NzLuaClass(const NzString& name);
//template<class U> void Inherit(NzLuaClass<U>& parent);
void Register(NzLuaInstance& lua);
void SetConstructor(ConstructorFunc constructor);
void SetFinalizer(FinalizerFunc finalizer);
void SetGetter(ClassIndexFunc getter);
void SetMethod(const NzString& name, ClassFunc method);
void SetSetter(ClassIndexFunc setter);
private:
static int ConstructorProxy(lua_State* state);
static int FinalizerProxy(lua_State* state);
static int GetterProxy(lua_State* state);
static int MethodProxy(lua_State* state);
static int SetterProxy(lua_State* state);
std::map<NzString, ClassFunc> m_methods;
ClassIndexFunc m_getter;
ClassIndexFunc m_setter;
ConstructorFunc m_constructor;
FinalizerFunc m_finalizer;
NzString m_name;
};
#include <Nazara/Lua/LuaClass.inl>
#endif // NAZARA_LUACLASS_HPP

View File

@ -0,0 +1,200 @@
// Copyright (C) 2013 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/Debug.hpp>
#include <Nazara/Core/Error.hpp>
template<class T>
NzLuaClass<T>::NzLuaClass(const NzString& name) :
m_getter(nullptr),
m_setter(nullptr),
m_constructor(nullptr),
m_finalizer(nullptr),
m_name(name)
{
}
template<class T>
void NzLuaClass<T>::Register(NzLuaInstance& lua)
{
if (!lua.NewMetatable(m_name))
NazaraWarning("Class \"" + m_name + "\" already registred in this instance");
{
FinalizerFunc* finalizer = static_cast<FinalizerFunc*>(lua.PushUserdata(sizeof(FinalizerFunc)));
*finalizer = m_finalizer;
lua.PushString(m_name);
lua.PushCFunction(FinalizerProxy, 2);
lua.SetField("__gc");
if (m_getter)
{
ClassIndexFunc* getter = static_cast<ClassIndexFunc*>(lua.PushUserdata(sizeof(ClassIndexFunc)));
*getter = m_getter;
lua.PushString(m_name);
lua.PushCFunction(GetterProxy, 2);
}
else
lua.PushValue(-1);
lua.SetField("__index");
if (m_setter)
{
ClassIndexFunc* setter = static_cast<ClassIndexFunc*>(lua.PushUserdata(sizeof(ClassIndexFunc)));
*setter = m_setter;
lua.PushString(m_name);
lua.PushCFunction(SetterProxy, 2);
lua.SetField("__newindex");
}
for (auto it = m_methods.begin(); it != m_methods.end(); ++it)
{
ClassFunc* method = static_cast<ClassFunc*>(lua.PushUserdata(sizeof(ClassFunc)));
*method = it->second;
lua.PushString(m_name);
lua.PushCFunction(MethodProxy, 2);
lua.SetField(it->first);
}
}
lua.Pop();
if (m_constructor)
{
ConstructorFunc* ptr = static_cast<ConstructorFunc*>(lua.PushUserdata(sizeof(ConstructorFunc)));
*ptr = m_constructor;
lua.PushString(m_name);
lua.PushCFunction(ConstructorProxy, 2);
lua.SetGlobal(m_name);
}
}
template<class T>
void NzLuaClass<T>::SetConstructor(ConstructorFunc constructor)
{
m_constructor = constructor;
}
template<class T>
void NzLuaClass<T>::SetFinalizer(FinalizerFunc finalizer)
{
m_finalizer = finalizer;
}
template<class T>
void NzLuaClass<T>::SetGetter(ClassIndexFunc getter)
{
m_getter = getter;
}
template<class T>
void NzLuaClass<T>::SetMethod(const NzString& name, ClassFunc method)
{
m_methods[name] = method;
}
template<class T>
void NzLuaClass<T>::SetSetter(ClassIndexFunc setter)
{
m_setter = setter;
}
template<class T>
int NzLuaClass<T>::ConstructorProxy(lua_State* state)
{
NzLuaInstance& lua = *NzLuaInstance::GetInstance(state);
ConstructorFunc func = *static_cast<ConstructorFunc*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
const char* className = lua.ToString(lua.GetIndexOfUpValue(2));
T* instance = func(lua);
if (!instance)
{
lua.Error("Constructor failed");
return 0; // Normalement pas nécessaire
}
T** ud = static_cast<T**>(lua.PushUserdata(sizeof(T*)));
lua.SetMetatable(className);
*ud = instance;
return 1;
}
template<class T>
int NzLuaClass<T>::FinalizerProxy(lua_State* state)
{
NzLuaInstance& lua = *NzLuaInstance::GetInstance(state);
FinalizerFunc func = *static_cast<FinalizerFunc*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
const char* className = lua.ToString(lua.GetIndexOfUpValue(2));
T* instance = *static_cast<T**>(lua.CheckUserdata(1, className));
lua.Remove(1);
if (!func || func(lua, *instance))
delete instance;
return 0;
}
template<class T>
int NzLuaClass<T>::GetterProxy(lua_State* state)
{
NzLuaInstance& lua = *NzLuaInstance::GetInstance(state);
ClassIndexFunc func = *static_cast<ClassIndexFunc*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
const char* className = lua.ToString(lua.GetIndexOfUpValue(2));
T& instance = *(*static_cast<T**>(lua.CheckUserdata(1, className)));
lua.Remove(1);
if (!func(lua, instance))
{
// On accède alors à la table
lua.PushMetatable(className);
lua.PushValue(1);
lua.GetTable();
}
return 1;
}
template<class T>
int NzLuaClass<T>::MethodProxy(lua_State* state)
{
NzLuaInstance& lua = *NzLuaInstance::GetInstance(state);
ClassFunc func = *static_cast<ClassFunc*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
const char* className = lua.ToString(lua.GetIndexOfUpValue(2));
T& instance = *(*static_cast<T**>(lua.CheckUserdata(1, className)));
lua.Remove(1);
return (*func)(lua, instance);
}
template<class T>
int NzLuaClass<T>::SetterProxy(lua_State* state)
{
NzLuaInstance& lua = *NzLuaInstance::GetInstance(state);
ClassIndexFunc func = *static_cast<ClassIndexFunc*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
const char* className = lua.ToString(lua.GetIndexOfUpValue(2));
T& instance = *(*static_cast<T**>(lua.CheckUserdata(1, className)));
lua.Remove(1);
if (!func(lua, instance))
lua.Error("Field not found");
return 1;
}
#include <Nazara/Lua/DebugOff.hpp>

View File

@ -0,0 +1,152 @@
// Copyright (C) 2013 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/InputStream.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Lua/Enums.hpp>
#include <cstddef>
struct lua_Debug;
struct lua_State;
class NzLuaInstance;
using NzLuaCFunction = int (*)(lua_State* state);
using NzLuaFunction = int (*)(NzLuaInstance& instance);
class NAZARA_API NzLuaInstance : NzNonCopyable
{
public:
NzLuaInstance();
~NzLuaInstance();
void CheckAny(int index) const;
int CheckInteger(int index) const;
int CheckInteger(int index, int 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 NzString& 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, nzLuaType type) const;
unsigned int CheckUnsigned(int index) const;
unsigned int CheckUnsigned(int index, unsigned int defValue) const;
void* CheckUserdata(int index, const char* tname) const;
void* CheckUserdata(int index, const NzString& tname) const;
bool Compare(int index1, int index2, nzLuaComparison comparison) const;
void Compute(nzLuaOperation operation);
void Concatenate(int count);
void Error(const char* message);
void Error(const NzString& message);
bool Execute(const NzString& code);
bool ExecuteFromFile(const NzString& filePath);
bool ExecuteFromMemory(const void* data, unsigned int size);
bool ExecuteFromStream(NzInputStream& stream);
int GetAbsIndex(int index) const;
void GetField(const char* fieldName, int index = -1) const;
void GetField(const NzString& fieldName, int index = -1) const;
void GetGlobal(const char* name) const;
void GetGlobal(const NzString& name) const;
lua_State* GetInternalState() const;
NzString GetLastError() const;
nzUInt32 GetMemoryLimit() const;
nzUInt32 GetMemoryUsage() const;
void GetMetatable(const char* tname) const;
void GetMetatable(const NzString& tname) const;
bool GetMetatable(int index) const;
unsigned int GetStackTop() const;
void GetTable(int index = -2) const;
nzUInt32 GetTimeLimit() const;
nzLuaType GetType(int index) const;
const char* GetTypeName(nzLuaType type) const;
void Insert(int index);
bool IsOfType(int index, nzLuaType type) const;
bool IsOfType(int index, const char* tname) const;
bool IsOfType(int index, const NzString& tname) const;
bool IsValid(int index) const;
unsigned int Length(int index) const;
void MoveTo(NzLuaInstance* instance, int n);
bool NewMetatable(const char* str);
bool NewMetatable(const NzString& str);
bool Next(int index = -2);
void Pop(unsigned int n = 1U);
void PushBoolean(bool value);
void PushCFunction(NzLuaCFunction func, int valueCount = 0);
void PushFunction(NzLuaFunction func);
void PushInteger(int value);
void PushLightUserdata(void* value);
void PushMetatable(const char* str);
void PushMetatable(const NzString& str);
void PushNil();
void PushNumber(double value);
void PushString(const char* str);
void PushString(const NzString& str);
void PushTable(unsigned int sequenceElementCount = 0, unsigned int arrayElementCount = 0);
void PushUnsigned(unsigned int value);
void* PushUserdata(unsigned int size);
void PushValue(int index);
void Remove(int index);
void Replace(int index);
void SetField(const char* name, int index = -2);
void SetField(const NzString& name, int index = -2);
void SetGlobal(const char* name);
void SetGlobal(const NzString& name);
void SetMetatable(const char* tname);
void SetMetatable(const NzString& tname);
void SetMetatable(int index);
void SetMemoryLimit(nzUInt32 memoryLimit);
void SetTable(int index = -3);
void SetTimeLimit(nzUInt32 timeLimit);
bool ToBoolean(int index) const;
int ToInteger(int index, bool* succeeded = nullptr) const;
double ToNumber(int index, bool* succeeded = nullptr) const;
const char* ToString(int index, std::size_t* length = nullptr) const;
unsigned int ToUnsigned(int index, bool* succeeded = nullptr) const;
void* ToUserdata(int index) const;
void* ToUserdata(int index, const char* tname) const;
void* ToUserdata(int index, const NzString& tname) const;
static int GetIndexOfUpValue(int upValue);
static NzLuaInstance* GetInstance(lua_State* state);
private:
bool Run();
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);
nzUInt32 m_memoryLimit;
nzUInt32 m_memoryUsage;
nzUInt32 m_timeLimit;
NzClock m_clock;
NzString m_lastError;
lua_State* m_state;
unsigned int m_level;
};
#endif // NAZARA_LUASTATE_HPP

View File

@ -0,0 +1,29 @@
// Copyright (C) 2013 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/Config.hpp>
#if NAZARA_LUA_MEMORYLEAKTRACKER || defined(NAZARA_DEBUG)
#include <Nazara/Core/Debug/MemoryLeakTracker.hpp>
#include <new>
void* operator new(std::size_t size)
{
return NzMemoryManager::Allocate(size, false);
}
void* operator new[](std::size_t size)
{
return NzMemoryManager::Allocate(size, true);
}
void operator delete(void* pointer) noexcept
{
NzMemoryManager::Free(pointer, false);
}
void operator delete[](void* pointer) noexcept
{
NzMemoryManager::Free(pointer, true);
}
#endif

56
src/Nazara/Lua/Lua.cpp Normal file
View File

@ -0,0 +1,56 @@
// Copyright (C) 2013 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/Lua.hpp>
#include <Nazara/Core/Core.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Log.hpp>
#include <Nazara/Lua/Config.hpp>
#include <Nazara/Lua/Debug.hpp>
bool NzLua::Initialize()
{
if (s_moduleReferenceCounter++ != 0)
return true; // Déjà initialisé
// Initialisation des dépendances
if (!NzCore::Initialize())
{
NazaraError("Failed to initialize core module");
return false;
}
// Initialisation du module
NazaraNotice("Initialized: Lua module");
return true;
}
bool NzLua::IsInitialized()
{
return s_moduleReferenceCounter != 0;
}
void NzLua::Uninitialize()
{
if (s_moduleReferenceCounter != 1)
{
// Le module est soit encore utilisé, soit pas initialisé
if (s_moduleReferenceCounter > 1)
s_moduleReferenceCounter--;
return;
}
// Libération du module
s_moduleReferenceCounter = 0;
NazaraNotice("Uninitialized: Lua module");
// Libération des dépendances
NzCore::Uninitialize();
}
unsigned int NzLua::s_moduleReferenceCounter = 0;

View File

@ -0,0 +1,790 @@
// Copyright (C) 2013 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/LuaInstance.hpp>
#include <Lua/lauxlib.h>
#include <Lua/lua.h>
#include <Lua/lualib.h>
#include <Nazara/Core/Clock.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/File.hpp>
#include <Nazara/Core/MemoryStream.hpp>
#include <cstdlib>
#include <stdexcept>
#include <unordered_map>
#include <Nazara/Lua/Debug.hpp>
namespace
{
struct StreamData
{
NzInputStream* stream;
char buffer[NAZARA_CORE_FILE_BUFFERSIZE];
};
int AtPanic(lua_State* state)
{
NazaraUnused(state);
throw std::runtime_error("Lua panic !");
}
const char* StreamReader(lua_State* state, void* data, std::size_t* size)
{
NazaraUnused(state);
StreamData* streamData = static_cast<StreamData*>(data);
if (streamData->stream->EndOfStream())
return nullptr;
else
{
*size = streamData->stream->Read(streamData->buffer, NAZARA_CORE_FILE_BUFFERSIZE);
return streamData->buffer;
}
}
int s_comparisons[nzLuaComparison_Max+1] = {
LUA_OPEQ, // nzLuaComparison_Equality
LUA_OPLT, // nzLuaComparison_Less
LUA_OPLE // nzLuaComparison_LessOrEqual
};
int s_operations[nzLuaOperation_Max+1] = {
LUA_OPADD, // nzLuaOperation_Addition
LUA_OPDIV, // nzLuaOperation_Division
LUA_OPPOW, // nzLuaOperation_Exponentiation
LUA_OPMOD, // nzLuaOperation_Modulo
LUA_OPMUL, // nzLuaOperation_Multiplication
LUA_OPUNM, // nzLuaOperation_Negation
LUA_OPSUB // nzLuaOperation_Substraction
};
int s_types[nzLuaType_Max+1] = {
LUA_TBOOLEAN, // nzLuaType_Boolean
LUA_TFUNCTION, // nzLuaType_Function
LUA_TLIGHTUSERDATA, // nzLuaType_LightUserdata
LUA_TNIL, // nzLuaType_Nil
LUA_TNUMBER, // nzLuaType_Number
LUA_TNONE, // nzLuaType_None
LUA_TSTRING, // nzLuaType_String
LUA_TTABLE, // nzLuaType_Table
LUA_TTHREAD, // nzLuaType_Thread
LUA_TUSERDATA // nzLuaType_Userdata
};
}
NzLuaInstance::NzLuaInstance() :
m_memoryLimit(0),
m_memoryUsage(0),
m_timeLimit(1000),
m_level(0)
{
m_state = lua_newstate(MemoryAllocator, this);
lua_atpanic(m_state, AtPanic);
lua_sethook(m_state, TimeLimiter, LUA_MASKCOUNT, 1000);
luaL_openlibs(m_state);
}
NzLuaInstance::~NzLuaInstance()
{
lua_close(m_state);
}
void NzLuaInstance::CheckAny(int index) const
{
luaL_checkany(m_state, index);
}
int NzLuaInstance::CheckInteger(int index) const
{
return luaL_checkint(m_state, index);
}
int NzLuaInstance::CheckInteger(int index, int defValue) const
{
return luaL_optint(m_state, index, defValue);
}
double NzLuaInstance::CheckNumber(int index) const
{
return luaL_checknumber(m_state, index);
}
double NzLuaInstance::CheckNumber(int index, double defValue) const
{
return luaL_optnumber(m_state, index, defValue);
}
void NzLuaInstance::CheckStack(int space, const char* error) const
{
luaL_checkstack(m_state, space, error);
}
void NzLuaInstance::CheckStack(int space, const NzString& error) const
{
CheckStack(space, error.GetConstBuffer());
}
const char* NzLuaInstance::CheckString(int index, std::size_t* length) const
{
return luaL_checklstring(m_state, index, length);
}
const char* NzLuaInstance::CheckString(int index, const char* defValue, std::size_t* length) const
{
return luaL_optlstring(m_state, index, defValue, length);
}
void NzLuaInstance::CheckType(int index, nzLuaType type) const
{
#ifdef NAZARA_DEBUG
if (type > nzLuaType_Max)
{
NazaraError("Lua type out of enum");
return;
}
#endif
luaL_checktype(m_state, index, s_types[type]);
}
unsigned int NzLuaInstance::CheckUnsigned(int index) const
{
return luaL_checkunsigned(m_state, index);
}
unsigned int NzLuaInstance::CheckUnsigned(int index, unsigned int defValue) const
{
return luaL_optunsigned(m_state, index, defValue);
}
void* NzLuaInstance::CheckUserdata(int index, const char* tname) const
{
return luaL_checkudata(m_state, index, tname);
}
void* NzLuaInstance::CheckUserdata(int index, const NzString& tname) const
{
return luaL_checkudata(m_state, index, tname.GetConstBuffer());
}
bool NzLuaInstance::Compare(int index1, int index2, nzLuaComparison comparison) const
{
#ifdef NAZARA_DEBUG
if (comparison > nzLuaComparison_Max)
{
NazaraError("Lua comparison out of enum");
return false;
}
#endif
return lua_compare(m_state, index1, index2, s_comparisons[comparison]);
}
void NzLuaInstance::Compute(nzLuaOperation operation)
{
#ifdef NAZARA_DEBUG
if (operation > nzLuaOperation_Max)
{
NazaraError("Lua operation out of enum");
return;
}
#endif
lua_arith(m_state, s_operations[operation]);
}
void NzLuaInstance::Concatenate(int count)
{
lua_concat(m_state, count);
}
void NzLuaInstance::Error(const char* message)
{
luaL_error(m_state, message);
}
void NzLuaInstance::Error(const NzString& message)
{
luaL_error(m_state, message.GetConstBuffer());
}
bool NzLuaInstance::Execute(const NzString& code)
{
if (code.IsEmpty())
return true;
if (luaL_loadstring(m_state, code.GetConstBuffer()) != 0)
{
m_lastError = lua_tostring(m_state, -1);
lua_pop(m_state, 1);
return false;
}
if (m_level++ == 0)
m_clock.Restart();
int status = lua_pcall(m_state, 0, LUA_MULTRET, 0);
m_level--;
if (status != 0)
{
m_lastError = lua_tostring(m_state, -1);
lua_pop(m_state, 1);
return false;
}
return true;
}
bool NzLuaInstance::ExecuteFromFile(const NzString& filePath)
{
NzFile file(filePath);
if (!file.Open(NzFile::ReadOnly | NzFile::Text))
{
NazaraError("Failed to open file");
return false;
}
unsigned int length = file.GetSize();
NzString source;
source.Resize(length);
if (file.Read(&source[0], length) != length)
{
NazaraError("Failed to read file");
return false;
}
file.Close();
return Execute(source);
}
bool NzLuaInstance::ExecuteFromMemory(const void* data, unsigned int size)
{
NzMemoryStream stream(data, size);
return ExecuteFromStream(stream);
}
bool NzLuaInstance::ExecuteFromStream(NzInputStream& stream)
{
StreamData data;
data.stream = &stream;
if (lua_load(m_state, StreamReader, &data, "C", nullptr) != 0)
{
m_lastError = lua_tostring(m_state, -1);
lua_pop(m_state, 1);
return false;
}
return Run();
}
int NzLuaInstance::GetAbsIndex(int index) const
{
return lua_absindex(m_state, index);
}
void NzLuaInstance::GetField(const char* fieldName, int index) const
{
lua_getfield(m_state, index, fieldName);
}
void NzLuaInstance::GetField(const NzString& fieldName, int index) const
{
lua_getfield(m_state, index, fieldName.GetConstBuffer());
}
void NzLuaInstance::GetGlobal(const char* name) const
{
lua_getglobal(m_state, name);
}
void NzLuaInstance::GetGlobal(const NzString& name) const
{
lua_getglobal(m_state, name.GetConstBuffer());
}
lua_State* NzLuaInstance::GetInternalState() const
{
return m_state;
}
NzString NzLuaInstance::GetLastError() const
{
return m_lastError;
}
nzUInt32 NzLuaInstance::GetMemoryLimit() const
{
return m_memoryLimit;
}
nzUInt32 NzLuaInstance::GetMemoryUsage() const
{
return m_memoryUsage;
}
void NzLuaInstance::GetMetatable(const char* tname) const
{
luaL_getmetatable(m_state, tname);
}
void NzLuaInstance::GetMetatable(const NzString& tname) const
{
luaL_getmetatable(m_state, tname.GetConstBuffer());
}
bool NzLuaInstance::GetMetatable(int index) const
{
return lua_getmetatable(m_state, index);
}
unsigned int NzLuaInstance::GetStackTop() const
{
return lua_gettop(m_state);
}
void NzLuaInstance::GetTable(int index) const
{
lua_gettable(m_state, index);
}
nzUInt32 NzLuaInstance::GetTimeLimit() const
{
return m_timeLimit;
}
nzLuaType NzLuaInstance::GetType(int index) const
{
switch (lua_type(m_state, index))
{
case LUA_TBOOLEAN:
return nzLuaType_Boolean;
case LUA_TFUNCTION:
return nzLuaType_Function;
case LUA_TLIGHTUSERDATA:
return nzLuaType_LightUserdata;
case LUA_TNIL:
return nzLuaType_Nil;
case LUA_TNONE:
return nzLuaType_None;
case LUA_TNUMBER:
return nzLuaType_Number;
case LUA_TSTRING:
return nzLuaType_String;
case LUA_TTABLE:
return nzLuaType_Table;
case LUA_TTHREAD:
return nzLuaType_Thread;
case LUA_TUSERDATA:
return nzLuaType_Userdata;
default:
return nzLuaType_None;
}
}
const char* NzLuaInstance::GetTypeName(nzLuaType type) const
{
#ifdef NAZARA_DEBUG
if (type > nzLuaType_Max)
{
NazaraError("Lua type out of enum");
return nullptr;
}
#endif
return lua_typename(m_state, s_types[type]);
}
void NzLuaInstance::Insert(int index)
{
lua_insert(m_state, index);
}
bool NzLuaInstance::IsOfType(int index, nzLuaType type) const
{
switch (type)
{
case nzLuaType_Boolean:
return lua_isboolean(m_state, index);
case nzLuaType_Function:
return lua_isfunction(m_state, index);
case nzLuaType_LightUserdata:
return lua_islightuserdata(m_state, index);
case nzLuaType_Nil:
return lua_isnil(m_state, index);
case nzLuaType_None:
return lua_isnone(m_state, index);
case nzLuaType_Number:
return lua_isnumber(m_state, index);
case nzLuaType_String:
return lua_isstring(m_state, index);
case nzLuaType_Table:
return lua_istable(m_state, index);
case nzLuaType_Thread:
return lua_isthread(m_state, index);
case nzLuaType_Userdata:
return lua_isuserdata(m_state, index);
}
NazaraError("Lua type unhandled (0x" + NzString::Number(type, 16) + ')');
return false;
}
bool NzLuaInstance::IsOfType(int index, const char* tname) const
{
void* ud = luaL_testudata(m_state, index, tname);
return ud != nullptr;
}
bool NzLuaInstance::IsOfType(int index, const NzString& tname) const
{
return IsOfType(index, tname.GetConstBuffer());
}
bool NzLuaInstance::IsValid(int index) const
{
return !lua_isnoneornil(m_state, index);
}
unsigned int NzLuaInstance::Length(int index) const
{
return luaL_len(m_state, index);
}
void NzLuaInstance::MoveTo(NzLuaInstance* instance, int n)
{
lua_xmove(m_state, instance->m_state, n);
}
bool NzLuaInstance::NewMetatable(const char* str)
{
return luaL_newmetatable(m_state, str);
}
bool NzLuaInstance::NewMetatable(const NzString& str)
{
return luaL_newmetatable(m_state, str.GetConstBuffer());
}
bool NzLuaInstance::Next(int index)
{
return lua_next(m_state, index);
}
void NzLuaInstance::Pop(unsigned int n)
{
lua_pop(m_state, n);
}
void NzLuaInstance::PushBoolean(bool value)
{
lua_pushboolean(m_state, value);
}
void NzLuaInstance::PushCFunction(NzLuaCFunction func, int valueCount)
{
lua_pushcclosure(m_state, func, valueCount);
}
void NzLuaInstance::PushFunction(NzLuaFunction func)
{
NzLuaFunction* luaFunc = reinterpret_cast<NzLuaFunction*>(lua_newuserdata(m_state, sizeof(NzLuaFunction)));
*luaFunc = func;
lua_pushcclosure(m_state, ProxyFunc, 1);
}
void NzLuaInstance::PushInteger(int value)
{
lua_pushinteger(m_state, value);
}
void NzLuaInstance::PushLightUserdata(void* value)
{
lua_pushlightuserdata(m_state, value);
}
void NzLuaInstance::PushMetatable(const char* str)
{
luaL_getmetatable(m_state, str);
}
void NzLuaInstance::PushMetatable(const NzString& str)
{
luaL_getmetatable(m_state, str.GetConstBuffer());
}
void NzLuaInstance::PushNil()
{
lua_pushnil(m_state);
}
void NzLuaInstance::PushNumber(double value)
{
lua_pushnumber(m_state, value);
}
void NzLuaInstance::PushString(const char* str)
{
lua_pushstring(m_state, str);
}
void NzLuaInstance::PushString(const NzString& str)
{
lua_pushlstring(m_state, str.GetConstBuffer(), str.GetSize());
}
void NzLuaInstance::PushTable(unsigned int sequenceElementCount, unsigned int arrayElementCount)
{
lua_createtable(m_state, sequenceElementCount, arrayElementCount);
}
void NzLuaInstance::PushUnsigned(unsigned int value)
{
lua_pushunsigned(m_state, value);
}
void* NzLuaInstance::PushUserdata(unsigned int size)
{
return lua_newuserdata(m_state, size);
}
void NzLuaInstance::PushValue(int index)
{
lua_pushvalue(m_state, index);
}
void NzLuaInstance::Remove(int index)
{
lua_remove(m_state, index);
}
void NzLuaInstance::Replace(int index)
{
lua_replace(m_state, index);
}
void NzLuaInstance::SetField(const char* name, int index)
{
lua_setfield(m_state, index, name);
}
void NzLuaInstance::SetField(const NzString& name, int index)
{
lua_setfield(m_state, index, name.GetConstBuffer());
}
void NzLuaInstance::SetGlobal(const char* name)
{
lua_setglobal(m_state, name);
}
void NzLuaInstance::SetGlobal(const NzString& name)
{
lua_setglobal(m_state, name.GetConstBuffer());
}
void NzLuaInstance::SetMetatable(const char* tname)
{
luaL_setmetatable(m_state, tname);
}
void NzLuaInstance::SetMetatable(const NzString& tname)
{
luaL_setmetatable(m_state, tname.GetConstBuffer());
}
void NzLuaInstance::SetMetatable(int index)
{
lua_setmetatable(m_state, index);
}
void NzLuaInstance::SetMemoryLimit(nzUInt32 memoryLimit)
{
m_memoryLimit = memoryLimit;
}
void NzLuaInstance::SetTable(int index)
{
lua_settable(m_state, index);
}
void NzLuaInstance::SetTimeLimit(nzUInt32 timeLimit)
{
if (m_timeLimit != timeLimit)
{
if (m_timeLimit == 0)
lua_sethook(m_state, TimeLimiter, LUA_MASKCOUNT, 1000);
else if (timeLimit == 0)
lua_sethook(m_state, TimeLimiter, 0, 1000);
m_timeLimit = timeLimit;
}
}
bool NzLuaInstance::ToBoolean(int index) const
{
return lua_toboolean(m_state, index);
}
int NzLuaInstance::ToInteger(int index, bool* succeeded) const
{
int success;
int result = lua_tointegerx(m_state, index, &success);
if (succeeded)
*succeeded = success;
return result;
}
double NzLuaInstance::ToNumber(int index, bool* succeeded) const
{
int success;
double result = lua_tonumberx(m_state, index, &success);
if (succeeded)
*succeeded = success;
return result;
}
const char* NzLuaInstance::ToString(int index, std::size_t* length) const
{
return lua_tolstring(m_state, index, length);
}
unsigned int NzLuaInstance::ToUnsigned(int index, bool* succeeded) const
{
int success;
unsigned int result = lua_tounsignedx(m_state, index, &success);
if (succeeded)
*succeeded = success;
return result;
}
void* NzLuaInstance::ToUserdata(int index) const
{
return lua_touserdata(m_state, index);
}
void* NzLuaInstance::ToUserdata(int index, const char* tname) const
{
return luaL_testudata(m_state, index, tname);
}
void* NzLuaInstance::ToUserdata(int index, const NzString& tname) const
{
return luaL_testudata(m_state, index, tname.GetConstBuffer());
}
int NzLuaInstance::GetIndexOfUpValue(int upValue)
{
return lua_upvalueindex(upValue);
}
NzLuaInstance* NzLuaInstance::GetInstance(lua_State* state)
{
NzLuaInstance* instance;
lua_getallocf(state, reinterpret_cast<void**>(&instance));
return instance;
}
bool NzLuaInstance::Run()
{
if (m_level++ == 0)
m_clock.Restart();
int status = lua_pcall(m_state, 0, 0, 0);
m_level--;
if (status != 0)
{
m_lastError = lua_tostring(m_state, -1);
lua_pop(m_state, 1);
return false;
}
return true;
}
void* NzLuaInstance::MemoryAllocator(void* ud, void* ptr, std::size_t osize, std::size_t nsize)
{
NzLuaInstance* instance = static_cast<NzLuaInstance*>(ud);
nzUInt32& memoryLimit = instance->m_memoryLimit;
nzUInt32& memoryUsage = instance->m_memoryUsage;
if (nsize == 0)
{
memoryUsage -= osize;
std::free(ptr);
return nullptr;
}
else
{
nzUInt32 usage = memoryUsage + nsize;
if (ptr)
usage -= osize;
if (memoryLimit != 0 && usage > memoryLimit)
{
NazaraError("Lua memory usage is over memory limit (" + NzString::Number(usage) + " > " + NzString::Number(memoryLimit) + ')');
return nullptr;
}
memoryUsage = usage;
return std::realloc(ptr, nsize);
}
}
int NzLuaInstance::ProxyFunc(lua_State* state)
{
NzLuaFunction* func = static_cast<NzLuaFunction*>(lua_touserdata(state, lua_upvalueindex(1)));
return (*func)(*GetInstance(state));
}
void NzLuaInstance::TimeLimiter(lua_State* state, lua_Debug* debug)
{
NazaraUnused(debug);
NzLuaInstance* instance = GetInstance(state);
if (instance->m_clock.GetMilliseconds() > instance->m_timeLimit)
luaL_error(state, "maximum execution time exceeded");
}