diff options
| author | Remko Tronçon <git@el-tramo.be> | 2011-04-11 20:15:20 (GMT) | 
|---|---|---|
| committer | Remko Tronçon <git@el-tramo.be> | 2011-04-18 19:11:42 (GMT) | 
| commit | 92af1a97f318f7f623df3183e90e7e828fa2eeb9 (patch) | |
| tree | 886d66feead5ca3c1d04152b570f7712be4a86c0 | |
| parent | eda3475756f88098de69d5bea05b328b53d7ec04 (diff) | |
| download | swift-contrib-92af1a97f318f7f623df3183e90e7e828fa2eeb9.zip swift-contrib-92af1a97f318f7f623df3183e90e7e828fa2eeb9.tar.bz2 | |
Make parser infrastructure parser aware.
Resolves: #492
| -rw-r--r-- | Swiften/Parser/Attribute.h | 33 | ||||
| -rw-r--r-- | Swiften/Parser/AttributeMap.cpp | 62 | ||||
| -rw-r--r-- | Swiften/Parser/AttributeMap.h | 62 | ||||
| -rw-r--r-- | Swiften/Parser/ExpatParser.cpp | 2 | ||||
| -rw-r--r-- | Swiften/Parser/IQParser.cpp | 17 | ||||
| -rw-r--r-- | Swiften/Parser/IQParser.h | 5 | ||||
| -rw-r--r-- | Swiften/Parser/LibXMLParser.cpp | 12 | ||||
| -rw-r--r-- | Swiften/Parser/MessageParser.cpp | 16 | ||||
| -rw-r--r-- | Swiften/Parser/PayloadParsers/DiscoInfoParser.cpp | 2 | ||||
| -rw-r--r-- | Swiften/Parser/PayloadParsers/RosterParser.cpp | 9 | ||||
| -rw-r--r-- | Swiften/Parser/PresenceParser.cpp | 21 | ||||
| -rw-r--r-- | Swiften/Parser/SConscript | 1 | ||||
| -rw-r--r-- | Swiften/Parser/SerializingParser.cpp | 6 | ||||
| -rw-r--r-- | Swiften/Parser/StanzaParser.cpp | 19 | ||||
| -rw-r--r-- | Swiften/Parser/UnitTest/AttributeMapTest.cpp | 20 | ||||
| -rw-r--r-- | Swiften/Parser/UnitTest/StanzaParserTest.cpp | 10 | ||||
| -rw-r--r-- | Swiften/Parser/UnitTest/XMLParserTest.cpp | 32 | 
17 files changed, 240 insertions, 89 deletions
| diff --git a/Swiften/Parser/Attribute.h b/Swiften/Parser/Attribute.h new file mode 100644 index 0000000..f1f9a83 --- /dev/null +++ b/Swiften/Parser/Attribute.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <string> + +namespace Swift { +	class Attribute { +		public: +			Attribute(const std::string& name, const std::string& ns) : name(name), ns(ns) { +			} + +			const std::string& getName() const { +				return name; +			} + +			const std::string& getNamespace() const { +				return ns; +			} + +			bool operator==(const Attribute& o) const { +				return o.name == name && o.ns == ns; +			} + +		private: +			std::string name; +			std::string ns; +	}; +} diff --git a/Swiften/Parser/AttributeMap.cpp b/Swiften/Parser/AttributeMap.cpp new file mode 100644 index 0000000..1aeaf99 --- /dev/null +++ b/Swiften/Parser/AttributeMap.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swiften/Parser/AttributeMap.h> + +#include <algorithm> +#include <boost/optional.hpp> + +using namespace Swift; + +namespace { +	struct AttributeIs { +		AttributeIs(const Attribute& attribute) : attribute(attribute) { +		} + +		bool operator()(const AttributeMap::Entry& o) const { +			return o.getAttribute() == attribute; +		} + +		Attribute attribute; +	}; +} + +AttributeMap::AttributeMap() { +} + +std::string AttributeMap::getAttribute(const std::string& attribute, const std::string& ns) const { +	AttributeValueMap::const_iterator i = std::find_if(attributes.begin(), attributes.end(), AttributeIs(Attribute(attribute, ns))); +	if (i == attributes.end()) { +		return ""; +	} +	else { +		return i->getValue(); +	} +} + +bool AttributeMap::getBoolAttribute(const std::string& attribute, bool defaultValue) const { +	AttributeValueMap::const_iterator i = std::find_if(attributes.begin(), attributes.end(), AttributeIs(Attribute(attribute, ""))); +	if (i == attributes.end()) { +		return defaultValue; +	} +	else { +		return i->getValue() == "true" || i->getValue() == "1"; +	} +} + +boost::optional<std::string> AttributeMap::getAttributeValue(const std::string& attribute) const { +	AttributeValueMap::const_iterator i = std::find_if(attributes.begin(), attributes.end(), AttributeIs(Attribute(attribute, ""))); +	if (i == attributes.end()) { +		return boost::optional<std::string>(); +	} +	else { +		return i->getValue(); +	} +} + +void AttributeMap::addAttribute(const std::string& name, const std::string& ns, const std::string& value) { +	attributes.push_back(Entry(Attribute(name, ns), value)); +} diff --git a/Swiften/Parser/AttributeMap.h b/Swiften/Parser/AttributeMap.h index c8b287b..31df606 100644 --- a/Swiften/Parser/AttributeMap.h +++ b/Swiften/Parser/AttributeMap.h @@ -4,38 +4,50 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#ifndef ATTRIBUTEMAP_H -#define ATTRIBUTEMAP_H +#pragma once +#include <vector> +#include <string>  #include <map> +#include <boost/optional/optional_fwd.hpp> -#include <string> +#include <Swiften/Parser/Attribute.h>  namespace Swift { -	class AttributeMap : public std::map<std::string,std::string> { +	class AttributeMap {  		public: -			AttributeMap() {} - -			std::string getAttribute(const std::string& attribute) const { -				AttributeMap::const_iterator i = find(attribute); -				if (i == end()) { -					return ""; -				} -				else { -					return i->second; -				} -			} +			class Entry { +				public: +					Entry(const Attribute& attribute, const std::string& value) : attribute(attribute), value(value) { +					} + +					const Attribute& getAttribute() const { +						return attribute; +					} + +					const std::string& getValue() const { +						return value; +					} + +				private: +					Attribute attribute; +					std::string value; +			}; -			bool getBoolAttribute(const std::string& attribute, bool defaultValue = false) const { -				AttributeMap::const_iterator i = find(attribute); -				if (i == end()) { -					return defaultValue; -				} -				else { -					return i->second == "true" || i->second == "1"; -				} +			AttributeMap(); + +			std::string getAttribute(const std::string& attribute, const std::string& ns = "") const; +			bool getBoolAttribute(const std::string& attribute, bool defaultValue = false) const; +			boost::optional<std::string> getAttributeValue(const std::string&) const; + +			void addAttribute(const std::string& name, const std::string& ns, const std::string& value); + +			const std::vector<Entry>& getEntries() const { +				return attributes;  			} + +		private: +			typedef std::vector<Entry> AttributeValueMap; +			AttributeValueMap attributes;  	};  } - -#endif diff --git a/Swiften/Parser/ExpatParser.cpp b/Swiften/Parser/ExpatParser.cpp index 88be752..448b199 100644 --- a/Swiften/Parser/ExpatParser.cpp +++ b/Swiften/Parser/ExpatParser.cpp @@ -30,7 +30,7 @@ static void handleStartElement(void* client, const XML_Char* name, const XML_Cha  			nsAttributePair.second = nsAttributePair.first;  			nsAttributePair.first = "";  		} -		attributeValues[nsAttributePair.second] = std::string(*(currentAttribute+1)); +		attributeValues.addAttribute(nsAttributePair.second, nsAttributePair.first, std::string(*(currentAttribute+1)));  		currentAttribute += 2;  	} diff --git a/Swiften/Parser/IQParser.cpp b/Swiften/Parser/IQParser.cpp index e0883f2..62d775f 100644 --- a/Swiften/Parser/IQParser.cpp +++ b/Swiften/Parser/IQParser.cpp @@ -5,8 +5,9 @@   */  #include <iostream> +#include <boost/optional.hpp> -#include "Swiften/Parser/IQParser.h" +#include <Swiften/Parser/IQParser.h>  namespace Swift { @@ -15,22 +16,22 @@ IQParser::IQParser(PayloadParserFactoryCollection* factories) :  }  void IQParser::handleStanzaAttributes(const AttributeMap& attributes) { -	AttributeMap::const_iterator type = attributes.find("type"); -	if (type != attributes.end()) { -		if (type->second == "set") { +	boost::optional<std::string> type = attributes.getAttributeValue("type"); +	if (type) { +		if (*type == "set") {  			getStanzaGeneric()->setType(IQ::Set);  		} -		else if (type->second == "get") { +		else if (*type == "get") {  			getStanzaGeneric()->setType(IQ::Get);  		} -		else if (type->second == "result") { +		else if (*type == "result") {  			getStanzaGeneric()->setType(IQ::Result);  		} -		else if (type->second == "error") { +		else if (*type == "error") {  			getStanzaGeneric()->setType(IQ::Error);  		}  		else { -			std::cerr << "Unknown IQ type: " << type->second << std::endl; +			std::cerr << "Unknown IQ type: " << *type << std::endl;  			getStanzaGeneric()->setType(IQ::Get);  		}  	} diff --git a/Swiften/Parser/IQParser.h b/Swiften/Parser/IQParser.h index e104dc4..35ab132 100644 --- a/Swiften/Parser/IQParser.h +++ b/Swiften/Parser/IQParser.h @@ -4,8 +4,7 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#ifndef SWIFTEN_IQParser_H -#define SWIFTEN_IQParser_H +#pragma once  #include "Swiften/Parser/GenericStanzaParser.h"  #include "Swiften/Elements/IQ.h" @@ -19,5 +18,3 @@ namespace Swift {  			virtual void handleStanzaAttributes(const AttributeMap&);  	};  } - -#endif diff --git a/Swiften/Parser/LibXMLParser.cpp b/Swiften/Parser/LibXMLParser.cpp index 34db4ca..0b15848 100644 --- a/Swiften/Parser/LibXMLParser.cpp +++ b/Swiften/Parser/LibXMLParser.cpp @@ -15,10 +15,18 @@  namespace Swift { -static void handleStartElement(void *client, const xmlChar* name, const xmlChar*, const xmlChar* xmlns, int, const xmlChar**, int nbAttributes, int, const xmlChar ** attributes) { +static void handleStartElement(void *client, const xmlChar* name, const xmlChar*, const xmlChar* xmlns, int, const xmlChar**, int nbAttributes, int nbDefaulted, const xmlChar ** attributes) {  	AttributeMap attributeValues; +	if (nbDefaulted != 0) { +		// Just because i don't understand what this means yet :-) +		std::cerr << "Unexpected nbDefaulted on XML element" << std::endl; +	}  	for (int i = 0; i < nbAttributes*5; i += 5) { -		attributeValues[std::string(reinterpret_cast<const char*>(attributes[i]))] = std::string(reinterpret_cast<const char*>(attributes[i+3]), attributes[i+4]-attributes[i+3]); +		std::string attributeNS = ""; +		if (attributes[i+2]) { +			attributeNS = std::string(reinterpret_cast<const char*>(attributes[i+2])); +		} +		attributeValues.addAttribute(std::string(reinterpret_cast<const char*>(attributes[i])), attributeNS, std::string(reinterpret_cast<const char*>(attributes[i+3]), attributes[i+4]-attributes[i+3]));  	}  	static_cast<XMLParserClient*>(client)->handleStartElement(reinterpret_cast<const char*>(name), (xmlns ? reinterpret_cast<const char*>(xmlns) : std::string()), attributeValues);  } diff --git a/Swiften/Parser/MessageParser.cpp b/Swiften/Parser/MessageParser.cpp index 5f4d59c..7f5e6d4 100644 --- a/Swiften/Parser/MessageParser.cpp +++ b/Swiften/Parser/MessageParser.cpp @@ -4,9 +4,9 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include <iostream> +#include <boost/optional.hpp> -#include "Swiften/Parser/MessageParser.h" +#include <Swiften/Parser/MessageParser.h>  namespace Swift { @@ -16,18 +16,18 @@ MessageParser::MessageParser(PayloadParserFactoryCollection* factories) :  }  void MessageParser::handleStanzaAttributes(const AttributeMap& attributes) { -	AttributeMap::const_iterator type = attributes.find("type"); -	if (type != attributes.end()) { -		if (type->second == "chat") { +	boost::optional<std::string> type = attributes.getAttributeValue("type"); +	if (type) { +		if (*type == "chat") {  			getStanzaGeneric()->setType(Message::Chat);  		} -		else if (type->second == "error") { +		else if (*type == "error") {  			getStanzaGeneric()->setType(Message::Error);  		} -		else if (type->second == "groupchat") { +		else if (*type == "groupchat") {  			getStanzaGeneric()->setType(Message::Groupchat);  		} -		else if (type->second == "headline") { +		else if (*type == "headline") {  			getStanzaGeneric()->setType(Message::Headline);  		}  		else { diff --git a/Swiften/Parser/PayloadParsers/DiscoInfoParser.cpp b/Swiften/Parser/PayloadParsers/DiscoInfoParser.cpp index e1fcb20..2e9e87a 100644 --- a/Swiften/Parser/PayloadParsers/DiscoInfoParser.cpp +++ b/Swiften/Parser/PayloadParsers/DiscoInfoParser.cpp @@ -15,7 +15,7 @@ DiscoInfoParser::DiscoInfoParser() : level_(TopLevel), formParser_(NULL) {  void DiscoInfoParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) {  	if (level_ == PayloadLevel) {  		if (element == "identity") { -			getPayloadInternal()->addIdentity(DiscoInfo::Identity(attributes.getAttribute("name"), attributes.getAttribute("category"), attributes.getAttribute("type"), attributes.getAttribute("lang"))); +			getPayloadInternal()->addIdentity(DiscoInfo::Identity(attributes.getAttribute("name"), attributes.getAttribute("category"), attributes.getAttribute("type"), attributes.getAttribute("lang", "http://www.w3.org/XML/1998/namespace")));  		}  		else if (element == "feature") {  			getPayloadInternal()->addFeature(attributes.getAttribute("var")); diff --git a/Swiften/Parser/PayloadParsers/RosterParser.cpp b/Swiften/Parser/PayloadParsers/RosterParser.cpp index 0da9f48..5fba30b 100644 --- a/Swiften/Parser/PayloadParsers/RosterParser.cpp +++ b/Swiften/Parser/PayloadParsers/RosterParser.cpp @@ -5,6 +5,9 @@   */  #include "Swiften/Parser/PayloadParsers/RosterParser.h" + +#include <boost/optional.hpp> +  #include "Swiften/Parser/SerializingParser.h"  namespace Swift { @@ -14,9 +17,9 @@ RosterParser::RosterParser() : level_(TopLevel), inItem_(false), unknownContentP  void RosterParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) {  	if (level_ == TopLevel) { -		AttributeMap::const_iterator i = attributes.find("ver"); -		if (i != attributes.end()) { -			getPayloadInternal()->setVersion(i->second); +		boost::optional<std::string> ver = attributes.getAttributeValue("ver"); +		if (ver) { +			getPayloadInternal()->setVersion(*ver);  		}  	}  	else if (level_ == PayloadLevel) { diff --git a/Swiften/Parser/PresenceParser.cpp b/Swiften/Parser/PresenceParser.cpp index 845ccf0..867155f 100644 --- a/Swiften/Parser/PresenceParser.cpp +++ b/Swiften/Parser/PresenceParser.cpp @@ -5,6 +5,7 @@   */  #include <iostream> +#include <boost/optional.hpp>  #include "Swiften/Parser/PresenceParser.h" @@ -15,31 +16,31 @@ PresenceParser::PresenceParser(PayloadParserFactoryCollection* factories) :  }  void PresenceParser::handleStanzaAttributes(const AttributeMap& attributes) { -	AttributeMap::const_iterator type = attributes.find("type"); -	if (type != attributes.end()) { -		if (type->second == "unavailable") { +	boost::optional<std::string> type = attributes.getAttributeValue("type"); +	if (type) { +		if (*type == "unavailable") {  			getStanzaGeneric()->setType(Presence::Unavailable);  		} -		else if (type->second == "probe") { +		else if (*type == "probe") {  			getStanzaGeneric()->setType(Presence::Probe);  		} -		else if (type->second == "subscribe") { +		else if (*type == "subscribe") {  			getStanzaGeneric()->setType(Presence::Subscribe);  		} -		else if (type->second == "subscribed") { +		else if (*type == "subscribed") {  			getStanzaGeneric()->setType(Presence::Subscribed);  		} -		else if (type->second == "unsubscribe") { +		else if (*type == "unsubscribe") {  			getStanzaGeneric()->setType(Presence::Unsubscribe);  		} -		else if (type->second == "unsubscribed") { +		else if (*type == "unsubscribed") {  			getStanzaGeneric()->setType(Presence::Unsubscribed);  		} -		else if (type->second == "error") { +		else if (*type == "error") {  			getStanzaGeneric()->setType(Presence::Error);  		}  		else { -			std::cerr << "Unknown Presence type: " << type->second << std::endl; +			std::cerr << "Unknown Presence type: " << *type << std::endl;  			getStanzaGeneric()->setType(Presence::Available);  		}  	} diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript index cbb2190..2bd5aff 100644 --- a/Swiften/Parser/SConscript +++ b/Swiften/Parser/SConscript @@ -6,6 +6,7 @@ myenv.MergeFlags(swiften_env.get("LIBXML_FLAGS", ""))  myenv.MergeFlags(swiften_env.get("EXPAT_FLAGS", ""))  sources = [ +		"AttributeMap.cpp",  		"AuthRequestParser.cpp",  		"AuthChallengeParser.cpp",  		"AuthSuccessParser.cpp", diff --git a/Swiften/Parser/SerializingParser.cpp b/Swiften/Parser/SerializingParser.cpp index 43dfc51..03b9575 100644 --- a/Swiften/Parser/SerializingParser.cpp +++ b/Swiften/Parser/SerializingParser.cpp @@ -7,7 +7,6 @@  #include "Swiften/Parser/SerializingParser.h"  #include "Swiften/Serializer/XML/XMLTextNode.h"  #include "Swiften/Base/foreach.h" -#include <iostream>  namespace Swift { @@ -16,8 +15,9 @@ SerializingParser::SerializingParser() {  void SerializingParser::handleStartElement(const std::string& tag, const std::string&  ns, const AttributeMap& attributes) {  	boost::shared_ptr<XMLElement> element(new XMLElement(tag, ns)); -	for (AttributeMap::const_iterator i = attributes.begin(); i != attributes.end(); ++i) { -		element->setAttribute((*i).first, (*i).second); +	// FIXME: Ignoring attribute namespace +	foreach (const AttributeMap::Entry& e, attributes.getEntries()) { +		element->setAttribute(e.getAttribute().getName(), e.getValue());  	}  	if (elementStack_.empty()) { diff --git a/Swiften/Parser/StanzaParser.cpp b/Swiften/Parser/StanzaParser.cpp index 64c4901..051f37e 100644 --- a/Swiften/Parser/StanzaParser.cpp +++ b/Swiften/Parser/StanzaParser.cpp @@ -7,6 +7,7 @@  #include "Swiften/Parser/StanzaParser.h"  #include <iostream> +#include <boost/optional.hpp>  #include <cassert>  #include "Swiften/Parser/PayloadParser.h" @@ -39,17 +40,17 @@ void StanzaParser::handleStartElement(const std::string& element, const std::str  		currentPayloadParser_->handleStartElement(element, ns, attributes);  	}  	else { -		AttributeMap::const_iterator from = attributes.find("from"); -		if (from != attributes.end()) { -			getStanza()->setFrom(JID(from->second)); +		boost::optional<std::string> from = attributes.getAttributeValue("from"); +		if (from) { +			getStanza()->setFrom(JID(*from));  		} -		AttributeMap::const_iterator to = attributes.find("to"); -		if (to != attributes.end()) { -			getStanza()->setTo(JID(to->second)); +		boost::optional<std::string> to = attributes.getAttributeValue("to"); +		if (to) { +			getStanza()->setTo(JID(*to));  		} -		AttributeMap::const_iterator id = attributes.find("id"); -		if (id != attributes.end()) { -			getStanza()->setID(id->second); +		boost::optional<std::string> id = attributes.getAttributeValue("id"); +		if (id) { +			getStanza()->setID(*id);  		}  		handleStanzaAttributes(attributes);  	} diff --git a/Swiften/Parser/UnitTest/AttributeMapTest.cpp b/Swiften/Parser/UnitTest/AttributeMapTest.cpp index fb68f29..8e2ccff 100644 --- a/Swiften/Parser/UnitTest/AttributeMapTest.cpp +++ b/Swiften/Parser/UnitTest/AttributeMapTest.cpp @@ -14,6 +14,7 @@ using namespace Swift;  class AttributeMapTest : public CppUnit::TestFixture  {  		CPPUNIT_TEST_SUITE(AttributeMapTest); +		CPPUNIT_TEST(testGetAttribute_Namespaced);  		CPPUNIT_TEST(testGetBoolAttribute_True);  		CPPUNIT_TEST(testGetBoolAttribute_1);  		CPPUNIT_TEST(testGetBoolAttribute_False); @@ -24,39 +25,46 @@ class AttributeMapTest : public CppUnit::TestFixture  		CPPUNIT_TEST_SUITE_END();  	public: -		AttributeMapTest() {} +		void testGetAttribute_Namespaced() { +			AttributeMap testling; +			testling.addAttribute("lang", "", "nl"); +			testling.addAttribute("lang", "http://www.w3.org/XML/1998/namespace", "en"); +			testling.addAttribute("lang", "", "fr"); + +			CPPUNIT_ASSERT_EQUAL(std::string("en"), testling.getAttribute("lang", "http://www.w3.org/XML/1998/namespace")); +		}  		void testGetBoolAttribute_True() {  			AttributeMap testling; -			testling["foo"] = "true"; +			testling.addAttribute("foo", "", "true");  			CPPUNIT_ASSERT(testling.getBoolAttribute("foo"));  		}  		void testGetBoolAttribute_1() {  			AttributeMap testling; -			testling["foo"] = "1"; +			testling.addAttribute("foo", "", "1");  			CPPUNIT_ASSERT(testling.getBoolAttribute("foo"));  		}  		void testGetBoolAttribute_False() {  			AttributeMap testling; -			testling["foo"] = "false"; +			testling.addAttribute("foo", "", "false");  			CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", true));  		}  		void testGetBoolAttribute_0() {  			AttributeMap testling; -			testling["foo"] = "0"; +			testling.addAttribute("foo", "", "0");  			CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", true));  		}  		void testGetBoolAttribute_Invalid() {  			AttributeMap testling; -			testling["foo"] = "bla"; +			testling.addAttribute("foo", "", "bla");  			CPPUNIT_ASSERT(!testling.getBoolAttribute("foo", true));  		} diff --git a/Swiften/Parser/UnitTest/StanzaParserTest.cpp b/Swiften/Parser/UnitTest/StanzaParserTest.cpp index d57f798..2657750 100644 --- a/Swiften/Parser/UnitTest/StanzaParserTest.cpp +++ b/Swiften/Parser/UnitTest/StanzaParserTest.cpp @@ -40,8 +40,8 @@ class StanzaParserTest : public CppUnit::TestFixture {  			MyStanzaParser testling(factoryCollection_);  			AttributeMap attributes; -			attributes["foo"] = "fum"; -			attributes["bar"] = "baz"; +			attributes.addAttribute("foo", "", "fum"); +			attributes.addAttribute("bar", "", "baz");  			testling.handleStartElement("mystanza", "", attributes);  			testling.handleStartElement("mypayload1", "", attributes);  			testling.handleStartElement("child", "", attributes); @@ -107,9 +107,9 @@ class StanzaParserTest : public CppUnit::TestFixture {  			MyStanzaParser testling(factoryCollection_);  			AttributeMap attributes; -			attributes["to"] = "foo@example.com/blo"; -			attributes["from"] = "bar@example.com/baz"; -			attributes["id"] = "id-123"; +			attributes.addAttribute("to", "", "foo@example.com/blo"); +			attributes.addAttribute("from", "", "bar@example.com/baz"); +			attributes.addAttribute("id", "", "id-123");  			testling.handleStartElement("mystanza", "", attributes);  			testling.handleEndElement("mypayload1", ""); diff --git a/Swiften/Parser/UnitTest/XMLParserTest.cpp b/Swiften/Parser/UnitTest/XMLParserTest.cpp index 426b7a0..27534a1 100644 --- a/Swiften/Parser/UnitTest/XMLParserTest.cpp +++ b/Swiften/Parser/UnitTest/XMLParserTest.cpp @@ -31,6 +31,8 @@ class XMLParserTest : public CppUnit::TestFixture {  		CPPUNIT_TEST(testParse_InErrorState);  		CPPUNIT_TEST(testParse_Incremental);  		CPPUNIT_TEST(testParse_WhitespaceInAttribute); +		CPPUNIT_TEST(testParse_AttributeWithoutNamespace); +		CPPUNIT_TEST(testParse_AttributeWithNamespace);  		CPPUNIT_TEST_SUITE_END();  	public: @@ -46,13 +48,13 @@ class XMLParserTest : public CppUnit::TestFixture {  			CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type);  			CPPUNIT_ASSERT_EQUAL(std::string("iq"), client_.events[0].data); -			CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.size()); -			CPPUNIT_ASSERT_EQUAL(std::string("get"), client_.events[0].attributes["type"]); +			CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.getEntries().size()); +			CPPUNIT_ASSERT_EQUAL(std::string("get"), client_.events[0].attributes.getAttribute("type"));  			CPPUNIT_ASSERT_EQUAL(std::string(), client_.events[0].ns);  			CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type);  			CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[1].data); -			CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[1].attributes.size()); +			CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[1].attributes.getEntries().size());  			CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[1].ns);  			CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[2].type); @@ -76,7 +78,7 @@ class XMLParserTest : public CppUnit::TestFixture {  			CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type);  			CPPUNIT_ASSERT_EQUAL(std::string("query"), client_.events[0].data); -			CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[0].attributes.size()); +			CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[0].attributes.getEntries().size());  			CPPUNIT_ASSERT_EQUAL(std::string("jabber:iq:version"), client_.events[0].ns);  			CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type); @@ -205,6 +207,28 @@ class XMLParserTest : public CppUnit::TestFixture {  			CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[2].type);  			CPPUNIT_ASSERT_EQUAL(std::string("presence"), client_.events[2].data);  		} + +		void testParse_AttributeWithoutNamespace() { +			ParserType testling(&client_); + +			CPPUNIT_ASSERT(testling.parse( +				"<query xmlns='http://swift.im' attr='3'/>")); + +			CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.getEntries().size()); +			CPPUNIT_ASSERT_EQUAL(std::string("attr"), client_.events[0].attributes.getEntries()[0].getAttribute().getName()); +			CPPUNIT_ASSERT_EQUAL(std::string(""), client_.events[0].attributes.getEntries()[0].getAttribute().getNamespace()); +		} + +		void testParse_AttributeWithNamespace() { +			ParserType testling(&client_); + +			CPPUNIT_ASSERT(testling.parse( +				"<query xmlns='http://swift.im' xmlns:f='http://swift.im/f' f:attr='3'/>")); + +			CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.getEntries().size()); +			CPPUNIT_ASSERT_EQUAL(std::string("attr"), client_.events[0].attributes.getEntries()[0].getAttribute().getName()); +			CPPUNIT_ASSERT_EQUAL(std::string("http://swift.im/f"), client_.events[0].attributes.getEntries()[0].getAttribute().getNamespace()); +		}  	private:  		class Client : public XMLParserClient { | 
 Swift
 Swift