Pārlūkot izejas kodu

Use a lua_type switch/case in thread.send, to prevent casts (bug #252)
Push non-love userdata as lightuserdata, will probably break it, but shouldn't crash love (bug #243)

Bart van Strien 14 gadi atpakaļ
vecāks
revīzija
ce5927379d
2 mainītis faili ar 73 papildinājumiem un 116 dzēšanām
  1. 9 4
      src/modules/thread/Thread.cpp
  2. 64 112
      src/modules/thread/wrap_Thread.cpp

+ 9 - 4
src/modules/thread/Thread.cpp

@@ -101,10 +101,15 @@ namespace thread
 	{
 		type = FUSERDATA;
 		this->udatatype = udatatype;
-		Proxy *p = (Proxy *) userdata;
-		flags = p->flags;
-		data.userdata = p->data;
-		((love::Object *) data.userdata)->retain();
+		if (udatatype != INVALID_ID)
+		{
+			Proxy *p = (Proxy *) userdata;
+			flags = p->flags;
+			data.userdata = p->data;
+			((love::Object *) data.userdata)->retain();
+		}
+		else
+			data.userdata = userdata;
 	}
 
 	ThreadVariant::~ThreadVariant()

+ 64 - 112
src/modules/thread/wrap_Thread.cpp

@@ -70,18 +70,12 @@ namespace thread
 		return 1;
 	}
 
-	int w_Thread_get(lua_State *L)
+	bool __pushThreadVariant(lua_State *L, ThreadVariant *v)
 	{
-		Thread *t = luax_checkthread(L, 1);
-		std::string name = luax_checklstring(L, 2);
-		t->lock();
-		ThreadVariant *v = t->get(name);
-		t->clear(name);
-		t->unlock();
 		if (!v)
 		{
 			lua_pushnil(L);
-			return 1;
+			return false;
 		}
 		switch(v->type)
 		{
@@ -98,17 +92,36 @@ namespace thread
 				lua_pushlightuserdata(L, v->data.userdata);
 				break;
 			case FUSERDATA:
-			{
-				const char *name = NULL;
-				love::types.find(v->udatatype, name);
-				((love::Object *) v->data.userdata)->retain();
-				luax_newtype(L, name, v->flags, v->data.userdata);
+				if (v->udatatype != INVALID_ID)
+				{
+					const char *name = NULL;
+					love::types.find(v->udatatype, name);
+					((love::Object *) v->data.userdata)->retain();
+					luax_newtype(L, name, v->flags, v->data.userdata);
+				}
+				else
+					lua_pushlightuserdata(L, v->data.userdata);
+				// I know this is not the same
+				// sadly, however, it's the most
+				// I can do (at the moment).
 				break;
-			}
 			default:
 				lua_pushnil(L);
 				break;
 		}
+		return true;
+	}
+
+	int w_Thread_get(lua_State *L)
+	{
+		Thread *t = luax_checkthread(L, 1);
+		std::string name = luax_checklstring(L, 2);
+		t->lock();
+		ThreadVariant *v = t->get(name);
+		t->clear(name);
+		t->unlock();
+		if (!__pushThreadVariant(L, v))
+			return 1;
 		t->lock();
 		v->release();
 		t->unlock();
@@ -123,37 +136,8 @@ namespace thread
 		ThreadVariant *v = t->demand(name);
 		t->clear(name);
 		t->unlock();
-		if (!v)
-		{
-			lua_pushnil(L);
+		if (!__pushThreadVariant(L, v))
 			return 1;
-		}
-		switch(v->type)
-		{
-			case BOOLEAN:
-				lua_pushboolean(L, v->data.boolean);
-				break;
-			case NUMBER:
-				lua_pushnumber(L, v->data.number);
-				break;
-			case STRING:
-				lua_pushlstring(L, v->data.string.str, v->data.string.len);
-				break;
-			case LUSERDATA:
-				lua_pushlightuserdata(L, v->data.userdata);
-				break;
-			case FUSERDATA:
-			{
-				const char *name = NULL;
-				types.find(v->udatatype, name);
-				((love::Object *) v->data.userdata)->retain();
-				luax_newtype(L, name, v->flags, v->data.userdata);
-				break;
-			}
-			default:
-				lua_pushnil(L);
-				break;
-		}
 		t->lock();
 		v->release();
 		t->unlock();
@@ -167,37 +151,8 @@ namespace thread
 		t->lock();
 		ThreadVariant *v = t->get(name);
 		t->unlock();
-		if (!v)
-		{
-			lua_pushnil(L);
+		if (!__pushThreadVariant(L, v))
 			return 1;
-		}
-		switch(v->type)
-		{
-			case BOOLEAN:
-				lua_pushboolean(L, v->data.boolean);
-				break;
-			case NUMBER:
-				lua_pushnumber(L, v->data.number);
-				break;
-			case STRING:
-				lua_pushlstring(L, v->data.string.str, v->data.string.len);
-				break;
-			case LUSERDATA:
-				lua_pushlightuserdata(L, v->data.userdata);
-				break;
-			case FUSERDATA:
-			{
-				const char *name = NULL;
-				types.find(v->udatatype, name);
-				((love::Object *) v->data.userdata)->retain();
-				luax_newtype(L, name, v->flags, v->data.userdata);
-				break;
-			}
-			default:
-				lua_pushnil(L);
-				break;
-		}
 		t->lock();
 		v->release();
 		t->unlock();
@@ -205,51 +160,48 @@ namespace thread
 	}
 
 	Type extractudatatype(lua_State * L, int idx)
