mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-07 16:18:19 -10:00
w_bank: add a move constructor. object_copy_including_array_member returns by value, and without a move constructor the return fell back to the shallow copy constructor whenever NRVO was not applied (e.g. MSVC debug builds), after which the local's destructor deleted the freshly allocated arrays -- leaving the stored bank dangling and double-deleting at model unload. Also add noexcept to the move operations, replace the destructor call in move-assignment with explicit delete[]s (using an object after its lifetime has ended is undefined behavior), guard against self-move, and document that the defaulted copy constructor is intentionally shallow for object_copy_including_array_member's copy-then-replace pattern. LuaThread: declare the defaulted move operations noexcept. This exposed that LuaTable was not movable at all (its user-declared destructor suppressed the implicit moves), so LuaThread's implicit move spec was formally throwing -- a hard error on gcc 9, which still requires the spec on a defaulted redeclaration to match the implicit one. Restore LuaTable's rule of five and declare the LuaValue and LuaFunction copy operations noexcept (they only copy a shared_ptr, a raw pointer, and an enum), making the noexcept claims hold throughout the hierarchy. Co-Authored-By: Claude Fable 5 <[email protected]>
125 lines
2.5 KiB
C++
125 lines
2.5 KiB
C++
#include "LuaValue.h"
|
|
#include "LuaException.h"
|
|
|
|
namespace {
|
|
using namespace luacpp;
|
|
|
|
ValueType luaToEnumType(int luaType) {
|
|
switch (luaType) {
|
|
case LUA_TNONE:
|
|
return ValueType::NONE;
|
|
case LUA_TNIL:
|
|
return ValueType::NIL;
|
|
case LUA_TBOOLEAN:
|
|
return ValueType::BOOLEAN;
|
|
case LUA_TLIGHTUSERDATA:
|
|
return ValueType::LIGHTUSERDATA;
|
|
case LUA_TNUMBER:
|
|
return ValueType::NUMBER;
|
|
case LUA_TSTRING:
|
|
return ValueType::STRING;
|
|
case LUA_TTABLE:
|
|
return ValueType::TABLE;
|
|
case LUA_TFUNCTION:
|
|
return ValueType::FUNCTION;
|
|
case LUA_TUSERDATA:
|
|
return ValueType::USERDATA;
|
|
case LUA_TTHREAD:
|
|
return ValueType::THREAD;
|
|
|
|
default:
|
|
return ValueType::NONE;
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace luacpp {
|
|
LuaValue LuaValue::createNil(lua_State* L)
|
|
{
|
|
lua_pushnil(L);
|
|
|
|
LuaValue val(L);
|
|
|
|
val.setReference(UniqueLuaReference::create(L));
|
|
|
|
return val;
|
|
}
|
|
|
|
LuaValue::LuaValue() = default;
|
|
|
|
LuaValue::LuaValue(lua_State* state) : _luaState(state)
|
|
{
|
|
Assertion(state != nullptr, "Lua state pointer is not valid!");
|
|
}
|
|
|
|
LuaValue::LuaValue(const LuaValue&) noexcept = default;
|
|
LuaValue& LuaValue::operator=(const LuaValue&) noexcept = default;
|
|
|
|
LuaValue::LuaValue(LuaValue&&) noexcept = default;
|
|
LuaValue& LuaValue::operator=(LuaValue&&) noexcept = default;
|
|
|
|
LuaValue::~LuaValue() = default;
|
|
|
|
void LuaValue::setReference(const LuaReference& ref)
|
|
{
|
|
this->_reference = ref;
|
|
this->_luaState = ref->getState();
|
|
|
|
if (isValid()) {
|
|
this->_reference->pushValue(_luaState);
|
|
|
|
this->_luaType = luaToEnumType(lua_type(_luaState, -1));
|
|
|
|
lua_pop(_luaState, 1);
|
|
} else {
|
|
_luaType = ValueType::NONE;
|
|
}
|
|
}
|
|
|
|
const LuaReference LuaValue::getReference() const {
|
|
return _reference;
|
|
}
|
|
|
|
ValueType LuaValue::getValueType() const {
|
|
return _luaType;
|
|
}
|
|
|
|
bool LuaValue::isValid() const {
|
|
return _reference && _reference->isValid();
|
|
}
|
|
|
|
bool LuaValue::pushValue(lua_State* thread, bool manualStackAllocation) const
|
|
{
|
|
if (this->_reference->isValid()) {
|
|
this->_reference->pushValue(thread, manualStackAllocation);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
lua_State* LuaValue::getLuaState() const { return _luaState; }
|
|
|
|
namespace convert {
|
|
|
|
void pushValue(lua_State* luaState, const LuaValue& value) { value.pushValue(luaState); }
|
|
|
|
bool popValue(lua_State* luaState, LuaValue& target, int stackposition, bool remove)
|
|
{
|
|
if (!internal::isValidIndex(luaState, stackposition)) {
|
|
return false;
|
|
}
|
|
|
|
target.setReference(UniqueLuaReference::create(luaState, stackposition));
|
|
|
|
if (remove) {
|
|
lua_remove(luaState, stackposition);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
}
|