changeset 211:04aa866535fb

Merge
author David Demelier <markand@malikania.fr>
date Sat, 22 Mar 2014 22:02:24 +0100
parents e8ab4c7b8a25 (current diff) 3b0e276f0866 (diff)
children 35e34b0b80d4
files
diffstat 3 files changed, 147 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/C++/Luae.h	Sat Mar 22 22:01:58 2014 +0100
+++ b/C++/Luae.h	Sat Mar 22 22:02:24 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;
 	}
 
 	/**
--- a/C++/Parser.cpp	Sat Mar 22 22:01:58 2014 +0100
+++ b/C++/Parser.cpp	Sat Mar 22 22:02:24 2014 +0100
@@ -32,9 +32,9 @@
 {
 }
 
-Section::Section(const std::string &name)
+Section::Section(const std::string &name, bool allowed)
 	: m_name(name)
-	, m_allowed(true)
+	, m_allowed(allowed)
 {
 
 }
@@ -232,11 +232,7 @@
 	, m_tuning(tuning)
 	, m_commentChar(commentToken)
 {
-	Section s("");
-
-	s.m_allowed = (tuning & DisableRootSection) ? false : true;
-
-	m_sections.push_back(s);
+	m_sections.push_back(Section("", (tuning & DisableRootSection) ? false : true));
 	open();
 }
 
--- a/C++/Parser.h	Sat Mar 22 22:01:58 2014 +0100
+++ b/C++/Parser.h	Sat Mar 22 22:02:24 2014 +0100
@@ -37,9 +37,14 @@
  */
 class Section {
 public:
+	friend class Parser;
+
 	using Map = std::unordered_map<std::string, std::string>;
 
-	friend class Parser;
+	template <typename T>
+	struct Converter {
+		static const bool supported = false;
+	};
 
 private:
 	std::string	m_name;		/*! name of section */
@@ -47,11 +52,6 @@
 	bool		m_allowed;	/*! is authorized to push */
 
 public:
-	template <typename T>
-	struct Converter {
-		static const bool supported = false;
-	};
-
 	/**
 	 * Default constructor.
 	 */
@@ -61,8 +61,9 @@
 	 * Named constructor.
 	 *
 	 * @param name the section name
+	 * @param allowed is allowed to push
 	 */
-	Section(const std::string &name);
+	Section(const std::string &name, bool allowed = true);
 
 	/**
 	 * Tells if that section has the specified option name.