From 12024229138787d7df91cb8101d0986996880e3d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Thu, 3 Mar 2011 22:11:18 +0100
Subject: Some more Sluift tweaks.


diff --git a/3rdParty/Boost/src/boost/cast.hpp b/3rdParty/Boost/src/boost/cast.hpp
new file mode 100644
index 0000000..2615d18
--- /dev/null
+++ b/3rdParty/Boost/src/boost/cast.hpp
@@ -0,0 +1,107 @@
+//  boost cast.hpp header file  ----------------------------------------------//
+
+//  (C) Copyright Kevlin Henney and Dave Abrahams 1999.
+//  Distributed under the Boost
+//  Software License, Version 1.0. (See accompanying file
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org/libs/conversion for Documentation.
+
+//  Revision History
+//  23 JUn 05  numeric_cast removed and redirected to the new verion (Fernando Cacciola)
+//  02 Apr 01  Removed BOOST_NO_LIMITS workarounds and included
+//             <boost/limits.hpp> instead (the workaround did not
+//             actually compile when BOOST_NO_LIMITS was defined in
+//             any case, so we loose nothing). (John Maddock)
+//  21 Jan 01  Undid a bug I introduced yesterday. numeric_cast<> never
+//             worked with stock GCC; trying to get it to do that broke
+//             vc-stlport.
+//  20 Jan 01  Moved BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS to config.hpp.
+//             Removed unused BOOST_EXPLICIT_TARGET macro. Moved
+//             boost::detail::type to boost/type.hpp. Made it compile with
+//             stock gcc again (Dave Abrahams)
+//  29 Nov 00  Remove nested namespace cast, cleanup spacing before Formal
+//             Review (Beman Dawes)
+//  19 Oct 00  Fix numeric_cast for floating-point types (Dave Abrahams)
+//  15 Jul 00  Suppress numeric_cast warnings for GCC, Borland and MSVC
+//             (Dave Abrahams)
+//  30 Jun 00  More MSVC6 wordarounds.  See comments below.  (Dave Abrahams)
+//  28 Jun 00  Removed implicit_cast<>.  See comment below. (Beman Dawes)
+//  27 Jun 00  More MSVC6 workarounds
+//  15 Jun 00  Add workarounds for MSVC6
+//   2 Feb 00  Remove bad_numeric_cast ";" syntax error (Doncho Angelov)
+//  26 Jan 00  Add missing throw() to bad_numeric_cast::what(0 (Adam Levar)
+//  29 Dec 99  Change using declarations so usages in other namespaces work
+//             correctly (Dave Abrahams)
+//  23 Sep 99  Change polymorphic_downcast assert to also detect M.I. errors
+//             as suggested Darin Adler and improved by Valentin Bonnard.
+//   2 Sep 99  Remove controversial asserts, simplify, rename.
+//  30 Aug 99  Move to cast.hpp, replace value_cast with numeric_cast,
+//             place in nested namespace.
+//   3 Aug 99  Initial version
+
+#ifndef BOOST_CAST_HPP
+#define BOOST_CAST_HPP
+
+# include <boost/config.hpp>
+# include <boost/assert.hpp>
+# include <typeinfo>
+# include <boost/type.hpp>
+# include <boost/limits.hpp>
+# include <boost/detail/select_type.hpp>
+
+//  It has been demonstrated numerous times that MSVC 6.0 fails silently at link
+//  time if you use a template function which has template parameters that don't
+//  appear in the function's argument list.
+//
+//  TODO: Add this to config.hpp?
+# if defined(BOOST_MSVC) && BOOST_MSVC < 1300
+#  define BOOST_EXPLICIT_DEFAULT_TARGET , ::boost::type<Target>* = 0
+# else
+#  define BOOST_EXPLICIT_DEFAULT_TARGET
+# endif
+
+namespace boost
+{
+//  See the documentation for descriptions of how to choose between
+//  static_cast<>, dynamic_cast<>, polymorphic_cast<> and polymorphic_downcast<>
+
+//  polymorphic_cast  --------------------------------------------------------//
+
+    //  Runtime checked polymorphic downcasts and crosscasts.
+    //  Suggested in The C++ Programming Language, 3rd Ed, Bjarne Stroustrup,
+    //  section 15.8 exercise 1, page 425.
+
+    template <class Target, class Source>
+    inline Target polymorphic_cast(Source* x BOOST_EXPLICIT_DEFAULT_TARGET)
+    {
+        Target tmp = dynamic_cast<Target>(x);
+        if ( tmp == 0 ) throw std::bad_cast();
+        return tmp;
+    }
+
+//  polymorphic_downcast  ----------------------------------------------------//
+
+    //  BOOST_ASSERT() checked polymorphic downcast.  Crosscasts prohibited.
+
+    //  WARNING: Because this cast uses BOOST_ASSERT(), it violates
+    //  the One Definition Rule if used in multiple translation units
+    //  where BOOST_DISABLE_ASSERTS, BOOST_ENABLE_ASSERT_HANDLER
+    //  NDEBUG are defined inconsistently.
+
+    //  Contributed by Dave Abrahams
+
+    template <class Target, class Source>
+    inline Target polymorphic_downcast(Source* x BOOST_EXPLICIT_DEFAULT_TARGET)
+    {
+        BOOST_ASSERT( dynamic_cast<Target>(x) == x );  // detect logic error
+        return static_cast<Target>(x);
+    }
+
+#  undef BOOST_EXPLICIT_DEFAULT_TARGET
+
+} // namespace boost
+
+# include <boost/numeric/conversion/cast.hpp>
+
+#endif  // BOOST_CAST_HPP
diff --git a/3rdParty/Boost/src/boost/detail/select_type.hpp b/3rdParty/Boost/src/boost/detail/select_type.hpp
new file mode 100644
index 0000000..c13946f
--- /dev/null
+++ b/3rdParty/Boost/src/boost/detail/select_type.hpp
@@ -0,0 +1,36 @@
+// (C) Copyright David Abrahams 2001.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org for most recent version including documentation.
+
+// Revision History
+// 09 Feb 01  Applied John Maddock's Borland patch Moving <true>
+//            specialization to unspecialized template (David Abrahams)
+// 06 Feb 01  Created (David Abrahams)
+
+#ifndef SELECT_TYPE_DWA20010206_HPP
+# define SELECT_TYPE_DWA20010206_HPP
+
+namespace boost { namespace detail {
+
+  // Template class if_true -- select among 2 types based on a bool constant expression
+  // Usage:
+  //   typename if_true<(bool_const_expression)>::template then<true_type, false_type>::type
+
+  // HP aCC cannot deal with missing names for template value parameters
+  template <bool b> struct if_true
+  {
+      template <class T, class F>
+      struct then { typedef T type; };
+  };
+
+  template <>
+  struct if_true<false>
+  {
+      template <class T, class F>
+      struct then { typedef F type; };
+  };
+}}
+#endif // SELECT_TYPE_DWA20010206_HPP
diff --git a/3rdParty/Boost/update.sh b/3rdParty/Boost/update.sh
index 006840b..6344d72 100755
--- a/3rdParty/Boost/update.sh
+++ b/3rdParty/Boost/update.sh
@@ -12,6 +12,7 @@ fi
 ./bcp --boost="$1" \
 	tools/bcp \
 	bind.hpp \
