diff options
Diffstat (limited to 'src/plugins/xml/XmlParser.cpp')
-rw-r--r-- | src/plugins/xml/XmlParser.cpp | 102 |
1 files changed, 69 insertions, 33 deletions
diff --git a/src/plugins/xml/XmlParser.cpp b/src/plugins/xml/XmlParser.cpp index 42e0dd4..afc7f14 100644 --- a/src/plugins/xml/XmlParser.cpp +++ b/src/plugins/xml/XmlParser.cpp @@ -20,6 +20,7 @@ #include <expat.h> +#include <core/Utils.hpp> #include <core/parser/ParserStack.hpp> #include "XmlParser.hpp" @@ -44,30 +45,54 @@ static const State STATE_CONSTANT = 201; static const State STATE_ENUM = 202; static const State STATE_STRUCT = 203; -static Handler* createTestHandler(const ParserContext &ctx, - std::string name, State state, - State parentState, bool isChild) +class TestHandler : public Handler { +public: + using Handler::Handler; + + void start(const Variant &args) override + { + std::cout << this->name << ": start (isChild: " << (this->isChild) + << ", args: " << args << ")" << std::endl; + } + + void end() override + { + // TODO + } + + void data(const std::string &data, int field) override + { + std::cout << this->name << ": data \"" << data << "\"" << std::endl; + } + + void child(std::shared_ptr<Handler> handler) override + { + // TODO + } +}; + +static Handler *createTestHandler(const ParserContext &ctx, std::string name, + State state, State parentState, bool isChild) { - return nullptr; + return new TestHandler{ctx, name, state, parentState, isChild}; } static const std::multimap<std::string, HandlerDescriptor> XML_HANDLERS{ - /* Documents */ - {"document", {{STATE_NONE}, createTestHandler, STATE_DOCUMENT}}, - {"head", {{STATE_DOCUMENT}, createTestHandler, STATE_HEAD}}, - {"body", {{STATE_DOCUMENT}, createTestHandler, STATE_BODY, true}}, - - /* Special commands */ - {"use", {{STATE_HEAD}, createTestHandler, STATE_USE}}, - {"include", {{STATE_ALL}, createTestHandler, STATE_INCLUDE}}, - {"inline", {{STATE_ALL}, createTestHandler, STATE_INLINE}}, - - /* Typesystem definitions */ - {"types", {{STATE_NONE, STATE_HEAD}, createTestHandler, STATE_TYPES}}, - {"enum", {{STATE_TYPES}, createTestHandler, STATE_ENUM}}, - {"struct", {{STATE_TYPES}, createTestHandler, STATE_STRUCT}}, - {"constant", {{STATE_TYPES}, createTestHandler, STATE_CONSTANT}} -}; + /* Documents */ + {"document", {{STATE_NONE}, createTestHandler, STATE_DOCUMENT}}, + {"head", {{STATE_DOCUMENT}, createTestHandler, STATE_HEAD}}, + {"body", {{STATE_DOCUMENT}, createTestHandler, STATE_BODY, true}}, + + /* Special commands */ + {"use", {{STATE_HEAD}, createTestHandler, STATE_USE}}, + {"include", {{STATE_ALL}, createTestHandler, STATE_INCLUDE}}, + {"inline", {{STATE_ALL}, createTestHandler, STATE_INLINE}}, + + /* Typesystem definitions */ + {"typesystem", {{STATE_NONE, STATE_HEAD}, createTestHandler, STATE_TYPES}}, + {"enum", {{STATE_TYPES}, createTestHandler, STATE_ENUM}}, + {"struct", {{STATE_TYPES}, createTestHandler, STATE_STRUCT}}, + {"constant", {{STATE_TYPES}, createTestHandler, STATE_CONSTANT}}}; /** * Wrapper class around the XML_Parser pointer which safely frees it whenever @@ -89,8 +114,7 @@ public: * @param encoding is the protocol-defined encoding passed to expat (or * nullptr if expat should determine the encoding by itself). */ - ScopedExpatXmlParser(const XML_Char *encoding) - : parser(nullptr) + ScopedExpatXmlParser(const XML_Char *encoding) : parser(nullptr) { parser = XML_ParserCreate(encoding); if (!parser) { @@ -116,28 +140,36 @@ public: XML_Parser operator&() { return parser; } }; +/* Adapter Expat -> ParserStack */ + static void xmlStartElementHandler(void *userData, const XML_Char *name, const XML_Char **attrs) { - std::cout << "start tag: " << name << std::endl; + Variant::mapType args; const XML_Char **attr = attrs; while (*attr) { - std::cout << "\t" << *attr; - attr++; - std::cout << " -> " << *attr << std::endl; - attr++; + const std::string key{*(attr++)}; + args.emplace(std::make_pair(key, Variant{*(attr++)})); } + (static_cast<ParserStack *>(userData))->start(std::string(name), args); } -static void xmlEndElementHandler(void *userData, const XML_Char *name) { - std::cout << "end tag: " << name << std::endl; +static void xmlEndElementHandler(void *userData, const XML_Char *name) +{ + (static_cast<ParserStack *>(userData))->end(); } - -static void xmlCharacterDataHandler(void *userData, const XML_Char *s, int len) { - std::cout << "\tdata: " << std::string(s, len) << std::endl; +static void xmlCharacterDataHandler(void *userData, const XML_Char *s, int len) +{ + const std::string data = + Utils::trim(std::string{s, static_cast<size_t>(len)}); + if (!data.empty()) { + (static_cast<ParserStack *>(userData))->data(data); + } } +/* Class XmlParser */ + std::set<std::string> XmlParser::mimetypes() { return std::set<std::string>{{"text/vnd.ousia.oxm", "text/vnd.ousia.oxd"}}; @@ -147,7 +179,11 @@ Rooted<Node> XmlParser::parse(std::istream &is, ParserContext &ctx) { // Create the parser object ScopedExpatXmlParser p{"UTF-8"}; - XML_SetUserData(&p, &ctx); + + // Create the parser stack instance and pass the reference to the state + // machine descriptor + ParserStack stack{ctx, XML_HANDLERS}; + XML_SetUserData(&p, &stack); // Set the callback functions XML_SetStartElementHandler(&p, xmlStartElementHandler); |