Files
fs2open.github.com/code/scripting/lua/LuaConvert.cpp
T
asarium 235391154e Fix wrong return value when getting boolean value from Lua
This is probably a bug from when I changed how those functions worked.
The function is supposed to return if it successfully retreived a value
from the Lua stack but instead of returning true if it was, it returned
the value it just retrieved. This works fine if that value is true but
causes issues if it was false.
2018-03-16 22:32:58 +01:00

226 lines
5.3 KiB
C++

#include "LuaConvert.h"
namespace
{
using namespace scripting;
ade_table_entry& getTableEntry(size_t idx) {
return ade_manager::getInstance()->getEntry(idx);
}
}
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);
}
void pushValue(lua_State* L, const ade_odata& od) {
using namespace scripting;
//WMC - char must be 1 byte, foo.
static_assert(sizeof(char) == 1, "char must be 1 byte!");
//WMC - step by step
//Create new LUA object and get handle
char *newod = (char*)lua_newuserdata(L, od.size + sizeof(ODATA_SIG_TYPE));
//Create or get object metatable
luaL_getmetatable(L, getTableEntry(od.idx).Name);
//Set the metatable for the object
lua_setmetatable(L, -2);
//Copy the actual object data to the Lua object
memcpy(newod, od.buf, od.size);
//Also copy in the unique sig
if (od.sig != NULL)
memcpy(newod + od.size, od.sig, sizeof(ODATA_SIG_TYPE));
else
{
ODATA_SIG_TYPE tempsig = ODATA_SIG_DEFAULT;
memcpy(newod + od.size, &tempsig, sizeof(ODATA_SIG_TYPE));
}
}
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 ((uint)lua_tonumber(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, getTableEntry((uint)lua_tonumber(L, -2)).Name, getTableEntry(od.idx).GetName());
return false;
}
lua_pop(L, 1);
}
lua_pop(L, 2);
if (od.size != ODATA_PTR_SIZE)
{
memcpy(od.buf, lua_touserdata(L, stackposition), od.size);
if (od.sig != NULL) {
//WMC - char must be 1
Assert(sizeof(char) == 1);
//WMC - Yuck. Copy sig data.
//Maybe in the future I'll do a packet userdata thing.
(*od.sig) = *(ODATA_SIG_TYPE*)(*(char **)od.buf + od.size);
}
}
else {
(*(void**)od.buf) = lua_touserdata(L, stackposition);
}
if (remove) {
lua_remove(L, stackposition);
}
return true;
}
}
}