-	{
-		Type t = INVALID_ID;
-		if (!lua_isuserdata(L, idx))
-			return t;
-		if (luaL_getmetafield (L, idx, "__tostring") == 0)
-			return t;
-		lua_pushvalue(L, idx);
-		int result = lua_pcall(L, 1, 1, 0);
-		if (result == 0)
-			types.find(lua_tostring(L, -1), t);
-		if (result == 0 || result == LUA_ERRRUN)
-			lua_pop(L, 1);
-		return t;
-	}
+        {
+                Type t = INVALID_ID;
+                if (!lua_isuserdata(L, idx))
+                        return t;
+                if (luaL_getmetafield (L, idx, "__tostring") == 0)
+                        return t;
+                lua_pushvalue(L, idx);
+                int result = lua_pcall(L, 1, 1, 0);
+                if (result == 0)
+                        types.find(lua_tostring(L, -1), t);
+                if (result == 0 || result == LUA_ERRRUN)
+                        lua_pop(L, 1);
+                return t;
+        }
 
 	int w_Thread_set(lua_State *L)
 	{
 		Thread *t = luax_checkthread(L, 1);
 		std::string name = luax_checklstring(L, 2);
 		ThreadVariant *v;
-		if (lua_isboolean(L, 3))
-		{
-			v = new ThreadVariant(luax_toboolean(L, 3));
-		}
-		else if (lua_isnumber(L, 3))
-		{
-			v = new ThreadVariant(lua_tonumber(L, 3));
-		}
-		else if (lua_isstring(L, 3))
-		{
-			size_t len;
-			const char *str = lua_tolstring(L, 3, &len);
-			v = new ThreadVariant(str, len);
-		}
-		else if (lua_islightuserdata(L, 3))
-		{
-			v = new ThreadVariant(lua_touserdata(L, 3));
-		}
-		else if (lua_isuserdata(L, 3))
-		{
-			v = new ThreadVariant(extractudatatype(L, 3), lua_touserdata(L, 3));
-		}
-		else
+		size_t len;
+		const char *str;
+		switch(lua_type(L, 3))
 		{
-			return luaL_error(L, "Expected boolean, number, string or userdata");
+			case LUA_TBOOLEAN:
+				v = new ThreadVariant(luax_toboolean(L, 3));
+				break;
+			case LUA_TNUMBER:
+				v = new ThreadVariant(lua_tonumber(L, 3));
+				break;
+			case LUA_TSTRING:
+				str = lua_tolstring(L, 3, &len);
+				v = new ThreadVariant(str, len);
+				break;
+			case LUA_TLIGHTUSERDATA:
+				v = new ThreadVariant(lua_touserdata(L, 3));
+				break;
+			case LUA_TUSERDATA:
+				v = new ThreadVariant(extractudatatype(L, 3), lua_touserdata(L, 3));
+				break;
+			default:
+				return luaL_error(L, "Expected boolean, number, string or userdata");
 		}
 		t->set(name, v);
 		v->release();