+	cast.hpp \
 	date_time/posix_time/posix_time.hpp \
 	foreach.hpp \
 	filesystem.hpp \
diff --git a/Sluift/.gitignore b/Sluift/.gitignore
index e343aca..35a18c0 100644
--- a/Sluift/.gitignore
+++ b/Sluift/.gitignore
@@ -1,3 +1,4 @@
 lua.c
 sluift_dll.cpp
 sluift
+dll.c
diff --git a/Sluift/Lua/Value.cpp b/Sluift/Lua/Value.cpp
index b612bd9..8dd8fcc 100644
--- a/Sluift/Lua/Value.cpp
+++ b/Sluift/Lua/Value.cpp
@@ -36,11 +36,10 @@ namespace {
 			lua_pushstring(state, s.c_str());
 		}
 
-		void operator()(const std::vector<Value>& list) const {
-			lua_newtable(state);
-			int i = 0;
-			foreach(const Value& value, list) {
-				boost::apply_visitor(PushVisitor(state), value);
+		void operator()(const std::vector<Value>& values) const {
+			lua_createtable(state, values.size(), 0);
+			for(size_t i = 0; i < values.size(); ++i) {
+				boost::apply_visitor(PushVisitor(state), values[i]);
 				lua_rawseti(state, -2, i + 1);
 			}
 		}
diff --git a/Sluift/SConscript b/Sluift/SConscript
index ec9f690..6f38693 100644
--- a/Sluift/SConscript
+++ b/Sluift/SConscript
@@ -1,3 +1,5 @@
+import Version
+
 Import(["env", "conf_env"])
 
 if env["SCONS_STAGE"] == "build" :
@@ -21,17 +23,22 @@ if env["SCONS_STAGE"] == "build" :
 	elif myenv["PLATFORM"] == "darwin" :
 		myenv["SHLIBSUFFIX"] = ".so"
 
+	myenv["SLUIFT_VERSION"] = Version.getBuildVersion("sluift")
 	def patchLua(env, target, source) :
 		f = open(source[0].abspath, "r")
 		contents = f.read()
 		f.close()
-		contents = contents.replace("LUA_RELEASE", "\"== Sluift XMPP Console ==\"")
+		if env["PLATFORM"] == "windows" :
+			key = "Z"
+		else :
+			key = "D"
+		contents = contents.replace("LUA_RELEASE", "\"== Sluift XMPP Console (%(version)s) == \\nPress Ctrl-%(key)s to exit\"" % {"version": source[1].get_contents(), "key" : key})
 		contents = contents.replace("LUA_COPYRIGHT", "")
 		f = open(target[0].abspath, "w")
 		f.write(contents)
 		f.close()
 
-	myenv.Command("lua.c", ["#/3rdParty/Lua/src/lua.c"], env.Action(patchLua, cmdstr = "$GENCOMSTR"))
+	myenv.Command("lua.c", ["#/3rdParty/Lua/src/lua.c", myenv.Value(myenv["SLUIFT_VERSION"])], env.Action(patchLua, cmdstr = "$GENCOMSTR"))
 	if myenv.get("HAVE_READLINE", False) :
 		myenv.Append(CPPDEFINES = ["LUA_USE_READLINE"])
 		myenv.MergeFlags(myenv["READLINE_FLAGS"])
@@ -40,4 +47,5 @@ if env["SCONS_STAGE"] == "build" :
 			"linit.c",
 		])
 
