Explorar o código

Add sort-of-map-based version of setFields

Ole %!s(int64=10) %!d(string=hai) anos
pai
achega
54be78c1e4
Modificáronse 3 ficheiros con 138 adicións e 20 borrados
  1. 33 9
      lib/luwra/auxiliary.hpp
  2. 76 0
      lib/luwra/types.hpp
  3. 29 11
      tests/auxiliary.cpp

+ 33 - 9
lib/luwra/auxiliary.hpp

@@ -10,6 +10,9 @@
 #include "common.hpp"
 #include "types.hpp"
 
+#include <vector>
+#include <utility>
+
 LUWRA_NS_BEGIN
 
 /**
@@ -76,6 +79,36 @@ void setFields(State* state, int index, R&&... args) {
 	internal::EntryPusher<R...>::push(state, index, std::forward<R>(args)...);
 }
 
+/**
+ *
+ */
+using FieldVector = std::vector<std::pair<Pushable, Pushable>>;
+
+/**
+ *
+ */
+static inline
+void setFields(State* state, int index, const FieldVector& fields) {
+	if (index < 0)
+		index = lua_gettop(state) + (index + 1);
+
+	for (const auto& pair: fields) {
+		pair.first.push(state);
+		pair.second.push(state);
+		lua_rawset(state, index);
+	}
+}
+
+template <>
+struct Value<FieldVector> {
+	static inline
+	size_t push(State* state, const FieldVector& fields) {
+		lua_newtable(state);
+		setFields(state, -1, fields);
+		return 1;
+	}
+};
+
 /**
  * Retrieve a field from a table.
  */
@@ -93,15 +126,6 @@ V getField(State* state, int index, K key) {
 	return value;
 }
 
-/**
- * Create a new table and set its fields.
- */
-template <typename... R> static inline
-void newTable(State* state, R&&... args) {
-	lua_newtable(state);
-	setFields(state, lua_gettop(state), std::forward<R>(args)...);
-}
-
 LUWRA_NS_END
 
 #endif

+ 76 - 0
lib/luwra/types.hpp

@@ -365,6 +365,82 @@ struct Value<const T>: Value<T> {};
 template <typename T>
 struct Value<volatile T>: Value<T> {};
 
+/**
+ *
+ */
+struct PushableI {
+	virtual
+	size_t push(State* state) const = 0;
+
+	virtual
+	PushableI* copy() const = 0;
+
+	virtual
+	~PushableI() {}
+};
+
+/**
+ *
+ */
+template <typename T>
+struct PushableT: virtual PushableI {
+	T value;
+
+	inline
+	PushableT(T value): value(value) {}
+
+	virtual
+	size_t push(State* state) const {
+		return Value<T>::push(state, value);
+	}
+
+	virtual
+	PushableI* copy() const {
+		return new PushableT<T>(value);
+	}
+};
+
+/**
+ *
+ */
+struct Pushable: virtual PushableI {
+	PushableI* interface;
+
+	template <typename T> inline
+	Pushable(T value): interface(new PushableT<T>(value)) {}
+
+	inline
+	Pushable(Pushable&& other): interface(other.interface) {
+		other.interface = nullptr;
+	}
+
+	Pushable(const Pushable& other): interface(other.interface->copy()) {}
+
+	virtual
+	size_t push(State* state) const {
+		return interface->push(state);
+	}
+
+	virtual
+	PushableI* copy() const {
+		return new Pushable(*this);
+	}
+
+	virtual
+	~Pushable() {
+		if (interface)
+			delete interface;
+	}
+};
+
+template <>
+struct Value<Pushable> {
+	static inline
+	size_t push(State* state, const Pushable& value) {
+		return value.push(state);
+	}
+};
+
 LUWRA_NS_END
 
 #endif

+ 29 - 11
tests/auxiliary.cpp

@@ -37,19 +37,37 @@ TEST_CASE("getGlobal") {
 
 TEST_CASE("setFields") {
 	luwra::StateWrapper state;
-
 	lua_newtable(state);
-	luwra::setFields(
-		state, -1,
-		"test", 1338,
-		123,    456
-	);
-
-	lua_setglobal(state, "test");
 
-	REQUIRE(luaL_dostring(state, "return test.test, test[123]") == LUA_OK);
-	REQUIRE(luwra::read<int>(state, -2) == 1338);
-	REQUIRE(luwra::read<int>(state, -1) == 456);
+	SECTION("templateVersion") {
+		luwra::setFields(
+			state, -1,
+			"test", 1338,
+			123,    456
+		);
+
+		lua_setglobal(state, "test");
+
+		REQUIRE(luaL_dostring(state, "return test.test, test[123]") == LUA_OK);
+		REQUIRE(luwra::read<int>(state, -2) == 1338);
+		REQUIRE(luwra::read<int>(state, -1) == 456);
+	}
+
+	SECTION("mapVersion") {
+		luwra::setFields(
+			state, -1,
+			{
+				{"test", 1338},
+				{123,    456}
+			}
+		);
+
+		lua_setglobal(state, "test");
+
+		REQUIRE(luaL_dostring(state, "return test.test, test[123]") == LUA_OK);
+		REQUIRE(luwra::read<int>(state, -2) == 1338);
+		REQUIRE(luwra::read<int>(state, -1) == 456);
+	}
 }
 
 TEST_CASE("getField") {