Browse Source

Fix Channel:push and other functions that accept love objects and store them in Variants internally. Cleaned up Variant code a bit.

--HG--
branch : minor
Alex Szpakowski 7 years ago
parent
commit
bc980b0f20
3 changed files with 38 additions and 52 deletions
  1. 32 47
      src/common/Variant.cpp
  2. 4 4
      src/common/Variant.h
  3. 2 1
      src/modules/event/wrap_Event.cpp

+ 32 - 47
src/common/Variant.cpp

@@ -26,7 +26,7 @@
 namespace love
 {
 
-static love::Type *extractudatatype(lua_State *L, int idx)
+static Proxy *tryextractproxy(lua_State *L, int idx)
 {
 	Proxy *u = (Proxy *)lua_touserdata(L, idx);
 
@@ -36,7 +36,7 @@ static love::Type *extractudatatype(lua_State *L, int idx)
 	// We could get rid of the dynamic_cast for more performance, but it would
 	// be less safe...
 	if (dynamic_cast<Object *>(u->object) != nullptr)
-		return u->type;
+		return u;
 
 	return nullptr;
 }
@@ -73,25 +73,20 @@ Variant::Variant(const char *string, size_t len)
 	}
 }
 
-Variant::Variant(void *userdata)
+Variant::Variant(void *lightuserdata)
 	: type(LUSERDATA)
 {
-	data.userdata = userdata;
+	data.userdata = lightuserdata;
 }
 
-Variant::Variant(love::Type *udatatype, void *userdata)
-	: type(FUSERDATA)
-	, udatatype(udatatype)
+Variant::Variant(love::Type *lovetype, love::Object *object)
+	: type(LOVEOBJECT)
 {
-	if (udatatype != nullptr)
-	{
-		love::Object *o = (love::Object *) userdata;
-		data.userdata = o;
-		if (o != nullptr)
-			o->retain();
-	}
-	else
-		data.userdata = userdata;
+	data.objectproxy.type = lovetype;
+	data.objectproxy.object = object;
+
+	if (data.objectproxy.object != nullptr)
+		data.objectproxy.object->retain();
 }
 
 // Variant gets ownership of the vector.
@@ -103,20 +98,18 @@ Variant::Variant(std::vector<std::pair<Variant, Variant>> *table)
 
 Variant::Variant(const Variant &v)
 	: type(v.type)
-	, udatatype(v.udatatype)
 	, data(v.data)
 {
 	if (type == STRING)
 		data.string->retain();
-	else if (type == FUSERDATA && udatatype != nullptr && data.userdata != nullptr)
-		((love::Object *) data.userdata)->retain();
+	else if (type == LOVEOBJECT && data.objectproxy.object != nullptr)
+		data.objectproxy.object->retain();
 	else if (type == TABLE)
 		data.table->retain();
 }
 
 Variant::Variant(Variant &&v)
 	: type(std::move(v.type))
