From 714f89d30cf04ad972df84a6a398258b751d3553 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Tue, 8 Dec 2020 20:30:25 +0100 Subject: Make tagreader use the new XML parser --- src/tagreader.cpp | 549 +++++++++++++++++++++++++----------------------------- src/xml.h | 10 + 2 files changed, 268 insertions(+), 291 deletions(-) diff --git a/src/tagreader.cpp b/src/tagreader.cpp index 62aadc3..d5f8d5f 100644 --- a/src/tagreader.cpp +++ b/src/tagreader.cpp @@ -21,17 +21,13 @@ #include #include #include +#include #include #include #include -#include - - -#include -#include -#include +#include "xml.h" #include "entry.h" #include "doxygen.h" #include "util.h" @@ -47,32 +43,32 @@ class TagAnchorInfo { public: - TagAnchorInfo(const QCString &f, - const QCString &l, - const QCString &t=QCString()) + TagAnchorInfo(const std::string &f, + const std::string &l, + const std::string &t=std::string()) : label(l), fileName(f), title(t) {} - QCString label; - QCString fileName; - QCString title; + std::string label; + std::string fileName; + std::string title; }; /** Container for enum values that are scoped within an enum */ class TagEnumValueInfo { public: - QCString name; - QCString file; - QCString anchor; - QCString clangid; + std::string name; + std::string file; + std::string anchor; + std::string clangid; }; /** Container for include info that can be read from a tagfile */ class TagIncludeInfo { public: - QCString id; - QCString name; - QCString text; + std::string id; + std::string name; + std::string text; bool isLocal; bool isImported; }; @@ -81,13 +77,13 @@ class TagIncludeInfo class TagMemberInfo { public: - QCString type; - QCString name; - QCString anchorFile; - QCString anchor; - QCString arglist; - QCString kind; - QCString clangId; + std::string type; + std::string name; + std::string anchorFile; + std::string anchor; + std::string arglist; + std::string kind; + std::string clangId; std::vector docAnchors; Protection prot = Public; Specifier virt = Normal; @@ -104,8 +100,8 @@ class TagCompoundInfo virtual ~TagCompoundInfo() {} CompoundType compoundType() const { return m_type; } std::vector members; - QCString name; - QCString filename; + std::string name; + std::string filename; std::vector docAnchors; private: CompoundType m_type; @@ -117,8 +113,8 @@ class TagClassInfo : public TagCompoundInfo public: enum class Kind { None=-1, Class, Struct, Union, Interface, Exception, Protocol, Category, Enum, Service, Singleton }; TagClassInfo(Kind k) : TagCompoundInfo(CompoundType::Class), kind(k) {} - QCString clangId; - QCString anchor; + std::string clangId; + std::string anchor; std::vector bases; StringVector templateArguments; StringVector classList; @@ -139,7 +135,7 @@ class TagNamespaceInfo : public TagCompoundInfo { public: TagNamespaceInfo() :TagCompoundInfo(CompoundType::Namespace) {} - QCString clangId; + std::string clangId; StringVector classList; StringVector namespaceList; static TagNamespaceInfo *get(std::unique_ptr &t) @@ -173,7 +169,7 @@ class TagFileInfo : public TagCompoundInfo { public: TagFileInfo() : TagCompoundInfo(CompoundType::File) { } - QCString path; + std::string path; StringVector classList; StringVector namespaceList; std::vector includes; @@ -192,7 +188,7 @@ class TagGroupInfo : public TagCompoundInfo { public: TagGroupInfo() : TagCompoundInfo(CompoundType::Group) { } - QCString title; + std::string title; StringVector subgroupList; StringVector classList; StringVector namespaceList; @@ -214,7 +210,7 @@ class TagPageInfo : public TagCompoundInfo { public: TagPageInfo() : TagCompoundInfo(CompoundType::Page) {} - QCString title; + std::string title; static TagPageInfo *get(std::unique_ptr &t) { return dynamic_cast(t.get()); @@ -230,7 +226,7 @@ class TagDirInfo : public TagCompoundInfo { public: TagDirInfo() : TagCompoundInfo(CompoundType::Dir) {} - QCString path; + std::string path; StringVector subdirList; StringVector fileList; static TagDirInfo *get(std::unique_ptr &t) @@ -249,75 +245,33 @@ class TagDirInfo : public TagCompoundInfo * memory. The method buildLists() is used to transfer/translate * the structures to the doxygen engine. */ -class TagFileParser : public QXmlDefaultHandler +class TagFileParser { - enum State { Invalid, - InClass, - InFile, - InNamespace, - InGroup, - InPage, - InMember, - InEnumValue, - InPackage, - InDir, - InTempArgList - }; - - struct CompoundFactory - { - using CreateFunc = std::function()>; - CompoundFactory(State s,CreateFunc f) : state(s), make_instance(f) {} - State state; - CreateFunc make_instance; - }; public: TagFileParser(const char *tagName) : m_tagName(tagName) {} - void setDocumentLocator ( QXmlLocator * locator ) + void setDocumentLocator ( const XMLLocator * locator ) { m_locator = locator; } - void setFileName( const QString &fileName ) - { - m_inputFileName = fileName.utf8(); - } - - void warn(const char *fmt) + void startDocument() { - ::warn(m_inputFileName,m_locator->lineNumber(),"%s", fmt); + m_state = Invalid; } - void warn(const char *fmt,const char *s) + void startElement( const std::string &name, const XMLHandlers::Attributes& attrib ); + void endElement( const std::string &name ); + void characters ( const std::string & ch ) { m_curString+=ch; } + void error( const std::string &fileName,int lineNr,const std::string &msg) { - ::warn(m_inputFileName,m_locator->lineNumber(),fmt,s); + ::warn(fileName.c_str(),lineNr,"%s",msg.c_str()); } - void startCompound( const QXmlAttributes& attrib ) - { - m_curString = ""; - QString kind = attrib.value("kind"); - QString isObjC = attrib.value("objc"); - - auto it = m_compoundFactory.find(kind.utf8().str()); - if (it!=m_compoundFactory.end()) - { - m_curCompound = it->second.make_instance(); - m_state = it->second.state; - } - else - { - warn("Unknown compound attribute '%s' found!",kind.data()); - m_state = Invalid; - } - - if (isObjC=="yes" && m_curCompound && - m_curCompound->compoundType()==TagCompoundInfo::CompoundType::Class) - { - TagClassInfo::get(m_curCompound)->isObjC = TRUE; - } - } + void dump(); + void buildLists(const std::shared_ptr &root); + void addIncludes(); + void startCompound( const XMLHandlers::Attributes& attrib ); void endCompound() { @@ -338,13 +292,13 @@ class TagFileParser : public QXmlDefaultHandler } } - void startMember( const QXmlAttributes& attrib) + void startMember( const XMLHandlers::Attributes& attrib) { m_curMember = TagMemberInfo(); - m_curMember.kind = attrib.value("kind").utf8(); - QCString protStr = attrib.value("protection").utf8(); - QCString virtStr = attrib.value("virtualness").utf8(); - QCString staticStr = attrib.value("static").utf8(); + m_curMember.kind = XMLHandlers::value(attrib,"kind"); + std::string protStr = XMLHandlers::value(attrib,"protection"); + std::string virtStr = XMLHandlers::value(attrib,"virtualness"); + std::string staticStr = XMLHandlers::value(attrib,"static"); if (protStr=="protected") { m_curMember.prot = Protected; @@ -388,15 +342,15 @@ class TagFileParser : public QXmlDefaultHandler } } - void startEnumValue( const QXmlAttributes& attrib) + void startEnumValue( const XMLHandlers::Attributes& attrib) { if (m_state==InMember) { m_curString = ""; m_curEnumValue = TagEnumValueInfo(); - m_curEnumValue.file = attrib.value("file").utf8(); - m_curEnumValue.anchor = attrib.value("anchor").utf8(); - m_curEnumValue.clangid = attrib.value("clangid").utf8(); + m_curEnumValue.file = XMLHandlers::value(attrib,"file"); + m_curEnumValue.anchor = XMLHandlers::value(attrib,"anchor"); + m_curEnumValue.clangid = XMLHandlers::value(attrib,"clangid"); m_stateStack.push(m_state); m_state = InEnumValue; } @@ -431,7 +385,7 @@ class TagFileParser : public QXmlDefaultHandler case InMember: case InPackage: case InDir: - if (QString(m_curString).startsWith("autotoc_md")) return; + if (m_curString.rfind("autotoc_md",0)==0) return; break; default: warn("Unexpected tag 'docanchor' found"); @@ -541,15 +495,15 @@ class TagFileParser : public QXmlDefaultHandler } } - void startStringValue(const QXmlAttributes& ) + void startStringValue(const XMLHandlers::Attributes& ) { m_curString = ""; } - void startDocAnchor(const QXmlAttributes& attrib ) + void startDocAnchor(const XMLHandlers::Attributes& attrib ) { - m_fileName = attrib.value("file").utf8(); - m_title = attrib.value("title").utf8(); + m_fileName = XMLHandlers::value(attrib,"file"); + m_title = XMLHandlers::value(attrib,"title"); m_curString = ""; } @@ -587,13 +541,13 @@ class TagFileParser : public QXmlDefaultHandler } } - void startBase(const QXmlAttributes& attrib ) + void startBase(const XMLHandlers::Attributes& attrib ) { m_curString=""; if (m_state==InClass && m_curCompound) { - QString protStr = attrib.value("protection"); - QString virtStr = attrib.value("virtualness"); + std::string protStr = XMLHandlers::value(attrib,"protection"); + std::string virtStr = XMLHandlers::value(attrib,"virtualness"); Protection prot = Public; Specifier virt = Normal; if (protStr=="protected") @@ -628,13 +582,13 @@ class TagFileParser : public QXmlDefaultHandler } } - void startIncludes(const QXmlAttributes& attrib ) + void startIncludes(const XMLHandlers::Attributes& attrib ) { m_curIncludes = TagIncludeInfo(); - m_curIncludes.id = attrib.value("id").utf8(); - m_curIncludes.name = attrib.value("name").utf8(); - m_curIncludes.isLocal = attrib.value("local").utf8()=="yes" ? TRUE : FALSE; - m_curIncludes.isImported = attrib.value("imported").utf8()=="yes" ? TRUE : FALSE; + m_curIncludes.id = XMLHandlers::value(attrib,"id"); + m_curIncludes.name = XMLHandlers::value(attrib,"name"); + m_curIncludes.isLocal = XMLHandlers::value(attrib,"local")=="yes"; + m_curIncludes.isImported = XMLHandlers::value(attrib,"imported")=="yes"; m_curString=""; } @@ -788,7 +742,7 @@ class TagFileParser : public QXmlDefaultHandler } } - void startIgnoreElement(const QXmlAttributes& ) + void startIgnoreElement(const XMLHandlers::Attributes& ) { } @@ -796,134 +750,40 @@ class TagFileParser : public QXmlDefaultHandler { } - bool startDocument() - { - m_state = Invalid; + void buildMemberList(const std::shared_ptr &ce,const std::vector &members); + void addDocAnchors(const std::shared_ptr &e,const std::vector &l); - m_startElementHandlers.insert({ - { "compound", std::bind(&TagFileParser::startCompound, this, std::placeholders::_1) }, - { "member", std::bind(&TagFileParser::startMember, this, std::placeholders::_1) }, - { "enumvalue", std::bind(&TagFileParser::startEnumValue, this, std::placeholders::_1) }, - { "name", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, - { "base", std::bind(&TagFileParser::startBase, this, std::placeholders::_1) }, - { "filename", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, - { "includes", std::bind(&TagFileParser::startIncludes, this, std::placeholders::_1) }, - { "path", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, - { "anchorfile", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, - { "anchor", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, - { "clangid", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, - { "arglist", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, - { "title", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, - { "subgroup", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, - { "class", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, - { "namespace", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, - { "file", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, - { "dir", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, - { "page", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, - { "docanchor", std::bind(&TagFileParser::startDocAnchor, this, std::placeholders::_1) }, - { "tagfile", std::bind(&TagFileParser::startIgnoreElement,this, std::placeholders::_1) }, - { "templarg", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) }, - { "type", std::bind(&TagFileParser::startStringValue, this, std::placeholders::_1) } - }); - - m_endElementHandlers.insert({ - { "compound", std::bind(&TagFileParser::endCompound, this) }, - { "member", std::bind(&TagFileParser::endMember, this) }, - { "enumvalue", std::bind(&TagFileParser::endEnumValue, this) }, - { "name", std::bind(&TagFileParser::endName, this) }, - { "base", std::bind(&TagFileParser::endBase, this) }, - { "filename", std::bind(&TagFileParser::endFilename, this) }, - { "includes", std::bind(&TagFileParser::endIncludes, this) }, - { "path", std::bind(&TagFileParser::endPath, this) }, - { "anchorfile", std::bind(&TagFileParser::endAnchorFile, this) }, - { "anchor", std::bind(&TagFileParser::endAnchor, this) }, - { "clangid", std::bind(&TagFileParser::endClangId, this) }, - { "arglist", std::bind(&TagFileParser::endArglist, this) }, - { "title", std::bind(&TagFileParser::endTitle, this) }, - { "subgroup", std::bind(&TagFileParser::endSubgroup, this) }, - { "class" , std::bind(&TagFileParser::endClass, this) }, - { "namespace", std::bind(&TagFileParser::endNamespace, this) }, - { "file", std::bind(&TagFileParser::endFile, this) }, - { "dir", std::bind(&TagFileParser::endDir, this) }, - { "page", std::bind(&TagFileParser::endPage, this) }, - { "docanchor", std::bind(&TagFileParser::endDocAnchor, this) }, - { "tagfile", std::bind(&TagFileParser::endIgnoreElement,this) }, - { "templarg", std::bind(&TagFileParser::endTemplateArg, this) }, - { "type", std::bind(&TagFileParser::endType, this) } - }); - - return TRUE; - } - - bool startElement( const QString&, const QString&, - const QString&name, const QXmlAttributes& attrib ) - { - //printf("startElement '%s'\n",name.data()); - auto it = m_startElementHandlers.find(name.utf8().str()); - if (it!=std::end(m_startElementHandlers)) - { - it->second(attrib); - } - else - { - warn("Unknown tag '%s' found!",name.data()); - } - return TRUE; - } - bool endElement( const QString&, const QString&, const QString& name ) + enum State { Invalid, + InClass, + InFile, + InNamespace, + InGroup, + InPage, + InMember, + InEnumValue, + InPackage, + InDir, + InTempArgList + }; + private: + + void warn(const char *fmt) { - //printf("endElement '%s'\n",name.data()); - auto it = m_endElementHandlers.find(name.utf8().str()); - if (it!=std::end(m_endElementHandlers)) - { - it->second(); - } - else - { - warn("Unknown tag '%s' found!",name.data()); - } - return TRUE; + std::string fileName = m_locator->fileName(); + ::warn(fileName.c_str(),m_locator->lineNr(),"%s", fmt); } - bool characters ( const QString & ch ) + void warn(const char *fmt,const char *s) { - m_curString+=ch.utf8(); - return TRUE; + std::string fileName = m_locator->fileName(); + ::warn(fileName.c_str(),m_locator->lineNr(),fmt,s); } - void dump(); - void buildLists(const std::shared_ptr &root); - void addIncludes(); - private: - void buildMemberList(const std::shared_ptr &ce,const std::vector &members); - void addDocAnchors(const std::shared_ptr &e,const std::vector &l); - std::vector< std::unique_ptr > m_tagFileCompounds; - - std::map< std::string, std::function > m_startElementHandlers; - std::map< std::string, std::function > m_endElementHandlers; - std::map< std::string, CompoundFactory > m_compoundFactory = - { - // kind tag state creation function - { "class", { InClass, []() { return std::make_unique(TagClassInfo::Kind::Class); } } }, - { "struct", { InClass, []() { return std::make_unique(TagClassInfo::Kind::Struct); } } }, - { "union", { InClass, []() { return std::make_unique(TagClassInfo::Kind::Union); } } }, - { "interface", { InClass, []() { return std::make_unique(TagClassInfo::Kind::Interface); } } }, - { "enum", { InClass, []() { return std::make_unique(TagClassInfo::Kind::Enum); } } }, - { "exception", { InClass, []() { return std::make_unique(TagClassInfo::Kind::Exception); } } }, - { "protocol", { InClass, []() { return std::make_unique(TagClassInfo::Kind::Protocol); } } }, - { "category", { InClass, []() { return std::make_unique(TagClassInfo::Kind::Category); } } }, - { "service", { InClass, []() { return std::make_unique(TagClassInfo::Kind::Service); } } }, - { "singleton", { InClass, []() { return std::make_unique(TagClassInfo::Kind::Singleton); } } }, - { "file", { InFile, []() { return std::make_unique(); } } }, - { "namespace", { InNamespace, []() { return std::make_unique(); } } }, - { "group", { InGroup, []() { return std::make_unique(); } } }, - { "page", { InPage, []() { return std::make_unique(); } } }, - { "package", { InPackage, []() { return std::make_unique(); } } }, - { "dir", { InDir, []() { return std::make_unique(); } } } - }; + //------------------------------------ + std::vector< std::unique_ptr > m_tagFileCompounds; std::unique_ptr m_curCompound; TagMemberInfo m_curMember; @@ -931,44 +791,149 @@ class TagFileParser : public QXmlDefaultHandler TagIncludeInfo m_curIncludes; std::string m_curString; - QCString m_tagName; - QCString m_fileName; - QCString m_title; + std::string m_tagName; + std::string m_fileName; + std::string m_title; State m_state = Invalid; std::stack m_stateStack; - QXmlLocator *m_locator = nullptr; - QCString m_inputFileName; + const XMLLocator *m_locator = nullptr; }; -/** Error handler for the XML tag file parser. - * - * Basically dumps all fatal error to stderr using err(). - */ -class TagFileErrorHandler : public QXmlErrorHandler +//--------------------------------------------------------------------------------------------------------------- + +struct ElementCallbacks { - public: - virtual ~TagFileErrorHandler() {} - bool warning( const QXmlParseException & ) - { - return FALSE; - } - bool error( const QXmlParseException & ) - { - return FALSE; - } - bool fatalError( const QXmlParseException &exception ) - { - err("Fatal error at line %d column %d: %s\n", - exception.lineNumber(),exception.columnNumber(), - exception.message().data()); - return FALSE; - } - QString errorString() { return ""; } + using StartCallback = std::function; + using EndCallback = std::function; - private: - QString errorMsg; + StartCallback startCb; + EndCallback endCb; +}; + +ElementCallbacks::StartCallback startCb(void (TagFileParser::*fn)(const XMLHandlers::Attributes &)) +{ + return [fn](TagFileParser &parser,const XMLHandlers::Attributes &attr) { (parser.*fn)(attr); }; +} + +ElementCallbacks::EndCallback endCb(void (TagFileParser::*fn)()) +{ + return [fn](TagFileParser &parser) { (parser.*fn)(); }; +} + +static const std::map< std::string, ElementCallbacks > g_elementHandlers = +{ + // name, start element callback, end element callback + { "compound", { startCb(&TagFileParser::startCompound ), endCb(&TagFileParser::endCompound ) } }, + { "member", { startCb(&TagFileParser::startMember ), endCb(&TagFileParser::endMember ) } }, + { "enumvalue", { startCb(&TagFileParser::startEnumValue ), endCb(&TagFileParser::endEnumValue ) } }, + { "name", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endName ) } }, + { "base", { startCb(&TagFileParser::startBase ), endCb(&TagFileParser::endBase ) } }, + { "filename", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endFilename ) } }, + { "includes", { startCb(&TagFileParser::startIncludes ), endCb(&TagFileParser::endIncludes ) } }, + { "path", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endPath ) } }, + { "anchorfile", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endAnchorFile ) } }, + { "anchor", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endAnchor ) } }, + { "clangid", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endClangId ) } }, + { "arglist", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endArglist ) } }, + { "title", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endTitle ) } }, + { "subgroup", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endSubgroup ) } }, + { "class", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endClass ) } }, + { "namespace", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endNamespace ) } }, + { "file", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endFile ) } }, + { "dir", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endDir ) } }, + { "page", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endPage ) } }, + { "docanchor", { startCb(&TagFileParser::startDocAnchor ), endCb(&TagFileParser::endDocAnchor ) } }, + { "tagfile", { startCb(&TagFileParser::startIgnoreElement), endCb(&TagFileParser::endIgnoreElement) } }, + { "templarg", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endTemplateArg ) } }, + { "type", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endType ) } } +}; + +//--------------------------------------------------------------------------------------------------------------- + +struct CompoundFactory +{ + using CreateFunc = std::function()>; + CompoundFactory(TagFileParser::State s,CreateFunc f) : state(s), make_instance(f) {} + TagFileParser::State state; + CreateFunc make_instance; }; +static const std::map< std::string, CompoundFactory > g_compoundFactory = +{ + // kind tag state creation function + { "class", { TagFileParser::InClass, []() { return std::make_unique(TagClassInfo::Kind::Class); } } }, + { "struct", { TagFileParser::InClass, []() { return std::make_unique(TagClassInfo::Kind::Struct); } } }, + { "union", { TagFileParser::InClass, []() { return std::make_unique(TagClassInfo::Kind::Union); } } }, + { "interface", { TagFileParser::InClass, []() { return std::make_unique(TagClassInfo::Kind::Interface); } } }, + { "enum", { TagFileParser::InClass, []() { return std::make_unique(TagClassInfo::Kind::Enum); } } }, + { "exception", { TagFileParser::InClass, []() { return std::make_unique(TagClassInfo::Kind::Exception); } } }, + { "protocol", { TagFileParser::InClass, []() { return std::make_unique(TagClassInfo::Kind::Protocol); } } }, + { "category", { TagFileParser::InClass, []() { return std::make_unique(TagClassInfo::Kind::Category); } } }, + { "service", { TagFileParser::InClass, []() { return std::make_unique(TagClassInfo::Kind::Service); } } }, + { "singleton", { TagFileParser::InClass, []() { return std::make_unique(TagClassInfo::Kind::Singleton); } } }, + { "file", { TagFileParser::InFile, []() { return std::make_unique(); } } }, + { "namespace", { TagFileParser::InNamespace, []() { return std::make_unique(); } } }, + { "group", { TagFileParser::InGroup, []() { return std::make_unique(); } } }, + { "page", { TagFileParser::InPage, []() { return std::make_unique(); } } }, + { "package", { TagFileParser::InPackage, []() { return std::make_unique(); } } }, + { "dir", { TagFileParser::InDir, []() { return std::make_unique(); } } } +}; + +//--------------------------------------------------------------------------------------------------------------- + +void TagFileParser::startElement( const std::string &name, const XMLHandlers::Attributes& attrib ) +{ + //printf("startElement '%s'\n",name.data()); + auto it = g_elementHandlers.find(name); + if (it!=std::end(g_elementHandlers)) + { + it->second.startCb(*this,attrib); + } + else + { + warn("Unknown start tag '%s' found!",name.data()); + } +} + +void TagFileParser::endElement( const std::string &name ) +{ + //printf("endElement '%s'\n",name.data()); + auto it = g_elementHandlers.find(name); + if (it!=std::end(g_elementHandlers)) + { + it->second.endCb(*this); + } + else + { + warn("Unknown end tag '%s' found!",name.data()); + } +} + +void TagFileParser::startCompound( const XMLHandlers::Attributes& attrib ) +{ + m_curString = ""; + std::string kind = XMLHandlers::value(attrib,"kind"); + std::string isObjC = XMLHandlers::value(attrib,"objc"); + + auto it = g_compoundFactory.find(kind); + if (it!=g_compoundFactory.end()) + { + m_curCompound = it->second.make_instance(); + m_state = it->second.state; + } + else + { + warn("Unknown compound attribute '%s' found!",kind.c_str()); + m_state = Invalid; + } + + if (isObjC=="yes" && m_curCompound && + m_curCompound->compoundType()==TagCompoundInfo::CompoundType::Class) + { + TagClassInfo::get(m_curCompound)->isObjC = TRUE; + } +} + /*! Dumps the internal structures. For debugging only! */ void TagFileParser::dump() { @@ -1134,13 +1099,13 @@ void TagFileParser::addDocAnchors(const std::shared_ptr &e,const std::vec { for (const auto &ta : l) { - if (SectionManager::instance().find(ta.label)==0) + if (SectionManager::instance().find(ta.label.c_str())==0) { //printf("New sectionInfo file=%s anchor=%s\n", // ta->fileName.data(),ta->label.data()); SectionInfo *si=SectionManager::instance().add( - ta.label,ta.fileName,-1,ta.title, - SectionType::Anchor,0,m_tagName); + ta.label.c_str(),ta.fileName.c_str(),-1,ta.title.c_str(), + SectionType::Anchor,0,m_tagName.c_str()); e->anchors.push_back(si); } else @@ -1347,27 +1312,28 @@ void TagFileParser::buildLists(const std::shared_ptr &root) const TagFileInfo *tfi = TagFileInfo::get(comp); std::shared_ptr fe = std::make_shared(); - fe->section = guessSection(tfi->name); - fe->name = tfi->name; + fe->section = guessSection(tfi->name.c_str()); + fe->name = tfi->name.c_str(); addDocAnchors(fe,tfi->docAnchors); fe->tagInfoData.tagName = m_tagName; fe->tagInfoData.fileName = tfi->filename; fe->hasTagInfo = TRUE; - QCString fullName = m_tagName+":"+tfi->path+stripPath(tfi->name); + std::string fullName = m_tagName+":"+tfi->path+stripPath(tfi->name).str(); fe->fileName = fullName; //printf("createFileDef() filename=%s\n",tfi->filename.data()); - std::unique_ptr fd { createFileDef(m_tagName+":"+tfi->path, - tfi->name,m_tagName, - tfi->filename) }; + std::string tagid = m_tagName+":"+tfi->path; + std::unique_ptr fd { createFileDef(tagid.c_str(), + tfi->name.c_str(),m_tagName.c_str(), + tfi->filename.c_str()) }; FileName *mn; - if ((mn=Doxygen::inputNameLinkedMap->find(tfi->name))) + if ((mn=Doxygen::inputNameLinkedMap->find(tfi->name.c_str()))) { mn->push_back(std::move(fd)); } else { - mn = Doxygen::inputNameLinkedMap->add(tfi->name,fullName); + mn = Doxygen::inputNameLinkedMap->add(tfi->name.c_str(),fullName.c_str()); mn->push_back(std::move(fd)); } buildMemberList(fe,tfi->members); @@ -1451,7 +1417,7 @@ void TagFileParser::buildLists(const std::shared_ptr &root) [&](const std::shared_ptr &e) { return e->name == sg.c_str(); }); if (i!=children.end()) { - (*i)->groups.push_back(Grouping(tgi->name,Grouping::GROUPING_INGROUP)); + (*i)->groups.push_back(Grouping(tgi->name.c_str(),Grouping::GROUPING_INGROUP)); } } } @@ -1465,7 +1431,7 @@ void TagFileParser::buildLists(const std::shared_ptr &root) const TagPageInfo *tpi = TagPageInfo::get(comp); std::shared_ptr pe = std::make_shared(); - bool isIndex = (stripExtensionGeneral(tpi->filename,getFileNameExtension(tpi->filename))=="index"); + bool isIndex = (stripExtensionGeneral(tpi->filename.c_str(),getFileNameExtension(tpi->filename.c_str()))=="index"); pe->section = isIndex ? Entry::MAINPAGEDOC_SEC : Entry::PAGEDOC_SEC; pe->name = tpi->name; pe->args = tpi->title; @@ -1486,7 +1452,7 @@ void TagFileParser::addIncludes() { const TagFileInfo *tfi = TagFileInfo::get(comp); //printf("tag file tagName=%s path=%s name=%s\n",m_tagName.data(),tfi->path.data(),tfi->name.data()); - FileName *fn = Doxygen::inputNameLinkedMap->find(tfi->name); + FileName *fn = Doxygen::inputNameLinkedMap->find(tfi->name.c_str()); if (fn) { for (const auto &fd : *fn) @@ -1498,7 +1464,7 @@ void TagFileParser::addIncludes() for (const auto &ii : tfi->includes) { //printf("ii->name='%s'\n",ii->name.data()); - FileName *ifn = Doxygen::inputNameLinkedMap->find(ii.name); + FileName *ifn = Doxygen::inputNameLinkedMap->find(ii.name.c_str()); ASSERT(ifn!=0); if (ifn) { @@ -1508,7 +1474,7 @@ void TagFileParser::addIncludes() // ifd->getOutputFileBase().data(),ii->id.data()); if (ifd->getOutputFileBase()==QCString(ii.id)) { - fd->addIncludeDependency(ifd.get(),ii.text,ii.isLocal,ii.isImported); + fd->addIncludeDependency(ifd.get(),ii.text.c_str(),ii.isLocal,ii.isImported); } } } @@ -1522,18 +1488,19 @@ void TagFileParser::addIncludes() void parseTagFile(const std::shared_ptr &root,const char *fullName) { - QFileInfo fi(fullName); - if (!fi.exists()) return; - TagFileParser handler( fullName ); // tagName - handler.setFileName(fullName); - TagFileErrorHandler errorHandler; - QFile xmlFile( fullName ); - QXmlInputSource source( xmlFile ); - QXmlSimpleReader reader; - reader.setContentHandler( &handler ); - reader.setErrorHandler( &errorHandler ); - reader.parse( source ); - handler.buildLists(root); - handler.addIncludes(); - //handler.dump(); + TagFileParser tagFileParser(fullName); + QCString inputStr = fileToString(fullName); + XMLHandlers handlers; + // connect the generic events handlers of the XML parser to the specific handlers of the tagFileParser object + handlers.startDocument = [&tagFileParser]() { tagFileParser.startDocument(); }; + handlers.startElement = [&tagFileParser](const std::string &name,const XMLHandlers::Attributes &attrs) { tagFileParser.startElement(name,attrs); }; + handlers.endElement = [&tagFileParser](const std::string &name) { tagFileParser.endElement(name); }; + handlers.characters = [&tagFileParser](const std::string &chars) { tagFileParser.characters(chars); }; + handlers.error = [&tagFileParser](const std::string &fileName,int lineNr,const std::string &msg) { tagFileParser.error(fileName,lineNr,msg); }; + XMLParser parser(handlers); + tagFileParser.setDocumentLocator(&parser); + parser.parse(fullName,inputStr); + tagFileParser.buildLists(root); + tagFileParser.addIncludes(); + //tagFileParser.dump(); } diff --git a/src/xml.h b/src/xml.h index 6ba36b2..add95f1 100644 --- a/src/xml.h +++ b/src/xml.h @@ -25,6 +25,16 @@ class XMLHandlers std::function endElement; /**< handler invoked when a closing tag has been found */ std::function characters; /**< handler invoked when content between tags has been found */ std::function error; /**< handler invoked when the parser encounters an error */ + + static std::string value(const Attributes &attrib,const std::string &key) + { + auto it = attrib.find(key); + if (it!=attrib.end()) + { + return it->second; + } + return ""; + } }; class XMLLocator -- cgit v0.12