mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-08 07:28:22 -10:00
This commit changes the way the scripting API works by properly using the newly available type information for moving the FSO resources into the memory supplied by lua. This has full support for rvalue references which will make it possible to use move-only types with the scripting API. This also makes the API much safer to use since it doesn't use pointers to local values anymore which made it very hard to use the API in a different context without causing issues. This only covers writing the FSO values to Lua. Getting values back is not covered yet.
183 lines
4.2 KiB
C++
183 lines
4.2 KiB
C++
|
|
#include "LuaConvert.h"
|
|
|
|
namespace luacpp {
|
|
namespace convert {
|
|
namespace internal {
|
|
|
|
bool isValidIndex(lua_State* state, int index) {
|
|
if (1 <= std::abs(index) && std::abs(index) <= lua_gettop(state)) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void pushValue(lua_State* luaState, const double& value) {
|
|
lua_pushnumber(luaState, value);
|
|
}
|
|
void pushValue(lua_State* luaState, const float& value) {
|
|
lua_pushnumber(luaState, value);
|
|
}
|
|
void pushValue(lua_State* luaState, const int& value) {
|
|
lua_pushnumber(luaState, value);
|
|
}
|
|
void pushValue(lua_State* luaState, const size_t& value) {
|
|
lua_pushnumber(luaState, (lua_Number)value);
|
|
}
|
|
void pushValue(lua_State* luaState, const std::string& value) {
|
|
lua_pushlstring(luaState, value.c_str(), value.size());
|
|
}
|
|
void pushValue(lua_State* luaState, const char* value) {
|
|
lua_pushstring(luaState, value);
|
|
}
|
|
void pushValue(lua_State* luaState, const bool& value) {
|
|
lua_pushboolean(luaState, value);
|
|
}
|
|
void pushValue(lua_State* luaState, const lua_CFunction& value) {
|
|
lua_pushcfunction(luaState, value);
|
|
}
|
|
|
|
bool popValue(lua_State* luaState, int& target, int stackposition, bool remove) {
|
|
double temp;
|
|
|
|
auto ret = popValue(luaState, temp, stackposition, remove);
|
|
if (ret) {
|
|
target = (int)temp;
|
|
}
|
|
return ret;
|
|
}
|
|
bool popValue(lua_State* luaState, size_t& target, int stackposition, bool remove) {
|
|
double temp;
|
|
|
|
auto ret = popValue(luaState, temp, stackposition, remove);
|
|
if (ret) {
|
|
target = (size_t)temp;
|
|
}
|
|
return ret;
|
|
}
|
|
bool popValue(lua_State* luaState, float& target, int stackposition, bool remove) {
|
|
double temp;
|
|
|
|
auto ret = popValue(luaState, temp, stackposition, remove);
|
|
if (ret) {
|
|
target = (float)temp;
|
|
}
|
|
return ret;
|
|
}
|
|
bool popValue(lua_State* luaState, double& target, int stackposition, bool remove) {
|
|
if (!internal::isValidIndex(luaState, stackposition)) {
|
|
return false;
|
|
}
|
|
|
|
if (!lua_isnumber(luaState, stackposition)) {
|
|
return false;
|
|
} else {
|
|
target = lua_tonumber(luaState, stackposition);
|
|
|
|
if (remove) {
|
|
lua_remove(luaState, stackposition);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
bool popValue(lua_State* luaState, std::string& target, int stackposition, bool remove) {
|
|
if (!internal::isValidIndex(luaState, stackposition)) {
|
|
return false;
|
|
}
|
|
|
|
if (!lua_isstring(luaState, stackposition)) {
|
|
return false;
|
|
} else {
|
|
size_t size;
|
|
const char* string = lua_tolstring(luaState, stackposition, &size);
|
|
target.assign(string, size);
|
|
|
|
if (remove) {
|
|
lua_remove(luaState, stackposition);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool popValue(lua_State* luaState, bool& target, int stackposition, bool remove) {
|
|
if (!internal::isValidIndex(luaState, stackposition)) {
|
|
return false;
|
|
}
|
|
|
|
if (!lua_isboolean(luaState, stackposition)) {
|
|
return false;
|
|
} else {
|
|
target = lua_toboolean(luaState, stackposition) != 0;
|
|
|
|
if (remove) {
|
|
lua_remove(luaState, stackposition);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool popValue(lua_State* luaState, lua_CFunction& target, int stackposition, bool remove) {
|
|
if (!internal::isValidIndex(luaState, stackposition)) {
|
|
return false;
|
|
}
|
|
|
|
if (!lua_iscfunction(luaState, stackposition)) {
|
|
return false;
|
|
} else {
|
|
target = lua_tocfunction(luaState, stackposition);
|
|
|
|
if (remove) {
|
|
lua_remove(luaState, stackposition);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool popValue(lua_State* L, scripting::ade_odata& od, int stackposition, bool remove) {
|
|
//WMC - Get metatable
|
|
lua_getmetatable(L, stackposition);
|
|
int mtb_ldx = lua_gettop(L);
|
|
Assert(!lua_isnil(L, -1));
|
|
|
|
//Get ID
|
|
lua_pushstring(L, "__adeid");
|
|
lua_rawget(L, mtb_ldx);
|
|
|
|
if (lua_tonumber(L, -1) != od.idx)
|
|
{
|
|
lua_pushstring(L, "__adederivid");
|
|
lua_rawget(L, mtb_ldx);
|
|
if ((size_t)lua_tointeger(L, -1) != od.idx) {
|
|
// Issue the LuaError here since this is the only place where we have all relevant information
|
|
LuaError(L, "Argument %d is the wrong type of userdata; '%s' given, but '%s' expected", stackposition,
|
|
::scripting::internal::getTableEntry((size_t)lua_tointeger(L, -2)).Name,
|
|
::scripting::internal::getTableEntry(od.idx).GetName());
|
|
return false;
|
|
}
|
|
lua_pop(L, 1);
|
|
}
|
|
lua_pop(L, 2);
|
|
if (od.size != scripting::ODATA_PTR_SIZE) {
|
|
memcpy(od.buf, lua_touserdata(L, stackposition), od.size);
|
|
}
|
|
else {
|
|
*(void**)od.buf = lua_touserdata(L, stackposition);
|
|
}
|
|
|
|
if (remove) {
|
|
lua_remove(L, stackposition);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
}
|
|
}
|