Commits

Igor Baidiuk committed 2289c18

Implemented in-place tuple with safe copying; compilable but invalid without Table done right

Comments (0)

Files changed (2)

src/common/Variant.cpp

 		return t;
 	}
 
+	Variant::Variant()
+		: type(UNKNOWN)
+	{ }
+
 	Variant::Variant(bool boolean)
 	{
 		type = BOOLEAN;
 			data.full.data = userdata;
 	}
 
-	Variant::Variant(Ptr<Variant>* tuple, size_t size)
-	{
-		type = TUPLE;
-		data.tuple.array = new Ptr<Variant>[size];
-		data.tuple.len = size;
-
-		for (size_t i = 0; i < size; ++i)
-			data.tuple.array[i] = tuple[i];
-	}
-
 	Variant::Variant(Pair* table, size_t size)
 	{
 		type = TABLE;
 				((love::Object*)data.full.data)->retain();
 			break;
 		case TUPLE:
+			if (data.tuple = other.data.tuple)
+				((RefTuple*)data.tuple)->retain();
 			break;
 		case TABLE:
 			break;
 		}
+		return *this;
 	}
 
 	Variant::~Variant()
 					((love::Object *) data.full.data)->release();
 				break;
 			case TUPLE:
-				if (data.tuple.array)
-					delete[] data.tuple.array;
+				if (data.tuple)
+					((RefTuple*)data.tuple)->release();
 				break;
 			case TABLE:
 				if (data.table.pairs)
 		}
 	}
 
-	VariantPtr Variant::getVariant(lua_State *L, int n)
+	Variant Variant::getVariant(lua_State *L, int n)
 	{
 		size_t len = 0;
 		const char *str = 0;
 		switch(lua_type(L, n))
 		{
 			case LUA_TBOOLEAN:
-				return VariantPtr::make(luax_toboolean(L, n));
+				return Variant(luax_toboolean(L, n));
 			case LUA_TNUMBER:
-				return VariantPtr::make(lua_tonumber(L, n));
+				return Variant(lua_tonumber(L, n));
 			case LUA_TSTRING:
 				str = lua_tolstring(L, n, &len);
-				return VariantPtr::make(str, len);
+				return Variant(str, len);
 			case LUA_TLIGHTUSERDATA:
-				return new Variant(lua_touserdata(L, n));
+				return Variant(lua_touserdata(L, n));
 			case LUA_TUSERDATA:
-				return new Variant(extractudatatype(L, n), lua_touserdata(L, n));
+				return Variant(extractudatatype(L, n), lua_touserdata(L, n));
 			case LUA_TTABLE:
 				{
 					lua_checkstack(L, 4);
 					lua_pushnil(L);
 					while (lua_next(L, n))
 					{
-						Variant::Pair pair = { getVariant(L, -2), getVariant(L, -1) };
+						Variant::Pair pair = { new Variant(getVariant(L, -2)), new Variant(getVariant(L, -1)) };
 						if (pair.key && pair.value)
 							pairs.push_back(pair);
 						lua_pop(L, 1);
 					}
-					return new Variant(&pairs.front(), pairs.size());
+					return Variant(&pairs.front(), pairs.size());
 				}
 		}
-		return VariantPtr();
+		return Variant();
 	}
 
 	Variant *Variant::fromLua(lua_State *L, int n_from, int n_to)
 		{
 			int step = n_to - n_from >= 0 ? 1 : -1;
 			size_t size = std::abs(n_to - n_from) + 1;
-			std::vector<Ptr<Variant> > items;
+			std::vector<Variant> items;
 
 			for (int i = 0; i < (int)size; ++i)
-			{
-				VariantPtr v = getVariant(L, n_from + step*i);
-				if (v)
-					items.push_back(v);
-			}
+				items.push_back(getVariant(L, n_from + step*i));
 
-			return new Variant(&items.front(), items.size());
+			Variant* v = new Variant();
+			v->type = TUPLE;
+			v->data.tuple = RefTuple::create(items.size(), &items.front());
+			return v;
 		}
 		else
-			return getVariant(L, n_from).detach();
+			return new Variant(getVariant(L, n_from));
 	}
 
 	int Variant::toLua(lua_State *L)
 				// I can do (at the moment).
 				break;
 			case TUPLE: // Tuple, all its values are placed on stack in direct order
-				lua_checkstack(L, data.tuple.len + 1);
-				for (size_t i = 0; i < data.tuple.len; ++i)
-					if (data.tuple.array[i])
-						data.tuple.array[i]->toLua(L);
-				return (int)data.tuple.len;
+				if (!data.tuple)
+					return 0;
+				{
+					RefTuple* t = (RefTuple*)data.tuple;
+					lua_checkstack(L, t->size() + 1);
+					for (Variant *i = t->begin(), *e = t->end(); i != e; ++i)
+						i->toLua(L);
+					return t->size();
+				}
 			case TABLE: // de-marshal table
 				lua_checkstack(L, 4);
 				lua_newtable(L);
 			printf("Userdata at %p\n", data.full.data);
 			break;
 		case TUPLE:
-			printf("%u-tuple:\n", data.tuple.len);
-			++offset;
-			for (size_t i = 0; i < data.tuple.len; ++i)
-				if (data.tuple.array[i])
-					data.tuple.array[i]->prettyPrint();
-				else
-					printf("%*s NIL\n", offset*2, "");
-			--offset;
+			if (data.tuple)
+			{
+				RefTuple* tuple = (RefTuple*)data.tuple;
+				printf("%u-tuple:\n", tuple->size());
+				++offset;
+				for (Variant *i = tuple->begin(), *e = tuple->end(); i != e; ++i)
+					i->prettyPrint();
+				--offset;
+			}
+			else
+				printf("0-tuple\n");
 			break;
 		case TABLE:
 			printf("%u-table:\n", data.table.len);

src/common/Variant.h

 				void *data;
 				love::Type type;
 			} full;
-			struct {
-				Ptr<Variant>* array;
-				size_t len;
-			} tuple;
+			void* tuple;
 			struct {
 				Pair* pairs;
 				size_t len;
 		} data;
 		bits flags;
 
+		Variant();
 		Variant(void *userdata);
 		Variant(love::Type udatatype, void *userdata);
-		Variant(Ptr<Variant>* tuple, size_t size);
 		Variant(Pair* table, size_t size);
 
-		static Ptr<Variant> getVariant(lua_State* L, int n);
+		static Variant getVariant(lua_State* L, int n);
 
 	public:		
 		Variant(bool boolean);