From b97b3b47d3d71c5ac121df27863c8d3bc27273ea Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Fri, 15 Jan 2021 22:12:10 +0100 Subject: Refactoring: modernize HtmlAttribList --- src/docbookvisitor.cpp | 36 +++++++--------- src/docparser.cpp | 111 +++++++++++++++++++----------------------------- src/doctokenizer.l | 2 +- src/htmlattrib.h | 58 +++---------------------- src/htmldocvisitor.cpp | 49 ++++++++------------- src/latexdocvisitor.cpp | 25 ++++++++--- src/rtfdocvisitor.cpp | 12 ++---- src/xmldocvisitor.cpp | 54 +++++++++++------------ 8 files changed, 136 insertions(+), 211 deletions(-) diff --git a/src/docbookvisitor.cpp b/src/docbookvisitor.cpp index 5018230..a03fa3c 100644 --- a/src/docbookvisitor.cpp +++ b/src/docbookvisitor.cpp @@ -1045,14 +1045,12 @@ DB_VIS_C m_t << " attribs()); - HtmlAttrib *opt; - for (li.toFirst();(opt=li.current());++li) + for (const auto &opt : tr->attribs()) { - if (supportedHtmlAttribute(opt->name)) + if (supportedHtmlAttribute(opt.name)) { // process supported attributes only - m_t << " " << opt->name << "='" << convertToDocBook(opt->value) << "'"; + m_t << " " << opt.name << "='" << convertToDocBook(opt.value) << "'"; } } m_t << ">\n"; @@ -1077,35 +1075,33 @@ DB_VIS_C if (m_hide) return; m_t << "attribs()); - HtmlAttrib *opt; - for (li.toFirst();(opt=li.current());++li) + for (const auto &opt : c->attribs()) { - if (opt->name=="colspan") + if (opt.name=="colspan") { m_t << " namest='c" << m_colCnt << "'"; - int cols = opt->value.toInt(); + int cols = opt.value.toInt(); m_colCnt += (cols - 1); m_t << " nameend='c" << m_colCnt << "'"; } - else if (opt->name=="rowspan") + else if (opt.name=="rowspan") { - int extraRows = opt->value.toInt() - 1; + int extraRows = opt.value.toInt() - 1; m_t << " morerows='" << extraRows << "'"; } - else if (opt->name=="class") + else if (opt.name=="class") { - if (opt->value.left(13)=="markdownTable") // handle markdown generated attributes + if (opt.value.left(13)=="markdownTable") // handle markdown generated attributes { - if (opt->value.right(5)=="Right") + if (opt.value.right(5)=="Right") { m_t << " align='right'"; } - else if (opt->value.right(4)=="Left") + else if (opt.value.right(4)=="Left") { m_t << " align='left'"; } - else if (opt->value.right(6)=="Center") + else if (opt.value.right(6)=="Center") { m_t << " align='center'"; } @@ -1113,13 +1109,13 @@ DB_VIS_C } else { - m_t << " class='" << convertToDocBook(opt->value) << "'"; + m_t << " class='" << convertToDocBook(opt.value) << "'"; } } - else if (supportedHtmlAttribute(opt->name)) + else if (supportedHtmlAttribute(opt.name)) { // process supported attributes only - m_t << " " << opt->name << "='" << convertToDocBook(opt->value) << "'"; + m_t << " " << opt.name << "='" << convertToDocBook(opt.value) << "'"; } } m_t << ">"; diff --git a/src/docparser.cpp b/src/docparser.cpp index a4d2b4c..b0815b1 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -988,22 +988,15 @@ static void handleInitialStyleCommands(DocPara *parent,DocNodeList &children) static int handleAHref(DocNode *parent,DocNodeList &children,const HtmlAttribList &tagHtmlAttribs) { - HtmlAttribListIterator li(tagHtmlAttribs); - HtmlAttrib *opt; uint index=0; int retval = RetVal_OK; - for (li.toFirst();(opt=li.current());++li,++index) + for (const auto &opt : tagHtmlAttribs) { - if (opt->name=="name" || opt->name=="id") // or tag + if (opt.name=="name" || opt.name=="id") // or tag { - if (!opt->value.isEmpty()) + if (!opt.value.isEmpty()) { - // copy attributes - HtmlAttribList attrList = tagHtmlAttribs; - // and remove the href attribute - bool result = attrList.remove(index); - ASSERT(result); - children.push_back(std::make_unique(parent,opt->value,TRUE)); + children.push_back(std::make_unique(parent,opt.value,TRUE)); break; // stop looking for other tag attribs } else @@ -1011,14 +1004,13 @@ static int handleAHref(DocNode *parent,DocNodeList &children,const HtmlAttribLis warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found tag with name option but without value!"); } } - else if (opt->name=="href") // .. tag + else if (opt.name=="href") // .. tag { // copy attributes HtmlAttribList attrList = tagHtmlAttribs; // and remove the href attribute - bool result = attrList.remove(index); - ASSERT(result); - DocHRef *href = new DocHRef(parent,attrList,opt->value,g_relPath); + attrList.erase(attrList.begin()+index); + DocHRef *href = new DocHRef(parent,attrList,opt.value,g_relPath); children.push_back(std::unique_ptr(href)); g_insideHtmlLink=TRUE; retval = href->parse(); @@ -1028,6 +1020,7 @@ static int handleAHref(DocNode *parent,DocNodeList &children,const HtmlAttribLis else // unsupported option for tag a { } + ++index; } return retval; } @@ -1738,26 +1731,24 @@ handlepara: static void handleImg(DocNode *parent, DocNodeList &children,const HtmlAttribList &tagHtmlAttribs) { - HtmlAttribListIterator li(tagHtmlAttribs); - HtmlAttrib *opt; bool found=FALSE; uint index=0; - for (li.toFirst();(opt=li.current());++li,++index) + for (const auto &opt : tagHtmlAttribs) { - //printf("option name=%s value=%s\n",opt->name.data(),opt->value.data()); - if (opt->name=="src" && !opt->value.isEmpty()) + //printf("option name=%s value=%s\n",opt.name.data(),opt.value.data()); + if (opt.name=="src" && !opt.value.isEmpty()) { // copy attributes HtmlAttribList attrList = tagHtmlAttribs; // and remove the src attribute - bool result = attrList.remove(index); - ASSERT(result); + attrList.erase(attrList.begin()+index); DocImage::Type t = DocImage::Html; children.push_back( std::make_unique( - parent,attrList,findAndCopyImage(opt->value,t,false),t,opt->value)); + parent,attrList,findAndCopyImage(opt.value,t,false),t,opt.value)); found = TRUE; } + ++index; } if (!found) { @@ -3206,13 +3197,11 @@ endindexentry: DocHtmlCaption::DocHtmlCaption(DocNode *parent,const HtmlAttribList &attribs) { m_hasCaptionId = FALSE; - HtmlAttribListIterator li(attribs); - HtmlAttrib *opt; - for (li.toFirst();(opt=li.current());++li) + for (const auto &opt : attribs) { - if (opt->name=="id" && !opt->value.isEmpty()) // interpret id attribute as an anchor + if (opt.name=="id" && !opt.value.isEmpty()) // interpret id attribute as an anchor { - const SectionInfo *sec = SectionManager::instance().find(opt->value); + const SectionInfo *sec = SectionManager::instance().find(opt.value); if (sec) { //printf("Found anchor %s\n",id.data()); @@ -3222,12 +3211,12 @@ DocHtmlCaption::DocHtmlCaption(DocNode *parent,const HtmlAttribList &attribs) } else { - warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid caption id '%s'",qPrint(opt->value)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid caption id '%s'",qPrint(opt.value)); } } else // copy attribute { - m_attribs.append(new HtmlAttrib(*opt)); + m_attribs.push_back(opt); } } m_parent = parent; @@ -3351,67 +3340,57 @@ int DocHtmlCell::parseXml() uint DocHtmlCell::rowSpan() const { - uint retval = 0; - HtmlAttribList attrs = attribs(); - uint i; - for (i=0; iname.lower()=="rowspan") + if (attr.name.lower()=="rowspan") { - retval = attrs.at(i)->value.toUInt(); - break; + return attr.value.toUInt(); } } - return retval; + return 0; } uint DocHtmlCell::colSpan() const { - uint retval = 1; - HtmlAttribList attrs = attribs(); - uint i; - for (i=0; iname.lower()=="colspan") + if (attr.name.lower()=="colspan") { - retval = QMAX(1,attrs.at(i)->value.toUInt()); - break; + return QMAX(1,attr.value.toUInt()); } } - return retval; + return 1; } DocHtmlCell::Alignment DocHtmlCell::alignment() const { - HtmlAttribList attrs = attribs(); - uint i; - for (i=0; iname.lower()=="align") + if (attr.name.lower()=="align") { - if (attrs.at(i)->value.lower()=="center") + if (attr.value.lower()=="center") return Center; - else if (attrs.at(i)->value.lower()=="right") + else if (attr.value.lower()=="right") return Right; else return Left; } - else if (attrs.at(i)->name.lower()=="class") + else if (attr.name.lower()=="class") { - if (attrs.at(i)->value.lower()=="markdowntableheadcenter") + if (attr.value.lower()=="markdowntableheadcenter") return Center; - else if (attrs.at(i)->value.lower()=="markdowntableheadright") + else if (attr.value.lower()=="markdowntableheadright") return Right; - else if (attrs.at(i)->value.lower()=="markdowntableheadleft") + else if (attr.value.lower()=="markdowntableheadleft") return Left; - else if (attrs.at(i)->value.lower()=="markdowntableheadnone") + else if (attr.value.lower()=="markdowntableheadnone") return Center; - else if (attrs.at(i)->value.lower()=="markdowntablebodycenter") + else if (attr.value.lower()=="markdowntablebodycenter") return Center; - else if (attrs.at(i)->value.lower()=="markdowntablebodyright") + else if (attr.value.lower()=="markdowntablebodyright") return Right; - else if (attrs.at(i)->value.lower()=="markdowntablebodyleft") + else if (attr.value.lower()=="markdowntablebodyleft") return Left; - else if (attrs.at(i)->value.lower()=="markdowntablebodynone") + else if (attr.value.lower()=="markdowntablebodynone") return Left; else return Left; } @@ -5800,13 +5779,11 @@ static bool findAttribute(const HtmlAttribList &tagHtmlAttribs, QCString *result) { - HtmlAttribListIterator li(tagHtmlAttribs); - HtmlAttrib *opt; - for (li.toFirst();(opt=li.current());++li) + for (const auto &opt : tagHtmlAttribs) { - if (opt->name==attrName) + if (opt.name==attrName) { - *result = opt->value; + *result = opt.value; return TRUE; } } @@ -6998,7 +6975,7 @@ void DocRoot::parse() DocPara *par = new DocPara(this); if (isFirst) { par->markFirst(); isFirst=FALSE; } retval=par->parse(); - if (!par->isEmpty() || par->attribs().count()>0) + if (!par->isEmpty() || !par->attribs().empty()) { m_children.push_back(std::unique_ptr(par)); lastPar=par; diff --git a/src/doctokenizer.l b/src/doctokenizer.l index 63a49ca..c9fe84f 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -298,7 +298,7 @@ static void handleHtmlTag() } //printf("=====> Adding option name=<%s> value=<%s>\n", // opt.name.data(),opt.value.data()); - g_token->attribs.append(&opt); + g_token->attribs.push_back(opt); } g_token->attribsStr = tagText.mid(startAttribList,i-startAttribList); } diff --git a/src/htmlattrib.h b/src/htmlattrib.h index 66d5325..ea3bd04 100644 --- a/src/htmlattrib.h +++ b/src/htmlattrib.h @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -15,63 +15,19 @@ #ifndef _HTMLATTRIB_H #define _HTMLATTRIB_H +#include #include -#include -/*! A Html option. A name, value pair */ +/*! \brief Class reprenting a HTML attibute. */ struct HtmlAttrib { QCString name; QCString value; }; -/*! @brief A list of Html attributes. - * - * The Html attributes are deeply copied into the list. - */ -class HtmlAttribList : public QList -{ - public: - HtmlAttribList() : QList() { setAutoDelete(TRUE); } - ~HtmlAttribList() { clear(); } - HtmlAttribList(const HtmlAttribList &l) : QList() - { operator=(l); } - HtmlAttribList &operator=(const HtmlAttribList &l) - { clear(); QList::operator=(l); return *this; } - QCString find(const QCString name) const - { - QListIterator it(*this); - QCString result; - HtmlAttrib *attr; - for (;(attr=it.current());++it) - { - if (attr->name==name) return attr->value; - } - return result; - } - QCString toString() const - { - QListIterator it(*this); - QCString result; - HtmlAttrib *attr; - for (;(attr=it.current());++it) - { - result+=" "+attr->name+"=\""+attr->value+"\""; - } - return result; - } - private: - HtmlAttrib *newValue( HtmlAttrib *v ) const - { return new HtmlAttrib(*v); } - void deleteValue(HtmlAttrib *v) const - { delete v; } -}; - -/*! @brief Html attribute list iterator */ -class HtmlAttribListIterator : public QListIterator +/*! \brief Class representing a list of HTML attributes. */ +class HtmlAttribList : public std::vector { - public: - HtmlAttribListIterator(const HtmlAttribList &l) : QListIterator(l) {} }; #endif diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp index daf6a39..9b11685 100644 --- a/src/htmldocvisitor.cpp +++ b/src/htmldocvisitor.cpp @@ -213,30 +213,19 @@ static bool isInvisibleNode(const DocNode *node) ; } -static void mergeHtmlAttributes(const HtmlAttribList &attribs, HtmlAttribList *mergeInto) +static void mergeHtmlAttributes(const HtmlAttribList &attribs, HtmlAttribList &mergeInto) { - HtmlAttribListIterator li(attribs); - HtmlAttrib *att; - for (li.toFirst();(att=li.current());++li) + for (const auto &att : attribs) { - HtmlAttribListIterator ml(*mergeInto); - HtmlAttrib *opt; - bool found = false; - for (ml.toFirst();(opt=ml.current());++ml) + auto it = std::find_if(mergeInto.begin(),mergeInto.end(), + [&att](const auto &opt) { return opt.name==att.name; }); + if (it!=mergeInto.end()) // attribute name already in mergeInto { - if (opt->name == att -> name) - { - found = true; - break; - } + it->value = it->value + " " + att.value; } - if (found) - { - opt->value = opt->value + " " + att->value; - } - else + else // attribute name not yet in mergeInto { - mergeInto->append(att); + mergeInto.push_back(att); } } } @@ -244,31 +233,29 @@ static void mergeHtmlAttributes(const HtmlAttribList &attribs, HtmlAttribList *m static QCString htmlAttribsToString(const HtmlAttribList &attribs, QCString *pAltValue = 0) { QCString result; - HtmlAttribListIterator li(attribs); - HtmlAttrib *att; - for (li.toFirst();(att=li.current());++li) + for (const auto &att : attribs) { - if (!att->value.isEmpty()) // ignore attribute without values as they + if (!att.value.isEmpty()) // ignore attribute without values as they // are not XHTML compliant, with the exception // of the alt attribute with the img tag { - if (att->name=="alt" && pAltValue) // optionally return the value of alt separately + if (att.name=="alt" && pAltValue) // optionally return the value of alt separately // need to convert to for SVG images, // which do not support the alt attribute { - *pAltValue = att->value; + *pAltValue = att.value; } else { result+=" "; - result+=att->name; - result+="=\""+convertToXML(att->value)+"\""; + result+=att.name; + result+="=\""+convertToXML(att.value)+"\""; } } - else if (att->name=="nowrap") // In XHTML, attribute minimization is forbidden, and the nowrap attribute must be defined as . + else if (att.name=="nowrap") // In XHTML, attribute minimization is forbidden, and the nowrap attribute must be defined as . { result+=" "; - result+=att->name; + result+=att.name; result+="=\"nowrap\""; } } @@ -1726,10 +1713,10 @@ void HtmlDocVisitor::visitPre(DocImage *img) HtmlAttrib opt; opt.name = "style"; opt.value = "pointer-events: none;"; - extraAttribs.append(&opt); + extraAttribs.push_back(opt); } QCString alt; - mergeHtmlAttributes(img->attribs(),&extraAttribs); + mergeHtmlAttributes(img->attribs(),extraAttribs); QCString attrs = htmlAttribsToString(extraAttribs,&alt); QCString src; if (url.isEmpty()) diff --git a/src/latexdocvisitor.cpp b/src/latexdocvisitor.cpp index b456e4a..abdf116 100644 --- a/src/latexdocvisitor.cpp +++ b/src/latexdocvisitor.cpp @@ -949,20 +949,33 @@ void LatexDocVisitor::visitPost(DocHtmlListItem *) // m_t << "\\end{alltt}\\normalsize " << endl; //} + +static bool classEqualsReflist(const DocNode *n) +{ + if (n->kind()==DocNode::Kind_HtmlDescList) + { + HtmlAttribList attrs = ((DocHtmlDescList *)n)->attribs(); + auto it = std::find_if(attrs.begin(),attrs.end(), + [](const auto &att) { return att.name=="class"; }); + if (it!=attrs.end() && it->value == "reflist") return true; + } + return false; +} + + static bool listIsNested(const DocNode *n) { bool isNested=false; if (n) { - if (n->kind()==DocNode::Kind_HtmlDescList && ((DocHtmlDescList *)n)->attribs().find("class") == "reflist") return false; + if (classEqualsReflist(n)) return false; n = n->parent(); } while (n && !isNested) { if (n->kind()==DocNode::Kind_HtmlDescList) { - QCString val = ((DocHtmlDescList *)n)->attribs().find("class"); - isNested = (val!="reflist"); + isNested = !classEqualsReflist(n); } n = n->parent(); } @@ -972,8 +985,7 @@ static bool listIsNested(const DocNode *n) void LatexDocVisitor::visitPre(DocHtmlDescList *dl) { if (m_hide) return; - QCString val = dl->attribs().find("class"); - if (val=="reflist") + if (classEqualsReflist(dl)) { m_t << "\n\\begin{DoxyRefList}"; } @@ -987,8 +999,7 @@ void LatexDocVisitor::visitPre(DocHtmlDescList *dl) void LatexDocVisitor::visitPost(DocHtmlDescList *dl) { if (m_hide) return; - QCString val = dl->attribs().find("class"); - if (val=="reflist") + if (classEqualsReflist(dl)) { m_t << "\n\\end{DoxyRefList}"; } diff --git a/src/rtfdocvisitor.cpp b/src/rtfdocvisitor.cpp index f20a8a1..5b9b116 100644 --- a/src/rtfdocvisitor.cpp +++ b/src/rtfdocvisitor.cpp @@ -42,16 +42,12 @@ static QCString align(DocHtmlCell *cell) { - HtmlAttribList attrs = cell->attribs(); - uint i; - for (i=0; iattribs()) { - if (attrs.at(i)->name.lower()=="align") + if (attr.name.lower()=="align") { - if (attrs.at(i)->value.lower()=="center") - return "\\qc "; - else if (attrs.at(i)->value.lower()=="right") - return "\\qr "; + if (attr.value.lower()=="center") return "\\qc "; + else if (attr.value.lower()=="right") return "\\qr "; else return ""; } } diff --git a/src/xmldocvisitor.cpp b/src/xmldocvisitor.cpp index b9e3dae..43ca8c9 100644 --- a/src/xmldocvisitor.cpp +++ b/src/xmldocvisitor.cpp @@ -777,13 +777,11 @@ void XmlDocVisitor::visitPre(DocHtmlTable *t) if (m_hide) return; m_t << "numRows() << "\" cols=\"" << t->numColumns() << "\"" ; - HtmlAttribListIterator li(t->attribs()); - HtmlAttrib* opt; - for (li.toFirst(); (opt = li.current()); ++li) + for (const auto &opt : t->attribs()) { - if (opt->name=="width") + if (opt.name=="width") { - m_t << " " << opt->name << "=\"" << opt->value << "\""; + m_t << " " << opt.name << "=\"" << opt.value << "\""; } } m_t << ">"; @@ -811,49 +809,47 @@ void XmlDocVisitor::visitPre(DocHtmlCell *c) { if (m_hide) return; if (c->isHeading()) m_t << "attribs()); - HtmlAttrib *opt; - for (li.toFirst();(opt=li.current());++li) + for (const auto &opt : c->attribs()) { - if (opt->name=="colspan" || opt->name=="rowspan") + if (opt.name=="colspan" || opt.name=="rowspan") { - m_t << " " << opt->name << "=\"" << opt->value.toInt() << "\""; + m_t << " " << opt.name << "=\"" << opt.value.toInt() << "\""; } - else if (opt->name=="align" && - (opt->value=="right" || opt->value=="left" || opt->value=="center")) + else if (opt.name=="align" && + (opt.value=="right" || opt.value=="left" || opt.value=="center")) { - m_t << " align=\"" << opt->value << "\""; + m_t << " align=\"" << opt.value << "\""; } - else if (opt->name=="valign" && - (opt->value == "bottom" || opt->value == "top" || opt->value == "middle")) + else if (opt.name=="valign" && + (opt.value == "bottom" || opt.value == "top" || opt.value == "middle")) { - m_t << " valign=\"" << opt->value << "\""; + m_t << " valign=\"" << opt.value << "\""; } - else if (opt->name=="width") + else if (opt.name=="width") { - m_t << " width=\"" << opt->value << "\""; + m_t << " width=\"" << opt.value << "\""; } - else if (opt->name=="class") // handle markdown generated attributes + else if (opt.name=="class") // handle markdown generated attributes { - if (opt->value.left(13)=="markdownTable") // handle markdown generated attributes + if (opt.value.left(13)=="markdownTable") // handle markdown generated attributes { - if (opt->value.right(5)=="Right") + if (opt.value.right(5)=="Right") { m_t << " align='right'"; } - else if (opt->value.right(4)=="Left") + else if (opt.value.right(4)=="Left") { m_t << " align='left'"; } - else if (opt->value.right(6)=="Center") + else if (opt.value.right(6)=="Center") { m_t << " align='center'"; } // skip 'markdownTable*' value ending with "None" } - else if (!opt->value.isEmpty()) + else if (!opt.value.isEmpty()) { - m_t << " class=\"" << convertToXML(opt->value) << "\""; + m_t << " class=\"" << convertToXML(opt.value) << "\""; } } } @@ -928,7 +924,13 @@ void XmlDocVisitor::visitPre(DocImage *img) { baseName = correctURL(url,img->relPath()); } - visitPreStart(m_t, "image", FALSE, this, img->children(), baseName, TRUE, img->type(), img->width(), img->height(), img->attribs().find("alt"), img->isInlineImage()); + HtmlAttribList attribs = img->attribs(); + auto it = std::find_if(attribs.begin(),attribs.end(), + [](const auto &att) { return att.name=="alt"; }); + QCString altValue = it!=attribs.end() ? it->value : ""; + visitPreStart(m_t, "image", FALSE, this, img->children(), baseName, TRUE, + img->type(), img->width(), img->height(), + altValue, img->isInlineImage()); // copy the image to the output dir FileDef *fd; -- cgit v0.12