瀏覽代碼

Add support for "flat" tables to Variant.

This means you can now use Variants (used by Channels and love.event, for instance) to send tables as long as they only contain keys and values supported by Variant, AND they are not tables themselves.
Bart van Strien 12 年之前
父節點
當前提交
98d92d3e1f
共有 2 個文件被更改,包括 78 次插入3 次删除
  1. 71 1
      src/common/Variant.cpp
  2. 7 2
      src/common/Variant.h

+ 71 - 1
src/common/Variant.cpp

@@ -42,6 +42,18 @@ love::Type extractudatatype(lua_State *L, int idx)
 	return t;
 	return t;
 }
 }
 
 
+static inline void delete_table(std::vector<std::pair<Variant*, Variant*> > *table)
+{
+	while (!table->empty())
+	{
+		std::pair<Variant*, Variant*> &kv = table->back();
+		kv.first->release();
+		kv.second->release();
+		table->pop_back();
+	}
+	delete table;
+}
+
 Variant::Variant()
 Variant::Variant()
 	: type(NIL)
 	: type(NIL)
 	, data()
 	, data()
@@ -97,6 +109,13 @@ Variant::Variant(love::Type udatatype, void *userdata)
 		data.userdata = userdata;
 		data.userdata = userdata;
 }
 }
 
 
+// Variant gets ownership of the vector.
+Variant::Variant(std::vector<std::pair<Variant*, Variant*> > *table)
+	: type(TABLE)
+{
+	data.table = table;
+}
+
 Variant::~Variant()
 Variant::~Variant()
 {
 {
 	switch (type)
 	switch (type)
@@ -107,16 +126,21 @@ Variant::~Variant()
 	case FUSERDATA:
 	case FUSERDATA:
 		((love::Object *) data.userdata)->release();
 		((love::Object *) data.userdata)->release();
 		break;
 		break;
+	case TABLE:
+		delete_table(data.table);
 	default:
 	default:
 		break;
 		break;
 	}
 	}
 }
 }
 
 
-Variant *Variant::fromLua(lua_State *L, int n)
+Variant *Variant::fromLua(lua_State *L, int n, bool allowTables)
 {
 {
 	Variant *v = NULL;
 	Variant *v = NULL;
 	size_t len;
 	size_t len;
 	const char *str;
 	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))
 	switch (lua_type(L, n))
 	{
 	{
 	case LUA_TBOOLEAN:
 	case LUA_TBOOLEAN:
@@ -138,6 +162,42 @@ Variant *Variant::fromLua(lua_State *L, int n)
 	case LUA_TNIL:
 	case LUA_TNIL:
 		v = new Variant();
 		v = new Variant();
 		break;
 		break;
+	case LUA_TTABLE:
+		if (allowTables)
+		{
+			bool success = true;
+			std::vector<std::pair<Variant*, Variant*> > *table = new std::vector<std::pair<Variant*, Variant*> >();
+			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;
 	return v;
 }
 }
@@ -175,6 +235,16 @@ void Variant::toLua(lua_State *L)
 		// sadly, however, it's the most
 		// sadly, however, it's the most
 		// I can do (at the moment).
 		// I can do (at the moment).
 		break;
 		break;
+	case TABLE:
+		lua_newtable(L);
+		for (int i = 0; i < data.table->size(); ++i)
+		{
+			std::pair<Variant*, Variant*> &kv = data.table->at(i);
+			kv.first->toLua(L);
+			kv.second->toLua(L);
+			lua_settable(L, -3);
+		}
+		break;
 	case NIL:
 	case NIL:
 	default:
 	default:
 		lua_pushnil(L);
 		lua_pushnil(L);

+ 7 - 2
src/common/Variant.h

@@ -25,6 +25,8 @@
 #include "common/Object.h"
 #include "common/Object.h"
 
 
 #include <cstring>
 #include <cstring>
+#include <vector>
+#include <utility>
 
 
 namespace love
 namespace love
 {
 {
@@ -40,9 +42,10 @@ public:
 	Variant(char c);
 	Variant(char c);
 	Variant(void *userdata);
 	Variant(void *userdata);
 	Variant(love::Type udatatype, void *userdata);
 	Variant(love::Type udatatype, void *userdata);
+	Variant(std::vector<std::pair<Variant*, Variant*> > *table);
 	virtual ~Variant();
 	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);
 	void toLua(lua_State *L);
 
 
 private:
 private:
@@ -55,7 +58,8 @@ private:
 		STRING,
 		STRING,
 		LUSERDATA,
 		LUSERDATA,
 		FUSERDATA,
 		FUSERDATA,
-		NIL
+		NIL,
+		TABLE
 	} type;
 	} type;
 	union
 	union
 	{
 	{
@@ -68,6 +72,7 @@ private:
 			size_t len;
 			size_t len;
 		} string;
 		} string;
 		void *userdata;
 		void *userdata;
+		std::vector<std::pair<Variant*, Variant*> > *table;
 	} data;
 	} data;
 	love::Type udatatype;
 	love::Type udatatype;
 	bits flags;
 	bits flags;