diff --git a/src/common/Variant.cpp b/src/common/Variant.cpp index f2b1b6144..38cfcd0fa 100644 --- a/src/common/Variant.cpp +++ b/src/common/Variant.cpp @@ -42,6 +42,18 @@ love::Type extractudatatype(lua_State *L, int idx) return t; } +static inline void delete_table(std::vector > *table) +{ + while (!table->empty()) + { + std::pair &kv = table->back(); + kv.first->release(); + kv.second->release(); + table->pop_back(); + } + delete table; +} + Variant::Variant() : type(NIL) , data() @@ -97,6 +109,13 @@ Variant::Variant(love::Type udatatype, void *userdata) data.userdata = userdata; } +// Variant gets ownership of the vector. +Variant::Variant(std::vector > *table) + : type(TABLE) +{ + data.table = table; +} + Variant::~Variant() { switch (type) @@ -107,16 +126,21 @@ Variant::~Variant() case FUSERDATA: ((love::Object *) data.userdata)->release(); break; + case TABLE: + delete_table(data.table); default: break; } } -Variant *Variant::fromLua(lua_State *L, int n) +Variant *Variant::fromLua(lua_State *L, int n, bool allowTables) { Variant *v = NULL; size_t len; const char *str; + if (n < 0) // Fix the stack position, we might modify it later + n += lua_gettop(L) + 1; + switch (lua_type(L, n)) { case LUA_TBOOLEAN: @@ -138,6 +162,42 @@ Variant *Variant::fromLua(lua_State *L, int n) case LUA_TNIL: v = new Variant(); break; + case LUA_TTABLE: + if (allowTables) + { + bool success = true; + std::vector > *table = new std::vector >(); + lua_pushnil(L); + while (lua_next(L, n)) + { + Variant *key = fromLua(L, -2, false); + if (!key) + { + success = false; + lua_pop(L, 2); + break; + } + + Variant *value = fromLua(L, -1, false); + if (!value) + { + delete key; + success = false; + lua_pop(L, 2); + break; + } + + table->push_back(std::make_pair(key, value)); + + lua_pop(L, 1); + } + + if (success) + v = new Variant(table); + else + delete_table(table); + } + break; } return v; } @@ -175,6 +235,16 @@ void Variant::toLua(lua_State *L) // sadly, however, it's the most // I can do (at the moment). break; + case TABLE: + lua_newtable(L); + for (int i = 0; i < data.table->size(); ++i) + { + std::pair &kv = data.table->at(i); + kv.first->toLua(L); + kv.second->toLua(L); + lua_settable(L, -3); + } + break; case NIL: default: lua_pushnil(L); diff --git a/src/common/Variant.h b/src/common/Variant.h index 8f5dfa4e7..e75c676de 100644 --- a/src/common/Variant.h +++ b/src/common/Variant.h @@ -25,6 +25,8 @@ #include "common/Object.h" #include +#include +#include namespace love { @@ -40,9 +42,10 @@ public: Variant(char c); Variant(void *userdata); Variant(love::Type udatatype, void *userdata); + Variant(std::vector > *table); virtual ~Variant(); - static Variant *fromLua(lua_State *L, int n); + static Variant *fromLua(lua_State *L, int n, bool allowTables = true); void toLua(lua_State *L); private: @@ -55,7 +58,8 @@ private: STRING, LUSERDATA, FUSERDATA, - NIL + NIL, + TABLE } type; union { @@ -68,6 +72,7 @@ private: size_t len; } string; void *userdata; + std::vector > *table; } data; love::Type udatatype; bits flags;