1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
#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;
}
}
}
|