mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-08 07:28:22 -10:00
155 lines
3.3 KiB
C++
155 lines
3.3 KiB
C++
#include "LuaException.h"
|
|
#include "LuaTable.h"
|
|
|
|
namespace luacpp {
|
|
LuaTable LuaTable::create(lua_State* state) {
|
|
LuaTable table;
|
|
|
|
lua_newtable(state);
|
|
|
|
table.setReference(UniqueLuaReference::create(state));
|
|
|
|
lua_pop(state, 1);
|
|
|
|
return table;
|
|
}
|
|
|
|
LuaTable::LuaTable() : LuaValue() {
|
|
}
|
|
|
|
LuaTable::~LuaTable() {
|
|
}
|
|
|
|
bool LuaTable::setMetatable(const LuaTable& table) {
|
|
if (!table.getReference()->isValid()) {
|
|
throw LuaException("Meta table reference is not valid!");
|
|
}
|
|
|
|
this->pushValue(_luaState);
|
|
table.pushValue(_luaState);
|
|
|
|
lua_setmetatable(_luaState, -2);
|
|
|
|
lua_pop(_luaState, 1);
|
|
|
|
return true;
|
|
}
|
|
|
|
void LuaTable::setReference(const LuaReference& ref) {
|
|
lua_State* L = ref->getState();
|
|
|
|
ref->pushValue(L);
|
|
|
|
if (lua_type(L, -1) != LUA_TTABLE) {
|
|
lua_pop(L, 1);
|
|
throw LuaException("Reference does not refer to a table!");
|
|
} else {
|
|
lua_pop(L, 1);
|
|
LuaValue::setReference(ref);
|
|
}
|
|
}
|
|
|
|
size_t LuaTable::getLength() const {
|
|
this->pushValue(_luaState);
|
|
|
|
size_t length = lua_objlen(_luaState, -1);
|
|
|
|
lua_pop(_luaState, 1);
|
|
|
|
return length;
|
|
}
|
|
|
|
LuaTable::iterator::iterator(const LuaTable& parent) {
|
|
_iter.reset(new LuaTableIterator(parent));
|
|
|
|
// Ensure that this value is correct if we try to iterate over an empty table
|
|
_atEnd = !_iter->hasElement();
|
|
}
|
|
LuaTable::iterator::iterator() : _iter(nullptr), _atEnd(true) {
|
|
}
|
|
bool LuaTable::iterator::operator==(const iterator& other) {
|
|
return _atEnd == other._atEnd;
|
|
}
|
|
bool LuaTable::iterator::operator!=(const LuaTable::iterator& other) {
|
|
return !(*this == other);
|
|
}
|
|
LuaTable::iterator& LuaTable::iterator::operator++() {
|
|
_iter->toNextElement();
|
|
|
|
_atEnd = !_iter->hasElement();
|
|
|
|
return *this;
|
|
}
|
|
LuaTable::iterator& LuaTable::iterator::operator++(int) {
|
|
return ++(*this); // Post-fix operator doesn't make sense for us.
|
|
}
|
|
std::pair<LuaValue, LuaValue> LuaTable::iterator::operator*() {
|
|
return _iter->getElement();
|
|
}
|
|
|
|
LuaTable::iterator LuaTable::begin() const {
|
|
iterator iter(*this);
|
|
|
|
// This will call lua_next and automatically handle the end of the table
|
|
return iter;
|
|
}
|
|
LuaTable::iterator LuaTable::end() const { // NOLINT(readability-convert-member-functions-to-static)
|
|
return iterator(); // Empty iterator
|
|
}
|
|
|
|
LuaTableIterator::LuaTableIterator(const LuaTable& t) : _luaState(t.getLuaState()) {
|
|
_stackTop = lua_gettop(_luaState);
|
|
|
|
t.pushValue(_luaState);
|
|
lua_pushnil(_luaState);
|
|
|
|
toNextElement();
|
|
}
|
|
LuaTableIterator::~LuaTableIterator() {
|
|
lua_settop(_luaState, _stackTop);
|
|
}
|
|
bool LuaTableIterator::hasElement() {
|
|
return _hasElement;
|
|
}
|
|
void LuaTableIterator::toNextElement() {
|
|
auto ret = lua_next(_luaState, -2);
|
|
|
|
_hasElement = ret != 0;
|
|
|
|
if (_hasElement) {
|
|
LuaValue key;
|
|
key.setReference(UniqueLuaReference::create(_luaState, -2));
|
|
|
|
LuaValue value;
|
|
value.setReference(UniqueLuaReference::create(_luaState, -1));
|
|
|
|
_currentVal = std::make_pair(key, value);
|
|
|
|
// Remove value from stack
|
|
lua_pop(_luaState, 1);
|
|
}
|
|
}
|
|
std::pair<LuaValue, LuaValue> LuaTableIterator::getElement() {
|
|
return _currentVal;
|
|
}
|
|
|
|
bool convert::popValue(lua_State* luaState, LuaTable& target, int stackposition, bool remove) {
|
|
if (!internal::isValidIndex(luaState, stackposition)) {
|
|
return false;
|
|
}
|
|
|
|
if (!lua_istable(luaState, stackposition)) {
|
|
return false;
|
|
} else {
|
|
target.setReference(UniqueLuaReference::create(luaState, stackposition));
|
|
|
|
if (remove) {
|
|
lua_remove(luaState, stackposition);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
}
|