diff options
Diffstat (limited to 'Swiften/Parser/ExpatParser.cpp')
| -rw-r--r-- | Swiften/Parser/ExpatParser.cpp | 57 |
1 files changed, 39 insertions, 18 deletions
diff --git a/Swiften/Parser/ExpatParser.cpp b/Swiften/Parser/ExpatParser.cpp index 640d561..6c3845a 100644 --- a/Swiften/Parser/ExpatParser.cpp +++ b/Swiften/Parser/ExpatParser.cpp | |||
| @@ -11,6 +11,8 @@ | |||
| 11 | #include <memory> | 11 | #include <memory> |
| 12 | #include <string> | 12 | #include <string> |
| 13 | 13 | ||
| 14 | #include <boost/algorithm/string.hpp> | ||
| 15 | |||
| 14 | #include <expat.h> | 16 | #include <expat.h> |
| 15 | 17 | ||
| 16 | #include <Swiften/Base/String.h> | 18 | #include <Swiften/Base/String.h> |
| @@ -18,6 +20,33 @@ | |||
| 18 | 20 | ||
| 19 | #pragma clang diagnostic ignored "-Wdisabled-macro-expansion" | 21 | #pragma clang diagnostic ignored "-Wdisabled-macro-expansion" |
| 20 | 22 | ||
| 23 | namespace { | ||
| 24 | struct XmlInfo { | ||
| 25 | std::string prefix; | ||
| 26 | std::string uri; | ||
| 27 | std::string name; | ||
| 28 | }; | ||
| 29 | |||
| 30 | XmlInfo splitExpatInfo(const std::string& s, char sep) { | ||
| 31 | // name | ||
| 32 | // uri|name | ||
| 33 | // uri|name|prefix | ||
| 34 | std::vector<std::string> v; | ||
| 35 | boost::split(v, s, [sep](char c) {return c == sep; }); | ||
| 36 | switch (v.size()) { | ||
| 37 | case 1: | ||
| 38 | return{ "", "", std::move(v[0]) }; | ||
| 39 | case 2: | ||
| 40 | return{ "", std::move(v[0]), std::move(v[1]) }; | ||
| 41 | case 3: | ||
| 42 | return{ std::move(v[2]), std::move(v[0]), std::move(v[1]) }; | ||
| 43 | default: | ||
| 44 | return{ "", "", "" }; | ||
| 45 | } | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | |||
| 21 | namespace Swift { | 50 | namespace Swift { |
| 22 | 51 | ||
| 23 | static const char NAMESPACE_SEPARATOR = '\x01'; | 52 | static const char NAMESPACE_SEPARATOR = '\x01'; |
| @@ -27,33 +56,24 @@ struct ExpatParser::Private { | |||
| 27 | }; | 56 | }; |
| 28 | 57 | ||
| 29 | static void handleStartElement(void* parser, const XML_Char* name, const XML_Char** attributes) { | 58 | static void handleStartElement(void* parser, const XML_Char* name, const XML_Char** attributes) { |
| 30 | std::pair<std::string,std::string> nsTagPair = String::getSplittedAtFirst(name, NAMESPACE_SEPARATOR); | 59 | auto elemInfo = splitExpatInfo(name, NAMESPACE_SEPARATOR); |
| 31 | if (nsTagPair.second == "") { | 60 | |
| 32 | nsTagPair.second = nsTagPair.first; | ||
| 33 | nsTagPair.first = ""; | ||
| 34 | } | ||
| 35 | AttributeMap attributeValues; | 61 | AttributeMap attributeValues; |
| 36 | const XML_Char** currentAttribute = attributes; | 62 | const XML_Char** currentAttribute = attributes; |
| 37 | while (*currentAttribute) { | 63 | while (*currentAttribute) { |
| 38 | std::pair<std::string,std::string> nsAttributePair = String::getSplittedAtFirst(*currentAttribute, NAMESPACE_SEPARATOR); | 64 | auto attribInfo = splitExpatInfo(*currentAttribute, NAMESPACE_SEPARATOR); |
| 39 | if (nsAttributePair.second == "") { | 65 | attributeValues.addAttribute(attribInfo.name, attribInfo.uri, attribInfo.prefix, std::string(*(currentAttribute+1))); |
| 40 | nsAttributePair.second = nsAttributePair.first; | ||
| 41 | nsAttributePair.first = ""; | ||
| 42 | } | ||
| 43 | attributeValues.addAttribute(nsAttributePair.second, nsAttributePair.first, std::string(*(currentAttribute+1))); | ||
| 44 | currentAttribute += 2; | 66 | currentAttribute += 2; |
| 45 | } | 67 | } |
| 46 | 68 | ||
| 47 | static_cast<XMLParser*>(parser)->getClient()->handleStartElement(nsTagPair.second, nsTagPair.first, attributeValues); | 69 | auto* client = static_cast<XMLParser*>(parser)->getClient(); |
| 70 | client->handleStartElementPrefix(elemInfo.prefix, elemInfo.uri, elemInfo.name, elemInfo.name, elemInfo.uri, attributeValues); | ||
| 71 | client->handleStartElement(elemInfo.name, elemInfo.uri, attributeValues); | ||
| 48 | } | 72 | } |
| 49 | 73 | ||
| 50 | static void handleEndElement(void* parser, const XML_Char* name) { | 74 | static void handleEndElement(void* parser, const XML_Char* name) { |
| 51 | std::pair<std::string,std::string> nsTagPair = String::getSplittedAtFirst(name, NAMESPACE_SEPARATOR); | 75 | auto elemInfo = splitExpatInfo(name, NAMESPACE_SEPARATOR); |
| 52 | if (nsTagPair.second == "") { | 76 | static_cast<XMLParser*>(parser)->getClient()->handleEndElement(elemInfo.name, elemInfo.uri); |
| 53 | nsTagPair.second = nsTagPair.first; | ||
| 54 | nsTagPair.first = ""; | ||
| 55 | } | ||
| 56 | static_cast<XMLParser*>(parser)->getClient()->handleEndElement(nsTagPair.second, nsTagPair.first); | ||
| 57 | } | 77 | } |
| 58 | 78 | ||
| 59 | static void handleCharacterData(void* parser, const XML_Char* data, int len) { | 79 | static void handleCharacterData(void* parser, const XML_Char* data, int len) { |
| @@ -88,6 +108,7 @@ static void handleDoctypeDeclaration(void* parser, const XML_Char* /*doctypeName | |||
| 88 | 108 | ||
| 89 | ExpatParser::ExpatParser(XMLParserClient* client, bool allowComments) : XMLParser(client, allowComments), p(new Private()) { | 109 | ExpatParser::ExpatParser(XMLParserClient* client, bool allowComments) : XMLParser(client, allowComments), p(new Private()) { |
| 90 | p->parser_ = XML_ParserCreateNS("UTF-8", NAMESPACE_SEPARATOR); | 110 | p->parser_ = XML_ParserCreateNS("UTF-8", NAMESPACE_SEPARATOR); |
| 111 | XML_SetReturnNSTriplet(p->parser_, true); | ||
| 91 | XML_SetUserData(p->parser_, this); | 112 | XML_SetUserData(p->parser_, this); |
| 92 | XML_SetElementHandler(p->parser_, handleStartElement, handleEndElement); | 113 | XML_SetElementHandler(p->parser_, handleStartElement, handleEndElement); |
| 93 | XML_SetCharacterDataHandler(p->parser_, handleCharacterData); | 114 | XML_SetCharacterDataHandler(p->parser_, handleCharacterData); |
Swift