changeset 207:d859ed8bc815

Luae: add pushIterator
author David Demelier <markand@malikania.fr>
date Fri, 28 Feb 2014 16:51:09 +0100
parents b54c83ed71ca
children 3b0e276f0866
files C++/Luae.h
diffstat 1 files changed, 136 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/C++/Luae.h	Sun Feb 23 22:14:43 2014 +0100
+++ b/C++/Luae.h	Fri Feb 28 16:51:09 2014 +0100
@@ -76,6 +76,24 @@
 	};
 
 	/**
+	 * @struct Iterator
+	 * @brief Wrap STL containers
+	 */
+	template <typename Type>
+	struct Iterator {
+		Type	begin;
+		Type	end;
+		Type	current;
+
+		Iterator(Type begin, Type end)
+			: begin(begin)
+			, end(end)
+			, current(begin)
+		{
+		}
+	};
+
+	/**
 	 * Preload a library, it will be added to package.preload so the
 	 * user can successfully call require "name". In order to work, you need
 	 * to open luaopen_package and luaopen_base first.
@@ -101,6 +119,39 @@
 	}
 
 	/**
+	 * Load all Lua libraries.
+	 *
+	 * @param L the Lua state
+	 */
+	static inline void openlibs(lua_State *L)
+	{
+		luaL_openlibs(L);
+	}
+
+	/**
+	 * Set a global.
+	 *
+	 * @param L the Lua state
+	 * @param name the name
+	 */
+	static inline void setglobal(lua_State *L, const std::string &name)
+	{
+		lua_setglobal(L, name.c_str());
+	}
+
+	/**
+	 * Push a function with an optional number of upvalues.
+	 *
+	 * @param L the Lua state
+	 * @param func the function
+	 * @param nup the number of up values
+	 */
+	static inline void pushfunction(lua_State *L, lua_CFunction func, int nup = 0)
+	{
+		lua_pushcclosure(L, func, nup);
+	}
+
+	/**
 	 * Move the top element at the given index.
 	 *
 	 * @param L the Lua state
@@ -272,6 +323,57 @@
 	}
 
 	/**
+	 * Push an iterator function onto the stack. May be used by functions
+	 * calls or directly with __pairs.
+	 *
+	 * The container must at least have:
+	 *	value_type,
+	 *	const_iterator
+	 *
+	 * The value of the container must also be pushable with Luae::Convert.
+	 *
+	 * @param L the Lua state
+	 * @param container the container
+	 * @return 1
+	 */
+	template <typename Container,
+		  typename Converter = Convert<typename Container::value_type>>
+	static int pushIterator(lua_State *L, const Container &container)
+	{
+		using ValueType		= typename Container::value_type;
+		using IteratorType	= typename Container::const_iterator;
+
+		LUAE_STACK_CHECKBEGIN(L);
+
+		auto it = new (L) Iterator<IteratorType>(container.cbegin(), container.cend());
+
+		lua_createtable(L, 0, 0);
+		lua_pushcfunction(L, [] (lua_State *L) -> int {
+			toType<Iterator<IteratorType> *>(L, 1)->~Iterator<IteratorType>();
+
+			return 0;
+		});
+		lua_setfield(L, -2, "__gc");
+		lua_setmetatable(L, -2);
+
+		// Push the iterator function
+		lua_pushcclosure(L, [] (lua_State *L) -> int {
+			auto it = toType<Iterator<IteratorType> *>(L, lua_upvalueindex(1));
+
+			if (it->current == it->end)
+				return 0;
+
+				Converter::push(L, *(it->current++));
+
+			return 1;
+		}, 1);
+
+		LUAE_STACK_CHECKEND(L, -1);
+		
+		return 1;
+	}
+
+	/**
 	 * Convert a new placement made object, without testing if its a real
 	 * object.
 	 *
@@ -635,6 +737,30 @@
 		
 		return *static_cast<Ptr<T> *>(lua_touserdata(L, index));
 	}
+
+	/**
+	 * Delete the shared pointer at the given index. This function does
+	 * not check if the type is valid for performance reason. And because
+	 * it's usually called in __gc, there is no reason to check.
+	 *
+	 * Also return 0 the __gc method can directly call
+	 * return LuaeClass::deleteShared(...)
+	 *
+	 * @param L the Lua state
+	 * @param index the index
+	 * @return 0 for convenience
+	 */
+	template <typename T>
+	static int deleteShared(lua_State *L, int index)
+	{
+		LUAE_STACK_CHECKBEGIN(L);
+
+		Luae::toType<Ptr<T> *>(L, index)->~shared_ptr<T>();
+
+		LUAE_STACK_CHECKEQUALS(L);
+
+		return 0;
+	}
 };
 
 /* }}} */
@@ -758,8 +884,12 @@
 			      const std::string &meta,
 			      LuaeClass::Ptr<T> o)
 	{
+		LUAE_STACK_CHECKBEGIN(L);
+
 		LuaeClass::pushShared(L, o, meta);
 		LuaeTable::setfield(L, (index < 0) ? --index : index, name);
+
+		LUAE_STACK_CHECKEQUALS(L);
 	}
 
 	/**
@@ -773,6 +903,8 @@
 	template <typename T>
 	static T require(lua_State *L, int idx, const std::string &name)
 	{
+		LUAE_STACK_CHECKBEGIN(L);
+
 		lua_getfield(L, idx, name.c_str());
 
 		if (lua_type(L, -1) == LUA_TNIL)
@@ -780,8 +912,11 @@
 			// NOT REACHED
 
 		lua_pop(L, 1);
+		auto v = get<T>(L, idx, name);
 
-		return get<T>(L, idx, name);
+		LUAE_STACK_CHECKEQUALS(L);
+
+		return v;
 	}
 
 	/**