-	, udatatype(std::move(v.udatatype))
 	, data(std::move(v.data))
 {
 	v.type = NIL;
@@ -124,42 +117,32 @@ Variant::Variant(Variant &&v)
 
 Variant::~Variant()
 {
-	switch (type)
-	{
-	case STRING:
+	if (type == STRING)
 		data.string->release();
-		break;
-	case FUSERDATA:
-		if (udatatype != nullptr && data.userdata != nullptr)
-			((love::Object *) data.userdata)->release();
-		break;
-	case TABLE:
+	else if (type == LOVEOBJECT && data.objectproxy.object != nullptr)
+		data.objectproxy.object->release();
+	else if (type == TABLE)
 		data.table->release();
-		break;
-	default:
-		break;
-	}
 }
 
 Variant &Variant::operator = (const Variant &v)
 {
 	if (v.type == STRING)
 		v.data.string->retain();
-	else if (v.type == FUSERDATA && v.udatatype != nullptr && v.data.userdata != nullptr)
-		((love::Object *) v.data.userdata)->retain();
+	else if (v.type == LOVEOBJECT && v.data.objectproxy.object != nullptr)
+		v.data.objectproxy.object->retain();
 	else if (v.type == TABLE)
 		v.data.table->retain();
 
 	if (type == STRING)
 		data.string->release();
-	else if (type == FUSERDATA && udatatype != nullptr && data.userdata != nullptr)
-		((love::Object *) data.userdata)->release();
+	else if (type == LOVEOBJECT && data.objectproxy.object != nullptr)
+		data.objectproxy.object->release();
 	else if (type == TABLE)
 		data.table->release();
 
 	type = v.type;
 	data = v.data;
-	udatatype = v.udatatype;
 
 	return *this;
 }
@@ -168,6 +151,7 @@ Variant Variant::fromLua(lua_State *L, int n, std::set<const void*> *tableSet)
 {
 	size_t len;
 	const char *str;
+	Proxy *p = nullptr;
 
 	if (n < 0) // Fix the stack position, we might modify it later
 		n += lua_gettop(L) + 1;
@@ -184,7 +168,14 @@ Variant Variant::fromLua(lua_State *L, int n, std::set<const void*> *tableSet)
 	case LUA_TLIGHTUSERDATA:
 		return Variant(lua_touserdata(L, n));
 	case LUA_TUSERDATA:
-		return Variant(extractudatatype(L, n), lua_touserdata(L, n));
+		p = tryextractproxy(L, n);
+		if (p != nullptr)
+			return Variant(p->type, p->object);
+		else
+		{
+			luax_typerror(L, n, "love type");
+			return Variant();
+		}
 	case LUA_TNIL:
 		return Variant();
 	case LUA_TTABLE:
@@ -259,14 +250,8 @@ void Variant::toLua(lua_State *L) const
 	case LUSERDATA:
 		lua_pushlightuserdata(L, data.userdata);
 		break;
-	case FUSERDATA:
-		if (udatatype != nullptr)
-			luax_pushtype(L, *udatatype, (love::Object *) data.userdata);
-		else
-			lua_pushlightuserdata(L, data.userdata);
-		// I know this is not the same
-		// sadly, however, it's the most
-		// I can do (at the moment).
+	case LOVEOBJECT:
+		luax_pushtype(L, *data.objectproxy.type, data.objectproxy.object);
 		break;
 	case TABLE:
 	{

+ 4 - 4
src/common/Variant.h

@@ -44,7 +44,7 @@ public:
 		STRING,
 		SMALLSTRING,
 		LUSERDATA,
-		FUSERDATA,
+		LOVEOBJECT,
 		NIL,
 		TABLE
 	};
@@ -53,8 +53,8 @@ public:
 	Variant(bool boolean);
 	Variant(double number);
 	Variant(const char *string, size_t len);
-	Variant(void *userdata);
-	Variant(love::Type *udatatype, void *userdata);
+	Variant(void *lightuserdata);
+	Variant(love::Type *type, love::Object *object);
 	Variant(std::vector<std::pair<Variant, Variant>> *table);
 	Variant(const Variant &v);
 	Variant(Variant &&v);
@@ -102,7 +102,6 @@ private:
 	static const int MAX_SMALL_STRING_LENGTH = 15;
 
 	Type type;
-	love::Type *udatatype;
 
 	union Data
 	{
@@ -110,6 +109,7 @@ private:
 		double number;
 		SharedString *string;
 		void *userdata;
+		Proxy objectproxy;
 		SharedTable *table;
 		struct
 		{

+ 2 - 1
src/modules/event/wrap_Event.cpp

@@ -74,7 +74,8 @@ int w_wait(lua_State *L)
 
 int w_push(lua_State *L)
 {
-	StrongRef<Message> m(Message::fromLua(L, 1), Acquire::NORETAIN);
+	StrongRef<Message> m;
+	luax_catchexcept(L, [&]() { m.set(Message::fromLua(L, 1), Acquire::NORETAIN); });
 
 	luax_pushboolean(L, m.get() != nullptr);