-	myenv.SharedLibrary("sluift", []);
+	myenv.WriteVal("dll.c", myenv.Value(""))
+	myenv.SharedLibrary("sluift", ["dll.c"])
diff --git a/Sluift/sluift.cpp b/Sluift/sluift.cpp
index 5d24276..324c94e 100644
--- a/Sluift/sluift.cpp
+++ b/Sluift/sluift.cpp
@@ -320,35 +320,45 @@ static int sluift_client_send_presence(lua_State *L) {
 }
 
 static int sluift_client_get(lua_State *L) {
-	SluiftClient* client = getClient(L);
-	JID jid;
-	std::string data;
-	if (lua_type(L, 3) != LUA_TNONE) {
-		jid = JID(std::string(luaL_checkstring(L, 2)));
-		data = std::string(luaL_checkstring(L, 3));
+	try {
+		SluiftClient* client = getClient(L);
+		JID jid;
+		std::string data;
+		if (lua_type(L, 3) != LUA_TNONE) {
+			jid = JID(std::string(luaL_checkstring(L, 2)));
+			data = std::string(luaL_checkstring(L, 3));
+		}
+		else {
+			data = std::string(luaL_checkstring(L, 2));
+		}
+		std::string result = client->sendQuery(jid, IQ::Get, data);
+		lua_pushstring(L, result.c_str());
+		return 1;
 	}
-	else {
-		data = std::string(luaL_checkstring(L, 2));
+	catch (const SluiftException& e) {
+		return luaL_error(L, e.getReason().c_str());
 	}
-	std::string result = client->sendQuery(jid, IQ::Get, data);
-	lua_pushstring(L, result.c_str());
-	return 1;
 }
 
 static int sluift_client_set(lua_State *L) {
-	SluiftClient* client = getClient(L);
-	JID jid;
-	std::string data;
-	if (lua_type(L, 3) != LUA_TNONE) {
-		jid = JID(std::string(luaL_checkstring(L, 2)));
-		data = std::string(luaL_checkstring(L, 3));
+	try {
+		SluiftClient* client = getClient(L);
+		JID jid;
+		std::string data;
+		if (lua_type(L, 3) != LUA_TNONE) {
+			jid = JID(std::string(luaL_checkstring(L, 2)));
+			data = std::string(luaL_checkstring(L, 3));
+		}
+		else {
+			data = std::string(luaL_checkstring(L, 2));
+		}
+		std::string result = client->sendQuery(jid, IQ::Set, data);
+		lua_pushstring(L, result.c_str());
+		return 1;
 	}
-	else {
-		data = std::string(luaL_checkstring(L, 2));
+	catch (const SluiftException& e) {
+		return luaL_error(L, e.getReason().c_str());
 	}
-	std::string result = client->sendQuery(jid, IQ::Set, data);
-	lua_pushstring(L, result.c_str());
-	return 1;
 }
 
 static int sluift_client_send(lua_State *L) {
@@ -452,12 +462,41 @@ static int sluift_client_add_contact(lua_State* L) {
 	try {
 		eventLoop.runOnce();
 		SluiftClient* client = getClient(L);
-		JID jid(luaL_checkstring(L, 2));
+		RosterItemPayload item;
+		if (lua_type(L, 2) == LUA_TTABLE) {
+			lua_getfield(L, 2, "jid");
+			const char* rawJID = lua_tostring(L, -1);
+			if (rawJID) {
+				item.setJID(std::string(rawJID));
+			}
+			lua_getfield(L, 2, "name");
+			const char* rawName = lua_tostring(L, -1);
+			if (rawName) {
+				item.setName(rawName);
+			}
+			lua_getfield(L, 2, "groups");
+			if (!lua_isnil(L, -1)) {
+				if (lua_type(L, -1) == LUA_TTABLE) {
+					for (size_t i = 1; i <= lua_objlen(L, -1); ++i) {
+						lua_rawgeti(L, -1, i);
+						const char* rawGroup = lua_tostring(L, -1);
+						if (rawGroup) {
+							item.addGroup(rawGroup);
+						}
+						lua_pop(L, 1);
+					}
+				}
+				else {
+					return luaL_error(L, "Groups should be a table");
+				}
+			}
+		}
+		else {
+			item.setJID(luaL_checkstring(L, 2));
+		}
 
 		client->getRoster();
-		if (!client->getClient()->getRoster()->containsJID(jid)) {
-			RosterItemPayload item;
-			item.setJID(jid);
+		if (!client->getClient()->getRoster()->containsJID(item.getJID())) {
 			RosterPayload::ref roster = boost::make_shared<RosterPayload>();
 			roster->addItem(item);
 
@@ -473,7 +512,7 @@ static int sluift_client_add_contact(lua_State* L) {
 				return 1;
 			}
 		}
-		client->getClient()->getSubscriptionManager()->requestSubscription(jid);
+		client->getClient()->getSubscriptionManager()->requestSubscription(item.getJID());
 		lua_pushboolean(L, true);
 		return 1;
 	}
diff --git a/Swiften/Parser/PayloadParsers/CommandParser.cpp b/Swiften/Parser/PayloadParsers/CommandParser.cpp
index 9422170..3ebab39 100644
--- a/Swiften/Parser/PayloadParsers/CommandParser.cpp
+++ b/Swiften/Parser/PayloadParsers/CommandParser.cpp
@@ -5,6 +5,9 @@
  */
 
 #include "Swiften/Parser/PayloadParsers/CommandParser.h"
+
+#include <boost/cast.hpp>
+
 #include "Swiften/Parser/PayloadParsers/FormParserFactory.h"
 #include "Swiften/Parser/PayloadParsers/FormParser.h"
 
@@ -43,7 +46,7 @@ void CommandParser::handleStartElement(const std::string& element, const std::st
 	else if (level_ == FormOrNoteOrActionsLevel) {
 		assert(!formParser_);
 		if (formParserFactory_->canParse(element, ns, attributes)) {
-			formParser_ = dynamic_cast<FormParser*>(formParserFactory_->createPayloadParser());
+			formParser_ = boost::polymorphic_downcast<FormParser*>(formParserFactory_->createPayloadParser());
 			assert(formParser_);
 		}
 		else if (element == "note") {
diff --git a/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.cpp b/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.cpp
index 2ec1916..56995d8 100644
--- a/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.cpp
+++ b/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.cpp
@@ -5,6 +5,9 @@
  */
 
 #include "Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h"
+
+#include <boost/cast.hpp>
+
 #include "Swiften/Parser/PayloadParsers/FormParserFactory.h"
 #include "Swiften/Parser/PayloadParsers/FormParser.h"
 
@@ -24,7 +27,7 @@ void InBandRegistrationPayloadParser::handleStartElement(const std::string& elem
 	else if (level == PayloadLevel) {
 		if (element == "x" && ns == "jabber:x:data") {
 			assert(!formParser);
-			formParser = dynamic_cast<FormParser*>(formParserFactory->createPayloadParser());
+			formParser = boost::polymorphic_downcast<FormParser*>(formParserFactory->createPayloadParser());
 		}
 		else {
 			currentText.clear();
diff --git a/Swiften/Parser/PayloadParsers/SearchPayloadParser.cpp b/Swiften/Parser/PayloadParsers/SearchPayloadParser.cpp
index 7c8752c..9daf842 100644
--- a/Swiften/Parser/PayloadParsers/SearchPayloadParser.cpp
+++ b/Swiften/Parser/PayloadParsers/SearchPayloadParser.cpp
@@ -5,6 +5,9 @@
  */
 
 #include "Swiften/Parser/PayloadParsers/SearchPayloadParser.h"
+
+#include <boost/cast.hpp>
+
 #include "Swiften/Parser/PayloadParsers/FormParserFactory.h"
 #include "Swiften/Parser/PayloadParsers/FormParser.h"
 
@@ -24,7 +27,7 @@ void SearchPayloadParser::handleStartElement(const std::string& element, const s
 	else if (level == PayloadLevel) {
 		if (element == "x" && ns == "jabber:x:data") {
 			assert(!formParser);
-			formParser = dynamic_cast<FormParser*>(formParserFactory->createPayloadParser());
+			formParser = boost::polymorphic_downcast<FormParser*>(formParserFactory->createPayloadParser());
 		}
 		else if (element == "item") {
 			assert(!currentItem);
diff --git a/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp b/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp
index 28c5cf5..1cf7fcf 100644
--- a/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp
+++ b/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp
@@ -7,6 +7,7 @@
 #include "Swiften/Parser/PayloadParsers/StreamInitiationParser.h"
 
 #include <boost/lexical_cast.hpp>
+#include <boost/cast.hpp>
 
 #include "Swiften/Parser/PayloadParsers/FormParserFactory.h"
 #include "Swiften/Parser/PayloadParsers/FormParser.h"
@@ -54,7 +55,7 @@ void StreamInitiationParser::handleStartElement(const std::string& element, cons
 		}
 		else if (inFeature && formParserFactory->canParse(element, ns, attributes)) {
 			assert(!formParser);
-			formParser = dynamic_cast<FormParser*>(formParserFactory->createPayloadParser());
+			formParser = boost::polymorphic_downcast<FormParser*>(formParserFactory->createPayloadParser());
 		}
 	}
 
-- 
cgit v0.10.2-6-g49f6