changeset 228:927c4f3b8a88

Add Luae::optional to templatize luaL_opt*
author David Demelier <markand@malikania.fr>
date Mon, 09 Jun 2014 13:05:33 +0200
parents 4c9b2a3f2396
children 96ff112d05cf 5e1001649d07
files C++/Luae.h C++/Tests/Luae/TestLuae.cpp C++/Tests/Luae/TestLuae.h
diffstat 3 files changed, 248 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/C++/Luae.h	Thu May 29 10:58:32 2014 +0200
+++ b/C++/Luae.h	Mon Jun 09 13:05:33 2014 +0200
@@ -132,6 +132,11 @@
 	 *
 	 * 		return get(L, index);
 	 * 	}
+	 *
+	 *	static Point optional(lua_State *L, int index, const Point &def)
+	 *	{
+	 *		// Do your check or return def
+	 *	}
 	 * };
 	 *
 	 * int l_push(lua_State *L)
@@ -166,6 +171,7 @@
 		static const bool	canGet = true;
 		static const bool	canPush = true;
 		static const bool	canCheck = true;
+		static const bool	canOptional = true;
 		static const bool	isCustom = true;
 		static const bool	isUserdata = false;
 	};
@@ -191,9 +197,7 @@
 	};
 	
 	template <typename T>
-	struct IsSharedUserdata : std::false_type 
-	{
-	};
+	struct IsSharedUserdata : std::false_type { };
 
 	template <typename T>
 	struct IsSharedUserdata<std::shared_ptr<T>> {
@@ -1060,6 +1064,45 @@
 	}
 
 	/**
+	 * Get an optional custom type. Returns the value or the
+	 * def argument.
+	 *
+	 * @param L the Lua state
+	 * @param index the index
+	 * @param def the default value
+	 * @return the value or def
+	 */
+	template <typename T>
+	static EnableIf<IsCustom<T>::value, T>
+	optional(lua_State *L, int index, const T &def)
+	{
+		static_assert(TypeInfo<T>::canOptional, "type not supported");
+
+		return TypeInfo<T>::optional(L, index, def);
+	}
+	
+	/**
+	 * Get an optional userdata, returns the userdata pointer
+	 * or a new created one.
+	 *
+	 * @param L the Lua state
+	 * @param index the index
+	 * @param def the default value
+	 * @return the value or def
+	 */
+	template <typename T>
+	static EnableIf<IsUserdata<T>::value, T *>
+	optional(lua_State *L, int index, const T &def)
+	{
+		auto ptr = luaL_testudata(L, index, TypeInfo<T>::name);
+
+		if (!ptr)
+			return new (L, TypeInfo<T>::name) T(def);
+
+		return ptr;
+	}
+
+	/**
 	 * Get a custom type with check.
 	 *
 	 * @param L the Lua state
@@ -1190,6 +1233,22 @@
 	{
 		return lua_toboolean(L, index);
 	}
+
+	/**
+	 * Get an optional boolean.
+	 *
+	 * @param L the Lua state
+	 * @param index the index
+	 * @param def the default value if not boolean
+	 * @return the value or def
+	 */
+	static bool optional(lua_State *L, int index, const bool &def)
+	{
+		if (lua_type(L, index) == LUA_TBOOLEAN)
+			return lua_toboolean(L, index);
+
+		return def;
+	}
 };
 
 /**
@@ -1230,6 +1289,19 @@
 	{
 		return luaL_checkinteger(L, index);
 	}
+
+	/**
+	 * Get an optional integer.
+	 *
+	 * @param L the Lua state
+	 * @param index the index
+	 * @param def the default value
+	 * @return the value or def
+	 */
+	static int optional(lua_State *L, int index, const int &def)
+	{
+		return luaL_optint(L, index, def);
+	}
 };
 
 /**
@@ -1270,6 +1342,19 @@
 	{
 		return luaL_checkinteger(L, index);
 	}
+
+	/**
+	 * Get an optional long.
+	 *
+	 * @param L the Lua state
+	 * @param index the index
+	 * @param def the default value
+	 * @return the value or def
+	 */
+	static long optional(lua_State *L, int index, const long &def)
+	{
+		return luaL_optlong(L, index, def);
+	}
 };
 
 /**
@@ -1310,6 +1395,19 @@
 	{
 		return luaL_checknumber(L, index);
 	}
+
+	/**
+	 * Get an optional double.
+	 *
+	 * @param L the Lua state
+	 * @param index the index
+	 * @param def the default value
+	 * @return the value or def
+	 */
+	static double optional(lua_State *L, int index, const double &def)
+	{
+		return luaL_optnumber(L, index, def);
+	}
 };
 
 /**
@@ -1333,11 +1431,17 @@
 	 *
 	 * @param L the Lua state
 	 * @param index the index
-	 * @return a boolean
+	 * @return the string or ""
 	 */
 	static std::string get(lua_State *L, int index)
 	{
-		return lua_tostring(L, index);
+		size_t length;
+		const char *str = lua_tolstring(L, index, &length);
+
+		if (!str)
+			return "";
+
+		return std::string(str, length);
 	}
 
 	/**
@@ -1345,10 +1449,30 @@
 	 *
 	 * @param L the Lua state
 	 * @param index the index
+	 * @return the string
 	 */
 	static std::string check(lua_State *L, int index)
 	{
-		return luaL_checkstring(L, index);
+		size_t length;
+		const char *str = luaL_tolstring(L, index, &length);
+
+		return std::string(str, length);
+	}
+
+	/**
+	 * Get an optional string.
+	 *
+	 * @param L the Lua state
+	 * @param index the index
+	 * @param def the default value
+	 * @return the value or def
+	 */
+	static std::string optional(lua_State *L, int index, const std::string &def)
+	{
+		size_t length;
+		const char *str = luaL_optlstring(L, index, def.c_str(), &length);
+
+		return std::string(str, length);
 	}
 };
 
