From 7d2074bc046c38cf6947da77e1b9610c1809217d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Mon, 2 May 2011 22:05:08 +0200
Subject: Add a generic erase() algorithm.


diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index eaf3316..d8c9e31 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -11,6 +11,7 @@
 
 #include <Swift/Controllers/Intl.h>
 #include <Swiften/Base/format.h>
+#include <Swiften/Base/Algorithm.h>
 #include "Swiften/Avatars/AvatarManager.h"
 #include "Swiften/Chat/ChatStateNotifier.h"
 #include "Swiften/Chat/ChatStateTracker.h"
@@ -134,13 +135,7 @@ void ChatController::postSendMessage(const std::string& body, boost::shared_ptr<
 	boost::shared_ptr<Replace> replace = sentStanza->getPayload<Replace>();
 	if (replace) {
 		chatWindow_->replaceMessage(body, myLastMessageUIID_, boost::posix_time::microsec_clock::universal_time());
-		for (std::map<boost::shared_ptr<Stanza>, std::string>::iterator it = unackedStanzas_.begin(); it != unackedStanzas_.end(); ) {
-			if ((*it).second == myLastMessageUIID_) {
-				unackedStanzas_.erase(it++);
-			} else {
-				++it;
-			}
-		}
+		eraseIf(unackedStanzas_, PairSecondEquals<boost::shared_ptr<Stanza>, std::string>(myLastMessageUIID_));
 	} else {
 		myLastMessageUIID_ = addMessage(body, QT_TRANSLATE_NOOP("", "me"), true, labelsEnabled_ ? chatWindow_->getSelectedSecurityLabel().getLabel() : boost::shared_ptr<SecurityLabel>(), std::string(avatarManager_->getAvatarPath(selfJID_).string()), boost::posix_time::microsec_clock::universal_time());
 	}
diff --git a/Swiften/Base/Algorithm.h b/Swiften/Base/Algorithm.h
new file mode 100644
index 0000000..f0c6b48
--- /dev/null
+++ b/Swiften/Base/Algorithm.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <vector>
+#include <list>
+#include <map>
+#include <algorithm>
+
+namespace Swift {
+	/*
+	 * Generic erase()
+	 */
+	namespace Detail {
+		struct VectorCategory {};
+		struct ListCategory {};
+		struct MapCategory {};
+
+		template<typename T> 
+		struct ContainerTraits {};
+
+		template<typename A, typename B> 
+		struct ContainerTraits< std::vector<A, B> > {
+			typedef VectorCategory Category;
+		};
+
+		template<>
+		struct ContainerTraits< std::string > {
+			typedef VectorCategory Category;
+		};
+
+		template<typename A, typename B> 
+		struct ContainerTraits< std::list<A, B> > {
+			typedef ListCategory Category;
+		};
+
+		template<typename A, typename B, typename C, typename D> 
+		struct ContainerTraits< std::map<A, B, C, D> > {
+			typedef MapCategory Category;
+		};
+
+		template<typename C, typename V>
+		void eraseImpl(C& c, const V& v, VectorCategory) {
+			c.erase(std::remove(c.begin(), c.end(), v), c.end());
+		}
+
+		template<typename C, typename V>
+		void eraseImpl(C& c, const V& v, ListCategory) {
+			c.remove(v);
+		}
+
+		template<typename C, typename V>
+		void eraseImpl(C& c, const V& v, MapCategory) {
+		  for (typename C::iterator it = c.begin(); it != c.end(); ) {
+				if (it->second == v) {
+					c.erase(it++);
+				}
+				else {
+					++it;
+				}
+			}
+		}
+
+		template<typename C, typename P>
+		void eraseIfImpl(C& c, const P& p, MapCategory) {
+		  for (typename C::iterator it = c.begin(); it != c.end(); ) {
+				if (p(*it)) {
+					c.erase(it++);
+				}
+				else {
+					++it;
+				}
+			}
+		}
+	}
+
+	template<typename C, typename V>
+	void erase(C& container, const V& value) {
+		Detail::eraseImpl(container, value, typename Detail::ContainerTraits<C>::Category());
+	}
+
+	template<typename C, typename P>
+	void eraseIf(C& container, const P& predicate) {
+		Detail::eraseIfImpl(container, predicate, typename Detail::ContainerTraits<C>::Category());
+	}
+
+	/*
+	 * Functors
+	 */
+	template<typename K, typename V>
+	class PairSecondEquals {
+		public:
+			PairSecondEquals(const V& value) : value(value) {
+			}
+
+			bool operator()(const std::pair<K,V>& pair) const {
+				return pair.second == value;
+			}
+
+		private:
+			V value;
+	};
+}
diff --git a/Swiften/Jingle/JingleSessionManager.cpp b/Swiften/Jingle/JingleSessionManager.cpp
index 58e90c8..f9a94f3 100644
--- a/Swiften/Jingle/JingleSessionManager.cpp
+++ b/Swiften/Jingle/JingleSessionManager.cpp
@@ -8,6 +8,7 @@
 #include <Swiften/Jingle/JingleResponder.h>
 #include <Swiften/Jingle/IncomingJingleSessionHandler.h>
 #include <Swiften/Base/foreach.h>
+#include <Swiften/Base/Algorithm.h>
 
 namespace Swift {
 
@@ -29,7 +30,7 @@ void JingleSessionManager::addIncomingSessionHandler(IncomingJingleSessionHandle
 }
 
 void JingleSessionManager::removeIncomingSessionHandler(IncomingJingleSessionHandler* handler) {
-	incomingSessionHandlers.erase(std::remove(incomingSessionHandlers.begin(), incomingSessionHandlers.end(), handler), incomingSessionHandlers.end());
+	erase(incomingSessionHandlers, handler);
 }
 
 void JingleSessionManager::handleIncomingSession(const JID& from, JingleSessionImpl::ref session, const std::vector<JingleContentPayload::ref>& contents) {
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp
index 06f175c..5331964 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp
@@ -15,6 +15,7 @@
 #include <Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h>
 #include <Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h>
 #include <Swiften/Base/foreach.h>
+#include <Swiften/Base/Algorithm.h>
 
 namespace Swift {
 
@@ -59,8 +60,7 @@ void BonjourQuerier::addRunningQuery(boost::shared_ptr<BonjourQuery> query) {
 void BonjourQuerier::removeRunningQuery(boost::shared_ptr<BonjourQuery> query) {
 	{
 		boost::lock_guard<boost::mutex> lock(runningQueriesMutex);
-		runningQueries.erase(std::remove(
-			runningQueries.begin(), runningQueries.end(), query), runningQueries.end());
+		erase(runningQueries, query);
 	}
 }
 
diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp
index ff2b03c..1ddeffa 100644
--- a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp
+++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp
@@ -10,6 +10,7 @@
 #include <iostream>
 
 #include <Swiften/Base/foreach.h>
+#include <Swiften/Base/Algorithm.h>
 #include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDBrowseQuery.h>
 #include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDRegisterQuery.h>
 #include <Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveServiceQuery.h>
@@ -74,8 +75,7 @@ void FakeDNSSDQuerier::addRunningQuery(boost::shared_ptr<FakeDNSSDQuery> query)
 }
 
 void FakeDNSSDQuerier::removeRunningQuery(boost::shared_ptr<FakeDNSSDQuery> query) {
-	runningQueries.erase(std::remove(
-		runningQueries.begin(), runningQueries.end(), query), runningQueries.end());
+	erase(runningQueries, query);
 }
 
 void FakeDNSSDQuerier::addService(const DNSSDServiceID& id) {
diff --git a/Swiften/MUC/MUCRegistry.cpp b/Swiften/MUC/MUCRegistry.cpp
index 6776be9..f4d061e 100644
--- a/Swiften/MUC/MUCRegistry.cpp
+++ b/Swiften/MUC/MUCRegistry.cpp
@@ -6,7 +6,7 @@
 
 #include <Swiften/MUC/MUCRegistry.h>
 
-#include <algorithm>
+#include <Swiften/Base/Algorithm.h>
 
 namespace Swift {
 
@@ -22,7 +22,7 @@ void MUCRegistry::addMUC(const JID& j) {
 }
 
 void MUCRegistry::removeMUC(const JID& j) {
-	mucs.erase(std::remove(mucs.begin(), mucs.end(), j), mucs.end());
+	erase(mucs, j);
 }
 
 
diff --git a/Swiften/QA/DNSSDTest/DNSSDTest.cpp b/Swiften/QA/DNSSDTest/DNSSDTest.cpp
index 65daa6e..2409f66 100644
--- a/Swiften/QA/DNSSDTest/DNSSDTest.cpp
+++ b/Swiften/QA/DNSSDTest/DNSSDTest.cpp
@@ -9,9 +9,8 @@
 #include <cppunit/extensions/TestFactoryRegistry.h>
 #include <boost/bind.hpp>
 
-#include <algorithm>
-
 #include <Swiften/Base/sleep.h>
+#include <Swiften/Base/Algorithm.h>
 #include <Swiften/Base/ByteArray.h>
 #include <Swiften/EventLoop/DummyEventLoop.h>
 #include <Swiften/LinkLocal/LinkLocalServiceInfo.h>
@@ -112,7 +111,7 @@ class DNSSDTest : public CppUnit::TestFixture {
 
 		void handleServiceRemoved(const DNSSDServiceID& id) {
 			CPPUNIT_ASSERT(std::find(toRemove.begin(), toRemove.end(), id) != toRemove.end());
-			toRemove.erase(std::remove(toRemove.begin(), toRemove.end(), id));
+			erase(toRemove, id);
 		}
 
 		void handleRegisterFinished(boost::optional<DNSSDServiceID> id) {
diff --git a/Swiften/Queries/IQRouter.cpp b/Swiften/Queries/IQRouter.cpp
index 4e23389..65f9d7f 100644
--- a/Swiften/Queries/IQRouter.cpp
+++ b/Swiften/Queries/IQRouter.cpp
@@ -6,9 +6,9 @@
 
 #include <Swiften/Queries/IQRouter.h>
 
-#include <algorithm>
 #include <boost/bind.hpp>
 
+#include <Swiften/Base/Algorithm.h>
 #include <Swiften/Base/foreach.h>
 #include <Swiften/Queries/IQHandler.h>
 #include <Swiften/Queries/IQChannel.h>
@@ -54,7 +54,7 @@ void IQRouter::handleIQ(boost::shared_ptr<IQ> iq) {
 
 void IQRouter::processPendingRemoves() {
 	foreach(boost::shared_ptr<IQHandler> handler, queuedRemoves_) {
-		handlers_.erase(std::remove(handlers_.begin(), handlers_.end(), handler), handlers_.end());
+		erase(handlers_, handler);
 	}
 	queuedRemoves_.clear();
 }
@@ -76,7 +76,7 @@ void IQRouter::removeHandler(boost::shared_ptr<IQHandler> handler) {
 		queuedRemoves_.push_back(handler);
 	}
 	else {
-		handlers_.erase(std::remove(handlers_.begin(), handlers_.end(), handler), handlers_.end());
+		erase(handlers_, handler);
 	}
 }
 
diff --git a/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp b/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp
index eae4c02..7a6bb79 100644
--- a/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp
+++ b/Swiften/Serializer/PayloadSerializers/FormSerializer.cpp
@@ -11,6 +11,7 @@
 #include <string>
 
 #include <Swiften/Base/String.h>
+#include <Swiften/Base/Algorithm.h>
 #include <Swiften/Base/foreach.h>
 #include <Swiften/Serializer/XML/XMLTextNode.h>
 #include <Swiften/Serializer/XML/XMLRawTextNode.h>
@@ -154,7 +155,7 @@ boost::shared_ptr<XMLElement> FormSerializer::fieldToXML(boost::shared_ptr<FormF
 
 void FormSerializer::multiLineify(const std::string& text, const std::string& elementName, boost::shared_ptr<XMLElement> element) const {
 	std::string unRdText(text);
-	unRdText.erase(std::remove(unRdText.begin(), unRdText.end(), '\r'), unRdText.end());
+	erase(unRdText, '\r');
 	std::vector<std::string> lines = String::split(unRdText, '\n');
 	foreach (std::string line, lines) {
 		boost::shared_ptr<XMLElement> lineElement(new XMLElement(elementName));
diff --git a/Swiften/Server/ServerStanzaRouter.cpp b/Swiften/Server/ServerStanzaRouter.cpp
index 7cd8ed3..1725359 100644
--- a/Swiften/Server/ServerStanzaRouter.cpp
+++ b/Swiften/Server/ServerStanzaRouter.cpp
@@ -6,6 +6,7 @@
 
 #include <Swiften/Server/ServerStanzaRouter.h>
 #include <Swiften/Server/ServerSession.h>
+#include <Swiften/Base/Algorithm.h>
 
 #include <cassert>
 #include <algorithm>
@@ -67,7 +68,7 @@ void ServerStanzaRouter::addClientSession(ServerSession* clientSession) {
 }
 
 void ServerStanzaRouter::removeClientSession(ServerSession* clientSession) {
-	clientSessions_.erase(std::remove(clientSessions_.begin(), clientSessions_.end(), clientSession), clientSessions_.end());
+	erase(clientSessions_, clientSession);
 }
 
 }
diff --git a/Swiften/StringCodecs/Base64.cpp b/Swiften/StringCodecs/Base64.cpp
index 214a425..a77fc93 100644
--- a/Swiften/StringCodecs/Base64.cpp
+++ b/Swiften/StringCodecs/Base64.cpp
@@ -5,9 +5,11 @@
  */
 
 #include <boost/numeric/conversion/cast.hpp>
+
 #include <algorithm>
 
 #include <Swiften/StringCodecs/Base64.h>
+#include <Swiften/Base/Algorithm.h>
 
 namespace Swift {
 
@@ -48,7 +50,7 @@ std::string Base64::encode(const ByteArray &s) {
 
 ByteArray Base64::decode(const std::string& input) {
 	std::string inputWithoutNewlines(input);
-	inputWithoutNewlines.erase(std::remove(inputWithoutNewlines.begin(), inputWithoutNewlines.end(), '\n'), inputWithoutNewlines.end());
+	erase(inputWithoutNewlines, '\n');
 
 	const std::string& s = inputWithoutNewlines;
 	ByteArray p;
-- 
cgit v0.10.2-6-g49f6