#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 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 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; } } }