Files
source/lua/lua_state.cpp
T
BeatAroundTheBuscherandGitHub ed00830202 Fixes Upper/Lower Casing for include paths (#487)
* Fixing upper/lower case for includes

types.h, zconf.h and zlib.h were renamed so that global includes like Types.h
are not used.
2025-08-16 22:01:12 -03:00

294 lines
5.9 KiB
C++

#include "lua_state.h"
#include <DEBUG.H>
#include "sgp_logger.h"
#include <vfs/Core/vfs_string.h>
LuaState::LuaState(lua_State* state, bool own) : _L(state), _own(own), _registry(state)
{
}
LuaState::LuaState() : _L(NULL), _own(true), _registry(NULL)
{
//_L = lua_open();
//_registry._L = _L;
}
LuaState::~LuaState()
{
}
void LuaState::init(bool init_libs)
{
if(!_L)
{
_L = lua_open();
if(init_libs)
{
luaL_openlibs(_L);
}
_registry._L = _L;
}
}
void LuaState::close()
{
if(_L && _own)
{
lua_close(_L);
}
}
#include <vfs/Core/vfs_file_raii.h>
bool LuaState::EvalFile(const char* filename)
{
try
{
vfs::COpenReadFile rfile(filename);
vfs::UInt32 size = rfile.file().getSize();
std::vector<vfs::Byte> buffer(size+1);
rfile.file().read(&buffer[0], size);
buffer[size] = 0;
return this->EvalString((char*)&buffer[0], size, filename);
}
catch(std::exception &ex)
{
SGP_ERROR(ex.what());
}
return false;
}
bool LuaState::CallFunction(const char* function_name)
{
if(function_name)
{
// call function
lua_getglobal(_L, function_name);
if(lua_isfunction(_L, -1))
{
if( lua_pcall(_L, 0, 1, 0) != 0 )
{
std::string err = lua_tostring(_L, -1);
std::wstringstream wss;
wss << L"Execution of lua function '" << vfs::String::as_utf16(function_name) << L"' failed : ";
wss << vfs::String::as_utf16(err);
SGP_THROW(wss.str().c_str());
}
return true;
}
}
return false;
}
bool LuaState::EvalString(const wchar_t *lua_str, size_t length, const char* id_str)
{
std::string s = vfs::String::as_utf8(lua_str, length);
return this->EvalString(s.c_str(), s.length(), id_str);
}
bool LuaState::EvalString(const char *lua_str, size_t length, const char* id_str)
{
int error;
if(length == 0)
{
length = strlen(lua_str);
}
error = luaL_loadbuffer(_L, lua_str, length, id_str) ||
lua_pcall(_L, 0, 0, 0);
if (error)
{
const char *error = lua_tostring(_L, -1);
int len = strlen( error);
if (len >= 7 && !strcmp( error + len - 7, "'<eof>'"))
{
lua_pop(_L, 1); /* pop error message from the stack */
return false;
}
std::string s = lua_tostring(_L, -1);
SGP_THROW(s);
//printf( "%s\n", lua_tostring(L, -1));
//lua_pop(L, 1); /* pop error message from the stack */
//return true;
}
return true;
}
/////////////////////////////////////////////////////////////////////////
LuaState::Registry::Registry(lua_State* L) : _L(L)
{
}
void LuaState::Registry::CreateCallbackTable()
{
lua_getfield(_L, LUA_REGISTRYINDEX, "__CallBackRegistry");
if(lua_isnil(_L,-1))
{
lua_pop(_L,1); // pop 'nil' from stack
lua_newtable(_L);
lua_setfield(_L,LUA_REGISTRYINDEX,"__CallBackRegistry"); // 'setfield' removes value from stack
return;
}
else if(lua_istable(_L,-1))
{
lua_pop(_L,1);
return;
}
SGP_THROW(L"Could not create callback registy table");
}
void LuaState::Registry::GetCallbackTable()
{
lua_getfield(_L, LUA_REGISTRYINDEX, "__CallBackRegistry");
if(!lua_istable(_L,-1))
{
SGP_THROW("CallBack registry table does not exist");
}
}
void LuaState::Registry::SetCallback(const char* callback_name)
{
// function is at (L, -2)
// user data value is at (L, -1)
this->GetCallbackTable();
lua_pushvalue(_L, -2);
lua_rawget(_L, -2);
if(!lua_istable(_L, -1))
{
lua_pop(_L, 1); // remove 'nil'
// set new table
lua_pushvalue(_L, -2);
lua_newtable(_L);
lua_rawset(_L, -3);
// get table
lua_pushvalue(_L, -2);
lua_rawget(_L, -2);
}
if(!lua_istable(_L,-1))
{
SGP_THROW("Could not create callback");
}
lua_pushvalue(_L, -4);
lua_setfield(_L, -2, callback_name);
lua_pop(_L, 4);
}
void LuaState::Registry::GetCallback(const char* callback_name)
{
// user data is at (L, -1)
this->GetCallbackTable();
lua_pushvalue(_L, -2);
lua_rawget(_L, -2);
if(lua_istable(_L, -1))
{
lua_getfield(_L, -1, callback_name);
if(lua_isfunction(_L, -1))
{
lua_insert(_L, -4);
lua_pop(_L, 3);
if(!lua_isfunction(_L,-1))
{
SGP_THROW("messed up stack");
}
return;
}
// no callback defined
lua_pop(_L, 4);
}
// no table created
lua_pop(_L, 3); // also pops user data
return;
}
void LuaState::Registry::CreateUserDataTable()
{
lua_getfield(_L, LUA_REGISTRYINDEX, "__UserData");
if(lua_isnil(_L,-1))
{
lua_pop(_L,1); // pop 'nil' from stack
lua_newtable(_L);
lua_setfield(_L,LUA_REGISTRYINDEX,"__UserData"); // 'setfield' removes value from stack
return;
}
else if(lua_istable(_L,-1))
{
lua_pop(_L,1);
return;
}
SGP_THROW(L"Could not create User Data registy table");
}
void LuaState::Registry::GetUserDataTable()
{
lua_getfield(_L, LUA_REGISTRYINDEX, "__UserData");
if(!lua_istable(_L,-1))
{
SGP_THROW("User Data registry table does not exist");
}
}
/************************************************************************************/
#include <map>
class LuaStateManager
{
public:
~LuaStateManager() {
_states.clear();
};
static LuaStateManager& instance() {
static LuaStateManager lsm;
return lsm;
};
LuaState& GetState(lua::State eState) {
return _states[eState];
}
private:
LuaStateManager() {};
static std::map<lua::State, LuaState> _states;
};
std::map<lua::State, LuaState> LuaStateManager::_states;
void LuaState::INIT(lua::State state_id, bool init_libs)
{
LuaStateManager::instance().GetState(state_id).init(init_libs);
}
LuaState LuaState::INIT(bool init_libs)
{
LuaState L;
L.init(init_libs);
return L;
}
void LuaState::CLOSE(lua::State state_id)
{
LuaStateManager::instance().GetState(state_id).close();
}
void LuaState::CLOSE(LuaState state)
{
state.close();
}
LuaState LuaState::GET(lua::State state_id)
{
return LuaStateManager::instance().GetState(state_id);
}