@@ -1416,6 +1540,23 @@
 
 		return get(L, index);
 	}
+
+	/**
+	 * Get an optional std::u32string.
+	 *
+	 * @param L the Lua state
+	 * @param index the index
+	 * @param def the default value
+	 * @return the value or def
+	 */
+	static std::u32string optional(lua_State *L, int index, const std::u32string &def)
+	{
+		if (lua_type(L, index) != LUA_TNUMBER &&
+		    lua_type(L, index) != LUA_TTABLE)
+			return def;
+
+		return get(L, index);
+	}
 };
 
 /**
@@ -1456,6 +1597,19 @@
 	{
 		return luaL_checkstring(L, index);
 	}
+
+	/**
+	 * Get an optional C string.
+	 *
+	 * @param L the Lua state
+	 * @param index the index
+	 * @param def the default value
+	 * @return the value or def
+	 */
+	static const char *optional(lua_State *L, int index, const char *& def)
+	{
+		return luaL_optstring(L, index, def);
+	}
 };
 
 /**
--- a/C++/Tests/Luae/TestLuae.cpp	Thu May 29 10:58:32 2014 +0200
+++ b/C++/Tests/Luae/TestLuae.cpp	Mon Jun 09 13:05:33 2014 +0200
@@ -408,6 +408,80 @@
 	}
 }
 
+void TestLuae::optionalbool()
+{
+	LuaeState L;
+	Luae::openlibs(L);
+
+	Luae::push(L, nullptr);
+	CPPUNIT_ASSERT_MESSAGE("false expected", Luae::optional<bool>(L, -1, false) == false);
+
+	Luae::push(L, true);
+	CPPUNIT_ASSERT_MESSAGE("true expected", Luae::optional<bool>(L, -1, false) == true);
+}
+
+void TestLuae::optionalint()
+{
+	LuaeState L;
+	Luae::openlibs(L);
+
+	Luae::push(L, nullptr);
+	CPPUNIT_ASSERT_MESSAGE("123 expected", Luae::optional<int>(L, -1, 123) == 123);
+
+	Luae::push(L, 456);
+	CPPUNIT_ASSERT_MESSAGE("456 expected", Luae::optional<int>(L, -1, 999) == 456);
+}
+
+void TestLuae::optionallong()
+{
+	LuaeState L;
+	Luae::openlibs(L);
+
+	Luae::push(L, nullptr);
+	CPPUNIT_ASSERT_MESSAGE("123456789 expected", Luae::optional<long>(L, -1, 123456789) == 123456789);
+
+	Luae::push(L, 789);
+	CPPUNIT_ASSERT_MESSAGE("789 expected", Luae::optional<long>(L, -1, 888) == 789);
+}
+
+void TestLuae::optionaldouble()
+{
+	LuaeState L;
+	Luae::openlibs(L);
+
+	Luae::push(L, nullptr);
+	CPPUNIT_ASSERT_MESSAGE("123.321 expected", Luae::optional<double>(L, -1, 123.321) == 123.321);
+
+	Luae::push(L, 99.44);
+	CPPUNIT_ASSERT_MESSAGE("99.44 expected", Luae::optional<double>(L, -1, 321.321) == 99.44);
+}
+
+void TestLuae::optionalstring()
+{
+	LuaeState L;
+	Luae::openlibs(L);
+
+	Luae::push(L, nullptr);
+	CPPUNIT_ASSERT_MESSAGE("abc expected", Luae::optional<std::string>(L, -1, "abc") == std::string("abc"));
+
+	Luae::push(L, "xyz");
+	CPPUNIT_ASSERT_MESSAGE("xyz expected", Luae::optional<std::string>(L, -1, "qwerty") == std::string("xyz"));
+}
+
+void TestLuae::optionalustring()
+{
+	LuaeState L;
+	Luae::openlibs(L);
+
+	std::u32string expected { 'a', 'b', 'c' };
+	Luae::push(L, nullptr);
+	CPPUNIT_ASSERT_MESSAGE("abc expected", Luae::optional<std::u32string>(L, -1, expected) == expected);
+
+	std::u32string notthatone { 'x', 'y' };
+	Luae::push(L, expected);
+	CPPUNIT_ASSERT_MESSAGE("abc expected", Luae::optional<std::u32string>(L, -1, notthatone) == expected);
+}
+
 int main()
 {
 	CppUnit::TextTestRunner runnerText;
@@ -415,4 +489,4 @@
 	runnerText.addTest(TestLuae::suite());
 
 	return runnerText.run("", false) == 1 ? 0 : 1;
-}
\ No newline at end of file
+}
--- a/C++/Tests/Luae/TestLuae.h	Thu May 29 10:58:32 2014 +0200
+++ b/C++/Tests/Luae/TestLuae.h	Mon Jun 09 13:05:33 2014 +0200
@@ -38,6 +38,12 @@
 	CPPUNIT_TEST(testdouble);
 	CPPUNIT_TEST(teststring);
 	CPPUNIT_TEST(testustring);
+	CPPUNIT_TEST(optionalbool);
+	CPPUNIT_TEST(optionalint);
+	CPPUNIT_TEST(optionallong);
+	CPPUNIT_TEST(optionaldouble);
+	CPPUNIT_TEST(optionalstring);
+	CPPUNIT_TEST(optionalustring);
 	CPPUNIT_TEST_SUITE_END();
 
 public:
@@ -54,6 +60,12 @@
 	void testdouble();
 	void teststring();
 	void testustring();
+	void optionalbool();
+	void optionalint();
+	void optionallong();
+	void optionaldouble();
+	void optionalstring();
+	void optionalustring();
 };
 
-#endif // !_TEST_LUAE_H_
\ No newline at end of file
+#endif // !_TEST_LUAE_H_