Преглед на файлове

Implement Table wrapper, make use of it in StateWrapper

Ole преди 9 години
родител
ревизия
9e61e382d0
променени са 3 файла, в които са добавени 163 реда и са изтрити 81 реда
  1. 1 0
      lib/luwra.hpp
  2. 12 81
      lib/luwra/state.hpp
  3. 150 0
      lib/luwra/tables.hpp

+ 1 - 0
lib/luwra.hpp

@@ -3,6 +3,7 @@
 
 #include "luwra/common.hpp"
 #include "luwra/types.hpp"
+#include "luwra/tables.hpp"
 #include "luwra/stack.hpp"
 #include "luwra/auxiliary.hpp"
 #include "luwra/functions.hpp"

+ 12 - 81
lib/luwra/state.hpp

@@ -9,70 +9,17 @@
 
 #include "common.hpp"
 #include "auxiliary.hpp"
+#include "tables.hpp"
 
 #include <string>
 #include <utility>
 
 LUWRA_NS_BEGIN
 
-/**
- * Accessor for an entry in the global namespace
- */
-struct GlobalAccessor {
-	State* state;
-	std::string key;
-
-	inline
-	GlobalAccessor(State* state, const std::string& key): state(state), key(key) {}
-
-	/**
-	 * Assign a new value.
-	 */
-	template <typename V> inline
-	GlobalAccessor& set(V value) {
-		setGlobal(state, key, value);
-		return *this;
-	}
-
-	/**
-	 * Shortcut for `set()`
-	 */
-	template <typename V> inline
-	GlobalAccessor& operator =(V value) {
-		return set<V>(value);
-	}
-
-	/**
-	 * Retrieve the associated value.
-	 */
-	template <typename V> inline
-	V read() {
-		return getGlobal<V>(state, key);
-	}
-
-	/**
-	 * Shortcut for `read()`
-	 */
-	template <typename V> inline
-	operator V() {
-		return read<V>();
-	}
-
-	/**
-	 * Update the fields of an existing table.
-	 */
-	inline
-	void updateFields(const luwra::FieldVector& fields) {
-		lua_getglobal(state, key.c_str());
-		luwra::setFields(state, -1, fields);
-		lua_pop(state, 1);
-	}
-};
-
 /**
  * Wrapper for a Lua state
  */
-struct StateWrapper {
+struct StateWrapper: Table {
 	State* state;
 	bool close_state;
 
@@ -80,13 +27,21 @@ struct StateWrapper {
 	 * Operate on a foreign state instance.
 	 */
 	inline
-	StateWrapper(State* state): state(state), close_state(false) {}
+	StateWrapper(State* state):
+		Table({state, LUA_RIDX_GLOBALS, false}),
+		state(state),
+		close_state(false)
+	{}
 
 	/**
 	 * Create a new Lua state.
 	 */
 	inline
-	StateWrapper(): state(luaL_newstate()), close_state(true) {}
+	StateWrapper():
+		Table({luaL_newstate(), LUA_RIDX_GLOBALS, false}),
+		state(ref.impl->state),
+		close_state(true)
+	{}
 
 	inline
 	~StateWrapper() {
@@ -104,30 +59,6 @@ struct StateWrapper {
 		luaL_openlibs(state);
 	}
 
-	/**
-	 * Retrieve a global value.
-	 */
-	template <typename V> inline
-	V getGlobal(const std::string& key) const {
-		return ::luwra::getGlobal<V>(state, key);
-	}
-
-	/**
-	 * Assign a global value.
-	 */
-	template <typename V> inline
-	void setGlobal(const std::string& key, V value) const {
-		::luwra::setGlobal(state, key, value);
-	}
-
-	/**
-	 * Create an accessor to a global value.
-	 */
-	inline
-	GlobalAccessor operator [](const std::string& key) const {
-		return GlobalAccessor(state, key);
-	}
-
 	/**
 	 * See [luwra::registerUserType](@ref luwra::registerUserType).
 	 */

+ 150 - 0
lib/luwra/tables.hpp

@@ -0,0 +1,150 @@
+/* Luwra
+ * Minimal-overhead Lua wrapper for C++
+ *
+ * Copyright (C) 2016, Ole Krüger <ole@vprsm.de>
+ */
+
+#ifndef LUWRA_TABLES_H_
+#define LUWRA_TABLES_H_
+
+#include "common.hpp"
+#include "types.hpp"
+#include "auxiliary.hpp"
+
+#include <iostream>
+
+LUWRA_NS_BEGIN
+
+namespace internal {
+	template <typename K>
+	struct TableAccessor;
+}
+
+struct Table {
+	Reference ref;
+
+	Table(const Reference& ref):
+		ref(ref)
+	{}
+
+	Table(State* state, int index):
+		ref(state, index, true)
+	{
+		luaL_checktype(state, index, LUA_TTABLE);
+	}
+
+	template <typename K> inline
+	internal::TableAccessor<K> access(K&& key);
+
+	template <typename K> inline
+	internal::TableAccessor<K> operator [](K&& key) {
+		return access<K>(std::forward<K>(key));
+	}
+
+	inline
+	void update(const FieldVector& fields) {
+		State* state = ref.impl->state;
+
+		push(state, ref);
+		setFields(state, -1, fields);
+
+		lua_pop(state, 1);
+	}
+
+	template <typename V, typename K> inline
+	void set(K&& key, V&& value) {
+		State* state = ref.impl->state;
+		push(state, ref);
+
+		size_t pushedKeys = push(state, key);
+		if (pushedKeys > 1) lua_pop(state, pushedKeys - 1);
+
+		size_t pushedValues = push(state, value);
+		if (pushedValues > 1) lua_pop(state, pushedValues - 1);
+
+		lua_rawset(state, -3);
+		lua_pop(state, 1);
+	}
+
+	template <typename V, typename K> inline
+	V get(K&& key) {
+		State* state = ref.impl->state;
+		push(state, ref);
+
+		size_t pushedKeys = push(state, key);
+		if (pushedKeys > 1) lua_pop(state, pushedKeys - 1);
+
+		lua_rawget(state, -2);
+		lua_remove(state, -2);
+
+		return read<V>(state, -1);
+	}
+};
+
+namespace internal {
+	template <typename K>
+	struct TableAccessor {
+		Table parent;
+		K key;
+
+		template <typename V> inline
+		V read() {
+			return parent.get<V>(key);
+		}
+
+		template <typename V> inline
+		operator V() {
+			return parent.get<V>(key);
+		}
+
+		template <typename V> inline
+		TableAccessor<K>& write(V&& value) {
+			parent.set(key, std::forward<V>(value));
+			return *this;
+		}
+
+		template <typename V> inline
+		TableAccessor<K>& operator =(V&& value) {
+			parent.set(key, std::forward<V>(value));
+			return *this;
+		}
+
+		template <typename T> inline
+		TableAccessor<T> access(T&& subkey) {
+			return {read<Table>(), subkey};
+		}
+
+		template <typename T> inline
+		TableAccessor<T> operator [](T&& subkey) {
+			return {read<Table>(), subkey};
+		}
+	};
+}
+
+/**
+ * Table
+ */
+template <typename K> inline
+internal::TableAccessor<K> Table::access(K&& key) {
+	return {*this, key};
+}
+
+/**
+ * See [Table](@ref Table).
+ */
+template <>
+struct Value<Table> {
+	static inline
+	Table read(State* state, int index) {
+		return {state, index};
+	}
+
+	static inline
+	size_t push(State* state, const Table& value) {
+		return value.ref.impl->push(state);
+	}
+};
+
+LUWRA_NS_END
+
+#endif