From 77a56dac2afe8987396052951986104af9efdbfe Mon Sep 17 00:00:00 2001 From: albert-github Date: Wed, 20 Jan 2021 15:56:22 +0100 Subject: Missing CLANG dependency For the tag `CLANG_ADD_INC_PATHS` the dependency to the rag `CLANG_ASSISTED_PARSING` was missing, giving in the doxywizard the wrong impression about this tag. --- src/config.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/config.xml b/src/config.xml index e25c94e..5ec34b3 100644 --- a/src/config.xml +++ b/src/config.xml @@ -1740,11 +1740,11 @@ to disable this feature. ]]> - + diff --git a/src/docparser.cpp b/src/docparser.cpp index 5e68c52..b63674a 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -512,7 +512,7 @@ static void checkRetvalName(const QCString &name) */ static void checkUnOrMultipleDocumentedParams() { - if (g_memberDef && g_hasParamCommand && Config_getBool(WARN_IF_DOC_ERROR)) + if (g_memberDef && g_hasParamCommand) { const ArgumentList &al=g_memberDef->isDocsForDefinition() ? g_memberDef->argumentList() : @@ -544,7 +544,7 @@ static void checkUnOrMultipleDocumentedParams() if (argName == par) count++; } } - if (count > 1) + if ((count > 1) && Config_getBool(WARN_IF_DOC_ERROR)) { warn_doc_error(g_memberDef->getDefFileName(), g_memberDef->getDefLine(), @@ -555,7 +555,7 @@ static void checkUnOrMultipleDocumentedParams() " has multiple @param documentation sections").data()); } } - if (notArgCnt>0) + if ((notArgCnt>0) && Config_getBool(WARN_IF_INCOMPLETE_DOC)) { bool first=TRUE; QCString errMsg= @@ -587,10 +587,10 @@ static void checkUnOrMultipleDocumentedParams() errMsg+=" parameter '"+argName+"'"; } } - warn_doc_error(g_memberDef->getDefFileName(), - g_memberDef->getDefLine(), - "%s", - substitute(errMsg,"%","%%").data()); + warn_incomplete_doc(g_memberDef->getDefFileName(), + g_memberDef->getDefLine(), + "%s", + substitute(errMsg,"%","%%").data()); } } } diff --git a/src/message.cpp b/src/message.cpp index 95a7553..5f06984 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -240,6 +240,14 @@ void warn_undoc(const char *file,int line,const char *fmt, ...) va_end(args); } +void warn_incomplete_doc(const char *file,int line,const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + do_warn(Config_getBool(WARN_IF_INCOMPLETE_DOC), file, line, warning_str, fmt, args); + va_end(args); +} + void warn_doc_error(const char *file,int line,const char *fmt, ...) { va_list args; diff --git a/src/message.h b/src/message.h index af49632..aa63ecb 100644 --- a/src/message.h +++ b/src/message.h @@ -29,6 +29,7 @@ extern void warn(const char *file,int line,const char *fmt, ...) PRINTFLIKE(3, 4 extern void va_warn(const char* file, int line, const char* fmt, va_list args); extern void warn_simple(const char *file,int line,const char *text); extern void warn_undoc(const char *file,int line,const char *fmt, ...) PRINTFLIKE(3, 4); +extern void warn_incomplete_doc(const char *file,int line,const char *fmt, ...) PRINTFLIKE(3, 4); extern void warn_doc_error(const char *file,int line,const char *fmt, ...) PRINTFLIKE(3, 4); extern void warn_uncond(const char *fmt, ...) PRINTFLIKE(1, 2); extern void err(const char *fmt, ...) PRINTFLIKE(1, 2); -- cgit v0.12 From 46ac1937a1bce5a163b78dff53408ad61db4d100 Mon Sep 17 00:00:00 2001 From: arwedus <70707249+arwedus@users.noreply.github.com> Date: Sat, 13 Feb 2021 22:00:38 +0100 Subject: fix typo in config.xml make docs failed because of outdated ref (I renamed the parameter to WARN_IF_INCOMPLETE_DOC to support generalizing the idea of "do not warn on incomplete doc of x". --- src/config.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.xml b/src/config.xml index c704916..7d5808a 100644 --- a/src/config.xml +++ b/src/config.xml @@ -1342,7 +1342,7 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn" documentation. If \ref cfg_extract_all "EXTRACT_ALL" is set to \c YES then this flag will automatically be disabled. - See also \ref cfg_warn_if_incomplete_paramdoc "WARN_IF_INCOMPLETE_PARAMDOC" + See also \ref cfg_warn_if_incomplete_doc "WARN_IF_INCOMPLETE_DOC" ]]> -- cgit v0.12 From 9e4d6df2e549c2251d2bd3a88431cec0b262fad8 Mon Sep 17 00:00:00 2001 From: albert-github Date: Tue, 16 Feb 2021 11:44:05 +0100 Subject: Get preprocessor output without line numbers For easier comparison of the original source with a doxygen preprocessed source the line numbers can be a bit of an obstacle. To remove the line numbers in the preprocessor output the option `NoLineno` has been added. (In case `Preprocessor` is not invoked, `NoLineno` has no effect). --- doc/preprocessing.doc | 4 ++++ src/debug.cpp | 3 ++- src/debug.h | 3 ++- src/pre.l | 5 +++-- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/doc/preprocessing.doc b/doc/preprocessing.doc index 4df83ff..5a297a7 100644 --- a/doc/preprocessing.doc +++ b/doc/preprocessing.doc @@ -259,6 +259,10 @@ you can run doxygen as follows: \verbatim doxygen -d Preprocessor \endverbatim +when the line numbers are no required: +\verbatim + doxygen -d Preprocessor -d NoLineno +\endverbatim This will instruct doxygen to dump the input sources to standard output after preprocessing has been done (Hint: set QUIET = YES and WARNINGS = NO in the configuration file to disable any other diff --git a/src/debug.cpp b/src/debug.cpp index c270b47..bc5abb2 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -31,6 +31,7 @@ static std::map< std::string, Debug::DebugMask > s_labels = { "functions", Debug::Functions }, { "variables", Debug::Variables }, { "preprocessor", Debug::Preprocessor }, + { "nolineno", Debug::NoLineNo }, { "classes", Debug::Classes }, { "commentcnv", Debug::CommentCnv }, { "commentscan", Debug::CommentScan }, @@ -79,7 +80,7 @@ static int labelToEnumValue(const char *l) int Debug::setFlag(const char *lab) { int retVal = labelToEnumValue(lab); - curMask = (DebugMask)(curMask | labelToEnumValue(lab)); + curMask = (DebugMask)(curMask | retVal); return retVal; } diff --git a/src/debug.h b/src/debug.h index e71595f..5d4717a 100644 --- a/src/debug.h +++ b/src/debug.h @@ -37,7 +37,8 @@ class Debug Lex = 0x00002000, Plantuml = 0x00004000, FortranFixed2Free = 0x00008000, - Cite = 0x00010000 + Cite = 0x00010000, + NoLineNo = 0x00020000 }; static void print(DebugMask mask,int prio,const char *fmt,...); diff --git a/src/pre.l b/src/pre.l index e817a9d..21746a0 100644 --- a/src/pre.l +++ b/src/pre.l @@ -3390,11 +3390,12 @@ void Preprocessor::processFile(const char *fileName,BufStr &input,BufStr &output char *newPos=output.data()+output.curPos(); Debug::print(Debug::Preprocessor,0,"Preprocessor output of %s (size: %d bytes):\n",fileName,newPos-orgPos); int line=1; - Debug::print(Debug::Preprocessor,0,"---------\n00001 "); + Debug::print(Debug::Preprocessor,0,"---------\n"); + if (!Debug::isFlagSet(Debug::NoLineNo)) Debug::print(Debug::Preprocessor,0,"00001 "); while (orgPos Date: Tue, 16 Feb 2021 15:43:14 +0100 Subject: Strange HTML tab title in case of a page without title In case we have an example like: ``` /// @page Bug_err /// /// \brief Some text in cpp file /// \details Some detailed text in cpp file ``` we will have as in the HTML tab: `Project Title: $title` as the page has an empty title. A better title would in this case be: `Project Title: Bug_err`. This has been implemented by setting the name of the page in the empty title. In case of a main page the xml output sets the empty title to the PROJECT_NAME, as the new, default, setting would see to it that also the mainpage with an empty title would be set we have to see that this is done beforehand. --- src/doxygen.cpp | 1 + src/pagedef.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/doxygen.cpp b/src/doxygen.cpp index f5a280b..b79e55b 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -8587,6 +8587,7 @@ static void findMainPage(Entry *root) //printf("mainpage: docLine=%d startLine=%d\n",root->docLine,root->startLine); //printf("Found main page! \n======\n%s\n=======\n",root->doc.data()); QCString title=root->args.stripWhiteSpace(); + if (title.isEmpty()) title = Config_getString(PROJECT_NAME); //QCString indexName=Config_getBool(GENERATE_TREEVIEW)?"main":"index"; QCString indexName="index"; Doxygen::mainPage.reset(createPageDef(root->docFile,root->docLine, diff --git a/src/pagedef.cpp b/src/pagedef.cpp index d3cf823..a3cc0b5 100644 --- a/src/pagedef.cpp +++ b/src/pagedef.cpp @@ -82,7 +82,7 @@ PageDef *createPageDef(const char *f,int l,const char *n,const char *d,const cha PageDefImpl::PageDefImpl(const char *f,int l,const char *n, const char *d,const char *t) - : DefinitionMixin(f,l,1,n), m_title(t) + : DefinitionMixin(f,l,1,n), m_title(t?t:n) { setDocumentation(d,f,l); m_pageScope = 0; -- cgit v0.12 From bcf2920bf17beb1b943d8d3b50309fa185d8ba5b Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Tue, 16 Feb 2021 19:43:55 +0100 Subject: Update preprocessing.doc --- doc/preprocessing.doc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/preprocessing.doc b/doc/preprocessing.doc index 5a297a7..34aa3ed 100644 --- a/doc/preprocessing.doc +++ b/doc/preprocessing.doc @@ -259,7 +259,7 @@ you can run doxygen as follows: \verbatim doxygen -d Preprocessor \endverbatim -when the line numbers are no required: +or when the line numbers are not wanted: \verbatim doxygen -d Preprocessor -d NoLineno \endverbatim -- cgit v0.12 From 7d828386b5658caef5d3086a71b0a42bbfdfa40c Mon Sep 17 00:00:00 2001 From: albert-github Date: Wed, 17 Feb 2021 11:09:48 +0100 Subject: Correct documentation redirection link The link to the C#-standard has changed, it is redirected to the new place. The new place is now used in the documentation. --- doc/xmlcmds.doc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/xmlcmds.doc b/doc/xmlcmds.doc index 3a58301..6cb78bd 100644 --- a/doc/xmlcmds.doc +++ b/doc/xmlcmds.doc @@ -18,7 +18,7 @@ Doxygen supports most of the XML commands that are typically used in C# code comments. The XML tags are defined in Appendix D of the -ECMA-334 +ECMA-334 standard, which defines the C# language. Unfortunately, the specification is not very precise and a number of the examples given are of poor quality. -- cgit v0.12 From 95b0c861caf58c8f4e2cdcc2c7506679668728bb Mon Sep 17 00:00:00 2001 From: albert-github Date: Fri, 19 Feb 2021 11:20:54 +0100 Subject: Correction end tag in documentation Small documentation correction (missing `/` in end tag). --- doc/trouble.doc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/trouble.doc b/doc/trouble.doc index 5405a81..a2e9be6 100644 --- a/doc/trouble.doc +++ b/doc/trouble.doc @@ -34,7 +34,7 @@ or unions with the same name in your code. It should not crash however, rather it should ignore all of the classes with the same name except one.
  • Some commands do not work inside the arguments of other commands. - Inside a HTML link (i.e. \...\) for instance + Inside a HTML link (i.e. \...\) for instance other commands (including other HTML commands) do not work! The sectioning commands are an important exception.
  • Redundant braces can confuse doxygen in some cases. -- cgit v0.12 From 52352ffd0713a666cf070ce859a11149f0453db5 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Wed, 10 Feb 2021 20:33:23 +0100 Subject: Improve handling of @param command without name or description --- src/docparser.cpp | 13 ++++++++----- src/doctokenizer.l | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/docparser.cpp b/src/docparser.cpp index b63674a..83887c6 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -4518,7 +4518,7 @@ int DocParamList::parse(const QCString &cmdName) { warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(saveCmdName)); - retval=0; + retval=RetVal_EndParBlock; goto endparamlist; } doctokenizerYYsetStateParam(); @@ -4556,14 +4556,17 @@ int DocParamList::parse(const QCString &cmdName) { warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment block while parsing the " "argument of command %s",qPrint(saveCmdName)); - retval=0; + retval=RetVal_EndParBlock; goto endparamlist; } if (tok!=TK_WHITESPACE) /* premature end of comment block */ { - warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token in comment block while parsing the " - "argument of command %s",qPrint(saveCmdName)); - retval=0; + if (tok!=TK_NEWPARA) /* empty param description */ + { + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token in comment block while parsing the " + "argument of command %s",qPrint(saveCmdName)); + } + retval=RetVal_EndParBlock; goto endparamlist; } diff --git a/src/doctokenizer.l b/src/doctokenizer.l index 0c167ca..a11f2fe 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -808,7 +808,7 @@ RCSID "$"("Author"|"Date"|"Header"|"Id"|"Locker"|"Log"|"Name"|"RCSfile"|"Revisio } lineCount(yytext,yyleng); } -({BLANK}*(\n|"\\ilinebr"))+{BLANK}*(\n|"\\ilinebr"){BLANK}* { +({BLANK}*(\n|"\\ilinebr"))+{BLANK}*(\n|"\\ilinebr"){BLANK}* { lineCount(yytext,yyleng); if (g_insidePre) { -- cgit v0.12 From 37deea7dc7f4d3e6d1df167471a01d3933a65602 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Mon, 8 Feb 2021 21:21:26 +0100 Subject: Refactoring: replace QRegExp by std::regex in util.cpp --- qtools/qcstring.h | 6 + src/doxygen.cpp | 16 +- src/growbuf.h | 10 + src/index.cpp | 8 +- src/memberdef.cpp | 12 +- src/pagedef.cpp | 2 +- src/perlmodgen.cpp | 2 +- src/sqlite3gen.cpp | 2 +- src/symbolresolver.cpp | 2 +- src/util.cpp | 778 ++++++++++++++++++++++++++++--------------------- src/util.h | 16 +- src/xmlgen.cpp | 6 +- 12 files changed, 492 insertions(+), 368 deletions(-) diff --git a/qtools/qcstring.h b/qtools/qcstring.h index 75bdf29..a70f8f4 100644 --- a/qtools/qcstring.h +++ b/qtools/qcstring.h @@ -358,6 +358,12 @@ class QCString return m_rep; } + QCString &operator+=( const std::string &str) + { + m_rep+=str; + return *this; + } + /** Appends string \a str to this string and returns a reference to the result. */ QCString &operator+=( const char *str ) { diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 28bb49b..744db35 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -14,7 +14,8 @@ */ #include -#include +#include +#include #include #include @@ -3916,7 +3917,7 @@ static void findUsedClassesForClass(const Entry *root, QCString templSpec; bool found=FALSE; // the type can contain template variables, replace them if present - type = substituteTemplateArgumentsInString(type,formalArgs,actualArgs); + type = substituteTemplateArgumentsInString(type.str(),formalArgs,actualArgs); //printf(" template substitution gives=%s\n",type.data()); while (!found && extractClassNameFromType(type,pos,usedClassName,templSpec,root->lang)!=-1) @@ -4075,7 +4076,7 @@ static void findBaseClassesForClass( formTemplateNames = getTemplateArgumentsInName(formalArgs,bi.name); } BaseInfo tbi = bi; - tbi.name = substituteTemplateArgumentsInString(bi.name,formalArgs,actualArgs); + tbi.name = substituteTemplateArgumentsInString(bi.name.str(),formalArgs,actualArgs); //printf("bi->name=%s tbi.name=%s\n",bi->name.data(),tbi.name.data()); if (mode==DocumentedOnly) @@ -4815,7 +4816,7 @@ static void computeTemplateClassRelations() } } - tbi.name = substituteTemplateArgumentsInString(bi.name,tl,templArgs); + tbi.name = substituteTemplateArgumentsInString(bi.name.str(),tl,templArgs); // find a documented base class in the correct scope if (!findClassRelation(root,cd,tcd,&tbi,actualTemplateNames,DocumentedOnly,FALSE)) { @@ -10072,9 +10073,10 @@ void initDoxygen() initResources(); const char *lang = Portable::getenv("LC_ALL"); if (lang) Portable::setenv("LANG",lang); - setlocale(LC_ALL,""); - setlocale(LC_CTYPE,"C"); // to get isspace(0xA0)==0, needed for UTF-8 - setlocale(LC_NUMERIC,"C"); + std::setlocale(LC_ALL,""); + std::setlocale(LC_CTYPE,"C"); // to get isspace(0xA0)==0, needed for UTF-8 + std::setlocale(LC_NUMERIC,"C"); + std::locale::global(std::locale("en_US.UTF-8")); Portable::correct_path(); diff --git a/src/growbuf.h b/src/growbuf.h index 2f8075b..bb26404 100644 --- a/src/growbuf.h +++ b/src/growbuf.h @@ -3,6 +3,7 @@ #include #include +#include #define GROW_AMOUNT 1024 @@ -27,6 +28,15 @@ class GrowBuf m_pos+=l; } } + void addStr(const std::string &s) { + if (!s.empty()) + { + uint l=(uint)s.length(); + if (m_pos+l>=m_len) { m_len+=l+GROW_AMOUNT; m_str = (char*)realloc(m_str,m_len); } + strcpy(&m_str[m_pos],s.c_str()); + m_pos+=l; + } + } void addStr(const char *s) { if (s) { diff --git a/src/index.cpp b/src/index.cpp index 1f425d4..1e35b30 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -3465,7 +3465,7 @@ static void writeExampleIndex(OutputList &ol) ol.writeObjectLink(0,n,0,pd->title()); if (addToIndex) { - Doxygen::indexList->addContentsItem(FALSE,filterTitle(pd->title()),pd->getReference(),n,0,FALSE,TRUE); + Doxygen::indexList->addContentsItem(FALSE,filterTitle(pd->title().str()),pd->getReference(),n,0,FALSE,TRUE); } } else @@ -3516,7 +3516,7 @@ static bool mainPageHasOwnTitle() QCString title; if (Doxygen::mainPage) { - title = filterTitle(Doxygen::mainPage->title()); + title = filterTitle(Doxygen::mainPage->title().str()); } return !projectName.isEmpty() && mainPageHasTitle() && qstricmp(title,projectName)!=0; } @@ -3538,7 +3538,7 @@ static void writePages(const PageDef *pd,FTVHelp *ftv) if (pd->title().isEmpty()) pageTitle=pd->name(); else - pageTitle=filterTitle(pd->title()); + pageTitle=filterTitle(pd->title().str()); if (ftv) { @@ -4094,7 +4094,7 @@ static void writeIndex(OutputList &ol) } else if (Doxygen::mainPage) { - title = filterTitle(Doxygen::mainPage->title()); + title = filterTitle(Doxygen::mainPage->title().str()); } QCString indexName="index"; diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 7e58331..8d59880 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -4178,29 +4178,29 @@ MemberDefMutable *MemberDefImpl::createTemplateInstanceMember( // replace formal arguments with actuals for (Argument &arg : *actualArgList) { - arg.type = substituteTemplateArgumentsInString(arg.type,formalArgs,actualArgs); + arg.type = substituteTemplateArgumentsInString(arg.type.str(),formalArgs,actualArgs); } actualArgList->setTrailingReturnType( - substituteTemplateArgumentsInString(actualArgList->trailingReturnType(),formalArgs,actualArgs)); + substituteTemplateArgumentsInString(actualArgList->trailingReturnType().str(),formalArgs,actualArgs)); } QCString methodName=name(); if (methodName.left(9)=="operator ") // conversion operator { - methodName=substituteTemplateArgumentsInString(methodName,formalArgs,actualArgs); + methodName=substituteTemplateArgumentsInString(methodName.str(),formalArgs,actualArgs); } MemberDefMutable *imd = createMemberDef( getDefFileName(),getDefLine(),getDefColumn(), - substituteTemplateArgumentsInString(m_impl->type,formalArgs,actualArgs), + substituteTemplateArgumentsInString(m_impl->type.str(),formalArgs,actualArgs), methodName, - substituteTemplateArgumentsInString(m_impl->args,formalArgs,actualArgs), + substituteTemplateArgumentsInString(m_impl->args.str(),formalArgs,actualArgs), m_impl->exception, m_impl->prot, m_impl->virt, m_impl->stat, m_impl->related, m_impl->mtype, ArgumentList(), ArgumentList(), "" ); imd->moveArgumentList(std::move(actualArgList)); - imd->setDefinition(substituteTemplateArgumentsInString(m_impl->def,formalArgs,actualArgs)); + imd->setDefinition(substituteTemplateArgumentsInString(m_impl->def.str(),formalArgs,actualArgs)); imd->setBodyDef(getBodyDef()); imd->setBodySegment(getDefLine(),getStartBodyLine(),getEndBodyLine()); //imd->setBodyMember(this); diff --git a/src/pagedef.cpp b/src/pagedef.cpp index d3cf823..0c34f08 100644 --- a/src/pagedef.cpp +++ b/src/pagedef.cpp @@ -288,7 +288,7 @@ void PageDefImpl::writeDocumentation(OutputList &ol) ol.popGeneratorState(); //1.} - Doxygen::indexList->addIndexItem(this,0,0,filterTitle(title())); + Doxygen::indexList->addIndexItem(this,0,0,filterTitle(title().str())); } void PageDefImpl::writePageDocumentation(OutputList &ol) const diff --git a/src/perlmodgen.cpp b/src/perlmodgen.cpp index 20bd01b..4cf0d4a 100644 --- a/src/perlmodgen.cpp +++ b/src/perlmodgen.cpp @@ -2144,7 +2144,7 @@ void PerlModGenerator::generatePerlModForPage(PageDef *pd) const SectionInfo *si = SectionManager::instance().find(pd->name()); if (si) - m_output.addFieldQuotedString("title4", filterTitle(si->title())); + m_output.addFieldQuotedString("title4", filterTitle(si->title().str())); addPerlModDocBlock(m_output,"detailed",pd->docFile(),pd->docLine(),0,0,pd->documentation()); m_output.closeHash(); diff --git a/src/sqlite3gen.cpp b/src/sqlite3gen.cpp index cc53b13..222b076 100644 --- a/src/sqlite3gen.cpp +++ b/src/sqlite3gen.cpp @@ -2348,7 +2348,7 @@ static void generateSqlite3ForPage(const PageDef *pd,bool isExample) { if (mainPageHasTitle()) { - title = filterTitle(convertCharEntitiesToUTF8(Doxygen::mainPage->title())); + title = filterTitle(convertCharEntitiesToUTF8(Doxygen::mainPage->title()).str()); } else { diff --git a/src/symbolresolver.cpp b/src/symbolresolver.cpp index 9f80c15..dd9e0f7 100644 --- a/src/symbolresolver.cpp +++ b/src/symbolresolver.cpp @@ -521,7 +521,7 @@ const ClassDef *SymbolResolver::Private::newResolveTypedef( if (typeClass && typeClass->isTemplate() && actTemplParams && !actTemplParams->empty()) { - type = substituteTemplateArgumentsInString(type, + type = substituteTemplateArgumentsInString(type.str(), typeClass->templateArguments(),actTemplParams); } QCString typedefValue = type; diff --git a/src/util.cpp b/src/util.cpp index 3bf349a..a7f4630 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -15,20 +15,23 @@ */ #include -#include #include #include #include -#include #include -#include #include #include +#include +#include +#include +#include +#include +#include +#include #include "md5.h" -#include #include #include @@ -158,54 +161,68 @@ const int maxInheritanceDepth = 100000; "bla @1" => "bla" \endverbatim */ -QCString removeAnonymousScopes(const QCString &s) +QCString removeAnonymousScopes(const char *str) { - QCString result; - if (s.isEmpty()) return result; - static QRegExp re("[ :]*@[0-9]+[: ]*"); - int i,l,sl=s.length(); - int p=0; - while ((i=re.match(s,p,&l))!=-1) + std::string result; + if (str==0) return result; + + // helper to check if the found delimiter starts with a colon + auto startsWithColon = [](const std::string &del) { - result+=s.mid(p,i-p); - int c=i; - bool b1=FALSE,b2=FALSE; - while (c=i && s.at(c)!='@') if (s.at(c--)==':') b2=TRUE; - if (b1 && b2) + for (size_t i=0;i=0;i--) { - result+=replacement; + if (del[i]=='@') return false; + else if (del[i]==':') return true; } - else + return false; + }; + + static std::regex re("[ :]*@[[:digit:]]+[: ]*"); + std::string s = str; + std::sregex_iterator iter( s.begin(), s.end(), re); + std::sregex_iterator end; + size_t p=0; + size_t sl=s.length(); + bool needsSeparator=false; + for ( ; iter!=end ; ++iter) + { + const auto &match = *iter; + size_t i = match.position(); + if (i>p) // add non-matching prefix { - result+="__anonymous__"; + if (needsSeparator) result+="::"; + needsSeparator=false; + result+=s.substr(p,i-p); } - p=i+l; + std::string delim = match.str(); + needsSeparator = needsSeparator || (startsWithColon(delim) && endsWithColon(delim)); + p = match.position()+match.length(); + } + if (pname().data():"", // fileScope?fileScope->name().data():"", // txtStr.data(),strLen,external); - int matchLen; - int index=0; - int newIndex; - int skipIndex=0; - int floatingIndex=0; - // read a word from the text string - while ((newIndex=regExp.match(txtStr,index,&matchLen))!=-1) - { + size_t index=0; + size_t skipIndex=0; + size_t floatingIndex=0; + for (; it!=end ; ++it) // for each word from the text string + { + const auto &match = *it; + size_t newIndex = match.position(); + size_t matchLen = match.length(); floatingIndex+=newIndex-skipIndex+matchLen; if (newIndex>0 && txtStr.at(newIndex-1)=='0') // ignore hex numbers (match x00 in 0x00) { - out.writeString(txtStr.mid(skipIndex,newIndex+matchLen-skipIndex),keepSpaces); + std::string part = txtStr.substr(skipIndex,newIndex+matchLen-skipIndex); + out.writeString(part.c_str(),keepSpaces); skipIndex=index=newIndex+matchLen; continue; } // add non-word part to the result bool insideString=FALSE; - int i; - for (i=index;i35 && floatingIndex>30 && autoBreak) // try to insert a split point { - QCString splitText = txtStr.mid(skipIndex,newIndex-skipIndex); - int splitLength = splitText.length(); - int offset=1; - i=splitText.find(regExpSplit,0); - if (i==-1) { i=splitText.find('<'); if (i!=-1) offset=0; } - if (i==-1) i=splitText.find('>'); - if (i==-1) i=splitText.find(' '); + std::string splitText = txtStr.substr(skipIndex,newIndex-skipIndex); + size_t splitLength = splitText.length(); + size_t offset=1; + size_t i = splitText.find(','); + if (i==std::string::npos) { i=splitText.find('<'); if (i!=std::string::npos) offset=0; } + if (i==std::string::npos) i=splitText.find('>'); + if (i==std::string::npos) i=splitText.find(' '); //printf("splitText=[%s] len=%d i=%d offset=%d\n",splitText.data(),splitLength,i,offset); - if (i!=-1) // add a link-break at i in case of Html output + if (i!=std::string::npos) // add a link-break at i in case of Html output { - out.writeString(splitText.left(i+offset),keepSpaces); + std::string part1 = splitText.substr(0,i+offset); + out.writeString(part1.c_str(),keepSpaces); out.writeBreak(indentLevel==0 ? 0 : indentLevel+1); - out.writeString(splitText.right(splitLength-i-offset),keepSpaces); + std::string part2 = splitText.substr(i+offset); + out.writeString(part2.c_str(),keepSpaces); floatingIndex=splitLength-i-offset+matchLen; } else { - out.writeString(splitText,keepSpaces); + out.writeString(splitText.c_str(),keepSpaces); } } else { //ol.docify(txtStr.mid(skipIndex,newIndex-skipIndex)); - out.writeString(txtStr.mid(skipIndex,newIndex-skipIndex),keepSpaces); + std::string part = txtStr.substr(skipIndex,newIndex-skipIndex); + out.writeString(part.c_str(),keepSpaces); } // get word from string - QCString word=txtStr.mid(newIndex,matchLen); + std::string word=txtStr.substr(newIndex,matchLen); QCString matchWord = substitute(substitute(word,"\\","::"),".","::"); //printf("linkifyText word=%s matchWord=%s scope=%s\n", // word.data(),matchWord.data(),scope?scope->name().data():""); @@ -963,7 +986,7 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, out.writeLink(typeDef->getReference(), typeDef->getOutputFileBase(), typeDef->anchor(), - word); + word.c_str()); found=TRUE; } } @@ -976,7 +999,7 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, { if (cd!=self) { - out.writeLink(cd->getReference(),cd->getOutputFileBase(),cd->anchor(),word); + out.writeLink(cd->getReference(),cd->getOutputFileBase(),cd->anchor(),word.c_str()); found=TRUE; } } @@ -988,7 +1011,7 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, { if (cd!=self) { - out.writeLink(cd->getReference(),cd->getOutputFileBase(),cd->anchor(),word); + out.writeLink(cd->getReference(),cd->getOutputFileBase(),cd->anchor(),word.c_str()); found=TRUE; } } @@ -1048,7 +1071,7 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, if (!(scope && (scope->getLanguage() == SrcLangExt_Fortran) && md->isVariable() && (md->getLanguage() != SrcLangExt_Fortran))) { out.writeLink(md->getReference(),md->getOutputFileBase(), - md->anchor(),word); + md->anchor(),word.c_str()); //printf("found symbol %s\n",matchWord.data()); found=TRUE; } @@ -1058,7 +1081,7 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, if (!found) // add word to the result { - out.writeString(word,keepSpaces); + out.writeString(word.c_str(),keepSpaces); } // set next start point in the string //printf("index=%d/%d\n",index,txtStr.length()); @@ -1066,30 +1089,32 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, } // add last part of the string to the result. //ol.docify(txtStr.right(txtStr.length()-skipIndex)); - out.writeString(txtStr.right(txtStr.length()-skipIndex),keepSpaces); + std::string lastPart = txtStr.substr(skipIndex); + out.writeString(lastPart.c_str(),keepSpaces); } void writeExamples(OutputList &ol,const ExampleList &list) { - QCString exampleLine=theTranslator->trWriteList((int)list.size()); + std::string exampleLine=theTranslator->trWriteList((int)list.size()).str(); - //bool latexEnabled = ol.isEnabled(OutputGenerator::Latex); - //bool manEnabled = ol.isEnabled(OutputGenerator::Man); - //bool htmlEnabled = ol.isEnabled(OutputGenerator::Html); - QRegExp marker("@[0-9]+"); - int index=0,newIndex,matchLen; + static std::regex marker("@[[:digit:]]+"); + std::sregex_iterator it(exampleLine.begin(),exampleLine.end(),marker); + std::sregex_iterator end; + size_t index=0; // now replace all markers in inheritLine with links to the classes - while ((newIndex=marker.match(exampleLine,index,&matchLen))!=-1) + for ( ; it!=end ; ++it) { - bool ok; - ol.parseText(exampleLine.mid(index,newIndex-index)); - uint entryIndex = exampleLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - if (ok && entryIndex +static bool isMatchingWildcard(const StringType &input,size_t input_pos, + const StringType &pattern,size_t pattern_pos, + bool caseSensitive) +{ + // end of pattern reached + if (pattern_pos==pattern.length()) + { + // match iff also at the end of the input string + return input_pos==input.length(); + } + + // if we are at the end of the input string + if (input_pos==input.length()) + { + // match iff the remainer of the pattern is '*'s + for (size_t i=pattern_pos; i > conv; + return isMatchingWildcard(conv.from_bytes(input),0,conv.from_bytes(pattern),0,caseSensitive); + } + else // simple case were we can do byte matching for characters. + { + return isMatchingWildcard(input,0,pattern,0,caseSensitive); + } +} + static QCString getFilterFromList(const char *name,const StringVector &filterList,bool &found) { found=FALSE; @@ -1260,8 +1348,7 @@ static QCString getFilterFromList(const char *name,const StringVector &filterLis if (i_equals!=-1) { QCString filterPattern = fs.left(i_equals); - QRegExp fpat(filterPattern,Portable::fileSystemIsCaseSensitive(),TRUE); - if (fpat.match(name)!=-1) + if (isMatchingWildcard(name,filterPattern.str(),Portable::fileSystemIsCaseSensitive())) { // found a match! QCString filterName = fs.mid(i_equals+1); @@ -1818,8 +1905,6 @@ static QCString extractCanonicalType(const Definition *d,const FileDef *fs,QCStr //printf("extractCanonicalType(type=%s) start: def=%s file=%s\n",type.data(), // d ? d->name().data() : "",fs ? fs->name().data() : ""); - //static QRegExp id("[a-z_A-Z\\x80-\\xFF][:a-z_A-Z0-9\\x80-\\xFF]*"); - QCString canType; QCString templSpec,word; int i,p=0,pp=0; @@ -1848,17 +1933,25 @@ static QCString extractCanonicalType(const Definition *d,const FileDef *fs,QCStr // (i.e. type is not a template specialization) // then resolve any identifiers inside. { - static QRegExp re("[a-z_A-Z\\x80-\\xFF][a-z_A-Z0-9\\x80-\\xFF]*"); - int tp=0,tl,ti; + static std::regex re("[[:alpha:]_][[:alnum:]_]*"); + std::string ts = templSpec.str(); + std::sregex_iterator it(ts.begin(),ts.end(),re); + std::sregex_iterator end; + + size_t tp=0; // for each identifier template specifier //printf("adding resolved %s to %s\n",templSpec.data(),canType.data()); - while ((ti=re.match(templSpec,tp,&tl))!=-1) - { - canType += templSpec.mid(tp,ti-tp); - canType += getCanonicalTypeForIdentifier(d,fs,templSpec.mid(ti,tl),0); + for (; it!=end ; ++it) + { + const auto &match = *it; + size_t ti = match.position(); + size_t tl = match.length(); + std::string matchStr = match.str(); + canType += ts.substr(tp,ti-tp); + canType += getCanonicalTypeForIdentifier(d,fs,matchStr.c_str(),0); tp=ti+tl; } - canType+=templSpec.right(templSpec.length()-tp); + canType+=ts.substr(tp); } pp=p; @@ -3236,34 +3329,6 @@ void generateFileRef(OutputDocInterface &od,const char *name,const char *text) //---------------------------------------------------------------------- -#if 0 -QCString substituteClassNames(const QCString &s) -{ - int i=0,l,p; - QCString result; - if (s.isEmpty()) return result; - QRegExp r("[a-z_A-Z][a-z_A-Z0-9]*"); - while ((p=r.match(s,i,&l))!=-1) - { - QCString *subst; - if (p>i) result+=s.mid(i,p-i); - if ((subst=substituteDict[s.mid(p,l)])) - { - result+=*subst; - } - else - { - result+=s.mid(p,l); - } - i=p+l; - } - result+=s.mid(i,s.length()-i); - return result; -} -#endif - -//---------------------------------------------------------------------- - /** Cache element for the file name to FileDef mapping cache. */ struct FindFileCacheElem { @@ -4240,21 +4305,28 @@ QCString convertToLaTeX(const QCString &s,bool insideTabbing,bool keepSpaces) -QCString convertCharEntitiesToUTF8(const QCString &s) +QCString convertCharEntitiesToUTF8(const char *str) { - QCString result; - static QRegExp entityPat("&[a-zA-Z]+[0-9]*;"); + if (str==0) return QCString(); + + static std::regex re("&[[:alpha:]][[:alnum:]]*;"); + std::string s = str; + std::sregex_iterator it(s.begin(),s.end(),re); + std::sregex_iterator end; - if (s.length()==0) return result; GrowBuf growBuf; - int p,i=0,l; - while ((p=entityPat.match(s,i,&l))!=-1) + size_t p,i=0,l; + //while ((p=entityPat.match(s,i,&l))!=-1) + for (; it!=end ; ++it) { + const auto &match = *it; + p = match.position(); + l = match.length(); if (p>i) { - growBuf.addStr(s.mid(i,p-i)); + growBuf.addStr(s.substr(i,p-i)); } - QCString entity = s.mid(p,l); + std::string entity = match.str(); DocSymbol::SymType symType = HtmlEntityMapper::instance()->name2sym(entity); const char *code=0; if (symType!=DocSymbol::Sym_Unknown && (code=HtmlEntityMapper::instance()->utf8(symType))) @@ -4263,11 +4335,11 @@ QCString convertCharEntitiesToUTF8(const QCString &s) } else { - growBuf.addStr(s.mid(p,l)); + growBuf.addStr(entity); } i=p+l; } - growBuf.addStr(s.mid(i,s.length()-i)); + growBuf.addStr(s.substr(i)); growBuf.addChar(0); //printf("convertCharEntitiesToUTF8(%s)->%s\n",s.data(),growBuf.get()); return growBuf.get(); @@ -4400,71 +4472,71 @@ void addMembersToMemberGroup(MemberList *ml, * class \a name and a template argument list \a templSpec. If -1 is returned * there are no more matches. */ -int extractClassNameFromType(const QCString &type,int &pos,QCString &name,QCString &templSpec,SrcLangExt lang) +int extractClassNameFromType(const char *type,int &pos,QCString &name,QCString &templSpec,SrcLangExt lang) { - static const QRegExp re_norm("[a-z_A-Z\\x80-\\xFF][a-z_A-Z0-9:\\x80-\\xFF]*"); - static const QRegExp re_ftn("[a-z_A-Z\\x80-\\xFF][()=_a-z_A-Z0-9:\\x80-\\xFF]*"); - QRegExp re; + static std::regex re_norm("[[:alpha:]_][[:alnum:]_:]*"); + static std::regex re_fortran("[[:alpha:]_][[:alnum:]_:()=]*"); + static std::regex &re = re_norm; name.resize(0); templSpec.resize(0); - int i,l; - int typeLen=type.length(); + if (type==0) return -1; + size_t typeLen=qstrlen(type); if (typeLen>0) { if (lang == SrcLangExt_Fortran) { - if (type.at(pos)==',') return -1; - if (type.left(4).lower()=="type") + if (type[pos]==',') return -1; + if (QCString(type).left(4).lower()!="type") { - re = re_norm; + re = re_fortran; } - else - { - re = re_ftn; - } - } - else - { - re = re_norm; } + std::string part = type + pos; + std::sregex_iterator it(part.begin(),part.end(),re); + std::sregex_iterator end; - if ((i=re.match(type,pos,&l))!=-1) // for each class name in the type + if (it!=end) { - int ts=i+l; - int te=ts; - int tl=0; - while (type.at(ts)==' ' && ts') + if (type[te]=='>') { - if (te') te++; else brCount--; + if (te') te++; else brCount--; } te++; } } - name = type.mid(i,l); + name = match.str(); if (te>ts) { - templSpec = type.mid(ts,te-ts),tl+=te-ts; + templSpec = QCString(type).mid(ts,te-ts); + tl+=te-ts; pos=i+l+tl; } else // no template part { pos=i+l; } - //printf("extractClassNameFromType([in] type=%s,[out] pos=%d,[out] name=%s,[out] templ=%s)=TRUE\n", - // type.data(),pos,name.data(),templSpec.data()); + //printf("extractClassNameFromType([in] type=%s,[out] pos=%d,[out] name=%s,[out] templ=%s)=TRUE i=%d\n", + // type.data(),pos,name.data(),templSpec.data(),i); return i; } } @@ -4485,13 +4557,19 @@ QCString normalizeNonTemplateArgumentsInString( p++; QCString result = name.left(p); - static QRegExp re("[a-z:_A-Z\\x80-\\xFF][a-z:_A-Z0-9\\x80-\\xFF]*"); - int l,i; + static std::regex re("[[:alpha:]_:][[:alnum:]_:]*"); + std::string s = result.mid(p).str(); + std::sregex_iterator it(s.begin(),s.end(),re); + std::sregex_iterator end; + size_t pi=0; // for each identifier in the template part (e.g. B -> T) - while ((i=re.match(name,p,&l))!=-1) + for (; it!=end ; ++it) { - result += name.mid(p,i-p); - QCString n = name.mid(i,l); + const auto &match = *it; + size_t i = match.position(); + size_t l = match.length(); + result += s.substr(pi,i-pi); + std::string n = match.str(); bool found=FALSE; for (const Argument &formArg : formalArgs) { @@ -4505,7 +4583,7 @@ QCString normalizeNonTemplateArgumentsInString( { // try to resolve the type SymbolResolver resolver; - const ClassDef *cd = resolver.resolveClass(context,n); + const ClassDef *cd = resolver.resolveClass(context,n.c_str()); if (cd) { result+=cd->name(); @@ -4519,9 +4597,9 @@ QCString normalizeNonTemplateArgumentsInString( { result+=n; } - p=i+l; + pi=i+l; } - result+=name.right(name.length()-p); + result+=s.substr(pi); //printf("normalizeNonTemplateArgumentInString(%s)=%s\n",name.data(),result.data()); return removeRedundantWhiteSpace(result); } @@ -4534,21 +4612,27 @@ QCString normalizeNonTemplateArgumentsInString( * prevent recursive substitution. */ QCString substituteTemplateArgumentsInString( - const QCString &name, + const std::string &name, const ArgumentList &formalArgs, const std::unique_ptr &actualArgs) { //printf("substituteTemplateArgumentsInString(name=%s formal=%s actualArg=%s)\n", // name.data(),argListToString(formalArgs).data(),argListToString(actualArgs).data()); if (formalArgs.empty()) return name; - QCString result; - static QRegExp re("[a-z_A-Z\\x80-\\xFF][a-z_A-Z0-9:\\x80-\\xFF]*"); - int p=0,l,i; - // for each identifier in the base class name (e.g. B -> B and T) - while ((i=re.match(name,p,&l))!=-1) + std::string result; + + static std::regex re("[[:alpha:]_][[:alnum:]_:]*"); + std::sregex_iterator it(name.begin(),name.end(),re); + std::sregex_iterator end; + size_t p=0; + + for (; it!=end ; ++it) { - result += name.mid(p,i-p); - QCString n = name.mid(i,l); + const auto &match = *it; + size_t i = match.position(); + size_t l = match.length(); + if (i>p) result += name.substr(p,i-p); + std::string n = match.str(); ArgumentList::iterator actIt; if (actualArgs) { @@ -4616,7 +4700,7 @@ QCString substituteTemplateArgumentsInString( formArg.defval!=name /* to prevent recursion */ ) { - result += substituteTemplateArgumentsInString(formArg.defval,formalArgs,actualArgs)+" "; + result += substituteTemplateArgumentsInString(formArg.defval.str(),formalArgs,actualArgs)+" "; found=TRUE; } } @@ -4626,7 +4710,7 @@ QCString substituteTemplateArgumentsInString( formArg.defval!=name /* to prevent recursion */ ) { - result += substituteTemplateArgumentsInString(formArg.defval,formalArgs,actualArgs)+" "; + result += substituteTemplateArgumentsInString(formArg.defval.str(),formalArgs,actualArgs)+" "; found=TRUE; } if (actualArgs && actIt!=actualArgs->end()) @@ -4640,10 +4724,10 @@ QCString substituteTemplateArgumentsInString( } p=i+l; } - result+=name.right(name.length()-p); + result+=name.substr(p); //printf(" Inheritance relation %s -> %s\n", // name.data(),result.data()); - return result.stripWhiteSpace(); + return QCString(result).stripWhiteSpace(); } @@ -5354,36 +5438,55 @@ QCString stripPath(const char *s) } /** returns \c TRUE iff string \a s contains word \a w */ -bool containsWord(const QCString &s,const QCString &word) +bool containsWord(const char *str,const char *word) { - static QRegExp wordExp("[a-z_A-Z\\x80-\\xFF]+"); - int p=0,i,l; - while ((i=wordExp.match(s,p,&l))!=-1) + if (str==0 || word==0) return false; + static std::regex re("[[:alpha:]_]+"); + std::string s = str; + for (std::sregex_iterator it(s.begin(),s.end(),re) ; it!=std::sregex_iterator() ; ++it) { - if (s.mid(i,l)==word) return TRUE; - p=i+l; + if (it->str()==word) return true; } - return FALSE; + return false; } -bool findAndRemoveWord(QCString &s,const QCString &word) +/** removes occurrences of whole \a word from \a sentence, + * while keeps internal spaces and reducing multiple sequences of spaces. + * Example: sentence=` cat+ catfish cat cat concat cat`, word=`cat` returns: `+ catfish concat` + */ +bool findAndRemoveWord(QCString &sentence,const char *word) { - static QRegExp wordExp("[a-z_A-Z\\x80-\\xFF]+"); - int p=0,i,l; - while ((i=wordExp.match(s,p,&l))!=-1) + static std::regex re("[^[:alpha:]_]+"); + std::string s = sentence.str(); + std::sregex_token_iterator it(s.begin(),s.end(),re,{-1,0}); + std::sregex_token_iterator end; + + bool found=false; + std::string result; + bool keepSpaces=false; // skip leading whitespace + for (;it!=end;it++) { - if (s.mid(i,l)==word) + std::string part = it->str(); + bool whiteSpaceOnly = std::all_of(part.begin(),part.end(), + [](const auto ch) { return std::isspace(ch); }); + bool matchingWord = part==word; + if (!matchingWord && (keepSpaces || !whiteSpaceOnly)) { - if (i>0 && isspace((uchar)s.at(i-1))) - i--,l++; - else if (i+l<(int)s.length() && isspace((uchar)s.at(i+l))) - l++; - s = s.left(i)+s.mid(i+l); // remove word + spacing - return TRUE; + result+=part; + keepSpaces=!whiteSpaceOnly; // skip sequences of spaces + } + else if (matchingWord) + { + found=true; } - p=i+l; } - return FALSE; + + // trim trailing whitespace + result.erase(std::find_if(result.rbegin(), result.rend(), + [](const auto ch) { return !std::isspace(ch); }).base(), result.end()); + + sentence = result; + return found; } /** Special version of QCString::stripWhiteSpace() that only strips @@ -5433,25 +5536,6 @@ QCString stripLeadingAndTrailingEmptyLines(const QCString &s,int &docLine) return s.mid(li,bi-li); } -#if 0 -void stringToSearchIndex(const QCString &docBaseUrl,const QCString &title, - const QCString &str,bool priority,const QCString &anchor) -{ - static bool searchEngine = Config_getBool(SEARCHENGINE); - if (searchEngine) - { - Doxygen::searchIndex->setCurrentDoc(title,docBaseUrl,anchor); - static QRegExp wordPattern("[a-z_A-Z\\x80-\\xFF][a-z_A-Z0-9\\x80-\\xFF]*"); - int i,p=0,l; - while ((i=wordPattern.match(str,p,&l))!=-1) - { - Doxygen::searchIndex->addWord(str.mid(i,l),priority); - p=i+l; - } - } -} -#endif - //-------------------------------------------------------------------------- static std::unordered_map g_extLookup; @@ -5738,18 +5822,37 @@ int nextUtf8CharPosition(const QCString &utf8Str,uint len,uint startPos) } else if (c=='&') // skip over character entities { - static QRegExp re1("&#[0-9]+;"); // numerical entity - static QRegExp re2("&[A-Z_a-z]+;"); // named entity - int l1,l2; - int i1 = re1.match(utf8Str,startPos,&l1); - int i2 = re2.match(utf8Str,startPos,&l2); - if (i1!=-1) + int (*matcher)(int) = 0; + c = (uchar)utf8Str[startPos+bytes]; + if (c=='#') // numerical entity? + { + bytes++; + c = (uchar)utf8Str[startPos+bytes]; + if (c=='x') // hexadecimal entity? + { + bytes++; + matcher = std::isxdigit; + } + else // decimal entity + { + matcher = std::isdigit; + } + } + else if (std::isalnum(c)) // named entity? { - bytes=l1; + bytes++; + matcher = std::isalnum; + } + if (matcher) + { + while ((c = (uchar)utf8Str[startPos+bytes])!=0 && matcher(c)) + { + bytes++; + } } - else if (i2!=-1) + if (c!=';') { - bytes=l2; + bytes=1; // not a valid entity, reset bytes counter } } return startPos+bytes; @@ -5760,6 +5863,7 @@ QCString parseCommentAsText(const Definition *scope,const MemberDef *md, { QGString s; if (doc.isEmpty()) return s.data(); + //printf("parseCommentAsText(%s)\n",doc.data()); FTextStream t(&s); DocNode *root = validatingParseDoc(fileName,lineNr, (Definition*)scope,(MemberDef*)md,doc,FALSE,FALSE, @@ -5799,7 +5903,7 @@ QCString parseCommentAsText(const Definition *scope,const MemberDef *md, //-------------------------------------------------------------------------------------- static QCString expandAliasRec(StringUnorderedSet &aliasesProcessed, - const QCString s,bool allowRecursion=FALSE); + const std::string &s,bool allowRecursion=FALSE); struct Marker { @@ -5911,7 +6015,7 @@ static QCString replaceAliasArguments(StringUnorderedSet &aliasesProcessed, //printf("part before marker %d: '%s'\n",i,aliasValue.mid(p,m->pos-p).data()); if (m.number>0 && m.number<=(int)args.size()) // valid number { - result+=expandAliasRec(aliasesProcessed,args.at(m.number-1),TRUE); + result+=expandAliasRec(aliasesProcessed,args.at(m.number-1).str(),TRUE); //printf("marker index=%d pos=%d number=%d size=%d replacement %s\n",i,m->pos,m->number,m->size, // args.at(m->number-1)->data()); } @@ -5923,7 +6027,7 @@ static QCString replaceAliasArguments(StringUnorderedSet &aliasesProcessed, // expand the result again result = substitute(result,"\\{","{"); result = substitute(result,"\\}","}"); - result = expandAliasRec(aliasesProcessed,substitute(result,"\\,",",")); + result = expandAliasRec(aliasesProcessed,substitute(result,"\\,",",").str()); return result; } @@ -5950,19 +6054,27 @@ static QCString escapeCommas(const QCString &s) return result.data(); } -static QCString expandAliasRec(StringUnorderedSet &aliasesProcessed,const QCString s,bool allowRecursion) -{ - QCString result; - static QRegExp cmdPat("[\\\\@][a-z_A-Z][a-z_A-Z0-9]*"); - QCString value=s; - int i,p=0,l; - while ((i=cmdPat.match(value,p,&l))!=-1) - { - result+=value.mid(p,i-p); - QCString args = extractAliasArgs(value,i+l); +static QCString expandAliasRec(StringUnorderedSet &aliasesProcessed,const std::string &s,bool allowRecursion) +{ + //QCString result; + std::string result; + std::regex re("[\\\\@][[:alpha:]_][[:alnum:]_]*"); + std::sregex_iterator re_it(s.begin(),s.end(),re); + std::sregex_iterator end; + size_t p = 0; + //QCString value=s; + //int i,p=0,l; + //while ((i=cmdPat.match(value,p,&l))!=-1) + for ( ; re_it!=end ; ++re_it) + { + const auto &match = *re_it; + size_t i = match.position(); + size_t l = match.length(); + if (i>p) result+=s.substr(p,i-p); + QCString args = extractAliasArgs(s,i+l); bool hasArgs = !args.isEmpty(); // found directly after command int argsLen = args.length(); - QCString cmd = value.mid(i+1,l-1); + QCString cmd = match.str().substr(1); QCString cmdNoArgs = cmd; int numArgs=0; if (hasArgs) @@ -5996,7 +6108,7 @@ static QCString expandAliasRec(StringUnorderedSet &aliasesProcessed,const QCStri //printf("replace '%s'->'%s' args='%s'\n", // aliasText->data(),val.data(),args.data()); } - result+=expandAliasRec(aliasesProcessed,val); + result+=expandAliasRec(aliasesProcessed,val.str()).str(); if (!allowRecursion) aliasesProcessed.erase(cmd.str()); p=i+l; if (hasArgs) p+=argsLen+2; @@ -6004,11 +6116,11 @@ static QCString expandAliasRec(StringUnorderedSet &aliasesProcessed,const QCStri else // command is not an alias { //printf("not an alias!\n"); - result+=value.mid(i,l); + result+=match.str(); p=i+l; } } - result+=value.right(value.length()-p); + result+=s.substr(p); //printf("expandAliases '%s'->'%s'\n",s.data(),result.data()); return result; @@ -6069,7 +6181,7 @@ QCString resolveAliasCmd(const QCString aliasCmd) QCString result; StringUnorderedSet aliasesProcessed; //printf("Expanding: '%s'\n",aliasCmd.data()); - result = expandAliasRec(aliasesProcessed,aliasCmd); + result = expandAliasRec(aliasesProcessed,aliasCmd.str()); //printf("Expanding result: '%s'->'%s'\n",aliasCmd.data(),result.data()); return result; } @@ -6269,18 +6381,23 @@ bool readInputFile(const char *fileName,BufStr &inBuf,bool filter,bool isSourceC } // Replace %word by word in title -QCString filterTitle(const QCString &title) -{ - QCString tf; - static QRegExp re("%[A-Z_a-z]"); - int p=0,i,l; - while ((i=re.match(title,p,&l))!=-1) - { - tf+=title.mid(p,i-p); - tf+=title.mid(i+1,l-1); // skip % +QCString filterTitle(const std::string &title) +{ + std::string tf; + std::regex re("%[A-Z_A-z]"); + std::sregex_iterator it(title.begin(),title.end(),re); + std::sregex_iterator end; + size_t p = 0; + for (; it!=end ; ++it) + { + const auto &match = *it; + size_t i = match.position(); + size_t l = match.length(); + if (i>p) tf+=title.substr(p,i-p); + tf+=match.str().substr(1); // skip % p=i+l; } - tf+=title.right(title.length()-p); + tf+=title.substr(p); return tf; } @@ -6301,23 +6418,20 @@ bool patternMatch(const QFileInfo &fi,const StringVector &patList) if (!patList.empty()) { - QCString fn = fi.fileName().data(); - QCString fp = fi.filePath().data(); - QCString afp= fi.absFilePath().data(); + std::string fn = fi.fileName().data(); + std::string fp = fi.filePath().data(); + std::string afp= fi.absFilePath().data(); - for (const auto &pat: patList) + for (auto pattern: patList) { - QCString pattern = pat.c_str(); - if (!pattern.isEmpty()) + if (!pattern.empty()) { - int i=pattern.find('='); - if (i!=-1) pattern=pattern.left(i); // strip of the extension specific filter name - - QRegExp re(pattern,caseSenseNames,TRUE); + size_t i=pattern.find('='); + if (i!=std::string::npos) pattern=pattern.substr(0,i); // strip of the extension specific filter name - found = re.match(fn)!=-1 || - re.match(fp)!=-1 || - re.match(afp)!=-1; + found = isMatchingWildcard(fn,pattern,caseSenseNames) || + isMatchingWildcard(fp,pattern,caseSenseNames) || + isMatchingWildcard(afp,pattern,caseSenseNames); if (found) break; //printf("Matching '%s' against pattern '%s' found=%d\n", // fi->fileName().data(),pattern.data(),found); @@ -6327,36 +6441,6 @@ bool patternMatch(const QFileInfo &fi,const StringVector &patList) return found; } -#if 0 // move to HtmlGenerator::writeSummaryLink -void writeSummaryLink(OutputList &ol,const char *label,const char *title, - bool &first,const char *file) -{ - if (first) - { - ol.writeString("
    \n"); - first=FALSE; - } - else - { - ol.writeString(" |\n"); - } - if (file) - { - ol.writeString(""); - ol.writeString(title); - ol.writeString(""); -} -#endif - QCString externalLinkTarget(const bool parent) { static bool extLinksInWindow = Config_getBool(EXT_LINKS_IN_WINDOW); @@ -6429,18 +6513,24 @@ void writeColoredImgData(const char *dir,ColoredImgDataItem data[]) */ QCString replaceColorMarkers(const char *str) { - QCString result; - QCString s=str; - if (s.isEmpty()) return result; - static QRegExp re("##[0-9A-Fa-f][0-9A-Fa-f]"); + if (str==0) return QCString(); + std::string result; + std::string s=str; + static std::regex re("##[0-9A-Fa-f][0-9A-Fa-f]"); + std::sregex_iterator it(s.begin(),s.end(),re); + std::sregex_iterator end; static int hue = Config_getInt(HTML_COLORSTYLE_HUE); static int sat = Config_getInt(HTML_COLORSTYLE_SAT); static int gamma = Config_getInt(HTML_COLORSTYLE_GAMMA); - int i,l,sl=s.length(),p=0; - while ((i=re.match(s,p,&l))!=-1) - { - result+=s.mid(p,i-p); - QCString lumStr = s.mid(i+2,l-2); + size_t sl=s.length(); + size_t p=0; + for (; it!=end ; ++it) + { + const auto &match = *it; + size_t i = match.position(); + size_t l = match.length(); + if (i>p) result+=s.substr(p,i-p); + std::string lumStr = match.str().substr(2); #define HEXTONUM(x) (((x)>='0' && (x)<='9') ? ((x)-'0') : \ ((x)>='a' && (x)<='f') ? ((x)-'a'+10) : \ ((x)>='A' && (x)<='F') ? ((x)-'A'+10) : 0) @@ -6466,7 +6556,7 @@ QCString replaceColorMarkers(const char *str) result+=colStr; p=i+l; } - result+=s.right(sl-p); + if (p2) + std::regex re("\\[[ inout,]+\\]"); + std::string s = docs.str(); + std::sregex_iterator it(s.begin(),s.end(),re); + std::sregex_iterator end; + if (it!=end) { - // make dir the part inside [...] without separators - QCString dir=substitute(substitute(docs.mid(1,l-2)," ",""),",",""); - int inIndex, outIndex; - unsigned char ioMask=0; - if (( inIndex=dir.find( "in"))!=-1) dir.remove (inIndex,2),ioMask|=(1<<0); - if ((outIndex=dir.find("out"))!=-1) dir.remove(outIndex,3),ioMask|=(1<<1); - if (dir.isEmpty() && ioMask!=0) // only in and/or out attributes found + const auto &match = *it; + size_t p = match.position(); + size_t l = match.length(); + if (p==0 && l>2) { - docs = docs.mid(l); // strip attributes - if (ioMask==((1<<0)|(1<<1))) return "[in,out]"; - else if (ioMask==(1<<0)) return "[in]"; - else if (ioMask==(1<<1)) return "[out]"; + // make dir the part inside [...] without separators + std::string dir = match.str().substr(1,l-2); + // strip , and ' ' from dir + dir.erase(std::remove_if(dir.begin(),dir.end(), + [](const char c) { return c==' ' || c==','; } + ),dir.end()); + size_t inIndex, outIndex; + unsigned char ioMask=0; + if (( inIndex=dir.find( "in"))!=std::string::npos) dir.erase( inIndex,2),ioMask|=(1<<0); + if ((outIndex=dir.find("out"))!=std::string::npos) dir.erase(outIndex,3),ioMask|=(1<<1); + if (dir.empty() && ioMask!=0) // only in and/or out attributes found + { + docs = s.substr(l); // strip attributes + if (ioMask==((1<<0)|(1<<1))) return "[in,out]"; + else if (ioMask==(1<<0)) return "[in]"; + else if (ioMask==(1<<1)) return "[out]"; + } } } - return QCString(); + return ""; } //----------------------------------------------------------- diff --git a/src/util.h b/src/util.h index d70ef96..1e5a913 100644 --- a/src/util.h +++ b/src/util.h @@ -219,9 +219,9 @@ QCString substituteKeywords(const QCString &s,const char *title, int getPrefixIndex(const QCString &name); -QCString removeAnonymousScopes(const QCString &s); +QCString removeAnonymousScopes(const char *s); -QCString replaceAnonymousScopes(const QCString &s,const char *replacement=0); +QCString replaceAnonymousScopes(const char *s,const char *replacement=0); bool hasVisibleRoot(const BaseClassList &bcl); bool classHasVisibleChildren(const ClassDef *cd); @@ -263,7 +263,7 @@ void addMembersToMemberGroup(/* in,out */ MemberList *ml, /* in,out */ MemberGroupList *pMemberGroups, /* in */ const Definition *context); -int extractClassNameFromType(const QCString &type,int &pos, +int extractClassNameFromType(const char *type,int &pos, QCString &name,QCString &templSpec,SrcLangExt=SrcLangExt_Unknown); QCString normalizeNonTemplateArgumentsInString( @@ -272,7 +272,7 @@ QCString normalizeNonTemplateArgumentsInString( const ArgumentList &formalArgs); QCString substituteTemplateArgumentsInString( - const QCString &name, + const std::string &name, const ArgumentList &formalArgs, const std::unique_ptr &actualArgs); @@ -351,9 +351,9 @@ void createSubDirs(QDir &d); QCString stripPath(const char *s); -bool containsWord(const QCString &s,const QCString &word); +bool containsWord(const char *s,const char *word); -bool findAndRemoveWord(QCString &s,const QCString &word); +bool findAndRemoveWord(QCString &s,const char *word); QCString stripLeadingAndTrailingEmptyLines(const QCString &s,int &docLine); @@ -380,13 +380,13 @@ std::string expandAlias(const std::string &aliasName,const std::string &aliasVal void writeTypeConstraints(OutputList &ol,const Definition *d,const ArgumentList &al); -QCString convertCharEntitiesToUTF8(const QCString &s); +QCString convertCharEntitiesToUTF8(const char *s); void stackTrace(); bool readInputFile(const char *fileName,BufStr &inBuf, bool filter=TRUE,bool isSourceCode=FALSE); -QCString filterTitle(const QCString &title); +QCString filterTitle(const std::string &title); bool patternMatch(const QFileInfo &fi,const StringVector &patList); diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp index db62e1b..cf032d6 100644 --- a/src/xmlgen.cpp +++ b/src/xmlgen.cpp @@ -796,7 +796,7 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream ) { writeMemberTemplateLists(md,t); - QCString typeStr = md->typeString(); //replaceAnonymousScopes(md->typeString()); + QCString typeStr = md->typeString(); stripQualifiers(typeStr); t << " "; linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,typeStr); @@ -1728,7 +1728,7 @@ static void generateXMLForPage(PageDef *pd,FTextStream &ti,bool isExample) QCString title; if (mainPageHasTitle()) { - title = filterTitle(convertCharEntitiesToUTF8(Doxygen::mainPage->title())); + title = filterTitle(convertCharEntitiesToUTF8(Doxygen::mainPage->title()).str()); } else { @@ -1742,7 +1742,7 @@ static void generateXMLForPage(PageDef *pd,FTextStream &ti,bool isExample) const SectionInfo *si = SectionManager::instance().find(pd->name()); if (si) { - t << " " << convertToXML(convertCharEntitiesToUTF8(filterTitle(si->title()))) + t << " <title>" << convertToXML(filterTitle(convertCharEntitiesToUTF8(si->title()).str())) << "" << endl; } } -- cgit v0.12 From 46599bf9478f0c9690b8df635d0c6ff307953fdd Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Fri, 12 Feb 2021 19:31:58 +0100 Subject: Refactoring: replace QRegExp by std::regex in classdef.cpp --- src/classdef.cpp | 56 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/src/classdef.cpp b/src/classdef.cpp index 625f70f..9e8175b 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -17,10 +17,10 @@ #include #include +#include #include #include -#include #include "classdef.h" #include "classlist.h" #include "entry.h" @@ -1630,18 +1630,22 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const ol.startParagraph(); //parseText(ol,theTranslator->trInherits()+" "); - QCString inheritLine = theTranslator->trInheritsList((int)m_impl->inherits.size()); - QRegExp marker("@[0-9]+"); - int index=0,newIndex,matchLen; + std::string inheritLine = theTranslator->trInheritsList((int)m_impl->inherits.size()).str(); + static std::regex marker("@[[:digit:]]+"); + std::sregex_iterator it(inheritLine.begin(),inheritLine.end(),marker); + std::sregex_iterator end; + size_t index=0; // now replace all markers in inheritLine with links to the classes - while ((newIndex=marker.match(inheritLine,index,&matchLen))!=-1) + for ( ; it!=end ; ++it) { - ol.parseText(inheritLine.mid(index,newIndex-index)); - bool ok; - uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - BaseClassDef &bcd=m_impl->inherits.at(entryIndex); - if (ok) + const auto &match = *it; + size_t newIndex = match.position(); + size_t matchLen = match.length(); + ol.parseText(inheritLine.substr(index,newIndex-index)); + unsigned long entryIndex = std::stoul(match.str().substr(1)); + if (entryIndex<(unsigned long)m_impl->inherits.size()) { + BaseClassDef &bcd=m_impl->inherits[entryIndex]; ClassDef *cd=bcd.classDef; // use the class name but with the template arguments as given @@ -1663,11 +1667,11 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const } else { - err("invalid marker %d in inherits list!\n",entryIndex); + err("invalid marker %zu in inherits list!\n",entryIndex); } index=newIndex+matchLen; } - ol.parseText(inheritLine.right(inheritLine.length()-(uint)index)); + ol.parseText(inheritLine.substr(index)); ol.endParagraph(); } @@ -1675,18 +1679,22 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const if (!m_impl->inheritedBy.empty()) { ol.startParagraph(); - QCString inheritLine = theTranslator->trInheritedByList((int)m_impl->inheritedBy.size()); - QRegExp marker("@[0-9]+"); - int index=0,newIndex,matchLen; + std::string inheritLine = theTranslator->trInheritedByList((int)m_impl->inheritedBy.size()).str(); + static std::regex marker("@[[:digit:]]+"); + std::sregex_iterator it(inheritLine.begin(),inheritLine.end(),marker); + std::sregex_iterator end; + size_t index=0; // now replace all markers in inheritLine with links to the classes - while ((newIndex=marker.match(inheritLine,index,&matchLen))!=-1) + for ( ; it!=end ; ++it) { - ol.parseText(inheritLine.mid(index,newIndex-index)); - bool ok; - uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - BaseClassDef &bcd=m_impl->inheritedBy.at(entryIndex); - if (ok) + const auto &match = *it; + size_t newIndex = match.position(); + size_t matchLen = match.length(); + ol.parseText(inheritLine.substr(index,newIndex-index)); + unsigned long entryIndex = std::stoul(match.str().substr(1)); + if (entryIndex<(unsigned long)m_impl->inherits.size()) { + BaseClassDef &bcd=m_impl->inheritedBy[entryIndex]; ClassDef *cd=bcd.classDef; if (cd->isLinkable()) { @@ -1698,9 +1706,13 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const } writeInheritanceSpecifier(ol,bcd); } + else + { + err("invalid marker %zu in inheritedBy list!\n",entryIndex); + } index=newIndex+matchLen; } - ol.parseText(inheritLine.right(inheritLine.length()-(uint)index)); + ol.parseText(inheritLine.substr(index)); ol.endParagraph(); } -- cgit v0.12 From b800b3c6f464e0d5f86fa68c710426779cf9ba44 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Fri, 12 Feb 2021 20:01:00 +0100 Subject: Refactoring: replace QRegExp by std::regex in definition.cpp --- src/definition.cpp | 263 +++++++++++++++++++++++++++-------------------------- 1 file changed, 133 insertions(+), 130 deletions(-) diff --git a/src/definition.cpp b/src/definition.cpp index 88b5960..ad508ad 100644 --- a/src/definition.cpp +++ b/src/definition.cpp @@ -19,9 +19,9 @@ #include #include #include +#include #include -#include #include "md5.h" #include #include @@ -164,7 +164,7 @@ static bool matchExcludedSymbols(const char *name) { const StringVector &exclSyms = Config_getList(EXCLUDE_SYMBOLS); if (exclSyms.empty()) return FALSE; // nothing specified - QCString symName = name; + std::string symName = name; for (const auto &pat : exclSyms) { QCString pattern = pat.c_str(); @@ -176,15 +176,15 @@ static bool matchExcludedSymbols(const char *name) pattern=pattern.left(pattern.length()-1),forceEnd=TRUE; if (pattern.find('*')!=-1) // wildcard mode { - QRegExp re(substitute(pattern,"*",".*"),TRUE); - int pl; - int i = re.match(symName,0,&pl); - //printf(" %d = re.match(%s) pattern=%s pl=%d len=%d\n",i,symName.data(),pattern.data(),pl,symName.length()); - if (i!=-1) // wildcard match + std::regex re(substitute(pattern,"*",".*").str()); + std::sregex_iterator it(symName.begin(),symName.end(),re); + std::sregex_iterator end; + if (it!=end) // wildcard match { - uint ui=(uint)i; - uint sl=symName.length(); - // check if it is a whole word match + const auto &match = *it; + size_t ui = match.position(); + size_t pl = match.length(); + size_t sl = symName.length(); if ((ui==0 || pattern.at(0)=='*' || (!isId(symName.at(ui-1)) && !forceStart)) && (ui+pl==sl || pattern.at(pattern.length()-1)=='*' || (!isId(symName.at(ui+pl)) && !forceEnd)) ) @@ -196,12 +196,12 @@ static bool matchExcludedSymbols(const char *name) } else if (!pattern.isEmpty()) // match words { - int i = symName.find(pattern); - if (i!=-1) // we have a match! + size_t i = symName.find(pattern); + if (i!=std::string::npos) // we have a match! { - uint ui=(uint)i; - uint pl=pattern.length(); - uint sl=symName.length(); + size_t ui=i; + size_t pl=pattern.length(); + size_t sl=symName.length(); // check if it is a whole word match if ((ui==0 || (!isId(symName.at(ui-1)) && !forceStart)) && (ui+pl==sl || (!isId(symName.at(ui+pl)) && !forceEnd)) @@ -1212,137 +1212,141 @@ void DefinitionImpl::_writeSourceRefList(OutputList &ol,const char *scopeName, ol.parseText(text); ol.docify(" "); - QCString ldefLine=theTranslator->trWriteList((int)members.size()); - - QRegExp marker("@[0-9]+"); - uint index=0; - int matchLen; - int newIndex; - // now replace all markers in inheritLine with links to the classes - while ((newIndex=marker.match(ldefLine,index,&matchLen))!=-1) + std::string ldefLine=theTranslator->trWriteList((int)members.size()).str(); + static std::regex marker("@[[:digit:]]+"); + std::sregex_iterator it(ldefLine.begin(),ldefLine.end(),marker); + std::sregex_iterator end; + size_t index=0; + // now replace all markers in ldefLine with links to the members + for ( ; it!=end ; ++it) { - bool ok; - ol.parseText(ldefLine.mid(index,(uint)newIndex-index)); - uint entryIndex = ldefLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - const MemberDef *md=members.at(entryIndex); - if (ok && md) + const auto &match = *it; + size_t newIndex = match.position(); + size_t matchLen = match.length(); + ol.parseText(ldefLine.substr(index,newIndex-index)); + unsigned long entryIndex = std::stoul(match.str().substr(1)); + if (entryIndex<(unsigned long)members.size()) { - QCString scope=md->getScopeString(); - QCString name=md->name(); - //printf("class=%p scope=%s scopeName=%s\n",md->getClassDef(),scope.data(),scopeName); - if (!scope.isEmpty() && scope!=scopeName) - { - name.prepend(scope+getLanguageSpecificSeparator(m_impl->lang)); - } - if (!md->isObjCMethod() && - (md->isFunction() || md->isSlot() || - md->isPrototype() || md->isSignal() - ) - ) - { - name+="()"; - } - //DefinitionImpl *d = md->getOutputFileBase(); - //if (d==Doxygen::globalScope) d=md->getBodyDef(); - if (sourceBrowser && - !(md->isLinkable() && !refLinkSource) && - md->getStartBodyLine()!=-1 && - md->getBodyDef() - ) + const MemberDef *md=members[entryIndex]; + if (md) { - //printf("md->getBodyDef()=%p global=%p\n",md->getBodyDef(),Doxygen::globalScope); - // for HTML write a real link - ol.pushGeneratorState(); - //ol.disableAllBut(OutputGenerator::Html); - - ol.disable(OutputGenerator::Man); - if (!latexSourceCode) - { - ol.disable(OutputGenerator::Latex); - } - if (!docbookSourceCode) + QCString scope=md->getScopeString(); + QCString name=md->name(); + //printf("class=%p scope=%s scopeName=%s\n",md->getClassDef(),scope.data(),scopeName); + if (!scope.isEmpty() && scope!=scopeName) { - ol.disable(OutputGenerator::Docbook); + name.prepend(scope+getLanguageSpecificSeparator(m_impl->lang)); } - if (!rtfSourceCode) + if (!md->isObjCMethod() && + (md->isFunction() || md->isSlot() || + md->isPrototype() || md->isSignal() + ) + ) { - ol.disable(OutputGenerator::RTF); + name+="()"; } - const int maxLineNrStr = 10; - char anchorStr[maxLineNrStr]; - qsnprintf(anchorStr,maxLineNrStr,"l%05d",md->getStartBodyLine()); - //printf("Write object link to %s\n",md->getBodyDef()->getSourceFileBase().data()); - ol.writeObjectLink(0,md->getBodyDef()->getSourceFileBase(),anchorStr,name); - ol.popGeneratorState(); - - // for the other output formats just mention the name - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Html); - if (latexSourceCode) + //DefinitionImpl *d = md->getOutputFileBase(); + //if (d==Doxygen::globalScope) d=md->getBodyDef(); + if (sourceBrowser && + !(md->isLinkable() && !refLinkSource) && + md->getStartBodyLine()!=-1 && + md->getBodyDef() + ) { - ol.disable(OutputGenerator::Latex); - } - if (docbookSourceCode) - { - ol.disable(OutputGenerator::Docbook); - } - if (rtfSourceCode) - { - ol.disable(OutputGenerator::RTF); - } - ol.docify(name); - ol.popGeneratorState(); - } - else if (md->isLinkable() /*&& d && d->isLinkable()*/) - { - // for HTML write a real link - ol.pushGeneratorState(); - //ol.disableAllBut(OutputGenerator::Html); - ol.disable(OutputGenerator::Man); - if (!latexSourceCode) - { - ol.disable(OutputGenerator::Latex); - } - if (!docbookSourceCode) - { - ol.disable(OutputGenerator::Docbook); + //printf("md->getBodyDef()=%p global=%p\n",md->getBodyDef(),Doxygen::globalScope); + // for HTML write a real link + ol.pushGeneratorState(); + //ol.disableAllBut(OutputGenerator::Html); + + ol.disable(OutputGenerator::Man); + if (!latexSourceCode) + { + ol.disable(OutputGenerator::Latex); + } + if (!docbookSourceCode) + { + ol.disable(OutputGenerator::Docbook); + } + if (!rtfSourceCode) + { + ol.disable(OutputGenerator::RTF); + } + const int maxLineNrStr = 10; + char anchorStr[maxLineNrStr]; + qsnprintf(anchorStr,maxLineNrStr,"l%05d",md->getStartBodyLine()); + //printf("Write object link to %s\n",md->getBodyDef()->getSourceFileBase().data()); + ol.writeObjectLink(0,md->getBodyDef()->getSourceFileBase(),anchorStr,name); + ol.popGeneratorState(); + + // for the other output formats just mention the name + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Html); + if (latexSourceCode) + { + ol.disable(OutputGenerator::Latex); + } + if (docbookSourceCode) + { + ol.disable(OutputGenerator::Docbook); + } + if (rtfSourceCode) + { + ol.disable(OutputGenerator::RTF); + } + ol.docify(name); + ol.popGeneratorState(); } - if (!rtfSourceCode) + else if (md->isLinkable() /*&& d && d->isLinkable()*/) { - ol.disable(OutputGenerator::RTF); - } + // for HTML write a real link + ol.pushGeneratorState(); + //ol.disableAllBut(OutputGenerator::Html); + ol.disable(OutputGenerator::Man); + if (!latexSourceCode) + { + ol.disable(OutputGenerator::Latex); + } + if (!docbookSourceCode) + { + ol.disable(OutputGenerator::Docbook); + } + if (!rtfSourceCode) + { + ol.disable(OutputGenerator::RTF); + } - ol.writeObjectLink(md->getReference(), - md->getOutputFileBase(), - md->anchor(),name); - ol.popGeneratorState(); + ol.writeObjectLink(md->getReference(), + md->getOutputFileBase(), + md->anchor(),name); + ol.popGeneratorState(); - // for the other output formats just mention the name - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Html); - if (latexSourceCode) - { - ol.disable(OutputGenerator::Latex); - } - if (docbookSourceCode) - { - ol.disable(OutputGenerator::Docbook); + // for the other output formats just mention the name + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Html); + if (latexSourceCode) + { + ol.disable(OutputGenerator::Latex); + } + if (docbookSourceCode) + { + ol.disable(OutputGenerator::Docbook); + } + if (rtfSourceCode) + { + ol.disable(OutputGenerator::RTF); + } + ol.docify(name); + ol.popGeneratorState(); } - if (rtfSourceCode) + else { - ol.disable(OutputGenerator::RTF); + ol.docify(name); } - ol.docify(name); - ol.popGeneratorState(); - } - else - { - ol.docify(name); } } - index=(uint)newIndex+matchLen; + index=newIndex+matchLen; } - ol.parseText(ldefLine.right(ldefLine.length()-index)); + ol.parseText(ldefLine.substr(index)); ol.writeString("."); ol.endParagraph(); } @@ -1850,8 +1854,7 @@ QCString abbreviate(const char *s,const char *name) const StringVector &briefDescAbbrev = Config_getList(ABBREVIATE_BRIEF); for (const auto &p : briefDescAbbrev) { - QCString str = p.c_str(); - str.replace(QRegExp("\\$name"), scopelessName); // replace $name with entity name + QCString str = substitute(p.c_str(),"$name",scopelessName); // replace $name with entity name str += " "; stripWord(result,str); } -- cgit v0.12 From e3360f7b9ddff7ba3247ea1bbdb681fddc5a5afd Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Fri, 12 Feb 2021 20:36:47 +0100 Subject: Refactoring: reduce code duplication by using writeMarkerList function --- src/classdef.cpp | 103 +++++++++-------------- src/definition.cpp | 233 +++++++++++++++++++++++++---------------------------- src/memberdef.cpp | 111 ++++++++++++------------- src/util.cpp | 60 ++++++++------ src/util.h | 3 + 5 files changed, 237 insertions(+), 273 deletions(-) diff --git a/src/classdef.cpp b/src/classdef.cpp index 9e8175b..9636d97 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -1627,92 +1627,61 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const if (!m_impl->inherits.empty()) { - ol.startParagraph(); - //parseText(ol,theTranslator->trInherits()+" "); - - std::string inheritLine = theTranslator->trInheritsList((int)m_impl->inherits.size()).str(); - static std::regex marker("@[[:digit:]]+"); - std::sregex_iterator it(inheritLine.begin(),inheritLine.end(),marker); - std::sregex_iterator end; - size_t index=0; - // now replace all markers in inheritLine with links to the classes - for ( ; it!=end ; ++it) + auto replaceFunc = [this](OutputList &ol,size_t entryIndex) { - const auto &match = *it; - size_t newIndex = match.position(); - size_t matchLen = match.length(); - ol.parseText(inheritLine.substr(index,newIndex-index)); - unsigned long entryIndex = std::stoul(match.str().substr(1)); - if (entryIndex<(unsigned long)m_impl->inherits.size()) - { - BaseClassDef &bcd=m_impl->inherits[entryIndex]; - ClassDef *cd=bcd.classDef; + BaseClassDef &bcd=m_impl->inherits[entryIndex]; + ClassDef *cd=bcd.classDef; - // use the class name but with the template arguments as given - // in the inheritance relation - QCString displayName = insertTemplateSpecifierInScope( - cd->displayName(),bcd.templSpecifiers); + // use the class name but with the template arguments as given + // in the inheritance relation + QCString displayName = insertTemplateSpecifierInScope( + cd->displayName(),bcd.templSpecifiers); - if (cd->isLinkable()) - { - ol.writeObjectLink(cd->getReference(), - cd->getOutputFileBase(), - cd->anchor(), - displayName); - } - else - { - ol.docify(displayName); - } + if (cd->isLinkable()) + { + ol.writeObjectLink(cd->getReference(), + cd->getOutputFileBase(), + cd->anchor(), + displayName); } else { - err("invalid marker %zu in inherits list!\n",entryIndex); + ol.docify(displayName); } - index=newIndex+matchLen; - } - ol.parseText(inheritLine.substr(index)); + }; + + ol.startParagraph(); + writeMarkerList(ol, + theTranslator->trInheritsList((int)m_impl->inherits.size()).str(), + m_impl->inherits.size(), + replaceFunc); ol.endParagraph(); } // write subclasses if (!m_impl->inheritedBy.empty()) { - ol.startParagraph(); - std::string inheritLine = theTranslator->trInheritedByList((int)m_impl->inheritedBy.size()).str(); - static std::regex marker("@[[:digit:]]+"); - std::sregex_iterator it(inheritLine.begin(),inheritLine.end(),marker); - std::sregex_iterator end; - size_t index=0; - // now replace all markers in inheritLine with links to the classes - for ( ; it!=end ; ++it) + + auto replaceFunc = [this](OutputList &ol,size_t entryIndex) { - const auto &match = *it; - size_t newIndex = match.position(); - size_t matchLen = match.length(); - ol.parseText(inheritLine.substr(index,newIndex-index)); - unsigned long entryIndex = std::stoul(match.str().substr(1)); - if (entryIndex<(unsigned long)m_impl->inherits.size()) + BaseClassDef &bcd=m_impl->inheritedBy[entryIndex]; + ClassDef *cd=bcd.classDef; + if (cd->isLinkable()) { - BaseClassDef &bcd=m_impl->inheritedBy[entryIndex]; - ClassDef *cd=bcd.classDef; - if (cd->isLinkable()) - { - ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),cd->anchor(),cd->displayName()); - } - else - { - ol.docify(cd->displayName()); - } - writeInheritanceSpecifier(ol,bcd); + ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),cd->anchor(),cd->displayName()); } else { - err("invalid marker %zu in inheritedBy list!\n",entryIndex); + ol.docify(cd->displayName()); } - index=newIndex+matchLen; - } - ol.parseText(inheritLine.substr(index)); + writeInheritanceSpecifier(ol,bcd); + }; + + ol.startParagraph(); + writeMarkerList(ol, + theTranslator->trInheritedByList((int)m_impl->inheritedBy.size()).str(), + m_impl->inheritedBy.size(), + replaceFunc); ol.endParagraph(); } diff --git a/src/definition.cpp b/src/definition.cpp index ad508ad..7ee2314 100644 --- a/src/definition.cpp +++ b/src/definition.cpp @@ -1208,147 +1208,136 @@ void DefinitionImpl::_writeSourceRefList(OutputList &ol,const char *scopeName, { auto members = refMapToVector(membersMap); - ol.startParagraph("reference"); - ol.parseText(text); - ol.docify(" "); - - std::string ldefLine=theTranslator->trWriteList((int)members.size()).str(); - static std::regex marker("@[[:digit:]]+"); - std::sregex_iterator it(ldefLine.begin(),ldefLine.end(),marker); - std::sregex_iterator end; - size_t index=0; - // now replace all markers in ldefLine with links to the members - for ( ; it!=end ; ++it) + auto replaceFunc = [this,&members,scopeName](OutputList &ol,size_t entryIndex) { - const auto &match = *it; - size_t newIndex = match.position(); - size_t matchLen = match.length(); - ol.parseText(ldefLine.substr(index,newIndex-index)); - unsigned long entryIndex = std::stoul(match.str().substr(1)); - if (entryIndex<(unsigned long)members.size()) + const MemberDef *md=members[entryIndex]; + if (md) { - const MemberDef *md=members[entryIndex]; - if (md) + QCString scope=md->getScopeString(); + QCString name=md->name(); + //printf("class=%p scope=%s scopeName=%s\n",md->getClassDef(),scope.data(),scopeName); + if (!scope.isEmpty() && scope!=scopeName) + { + name.prepend(scope+getLanguageSpecificSeparator(m_impl->lang)); + } + if (!md->isObjCMethod() && + (md->isFunction() || md->isSlot() || + md->isPrototype() || md->isSignal() + ) + ) + { + name+="()"; + } + //DefinitionImpl *d = md->getOutputFileBase(); + //if (d==Doxygen::globalScope) d=md->getBodyDef(); + if (sourceBrowser && + !(md->isLinkable() && !refLinkSource) && + md->getStartBodyLine()!=-1 && + md->getBodyDef() + ) { - QCString scope=md->getScopeString(); - QCString name=md->name(); - //printf("class=%p scope=%s scopeName=%s\n",md->getClassDef(),scope.data(),scopeName); - if (!scope.isEmpty() && scope!=scopeName) + //printf("md->getBodyDef()=%p global=%p\n",md->getBodyDef(),Doxygen::globalScope); + // for HTML write a real link + ol.pushGeneratorState(); + //ol.disableAllBut(OutputGenerator::Html); + + ol.disable(OutputGenerator::Man); + if (!latexSourceCode) { - name.prepend(scope+getLanguageSpecificSeparator(m_impl->lang)); + ol.disable(OutputGenerator::Latex); } - if (!md->isObjCMethod() && - (md->isFunction() || md->isSlot() || - md->isPrototype() || md->isSignal() - ) - ) + if (!docbookSourceCode) { - name+="()"; + ol.disable(OutputGenerator::Docbook); } - //DefinitionImpl *d = md->getOutputFileBase(); - //if (d==Doxygen::globalScope) d=md->getBodyDef(); - if (sourceBrowser && - !(md->isLinkable() && !refLinkSource) && - md->getStartBodyLine()!=-1 && - md->getBodyDef() - ) + if (!rtfSourceCode) { - //printf("md->getBodyDef()=%p global=%p\n",md->getBodyDef(),Doxygen::globalScope); - // for HTML write a real link - ol.pushGeneratorState(); - //ol.disableAllBut(OutputGenerator::Html); - - ol.disable(OutputGenerator::Man); - if (!latexSourceCode) - { - ol.disable(OutputGenerator::Latex); - } - if (!docbookSourceCode) - { - ol.disable(OutputGenerator::Docbook); - } - if (!rtfSourceCode) - { - ol.disable(OutputGenerator::RTF); - } - const int maxLineNrStr = 10; - char anchorStr[maxLineNrStr]; - qsnprintf(anchorStr,maxLineNrStr,"l%05d",md->getStartBodyLine()); - //printf("Write object link to %s\n",md->getBodyDef()->getSourceFileBase().data()); - ol.writeObjectLink(0,md->getBodyDef()->getSourceFileBase(),anchorStr,name); - ol.popGeneratorState(); - - // for the other output formats just mention the name - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Html); - if (latexSourceCode) - { - ol.disable(OutputGenerator::Latex); - } - if (docbookSourceCode) - { - ol.disable(OutputGenerator::Docbook); - } - if (rtfSourceCode) - { - ol.disable(OutputGenerator::RTF); - } - ol.docify(name); - ol.popGeneratorState(); + ol.disable(OutputGenerator::RTF); } - else if (md->isLinkable() /*&& d && d->isLinkable()*/) + const int maxLineNrStr = 10; + char anchorStr[maxLineNrStr]; + qsnprintf(anchorStr,maxLineNrStr,"l%05d",md->getStartBodyLine()); + //printf("Write object link to %s\n",md->getBodyDef()->getSourceFileBase().data()); + ol.writeObjectLink(0,md->getBodyDef()->getSourceFileBase(),anchorStr,name); + ol.popGeneratorState(); + + // for the other output formats just mention the name + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Html); + if (latexSourceCode) { - // for HTML write a real link - ol.pushGeneratorState(); - //ol.disableAllBut(OutputGenerator::Html); - ol.disable(OutputGenerator::Man); - if (!latexSourceCode) - { - ol.disable(OutputGenerator::Latex); - } - if (!docbookSourceCode) - { - ol.disable(OutputGenerator::Docbook); - } - if (!rtfSourceCode) - { - ol.disable(OutputGenerator::RTF); - } + ol.disable(OutputGenerator::Latex); + } + if (docbookSourceCode) + { + ol.disable(OutputGenerator::Docbook); + } + if (rtfSourceCode) + { + ol.disable(OutputGenerator::RTF); + } + ol.docify(name); + ol.popGeneratorState(); + } + else if (md->isLinkable() /*&& d && d->isLinkable()*/) + { + // for HTML write a real link + ol.pushGeneratorState(); + //ol.disableAllBut(OutputGenerator::Html); + ol.disable(OutputGenerator::Man); + if (!latexSourceCode) + { + ol.disable(OutputGenerator::Latex); + } + if (!docbookSourceCode) + { + ol.disable(OutputGenerator::Docbook); + } + if (!rtfSourceCode) + { + ol.disable(OutputGenerator::RTF); + } - ol.writeObjectLink(md->getReference(), - md->getOutputFileBase(), - md->anchor(),name); - ol.popGeneratorState(); + ol.writeObjectLink(md->getReference(), + md->getOutputFileBase(), + md->anchor(),name); + ol.popGeneratorState(); - // for the other output formats just mention the name - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Html); - if (latexSourceCode) - { - ol.disable(OutputGenerator::Latex); - } - if (docbookSourceCode) - { - ol.disable(OutputGenerator::Docbook); - } - if (rtfSourceCode) - { - ol.disable(OutputGenerator::RTF); - } - ol.docify(name); - ol.popGeneratorState(); + // for the other output formats just mention the name + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Html); + if (latexSourceCode) + { + ol.disable(OutputGenerator::Latex); } - else + if (docbookSourceCode) { - ol.docify(name); + ol.disable(OutputGenerator::Docbook); } + if (rtfSourceCode) + { + ol.disable(OutputGenerator::RTF); + } + ol.docify(name); + ol.popGeneratorState(); + } + else + { + ol.docify(name); } } - index=newIndex+matchLen; - } - ol.parseText(ldefLine.substr(index)); + }; + + ol.startParagraph("reference"); + ol.parseText(text); + ol.docify(" "); + writeMarkerList(ol, + theTranslator->trWriteList((int)members.size()).str(), + members.size(), + replaceFunc); ol.writeString("."); ol.endParagraph(); + } ol.popGeneratorState(); } diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 8d59880..21892fb 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -13,6 +13,8 @@ * */ +#include + #include #include #include @@ -2790,76 +2792,69 @@ void MemberDefImpl::_writeReimplements(OutputList &ol) const void MemberDefImpl::_writeReimplementedBy(OutputList &ol) const { const MemberList &bml=reimplementedBy(); - if (!bml.empty()) + size_t count=0; + for (const auto &bmd : bml) { - uint count=0; - for (const auto &bmd : bml) + const ClassDef *bcd=bmd->getClassDef(); + // count the members that directly inherit from md and for + // which the member and class are visible in the docs. + if ( bcd && bmd->isLinkable() && bcd->isLinkable() ) { - const ClassDef *bcd=bmd->getClassDef(); - // count the members that directly inherit from md and for - // which the member and class are visible in the docs. - if ( bcd && bmd->isLinkable() && bcd->isLinkable() ) - { - count++; - } + count++; } - if (count>0) + } + if (count>0) + { + auto replaceFunc = [&bml](OutputList &ol,size_t entryIndex) { - // write the list of classes that overwrite this member - ol.startParagraph(); - - QCString reimplInLine; - if (m_impl->virt==Pure || (getClassDef() && getClassDef()->compoundType()==ClassDef::Interface)) - { - reimplInLine = theTranslator->trImplementedInList(count); - } - else - { - reimplInLine = theTranslator->trReimplementedInList(count); - } - static QRegExp marker("@[0-9]+"); - int index=0,newIndex,matchLen; - // now replace all markers in reimplInLine with links to the classes - while ((newIndex=marker.match(reimplInLine,index,&matchLen))!=-1) + size_t count=0; + auto it = bml.begin(); + // find the entryIndex-th documented entry in the inheritance list. + const MemberDef *bmd = 0; + const ClassDef *bcd = 0; + while (it!=bml.end()) { - ol.parseText(reimplInLine.mid(index,newIndex-index)); - bool ok; - uint entryIndex = reimplInLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - - count=0; - auto it = bml.begin(); - // find the entryIndex-th documented entry in the inheritance list. - const MemberDef *bmd = 0; - const ClassDef *bcd = 0; - while (it!=bml.end()) + bmd = *it; + bcd = bmd->getClassDef(); + if ( bmd->isLinkable() && bcd->isLinkable()) { - bmd = *it; - bcd = bmd->getClassDef(); - if ( bmd->isLinkable() && bcd->isLinkable()) - { - if (count==entryIndex) break; - count++; - } - ++it; + if (count==entryIndex) break; + count++; } + ++it; + } - if (ok && bcd && bmd) // write link for marker - { - //ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(), - // bmd->anchor(),bcd->name()); - ol.writeObjectLink(bmd->getReference(),bmd->getOutputFileBase(), - bmd->anchor(),bcd->displayName()); + if (bcd && bmd) // write link for marker + { + //ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(), + // bmd->anchor(),bcd->name()); + ol.writeObjectLink(bmd->getReference(),bmd->getOutputFileBase(), + bmd->anchor(),bcd->displayName()); - if (bmd->isLinkableInProject() ) - { - writePageRef(ol,bmd->getOutputFileBase(),bmd->anchor()); - } + if (bmd->isLinkableInProject() ) + { + writePageRef(ol,bmd->getOutputFileBase(),bmd->anchor()); } - index=newIndex+matchLen; } - ol.parseText(reimplInLine.right(reimplInLine.length()-index)); - ol.endParagraph(); + }; + + QCString reimplInLine; + if (m_impl->virt==Pure || (getClassDef() && getClassDef()->compoundType()==ClassDef::Interface)) + { + reimplInLine = theTranslator->trImplementedInList(count); + } + else + { + reimplInLine = theTranslator->trReimplementedInList(count); } + + // write the list of classes that overwrite this member + ol.startParagraph(); + writeMarkerList(ol, + reimplInLine.str(), + count, + replaceFunc); + ol.endParagraph(); } } diff --git a/src/util.cpp b/src/util.cpp index a7f4630..5f3dd8e 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1093,13 +1093,11 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, out.writeString(lastPart.c_str(),keepSpaces); } - -void writeExamples(OutputList &ol,const ExampleList &list) +void writeMarkerList(OutputList &ol,const std::string &markerText,size_t numMarkers, + std::function replaceFunc) { - std::string exampleLine=theTranslator->trWriteList((int)list.size()).str(); - static std::regex marker("@[[:digit:]]+"); - std::sregex_iterator it(exampleLine.begin(),exampleLine.end(),marker); + std::sregex_iterator it(markerText.begin(),markerText.end(),marker); std::sregex_iterator end; size_t index=0; // now replace all markers in inheritLine with links to the classes @@ -1108,32 +1106,42 @@ void writeExamples(OutputList &ol,const ExampleList &list) const auto &match = *it; size_t newIndex = match.position(); size_t matchLen = match.length(); - auto prefixPart = exampleLine.substr(index,newIndex-index); - ol.parseText(prefixPart); + ol.parseText(markerText.substr(index,newIndex-index)); unsigned long entryIndex = std::stoul(match.str().substr(1)); - if (entryIndex<(unsigned long)list.size()) + if (entryIndex<(unsigned long)numMarkers) { - const auto &e = list[entryIndex]; - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Latex); - ol.disable(OutputGenerator::RTF); - ol.disable(OutputGenerator::Docbook); - // link for Html / man - //printf("writeObjectLink(file=%s)\n",e->file.data()); - ol.writeObjectLink(0,e.file,e.anchor,e.name); - ol.popGeneratorState(); - - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Man); - ol.disable(OutputGenerator::Html); - // link for Latex / pdf with anchor because the sources - // are not hyperlinked (not possible with a verbatim environment). - ol.writeObjectLink(0,e.file,0,e.name); - ol.popGeneratorState(); + replaceFunc(ol,entryIndex); } index=newIndex+matchLen; } - ol.parseText(exampleLine.substr(index)); + ol.parseText(markerText.substr(index)); +} + +void writeExamples(OutputList &ol,const ExampleList &list) +{ + auto replaceFunc = [&list](OutputList &ol,size_t entryIndex) + { + const auto &e = list[entryIndex]; + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Latex); + ol.disable(OutputGenerator::RTF); + ol.disable(OutputGenerator::Docbook); + // link for Html / man + //printf("writeObjectLink(file=%s)\n",e->file.data()); + ol.writeObjectLink(0,e.file,e.anchor,e.name); + ol.popGeneratorState(); + + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Man); + ol.disable(OutputGenerator::Html); + // link for Latex / pdf with anchor because the sources + // are not hyperlinked (not possible with a verbatim environment). + ol.writeObjectLink(0,e.file,0,e.name); + ol.popGeneratorState(); + }; + + writeMarkerList(ol, theTranslator->trWriteList((int)list.size()).str(), list.size(), replaceFunc); + ol.writeString("."); } diff --git a/src/util.h b/src/util.h index 1e5a913..410a3ea 100644 --- a/src/util.h +++ b/src/util.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "types.h" @@ -395,6 +396,8 @@ QCString externalRef(const QCString &relPath,const QCString &ref,bool href); int nextUtf8CharPosition(const QCString &utf8Str,uint len,uint startPos); const char *writeUtf8Char(FTextStream &t,const char *s); +void writeMarkerList(OutputList &ol,const std::string &markerText,size_t numMarkers, + std::function replaceFunc); /** Data associated with a HSV colored image. */ struct ColoredImgDataItem -- cgit v0.12 From 7aec8d3d0b74aa0f9c9c90a1f3e5c33348b59917 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Fri, 12 Feb 2021 20:47:32 +0100 Subject: Refactoring: replace QRegExp by std::regex in template.cpp --- src/template.cpp | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/template.cpp b/src/template.cpp index a7d9bbb..d7587e6 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -20,9 +20,9 @@ #include #include #include +#include #include -#include #include #include "ftextstream.h" @@ -4184,26 +4184,32 @@ class TemplateNodeMarkers : public TemplateNodeCreator { TemplateListIntf::ConstIterator *it = list->createIterator(); c->push(); - QCString str = patternStr.toString(); - QRegExp marker("@[0-9]+"); // pattern for a marker, i.e. @0, @1 ... @12, etc - int index=0,newIndex,matchLen; - while ((newIndex=marker.match(str,index,&matchLen))!=-1) + std::string str = patternStr.toString().str(); + + static std::regex marker("@[[:digit:]]+"); + std::sregex_iterator re_it(str.begin(),str.end(),marker); + std::sregex_iterator end; + size_t index=0; + for ( ; re_it!=end ; ++re_it) { + const auto &match = *re_it; + size_t newIndex = match.position(); + size_t matchLen = match.length(); + std::string part = str.substr(index,newIndex-index); if (ci->needsRecoding()) { - ts << ci->recode(str.mid(index,newIndex-index)); // write text before marker + ts << ci->recode(part); // write text before marker } else { - ts << str.mid(index,newIndex-index); // write text before marker + ts << part; // write text before marker } - bool ok; - uint entryIndex = str.mid(newIndex+1,matchLen-1).toUInt(&ok); // get marker id + unsigned long entryIndex = std::stoul(match.str().substr(1)); TemplateVariant var; - uint i=0; + size_t i=0; // search for list element at position id for (it->toFirst(); (it->current(var)) && itoNext(),i++) {} - if (ok && i==entryIndex) // found element + if (i==entryIndex) // found element { TemplateAutoRef s(TemplateStruct::alloc()); s->set("id",(int)i); @@ -4214,10 +4220,6 @@ class TemplateNodeMarkers : public TemplateNodeCreator m_nodes.render(ts,c); ci->enableSpaceless(wasSpaceless); } - else if (!ok) - { - ci->warn(m_templateName,m_line,"markers pattern string has invalid markers '%s'",str.data()); - } else if (iwarn(m_templateName,m_line,"markers list does not an element for marker position %d",i); @@ -4226,11 +4228,11 @@ class TemplateNodeMarkers : public TemplateNodeCreator } if (ci->needsRecoding()) { - ts << ci->recode(str.right(str.length()-index)); // write text after last marker + ts << ci->recode(str.substr(index)); // write text after last marker } else { - ts << str.right(str.length()-index); // write text after last marker + ts << str.substr(index); // write text after last marker } c->pop(); delete it; -- cgit v0.12 From bcca6a94dd16f07c883fcd4c4d2026032afcda37 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Sat, 13 Feb 2021 13:38:47 +0100 Subject: Refactoring: replace QRegExp by std::regex in pre.l --- src/message.cpp | 55 ------------------------ src/pre.l | 128 +++++++++++++++++++++++++++++++++----------------------- 2 files changed, 75 insertions(+), 108 deletions(-) diff --git a/src/message.cpp b/src/message.cpp index 5f06984..6c7c8ac 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -25,12 +25,6 @@ static QCString outputFormat; static const char *warning_str = "warning: "; static const char *error_str = "error: "; -//static int warnFormatOrder; // 1 = $file,$line,$text -// // 2 = $text,$line,$file -// // 3 = $line,$text,$file -// // 4 = $file,$text,$line -// // 5 = $text,$file,$line -// // 6 = $line,$file,$text static FILE *warnFile = stderr; @@ -47,55 +41,6 @@ static std::mutex g_mutex; void initWarningFormat() { -// int filePos = Config_getString(WARN_FORMAT).find("$file"); -// int linePos = Config_getString(WARN_FORMAT).find("$line"); -// int textPos = Config_getString(WARN_FORMAT).find("$text"); -// -// // sort items on position (there are 6 cases) -// warnFormatOrder = 1; -// if (filePos>linePos && filePos>textPos) -// { -// if (linePos>textPos) // $text,$line,$file -// { -// warnFormatOrder = 2; -// } -// else // $line,$text,$file -// { -// warnFormatOrder = 3; -// } -// } -// else if (filePostextPos) // $file,$text,$line -// { -// warnFormatOrder = 4; -// } -// } -// else if (filePostextPos) // $text,$file,$line -// { -// warnFormatOrder = 5; -// } -// else // $line,$file,$text -// { -// warnFormatOrder = 6; -// } -// outputFormat = -// substitute( -// substitute( -// substitute( -// Config_getString(WARN_FORMAT), -// "$file","%s" -// ), -// "$text","%s" -// ), -// "$line","%d" -// )+'\n'; - - // replace(QRegExp("\\$file"),"%s"). - // replace(QRegExp("\\$text"),"%s"). - // replace(QRegExp("\\$line"),"%d")+ - // '\n'; - outputFormat = Config_getString(WARN_FORMAT); if (!Config_getString(WARN_LOGFILE).isEmpty()) diff --git a/src/pre.l b/src/pre.l index 21746a0..f7aca7f 100644 --- a/src/pre.l +++ b/src/pre.l @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -41,7 +42,6 @@ #include #include -#include #include #include "containers.h" @@ -1959,31 +1959,48 @@ static QCString stringize(const QCString &s) */ static void processConcatOperators(QCString &expr) { - //printf("processConcatOperators: in='%s'\n",expr.data()); - QRegExp r("[ \\t\\n]*##[ \\t\\n]*"); - int l,n,i=0; if (expr.isEmpty()) return; - while ((n=r.match(expr,i,&l))!=-1) + //printf("processConcatOperators: in='%s'\n",expr.data()); + std::string e = expr.str(); + static std::regex r("[[:space:]]*##[[:space:]]*"); + std::sregex_iterator end; + + size_t i=0; + for (;;) { - //printf("Match: '%s'\n",expr.data()+i); - if (n+l+1<(int)expr.length() && expr.at(n+l)=='@' && expr.at(n+l+1)=='-') + std::sregex_iterator it(e.begin()+i,e.end(),r); + if (it!=end) { - // remove no-rescan marker after ID - l+=2; + const auto &match = *it; + size_t n = i+match.position(); + size_t l = match.length(); + //printf("Match: '%s'\n",expr.data()+i); + if (n+l+1=0 && isId(e[k])) k--; + if (k>0 && e[k]=='-' && e[k-1]=='@') + { + // remove no-rescan marker before ID + e=e.substr(0,k-1)+e.substr(k+1); + n-=2; + } + i=n; } - //printf("found '%s'\n",expr.mid(n,l).data()); - // remove the ## operator and the surrounding whitespace - expr=expr.left(n)+expr.right(expr.length()-n-l); - int k=n-1; - while (k>=0 && isId(expr.at(k))) k--; - if (k>0 && expr.at(k)=='-' && expr.at(k-1)=='@') + else { - // remove no-rescan marker before ID - expr=expr.left(k-1)+expr.right(expr.length()-k-1); - n-=2; + break; } - i=n; } + + expr = e; + //printf("processConcatOperators: out='%s'\n",expr.data()); } @@ -3172,30 +3189,29 @@ static void initPredefined(yyscan_t yyscanner,const char *fileName) // add predefined macros const StringVector &predefList = Config_getList(PREDEFINED); - for (const auto &defStr : predefList) + for (const auto &ds : predefList) { - QCString ds = defStr.c_str(); - int i_equals=ds.find('='); - int i_obrace=ds.find('('); - int i_cbrace=ds.find(')'); - bool nonRecursive = i_equals>0 && ds.at(i_equals-1)==':'; + size_t i_equals=ds.find('='); + size_t i_obrace=ds.find('('); + size_t i_cbrace=ds.find(')'); + bool nonRecursive = i_equals!=std::string::npos && i_equals>0 && ds[i_equals-1]==':'; - if ((i_obrace==0) || (i_equals==0) || (i_equals==1 && ds.at(i_equals-1)==':')) + if ((i_obrace==0) || (i_equals==0) || (i_equals==1 && ds[i_equals-1]==':')) { continue; // no define name } if (i_obrace argMap; - QRegExp reId("[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*"); // regexp matching an id - if (ds.mid(i_obrace+1,i_cbrace-i_obrace-1)=="...") + if (ds.substr(i_obrace+1,i_cbrace-i_obrace-1)=="...") { varArgs = true; argMap.emplace("__VA_ARGS__",count); @@ -3203,14 +3219,18 @@ static void initPredefined(yyscan_t yyscanner,const char *fileName) } else { - //printf("predefined function macro '%s'\n",qPrint(ds.mid(i_obrace+1,i_cbrace-i_obrace-1))); - i=i_obrace+1; + size_t i=i_obrace+1; + //printf("predefined function macro '%s'\n",ds.c_str()); + std::sregex_iterator it(ds.begin()+i,ds.end(),reId); // gather the formal arguments in a dictionary - while (i0) // see bug375037 { - argMap.emplace(toStdString(ds.mid(pi,l)),count); + argMap.emplace(match.str(),count); count++; i=pi+l; } @@ -3218,18 +3238,24 @@ static void initPredefined(yyscan_t yyscanner,const char *fileName) { i++; } + ++it; } } // strip definition part - QCString tmp=ds.right(ds.length()-i_equals-1); - QCString definition; - i=0; + std::string definition; + std::string in=ds.substr(i_equals+1); + std::sregex_iterator re_it(in.begin(),in.end(),reId); + size_t i=0; // substitute all occurrences of formal arguments by their // corresponding markers - while ((pi=reId.match(tmp,i,&l))!=-1) + for (; re_it!=end; ++re_it) { - if (pi>i) definition+=tmp.mid(i,pi-i); - auto it = argMap.find(tmp.mid(pi,l).data()); + const auto &match = *re_it; + size_t pi = match.position(); + size_t l = match.length(); + if (pi>i) definition+=in.substr(i,pi-i); + + auto it = argMap.find(match.str()); if (it!=argMap.end()) { int argIndex = it->second; @@ -3239,15 +3265,15 @@ static void initPredefined(yyscan_t yyscanner,const char *fileName) } else { - definition+=tmp.mid(pi,l); + definition+=match.str(); } i=pi+l; } - if (i<(int)tmp.length()) definition+=tmp.mid(i,tmp.length()-i); + definition+=in.substr(i); // add define definition to the dictionary of defines for this file - QCString dname = ds.left(i_obrace); - if (!dname.isEmpty()) + std::string dname = ds.substr(0,i_obrace); + if (!dname.empty()) { Define def; def.name = dname; @@ -3263,16 +3289,12 @@ static void initPredefined(yyscan_t yyscanner,const char *fileName) //printf("#define '%s' '%s' #nargs=%d\n", // def->name.data(),def->definition.data(),def->nargs); } - } - else if ((i_obrace==-1 || i_obrace>i_equals) && - (i_cbrace==-1 || i_cbrace>i_equals) && - !ds.isEmpty() && (int)ds.length()>i_equals - ) // predefined non-function macro definition + else if (!ds.empty()) // predefined non-function macro definition { - //printf("predefined normal macro '%s'\n",defStr); + //printf("predefined normal macro '%s'\n",ds.c_str()); Define def; - if (i_equals==-1) // simple define without argument + if (i_equals==std::string::npos) // simple define without argument { def.name = ds; def.definition = "1"; // substitute occurrences by 1 (true) @@ -3280,8 +3302,8 @@ static void initPredefined(yyscan_t yyscanner,const char *fileName) else // simple define with argument { int ine=i_equals - (nonRecursive ? 1 : 0); - def.name = ds.left(ine); - def.definition = ds.right(ds.length()-i_equals-1); + def.name = ds.substr(0,ine); + def.definition = ds.substr(i_equals+1); } if (!def.name.isEmpty()) { -- cgit v0.12 From b6a6121a11d989c811d92d7f169be9f0da772438 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Sat, 13 Feb 2021 16:17:03 +0100 Subject: Refactoring: replace QRegExp by std::regex in configimpl.l --- src/configimpl.l | 52 +++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/src/configimpl.l b/src/configimpl.l index 83c4c89..1afe6d8 100644 --- a/src/configimpl.l +++ b/src/configimpl.l @@ -29,10 +29,10 @@ #include #include -#include #include #include +#include #include "configimpl.h" #include "version.h" @@ -1132,25 +1132,31 @@ void ConfigImpl::emptyValueToDefault() } } -static void substEnvVarsInString(QCString &s) +static void substEnvVarsInString(QCString &str) { - static QRegExp re("\\$\\([a-z_A-Z0-9.-]+\\)"); - static QRegExp re2("\\$\\([a-z_A-Z0-9.-]+\\([a-z_A-Z0-9.-]+\\)\\)"); // For e.g. PROGRAMFILES(X86) - if (s.isEmpty()) return; - int p=0; - int i,l; - //printf("substEnvVarInString(%s) start\n",s.data()); - while ((i=re.match(s,p,&l))!=-1 || (i=re2.match(s,p,&l))!=-1) + if (str.isEmpty()) return; + // match e.g. $(HOME) but also $(PROGRAMFILES(X86)) + static std::regex re("\\$\\([[:alpha:]_][[:alnum:].-]*(\\([[:alpha:]_][[:alnum:].-]*\\))?\\)"); + std::string s = str.str(); + std::sregex_iterator it(s.begin(),s.end(),re); + std::sregex_iterator end; + std::string result; + size_t p = 0; + for (; it!=end ; ++it) { - //printf("Found environment var s.mid(%d,%d)='%s'\n",i+2,l-3,s.mid(i+2,l-3).data()); - QCString env=Portable::getenv(s.mid(i+2,l-3)); + const auto &match = *it; + size_t i = match.position(); + size_t l = match.length(); + result+=s.substr(p,i-p); + std::string matchStr = match.str(); + std::string matchContents = matchStr.substr(2,matchStr.length()-3); + QCString env=Portable::getenv(matchContents.c_str()); // get content of $(..) match substEnvVarsInString(env); // recursively expand variables if needed. - s = s.left(i)+env+s.right(s.length()-i-l); - p=i+env.length(); // next time start at the end of the expanded string + result+=env.str(); + p=i+l; } - s=s.stripWhiteSpace(); // to strip the bogus space that was added when an argument - // has quotes - //printf("substEnvVarInString(%s) end\n",s.data()); + result+=s.substr(p); + str = QCString(result).stripWhiteSpace(); } static void substEnvVarsInStrList(StringVector &sl) @@ -1641,16 +1647,16 @@ void Config::checkAndCorrect() //------------------------ // check ALIASES const StringVector &aliasList = Config_getList(ALIASES); - for (const auto &s : aliasList) + for (const auto &alias : aliasList) { - QRegExp re1("[a-z_A-Z][a-z_A-Z0-9]*[ \t]*="); // alias without argument - QRegExp re2("[a-z_A-Z][a-z_A-Z0-9]*{[0-9]+}[ \t]*="); // alias with argument - QCString alias=s.c_str(); - alias=alias.stripWhiteSpace(); - if (alias.find(re1)!=0 && alias.find(re2)!=0) + // match aliases of the form 'name=' and 'name{2} =' + static std::regex re("[[:alpha:]_][[:alnum:]_]*(\\{[[:digit:]]+\\})?[[:space:]]*="); + std::sregex_iterator it(alias.begin(),alias.end(),re); + std::sregex_iterator end; + if (it==end) { err("Illegal ALIASES format '%s'. Use \"name=value\" or \"name{n}=value\", where n is the number of arguments\n", - alias.data()); + alias.c_str()); } } -- cgit v0.12 From 8c73f532713df7c6e7a4ffd438faee1f8666d5c8 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Sat, 13 Feb 2021 18:58:11 +0100 Subject: Refactoring: replace QRegExp by std::regex in fortranscanner.l --- src/fortranscanner.l | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fortranscanner.l b/src/fortranscanner.l index 74d6d03..e43e0f4 100644 --- a/src/fortranscanner.l +++ b/src/fortranscanner.l @@ -56,7 +56,6 @@ #include #include -#include #include #include "fortranscanner.h" @@ -1151,7 +1150,8 @@ private { if (yyextra->ifType == IF_ABSTRACT || yyextra->ifType == IF_SPECIFIC) { - yyextra->current_root->name.replace(QRegExp("\\$interface\\$"), yytext); + yyextra->current_root->name = substitute( + yyextra->current_root->name, "$interface$", yytext); } BEGIN(Parameterlist); -- cgit v0.12 From f640dced8976048f997026927a45a9c06672d02b Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Sat, 13 Feb 2021 18:58:43 +0100 Subject: Refactoring: replace QRegExp by std::regex in docparser.cpp --- src/code.l | 1 - src/commentcnv.l | 1 - src/defargs.l | 1 - src/docbookgen.cpp | 1 - src/docparser.cpp | 24 +++++++++++++----------- 5 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/code.l b/src/code.l index f7e1775..5481fdc 100644 --- a/src/code.l +++ b/src/code.l @@ -38,7 +38,6 @@ #include #include #include -#include #include #include "code.h" diff --git a/src/commentcnv.l b/src/commentcnv.l index 817feb3..7a3cda5 100644 --- a/src/commentcnv.l +++ b/src/commentcnv.l @@ -29,7 +29,6 @@ #include #include -#include #include #include diff --git a/src/defargs.l b/src/defargs.l index e25c1fe..6846544 100644 --- a/src/defargs.l +++ b/src/defargs.l @@ -56,7 +56,6 @@ //#include #include #include -#include #include #include "defargs.h" diff --git a/src/docbookgen.cpp b/src/docbookgen.cpp index 372a462..984d685 100644 --- a/src/docbookgen.cpp +++ b/src/docbookgen.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include "docbookgen.h" #include "doxygen.h" #include "message.h" diff --git a/src/docparser.cpp b/src/docparser.cpp index 83887c6..6c10bdb 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -425,7 +426,7 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type, bool * member g_memberDef, then a warning is raised (unless warnings * are disabled altogether). */ -static void checkArgumentName(const QCString &name) +static void checkArgumentName(const std::string &name) { if (!Config_getBool(WARN_IF_DOC_ERROR)) return; if (g_memberDef==0) return; // not a member @@ -436,11 +437,13 @@ static void checkArgumentName(const QCString &name) //printf("isDocsForDefinition()=%d\n",g_memberDef->isDocsForDefinition()); if (al.empty()) return; // no argument list - static QRegExp re("$?[a-zA-Z0-9_\\x80-\\xFF]+\\.*"); - int p=0,i=0,l; - while ((i=re.match(name,p,&l))!=-1) // to handle @param x,y + static std::regex re("(\\$[[:alnum:]_]|[[:alpha:]_])[[:alnum:]_]*\\.*"); + std::sregex_iterator it(name.begin(),name.end(),re); + std::sregex_iterator end; + for (; it!=end ; ++it) { - QCString aName=name.mid(i,l); + const auto &match = *it; + QCString aName=match.str(); if (lang==SrcLangExt_Fortran) aName=aName.lower(); //printf("aName='%s'\n",aName.data()); bool found=FALSE; @@ -482,7 +485,6 @@ static void checkArgumentName(const QCString &name) qPrint(aName), qPrint(scope), qPrint(g_memberDef->name()), qPrint(alStr), qPrint(inheritedFrom)); } - p=i+l; } } /*! Collects the return values found with \@retval command @@ -872,9 +874,9 @@ static int handleStyleArgument(DocNode *parent,DocNodeList &children, tok!=TK_ENDLIST ) { - static QRegExp specialChar("[.,|()\\[\\]:;\\?]"); + static std::regex specialChar("[.,|()\\[\\]:;\\?]"); if (tok==TK_WORD && g_token->name.length()==1 && - g_token->name.find(specialChar)!=-1) + std::regex_match(g_token->name.str(),specialChar)) { // special character that ends the markup command return tok; @@ -4533,13 +4535,13 @@ int DocParamList::parse(const QCString &cmdName) handleParameterType(this,m_paramTypes,g_token->name.left(typeSeparator)); g_token->name = g_token->name.mid(typeSeparator+1); g_hasParamCommand=TRUE; - checkArgumentName(g_token->name); + checkArgumentName(g_token->name.str()); ((DocParamSect*)parent())->m_hasTypeSpecifier=TRUE; } else { g_hasParamCommand=TRUE; - checkArgumentName(g_token->name); + checkArgumentName(g_token->name.str()); } } else if (m_type==DocParamSect::RetVal) @@ -4591,7 +4593,7 @@ int DocParamList::parseXml(const QCString ¶mName) if (m_type==DocParamSect::Param) { g_hasParamCommand=TRUE; - checkArgumentName(g_token->name); + checkArgumentName(g_token->name.str()); } else if (m_type==DocParamSect::RetVal) { -- cgit v0.12 From 1d993b03fb172021213fd65c5c0f061c8d42bfb5 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Sat, 13 Feb 2021 19:05:01 +0100 Subject: Refactoring: replace QRegExp by std::regex in htmlhelp.cpp --- src/htmlhelp.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/htmlhelp.cpp b/src/htmlhelp.cpp index af511bb..1d7f888 100644 --- a/src/htmlhelp.cpp +++ b/src/htmlhelp.cpp @@ -16,10 +16,10 @@ */ #include +#include #include #include -#include #include #include @@ -154,13 +154,15 @@ void HtmlHelpIndex::addItem(const char *level1,const char *level2, const char *url,const char *anchor,bool hasLink, bool reversed) { - QCString key = level1; - if (level2) key+= (QCString)"?" + level2; - if (key.find(QRegExp("@[0-9]+"))!=-1) // skip anonymous stuff + static std::regex re("@[[:digit:]]+"); + std::string key = level1; + if (level2) key+= std::string("?") + level2; + if (std::regex_match(key,re)) // skip anonymous stuff { return; } - m_map.add(key+anchor,key,url,anchor,hasLink,reversed); + std::string key_anchor = key+anchor; + m_map.add(key_anchor.c_str(),key.c_str(),url,anchor,hasLink,reversed); } static QCString field2URL(const IndexField *f,bool checkReversed) -- cgit v0.12 From 0e85b883e4b66632b352f910c3e1ae13f47cb47b Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Sat, 13 Feb 2021 19:36:46 +0100 Subject: Refactoring: replace QRegExp by std::regex in doctokenizer.l --- src/doctokenizer.l | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/doctokenizer.l b/src/doctokenizer.l index a11f2fe..d2ba897 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -26,6 +26,8 @@ #include #include +#include +#include #include #include @@ -513,9 +515,11 @@ RCSID "$"("Author"|"Date"|"Header"|"Id"|"Locker"|"Log"|"Name"|"RCSfile"|"Revisio else { lineCount(yytext,yyleng); - QCString text=yytext; - static QRegExp re("[*+]"); - int listPos = text.findRev(re); + std::string text=yytext; + static std::regex re("[*+][^*+]*$"); // find last + or * + std::smatch match; + std::regex_search(text,match,re); + size_t listPos = match.position(); g_token->isEnumList = FALSE; g_token->id = -1; g_token->indent = computeIndent(yytext,listPos); @@ -529,13 +533,13 @@ RCSID "$"("Author"|"Date"|"Header"|"Id"|"Locker"|"Log"|"Name"|"RCSfile"|"Revisio } else { - QCString text=yytext; - static QRegExp re("[1-9]"); - int digitPos = text.find(re); - int dotPos = text.find('.',digitPos); - g_token->isEnumList = TRUE; - g_token->id = atoi(QCString(yytext).mid(digitPos,dotPos-digitPos)); - g_token->indent = computeIndent(yytext,digitPos); + std::string text=yytext; + static std::regex re("[1-9]+"); + std::smatch match; + std::regex_search(text,match,re); + g_token->isEnumList = true; + g_token->id = std::stoul(match.str()); + g_token->indent = computeIndent(yytext,match.position()); return TK_LISTITEM; } } @@ -556,12 +560,14 @@ RCSID "$"("Author"|"Date"|"Header"|"Id"|"Locker"|"Log"|"Name"|"RCSfile"|"Revisio else { lineCount(yytext,yyleng); - QCString text=extractPartAfterNewLine(yytext); - static QRegExp re("[*+]"); - int markPos = text.findRev(re); + std::string text=extractPartAfterNewLine(yytext).str(); + static std::regex re("[*+][^*+]*$"); // find last + or * + std::smatch match; + std::regex_search(text,match,re); + size_t markPos = match.position(); g_token->isEnumList = FALSE; g_token->id = -1; - g_token->indent = computeIndent(text,markPos); + g_token->indent = computeIndent(text.c_str(),markPos); return TK_LISTITEM; } } @@ -573,13 +579,13 @@ RCSID "$"("Author"|"Date"|"Header"|"Id"|"Locker"|"Log"|"Name"|"RCSfile"|"Revisio else { lineCount(yytext,yyleng); - QCString text=extractPartAfterNewLine(yytext); - static QRegExp re("[1-9]"); - int digitPos = text.find(re); - int dotPos = text.find('.',digitPos); - g_token->isEnumList = TRUE; - g_token->id = atoi(QCString(text).mid(digitPos,dotPos-digitPos)); - g_token->indent = computeIndent(text,digitPos); + std::string text=extractPartAfterNewLine(yytext).str(); + static std::regex re("[1-9]+"); + std::smatch match; + std::regex_search(text,match,re); + g_token->isEnumList = true; + g_token->id = std::stoul(match.str()); + g_token->indent = computeIndent(text.c_str(),match.position()); return TK_LISTITEM; } } -- cgit v0.12 From 275d3ed4372cee6694f0c63bd79d82be8a3d8acd Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Sat, 13 Feb 2021 20:27:10 +0100 Subject: Refactoring: replace QRegExp by std::regex in markdown.cpp --- src/markdown.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/markdown.cpp b/src/markdown.cpp index b9fad70..df632d7 100644 --- a/src/markdown.cpp +++ b/src/markdown.cpp @@ -33,11 +33,11 @@ #include #include -#include #include #include #include +#include #include "markdown.h" #include "growbuf.h" @@ -1471,15 +1471,15 @@ static int isHRuler(const char *data,int size) static QCString extractTitleId(QCString &title, int level) { TRACE(title.data()); - //static QRegExp r1("^[a-z_A-Z][a-z_A-Z0-9\\-]*:"); - static QRegExp r2("\\{#[a-z_A-Z][a-z_A-Z0-9\\-]*\\}"); - int l=0; - int i = r2.match(title,0,&l); - if (i!=-1 && title.mid(i+l).stripWhiteSpace().isEmpty()) // found {#id} style id - { - QCString id = title.mid(i+2,l-3); - title = title.left(i); - //printf("found id='%s' title='%s'\n",id.data(),title.data()); + // match e.g. '{#id-b11} ' and capture 'id-b11' + static std::regex r2("\\{#([a-z_A-Z][a-z_A-Z0-9\\-]*)\\}[[:space:]]*$"); + std::smatch match; + std::string ti = title.str(); + if (std::regex_search(ti,match,r2)) + { + std::string id = match[1].str(); + title = title.left(match.position()); + //printf("found match id='%s' title=%s\n",id.c_str(),title.data()); return id; } if ((level > 0) && (level <= Config_getInt(TOC_INCLUDE_HEADINGS))) -- cgit v0.12 From bb25ca2abcce26688af658c088a6f4c73b030089 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Sat, 13 Feb 2021 20:27:19 +0100 Subject: Refactoring: make better use of capture groups --- src/configimpl.l | 5 ++--- src/template.cpp | 4 ++-- src/util.cpp | 22 +++++++++++----------- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/configimpl.l b/src/configimpl.l index 1afe6d8..2938eb8 100644 --- a/src/configimpl.l +++ b/src/configimpl.l @@ -1136,7 +1136,7 @@ static void substEnvVarsInString(QCString &str) { if (str.isEmpty()) return; // match e.g. $(HOME) but also $(PROGRAMFILES(X86)) - static std::regex re("\\$\\([[:alpha:]_][[:alnum:].-]*(\\([[:alpha:]_][[:alnum:].-]*\\))?\\)"); + static std::regex re("\\$\\(([[:alpha:]_][[:alnum:].-]*(\\([[:alpha:]_][[:alnum:].-]*\\))?)\\)"); std::string s = str.str(); std::sregex_iterator it(s.begin(),s.end(),re); std::sregex_iterator end; @@ -1148,8 +1148,7 @@ static void substEnvVarsInString(QCString &str) size_t i = match.position(); size_t l = match.length(); result+=s.substr(p,i-p); - std::string matchStr = match.str(); - std::string matchContents = matchStr.substr(2,matchStr.length()-3); + std::string matchContents = match[1].str(); QCString env=Portable::getenv(matchContents.c_str()); // get content of $(..) match substEnvVarsInString(env); // recursively expand variables if needed. result+=env.str(); diff --git a/src/template.cpp b/src/template.cpp index d7587e6..61411be 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -4186,7 +4186,7 @@ class TemplateNodeMarkers : public TemplateNodeCreator c->push(); std::string str = patternStr.toString().str(); - static std::regex marker("@[[:digit:]]+"); + static std::regex marker("@([[:digit:]]+)"); std::sregex_iterator re_it(str.begin(),str.end(),marker); std::sregex_iterator end; size_t index=0; @@ -4204,7 +4204,7 @@ class TemplateNodeMarkers : public TemplateNodeCreator { ts << part; // write text before marker } - unsigned long entryIndex = std::stoul(match.str().substr(1)); + unsigned long entryIndex = std::stoul(match[1].str()); TemplateVariant var; size_t i=0; // search for list element at position id diff --git a/src/util.cpp b/src/util.cpp index 5f3dd8e..e8fcab9 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -222,7 +222,7 @@ QCString replaceAnonymousScopes(const char *s,const char *replacement) { if (s==0) return QCString(); static std::regex marker("@[[:digit:]]+"); - std::string result = regex_replace(s,marker,replacement?replacement:"__anonymous__"); + std::string result = std::regex_replace(s,marker,replacement?replacement:"__anonymous__"); //printf("replaceAnonymousScopes('%s')='%s'\n",s.data(),result.data()); return result; } @@ -1096,7 +1096,7 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, void writeMarkerList(OutputList &ol,const std::string &markerText,size_t numMarkers, std::function replaceFunc) { - static std::regex marker("@[[:digit:]]+"); + static std::regex marker("@([[:digit:]]+)"); std::sregex_iterator it(markerText.begin(),markerText.end(),marker); std::sregex_iterator end; size_t index=0; @@ -1107,7 +1107,7 @@ void writeMarkerList(OutputList &ol,const std::string &markerText,size_t numMark size_t newIndex = match.position(); size_t matchLen = match.length(); ol.parseText(markerText.substr(index,newIndex-index)); - unsigned long entryIndex = std::stoul(match.str().substr(1)); + unsigned long entryIndex = std::stoul(match[1]); if (entryIndex<(unsigned long)numMarkers) { replaceFunc(ol,entryIndex); @@ -6066,7 +6066,7 @@ static QCString expandAliasRec(StringUnorderedSet &aliasesProcessed,const std::s { //QCString result; std::string result; - std::regex re("[\\\\@][[:alpha:]_][[:alnum:]_]*"); + std::regex re("[\\\\@]([[:alpha:]_][[:alnum:]_]*)"); std::sregex_iterator re_it(s.begin(),s.end(),re); std::sregex_iterator end; size_t p = 0; @@ -6082,7 +6082,7 @@ static QCString expandAliasRec(StringUnorderedSet &aliasesProcessed,const std::s QCString args = extractAliasArgs(s,i+l); bool hasArgs = !args.isEmpty(); // found directly after command int argsLen = args.length(); - QCString cmd = match.str().substr(1); + QCString cmd = match[1].str(); QCString cmdNoArgs = cmd; int numArgs=0; if (hasArgs) @@ -6392,7 +6392,7 @@ bool readInputFile(const char *fileName,BufStr &inBuf,bool filter,bool isSourceC QCString filterTitle(const std::string &title) { std::string tf; - std::regex re("%[A-Z_A-z]"); + std::regex re("%([A-Z_a-z]+)"); std::sregex_iterator it(title.begin(),title.end(),re); std::sregex_iterator end; size_t p = 0; @@ -6402,7 +6402,7 @@ QCString filterTitle(const std::string &title) size_t i = match.position(); size_t l = match.length(); if (i>p) tf+=title.substr(p,i-p); - tf+=match.str().substr(1); // skip % + tf+=match[1].str(); // skip % p=i+l; } tf+=title.substr(p); @@ -6524,7 +6524,7 @@ QCString replaceColorMarkers(const char *str) if (str==0) return QCString(); std::string result; std::string s=str; - static std::regex re("##[0-9A-Fa-f][0-9A-Fa-f]"); + static std::regex re("##([0-9A-Fa-f][0-9A-Fa-f])"); std::sregex_iterator it(s.begin(),s.end(),re); std::sregex_iterator end; static int hue = Config_getInt(HTML_COLORSTYLE_HUE); @@ -6538,7 +6538,7 @@ QCString replaceColorMarkers(const char *str) size_t i = match.position(); size_t l = match.length(); if (i>p) result+=s.substr(p,i-p); - std::string lumStr = match.str().substr(2); + std::string lumStr = match[1].str(); #define HEXTONUM(x) (((x)>='0' && (x)<='9') ? ((x)-'0') : \ ((x)>='a' && (x)<='f') ? ((x)-'a'+10) : \ ((x)>='A' && (x)<='F') ? ((x)-'A'+10) : 0) @@ -7012,7 +7012,7 @@ bool classVisibleInIndex(const ClassDef *cd) */ QCString extractDirection(QCString &docs) { - std::regex re("\\[[ inout,]+\\]"); + std::regex re("\\[([ inout,]+)\\]"); std::string s = docs.str(); std::sregex_iterator it(s.begin(),s.end(),re); std::sregex_iterator end; @@ -7024,7 +7024,7 @@ QCString extractDirection(QCString &docs) if (p==0 && l>2) { // make dir the part inside [...] without separators - std::string dir = match.str().substr(1,l-2); + std::string dir = match[1].str(); // strip , and ' ' from dir dir.erase(std::remove_if(dir.begin(),dir.end(), [](const char c) { return c==' ' || c==','; } -- cgit v0.12 From 7974279bd1da213244a527db16f0504355c1e074 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Sat, 13 Feb 2021 20:34:13 +0100 Subject: Refactoring: replace QRegExp by std::regex in groupdef.cpp --- src/groupdef.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/groupdef.cpp b/src/groupdef.cpp index b900148..3fdb9fb 100644 --- a/src/groupdef.cpp +++ b/src/groupdef.cpp @@ -17,9 +17,9 @@ #include #include +#include #include -#include #include "groupdef.h" #include "classdef.h" @@ -1090,12 +1090,15 @@ void GroupDefImpl::writeDocumentation(OutputList &ol) if (Doxygen::searchIndex) { Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE); - static QRegExp we("[a-zA-Z_][-a-zA-Z_0-9]*"); - int i=0,p=0,l=0; - while ((i=we.match(m_title,p,&l))!=-1) // foreach word in the title + static std::regex we("[[:alpha:]_][[:alnum:]_\\-]*"); + std::string title = m_title.str(); + std::sregex_iterator it(title.begin(),title.end(),we); + std::sregex_iterator end; + for (; it!=end ; ++it) { - Doxygen::searchIndex->addWord(m_title.mid(i,l),TRUE); - p=i+l; + const auto &match = *it; + std::string matchStr = match.str(); + Doxygen::searchIndex->addWord(matchStr.c_str(),TRUE); } } -- cgit v0.12 From 58d130788e9d6232a8880c4836d54a2355c4fe64 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Sun, 14 Feb 2021 14:18:51 +0100 Subject: Refactoring: replace QRegExp by std::regex in rtfstyle.cpp --- src/docparser.cpp | 2 +- src/htmlhelp.cpp | 2 +- src/rtfstyle.cpp | 211 +++++++++++++++++++++++------------------------------- src/rtfstyle.h | 4 +- 4 files changed, 94 insertions(+), 125 deletions(-) diff --git a/src/docparser.cpp b/src/docparser.cpp index 6c10bdb..725cee0 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -876,7 +876,7 @@ static int handleStyleArgument(DocNode *parent,DocNodeList &children, { static std::regex specialChar("[.,|()\\[\\]:;\\?]"); if (tok==TK_WORD && g_token->name.length()==1 && - std::regex_match(g_token->name.str(),specialChar)) + std::regex_search(g_token->name.str(),specialChar)) { // special character that ends the markup command return tok; diff --git a/src/htmlhelp.cpp b/src/htmlhelp.cpp index 1d7f888..b020bb0 100644 --- a/src/htmlhelp.cpp +++ b/src/htmlhelp.cpp @@ -157,7 +157,7 @@ void HtmlHelpIndex::addItem(const char *level1,const char *level2, static std::regex re("@[[:digit:]]+"); std::string key = level1; if (level2) key+= std::string("?") + level2; - if (std::regex_match(key,re)) // skip anonymous stuff + if (std::regex_search(key,re)) // skip anonymous stuff { return; } diff --git a/src/rtfstyle.cpp b/src/rtfstyle.cpp index 4b01002..e8643fb 100644 --- a/src/rtfstyle.cpp +++ b/src/rtfstyle.cpp @@ -1,9 +1,6 @@ /****************************************************************************** * - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2021 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 @@ -16,15 +13,13 @@ * */ -#include -#include -#include -#include +#include +#include +#include #include "rtfstyle.h" #include "message.h" - RTFListItemInfo rtf_listItemInfo[rtf_maxIndentLevels]; QCString rtf_title; @@ -38,6 +33,21 @@ QCString rtf_documentType; QCString rtf_documentId; QCString rtf_keywords; +static std::map g_styleMap = +{ + { "Title", rtf_title }, + { "Subject", rtf_subject }, + { "Comments", rtf_comments }, + { "Company", rtf_company }, + { "LogoFilename", rtf_logoFilename }, + { "Author", rtf_author }, + { "Manager", rtf_manager }, + { "DocumentType", rtf_documentType }, + { "DocumentId", rtf_documentId }, + { "Keywords", rtf_keywords } +}; + + char rtf_Style_Reset[] = "\\pard\\plain "; #define RTF_LatexToc(lvl,nest,nxt,pos,twps) \ @@ -224,116 +234,80 @@ Rtf_Style_Default rtf_Style_Default[] = } }; -static const QRegExp s_clause("\\\\s[0-9]+\\s*"); +static const std::regex s_clause("\\\\s([[:digit:]]+)[[:space:]]*"); -StyleData::StyleData(const char* reference, const char* definition) +StyleData::StyleData(const std::string &reference, const std::string &definition) { - const char *ref = reference; - - int start = s_clause.match(ref); ASSERT(start >= 0); - ref += start; - m_index = (int)atol(ref + 2); ASSERT(m_index > 0); - - m_reference = ref; + std::smatch match; + if (regex_search(reference,match,s_clause)) + { + m_index = static_cast(std::stoul(match[1].str())); + } + else // error + { + m_index = 0; + } + m_reference = reference; m_definition = definition; } -bool StyleData::setStyle(const char* s, const char* styleName) +bool StyleData::setStyle(const std::string &command, const std::string &styleName) { - static const QRegExp subgroup("^{[^}]*}\\s*"); - static const QRegExp any_clause("^\\\\[a-z][a-z0-9-]*\\s*"); - - int len = 0; // length of a particular RTF formatting control - int ref_len = 0; // length of the whole formatting section of a style - int start = s_clause.match(s, 0, &len); - if (start < 0) + std::smatch match; + if (!regex_search(command,match,s_clause)) { - err("Style sheet '%s' contains no '\\s' clause.\n{%s}\n", styleName, s); - return FALSE; - } - s += start; - m_index = (int)atol(s + 2); ASSERT(m_index > 0); - - // search for the end of pure formatting codes - const char* end = s + len; - ref_len = len; - bool haveNewDefinition = TRUE; - for(;;) - { - if (*end == '{') - { - // subgroups are used for \\additive - if (0 != subgroup.match(end, 0, &len)) - break; - else - { - end += len; - ref_len += len; - } - } - else if (*end == '\\') - { - if (0 == qstrncmp(end, "\\snext", 6)) - break; - if (0 == qstrncmp(end, "\\sbasedon", 9)) - break; - if (0 != any_clause.match(end, 0, &len)) - break; - end += len; - ref_len += len; - } - else if (*end == 0) - { // no style-definition part, keep default value - haveNewDefinition = FALSE; - break; - } - else // plain name without leading \\snext - break; + err("Style sheet '%s' contains no '\\s' clause.\n{%s}", styleName.c_str(), command.c_str()); + return false; } - m_reference = s; - if (haveNewDefinition) + m_index = static_cast(std::stoul(match[1].str())); + + static std::regex definition_splitter("^(.*)(\\\\sbasedon[[:digit:]]+.*)$"); + if (regex_match(command,match,definition_splitter)) { - m_definition = end; + m_reference = match[1].str(); + m_definition = match[2].str(); } - return TRUE; + + return true; } + void loadStylesheet(const char *name, StyleDataMap& map) { - QFile file(name); - if (!file.open(IO_ReadOnly)) + std::ifstream file(name); + if (!file.is_open()) { - err("Can't open RTF style sheet file %s. Using defaults.\n",name); + err("Can't open RTF style sheet file %s. Using defaults.",name); return; } msg("Loading RTF style sheet %s...\n",name); - static const QRegExp separator("[ \t]*=[ \t]*"); uint lineNr=1; - QTextStream t(&file); - while (!t.eof()) + for (std::string line ; getline(file,line) ; ) // for each line { - QCString s(4096); // string buffer of max line length - s = t.readLine().stripWhiteSpace().utf8(); - if (s.isEmpty() || s.at(0)=='#') continue; // skip blanks & comments - int sepLength; - int sepStart = separator.match(s,0,&sepLength); - if (sepStart<=0) // no valid assignment statement + if (line.empty() || line[0]=='#') continue; // skip blanks & comments + static std::regex assignment_splitter("[[:space:]]*=[[:space:]]*"); + std::smatch match; + if (std::regex_search(line,match,assignment_splitter)) { - warn(name,lineNr,"Assignment of style sheet name expected!\n"); - continue; + std::string key = match.prefix(); + std::string value = match.suffix(); + auto it = map.find(key); + if (it!=map.end()) + { + StyleData& styleData = it->second; + styleData.setStyle(value,key); + } + else + { + warn(name,lineNr,"Unknown style sheet name %s ignored.",key.data()); + } } - QCString key=s.left(sepStart); - auto it = map.find(key.str()); - if (it==map.end()) // not a valid style sheet name + else { - warn(name,lineNr,"Unknown style sheet name %s ignored.\n",key.data()); - continue; + warn(name,lineNr,"Assignment of style sheet name expected line='%s'!",line.c_str()); } - StyleData& styleData = it->second; - s+=" "; // add command separator - styleData.setStyle(s.data() + sepStart + sepLength, key.data()); lineNr++; } } @@ -342,44 +316,39 @@ StyleDataMap rtf_Style; void loadExtensions(const char *name) { - QFile file(name); - if (!file.open(IO_ReadOnly)) + std::ifstream file(name); + if (!file.is_open()) { - err("Can't open RTF extensions file %s. Using defaults.\n",name); + err("Can't open RTF extensions file %s. Using defaults.",name); return; } msg("Loading RTF extensions %s...\n",name); - static const QRegExp separator("[ \t]*=[ \t]*"); uint lineNr=1; - QTextStream t(&file); - t.setEncoding(QTextStream::UnicodeUTF8); - while (!t.eof()) + for (std::string line ; getline(file,line) ; ) // for each line { - QCString s(4096); // string buffer of max line length - s = t.readLine().stripWhiteSpace().utf8(); - if (s.length()==0 || s.at(0)=='#') continue; // skip blanks & comments - int sepLength; - int sepStart = separator.match(s,0,&sepLength); - if (sepStart<=0) // no valid assignment statement + if (line.empty() || line[0]=='#') continue; // skip blanks & comments + std::smatch match; + static std::regex assignment_splitter("[[:space:]]*=[[:space:]]*"); + if (std::regex_search(line,match,assignment_splitter)) + { + std::string key = match.prefix(); + std::string value = match.suffix(); + auto it = g_styleMap.find(key); + if (it!=g_styleMap.end()) + { + it->second = value; + } + else + { + warn(name,lineNr,"Ignoring unknown extension key '%s'...",key.c_str()); + } + } + else { - warn(name,lineNr,"Assignment of extension field expected!\n"); - continue; + warn(name,lineNr,"Assignment of style sheet name expected!"); } - QCString key=s.left(sepStart); - QCString data=s.data() + sepStart + sepLength; - - if (key == "Title") rtf_title = data.data(); - if (key == "Subject") rtf_subject = data.data(); - if (key == "Comments") rtf_comments = data.data(); - if (key == "Company") rtf_company = data.data(); - if (key == "LogoFilename") rtf_logoFilename = data.data(); - if (key == "Author") rtf_author = data.data(); - if (key == "Manager") rtf_manager = data.data(); - if (key == "DocumentType") rtf_documentType = data.data(); - if (key == "DocumentId") rtf_documentId = data.data(); - if (key == "Keywords") rtf_keywords = data.data(); lineNr++; } } diff --git a/src/rtfstyle.h b/src/rtfstyle.h index b3d04bd..140d31f 100644 --- a/src/rtfstyle.h +++ b/src/rtfstyle.h @@ -63,8 +63,8 @@ struct StyleData public: StyleData() = default; - StyleData(const char* reference, const char* definition); - bool setStyle(const char* s, const char* styleName); + StyleData(const std::string &reference, const std::string &definition); + bool setStyle(const std::string &command, const std::string &styleName); const char *reference() const { return m_reference.c_str(); } const char *definition() const { return m_definition.c_str(); } uint index() const { return m_index; } -- cgit v0.12 From f27dbdbbbae00c8862a5cb434ae3a7cd58035d39 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Mon, 15 Feb 2021 20:17:22 +0100 Subject: Refactoring: replace QRegExp by std::regex in scanner.l --- src/scanner.l | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/src/scanner.l b/src/scanner.l index 6970d3e..ebb37c7 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -1,8 +1,6 @@ /***************************************************************************** * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2021 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 @@ -31,13 +29,13 @@ #include #include #include +#include #include #include #include #include -#include #include #include "scanner.h" @@ -3741,9 +3739,9 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } else { - static QRegExp re("@[0-9]+$"); + static std::regex re("@[0-9]+$"); if (!yyextra->isTypedef && yyextra->memspecEntry && - yyextra->memspecEntry->name.find(re)==-1) // not typedef or anonymous type (see bug691071) + !std::regex_search(yyextra->memspecEntry->name.str(),re)) // not typedef or anonymous type (see bug691071) { // enabled the next two lines for bug 623424 yyextra->current->doc.resize(0); @@ -4833,10 +4831,16 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->fileName = yyextra->yyFileName; yyextra->current->startLine = yyextra->yyBegLineNr; yyextra->current->startColumn = yyextra->yyBegColNr; - static QRegExp re("([^)]*[*&][^)]*)"); // (...*...) + static std::regex re("\\([^)]*[*&][^]*\\)"); + std::smatch match; + std::string type = yyextra->current->type.str(); + int ti=-1; + if (std::regex_search(type,match,re)) + { + ti = (int)match.position(); + } int ts=yyextra->current->type.find('<'); int te=yyextra->current->type.findRev('>'); - int ti=yyextra->current->type.find(re,0); // bug677315: A get(); is not a function pointer bool isFunction = ti==-1 || // not a (...*...) pattern @@ -6891,15 +6895,16 @@ static void splitKnRArg(yyscan_t yyscanner,QCString &oldStyleArgPtr,QCString &ol int si = yyextra->current->args.length(); if (yyextra->oldStyleArgType.isEmpty()) // new argument { - static QRegExp re("([^)]*)"); - int bi1 = yyextra->current->args.findRev(re); - int bi2 = bi1!=-1 ? yyextra->current->args.findRev(re,bi1-1) : -1; + static std::regex re("(\\([^)]*\\))[[:space:]]*(\\([^)]*\\))?"); + std::string args = yyextra->current->args.str(); + std::smatch matches; + std::regex_search(args,matches,re); char c; - if (bi1!=-1 && bi2!=-1) // found something like "int (*func)(int arg)" + if (matches.length()==3 && !matches[2].str().empty()) // found something like "int (*func)(int arg)" { - int s=bi2+1; + size_t s = matches.position()+1; // keep opening ( yyextra->oldStyleArgType = yyextra->current->args.left(s); - int i=s; + int i=(int)s; while (icurrent->args.at(i))=='*' || isspace((uchar)c))) i++; yyextra->oldStyleArgType += yyextra->current->args.mid(s,i-s); s=i; @@ -6907,12 +6912,12 @@ static void splitKnRArg(yyscan_t yyscanner,QCString &oldStyleArgPtr,QCString &ol oldStyleArgName = yyextra->current->args.mid(s,i-s); yyextra->oldStyleArgType+=yyextra->current->args.mid(i); } - else if (bi1!=-1) // redundant braces like in "int (*var)" + else if (matches.length()==3) // redundant braces like in "int (*var)" { - int s=bi1; + size_t s = matches.position(); // strip opening ( yyextra->oldStyleArgType = yyextra->current->args.left(s); s++; - int i=s+1; + int i=(int)s+1; while (icurrent->args.at(i))=='*' || isspace((uchar)c))) i++; yyextra->oldStyleArgType += yyextra->current->args.mid(s,i-s); s=i; -- cgit v0.12 From bb99814ff2eeb0c916a4c5d632bd0c03e3e7ba96 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Mon, 15 Feb 2021 20:30:22 +0100 Subject: Refactoring: remove QRegExp in searchindex.cpp --- src/searchindex.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/searchindex.cpp b/src/searchindex.cpp index 89f1681..61d2d6c 100644 --- a/src/searchindex.cpp +++ b/src/searchindex.cpp @@ -18,7 +18,6 @@ #include #include -#include #include "searchindex.h" #include "config.h" @@ -200,7 +199,6 @@ static int charsToIndex(const char *word) void SearchIndex::addWord(const char *word,bool hiPriority,bool recurse) { - static QRegExp nextPart("[_a-z:][A-Z]"); if (word==0 || word[0]=='\0') return; QCString wStr = QCString(word).lower(); //printf("SearchIndex::addWord(%s,%d) wStr=%s\n",word,hiPriority,wStr.data()); @@ -227,7 +225,14 @@ void SearchIndex::addWord(const char *word,bool hiPriority,bool recurse) } if (!found) // no prefix stripped { - if ((i=nextPart.match(word))>=1) + i=0; + while (word[i]!=0 && + !((word[i]=='_' || word[i]==':' || (word[i]>='a' && word[i]<='z')) && // [_a-z:] + (word[i+1]>='A' && word[i+1]<='Z'))) // [A-Z] + { + i++; + } + if (word[i]!=0 && i>=1) { addWord(word+i+1,hiPriority,TRUE); } -- cgit v0.12 From df2512b5c4161fbf31751478c81c9effd2715a6a Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Tue, 16 Feb 2021 21:02:45 +0100 Subject: Refactoring: replace QRegExp by std::regex in doxygen.cpp --- src/doxygen.cpp | 172 ++++++++++++++++++++++++++------------------------------ 1 file changed, 81 insertions(+), 91 deletions(-) diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 744db35..f7849a3 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -32,6 +31,7 @@ #include #include #include +#include #include "version.h" #include "doxygen.h" @@ -2220,12 +2220,12 @@ static MemberDef *addVariableToFile( { ttype.stripPrefix("struct "); ttype.stripPrefix("union "); - static QRegExp re("[a-z_A-Z][a-z_A-Z0-9]*"); - int l,s; - s = re.match(ttype,0,&l); - if (s>=0) + static std::regex re("[:alpha:]_][:alnum:]_]*"); + std::smatch match; + std::string typ = ttype.str(); + if (std::regex_search(typ,match,re)) { - QCString typeValue = ttype.mid(s,l); + QCString typeValue = match.str(); ClassDefMutable *cd = getClassMutable(typeValue); if (cd) { @@ -2432,27 +2432,36 @@ static MemberDef *addVariableToFile( * \returns -1 if this is not a function pointer variable or * the index at which the closing brace of (...*name) was found. */ -static int findFunctionPtr(const QCString &type,int lang, int *pLength=0) +static int findFunctionPtr(const std::string &type,SrcLangExt lang, int *pLength=0) { if (lang == SrcLangExt_Fortran || lang == SrcLangExt_VHDL) { return -1; // Fortran and VHDL do not have function pointers } - static const QRegExp re("([^)]*[\\*\\^][^)]*)"); - int i=-1,l; - int bb=type.find('<'); - int be=type.findRev('>'); - if (!type.isEmpty() && // return type is non-empty - (i=re.match(type,0,&l))!=-1 && // contains (...*...) - type.find("operator")==-1 && // not an operator - (type.find(")(")==-1 || type.find("typedef ")!=-1) && - // not a function pointer return type + + static std::regex re("\\([^)]*[*\\^][^)]*\\)"); + std::smatch match; + size_t i=std::string::npos; + size_t l=0; + if (std::regex_search(type,match,re)) // contains (...*...) + { + i = match.position(); + l = match.length(); + } + size_t bb=type.find('<'); + size_t be=type.rfind('>'); + + if (!type.empty() && // return type is non-empty + i!=std::string::npos && // contains (...*...) + type.find("operator")==std::string::npos && // not an operator + (type.find(")(")==std::string::npos || type.find("typedef ")!=std::string::npos) && + // not a function pointer return type !(bb type" as a function pointer ) { - if (pLength) *pLength=l; - //printf("findFunctionPtr=%d\n",i); - return i; + if (pLength) *pLength=(int)l; + //printf("findFunctionPtr=%d\n",(int)i); + return (int)i; } else { @@ -2467,8 +2476,6 @@ static int findFunctionPtr(const QCString &type,int lang, int *pLength=0) */ static bool isVarWithConstructor(const Entry *root) { - static QRegExp initChars("[0-9\"'&*!^]+"); - static QRegExp idChars("[a-z_A-Z][a-z_A-Z0-9]*"); bool result=FALSE; bool typeIsClass = false; bool typePtrType = false; @@ -2525,9 +2532,12 @@ static bool isVarWithConstructor(const Entry *root) } for (const Argument &a : root->argList) { + static std::regex initChars("[0-9\"'&*!^]+"); + std::smatch match; if (!a.name.isEmpty() || !a.defval.isEmpty()) { - if (a.name.find(initChars)==0) + std::string name = a.name.str(); + if (std::regex_search(name,match,initChars) && match.position()==0) { result=TRUE; } @@ -2556,17 +2566,18 @@ static bool isVarWithConstructor(const Entry *root) result=FALSE; // argument is a typedef goto done; } - if (a.type.find(initChars)==0) + std::string atype = a.type.str(); + if (std::regex_search(atype,match,initChars) && match.position()==0) { result=TRUE; // argument type starts with typical initializer char goto done; } - QCString resType=resolveTypeDef(ctx,a.type); - if (resType.isEmpty()) resType=a.type; - int len; - if (idChars.match(resType,0,&len)==0) // resType starts with identifier + std::string resType=resolveTypeDef(ctx,a.type).str(); + if (resType.empty()) resType=atype; + static std::regex idChars("[[:alpha:]_][[:alnum:]_]*"); + if (std::regex_search(resType,match,idChars) && match.position()==0) // resType starts with identifier { - resType=resType.left(len); + resType=match.str(); //printf("resType=%s\n",resType.data()); if (resType=="int" || resType=="long" || resType=="float" || resType=="double" || resType=="char" || resType=="signed" || @@ -2613,15 +2624,15 @@ static void addVariable(const Entry *root,int isFuncPtr=-1) // type="" name="int *" args="(var[10])" type=name; - static const QRegExp reName("[a-z_A-Z][a-z_A-Z0-9]*"); - int l=0; - int j=0; - int i=args.isEmpty() ? -1 : reName.match(args,0,&l); - if (i!=-1) + std::string sargs = args.str(); + static const std::regex reName("[[:alpha:]_][[:alnum:]_]*"); + std::smatch match; + if (std::regex_search(sargs,match,reName)) { - name=args.mid(i,l); - j=args.find(')',i+l)-i-l; - if (j >= 0) args=args.mid(i+l,j); + name = match.str(); // e.g. 'var' in '(var[10])' + sargs = match.suffix().str(); // e.g. '[10]) in '(var[10])' + size_t j = sargs.find(')'); + if (j!=std::string::npos) args=sargs.substr(0,j); // extract, e.g '[10]' from '[10])' } //printf("new: type='%s' name='%s' args='%s'\n", // type.data(),name.data(),args.data()); @@ -2629,7 +2640,7 @@ static void addVariable(const Entry *root,int isFuncPtr=-1) else { int i=isFuncPtr; - if (i==-1 && (root->spec&Entry::Alias)==0) i=findFunctionPtr(type,root->lang); // for typedefs isFuncPtr is not yet set + if (i==-1 && (root->spec&Entry::Alias)==0) i=findFunctionPtr(type.str(),root->lang); // for typedefs isFuncPtr is not yet set Debug::print(Debug::Variables,0," functionPtr? %s\n",i!=-1?"yes":"no"); if (i!=-1) // function pointer { @@ -2871,7 +2882,7 @@ static void buildVarList(const Entry *root) (root->section==Entry::VARIABLE_SEC // it's a variable ) || (root->section==Entry::FUNCTION_SEC && // or maybe a function pointer variable - (isFuncPtr=findFunctionPtr(root->type,root->lang))!=-1 + (isFuncPtr=findFunctionPtr(root->type.str(),root->lang))!=-1 ) || (root->section==Entry::FUNCTION_SEC && // class variable initialized by constructor isVarWithConstructor(root) @@ -3036,24 +3047,8 @@ static void addMethodToClass(const Entry *root,ClassDefMutable *cd, { FileDef *fd=root->fileDef(); - int l; - static QRegExp re("([a-z_A-Z0-9: ]*[ &*]+[ ]*"); QCString type = rtype; QCString args = rargs; - int ts=type.find('<'); - int te=type.findRev('>'); - int i=re.match(type,0,&l); - if (i!=-1 && ts!=-1 && ts, see bug 677315 - { - i=-1; - } - - if (cd->getLanguage()==SrcLangExt_Cpp && // only C has pointers - !type.isEmpty() && (root->spec&Entry::Alias)==0 && i!=-1) // function variable - { - args+=type.right(type.length()-i-l); - type=type.left(i+l); - } QCString name=removeRedundantWhiteSpace(rname); if (name.left(2)=="::") name=name.right(name.length()-2); @@ -3066,6 +3061,7 @@ static void addMethodToClass(const Entry *root,ClassDefMutable *cd, else mtype=MemberType_Function; // strip redundant template specifier for constructors + int i = -1; int j = -1; if ((fd==0 || fd->getLanguage()==SrcLangExt_Cpp) && name.left(9)!="operator " && // not operator @@ -3373,21 +3369,9 @@ static void buildFunctionList(const Entry *root) } } - static QRegExp re("([a-z_A-Z0-9: ]*[ &*]+[ ]*"); - int ts=root->type.find('<'); - int te=root->type.findRev('>'); - int ti; if (!root->parent()->name.isEmpty() && (root->parent()->section & Entry::COMPOUND_MASK) && - cd && - // do some fuzzy things to exclude function pointers - (root->type.isEmpty() || - ((ti=root->type.find(re,0))==-1 || // type does not contain ..(..* - (ts!=-1 && ts - root->args.find(")[")!=-1) || // and args not )[.. -> function pointer - root->type.find(")(")!=-1 || root->type.find("operator")!=-1 || // type contains ..)(.. and not "operator" - cd->getLanguage()!=SrcLangExt_Cpp // language other than C - ) + cd ) { Debug::print(Debug::Functions,0," --> member %s of class %s!\n", @@ -3826,25 +3810,26 @@ static void transferRelatedFunctionDocumentation() * Example: A template class A with template arguments * that inherits from B will have T and S in the dictionary. */ -static TemplateNameMap getTemplateArgumentsInName(const ArgumentList &templateArguments,const QCString &name) +static TemplateNameMap getTemplateArgumentsInName(const ArgumentList &templateArguments,const std::string &name) { std::map templateNames; - static QRegExp re("[a-z_A-Z][a-z_A-Z0-9:]*"); int count=0; for (const Argument &arg : templateArguments) { - int i,p=0,l; - while ((i=re.match(name,p,&l))!=-1) + static std::regex re("[[:alpha:]_][[:alnum:]_:]*"); + std::sregex_iterator it(name.begin(),name.end(),re); + std::sregex_iterator end; + for (; it!=end ; ++it) { - QCString n = name.mid(i,l); + const auto &match = *it; + std::string n = match.str(); if (n==arg.name) { - if (templateNames.find(n.str())==templateNames.end()) + if (templateNames.find(n)==templateNames.end()) { - templateNames.insert(std::make_pair(n.str(),count)); + templateNames.insert(std::make_pair(n,count)); } } - p=i+l; } } return templateNames; @@ -3947,7 +3932,7 @@ static void findUsedClassesForClass(const Entry *root, TemplateNameMap formTemplateNames; if (templateNames.empty()) { - formTemplateNames = getTemplateArgumentsInName(formalArgs,usedName); + formTemplateNames = getTemplateArgumentsInName(formalArgs,usedName.str()); } BaseInfo bi(usedName,Public,Normal); findClassRelation(root,context,instanceCd,&bi,formTemplateNames,TemplateInstances,isArtificial); @@ -4073,7 +4058,7 @@ static void findBaseClassesForClass( TemplateNameMap formTemplateNames; if (templateNames.empty()) { - formTemplateNames = getTemplateArgumentsInName(formalArgs,bi.name); + formTemplateNames = getTemplateArgumentsInName(formalArgs,bi.name.str()); } BaseInfo tbi = bi; tbi.name = substituteTemplateArgumentsInString(bi.name.str(),formalArgs,actualArgs); @@ -4793,7 +4778,7 @@ static void computeTemplateClassRelations() if (!tl.empty()) { TemplateNameMap baseClassNames = tcd->getTemplateBaseClassNames(); - TemplateNameMap templateNames = getTemplateArgumentsInName(tl,bi.name); + TemplateNameMap templateNames = getTemplateArgumentsInName(tl,bi.name.str()); // for each template name that we inherit from we need to // substitute the formal with the actual arguments TemplateNameMap actualTemplateNames; @@ -5336,18 +5321,23 @@ static bool scopeIsTemplate(const Definition *d) static QCString substituteTemplatesInString( const ArgumentLists &srcTempArgLists, const ArgumentLists &dstTempArgLists, - const QCString &src + const std::string &src ) { - QCString dst; - QRegExp re( "[A-Za-z_][A-Za-z_0-9]*"); + std::string dst; + static const std::regex re("[[:alpha:]_][[:alnum:]_]*"); + std::sregex_iterator it(src.begin(),src.end(),re); + std::sregex_iterator end; //printf("type=%s\n",sa->type.data()); - int i,p=0,l; - while ((i=re.match(src,p,&l))!=-1) // for each word in srcType + size_t p=0; + for (; it!=end ; ++it) // for each word in srcType { + const auto &match = *it; + size_t i = match.position(); + size_t l = match.length(); bool found=FALSE; - dst+=src.mid(p,i-p); - QCString name=src.mid(i,l); + dst+=src.substr(p,i-p); + std::string name=match.str(); auto srcIt = srcTempArgLists.begin(); auto dstIt = dstTempArgLists.begin(); @@ -5390,7 +5380,7 @@ static QCString substituteTemplatesInString( } if (!tdaName.isEmpty()) { - name=tdaName; // substitute + name=tdaName.str(); // substitute found=TRUE; } } @@ -5406,7 +5396,7 @@ static QCString substituteTemplatesInString( dst+=name; p=i+l; } - dst+=src.right(src.length()-p); + dst+=src.substr(p); //printf(" substituteTemplatesInString(%s)=%s\n", // src.data(),dst.data()); return dst; @@ -5422,8 +5412,8 @@ static void substituteTemplatesInArgList( auto dstIt = dst.begin(); for (const Argument &sa : src) { - QCString dstType = substituteTemplatesInString(srcTempArgLists,dstTempArgLists,sa.type); - QCString dstArray = substituteTemplatesInString(srcTempArgLists,dstTempArgLists,sa.array); + QCString dstType = substituteTemplatesInString(srcTempArgLists,dstTempArgLists,sa.type.str()); + QCString dstArray = substituteTemplatesInString(srcTempArgLists,dstTempArgLists,sa.array.str()); if (dstIt == dst.end()) { Argument da = sa; @@ -5445,7 +5435,7 @@ static void substituteTemplatesInArgList( dst.setPureSpecifier(src.pureSpecifier()); dst.setTrailingReturnType(substituteTemplatesInString( srcTempArgLists,dstTempArgLists, - src.trailingReturnType())); + src.trailingReturnType().str())); //printf("substituteTemplatesInArgList: replacing %s with %s\n", // argListToString(src).data(),argListToString(dst).data() // ); @@ -6647,7 +6637,7 @@ static void filterMemberDocumentation(const Entry *root,const QCString relates) QCString type = root->type; QCString args = root->args; if ( // detect func variable/typedef to func ptr - (i=findFunctionPtr(type,root->lang,&l))!=-1 + (i=findFunctionPtr(type.str(),root->lang,&l))!=-1 ) { //printf("Fixing function pointer!\n"); -- cgit v0.12 From f8f4979682293b8f15c8293ac968402fe0c48a4e Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Wed, 17 Feb 2021 21:21:23 +0100 Subject: Refactoring: replace QRegExp by std::regex in memberdef.cpp --- src/memberdef.cpp | 149 ++++++++++++++++++++++-------------------------------- 1 file changed, 60 insertions(+), 89 deletions(-) diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 21892fb..0a64659 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -17,7 +17,6 @@ #include #include -#include #include #include "md5.h" #include "memberdef.h" @@ -922,27 +921,12 @@ static bool writeDefArgumentList(OutputList &ol,const Definition *scope,const Me ol.startParameterName(TRUE); } } - QRegExp re(")("),res("(.*\\*"); - int vp=a.type.find(re); - int wp=a.type.find(res); - - // use the following to put the function pointer type before the name - bool hasFuncPtrType=FALSE; if (!a.attrib.isEmpty() && !md->isObjCMethod()) // argument has an IDL attribute { ol.docify(a.attrib+" "); } - if (hasFuncPtrType) // argument type is a function pointer - { - //printf("a.type='%s' a.name='%s'\n",a.type.data(),a.name.data()); - QCString n=a.type.left(vp); - if (hasFuncPtrType) n=a.type.left(wp); - if (md->isObjCMethod()) { n.prepend("("); n.append(")"); } - if (!cName.isEmpty()) n=addTemplateNames(n,scope->name(),cName); - linkifyText(TextGeneratorOLImpl(ol),scope,md->getBodyDef(),md,n); - } - else // non-function pointer type + { QCString n=a.type; if (md->isObjCMethod()) { n.prepend("("); n.append(")"); } @@ -952,6 +936,7 @@ static bool writeDefArgumentList(OutputList &ol,const Definition *scope,const Me linkifyText(TextGeneratorOLImpl(ol),scope,md->getBodyDef(),md,n); } } + if (!isDefine) { if (paramTypeStarted) @@ -961,16 +946,8 @@ static bool writeDefArgumentList(OutputList &ol,const Definition *scope,const Me } ol.startParameterName(defArgList.size()<2); } - if (hasFuncPtrType) - { - ol.docify(a.type.mid(wp,vp-wp)); - } if (!a.name.isEmpty() || a.type=="...") // argument has a name { - //if (!hasFuncPtrType) - //{ - // ol.docify(" "); - //} ol.disable(OutputGenerator::Latex); ol.disable(OutputGenerator::Docbook); ol.disable(OutputGenerator::Html); @@ -994,12 +971,6 @@ static bool writeDefArgumentList(OutputList &ol,const Definition *scope,const Me { ol.docify(a.array); } - if (hasFuncPtrType) // write the part of the argument type - // that comes after the name - { - linkifyText(TextGeneratorOLImpl(ol),scope,md->getBodyDef(), - md,a.type.right(a.type.length()-vp)); - } if (!a.defval.isEmpty()) // write the default value { QCString n=a.defval; @@ -1857,6 +1828,8 @@ void MemberDefImpl::writeLink(OutputList &ol, */ ClassDef *MemberDefImpl::getClassDefOfAnonymousType() const { + //printf("%s:getClassDefOfAnonymousType() cache=%s\n",name().data(), + // m_impl->cachedAnonymousType?m_impl->cachedAnonymousType->name().data():""); if (m_impl->cachedAnonymousType) return m_impl->cachedAnonymousType; QCString cname; @@ -1873,20 +1846,18 @@ ClassDef *MemberDefImpl::getClassDefOfAnonymousType() const //if (ltype.left(7)=="static ") ltype=ltype.right(ltype.length()-7); // strip 'friend' keyword from ltype ltype.stripPrefix("friend "); - static QRegExp r("@[0-9]+"); - int l,i=r.match(ltype,0,&l); - //printf("ltype='%s' i=%d\n",ltype.data(),i); + // search for the last anonymous scope in the member type ClassDef *annoClassDef=0; - if (i!=-1) // found anonymous scope in type - { - int il=i-1,ir=i+l; - // extract anonymous scope - while (il>=0 && (isId(ltype.at(il)) || ltype.at(il)==':' || ltype.at(il)=='@')) il--; - if (il>0) il++; else if (il<0) il=0; - while (ir<(int)ltype.length() && (isId(ltype.at(ir)) || ltype.at(ir)==':' || ltype.at(ir)=='@')) ir++; - QCString annName = ltype.mid(il,ir-il); + // match expression if it contains at least one @1 marker, e.g. + // 'struct A::@1::@2::B' matches 'A::@1::@2::B' but 'struct A::B' does not match. + static const std::regex r("[[:alnum:]_@:]*@[[:digit:]]+[[:alnum:]_@:]*"); + std::string stype = ltype.str(); + std::smatch match; + if (std::regex_search(stype,match,r)) // found anonymous scope in type + { + QCString annName = match.str(); // if inside a class or namespace try to prepend the scope name if (!cname.isEmpty() && annName.left(cname.length()+2)!=cname+"::") @@ -2132,18 +2103,20 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, } // strip 'friend' keyword from ltype ltype.stripPrefix("friend "); - static QRegExp r("@[0-9]+"); - + static const std::regex r("@[[:digit:]]+"); + std::smatch match; + std::string stype = ltype.str(); bool endAnonScopeNeeded=FALSE; - int l,i=r.match(ltype,0,&l); - if (i!=-1) // member has an anonymous type + if (std::regex_search(stype,match,r)) // member has an anonymous type { + size_t i = match.position(); + size_t l = match.length(); //printf("annoClassDef=%p annMemb=%p scopeName='%s' anonymous='%s'\n", // annoClassDef,annMemb,cname.data(),ltype.mid(i,l).data()); if (annoClassDef) // type is an anonymous compound { - int ir=i+l; + size_t ir=i+l; //printf("<<<<<<<<<<<<<<\n"); ol.startAnonTypeScope(s_indentLevel++); annoClassDef->writeDeclaration(ol,m_impl->annMemb,inGroup,inheritedFrom,inheritId); @@ -2932,6 +2905,9 @@ void MemberDefImpl::_writeTypeConstraints(OutputList &ol) const } } +// match from the start of the scope until the last marker +static const std::regex reAnonymous("[[:alnum:]_:]*@[[:digit:]]+([^@]*@[[:digit:]]+)?"); + void MemberDefImpl::_writeEnumValues(OutputList &ol,const Definition *container, const QCString &cfname,const QCString &ciname, const QCString &cname) const @@ -3032,21 +3008,14 @@ QCString MemberDefImpl::displayDefinition() const ldef=ldef.mid(2); } } - static QRegExp r("@[0-9]+"); - int l,i=r.match(ldef,0,&l); - if (i!=-1) // replace anonymous parts with { ... } + + std::string sdef = ldef.str(); + std::smatch match; + if (std::regex_search(sdef,match,reAnonymous)) { - int si=ldef.find(' '),pi,ei=i+l; - if (si==-1) si=0; - while ((pi=r.match(ldef,i+l,&l))!=-1) - { - i=pi; - ei=i+l; - } - int ni=ldef.find("::",si); - if (ni>=ei) ei=ni+2; - ldef = ldef.left(si) + " { ... } " + ldef.right(ldef.length()-ei); + ldef = match.prefix().str() + " { ... } " + match.suffix().str(); } + const ClassDef *cd=getClassDef(); if (cd && cd->isObjectiveC()) { @@ -3066,9 +3035,9 @@ QCString MemberDefImpl::displayDefinition() const { ldef=ldef.left(dp+1); } - l=ldef.length(); + int l=ldef.length(); //printf("start >%s<\n",ldef.data()); - i=l-1; + int i=l-1; while (i>=0 && (isId(ldef.at(i)) || ldef.at(i)==':')) i--; while (i>=0 && isspace((uchar)ldef.at(i))) i--; if (i>0) @@ -3216,7 +3185,6 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, title += "()"; } int i=0,l; - static QRegExp r("@[0-9]+"); if (lang == SrcLangExt_Slice) { @@ -3237,19 +3205,26 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, QStrList sl; getLabels(sl,scopedContainer); - if ((isVariable() || isTypedef()) && (i=r.match(ldef,0,&l))!=-1) + static std::regex r("@[0-9]+"); + std::smatch match; + std::string sdef = ldef.str(); + if ((isVariable() || isTypedef()) && std::regex_search(sdef,match,r)) { + i = (int)match.position(); + l = (int)match.length(); // find enum type and insert it in the definition bool found=false; for (const auto &vmd : *ml) { - if (vmd->isEnumerate() && ldef.mid(i,l)==vmd->name()) + if (vmd->isEnumerate() && match.str()==vmd->name()) { ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs); ol.startMemberDoc(ciname,name(),memAnchor,name(),memCount,memTotal,showInline); - linkifyText(TextGeneratorOLImpl(ol),scopedContainer,getBodyDef(),this,ldef.left(i)); + std::string prefix = match.prefix().str(); + std::string suffix = match.suffix().str(); + linkifyText(TextGeneratorOLImpl(ol),scopedContainer,getBodyDef(),this,prefix.c_str()); vmd->writeEnumDeclaration(ol,getClassDef(),getNamespaceDef(),getFileDef(),getGroupDef()); - linkifyText(TextGeneratorOLImpl(ol),scopedContainer,getBodyDef(),this,ldef.right(ldef.length()-i-l)); + linkifyText(TextGeneratorOLImpl(ol),scopedContainer,getBodyDef(),this,suffix.c_str()); found=true; break; @@ -3261,21 +3236,20 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs); ol.startMemberDoc(ciname,name(),memAnchor,"",memCount,memTotal,showInline); // search for the last anonymous compound name in the definition - int si=ldef.find(' '),pi,ei=i+l; - if (si==-1) si=0; - while ((pi=r.match(ldef,i+l,&l))!=-1) + + ol.startMemberDocName(isObjCMethod()); + if (std::regex_search(sdef,match,reAnonymous)) { - i=pi; - ei=i+l; + std::string prefix = match.prefix().str(); + std::string suffix = match.suffix().str(); + ol.docify(prefix.c_str()); + ol.docify(" { ... } "); + linkifyText(TextGeneratorOLImpl(ol),scopedContainer,getBodyDef(),this,suffix.c_str()); + } + else + { + linkifyText(TextGeneratorOLImpl(ol),scopedContainer,getBodyDef(),this,ldef); } - // first si characters of ldef contain compound type name - ol.startMemberDocName(isObjCMethod()); - ol.docify(ldef.left(si)); - ol.docify(" { ... } "); - // last ei characters of ldef contain pointer/reference specifiers - int ni=ldef.find("::",si); - if (ni>=ei) ei=ni+2; - linkifyText(TextGeneratorOLImpl(ol),scopedContainer,getBodyDef(),this,ldef.right(ldef.length()-ei)); } } else // not an enum value or anonymous compound @@ -3637,21 +3611,18 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, } // strip scope and field name from the type -// example: "struct N::S.v.c" will become "struct v" +// example: "struct N::S.v.c" will become "struct v" static QCString simplifyTypeForTable(const QCString &s) { QCString ts=removeAnonymousScopes(s); if (ts.right(2)=="::") ts = ts.left(ts.length()-2); - static QRegExp re("[A-Z_a-z0-9]+::"); - int i,l; - while ((i=re.match(ts,0,&l))!=-1) + static const std::regex re("[[:alpha:]_][[:alnum:]_]*(<[^>]*>)?::([[:alpha:]_][[:alnum:]_]*)"); + std::smatch match; + std::string t = ts.str(); + if (std::regex_search(t,match,re)) { - ts=ts.left(i)+ts.mid(i+l); + ts = match[2].str(); // take the identifier after the last :: (second capture group) } - i=ts.findRev('.'); - if (i!=-1) ts = ts.left(i); - i=ts.findRev('.'); - if (i!=-1) ts = ts.right(ts.length()-i-1); //printf("simplifyTypeForTable(%s)->%s\n",s.data(),ts.data()); return ts; } -- cgit v0.12 From 51144470806ec4d17c3e8f2178718ca9d1e11e80 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Thu, 18 Feb 2021 20:26:40 +0100 Subject: Refactoring: replace QRegExp by std::regex in vhdljjparser.cpp --- src/vhdljjparser.cpp | 74 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/src/vhdljjparser.cpp b/src/vhdljjparser.cpp index b666f4c..845602d 100644 --- a/src/vhdljjparser.cpp +++ b/src/vhdljjparser.cpp @@ -10,6 +10,9 @@ * */ +#include +#include + #include #include #include "containers.h" @@ -269,12 +272,33 @@ void VHDLOutlineParser::handleFlowComment(const char* doc) int VHDLOutlineParser::checkInlineCode(QCString &doc) { - QRegExp cs("[\\\\@]code"); - QRegExp cend("[\\s ]*[\\\\@]endcode"); - QRegExp cbrief("[\\\\@]brief"); - int index = doc.find(cs); + static std::regex csRe("[\\\\@]code"); + static std::regex cendRe("[[:space:]]*[\\\\@]endcode"); + static std::regex cbriefRe("[\\\\@]brief"); + + // helper to simulate behavior of QString.find(const QRegExp &re,int pos) + auto findRe = [](const QCString &str,const std::regex &re,int pos=0) -> int + { + if ((int)str.length() QCString + { + return std::regex_replace(str.str(), re, replacement.str()); + }; + + int index = findRe(doc,csRe); - if (doc.contains(cend) > 0) + if (findRe(doc,cendRe)!=-1) return 1; if (index < 0) @@ -282,9 +306,9 @@ int VHDLOutlineParser::checkInlineCode(QCString &doc) VhdlParser::SharedState *s = &p->shared; p->strComment += doc; - p->code = p->inputString.find(cs, p->code + 1); + p->code = findRe(p->inputString,csRe, p->code + 1); int com = p->inputString.find(p->strComment.data()); - int ref = p->inputString.find(cend, p->code + 1); + int ref = findRe(p->inputString,cendRe, p->code + 1); int len = p->strComment.size(); int ll = com + len; @@ -296,24 +320,24 @@ int VHDLOutlineParser::checkInlineCode(QCString &doc) VhdlDocGen::prepareComment(p->strComment); QCStringList ql = QCStringList::split('\n', p->strComment); - QCString co; - QCString na; - for (QCString qcs : ql) - { - qcs = qcs.simplifyWhiteSpace(); - if (qcs.contains(cs)) - { - int i = qcs.find('{'); - int j = qcs.find('}'); - if (i > 0 && j > 0 && j > i) - { - na = qcs.mid(i + 1, (j - i - 1)); - } - continue; - } - qcs = qcs.replace(cbrief, ""); - co += qcs; - co += '\n'; + QCString co; + QCString na; + for (QCString qcs : ql) + { + qcs = qcs.simplifyWhiteSpace(); + if (findRe(qcs,csRe)!=-1) + { + int i = qcs.find('{'); + int j = qcs.find('}'); + if (i > 0 && j > 0 && j > i) + { + na = qcs.mid(i + 1, (j - i - 1)); + } + continue; + } + qcs = replaceRe(qcs,cbriefRe, ""); + co += qcs; + co += '\n'; } VhdlDocGen::prepareComment(co); -- cgit v0.12 From dfa3a285c140f57dfa08f4465ab1432853e92551 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Thu, 18 Feb 2021 21:15:21 +0100 Subject: Refactoring: replace QRegExp by std::regex in vhdlcode.l --- src/util.cpp | 39 +++++++++++++++++++++++++++++++++++++++ src/util.h | 5 +++++ src/vhdlcode.l | 35 ++++++++++++++++++++--------------- 3 files changed, 64 insertions(+), 15 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index e8fcab9..36866dd 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -7485,3 +7485,42 @@ QCString removeEmptyLines(const QCString &s) //printf("removeEmptyLines(%s)=%s\n",s.data(),out.data()); return out.data(); } + +/// split input string \a s by string delimiter \a delimiter. +/// returns a vector of non-empty strings that are between the delimiters +StringVector split(const std::string &s,const std::string &delimiter) +{ + StringVector result; + size_t prev = 0, pos = 0, len = s.length(); + do + { + pos = s.find(delimiter, prev); + if (pos == std::string::npos) pos = len; + if (pos>prev) result.push_back(s.substr(prev,pos-prev)); + prev = pos + delimiter.length(); + } + while (pos #include #include +#include #include #include "types.h" @@ -458,6 +459,10 @@ bool openOutputFile(const char *outFile,QFile &f); void writeExtraLatexPackages(FTextStream &t); void writeLatexSpecialFormulaChars(FTextStream &t); +StringVector split(const std::string &s,const std::string &delimiter); +StringVector split(const std::string &s,const std::regex &delimiter); +int findIndex(StringVector &sv,const std::string &s); + bool recognizeFixedForm(const char* contents, FortranFormat format); FortranFormat convertFileNameFortranParserCode(QCString fn); diff --git a/src/vhdlcode.l b/src/vhdlcode.l index 59872f3..37cc720 100644 --- a/src/vhdlcode.l +++ b/src/vhdlcode.l @@ -30,6 +30,7 @@ #include #include +#include /* * includes @@ -37,7 +38,6 @@ #include #include #include -#include #include #include @@ -226,9 +226,8 @@ XILINX "INST"|"NET"|"PIN"|"BLKNM"|"BUFG"|"COLLAPSE"|"CPLD"|"COMPGRP"|"CONFI [^()\n,--]* { /* write and link a port map lines */ QCString tt(yytext); VhdlDocGen::deleteAllChars(tt,','); - QRegExp r("=>"); - QCStringList ql=QCStringList::split(r,tt); - if (ql.count()>=2) + auto ql = split(tt.str(),"=>"); + if (ql.size()>=2) { unsigned int index=0; QCString t1=ql[0]; @@ -355,17 +354,17 @@ XILINX "INST"|"NET"|"PIN"|"BLKNM"|"BUFG"|"COLLAPSE"|"CPLD"|"COMPGRP"|"CONFI } {ENDEFUNC} { - QRegExp regg("[\\s]"); QCString tt(yytext); codifyLines(yyscanner,yytext,yyextra->currClass.data()); tt=tt.lower(); VhdlDocGen::deleteAllChars(tt,';'); tt.stripWhiteSpace(); - QCStringList ql=QCStringList::split(regg,tt); - int index=ql.findIndex(QCString("if"))+1; - index+=ql.findIndex(QCString("case"))+1; - index+=ql.findIndex(QCString("loop"))+1; - index+=ql.findIndex(QCString("generate"))+1; + static std::regex regg("[[:space:]]+"); + auto ql = split(tt.str(),regg); + int index=findIndex(ql,"if")+1; + index+=findIndex(ql,"case")+1; + index+=findIndex(ql,"loop")+1; + index+=findIndex(ql,"generate")+1; if (index==0) { BEGIN(Bases); @@ -955,18 +954,18 @@ static bool checkVhdlString(yyscan_t yyscanner,QCString &name) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (name.isEmpty()) return false; - static QRegExp regg("[\\s\"]"); int len=name.length(); if (name.at(0)=='"' && name.at(len-1)=='"' && len > 2) { - QCStringList qrl=QCStringList::split(regg,name); + std::string inside = name.str().substr(1,len-2); + static std::regex regg("[[:space:]]+"); + auto qrl=split(inside,regg); if (VhdlDocGen::isNumber(qrl[0])) { yyextra->code->codify("\""); startFontClass(yyscanner,"vhdllogic"); - QCString mid=name.mid(1,len-2); //" 1223 " - yyextra->code->codify(mid.data()); + yyextra->code->codify(inside.c_str()); endFontClass(yyscanner); yyextra->code->codify("\""); } @@ -1329,7 +1328,13 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner,CodeOutputInterface &ol cd = getClass(className.data()); if (!cd && curr_class) { - if (QCString(curr_class).contains(QRegExp("::"+QCString(clName)+"$"))) cd = getClass(curr_class); + QCString cls = curr_class; + QCString suffix = "::"; + suffix+=clName; + if (cls.right(suffix.length())==suffix) + { + cd = getClass(curr_class); + } } while (cd) -- cgit v0.12 From c3754eee8014e15ab673f999986320058aeb7324 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Thu, 18 Feb 2021 22:22:49 +0100 Subject: Refactoring: replace QRegExp by std::regex in vhdldocgen.cpp --- src/util.cpp | 10 +++- src/util.h | 3 +- src/vhdlcode.l | 23 +++---- src/vhdldocgen.cpp | 172 +++++++++++++++++++++-------------------------------- src/vhdldocgen.h | 2 +- 5 files changed, 93 insertions(+), 117 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index 36866dd..c9455d9 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -7518,9 +7518,17 @@ StringVector split(const std::string &s,const std::regex &delimiter) } /// find the index of a string in a vector of strings, returns -1 if the string could not be found -int findIndex(StringVector &sv,const std::string &s) +int findIndex(const StringVector &sv,const std::string &s) { auto it = std::find(sv.begin(),sv.end(),s); return it!=sv.end() ? (int)(it-sv.begin()) : -1; } +/// find the index of the first occurrence of pattern \a re in a string \a s +/// returns -1 if the pattern could not be found +int findIndex(const std::string &s,const std::regex &re) +{ + std::smatch match; + return (std::regex_search(s,match,re)) ? (int)match.position() : -1; +} + diff --git a/src/util.h b/src/util.h index f7f6171..d978c87 100644 --- a/src/util.h +++ b/src/util.h @@ -461,7 +461,8 @@ void writeLatexSpecialFormulaChars(FTextStream &t); StringVector split(const std::string &s,const std::string &delimiter); StringVector split(const std::string &s,const std::regex &delimiter); -int findIndex(StringVector &sv,const std::string &s); +int findIndex(const StringVector &sv,const std::string &s); +int findIndex(const std::string &s,const std::regex &re); bool recognizeFixedForm(const char* contents, FortranFormat format); FortranFormat convertFileNameFortranParserCode(QCString fn); diff --git a/src/vhdlcode.l b/src/vhdlcode.l index 37cc720..7c4b70b 100644 --- a/src/vhdlcode.l +++ b/src/vhdlcode.l @@ -324,7 +324,7 @@ XILINX "INST"|"NET"|"PIN"|"BLKNM"|"BUFG"|"COLLAPSE"|"CPLD"|"COMPGRP"|"CONFI QCString qcs(yytext); VhdlDocGen::deleteAllChars(qcs,'"'); VhdlDocGen::deleteAllChars(qcs,' '); - if (VhdlDocGen::isNumber(qcs)) + if (VhdlDocGen::isNumber(qcs.str())) { writeFont(yyscanner,"vhdllogic",yytext); } @@ -411,7 +411,7 @@ XILINX "INST"|"NET"|"PIN"|"BLKNM"|"BUFG"|"COLLAPSE"|"CPLD"|"COMPGRP"|"CONFI yyextra->vhdlKeyDict.find(yyextra->prevString.str())==yyextra->vhdlKeyDict.end()) { val=val.stripWhiteSpace(); - if (VhdlDocGen::isNumber(val)) + if (VhdlDocGen::isNumber(val.str())) { startFontClass(yyscanner,"vhdllogic"); codifyLines(yyscanner,yytext,yyextra->currClass.data()); @@ -846,7 +846,7 @@ XILINX "INST"|"NET"|"PIN"|"BLKNM"|"BUFG"|"COLLAPSE"|"CPLD"|"COMPGRP"|"CONFI VhdlDocGen::deleteAllChars(qcs,'"'); VhdlDocGen::deleteAllChars(qcs,' '); - if (VhdlDocGen::isNumber(qcs)) + if (VhdlDocGen::isNumber(qcs.str())) { writeFont(yyscanner,"vhdllogic",yytext); } @@ -978,7 +978,7 @@ static bool checkVhdlString(yyscan_t yyscanner,QCString &name) return true; } - if (VhdlDocGen::isNumber(name)) + if (VhdlDocGen::isNumber(name.str())) { startFontClass(yyscanner,"vhdllogic"); yyextra->code->codify(name.data()); @@ -1160,13 +1160,16 @@ static void writeWord(yyscan_t yyscanner,const char *word,const char* curr_class else { QCString qc(temp.data()); - if (VhdlDocGen::isNumber(qc)){ - startFontClass(yyscanner,"vhdllogic"); - yyextra->code->codify(temp.data()); - endFontClass(yyscanner); - } + if (VhdlDocGen::isNumber(qc.str())) + { + startFontClass(yyscanner,"vhdllogic"); + yyextra->code->codify(temp.data()); + endFontClass(yyscanner); + } else - yyextra->code->codify(temp.data()); + { + yyextra->code->codify(temp.data()); + } } } } diff --git a/src/vhdldocgen.cpp b/src/vhdldocgen.cpp index 299ae26..539caae 100644 --- a/src/vhdldocgen.cpp +++ b/src/vhdldocgen.cpp @@ -25,6 +25,9 @@ #include #include #include +#include +#include + #include #include #include @@ -271,23 +274,19 @@ static void writeVhdlDotLink(FTextStream &t, static QCString formatBriefNote(const QCString &brief,ClassDef * cd) { - QRegExp ep("[\n]"); QCString vForm; QCString repl("
    "); QCString file=cd->getDefFileName(); int k=cd->briefLine(); - QCStringList qsl=QCStringList::split(ep,brief); - for(uint j=0;jtypeString(),"inout")==0)); if (md) @@ -325,10 +323,8 @@ static void writeColumn(FTextStream &t,const MemberDef *md,bool start) if (!toolTip.isEmpty()) { QCString largs = md->argsString(); - if (!largs.isEmpty()) - largs=largs.replace(reg," "); toolTip+=" ["; - toolTip+=largs; + toolTip+=substitute(largs,"%"," "); toolTip+="]"; } } @@ -355,7 +351,7 @@ static void writeColumn(FTextStream &t,const MemberDef *md,bool start) QCString largs = md->argsString(); if (!largs.isEmpty()) { - largs=largs.replace(reg," "); + largs=substitute(largs,"%"," "); codify(t,largs.data()); } } @@ -1013,8 +1009,9 @@ void VhdlDocGen::parseFuncProto(const char* text,QCString& name,QCString& ret,bo else { s1=s1.stripWhiteSpace(); - int i=s1.find("(",0,FALSE); - int s=s1.find(QRegExp("[ \\t]")); + int i=s1.find('('); + int s=s1.find(' '); + if (s==-1) s=s1.find('\t'); if (i==-1 || i (unsigned int)index) + if ((size_t)index < ql.size()) { return ql[index]; } @@ -1128,7 +1122,7 @@ QCString VhdlDocGen::getProcessNumber() void VhdlDocGen::writeFormatString(const QCString& s,OutputList&ol,const MemberDef* mdef) { - QRegExp reg("[\\[\\]\\.\\/\\:\\<\\>\\:\\s\\,\\;\\'\\+\\-\\*\\|\\&\\=\\(\\)\"]"); + static std::regex reg("[\\[\\]\\.\\/\\<\\>\\:\\s\\,\\;\\'\\+\\-\\*\\|\\&\\=\\(\\)\"]"); QCString qcs = s; qcs+=QCString(" ");// parsing the last sign QCString find=qcs; @@ -1136,9 +1130,7 @@ void VhdlDocGen::writeFormatString(const QCString& s,OutputList&ol,const MemberD char buf[2]; buf[1]='\0'; - int j; - int len; - j = reg.match(temp.data(),0,&len); + int j = findIndex(temp.str(),reg); ol.startBold(); if (j>=0) @@ -1148,7 +1140,7 @@ void VhdlDocGen::writeFormatString(const QCString& s,OutputList&ol,const MemberD find=find.left(j); buf[0]=temp[j]; const char *ss=VhdlDocGen::findKeyWord(find); - bool k=isNumber(find); // is this a number + bool k=isNumber(find.str()); // is this a number if (k) { ol.docify(" "); @@ -1184,7 +1176,7 @@ void VhdlDocGen::writeFormatString(const QCString& s,OutputList&ol,const MemberD { temp=st; } - j = reg.match(temp.data(),0,&len); + j = findIndex(temp.str(),reg); }//while }//if else @@ -1197,16 +1189,10 @@ void VhdlDocGen::writeFormatString(const QCString& s,OutputList&ol,const MemberD /*! * returns TRUE if this string is a number */ -bool VhdlDocGen::isNumber(const QCString& s) +bool VhdlDocGen::isNumber(const std::string& s) { - static QRegExp regg("[0-9][0-9eEfFbBcCdDaA_.#-+?xXzZ]*"); - - if (s.isEmpty()) return FALSE; - int j,len; - j = regg.match(s.data(),0,&len); - if ((j==0) && (len==(int)s.length())) return TRUE; - return FALSE; - + static std::regex regg("[0-9][0-9eEfFbBcCdDaA_.#-+?xXzZ]*"); + return std::regex_match(s,regg); }// isNumber @@ -1666,7 +1652,7 @@ bool VhdlDocGen::writeVHDLTypeDocumentation(const MemberDef* mdef, const Definit writeLink(mdef,ol); ol.docify(" "); - largs=largs.replace(QRegExp("#")," "); + largs=substitute(largs,"#"," "); VhdlDocGen::formatString(largs,ol,mdef); return hasParams; } @@ -2312,8 +2298,8 @@ void VhdlDocGen::parseUCF(const char* input, Entry* entity,QCString fileName,b } else { - QRegExp ee("[\\s=]"); - int in=temp.find(ee); + static std::regex ee("[[:space:]=]"); + int in=findIndex(temp.str(),ee); QCString ff=temp.left(in); temp.stripPrefix(ff.data()); ff.append("#"); @@ -2332,14 +2318,14 @@ void VhdlDocGen::parseUCF(const char* input, Entry* entity,QCString fileName,b static void initUCF(Entry* root,const char* type,QCString & qcs,int line,QCString & fileName,QCString & brief) { if (qcs.isEmpty())return; - QRegExp reg("[\\s=]"); QCString n; // bool bo=(qstricmp(type,qcs.data())==0); VhdlDocGen::deleteAllChars(qcs,';'); qcs=qcs.stripWhiteSpace(); - int i= qcs.find(reg); + static std::regex reg("[[:space:]=]"); + int i = findIndex(qcs.str(),reg); if (i<0) return; if (i==0) { @@ -2417,26 +2403,28 @@ static void writeUCFLink(const MemberDef* mdef,OutputList &ol) // for cell_inst : [entity] work.proto [ (label|expr) ] QCString VhdlDocGen::parseForConfig(QCString & entity,QCString & arch) { - int index; QCString label; if (!entity.contains(":")) return ""; - QRegExp exp("[:()\\s]"); - QCStringList ql=QCStringList::split(exp,entity); - //int ii=ql.findIndex(ent); - assert(ql.count()>=2); + static std::regex exp("[:()[:space:]]"); + auto ql=split(entity.str(),exp); + if (ql.size()<2) + { + return ""; + } label = ql[0]; entity = ql[1]; + int index; if ((index=entity.findRev("."))>=0) { entity.remove(0,index+1); } - if (ql.count()==3) + if (ql.size()==3) { - arch= ql[2]; - ql=QCStringList::split(exp,arch); - if (ql.count()>1) // expression + arch = ql[2]; + ql=split(arch.str(),exp); + if (ql.size()>1) // expression { arch=""; } @@ -2448,26 +2436,29 @@ QCString VhdlDocGen::parseForConfig(QCString & entity,QCString & arch) QCString VhdlDocGen::parseForBinding(QCString & entity,QCString & arch) { - int index; - QRegExp exp("[()\\s]"); + static std::regex exp("[()[:space:]]"); - QCString label=""; - QCStringList ql=QCStringList::split(exp,entity); + auto ql = split(entity.str(),exp); - if (ql.contains("open")) + if (findIndex(ql,"open")!=-1) { return "open"; } - label=ql[0]; + if (ql.size()<2) + { + return ""; + } + std::string label=ql[0]; entity = ql[1]; + int index; if ((index=entity.findRev("."))>=0) { entity.remove(0,index+1); } - if (ql.count()==3) + if (ql.size()==3) { arch=ql[2]; } @@ -2607,14 +2598,6 @@ ferr: md->setDocumentation(cur->doc.data(),cur->docFile.data(),cur->docLine); FileDef *fd=ar->getFileDef(); md->setBodyDef(fd); - //QCString info="Info: Elaborating entity "+n1; - //fd=ar->getFileDef(); - //info+=" for hierarchy "; - //QRegExp epr("[|]"); - //QCString label=cur->type+":"+cur->write+":"+cur->name; - //label.replace(epr,":"); - //info+=label; - //fprintf(stderr,"\n[%s:%d:%s]\n",fd->fileName().data(),cur->startLine,info.data()); ar->insertMember(md.get()); MemberName *mn = Doxygen::functionNameLinkedMap->add(uu); mn->push_back(std::move(md)); @@ -2721,15 +2704,15 @@ void VhdlDocGen::addBaseClass(ClassDef* cd,ClassDef *ent) bcd.usedName.append("(2)"); return; } - static QRegExp reg("[0-9]+"); + static std::regex reg("[[:digit:]]+"); QCString s=n.left(i); QCString r=n.right(n.length()-i); - QCString t=r; + std::string t=r.str(); VhdlDocGen::deleteAllChars(r,')'); VhdlDocGen::deleteAllChars(r,'('); r.setNum(r.toInt()+1); - t.replace(reg,r.data()); - s.append(t.data()); + std::regex_replace(t, reg, r.str()); + s.append(t.c_str()); bcd.usedName=s; bcd.templSpecifiers=t; } @@ -2913,13 +2896,12 @@ void alignText(QCString & q) q.append(" ..."); - QRegExp reg("[\\s|]"); QCString str(q.data()); QCString temp; while (str.length()>80) { - int j=str.findRev(reg,80); + int j=std::max(str.findRev(' ',80),str.findRev('|',80)); if (j<=0) { temp+=str; @@ -2942,8 +2924,8 @@ void alignText(QCString & q) void FlowChart::printNode(const FlowChart& flo) { QCString ui="-"; - QCString q,t; - QRegExp ep("[\t\n\r]"); + std::string q; + std::string t; ui.fill('-',255); @@ -2951,7 +2933,7 @@ void FlowChart::printNode(const FlowChart& flo) { if (flo.stamp>0) { - q=ui.left(2*flo.stamp); + q=ui.left(2*flo.stamp).str(); } else { @@ -2964,20 +2946,21 @@ void FlowChart::printNode(const FlowChart& flo) { if (flo.type & COMMENT_NO) { - t=flo.label; + t=flo.label.str(); } else { - t=flo.text; + t=flo.text.str(); } - t=t.replace(ep,""); - if (t.isEmpty()) + static std::regex ep("[[:space:]]"); + t = std::regex_replace(t,ep,std::string("")); + if (t.empty()) { t=" "; } if (flo.stamp>0) { - q=ui.left(2*flo.stamp); + q=ui.left(2*flo.stamp).str(); } else { @@ -2985,15 +2968,15 @@ void FlowChart::printNode(const FlowChart& flo) } if (flo.type & EMPTNODE) { - printf("\n NO: %s%s[%d,%d]",q.data(),FlowChart::getNodeType(flo.type),flo.stamp,flo.id); + printf("\n NO: %s%s[%d,%d]",q.c_str(),FlowChart::getNodeType(flo.type),flo.stamp,flo.id); } else if (flo.type & COMMENT_NO) { - printf("\n NO: %s%s[%d,%d]",t.data(),FlowChart::getNodeType(flo.type),flo.stamp,flo.id); + printf("\n NO: %s%s[%d,%d]",t.c_str(),FlowChart::getNodeType(flo.type),flo.stamp,flo.id); } else { - printf("\n NO: %s[%d,%d]",t.data(),flo.stamp,flo.id); + printf("\n NO: %s[%d,%d]",t.c_str(),flo.stamp,flo.id); } } } @@ -3247,9 +3230,6 @@ FlowChart::FlowChart(int typ,const char * t,const char* ex,const char* lab) void FlowChart::addFlowChart(int type,const char* text,const char* exp, const char *label) { - static QRegExp reg("[;]"); - static QRegExp reg1("[\"]"); - if (!VhdlDocGen::getFlowMember()) return; QCString typeString(text); @@ -3258,12 +3238,12 @@ void FlowChart::addFlowChart(int type,const char* text,const char* exp, const ch if (text) { - typeString=typeString.replace(reg,"\n"); + typeString=substitute(typeString,";","\n"); } if (exp) { - expression=expression.replace(reg1,"\\\""); + expression=substitute(expression,"\"","\\\""); } if (type & (START_NO | VARIABLE_NO)) @@ -3366,23 +3346,7 @@ void FlowChart::printUmlTree() QCString FlowChart::convertNameToFileName() { - static QRegExp exp ("[^][a-z_A-Z0-9]"); - QCString temp,qcs; - const MemberDef* md=VhdlDocGen::getFlowMember(); - - // temp.sprintf("%p",md); - qcs=md->name(); - - #if 0 - if (qcs.find(exp,0)>=0) - { - qcs.prepend("Z"); - qcs=qcs.replace(exp,"_"); - } - #endif - - //QCString tt= qcs;VhdlDocGen::getRecordNumber(); - return qcs; + return VhdlDocGen::getFlowMember()->name(); } const char* FlowChart::getNodeType(int c) diff --git a/src/vhdldocgen.h b/src/vhdldocgen.h index 46c23a8..3a55b45 100644 --- a/src/vhdldocgen.h +++ b/src/vhdldocgen.h @@ -207,7 +207,7 @@ class VhdlDocGen static QCString getRecordNumber(); static QCString getClassName(const ClassDef*); - static bool isNumber(const QCString& s); + static bool isNumber(const std::string& s); static QCString getProtectionName(int prot); static void parseUCF(const char* input,Entry* entity,QCString f,bool vendor); -- cgit v0.12 From a59cd278932b11820dde87e764052622aa38980b Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Thu, 18 Feb 2021 22:26:30 +0100 Subject: Refactoring: replace QRegExp by std::regex in doxyparse.cpp --- addon/doxyparse/doxyparse.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/addon/doxyparse/doxyparse.cpp b/addon/doxyparse/doxyparse.cpp index dde9eb1..4059861 100644 --- a/addon/doxyparse/doxyparse.cpp +++ b/addon/doxyparse/doxyparse.cpp @@ -42,7 +42,6 @@ #include #include #include -#include #include "namespacedef.h" #include "portable.h" @@ -184,8 +183,8 @@ static int isPartOfCStruct(const MemberDef * md) { std::string sanitizeString(std::string data) { QCString new_data = QCString(data.c_str()); - new_data.replace(QRegExp("\""), ""); - new_data.replace(QRegExp("\\"), ""); // https://github.com/analizo/analizo/issues/138 + new_data = substitute(new_data,"\"", ""); + new_data = substitute(new_data,"\'", ""); // https://github.com/analizo/analizo/issues/138 return !new_data.isEmpty() ? new_data.data() : ""; } -- cgit v0.12 From cfdea8320f089c0f25fe72ecfb7ede76e39110d8 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Sat, 20 Feb 2021 18:50:41 +0100 Subject: Disable qregex.h and fix some warnings and issues --- qtools/qcstring.cpp | 10 +++++- qtools/qcstring.h | 10 +++--- qtools/qcstringlist.cpp | 4 +++ qtools/qcstringlist.h | 6 ++-- qtools/qdir.cpp | 2 +- qtools/qdir_unix.cpp | 2 +- qtools/qdir_win32.cpp | 26 +++++++------- qtools/qregexp.cpp | 2 +- qtools/qregexp.h | 92 ------------------------------------------------- qtools/qregexp_p.h | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ qtools/qstring.cpp | 5 +-- qtools/qstring.h | 10 +++--- qtools/qstringlist.cpp | 6 +++- qtools/qstringlist.h | 6 ++-- qtools/qtextstream.cpp | 3 +- src/classdef.cpp | 4 +-- src/definition.cpp | 2 +- src/docparser.cpp | 1 - src/doctokenizer.l | 1 - src/doxygen.cpp | 2 +- src/htmlgen.cpp | 3 +- src/index.cpp | 1 - src/layout.h | 1 - src/mangen.cpp | 1 - src/memberdef.cpp | 24 ++++++------- src/memberdef.h | 1 - src/memberlist.cpp | 2 -- src/pagedef.cpp | 2 -- src/rtfgen.cpp | 2 -- src/util.cpp | 38 ++++++++++---------- src/util.h | 2 +- src/vhdldocgen.cpp | 4 +-- 32 files changed, 183 insertions(+), 184 deletions(-) delete mode 100644 qtools/qregexp.h create mode 100644 qtools/qregexp_p.h diff --git a/qtools/qcstring.cpp b/qtools/qcstring.cpp index da7a46f..7e496fd 100644 --- a/qtools/qcstring.cpp +++ b/qtools/qcstring.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +//#include #include QCString &QCString::sprintf( const char *format, ... ) @@ -87,12 +87,14 @@ int QCString::find( const QCString &str, int index, bool cs ) const return find(str.data(),index,cs); } +#if 0 int QCString::find( const QRegExp &rx, int index ) const { if ( index < 0 ) index += length(); return rx.match( data(), index ); } +#endif int QCString::findRev( char c, int index, bool cs) const { @@ -146,6 +148,7 @@ int QCString::findRev( const char *str, int index, bool cs) const return -1; } +#if 0 int QCString::findRev( const QRegExp &rx, int index ) const { if ( index < 0 ) // neg index ==> start from end @@ -159,6 +162,7 @@ int QCString::findRev( const QRegExp &rx, int index ) const } return -1; } +#endif int QCString::contains( char c, bool cs ) const { @@ -202,6 +206,7 @@ int QCString::contains( const char *str, bool cs ) const return count; } +#if 0 int QCString::contains( const QRegExp &rx ) const { if ( isEmpty() ) @@ -217,6 +222,7 @@ int QCString::contains( const QRegExp &rx ) const } return count; } +#endif QCString QCString::simplifyWhiteSpace() const @@ -253,6 +259,7 @@ QCString &QCString::replace( uint index, uint len, const char *s) return *this; } +#if 0 QCString &QCString::replace( const QRegExp &rx, const char *str ) { if ( isEmpty() ) @@ -273,6 +280,7 @@ QCString &QCString::replace( const QRegExp &rx, const char *str ) } return *this; } +#endif static bool ok_in_base( char c, int base ) { diff --git a/qtools/qcstring.h b/qtools/qcstring.h index a70f8f4..bdd99f0 100644 --- a/qtools/qcstring.h +++ b/qtools/qcstring.h @@ -94,7 +94,7 @@ QDataStream &operator<<( QDataStream &, const QByteArray & ); QDataStream &operator>>( QDataStream &, QByteArray & ); #endif -class QRegExp; +//class QRegExp; /** This is an alternative implementation of QCString. It provides basically * the same functions but uses std::string as the underlying string type @@ -181,15 +181,15 @@ class QCString int find( char c, int index=0, bool cs=TRUE ) const; int find( const char *str, int index=0, bool cs=TRUE ) const; int find( const QCString &str, int index=0, bool cs=TRUE ) const; - int find( const QRegExp &rx, int index=0 ) const; + //int find( const QRegExp &rx, int index=0 ) const; int findRev( char c, int index=-1, bool cs=TRUE) const; int findRev( const char *str, int index=-1, bool cs=TRUE) const; - int findRev( const QRegExp &rx, int index=-1 ) const; + //int findRev( const QRegExp &rx, int index=-1 ) const; int contains( char c, bool cs=TRUE ) const; int contains( const char *str, bool cs=TRUE ) const; - int contains( const QRegExp &rx ) const; + //int contains( const QRegExp &rx ) const; bool stripPrefix(const char *prefix) { @@ -295,7 +295,7 @@ class QCString } QCString &replace( uint index, uint len, const char *s); - QCString &replace( const QRegExp &rx, const char *str ); + //QCString &replace( const QRegExp &rx, const char *str ); short toShort( bool *ok=0, int base=10 ) const; ushort toUShort( bool *ok=0, int base=10 ) const; diff --git a/qtools/qcstringlist.cpp b/qtools/qcstringlist.cpp index f1c4599..b8926ad 100644 --- a/qtools/qcstringlist.cpp +++ b/qtools/qcstringlist.cpp @@ -76,6 +76,7 @@ QCStringList QCStringList::split( const QCString &sep, const QCString &str, bool return lst; } +#if 0 /*! Splits the string \a str using the regular expression \a sep as separator. Returns the list of strings. If \a allowEmptyEntries is TRUE, also empty @@ -115,6 +116,7 @@ QCStringList QCStringList::split( const QRegExp &sep, const QCString &str, bool return lst; } +#endif /*! Returns a list of all strings containing the substring \a str. @@ -132,6 +134,7 @@ QCStringList QCStringList::grep( const QCString &str, bool cs ) const return res; } +#if 0 /*! Returns a list of all strings containing a substring that matches the regular expression \a expr. @@ -146,6 +149,7 @@ QCStringList QCStringList::grep( const QRegExp &expr ) const return res; } +#endif /*! Joins the stringlist into a single string with each element diff --git a/qtools/qcstringlist.h b/qtools/qcstringlist.h index a7d79b0..6f390b0 100644 --- a/qtools/qcstringlist.h +++ b/qtools/qcstringlist.h @@ -16,7 +16,7 @@ #include "qvaluelist_p.h" #include "qcstring.h" -#include "qregexp.h" +//#include "qregexp.h" class QStrList; class QDataStream; @@ -38,11 +38,11 @@ public: static QCStringList split( const QCString &sep, const QCString &str, bool allowEmptyEntries = FALSE ); static QCStringList split( char sep, const QCString &str, bool allowEmptyEntries = FALSE ); - static QCStringList split( const QRegExp &sep, const QCString &str, bool allowEmptyEntries = FALSE ); + //static QCStringList split( const QRegExp &sep, const QCString &str, bool allowEmptyEntries = FALSE ); QCString join( const QCString &sep ) const; QCStringList grep( const QCString &str, bool cs = TRUE ) const; - QCStringList grep( const QRegExp &expr ) const; + //QCStringList grep( const QRegExp &expr ) const; }; extern Q_EXPORT QDataStream &operator>>( QDataStream &, QCStringList& ); diff --git a/qtools/qdir.cpp b/qtools/qdir.cpp index fc84cbc..016313f 100644 --- a/qtools/qdir.cpp +++ b/qtools/qdir.cpp @@ -42,7 +42,7 @@ #ifndef QT_NO_DIR #include "qfileinfo.h" #include "qfiledefs_p.h" -#include "qregexp.h" +#include "qregexp_p.h" #include "qstringlist.h" #include #include diff --git a/qtools/qdir_unix.cpp b/qtools/qdir_unix.cpp index 520af79..fa3c42e 100644 --- a/qtools/qdir_unix.cpp +++ b/qtools/qdir_unix.cpp @@ -42,7 +42,7 @@ #include "qfileinfo.h" #include "qfiledefs_p.h" -#include "qregexp.h" +//#include "qregexp.h" #include "qstringlist.h" #include #include diff --git a/qtools/qdir_win32.cpp b/qtools/qdir_win32.cpp index 324ff24..f7f2982 100644 --- a/qtools/qdir_win32.cpp +++ b/qtools/qdir_win32.cpp @@ -1,19 +1,19 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2001 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. * * Documents produced by Doxygen are derivative works derived from the * input used in their production; they are not affected by this license. * - * Based on qdir_unix.cpp + * Based on qdir_unix.cpp * * Copyright (C) 1992-2000 Trolltech AS. */ @@ -27,7 +27,7 @@ #include "qfileinfo.h" #include "qfiledefs_p.h" -#include "qregexp.h" +#include "qregexp_p.h" #include "qstringlist.h" #include #include @@ -80,7 +80,7 @@ static QString p_getenv( QString name ) void QDir::slashify( QString& n ) { - for ( int i=0; i<(int)n.length(); i++ ) + for ( int i=0; i<(int)n.length(); i++ ) { if ( n[i] == '\\' ) n[i] = '/'; @@ -175,7 +175,7 @@ bool QDir::rename( const QString &name, const QString &newName, return ::rename( QFile::encodeName(fn1), QFile::encodeName(fn2) ) == 0; #else - return MoveFileW( ( LPCWSTR ) fn1.ucs2(), ( LPCWSTR ) fn2.ucs2() ) != 0; + return MoveFileW( ( LPCWSTR ) fn1.ucs2(), ( LPCWSTR ) fn2.ucs2() ) != 0; #endif } @@ -343,7 +343,7 @@ bool QDir::readDirEntries( const QString &nameFilter, #else ff = FindFirstFileW ( ( LPCWSTR ) p.ucs2(), &finfo ); #endif - if ( ff == FF_ERROR ) + if ( ff == FF_ERROR ) { #if defined(DEBUG) warning( "QDir::readDirEntries: Cannot read the directory: %s", @@ -351,12 +351,12 @@ bool QDir::readDirEntries( const QString &nameFilter, #endif return FALSE; } - - while ( TRUE ) + + while ( TRUE ) { if ( first ) first = FALSE; - else + else { #if defined(__CYGWIN32_) if ( FF_GETNEXT(ff,&finfo) == -1 ) @@ -393,7 +393,7 @@ bool QDir::readDirEntries( const QString &nameFilter, continue; QString name = fname; - if ( doExecable ) + if ( doExecable ) { QString ext = name.right(4).lower(); if ( ext == ".exe" || ext == ".com" || ext == ".bat" || @@ -401,7 +401,7 @@ bool QDir::readDirEntries( const QString &nameFilter, isExecable = TRUE; } - if ( (doDirs && isDir) || (doFiles && isFile) ) + if ( (doDirs && isDir) || (doFiles && isFile) ) { if ( noSymLinks && isSymLink ) continue; diff --git a/qtools/qregexp.cpp b/qtools/qregexp.cpp index 8709858..08138f5 100644 --- a/qtools/qregexp.cpp +++ b/qtools/qregexp.cpp @@ -35,7 +35,7 @@ ** **********************************************************************/ -#include "qregexp.h" +#include "qregexp_p.h" #include #include diff --git a/qtools/qregexp.h b/qtools/qregexp.h deleted file mode 100644 index 4bb0230..0000000 --- a/qtools/qregexp.h +++ /dev/null @@ -1,92 +0,0 @@ -/**************************************************************************** -** -** -** Definition of QRegExp class -** -** Created : 950126 -** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. -** -** This file is part of the tools module of the Qt GUI Toolkit. -** -** This file may be distributed under the terms of the Q Public License -** as defined by Trolltech AS of Norway and appearing in the file -** LICENSE.QPL included in the packaging of this file. -** -** This file may be distributed and/or modified under the terms of the -** GNU General Public License version 2 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. -** -** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition -** licenses may use this file in accordance with the Qt Commercial License -** Agreement provided with the Software. -** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** -** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for -** information about Qt Commercial License Agreements. -** See http://www.trolltech.com/qpl/ for QPL licensing information. -** See http://www.trolltech.com/gpl/ for GPL licensing information. -** -** Contact info@trolltech.com if any conditions of this licensing are -** not clear to you. -** -**********************************************************************/ - -#ifndef QREGEXP_H -#define QREGEXP_H - -#ifndef QT_H -#include "qcstring.h" -#endif // QT_H - - -class Q_EXPORT QRegExp -{ -public: - QRegExp(); - QRegExp( const QCString &, bool caseSensitive=TRUE, bool wildcard=FALSE ); - QRegExp( const QRegExp & ); - ~QRegExp(); - QRegExp &operator=( const QRegExp & ); - QRegExp &operator=( const QCString &pattern ); - - bool operator==( const QRegExp & ) const; - bool operator!=( const QRegExp &r ) const - { return !(this->operator==(r)); } - - bool isEmpty() const { return rxdata == 0; } - bool isValid() const { return error == 0; } - - bool caseSensitive() const { return cs; } - void setCaseSensitive( bool ); - - bool wildcard() const { return wc; } - void setWildcard( bool ); - - QCString pattern() const { return rxstring; } - // ### in Qt 3.0, provide a real implementation - void setPattern( const QCString& pattern ) - { operator=( pattern ); } - - int match( const QCString &str, int index=0, int *len=0, - bool indexIsStart = TRUE ) const; - int find( const QCString& str, int index ) - { return match( str, index ); } - -protected: - void compile(); - const char *matchstr( uint *, const char *, uint, const char * ) const; - -private: - QCString rxstring; // regular expression pattern - uint *rxdata; // compiled regexp pattern - int error; // error status - bool cs; // case sensitive - bool wc; // wildcard -}; - - -#endif // QREGEXP_H diff --git a/qtools/qregexp_p.h b/qtools/qregexp_p.h new file mode 100644 index 0000000..4bb0230 --- /dev/null +++ b/qtools/qregexp_p.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** +** Definition of QRegExp class +** +** Created : 950126 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QREGEXP_H +#define QREGEXP_H + +#ifndef QT_H +#include "qcstring.h" +#endif // QT_H + + +class Q_EXPORT QRegExp +{ +public: + QRegExp(); + QRegExp( const QCString &, bool caseSensitive=TRUE, bool wildcard=FALSE ); + QRegExp( const QRegExp & ); + ~QRegExp(); + QRegExp &operator=( const QRegExp & ); + QRegExp &operator=( const QCString &pattern ); + + bool operator==( const QRegExp & ) const; + bool operator!=( const QRegExp &r ) const + { return !(this->operator==(r)); } + + bool isEmpty() const { return rxdata == 0; } + bool isValid() const { return error == 0; } + + bool caseSensitive() const { return cs; } + void setCaseSensitive( bool ); + + bool wildcard() const { return wc; } + void setWildcard( bool ); + + QCString pattern() const { return rxstring; } + // ### in Qt 3.0, provide a real implementation + void setPattern( const QCString& pattern ) + { operator=( pattern ); } + + int match( const QCString &str, int index=0, int *len=0, + bool indexIsStart = TRUE ) const; + int find( const QCString& str, int index ) + { return match( str, index ); } + +protected: + void compile(); + const char *matchstr( uint *, const char *, uint, const char * ) const; + +private: + QCString rxstring; // regular expression pattern + uint *rxdata; // compiled regexp pattern + int error; // error status + bool cs; // case sensitive + bool wc; // wildcard +}; + + +#endif // QREGEXP_H diff --git a/qtools/qstring.cpp b/qtools/qstring.cpp index a964aca..c03ca3a 100644 --- a/qtools/qstring.cpp +++ b/qtools/qstring.cpp @@ -42,7 +42,7 @@ #endif #include "qstring.h" -#include "qregexp.h" +#include "qregexp_p.h" #include "qdatastream.h" #include "qtextcodec.h" #include "qstack_p.h" @@ -13750,7 +13750,7 @@ QString &QString::replace( uint index, uint len, const QChar* s, uint slen ) } - +#if 0 /*! Finds the first occurrence of the regular expression \a rx, starting at position \a index. If \a index is -1, the search starts at the last @@ -13863,6 +13863,7 @@ QString &QString::replace( const QRegExp &rx, const QString &str ) } return *this; } +#endif static bool ok_in_base( QChar c, int base ) diff --git a/qtools/qstring.h b/qtools/qstring.h index ed56d7f..c35faf3 100644 --- a/qtools/qstring.h +++ b/qtools/qstring.h @@ -49,7 +49,7 @@ QString class *****************************************************************************/ -class QRegExp; +//class QRegExp; class QString; class QCharRef; @@ -451,14 +451,14 @@ public: int find( QChar c, int index=0, bool cs=TRUE ) const; int find( char c, int index=0, bool cs=TRUE ) const; int find( const QString &str, int index=0, bool cs=TRUE ) const; - int find( const QRegExp &, int index=0 ) const; + //int find( const QRegExp &, int index=0 ) const; #ifndef QT_NO_CAST_ASCII int find( const char* str, int index=0 ) const; #endif int findRev( QChar c, int index=-1, bool cs=TRUE) const; int findRev( char c, int index=-1, bool cs=TRUE) const; int findRev( const QString &str, int index=-1, bool cs=TRUE) const; - int findRev( const QRegExp &, int index=-1 ) const; + //int findRev( const QRegExp &, int index=-1 ) const; #ifndef QT_NO_CAST_ASCII int findRev( const char* str, int index=-1 ) const; #endif @@ -469,7 +469,7 @@ public: int contains( const char* str, bool cs=TRUE ) const; #endif int contains( const QString &str, bool cs=TRUE ) const; - int contains( const QRegExp & ) const; + //int contains( const QRegExp & ) const; QString left( uint len ) const; QString right( uint len ) const; @@ -497,7 +497,7 @@ public: QString &remove( uint index, uint len ); QString &replace( uint index, uint len, const QString & ); QString &replace( uint index, uint len, const QChar*, uint clen ); - QString &replace( const QRegExp &, const QString & ); + //QString &replace( const QRegExp &, const QString & ); short toShort( bool *ok=0, int base=10 ) const; ushort toUShort( bool *ok=0, int base=10 ) const; diff --git a/qtools/qstringlist.cpp b/qtools/qstringlist.cpp index aa7ac16..ef1a43e 100644 --- a/qtools/qstringlist.cpp +++ b/qtools/qstringlist.cpp @@ -1,5 +1,5 @@ /**************************************************************************** -** +** ** ** Implementation of QStringList ** @@ -189,6 +189,7 @@ QStringList QStringList::split( const QCString &sep, const QCString &str, bool a return split(QString(sep.data()),QString(str.data()),allowEmptyEntries); } +#if 0 /*! Splits the string \a str using the regular expression \a sep as separator. Returns the list of strings. If \a allowEmptyEntries is TRUE, also empty @@ -228,6 +229,7 @@ QStringList QStringList::split( const QRegExp &sep, const QString &str, bool all return lst; } +#endif /*! Returns a list of all strings containing the substring \a str. @@ -245,6 +247,7 @@ QStringList QStringList::grep( const QString &str, bool cs ) const return res; } +#if 0 /*! Returns a list of all strings containing a substring that matches the regular expression \a expr. @@ -259,6 +262,7 @@ QStringList QStringList::grep( const QRegExp &expr ) const return res; } +#endif /*! Joins the stringlist into a single string with each element diff --git a/qtools/qstringlist.h b/qtools/qstringlist.h index 5e1e258..13703a1 100644 --- a/qtools/qstringlist.h +++ b/qtools/qstringlist.h @@ -41,7 +41,7 @@ #ifndef QT_H #include "qvaluelist_p.h" #include "qstring.h" -#include "qregexp.h" +//#include "qregexp.h" #endif // QT_H #ifndef QT_NO_STRINGLIST @@ -66,11 +66,11 @@ public: static QStringList split( const QString &sep, const QString &str, bool allowEmptyEntries = FALSE ); static QStringList split( const QCString &sep, const QCString &str, bool allowEmptyEntries = FALSE ); static QStringList split( const QChar &sep, const QString &str, bool allowEmptyEntries = FALSE ); - static QStringList split( const QRegExp &sep, const QString &str, bool allowEmptyEntries = FALSE ); + //static QStringList split( const QRegExp &sep, const QString &str, bool allowEmptyEntries = FALSE ); QString join( const QString &sep ) const; QStringList grep( const QString &str, bool cs = TRUE ) const; - QStringList grep( const QRegExp &expr ) const; + //QStringList grep( const QRegExp &expr ) const; }; #ifndef QT_NO_DATASTREAM diff --git a/qtools/qtextstream.cpp b/qtools/qtextstream.cpp index ffbdeba..a3abb53 100644 --- a/qtools/qtextstream.cpp +++ b/qtools/qtextstream.cpp @@ -1,5 +1,5 @@ /**************************************************************************** -** +** ** ** Implementation of QTextStream class ** @@ -39,7 +39,6 @@ #ifndef QT_NO_TEXTSTREAM #include "qtextcodec.h" -#include "qregexp.h" #include "qbuffer.h" #include "qfile.h" #include diff --git a/src/classdef.cpp b/src/classdef.cpp index 9636d97..3e602b0 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -1627,7 +1627,7 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const if (!m_impl->inherits.empty()) { - auto replaceFunc = [this](OutputList &ol,size_t entryIndex) + auto replaceFunc = [this,&ol](size_t entryIndex) { BaseClassDef &bcd=m_impl->inherits[entryIndex]; ClassDef *cd=bcd.classDef; @@ -1662,7 +1662,7 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const if (!m_impl->inheritedBy.empty()) { - auto replaceFunc = [this](OutputList &ol,size_t entryIndex) + auto replaceFunc = [this,&ol](size_t entryIndex) { BaseClassDef &bcd=m_impl->inheritedBy[entryIndex]; ClassDef *cd=bcd.classDef; diff --git a/src/definition.cpp b/src/definition.cpp index 7ee2314..6a5b6e3 100644 --- a/src/definition.cpp +++ b/src/definition.cpp @@ -1208,7 +1208,7 @@ void DefinitionImpl::_writeSourceRefList(OutputList &ol,const char *scopeName, { auto members = refMapToVector(membersMap); - auto replaceFunc = [this,&members,scopeName](OutputList &ol,size_t entryIndex) + auto replaceFunc = [this,&members,scopeName,&ol](size_t entryIndex) { const MemberDef *md=members[entryIndex]; if (md) diff --git a/src/docparser.cpp b/src/docparser.cpp index 725cee0..9fbfef1 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include diff --git a/src/doctokenizer.l b/src/doctokenizer.l index d2ba897..ad6ac11 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -31,7 +31,6 @@ #include #include -#include #include "doctokenizer.h" #include "cmdmapper.h" diff --git a/src/doxygen.cpp b/src/doxygen.cpp index f7849a3..3fd1069 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -2220,7 +2220,7 @@ static MemberDef *addVariableToFile( { ttype.stripPrefix("struct "); ttype.stripPrefix("union "); - static std::regex re("[:alpha:]_][:alnum:]_]*"); + static std::regex re("[[:alpha:]_][[:alnum:]_]*"); std::smatch match; std::string typ = ttype.str(); if (std::regex_search(typ,match,re)) diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp index c9f7bf2..3f335e5 100644 --- a/src/htmlgen.cpp +++ b/src/htmlgen.cpp @@ -21,7 +21,6 @@ #include #include -#include #include "message.h" #include "htmlgen.h" #include "config.h" @@ -1075,7 +1074,7 @@ void HtmlGenerator::startFile(const char *name,const char *, } m_lastFile = fileName; - t << substituteHtmlKeywords(g_header,convertToHtml(filterTitle(title)),m_relPath); + t << substituteHtmlKeywords(g_header,convertToHtml(filterTitle(title?title:"")),m_relPath); t << "" << endl; diff --git a/src/index.cpp b/src/index.cpp index 1e35b30..0984ac2 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include "message.h" #include "index.h" diff --git a/src/layout.h b/src/layout.h index 4dce583..851af22 100644 --- a/src/layout.h +++ b/src/layout.h @@ -26,7 +26,6 @@ class LayoutParser; struct LayoutNavEntry; class MemberList; -class QTextStream; /** @brief Base class representing a piece of a documentation page */ struct LayoutDocEntry diff --git a/src/mangen.cpp b/src/mangen.cpp index e58aa6e..9139aa8 100644 --- a/src/mangen.cpp +++ b/src/mangen.cpp @@ -445,7 +445,6 @@ void ManGenerator::startDoxyAnchor(const char *,const char *manName, { FTextStream linkstream; linkstream.setDevice(&linkfile); - //linkstream.setEncoding(QTextStream::UnicodeUTF8); linkstream << ".so " << getSubdir() << "/" << buildFileName( manName ) << endl; } } diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 0a64659..b3415ff 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -2109,14 +2109,14 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, bool endAnonScopeNeeded=FALSE; if (std::regex_search(stype,match,r)) // member has an anonymous type { - size_t i = match.position(); - size_t l = match.length(); + int i = (int)match.position(); + int l = (int)match.length(); //printf("annoClassDef=%p annMemb=%p scopeName='%s' anonymous='%s'\n", // annoClassDef,annMemb,cname.data(),ltype.mid(i,l).data()); if (annoClassDef) // type is an anonymous compound { - size_t ir=i+l; + int ir=i+l; //printf("<<<<<<<<<<<<<<\n"); ol.startAnonTypeScope(s_indentLevel++); annoClassDef->writeDeclaration(ol,m_impl->annMemb,inGroup,inheritedFrom,inheritId); @@ -2778,9 +2778,9 @@ void MemberDefImpl::_writeReimplementedBy(OutputList &ol) const } if (count>0) { - auto replaceFunc = [&bml](OutputList &ol,size_t entryIndex) + auto replaceFunc = [&bml,&ol](size_t entryIndex) { - size_t count=0; + size_t cnt=0; auto it = bml.begin(); // find the entryIndex-th documented entry in the inheritance list. const MemberDef *bmd = 0; @@ -2791,8 +2791,8 @@ void MemberDefImpl::_writeReimplementedBy(OutputList &ol) const bcd = bmd->getClassDef(); if ( bmd->isLinkable() && bcd->isLinkable()) { - if (count==entryIndex) break; - count++; + if (cnt==entryIndex) break; + cnt++; } ++it; } @@ -2814,11 +2814,11 @@ void MemberDefImpl::_writeReimplementedBy(OutputList &ol) const QCString reimplInLine; if (m_impl->virt==Pure || (getClassDef() && getClassDef()->compoundType()==ClassDef::Interface)) { - reimplInLine = theTranslator->trImplementedInList(count); + reimplInLine = theTranslator->trImplementedInList((int)count); } else { - reimplInLine = theTranslator->trReimplementedInList(count); + reimplInLine = theTranslator->trReimplementedInList((int)count); } // write the list of classes that overwrite this member @@ -3184,8 +3184,6 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, { title += "()"; } - int i=0,l; - if (lang == SrcLangExt_Slice) { // Remove the container scope from the member name. @@ -3210,8 +3208,6 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, std::string sdef = ldef.str(); if ((isVariable() || isTypedef()) && std::regex_search(sdef,match,r)) { - i = (int)match.position(); - l = (int)match.length(); // find enum type and insert it in the definition bool found=false; for (const auto &vmd : *ml) @@ -3343,7 +3339,7 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, } int dl=ldef.length(); //printf("start >%s<\n",ldef.data()); - i=dl-1; + int i=dl-1; while (i>=0 && (isId(ldef.at(i)) || ldef.at(i)==':')) i--; while (i>=0 && isspace((uchar)ldef.at(i))) i--; if (i>0) diff --git a/src/memberdef.h b/src/memberdef.h index 7b27cff..abaf3ff 100644 --- a/src/memberdef.h +++ b/src/memberdef.h @@ -36,7 +36,6 @@ class MemberGroup; class ExampleList; class OutputList; class GroupDef; -class QTextStream; class QStrList; struct TagInfo; class MemberDefMutable; diff --git a/src/memberlist.cpp b/src/memberlist.cpp index 9181e3f..8d07ae4 100644 --- a/src/memberlist.cpp +++ b/src/memberlist.cpp @@ -15,8 +15,6 @@ * */ -#include - #include "memberlist.h" #include "classdef.h" #include "message.h" diff --git a/src/pagedef.cpp b/src/pagedef.cpp index 0c34f08..9a18fda 100644 --- a/src/pagedef.cpp +++ b/src/pagedef.cpp @@ -13,8 +13,6 @@ * */ -#include - #include "pagedef.h" #include "groupdef.h" #include "docparser.h" diff --git a/src/rtfgen.cpp b/src/rtfgen.cpp index 65a5258..debda5c 100644 --- a/src/rtfgen.cpp +++ b/src/rtfgen.cpp @@ -22,8 +22,6 @@ #include #include -#include -#include #include "rtfgen.h" #include "config.h" diff --git a/src/util.cpp b/src/util.cpp index c9455d9..168fdf0 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -180,7 +180,7 @@ QCString removeAnonymousScopes(const char *str) // helper to check if the found delimiter ends with a colon auto endsWithColon = [](const std::string &del) { - for (size_t i=del.size()-1;i>=0;i--) + for (int i=(int)del.size()-1;i>=0;i--) { if (del[i]=='@') return false; else if (del[i]==':') return true; @@ -1094,7 +1094,7 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, } void writeMarkerList(OutputList &ol,const std::string &markerText,size_t numMarkers, - std::function replaceFunc) + std::function replaceFunc) { static std::regex marker("@([[:digit:]]+)"); std::sregex_iterator it(markerText.begin(),markerText.end(),marker); @@ -1110,7 +1110,7 @@ void writeMarkerList(OutputList &ol,const std::string &markerText,size_t numMark unsigned long entryIndex = std::stoul(match[1]); if (entryIndex<(unsigned long)numMarkers) { - replaceFunc(ol,entryIndex); + replaceFunc(entryIndex); } index=newIndex+matchLen; } @@ -1119,7 +1119,7 @@ void writeMarkerList(OutputList &ol,const std::string &markerText,size_t numMark void writeExamples(OutputList &ol,const ExampleList &list) { - auto replaceFunc = [&list](OutputList &ol,size_t entryIndex) + auto replaceFunc = [&list,&ol](size_t entryIndex) { const auto &e = list[entryIndex]; ol.pushGeneratorState(); @@ -1306,8 +1306,8 @@ static bool isMatchingWildcard(const StringType &input,size_t input_pos, auto pattern_char = pattern[pattern_pos]; if (!caseSensitive) { - input_char = std::tolower(input_char); - pattern_char = std::tolower(pattern_char); + input_char = (typename StringType::value_type)std::tolower(input_char); + pattern_char = (typename StringType::value_type)std::tolower(pattern_char); } // if current character matches against '?' pattern or literally if (pattern[pattern_pos]=='?' || input_char==pattern_char) @@ -4489,7 +4489,7 @@ int extractClassNameFromType(const char *type,int &pos,QCString &name,QCString & name.resize(0); templSpec.resize(0); if (type==0) return -1; - size_t typeLen=qstrlen(type); + int typeLen=qstrlen(type); if (typeLen>0) { if (lang == SrcLangExt_Fortran) @@ -4500,18 +4500,18 @@ int extractClassNameFromType(const char *type,int &pos,QCString &name,QCString & re = re_fortran; } } - std::string part = type + pos; - std::sregex_iterator it(part.begin(),part.end(),re); + std::string s = type; + std::sregex_iterator it(s.begin()+pos,s.end(),re); std::sregex_iterator end; if (it!=end) { const auto &match = *it; - size_t i = pos + match.position(); - size_t l = match.length(); - size_t ts = i+l; - size_t te = ts; - size_t tl = 0; + int i = pos+(int)match.position(); + int l = (int)match.length(); + int ts = i+l; + int te = ts; + int tl = 0; while (tsp) result+=s.substr(p,i-p); QCString args = extractAliasArgs(s,i+l); bool hasArgs = !args.isEmpty(); // found directly after command diff --git a/src/util.h b/src/util.h index d978c87..02767f8 100644 --- a/src/util.h +++ b/src/util.h @@ -398,7 +398,7 @@ int nextUtf8CharPosition(const QCString &utf8Str,uint len,uint startPos); const char *writeUtf8Char(FTextStream &t,const char *s); void writeMarkerList(OutputList &ol,const std::string &markerText,size_t numMarkers, - std::function replaceFunc); + std::function replaceFunc); /** Data associated with a HSV colored image. */ struct ColoredImgDataItem diff --git a/src/vhdldocgen.cpp b/src/vhdldocgen.cpp index 539caae..cc12006 100644 --- a/src/vhdldocgen.cpp +++ b/src/vhdldocgen.cpp @@ -2406,7 +2406,7 @@ QCString VhdlDocGen::parseForConfig(QCString & entity,QCString & arch) QCString label; if (!entity.contains(":")) return ""; - static std::regex exp("[:()[:space:]]"); + static std::regex exp("[:()[[:space:]]"); auto ql=split(entity.str(),exp); if (ql.size()<2) { @@ -2436,7 +2436,7 @@ QCString VhdlDocGen::parseForConfig(QCString & entity,QCString & arch) QCString VhdlDocGen::parseForBinding(QCString & entity,QCString & arch) { - static std::regex exp("[()[:space:]]"); + static std::regex exp("[()[[:space:]]"); auto ql = split(entity.str(),exp); -- cgit v0.12 From e43aaccb144ad800db4ee72137bdebc735217a31 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Sat, 20 Feb 2021 20:51:25 +0100 Subject: Added missing std:: namespace --- src/rtfstyle.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rtfstyle.cpp b/src/rtfstyle.cpp index e8643fb..3b0544e 100644 --- a/src/rtfstyle.cpp +++ b/src/rtfstyle.cpp @@ -239,7 +239,7 @@ static const std::regex s_clause("\\\\s([[:digit:]]+)[[:space:]]*"); StyleData::StyleData(const std::string &reference, const std::string &definition) { std::smatch match; - if (regex_search(reference,match,s_clause)) + if (std::regex_search(reference,match,s_clause)) { m_index = static_cast(std::stoul(match[1].str())); } @@ -254,7 +254,7 @@ StyleData::StyleData(const std::string &reference, const std::string &definition bool StyleData::setStyle(const std::string &command, const std::string &styleName) { std::smatch match; - if (!regex_search(command,match,s_clause)) + if (!std::regex_search(command,match,s_clause)) { err("Style sheet '%s' contains no '\\s' clause.\n{%s}", styleName.c_str(), command.c_str()); return false; @@ -262,7 +262,7 @@ bool StyleData::setStyle(const std::string &command, const std::string &styleNam m_index = static_cast(std::stoul(match[1].str())); static std::regex definition_splitter("^(.*)(\\\\sbasedon[[:digit:]]+.*)$"); - if (regex_match(command,match,definition_splitter)) + if (std::regex_match(command,match,definition_splitter)) { m_reference = match[1].str(); m_definition = match[2].str(); -- cgit v0.12 From 5a646f7453241643fc3c914f69042bdf601fd5eb Mon Sep 17 00:00:00 2001 From: albert-github Date: Sun, 21 Feb 2021 11:12:38 +0100 Subject: Correction of typing error Correction of typing error --- src/util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util.cpp b/src/util.cpp index 168fdf0..bad4c2e 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1294,7 +1294,7 @@ static bool isMatchingWildcard(const StringType &input,size_t input_pos, // if we are at the end of the input string if (input_pos==input.length()) { - // match iff the remainer of the pattern is '*'s + // match iff the remainder of the pattern is '*'s for (size_t i=pattern_pos; i Date: Sun, 21 Feb 2021 13:42:24 +0100 Subject: Regression: specifying character ranges for FILE_PATTERNS didn't work --- src/util.cpp | 73 ++++++++++++++++-------------------------------------------- 1 file changed, 19 insertions(+), 54 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index 168fdf0..80ea950 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1279,70 +1279,35 @@ int filterCRLF(char *buf,int len) return dest; // length of the valid part of the buf } -template -static bool isMatchingWildcard(const StringType &input,size_t input_pos, - const StringType &pattern,size_t pattern_pos, - bool caseSensitive) +static std::string wildcard2regex(const std::string &pattern) { - // end of pattern reached - if (pattern_pos==pattern.length()) - { - // match iff also at the end of the input string - return input_pos==input.length(); - } - - // if we are at the end of the input string - if (input_pos==input.length()) + std::string result="^"; // match start of input + char c; + const char *p = pattern.c_str(); + while ((c=*p++)) { - // match iff the remainer of the pattern is '*'s - for (size_t i=pattern_pos; i '.*' + case '?': result+='.'; break; // '?' => '.' + case '.': case '+': case '\\': case '$': case '^': result+='\\'; result+=c; break; // escape + case '[': if (*p=='^') { result+="[^"; p++; } else result+=c; break; // don't escape ^ after [ + default: result+=c; break; // just copy } - return true; - } - - auto input_char = input[input_pos]; - auto pattern_char = pattern[pattern_pos]; - if (!caseSensitive) - { - input_char = (typename StringType::value_type)std::tolower(input_char); - pattern_char = (typename StringType::value_type)std::tolower(pattern_char); - } - // if current character matches against '?' pattern or literally - if (pattern[pattern_pos]=='?' || input_char==pattern_char) - { - // then continue with the next one - return isMatchingWildcard(input,input_pos+1,pattern,pattern_pos+1,caseSensitive); } - - // current character in the pattern is '*' - if (pattern[pattern_pos]=='*') - { - // try the same match against the next character in the input (current char is eaten by '*') - return isMatchingWildcard(input,input_pos+1,pattern,pattern_pos ,caseSensitive) || - // or try to match against the next character in the pattern ('*' matches an empty string) - isMatchingWildcard(input,input_pos ,pattern,pattern_pos+1,caseSensitive); - } - - // found a mismatch - return false; + result+='$'; // match end of input + return result; } static bool isMatchingWildcard(const std::string &input,const std::string &pattern, bool caseSensitive=false) { - if (!caseSensitive) // to properly match input 'FÓÓ' against pattern 'fóó*' we need - // to convert the std::string to a std::wstring so std::tolower works - // on multi-byte characters like Ó and not one individual bytes. - { - std::wstring_convert< std::codecvt_utf8 > conv; - return isMatchingWildcard(conv.from_bytes(input),0,conv.from_bytes(pattern),0,caseSensitive); - } - else // simple case were we can do byte matching for characters. - { - return isMatchingWildcard(input,0,pattern,0,caseSensitive); - } + + std::regex::flag_type flags = std::regex::ECMAScript; + if (!caseSensitive) flags |= std::regex::icase; + std::string re_str = wildcard2regex(pattern); + std::regex rePattern(wildcard2regex(pattern),flags); + return std::regex_match(input,rePattern); } static QCString getFilterFromList(const char *name,const StringVector &filterList,bool &found) -- cgit v0.12 From cb34071ca4f1abd9e002c8bb05f08fd56a8798e5 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Sun, 21 Feb 2021 13:52:41 +0100 Subject: Remove double call to wildcard2regex() --- src/util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util.cpp b/src/util.cpp index 80ea950..05a90cb 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1306,7 +1306,7 @@ static bool isMatchingWildcard(const std::string &input,const std::string &patte std::regex::flag_type flags = std::regex::ECMAScript; if (!caseSensitive) flags |= std::regex::icase; std::string re_str = wildcard2regex(pattern); - std::regex rePattern(wildcard2regex(pattern),flags); + std::regex rePattern(re_str,flags); return std::regex_match(input,rePattern); } -- cgit v0.12 From 30d347bf8046775d6eab9bd8f70dbf3c3204e7b7 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Mon, 22 Feb 2021 22:12:58 +0100 Subject: Some performance tweaks + remove setting of global locale --- src/configimpl.l | 4 ++-- src/definition.cpp | 2 +- src/docparser.cpp | 4 ++-- src/doctokenizer.l | 8 ++++---- src/doxygen.cpp | 17 ++++++++--------- src/groupdef.cpp | 2 +- src/htmlhelp.cpp | 2 +- src/markdown.cpp | 2 +- src/memberdef.cpp | 10 +++++----- src/pre.l | 4 ++-- src/rtfstyle.cpp | 8 ++++---- src/scanner.l | 6 +++--- src/template.cpp | 2 +- src/util.cpp | 31 ++++++++++++++----------------- src/vhdlcode.l | 4 ++-- src/vhdldocgen.cpp | 18 +++++++++--------- src/vhdljjparser.cpp | 6 +++--- 17 files changed, 63 insertions(+), 67 deletions(-) diff --git a/src/configimpl.l b/src/configimpl.l index 2938eb8..b99ddf8 100644 --- a/src/configimpl.l +++ b/src/configimpl.l @@ -1136,7 +1136,7 @@ static void substEnvVarsInString(QCString &str) { if (str.isEmpty()) return; // match e.g. $(HOME) but also $(PROGRAMFILES(X86)) - static std::regex re("\\$\\(([[:alpha:]_][[:alnum:].-]*(\\([[:alpha:]_][[:alnum:].-]*\\))?)\\)"); + static const std::regex re("\\$\\(([[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF.-]*(\\([[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF.-]*\\))?)\\)", std::regex::optimize); std::string s = str.str(); std::sregex_iterator it(s.begin(),s.end(),re); std::sregex_iterator end; @@ -1649,7 +1649,7 @@ void Config::checkAndCorrect() for (const auto &alias : aliasList) { // match aliases of the form 'name=' and 'name{2} =' - static std::regex re("[[:alpha:]_][[:alnum:]_]*(\\{[[:digit:]]+\\})?[[:space:]]*="); + static const std::regex re("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_]*(\\{[[:digit:]]+\\})?[[:space:]]*=", std::regex::optimize); std::sregex_iterator it(alias.begin(),alias.end(),re); std::sregex_iterator end; if (it==end) diff --git a/src/definition.cpp b/src/definition.cpp index 6a5b6e3..1140a7f 100644 --- a/src/definition.cpp +++ b/src/definition.cpp @@ -176,7 +176,7 @@ static bool matchExcludedSymbols(const char *name) pattern=pattern.left(pattern.length()-1),forceEnd=TRUE; if (pattern.find('*')!=-1) // wildcard mode { - std::regex re(substitute(pattern,"*",".*").str()); + const std::regex re(substitute(pattern,"*",".*").str()); std::sregex_iterator it(symName.begin(),symName.end(),re); std::sregex_iterator end; if (it!=end) // wildcard match diff --git a/src/docparser.cpp b/src/docparser.cpp index 9fbfef1..e801133 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -436,7 +436,7 @@ static void checkArgumentName(const std::string &name) //printf("isDocsForDefinition()=%d\n",g_memberDef->isDocsForDefinition()); if (al.empty()) return; // no argument list - static std::regex re("(\\$[[:alnum:]_]|[[:alpha:]_])[[:alnum:]_]*\\.*"); + static const std::regex re("(\\$[[:alnum:]\\x80-\\xFF_]|[[:alpha:]\\x80-\\xFF_])[[:alnum:]\\x80-\\xFF_]*\\.*", std::regex::optimize); std::sregex_iterator it(name.begin(),name.end(),re); std::sregex_iterator end; for (; it!=end ; ++it) @@ -873,7 +873,7 @@ static int handleStyleArgument(DocNode *parent,DocNodeList &children, tok!=TK_ENDLIST ) { - static std::regex specialChar("[.,|()\\[\\]:;\\?]"); + static const std::regex specialChar("[.,|()\\[\\]:;\\?]", std::regex::optimize); if (tok==TK_WORD && g_token->name.length()==1 && std::regex_search(g_token->name.str(),specialChar)) { diff --git a/src/doctokenizer.l b/src/doctokenizer.l index ad6ac11..f30dba7 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -515,7 +515,7 @@ RCSID "$"("Author"|"Date"|"Header"|"Id"|"Locker"|"Log"|"Name"|"RCSfile"|"Revisio { lineCount(yytext,yyleng); std::string text=yytext; - static std::regex re("[*+][^*+]*$"); // find last + or * + static const std::regex re("[*+][^*+]*$", std::regex::optimize); // find last + or * std::smatch match; std::regex_search(text,match,re); size_t listPos = match.position(); @@ -533,7 +533,7 @@ RCSID "$"("Author"|"Date"|"Header"|"Id"|"Locker"|"Log"|"Name"|"RCSfile"|"Revisio else { std::string text=yytext; - static std::regex re("[1-9]+"); + static const std::regex re("[1-9]+", std::regex::optimize); std::smatch match; std::regex_search(text,match,re); g_token->isEnumList = true; @@ -560,7 +560,7 @@ RCSID "$"("Author"|"Date"|"Header"|"Id"|"Locker"|"Log"|"Name"|"RCSfile"|"Revisio { lineCount(yytext,yyleng); std::string text=extractPartAfterNewLine(yytext).str(); - static std::regex re("[*+][^*+]*$"); // find last + or * + static const std::regex re("[*+][^*+]*$", std::regex::optimize); // find last + or * std::smatch match; std::regex_search(text,match,re); size_t markPos = match.position(); @@ -579,7 +579,7 @@ RCSID "$"("Author"|"Date"|"Header"|"Id"|"Locker"|"Log"|"Name"|"RCSfile"|"Revisio { lineCount(yytext,yyleng); std::string text=extractPartAfterNewLine(yytext).str(); - static std::regex re("[1-9]+"); + static const std::regex re("[1-9]+", std::regex::optimize); std::smatch match; std::regex_search(text,match,re); g_token->isEnumList = true; diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 3fd1069..d4127a7 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -2220,7 +2220,7 @@ static MemberDef *addVariableToFile( { ttype.stripPrefix("struct "); ttype.stripPrefix("union "); - static std::regex re("[[:alpha:]_][[:alnum:]_]*"); + static const std::regex re("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_]*", std::regex::optimize); std::smatch match; std::string typ = ttype.str(); if (std::regex_search(typ,match,re)) @@ -2439,7 +2439,7 @@ static int findFunctionPtr(const std::string &type,SrcLangExt lang, int *pLength return -1; // Fortran and VHDL do not have function pointers } - static std::regex re("\\([^)]*[*\\^][^)]*\\)"); + static const std::regex re("\\([^)]*[*\\^][^)]*\\)", std::regex::optimize); std::smatch match; size_t i=std::string::npos; size_t l=0; @@ -2532,7 +2532,7 @@ static bool isVarWithConstructor(const Entry *root) } for (const Argument &a : root->argList) { - static std::regex initChars("[0-9\"'&*!^]+"); + static const std::regex initChars("[0-9\"'&*!^]+", std::regex::optimize); std::smatch match; if (!a.name.isEmpty() || !a.defval.isEmpty()) { @@ -2574,7 +2574,7 @@ static bool isVarWithConstructor(const Entry *root) } std::string resType=resolveTypeDef(ctx,a.type).str(); if (resType.empty()) resType=atype; - static std::regex idChars("[[:alpha:]_][[:alnum:]_]*"); + static const std::regex idChars("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_]*", std::regex::optimize); if (std::regex_search(resType,match,idChars) && match.position()==0) // resType starts with identifier { resType=match.str(); @@ -2625,7 +2625,7 @@ static void addVariable(const Entry *root,int isFuncPtr=-1) type=name; std::string sargs = args.str(); - static const std::regex reName("[[:alpha:]_][[:alnum:]_]*"); + static const std::regex reName("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_]*", std::regex::optimize); std::smatch match; if (std::regex_search(sargs,match,reName)) { @@ -3816,7 +3816,7 @@ static TemplateNameMap getTemplateArgumentsInName(const ArgumentList &templateAr int count=0; for (const Argument &arg : templateArguments) { - static std::regex re("[[:alpha:]_][[:alnum:]_:]*"); + static const std::regex re("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_:]*", std::regex::optimize); std::sregex_iterator it(name.begin(),name.end(),re); std::sregex_iterator end; for (; it!=end ; ++it) @@ -5325,7 +5325,7 @@ static QCString substituteTemplatesInString( ) { std::string dst; - static const std::regex re("[[:alpha:]_][[:alnum:]_]*"); + static const std::regex re("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_]*", std::regex::optimize); std::sregex_iterator it(src.begin(),src.end(),re); std::sregex_iterator end; //printf("type=%s\n",sa->type.data()); @@ -10066,7 +10066,6 @@ void initDoxygen() std::setlocale(LC_ALL,""); std::setlocale(LC_CTYPE,"C"); // to get isspace(0xA0)==0, needed for UTF-8 std::setlocale(LC_NUMERIC,"C"); - std::locale::global(std::locale("en_US.UTF-8")); Portable::correct_path(); @@ -10454,7 +10453,7 @@ void readConfiguration(int argc, char **argv) cleanUpDoxygen(); exit(0); } - else if ((qstrcmp(&argv[optind][2],"Version")==0) || + else if ((qstrcmp(&argv[optind][2],"Version")==0) || (qstrcmp(&argv[optind][2],"VERSION")==0)) { version(true); diff --git a/src/groupdef.cpp b/src/groupdef.cpp index 3fdb9fb..5a89a4a 100644 --- a/src/groupdef.cpp +++ b/src/groupdef.cpp @@ -1090,7 +1090,7 @@ void GroupDefImpl::writeDocumentation(OutputList &ol) if (Doxygen::searchIndex) { Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE); - static std::regex we("[[:alpha:]_][[:alnum:]_\\-]*"); + static const std::regex we("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_\\-]*", std::regex::optimize); std::string title = m_title.str(); std::sregex_iterator it(title.begin(),title.end(),we); std::sregex_iterator end; diff --git a/src/htmlhelp.cpp b/src/htmlhelp.cpp index b020bb0..e3a007a 100644 --- a/src/htmlhelp.cpp +++ b/src/htmlhelp.cpp @@ -154,7 +154,7 @@ void HtmlHelpIndex::addItem(const char *level1,const char *level2, const char *url,const char *anchor,bool hasLink, bool reversed) { - static std::regex re("@[[:digit:]]+"); + static const std::regex re("@[[:digit:]]+", std::regex::optimize); std::string key = level1; if (level2) key+= std::string("?") + level2; if (std::regex_search(key,re)) // skip anonymous stuff diff --git a/src/markdown.cpp b/src/markdown.cpp index df632d7..8ac2e5f 100644 --- a/src/markdown.cpp +++ b/src/markdown.cpp @@ -1472,7 +1472,7 @@ static QCString extractTitleId(QCString &title, int level) { TRACE(title.data()); // match e.g. '{#id-b11} ' and capture 'id-b11' - static std::regex r2("\\{#([a-z_A-Z][a-z_A-Z0-9\\-]*)\\}[[:space:]]*$"); + static const std::regex r2("\\{#([a-z_A-Z][a-z_A-Z0-9\\-]*)\\}[[:space:]]*$", std::regex::optimize); std::smatch match; std::string ti = title.str(); if (std::regex_search(ti,match,r2)) diff --git a/src/memberdef.cpp b/src/memberdef.cpp index b3415ff..5d2a0da 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -1852,7 +1852,7 @@ ClassDef *MemberDefImpl::getClassDefOfAnonymousType() const // match expression if it contains at least one @1 marker, e.g. // 'struct A::@1::@2::B' matches 'A::@1::@2::B' but 'struct A::B' does not match. - static const std::regex r("[[:alnum:]_@:]*@[[:digit:]]+[[:alnum:]_@:]*"); + static const std::regex r("[[:alnum:]\\x80-\\xFF_@:]*@[[:digit:]]+[[:alnum:]\\x80-\\xFF_@:]*", std::regex::optimize); std::string stype = ltype.str(); std::smatch match; if (std::regex_search(stype,match,r)) // found anonymous scope in type @@ -2103,7 +2103,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, } // strip 'friend' keyword from ltype ltype.stripPrefix("friend "); - static const std::regex r("@[[:digit:]]+"); + static const std::regex r("@[[:digit:]]+", std::regex::optimize); std::smatch match; std::string stype = ltype.str(); bool endAnonScopeNeeded=FALSE; @@ -2906,7 +2906,7 @@ void MemberDefImpl::_writeTypeConstraints(OutputList &ol) const } // match from the start of the scope until the last marker -static const std::regex reAnonymous("[[:alnum:]_:]*@[[:digit:]]+([^@]*@[[:digit:]]+)?"); +static const std::regex reAnonymous("[[:alnum:]\\x80-\\xFF_:]*@[[:digit:]]+([^@]*@[[:digit:]]+)?", std::regex::optimize); void MemberDefImpl::_writeEnumValues(OutputList &ol,const Definition *container, const QCString &cfname,const QCString &ciname, @@ -3203,7 +3203,7 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, QStrList sl; getLabels(sl,scopedContainer); - static std::regex r("@[0-9]+"); + static const std::regex r("@[0-9]+", std::regex::optimize); std::smatch match; std::string sdef = ldef.str(); if ((isVariable() || isTypedef()) && std::regex_search(sdef,match,r)) @@ -3612,7 +3612,7 @@ static QCString simplifyTypeForTable(const QCString &s) { QCString ts=removeAnonymousScopes(s); if (ts.right(2)=="::") ts = ts.left(ts.length()-2); - static const std::regex re("[[:alpha:]_][[:alnum:]_]*(<[^>]*>)?::([[:alpha:]_][[:alnum:]_]*)"); + static const std::regex re("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_]*(<[^>]*>)?::([[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_]*)", std::regex::optimize); std::smatch match; std::string t = ts.str(); if (std::regex_search(t,match,re)) diff --git a/src/pre.l b/src/pre.l index f7aca7f..296295f 100644 --- a/src/pre.l +++ b/src/pre.l @@ -1962,7 +1962,7 @@ static void processConcatOperators(QCString &expr) if (expr.isEmpty()) return; //printf("processConcatOperators: in='%s'\n",expr.data()); std::string e = expr.str(); - static std::regex r("[[:space:]]*##[[:space:]]*"); + static const std::regex r("[[:space:]]*##[[:space:]]*", std::regex::optimize); std::sregex_iterator end; size_t i=0; @@ -3206,7 +3206,7 @@ static void initPredefined(yyscan_t yyscanner,const char *fileName) i_obrace(std::stoul(match[1].str())); - static std::regex definition_splitter("^(.*)(\\\\sbasedon[[:digit:]]+.*)$"); + static const std::regex definition_splitter("^(.*)(\\\\sbasedon[[:digit:]]+.*)$", std::regex::optimize); if (std::regex_match(command,match,definition_splitter)) { m_reference = match[1].str(); @@ -287,7 +287,7 @@ void loadStylesheet(const char *name, StyleDataMap& map) for (std::string line ; getline(file,line) ; ) // for each line { if (line.empty() || line[0]=='#') continue; // skip blanks & comments - static std::regex assignment_splitter("[[:space:]]*=[[:space:]]*"); + static const std::regex assignment_splitter("[[:space:]]*=[[:space:]]*", std::regex::optimize); std::smatch match; if (std::regex_search(line,match,assignment_splitter)) { @@ -330,7 +330,7 @@ void loadExtensions(const char *name) { if (line.empty() || line[0]=='#') continue; // skip blanks & comments std::smatch match; - static std::regex assignment_splitter("[[:space:]]*=[[:space:]]*"); + static const std::regex assignment_splitter("[[:space:]]*=[[:space:]]*", std::regex::optimize); if (std::regex_search(line,match,assignment_splitter)) { std::string key = match.prefix(); diff --git a/src/scanner.l b/src/scanner.l index ebb37c7..4a1e720 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -3739,7 +3739,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } else { - static std::regex re("@[0-9]+$"); + static const std::regex re("@[0-9]+$", std::regex::optimize); if (!yyextra->isTypedef && yyextra->memspecEntry && !std::regex_search(yyextra->memspecEntry->name.str(),re)) // not typedef or anonymous type (see bug691071) { @@ -4831,7 +4831,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->fileName = yyextra->yyFileName; yyextra->current->startLine = yyextra->yyBegLineNr; yyextra->current->startColumn = yyextra->yyBegColNr; - static std::regex re("\\([^)]*[*&][^]*\\)"); + static const std::regex re("\\([^)]*[*&][^]*\\)", std::regex::optimize); std::smatch match; std::string type = yyextra->current->type.str(); int ti=-1; @@ -6895,7 +6895,7 @@ static void splitKnRArg(yyscan_t yyscanner,QCString &oldStyleArgPtr,QCString &ol int si = yyextra->current->args.length(); if (yyextra->oldStyleArgType.isEmpty()) // new argument { - static std::regex re("(\\([^)]*\\))[[:space:]]*(\\([^)]*\\))?"); + static const std::regex re("(\\([^)]*\\))[[:space:]]*(\\([^)]*\\))?", std::regex::optimize); std::string args = yyextra->current->args.str(); std::smatch matches; std::regex_search(args,matches,re); diff --git a/src/template.cpp b/src/template.cpp index 61411be..4c296aa 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -4186,7 +4186,7 @@ class TemplateNodeMarkers : public TemplateNodeCreator c->push(); std::string str = patternStr.toString().str(); - static std::regex marker("@([[:digit:]]+)"); + static const std::regex marker("@([[:digit:]]+)", std::regex::optimize); std::sregex_iterator re_it(str.begin(),str.end(),marker); std::sregex_iterator end; size_t index=0; diff --git a/src/util.cpp b/src/util.cpp index 05a90cb..9b76714 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -188,7 +188,7 @@ QCString removeAnonymousScopes(const char *str) return false; }; - static std::regex re("[ :]*@[[:digit:]]+[: ]*"); + static const std::regex re("[ :]*@[[:digit:]]+[: ]*", std::regex::optimize); std::string s = str; std::sregex_iterator iter( s.begin(), s.end(), re); std::sregex_iterator end; @@ -221,7 +221,7 @@ QCString removeAnonymousScopes(const char *str) QCString replaceAnonymousScopes(const char *s,const char *replacement) { if (s==0) return QCString(); - static std::regex marker("@[[:digit:]]+"); + static const std::regex marker("@[[:digit:]]+", std::regex::optimize); std::string result = std::regex_replace(s,marker,replacement?replacement:"__anonymous__"); //printf("replaceAnonymousScopes('%s')='%s'\n",s.data(),result.data()); return result; @@ -895,7 +895,7 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, size_t strLen = txtStr.length(); if (strLen==0) return; - static std::regex regExp("[[:alpha:]_][[:alnum:]_~!\\\\.:$]*"); + static const std::regex regExp("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_~!\\\\.:$]*", std::regex::optimize); std::sregex_iterator it( txtStr.begin(), txtStr.end(), regExp); std::sregex_iterator end; @@ -1096,7 +1096,7 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, void writeMarkerList(OutputList &ol,const std::string &markerText,size_t numMarkers, std::function replaceFunc) { - static std::regex marker("@([[:digit:]]+)"); + static const std::regex marker("@([[:digit:]]+)", std::regex::optimize); std::sregex_iterator it(markerText.begin(),markerText.end(),marker); std::sregex_iterator end; size_t index=0; @@ -1906,7 +1906,7 @@ static QCString extractCanonicalType(const Definition *d,const FileDef *fs,QCStr // (i.e. type is not a template specialization) // then resolve any identifiers inside. { - static std::regex re("[[:alpha:]_][[:alnum:]_]*"); + static const std::regex re("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_]*", std::regex::optimize); std::string ts = templSpec.str(); std::sregex_iterator it(ts.begin(),ts.end(),re); std::sregex_iterator end; @@ -4282,7 +4282,7 @@ QCString convertCharEntitiesToUTF8(const char *str) { if (str==0) return QCString(); - static std::regex re("&[[:alpha:]][[:alnum:]]*;"); + static const std::regex re("&[[:alpha:]\\x80-\\xFF][[:alnum:]\\x80-\\xFF]*;", std::regex::optimize); std::string s = str; std::sregex_iterator it(s.begin(),s.end(),re); std::sregex_iterator end; @@ -4447,8 +4447,8 @@ void addMembersToMemberGroup(MemberList *ml, */ int extractClassNameFromType(const char *type,int &pos,QCString &name,QCString &templSpec,SrcLangExt lang) { - static std::regex re_norm("[[:alpha:]_][[:alnum:]_:]*"); - static std::regex re_fortran("[[:alpha:]_][[:alnum:]_:()=]*"); + static std::regex re_norm("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_:]*"); + static std::regex re_fortran("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_:()=]*"); static std::regex &re = re_norm; name.resize(0); @@ -4530,7 +4530,7 @@ QCString normalizeNonTemplateArgumentsInString( p++; QCString result = name.left(p); - static std::regex re("[[:alpha:]_:][[:alnum:]_:]*"); + static const std::regex re("[[:alpha:]\\x80-\\xFF_:][[:alnum:]\\x80-\\xFF_:]*", std::regex::optimize); std::string s = result.mid(p).str(); std::sregex_iterator it(s.begin(),s.end(),re); std::sregex_iterator end; @@ -4594,7 +4594,7 @@ QCString substituteTemplateArgumentsInString( if (formalArgs.empty()) return name; std::string result; - static std::regex re("[[:alpha:]_][[:alnum:]_:]*"); + static const std::regex re("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_:]*", std::regex::optimize); std::sregex_iterator it(name.begin(),name.end(),re); std::sregex_iterator end; size_t p=0; @@ -5414,7 +5414,7 @@ QCString stripPath(const char *s) bool containsWord(const char *str,const char *word) { if (str==0 || word==0) return false; - static std::regex re("[[:alpha:]_]+"); + static const std::regex re("[[:alpha:]\\x80-\\xFF_]+", std::regex::optimize); std::string s = str; for (std::sregex_iterator it(s.begin(),s.end(),re) ; it!=std::sregex_iterator() ; ++it) { @@ -5429,7 +5429,7 @@ bool containsWord(const char *str,const char *word) */ bool findAndRemoveWord(QCString &sentence,const char *word) { - static std::regex re("[^[:alpha:]_]+"); + static const std::regex re("[^[:alpha:]\\x80-\\xFF_]+", std::regex::optimize); std::string s = sentence.str(); std::sregex_token_iterator it(s.begin(),s.end(),re,{-1,0}); std::sregex_token_iterator end; @@ -6031,13 +6031,10 @@ static QCString expandAliasRec(StringUnorderedSet &aliasesProcessed,const std::s { //QCString result; std::string result; - std::regex re("[\\\\@]([[:alpha:]_][[:alnum:]_]*)"); + std::regex re("[\\\\@]([[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_]*)"); std::sregex_iterator re_it(s.begin(),s.end(),re); std::sregex_iterator end; int p = 0; - //QCString value=s; - //int i,p=0,l; - //while ((i=cmdPat.match(value,p,&l))!=-1) for ( ; re_it!=end ; ++re_it) { const auto &match = *re_it; @@ -6489,7 +6486,7 @@ QCString replaceColorMarkers(const char *str) if (str==0) return QCString(); std::string result; std::string s=str; - static std::regex re("##([0-9A-Fa-f][0-9A-Fa-f])"); + static const std::regex re("##([0-9A-Fa-f][0-9A-Fa-f])", std::regex::optimize); std::sregex_iterator it(s.begin(),s.end(),re); std::sregex_iterator end; static int hue = Config_getInt(HTML_COLORSTYLE_HUE); diff --git a/src/vhdlcode.l b/src/vhdlcode.l index 7c4b70b..3e754c7 100644 --- a/src/vhdlcode.l +++ b/src/vhdlcode.l @@ -359,7 +359,7 @@ XILINX "INST"|"NET"|"PIN"|"BLKNM"|"BUFG"|"COLLAPSE"|"CPLD"|"COMPGRP"|"CONFI tt=tt.lower(); VhdlDocGen::deleteAllChars(tt,';'); tt.stripWhiteSpace(); - static std::regex regg("[[:space:]]+"); + static const std::regex regg("[[:space:]]+", std::regex::optimize); auto ql = split(tt.str(),regg); int index=findIndex(ql,"if")+1; index+=findIndex(ql,"case")+1; @@ -959,7 +959,7 @@ static bool checkVhdlString(yyscan_t yyscanner,QCString &name) if (name.at(0)=='"' && name.at(len-1)=='"' && len > 2) { std::string inside = name.str().substr(1,len-2); - static std::regex regg("[[:space:]]+"); + static const std::regex regg("[[:space:]]+", std::regex::optimize); auto qrl=split(inside,regg); if (VhdlDocGen::isNumber(qrl[0])) { diff --git a/src/vhdldocgen.cpp b/src/vhdldocgen.cpp index cc12006..3bd510f 100644 --- a/src/vhdldocgen.cpp +++ b/src/vhdldocgen.cpp @@ -1034,7 +1034,7 @@ void VhdlDocGen::parseFuncProto(const char* text,QCString& name,QCString& ret,bo QCString VhdlDocGen::getIndexWord(const char* c,int index) { - static std::regex reg("[[:space:]:|]"); + static const std::regex reg("[[:space:]:|]",std::regex::optimize); auto ql=split(c,reg); if ((size_t)index < ql.size()) @@ -1122,7 +1122,7 @@ QCString VhdlDocGen::getProcessNumber() void VhdlDocGen::writeFormatString(const QCString& s,OutputList&ol,const MemberDef* mdef) { - static std::regex reg("[\\[\\]\\.\\/\\<\\>\\:\\s\\,\\;\\'\\+\\-\\*\\|\\&\\=\\(\\)\"]"); + static const std::regex reg("[\\[\\]\\.\\/\\<\\>\\:\\s\\,\\;\\'\\+\\-\\*\\|\\&\\=\\(\\)\"]",std::regex::optimize); QCString qcs = s; qcs+=QCString(" ");// parsing the last sign QCString find=qcs; @@ -1191,7 +1191,7 @@ void VhdlDocGen::writeFormatString(const QCString& s,OutputList&ol,const MemberD */ bool VhdlDocGen::isNumber(const std::string& s) { - static std::regex regg("[0-9][0-9eEfFbBcCdDaA_.#-+?xXzZ]*"); + static const std::regex regg("[0-9][0-9eEfFbBcCdDaA_.#-+?xXzZ]*",std::regex::optimize); return std::regex_match(s,regg); }// isNumber @@ -2298,7 +2298,7 @@ void VhdlDocGen::parseUCF(const char* input, Entry* entity,QCString fileName,b } else { - static std::regex ee("[[:space:]=]"); + static const std::regex ee("[[:space:]=]",std::regex::optimize); int in=findIndex(temp.str(),ee); QCString ff=temp.left(in); temp.stripPrefix(ff.data()); @@ -2324,7 +2324,7 @@ static void initUCF(Entry* root,const char* type,QCString & qcs,int line,QCStr VhdlDocGen::deleteAllChars(qcs,';'); qcs=qcs.stripWhiteSpace(); - static std::regex reg("[[:space:]=]"); + static const std::regex reg("[[:space:]=]",std::regex::optimize); int i = findIndex(qcs.str(),reg); if (i<0) return; if (i==0) @@ -2406,7 +2406,7 @@ QCString VhdlDocGen::parseForConfig(QCString & entity,QCString & arch) QCString label; if (!entity.contains(":")) return ""; - static std::regex exp("[:()[[:space:]]"); + static const std::regex exp("[:()[[:space:]]",std::regex::optimize); auto ql=split(entity.str(),exp); if (ql.size()<2) { @@ -2436,7 +2436,7 @@ QCString VhdlDocGen::parseForConfig(QCString & entity,QCString & arch) QCString VhdlDocGen::parseForBinding(QCString & entity,QCString & arch) { - static std::regex exp("[()[[:space:]]"); + static const std::regex exp("[()[[:space:]]",std::regex::optimize); auto ql = split(entity.str(),exp); @@ -2704,7 +2704,7 @@ void VhdlDocGen::addBaseClass(ClassDef* cd,ClassDef *ent) bcd.usedName.append("(2)"); return; } - static std::regex reg("[[:digit:]]+"); + static const std::regex reg("[[:digit:]]+",std::regex::optimize); QCString s=n.left(i); QCString r=n.right(n.length()-i); std::string t=r.str(); @@ -2952,7 +2952,7 @@ void FlowChart::printNode(const FlowChart& flo) { t=flo.text.str(); } - static std::regex ep("[[:space:]]"); + static const std::regex ep("[[:space:]]",std::regex::optimize); t = std::regex_replace(t,ep,std::string("")); if (t.empty()) { diff --git a/src/vhdljjparser.cpp b/src/vhdljjparser.cpp index 845602d..3852045 100644 --- a/src/vhdljjparser.cpp +++ b/src/vhdljjparser.cpp @@ -272,9 +272,9 @@ void VHDLOutlineParser::handleFlowComment(const char* doc) int VHDLOutlineParser::checkInlineCode(QCString &doc) { - static std::regex csRe("[\\\\@]code"); - static std::regex cendRe("[[:space:]]*[\\\\@]endcode"); - static std::regex cbriefRe("[\\\\@]brief"); + static const std::regex csRe("[\\\\@]code", std::regex::optimize); + static const std::regex cendRe("[[:space:]]*[\\\\@]endcode", std::regex::optimize); + static const std::regex cbriefRe("[\\\\@]brief", std::regex::optimize); // helper to simulate behavior of QString.find(const QRegExp &re,int pos) auto findRe = [](const QCString &str,const std::regex &re,int pos=0) -> int -- cgit v0.12 From 3d4f0313d20cc8f71ade094faa006a2171ff29c2 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Tue, 2 Mar 2021 21:40:36 +0100 Subject: Refactoring: replaced std::regex with own much faster implementation --- src/CMakeLists.txt | 1 + src/classdef.cpp | 1 - src/configimpl.l | 58 ++-- src/context.cpp | 2 +- src/definition.cpp | 10 +- src/docparser.cpp | 12 +- src/docsets.cpp | 2 +- src/doctokenizer.l | 26 +- src/doxygen.cpp | 44 +-- src/groupdef.cpp | 8 +- src/htmlhelp.cpp | 6 +- src/markdown.cpp | 10 +- src/memberdef.cpp | 87 ++---- src/pre.l | 20 +- src/regex.cpp | 736 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/regex.h | 336 +++++++++++++++++++++++ src/rtfstyle.cpp | 40 +-- src/scanner.l | 40 +-- src/template.cpp | 10 +- src/util.cpp | 213 +++++++-------- src/util.h | 6 +- src/vhdlcode.l | 6 +- src/vhdldocgen.cpp | 27 +- src/vhdljjparser.cpp | 20 +- 24 files changed, 1374 insertions(+), 347 deletions(-) create mode 100644 src/regex.cpp create mode 100644 src/regex.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c6af813..4488067 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -281,6 +281,7 @@ add_library(doxymain STATIC qhp.cpp qhpxmlwriter.cpp reflist.cpp + regex.cpp resourcemgr.cpp rtfdocvisitor.cpp rtfgen.cpp diff --git a/src/classdef.cpp b/src/classdef.cpp index 3e602b0..198a1c9 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -17,7 +17,6 @@ #include #include -#include #include #include diff --git a/src/configimpl.l b/src/configimpl.l index b99ddf8..1f9be8d 100644 --- a/src/configimpl.l +++ b/src/configimpl.l @@ -32,8 +32,8 @@ #include #include -#include +#include "regex.h" #include "configimpl.h" #include "version.h" #include "portable.h" @@ -1135,27 +1135,32 @@ void ConfigImpl::emptyValueToDefault() static void substEnvVarsInString(QCString &str) { if (str.isEmpty()) return; - // match e.g. $(HOME) but also $(PROGRAMFILES(X86)) - static const std::regex re("\\$\\(([[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF.-]*(\\([[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF.-]*\\))?)\\)", std::regex::optimize); - std::string s = str.str(); - std::sregex_iterator it(s.begin(),s.end(),re); - std::sregex_iterator end; - std::string result; - size_t p = 0; - for (; it!=end ; ++it) - { - const auto &match = *it; - size_t i = match.position(); - size_t l = match.length(); - result+=s.substr(p,i-p); - std::string matchContents = match[1].str(); - QCString env=Portable::getenv(matchContents.c_str()); // get content of $(..) match - substEnvVarsInString(env); // recursively expand variables if needed. - result+=env.str(); - p=i+l; - } - result+=s.substr(p); - str = QCString(result).stripWhiteSpace(); + auto replace = [](const std::string &s, const reg::Ex &re) -> std::string + { + reg::Iterator it(s,re); + reg::Iterator end; + std::string result; + size_t p = 0; + for (; it!=end ; ++it) + { + const auto &match = *it; + size_t i = match.position(); + size_t l = match.length(); + result+=s.substr(p,i-p); + std::string matchContents = match[1].str(); + QCString env=Portable::getenv(matchContents.c_str()); // get content of $(..) match + substEnvVarsInString(env); // recursively expand variables if needed. + result+=env.str(); + p=i+l; + } + result+=s.substr(p); + return result; + }; + + // match e.g. re1=$(HOME) but also re2=$(PROGRAMFILES(X86)) + static const reg::Ex re1(R"(\$\((\a[\w.-]*)\))"); + static const reg::Ex re2(R"(\$\((\a[\w.-]*\(\a[\w.-]*\))\))"); + str = QCString(replace(replace(str.str(),re1),re2)).stripWhiteSpace(); } static void substEnvVarsInStrList(StringVector &sl) @@ -1648,11 +1653,10 @@ void Config::checkAndCorrect() const StringVector &aliasList = Config_getList(ALIASES); for (const auto &alias : aliasList) { - // match aliases of the form 'name=' and 'name{2} =' - static const std::regex re("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_]*(\\{[[:digit:]]+\\})?[[:space:]]*=", std::regex::optimize); - std::sregex_iterator it(alias.begin(),alias.end(),re); - std::sregex_iterator end; - if (it==end) + // match aliases of the form re1='name=' and re2='name{2} =' + static const reg::Ex re1(R"(\a\w*\s*=)"); + static const reg::Ex re2(R"(\a\w*{\d+}\s*=)"); + if (!reg::search(alias,re1) && !reg::search(alias,re2)) { err("Illegal ALIASES format '%s'. Use \"name=value\" or \"name{n}=value\", where n is the number of arguments\n", alias.c_str()); diff --git a/src/context.cpp b/src/context.cpp index d2cfa9e..8bdc23c 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -136,7 +136,7 @@ class GenericConstIterator : public TemplateListIntf::ConstIterator } void toLast() { - m_index=m_list.size()-1; + m_index=(int)m_list.size()-1; } void toNext() { diff --git a/src/definition.cpp b/src/definition.cpp index 1140a7f..70c1839 100644 --- a/src/definition.cpp +++ b/src/definition.cpp @@ -19,13 +19,13 @@ #include #include #include -#include #include #include "md5.h" #include #include #include +#include "regex.h" #include "config.h" #include "definitionimpl.h" #include "doxygen.h" @@ -176,12 +176,10 @@ static bool matchExcludedSymbols(const char *name) pattern=pattern.left(pattern.length()-1),forceEnd=TRUE; if (pattern.find('*')!=-1) // wildcard mode { - const std::regex re(substitute(pattern,"*",".*").str()); - std::sregex_iterator it(symName.begin(),symName.end(),re); - std::sregex_iterator end; - if (it!=end) // wildcard match + const reg::Ex re(substitute(pattern,"*",".*").str()); + reg::Match match; + if (reg::search(symName,match,re)) // wildcard match { - const auto &match = *it; size_t ui = match.position(); size_t pl = match.length(); size_t sl = symName.length(); diff --git a/src/docparser.cpp b/src/docparser.cpp index e801133..6325cd8 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -24,6 +23,7 @@ #include #include +#include "regex.h" #include "doxygen.h" #include "debug.h" #include "util.h" @@ -436,9 +436,9 @@ static void checkArgumentName(const std::string &name) //printf("isDocsForDefinition()=%d\n",g_memberDef->isDocsForDefinition()); if (al.empty()) return; // no argument list - static const std::regex re("(\\$[[:alnum:]\\x80-\\xFF_]|[[:alpha:]\\x80-\\xFF_])[[:alnum:]\\x80-\\xFF_]*\\.*", std::regex::optimize); - std::sregex_iterator it(name.begin(),name.end(),re); - std::sregex_iterator end; + static const reg::Ex re(R"(\$?\w+\.*)"); + reg::Iterator it(name,re); + reg::Iterator end; for (; it!=end ; ++it) { const auto &match = *it; @@ -873,9 +873,9 @@ static int handleStyleArgument(DocNode *parent,DocNodeList &children, tok!=TK_ENDLIST ) { - static const std::regex specialChar("[.,|()\\[\\]:;\\?]", std::regex::optimize); + static const reg::Ex specialChar(R"([.,|()\[\]:;?])"); if (tok==TK_WORD && g_token->name.length()==1 && - std::regex_search(g_token->name.str(),specialChar)) + reg::match(g_token->name.str(),specialChar)) { // special character that ends the markup command return tok; diff --git a/src/docsets.cpp b/src/docsets.cpp index 4f04623..2911025 100644 --- a/src/docsets.cpp +++ b/src/docsets.cpp @@ -201,7 +201,7 @@ void DocSets::finalize() QCString DocSets::Private::indent() { QCString result; - result.fill(' ',(indentStack.size()+2)*2); + result.fill(' ',((int)indentStack.size()+2)*2); return result; } diff --git a/src/doctokenizer.l b/src/doctokenizer.l index f30dba7..9bafcab 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -26,7 +26,6 @@ #include #include -#include #include #include @@ -42,6 +41,7 @@ #include "doxygen.h" #include "portable.h" #include "cite.h" +#include "regex.h" #define YY_NO_INPUT 1 #define YY_NO_UNISTD_H 1 @@ -515,9 +515,9 @@ RCSID "$"("Author"|"Date"|"Header"|"Id"|"Locker"|"Log"|"Name"|"RCSfile"|"Revisio { lineCount(yytext,yyleng); std::string text=yytext; - static const std::regex re("[*+][^*+]*$", std::regex::optimize); // find last + or * - std::smatch match; - std::regex_search(text,match,re); + static const reg::Ex re(R"([*+][^*+]*$)"); // find last + or * + reg::Match match; + reg::search(text,match,re); size_t listPos = match.position(); g_token->isEnumList = FALSE; g_token->id = -1; @@ -533,9 +533,9 @@ RCSID "$"("Author"|"Date"|"Header"|"Id"|"Locker"|"Log"|"Name"|"RCSfile"|"Revisio else { std::string text=yytext; - static const std::regex re("[1-9]+", std::regex::optimize); - std::smatch match; - std::regex_search(text,match,re); + static const reg::Ex re(R"(\d+)"); + reg::Match match; + reg::search(text,match,re); g_token->isEnumList = true; g_token->id = std::stoul(match.str()); g_token->indent = computeIndent(yytext,match.position()); @@ -560,9 +560,9 @@ RCSID "$"("Author"|"Date"|"Header"|"Id"|"Locker"|"Log"|"Name"|"RCSfile"|"Revisio { lineCount(yytext,yyleng); std::string text=extractPartAfterNewLine(yytext).str(); - static const std::regex re("[*+][^*+]*$", std::regex::optimize); // find last + or * - std::smatch match; - std::regex_search(text,match,re); + static const reg::Ex re(R"([*+][^*+]*$)"); // find last + or * + reg::Match match; + reg::search(text,match,re); size_t markPos = match.position(); g_token->isEnumList = FALSE; g_token->id = -1; @@ -579,9 +579,9 @@ RCSID "$"("Author"|"Date"|"Header"|"Id"|"Locker"|"Log"|"Name"|"RCSfile"|"Revisio { lineCount(yytext,yyleng); std::string text=extractPartAfterNewLine(yytext).str(); - static const std::regex re("[1-9]+", std::regex::optimize); - std::smatch match; - std::regex_search(text,match,re); + static const reg::Ex re(R"(\d+)"); + reg::Match match; + reg::search(text,match,re); g_token->isEnumList = true; g_token->id = std::stoul(match.str()); g_token->indent = computeIndent(text.c_str(),match.position()); diff --git a/src/doxygen.cpp b/src/doxygen.cpp index d4127a7..ce89540 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include "version.h" #include "doxygen.h" @@ -106,6 +105,7 @@ #include "threadpool.h" #include "clangparser.h" #include "symbolresolver.h" +#include "regex.h" #if USE_SQLITE3 #include @@ -2220,10 +2220,10 @@ static MemberDef *addVariableToFile( { ttype.stripPrefix("struct "); ttype.stripPrefix("union "); - static const std::regex re("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_]*", std::regex::optimize); - std::smatch match; + static const reg::Ex re(R"(\a\w*)"); + reg::Match match; std::string typ = ttype.str(); - if (std::regex_search(typ,match,re)) + if (reg::search(typ,match,re)) { QCString typeValue = match.str(); ClassDefMutable *cd = getClassMutable(typeValue); @@ -2439,11 +2439,11 @@ static int findFunctionPtr(const std::string &type,SrcLangExt lang, int *pLength return -1; // Fortran and VHDL do not have function pointers } - static const std::regex re("\\([^)]*[*\\^][^)]*\\)", std::regex::optimize); - std::smatch match; + static const reg::Ex re(R"(\([^)]*[*^][^)]*\))"); + reg::Match match; size_t i=std::string::npos; size_t l=0; - if (std::regex_search(type,match,re)) // contains (...*...) + if (reg::search(type,match,re)) // contains (...*...) { i = match.position(); l = match.length(); @@ -2532,12 +2532,12 @@ static bool isVarWithConstructor(const Entry *root) } for (const Argument &a : root->argList) { - static const std::regex initChars("[0-9\"'&*!^]+", std::regex::optimize); - std::smatch match; + static const reg::Ex initChars(R"([\d"'&*!^]+)"); + reg::Match match; if (!a.name.isEmpty() || !a.defval.isEmpty()) { std::string name = a.name.str(); - if (std::regex_search(name,match,initChars) && match.position()==0) + if (reg::search(name,match,initChars) && match.position()==0) { result=TRUE; } @@ -2567,15 +2567,15 @@ static bool isVarWithConstructor(const Entry *root) goto done; } std::string atype = a.type.str(); - if (std::regex_search(atype,match,initChars) && match.position()==0) + if (reg::search(atype,match,initChars) && match.position()==0) { result=TRUE; // argument type starts with typical initializer char goto done; } std::string resType=resolveTypeDef(ctx,a.type).str(); if (resType.empty()) resType=atype; - static const std::regex idChars("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_]*", std::regex::optimize); - if (std::regex_search(resType,match,idChars) && match.position()==0) // resType starts with identifier + static const reg::Ex idChars(R"(\a\w*)"); + if (reg::search(resType,match,idChars) && match.position()==0) // resType starts with identifier { resType=match.str(); //printf("resType=%s\n",resType.data()); @@ -2625,9 +2625,9 @@ static void addVariable(const Entry *root,int isFuncPtr=-1) type=name; std::string sargs = args.str(); - static const std::regex reName("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_]*", std::regex::optimize); - std::smatch match; - if (std::regex_search(sargs,match,reName)) + static const reg::Ex reName(R"(\a\w*)"); + reg::Match match; + if (reg::search(sargs,match,reName)) { name = match.str(); // e.g. 'var' in '(var[10])' sargs = match.suffix().str(); // e.g. '[10]) in '(var[10])' @@ -3816,9 +3816,9 @@ static TemplateNameMap getTemplateArgumentsInName(const ArgumentList &templateAr int count=0; for (const Argument &arg : templateArguments) { - static const std::regex re("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_:]*", std::regex::optimize); - std::sregex_iterator it(name.begin(),name.end(),re); - std::sregex_iterator end; + static const reg::Ex re(R"(\a[\w:]*)"); + reg::Iterator it(name,re); + reg::Iterator end; for (; it!=end ; ++it) { const auto &match = *it; @@ -5325,9 +5325,9 @@ static QCString substituteTemplatesInString( ) { std::string dst; - static const std::regex re("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_]*", std::regex::optimize); - std::sregex_iterator it(src.begin(),src.end(),re); - std::sregex_iterator end; + static const reg::Ex re(R"(\a\w*)"); + reg::Iterator it(src,re); + reg::Iterator end; //printf("type=%s\n",sa->type.data()); size_t p=0; for (; it!=end ; ++it) // for each word in srcType diff --git a/src/groupdef.cpp b/src/groupdef.cpp index 5a89a4a..095069e 100644 --- a/src/groupdef.cpp +++ b/src/groupdef.cpp @@ -17,7 +17,6 @@ #include #include -#include #include @@ -46,6 +45,7 @@ #include "dirdef.h" #include "config.h" #include "definitionimpl.h" +#include "regex.h" //--------------------------------------------------------------------------- @@ -1090,10 +1090,10 @@ void GroupDefImpl::writeDocumentation(OutputList &ol) if (Doxygen::searchIndex) { Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE); - static const std::regex we("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_\\-]*", std::regex::optimize); std::string title = m_title.str(); - std::sregex_iterator it(title.begin(),title.end(),we); - std::sregex_iterator end; + static const reg::Ex re(R"(\a[\w-]*)"); + reg::Iterator it(title,re); + reg::Iterator end; for (; it!=end ; ++it) { const auto &match = *it; diff --git a/src/htmlhelp.cpp b/src/htmlhelp.cpp index e3a007a..3d88e4f 100644 --- a/src/htmlhelp.cpp +++ b/src/htmlhelp.cpp @@ -16,7 +16,6 @@ */ #include -#include #include #include @@ -34,6 +33,7 @@ #include "filedef.h" #include "util.h" #include "linkedmap.h" +#include "regex.h" //---------------------------------------------------------------------------- @@ -154,10 +154,10 @@ void HtmlHelpIndex::addItem(const char *level1,const char *level2, const char *url,const char *anchor,bool hasLink, bool reversed) { - static const std::regex re("@[[:digit:]]+", std::regex::optimize); + static const reg::Ex re(R"(@\d+)"); std::string key = level1; if (level2) key+= std::string("?") + level2; - if (std::regex_search(key,re)) // skip anonymous stuff + if (reg::search(key,re)) // skip anonymous stuff { return; } diff --git a/src/markdown.cpp b/src/markdown.cpp index 8ac2e5f..185a43e 100644 --- a/src/markdown.cpp +++ b/src/markdown.cpp @@ -37,7 +37,6 @@ #include #include -#include #include "markdown.h" #include "growbuf.h" @@ -51,6 +50,7 @@ #include "section.h" #include "message.h" #include "portable.h" +#include "regex.h" #if !defined(NDEBUG) #define ENABLE_TRACING @@ -1472,13 +1472,13 @@ static QCString extractTitleId(QCString &title, int level) { TRACE(title.data()); // match e.g. '{#id-b11} ' and capture 'id-b11' - static const std::regex r2("\\{#([a-z_A-Z][a-z_A-Z0-9\\-]*)\\}[[:space:]]*$", std::regex::optimize); - std::smatch match; + static const reg::Ex r2(R"({#(\a[\w-]*)}\s*$)"); + reg::Match match; std::string ti = title.str(); - if (std::regex_search(ti,match,r2)) + if (reg::search(ti,match,r2)) { std::string id = match[1].str(); - title = title.left(match.position()); + title = title.left((int)match.position()); //printf("found match id='%s' title=%s\n",id.c_str(),title.data()); return id; } diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 5d2a0da..c357c43 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -13,11 +13,11 @@ * */ -#include #include #include #include + #include "md5.h" #include "memberdef.h" #include "membername.h" @@ -37,7 +37,6 @@ #include "dotcallgraph.h" #include "searchindex.h" #include "parserintf.h" - #include "vhdldocgen.h" #include "arguments.h" #include "memberlist.h" @@ -45,6 +44,7 @@ #include "filedef.h" #include "config.h" #include "definitionimpl.h" +#include "regex.h" //----------------------------------------------------------------------------- @@ -1852,10 +1852,10 @@ ClassDef *MemberDefImpl::getClassDefOfAnonymousType() const // match expression if it contains at least one @1 marker, e.g. // 'struct A::@1::@2::B' matches 'A::@1::@2::B' but 'struct A::B' does not match. - static const std::regex r("[[:alnum:]\\x80-\\xFF_@:]*@[[:digit:]]+[[:alnum:]\\x80-\\xFF_@:]*", std::regex::optimize); std::string stype = ltype.str(); - std::smatch match; - if (std::regex_search(stype,match,r)) // found anonymous scope in type + static const reg::Ex r(R"([\w@:]*@\d+[\w@:]*)"); + reg::Match match; + if (reg::search(stype,match,r)) // found anonymous scope in type { QCString annName = match.str(); @@ -2103,11 +2103,11 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, } // strip 'friend' keyword from ltype ltype.stripPrefix("friend "); - static const std::regex r("@[[:digit:]]+", std::regex::optimize); - std::smatch match; + static const reg::Ex r(R"(@\d+)"); + reg::Match match; std::string stype = ltype.str(); bool endAnonScopeNeeded=FALSE; - if (std::regex_search(stype,match,r)) // member has an anonymous type + if (reg::search(stype,match,r)) // member has an anonymous type { int i = (int)match.position(); int l = (int)match.length(); @@ -2905,9 +2905,6 @@ void MemberDefImpl::_writeTypeConstraints(OutputList &ol) const } } -// match from the start of the scope until the last marker -static const std::regex reAnonymous("[[:alnum:]\\x80-\\xFF_:]*@[[:digit:]]+([^@]*@[[:digit:]]+)?", std::regex::optimize); - void MemberDefImpl::_writeEnumValues(OutputList &ol,const Definition *container, const QCString &cfname,const QCString &ciname, const QCString &cname) const @@ -2978,6 +2975,9 @@ void MemberDefImpl::_writeEnumValues(OutputList &ol,const Definition *container, } } +// match from the start of the scope until the last marker +static const reg::Ex reAnonymous(R"([\w:@]*@\d+)"); + QCString MemberDefImpl::displayDefinition() const { QCString ldef = definition(); @@ -3010,8 +3010,8 @@ QCString MemberDefImpl::displayDefinition() const } std::string sdef = ldef.str(); - std::smatch match; - if (std::regex_search(sdef,match,reAnonymous)) + reg::Match match; + if (reg::search(sdef,match,reAnonymous)) { ldef = match.prefix().str() + " { ... } " + match.suffix().str(); } @@ -3203,10 +3203,10 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, QStrList sl; getLabels(sl,scopedContainer); - static const std::regex r("@[0-9]+", std::regex::optimize); - std::smatch match; + static const reg::Ex r(R"(@\d+)"); + reg::Match match; std::string sdef = ldef.str(); - if ((isVariable() || isTypedef()) && std::regex_search(sdef,match,r)) + if ((isVariable() || isTypedef()) && reg::search(sdef,match,r)) { // find enum type and insert it in the definition bool found=false; @@ -3234,7 +3234,7 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, // search for the last anonymous compound name in the definition ol.startMemberDocName(isObjCMethod()); - if (std::regex_search(sdef,match,reAnonymous)) + if (reg::search(sdef,match,reAnonymous)) { std::string prefix = match.prefix().str(); std::string suffix = match.suffix().str(); @@ -3612,61 +3612,18 @@ static QCString simplifyTypeForTable(const QCString &s) { QCString ts=removeAnonymousScopes(s); if (ts.right(2)=="::") ts = ts.left(ts.length()-2); - static const std::regex re("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_]*(<[^>]*>)?::([[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_]*)", std::regex::optimize); - std::smatch match; + static const reg::Ex re1(R"(\a\w*::(\a\w*))"); // non-template version + static const reg::Ex re2(R"(\a\w*<[^>]*>::(\a\w*))"); // template version + reg::Match match; std::string t = ts.str(); - if (std::regex_search(t,match,re)) + if (reg::search(t,match,re1) || reg::search(t,match,re2)) { - ts = match[2].str(); // take the identifier after the last :: (second capture group) + ts = match[1].str(); // take the identifier after the last :: } //printf("simplifyTypeForTable(%s)->%s\n",s.data(),ts.data()); return ts; } -#if 0 -/** Returns the type definition corresponding to a member's return type. - * @param[in] scope The scope in which to search for the class definition. - * @param[in] type The string representing the member's return type. - * @param[in] lang The programming language in which the class is defined. - * @param[out] start The string position where the class definition name was found. - * @param[out] length The length of the class definition's name. - */ -static Definition *getClassFromType(Definition *scope,const QCString &type,SrcLangExt lang,int &start,int &length) -{ - int pos=0; - int i; - QCString name; - QCString templSpec; - while ((i=extractClassNameFromType(type,pos,name,templSpec,lang))!=-1) - { - ClassDef *cd=0; - MemberDef *md=0; - int l = name.length()+templSpec.length(); - if (!templSpec.isEmpty()) - { - cd = getResolvedClass(scope,0,name+templSpec,&md); - } - cd = getResolvedClass(scope,0,name); - if (cd) - { - start=i; - length=l; - printf("getClassFromType: type=%s name=%s start=%d length=%d\n",type.data(),name.data(),start,length); - return cd; - } - else if (md) - { - start=i; - length=l; - printf("getClassFromType: type=%s name=%s start=%d length=%d\n",type.data(),name.data(),start,length); - return md; - } - pos=i+l; - } - return 0; -} -#endif - QCString MemberDefImpl::fieldType() const { QCString type = m_impl->accessorType; diff --git a/src/pre.l b/src/pre.l index 296295f..0b12ea9 100644 --- a/src/pre.l +++ b/src/pre.l @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -60,6 +59,7 @@ #include "condparser.h" #include "config.h" #include "filedef.h" +#include "regex.h" #define YY_NO_UNISTD_H 1 @@ -1962,17 +1962,17 @@ static void processConcatOperators(QCString &expr) if (expr.isEmpty()) return; //printf("processConcatOperators: in='%s'\n",expr.data()); std::string e = expr.str(); - static const std::regex r("[[:space:]]*##[[:space:]]*", std::regex::optimize); - std::sregex_iterator end; + static const reg::Ex r(R"(\s*##\s*)"); + reg::Iterator end; size_t i=0; for (;;) { - std::sregex_iterator it(e.begin()+i,e.end(),r); + reg::Iterator it(e,r,i); if (it!=end) { const auto &match = *it; - size_t n = i+match.position(); + size_t n = match.position(); size_t l = match.length(); //printf("Match: '%s'\n",expr.data()+i); if (n+l+1 argMap; @@ -3221,12 +3221,12 @@ static void initPredefined(yyscan_t yyscanner,const char *fileName) { size_t i=i_obrace+1; //printf("predefined function macro '%s'\n",ds.c_str()); - std::sregex_iterator it(ds.begin()+i,ds.end(),reId); + reg::Iterator it(ds,reId,i); // gather the formal arguments in a dictionary while (i0) // see bug375037 { @@ -3244,7 +3244,7 @@ static void initPredefined(yyscan_t yyscanner,const char *fileName) // strip definition part std::string definition; std::string in=ds.substr(i_equals+1); - std::sregex_iterator re_it(in.begin(),in.end(),reId); + reg::Iterator re_it(in,reId); size_t i=0; // substitute all occurrences of formal arguments by their // corresponding markers diff --git a/src/regex.cpp b/src/regex.cpp new file mode 100644 index 0000000..e3aa057 --- /dev/null +++ b/src/regex.cpp @@ -0,0 +1,736 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2021 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 + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +#include "regex.h" +#include +#include +#include +#include +#include + +#define ENABLE_DEBUG 0 +#if ENABLE_DEBUG +#define DBG(fmt,...) do { fprintf(stderr,fmt,__VA_ARGS__); } while(0) +#else +#define DBG(fmt,...) do {} while(0) +#endif + +namespace reg +{ + +/** Class representing a token in the compiled regular expression token stream. + * A token has a kind and an optional value whose meaning depends on the kind. + * It is also possible to store a (from,to) character range in a token. + */ +class PToken +{ + public: + /** The kind of token. + * + * Ranges per bit mask: + * - `0x00FF` from part of a range, except for `0x0000` which is the End marker + * - `0x1FFF` built-in ranges + * - `0x2FFF` user defined ranges + * - `0x4FFF` special operations + * - `0x8000` literal character + */ + enum class Kind : uint16_t + { + End = 0x0000, + WhiteSpace = 0x1001, // \s range [ \t\r\n] + Digit = 0x1002, // \d range [0-9] + Alpha = 0x1003, // \a range [a-z_A-Z\x80-\xFF] + AlphaNum = 0x1004, // \w range [a-Z_A-Z0-9\x80-\xFF] + CharClass = 0x2001, // [] + NegCharClass = 0x2002, // [^] + BeginOfLine = 0x4001, // ^ + EndOfLine = 0x4002, // $ + BeginOfWord = 0x4003, // \< + EndOfWord = 0x4004, // \> + BeginCapture = 0x4005, // ( + EndCapture = 0x4006, // ) + Any = 0x4007, // . + Star = 0x4008, // * + Optional = 0x4009, // ? + Character = 0x8000 // c + }; + + /** returns a string representation of the tokens kind (useful for debugging). */ + const char *kindStr() const + { + if ((m_rep>>16)>=0x1000 || m_rep==0) + { + switch(static_cast((m_rep>>16))) + { + case Kind::End: return "End"; + case Kind::Alpha: return "Alpha"; + case Kind::AlphaNum: return "AlphaNum"; + case Kind::WhiteSpace: return "WhiteSpace"; + case Kind::Digit: return "Digit"; + case Kind::CharClass: return "CharClass"; + case Kind::NegCharClass: return "NegCharClass"; + case Kind::Character: return "Character"; + case Kind::BeginOfLine: return "BeginOfLine"; + case Kind::EndOfLine: return "EndOfLine"; + case Kind::BeginOfWord: return "BeginOfWord"; + case Kind::EndOfWord: return "EndOfWord"; + case Kind::BeginCapture: return "BeginCapture"; + case Kind::EndCapture: return "EndCapture"; + case Kind::Any: return "Any"; + case Kind::Star: return "Star"; + case Kind::Optional: return "Optional"; + } + } + else + { + return "Range"; + } + } + + /** Creates a token of kind 'End' */ + PToken() : m_rep(0) {} + + /** Creates a token of the given kind \a k */ + explicit PToken(Kind k) : m_rep(static_cast(k)<<16) {} + + /** Create a token for an ASCII character */ + PToken(char c) : m_rep((static_cast(Kind::Character)<<16) | + static_cast(c)) {} + + /** Create a token for a byte of an UTF-8 character */ + PToken(uint16_t v) : m_rep((static_cast(Kind::Character)<<16) | + static_cast(v)) {} + + /** Create a token representing a range from one character \a from to another character \a to */ + PToken(uint16_t from,uint16_t to) : m_rep(static_cast(from)<<16 | to) {} + + /** Sets the value for a token */ + void setValue(uint16_t value) { m_rep = (m_rep & 0xFFFF0000) | value; } + + /** Returns the kind of the token */ + Kind kind() const { return static_cast(m_rep>>16); } + + /** Returns the 'from' part of the character range. Only valid if this token represents a range */ + uint16_t from() const { return m_rep>>16; } + + /** Returns the 'to' part of the character range. Only valid if this token represents a range */ + uint16_t to() const { return m_rep & 0xFFFF; } + + /** Returns the value for this token */ + uint16_t value() const { return m_rep & 0xFFFF; } + + /** Returns the value for this token as a ASCII character */ + char asciiValue() const { return static_cast(m_rep); } + + /** Returns true iff this token represents a range of characters */ + bool isRange() const { return m_rep!=0 && from()<=to(); } + + /** Returns true iff this token is a positive or negative character class */ + bool isCharClass() const { return kind()==Kind::CharClass || kind()==Kind::NegCharClass; } + + private: + uint32_t m_rep; +}; + +/** Private members of a regular expression */ +class Ex::Private +{ + public: + /** Creates the private part */ + Private(const std::string &pat) : pattern(pat) + { + data.reserve(100); + } + void compile(); +#if ENABLE_DEBUG + void dump(); +#endif + bool matchAt(size_t tokenPos,const std::string &str,Match &match,size_t pos,int level) const; + + /** Flag indicating the expression was succesfully compiled */ + bool error = false; + + /** The token stream representing the compiled regular expression. */ + std::vector data; // compiled pattern + + /** The pattern string as passed by the user */ + std::string pattern; +}; + +/** Compiles a regular expression passed as a string into a stream of tokens that can be used for + * efficient searching. + */ +void Ex::Private::compile() +{ + error = false; + data.clear(); + if (pattern.empty()) return; + const char *start = pattern.c_str(); + const char *ps = start; + char c; + + int prevTokenPos=-1; + int tokenPos=0; + + auto addToken = [&](PToken tok) + { + tokenPos++; + data.emplace_back(tok); + }; + + auto getNextCharacter = [&]() -> PToken + { + char cs=*ps; + PToken result = PToken(cs); + if (cs=='\\') // escaped character + { + ps++; + cs=*ps; + switch (cs) + { + case 'n': result = PToken('\n'); break; + case 'r': result = PToken('\r'); break; + case 't': result = PToken('\t'); break; + case 's': result = PToken(PToken::Kind::WhiteSpace); break; + case 'a': result = PToken(PToken::Kind::Alpha); break; + case 'w': result = PToken(PToken::Kind::AlphaNum); break; + case 'd': result = PToken(PToken::Kind::Digit); break; + case '<': result = PToken(PToken::Kind::BeginOfWord); break; + case '>': result = PToken(PToken::Kind::EndOfWord); break; + case 'x': + case 'X': + { + uint16_t v=0; + for (int i=0;i<2 && (cs=(*(ps+1)));i++) // 2 hex digits + { + int d = (cs>='a' && cs<='f') ? cs-'a'+10 : + (cs>='A' && cs<='F') ? cs-'A'+10 : + (cs>='0' && cs<='9') ? cs-'0' : + -1; + if (d>=0) { v<<=4; v|=d; ps++; } else break; + } + result = PToken(v); + } + break; + case '\0': ps--; break; // backslash at the end of the pattern + default: + result = PToken(cs); + break; + } + } + return result; + }; + + while ((c=*ps)) + { + switch (c) + { + case '^': // beginning of line (if first character of the pattern) + prevTokenPos = tokenPos; + addToken(ps==start ? PToken(PToken::Kind::BeginOfLine) : + PToken(c)); + break; + case '$': // end of the line (if last character of the pattern) + prevTokenPos = tokenPos; + addToken(*(ps+1)=='\0' ? PToken(PToken::Kind::EndOfLine) : + PToken(c)); + break; + case '.': // any character + prevTokenPos = tokenPos; + addToken(PToken(PToken::Kind::Any)); + break; + case '(': // begin of capture group + prevTokenPos = tokenPos; + addToken(PToken(PToken::Kind::BeginCapture)); + break; + case ')': // end of capture group + prevTokenPos = tokenPos; + addToken(PToken(PToken::Kind::EndCapture)); + break; + case '[': // character class + { + prevTokenPos = tokenPos; + ps++; + if (*ps==0) { error=true; return; } + bool esc = *ps=='\\'; + PToken tok = getNextCharacter(); + ps++; + if (!esc && tok.kind()==PToken::Kind::Character && + tok.asciiValue()=='^') // negated character class + { + addToken(PToken(PToken::Kind::NegCharClass)); + if (*ps==0) { error=true; return; } + tok = getNextCharacter(); + ps++; + } + else + { + addToken(PToken(PToken::Kind::CharClass)); + } + uint16_t numTokens=0; + while ((c=*ps)) + { + if (c=='-' && *(ps+1)!=']' && *(ps+1)!=0) // range + { + getNextCharacter(); + ps++; + PToken endTok = getNextCharacter(); + ps++; + if (tok.value()>endTok.value()) + { + addToken(PToken(endTok.value(),tok.value())); // swap start and end + } + else + { + addToken(PToken(tok.value(),endTok.value())); + } + numTokens++; + } + else // single char, from==to + { + if (tok.kind()==PToken::Kind::Character) + { + addToken(PToken(tok.value(),tok.value())); + } + else // special token, add as-is since from>to + { + addToken(tok); + } + numTokens++; + } + if (*ps==0) { error=true; return; } // expected at least a ] + esc = *ps=='\\'; + tok = getNextCharacter(); + if (!esc && tok.kind()==PToken::Kind::Character && + tok.value()==static_cast(']')) + { + break; // end of character class + } + if (*ps==0) { error=true; return; } // no ] found + ps++; + } + // set the value of either NegCharClass or CharClass + data[prevTokenPos].setValue(numTokens); + } + break; + case '*': // 0 or more + case '+': // 1 or more + case '?': // optional: 0 or 1 + { + if (prevTokenPos==-1) + { + error=true; + return; + } + switch (data[prevTokenPos].kind()) + { + case PToken::Kind::BeginOfLine: // $* or $+ or $? + case PToken::Kind::BeginOfWord: // \<* or \<+ or \* or \>+ or \>? + case PToken::Kind::Star: // ** or *+ or *? + case PToken::Kind::Optional: // ?* or ?+ or ?? + error=true; + return; + default: // ok + break; + } + int ddiff = static_cast(tokenPos-prevTokenPos); + if (*ps=='+') // convert + -> * + { + // turn a sequence of token [T1...Tn] followed by '+' into [T1..Tn T1..Tn T*] + // ddiff=n ^prevTokenPos + data.resize(data.size()+ddiff); + std::copy_n(data.begin()+prevTokenPos,ddiff,data.begin()+tokenPos); + prevTokenPos+=ddiff; + tokenPos+=ddiff; + } + data.insert(data.begin()+prevTokenPos, + c=='?' ? PToken(PToken::Kind::Optional) : PToken(PToken::Kind::Star)); + tokenPos++; + addToken(PToken(PToken::Kind::End)); + // turn a sequence of tokens [T1 T2 T3] followed by 'T*' or into [T* T1 T2 T3 TEND] + // ^prevTokenPos + // same for 'T?'. + } + break; + default: + prevTokenPos = tokenPos; + addToken(getNextCharacter()); + break; + } + ps++; + } + //addToken(PToken(PToken::Kind::End)); +} + +#if ENABLE_DEBUG +/** Dump the compiled token stream for this regular expression. For debugging purposes. */ +void Ex::Private::dump() +{ + size_t l = data.size(); + size_t i =0; + DBG("==== compiled token stream for pattern '%s' ===\n",pattern.c_str()); + while (i0 && i bool + { + PToken tok = data[tp]; + bool negate = tok.kind()==PToken::Kind::NegCharClass; + uint16_t numFields = tok.value(); + bool found = false; + for (uint16_t i=0;i(c); + if (tok.from()<=v && v<=tok.to()) + { + found=true; + break; + } + } + } + DBG("matchCharClass(tp=%zu,c=%c (x%02x))=%d\n",tp,c,c,negate?!found:found); + return negate ? !found : found; + }; + size_t index = pos; + enum SequenceType { Star, Optional }; + auto processSequence = [this,&tokenPos,&index,&str,&matchCharClass, + &isStartIdChar,&isIdChar,&match,&level,&pos](SequenceType type) -> bool + { + size_t startIndex = index; + PToken tok = data[++tokenPos]; + if (tok.kind()==PToken::Kind::Character) // 'x*' -> eat x's + { + char c_tok = tok.asciiValue(); + while (index<=str.length() && str[index]==c_tok) { index++; if (type==Optional) break; } + tokenPos++; + } + else if (tok.isCharClass()) // '[a-f0-4]* -> eat matching characters + { + while (index<=str.length() && matchCharClass(tokenPos,str[index])) { index++; if (type==Optional) break; } + tokenPos+=tok.value()+1; // skip over character ranges + end token + } + else if (tok.kind()==PToken::Kind::Alpha) // '\a*' -> eat start id characters + { + while (index<=str.length() && isStartIdChar(str[index])) { index++; if (type==Optional) break; } + tokenPos++; + } + else if (tok.kind()==PToken::Kind::AlphaNum) // '\w*' -> eat id characters + { + while (index<=str.length() && isIdChar(str[index])) { index++; if (type==Optional) break; } + tokenPos++; + } + else if (tok.kind()==PToken::Kind::WhiteSpace) // '\s*' -> eat spaces + { + while (index<=str.length() && std::isspace(str[index])) { index++; if (type==Optional) break; } + tokenPos++; + } + else if (tok.kind()==PToken::Kind::Digit) // '\d*' -> eat digits + { + while (index<=str.length() && std::isdigit(str[index])) { index++; if (type==Optional) break; } + tokenPos++; + } + else if (tok.kind()==PToken::Kind::Any) // '.*' -> eat all + { + if (type==Optional) index++; else index = str.length(); + tokenPos++; + } + tokenPos++; // skip over end marker + while ((int)index>=(int)startIndex) + { + // pattern 'x*xy' should match 'xy' and 'xxxxy' + bool found = matchAt(tokenPos,str,match,index,level+1); + if (found) + { + match.setMatch(pos,index-pos+match.length()); + return true; + } + index--; + } + return false; + }; + + while (tokenPos=str.length() || str[index]!=c_tok) return false; // end of string, or non matching char + index++,tokenPos++; + } + else if (tok.isCharClass()) + { + if (index>=str.length() || !matchCharClass(tokenPos,str[index])) return false; + index++,tokenPos+=tok.value()+1; // skip over character ranges + end token + } + else + { + switch (tok.kind()) + { + case PToken::Kind::Alpha: + if (index>=str.length() || !isStartIdChar(str[index])) return false; + index++; + break; + case PToken::Kind::AlphaNum: + if (index>=str.length() || !isIdChar(str[index])) return false; + index++; + break; + case PToken::Kind::WhiteSpace: + if (index>=str.length() || !std::isspace(str[index])) return false; + index++; + break; + case PToken::Kind::Digit: + if (index>=str.length() || !std::isdigit(str[index])) return false; + index++; + break; + case PToken::Kind::BeginOfLine: + if (index!=pos) return false; + break; + case PToken::Kind::EndOfLine: + if (index0?str[index]-1:0, + index>0?isIdChar(str[index-1]):-1); + if (index>=str.length() || + !isIdChar(str[index]) || + (index>0 && isIdChar(str[index-1]))) return false; + break; + case PToken::Kind::EndOfWord: + DBG("EndOfWord: index=%zu pos=%zu idIdChar(%c)=%d prev.isIsChar(%c)=%d\n", + index,pos,str[index],isIdChar(str[index]), + index==0 ? 0 : str[index-1], + index==0 ? -1 : isIdChar(str[index-1])); + if (index=str.length()) return false; + index++; + break; + case PToken::Kind::Star: + return processSequence(Star); + case PToken::Kind::Optional: + return processSequence(Optional); + default: + return false; + } + tokenPos++; + } + } + match.setMatch(pos,index-pos); + return true; +} + +static std::string wildcard2regex(const std::string &pattern) +{ + std::string result="^"; // match start of input + char c; + const char *p = pattern.c_str(); + while ((c=*p++)) + { + switch(c) + { + case '*': + result+=".*"; + break; // '*' => '.*' + case '?': + result+='.'; + break; // '?' => '.' + case '.': + case '+': + case '\\': + case '$': + case '^': + case '(': + case ')': + result+='\\'; result+=c; // escape + break; + case '[': + if (*p=='^') // don't escape ^ after [ + { + result+="[^"; + p++; + } + else + { + result+=c; + } + break; + default: // just copy + result+=c; + break; + } + } + result+='$'; // match end of input + return result; +} + + +Ex::Ex(const std::string &pattern, Mode mode) + : p(std::make_unique(mode==Mode::RegEx ? pattern : wildcard2regex(pattern))) +{ + p->compile(); +#if ENABLE_DEBUG + p->dump(); + assert(!p->error); +#endif +} + +Ex::~Ex() +{ +} + +bool Ex::match(const std::string &str,Match &match,size_t pos) const +{ + bool found=false; + if (p->data.size()==0 || p->error) return found; + match.init(&str); + + PToken tok = p->data[0]; + if (tok.kind()==PToken::Kind::BeginOfLine) // only test match at the given position + { + found = p->matchAt(0,str,match,pos,0); + } + else + { + if (tok.kind()==PToken::Kind::Character) // search for the start character + { + size_t index = str.find(tok.asciiValue(),pos); + if (index==std::string::npos) + { + DBG("Ex::match(str='%s',pos=%zu)=false (no start char '%c')\n",str.c_str(),pos,tok.asciiValue()); + return false; + } + DBG("pos=%zu str='%s' char='%c' index=%zu\n",index,str.c_str(),tok.asciiValue(),index); + pos=index; + } + while (posmatchAt(0,str,match,pos,0); + if (found) break; + pos++; + } + } + DBG("Ex::match(str='%s',pos=%zu)=%d\n",str.c_str(),pos,found); + return found; +} + +bool Ex::isValid() const +{ + return !p->pattern.empty() && !p->error; +} + +//---------------------------------------------------------------------------------------- + +bool search(const std::string &str,Match &match,const Ex &re,size_t pos) +{ + return re.match(str,match,pos); +} + +bool search(const std::string &str,const Ex &re,size_t pos) +{ + Match match; + return re.match(str,match,pos); +} + +bool match(const std::string &str,Match &match,const Ex &re) +{ + return re.match(str,match,0) && match.position()==0 && match.length()==str.length(); +} + +bool match(const std::string &str,const Ex &re) +{ + Match match; + return re.match(str,match,0) && match.position()==0 && match.length()==str.length(); +} + +std::string replace(const std::string &str,const Ex &re,const std::string &replacement) +{ + std::string result; + Match match; + size_t p=0; + while (re.match(str,match,p)) + { + size_t i=match.position(); + size_t l=match.length(); + if (i>p) result+=str.substr(p,i-p); + result+=replacement; + p=i+l; + } + if (p +#include +#include +#include + +/** Namespace for the regular expression functions */ +namespace reg +{ + +class Match; + +/** Class representing a regular expression. + * + * It has a similar API as `std::regex`, + * but is much faster (and also somewhat more limited). + */ +class Ex +{ + public: + /** Matching algorithm */ + enum class Mode + { + RegEx, /**< full regular expression. */ + Wildcard /**< simple globbing pattern. */ + }; + /** Creates a regular expression object given the pattern as a string. + * Two modes of matching are supported: RegEx and Wildcard + * + * The following special characters are supported in Mode::RegEx mode. + * - `c` matches character `c` + * - `.` matches any character + * - `^` matches the start of the input + * - `$` matches the end of the input + * - `\<` matches the start of a word + * - `\>` matches the end of a word + * - `[]` matches a set of characters + * - `x*` matches a sequence of zero or more `x`'s + * - `x+` matches a sequence of one or more `x`'s + * - `x?` matches an optional `x` + * - `(` matches the start of a capture range + * - `)` matches the ends a capture range + * - `\c` to escape a special character, such as `+`, `[`, `*`, `(`, etc. + * - `\t` matches a tab character + * - `\n` matches a newline character + * - `\r` matches a return character + * - `\s` matches any whitespace as defined by `std::isspace()` + * - `\d` matches any digit as defined by `std::digit()` + * - `\a` matches any alphabetical characters, same as `[a-z_A-Z\x80-\xFF]` + * - `\w` matches any alpha numercial character, same as `[a-z_A-Z0-9\x80-\xFF]` + * - `\xHH` matches a hexadecimal character, e.g. `\xA0` matches character code 160. + * + * A character range can be used to match a character that falls inside a range + * (or set of ranges). + * Within the opening `[` and closing `]` brackets of a character ranges the following + * is supported: + * - `^` if at the start of the range, a character matches if it is \e not in the range, + * e.g. `[^\d]` matches any character not a digit + * - `-` when placed between 2 characters it defines a range from the first character to the second. + * any character that falls in the range will match, e.g. [0-9] matches the digit from 0 to 9. + * - `\s`, `\d`, `\a`, and `\w` as explained above. + * + * @note that special characters `.`, `*`, `?`, `$`, `+`, `[` do not have a special + * meaning in a character range. `^` only has a special meaning as the first character. + * + * @note that capture ranges cannot be nested, and `*`, `+`, and `?` do not work on + * capture ranges. e.g. `(abd)?` is not valid. If multiple capture ranges are + * specified then some character has to be inbetween them, + * e.g. this does not work `(.*)(a.*)`, but this does `(.*)a(.*)`. + * + * In Wildcard mode `*` is used to match any sequence of zero or more characters. + * The character `?` can be used to match an optional character. Character ranges are + * also supported, but other characters like `$` and `+` are just treated as + * literal characters. + * + */ + Ex(const std::string &pattern, Mode mode=Mode::RegEx); + + /** Destroys the regular expression object. Frees resources. */ + ~Ex(); + + /** Check if a given string matches this regular expression. + * @param str The input string to match against. + * @param match The match object to hold the matching results. + * @param pos The position in the string at which to start the match. + * @returns true iff a match is found. Details are stored in the match object. + */ + bool match(const std::string &str,Match &match,size_t pos=0) const; + bool isValid() const; + private: + Ex(const Ex &) = delete; + Ex &operator=(const Ex &e) = delete; + + class Private; + std::unique_ptr p; +}; + +/** Object representing the match results of a capture range. */ +class SubMatch +{ + public: + /** Creates a match for a single capture range given a non-owning pointer to the string. */ + SubMatch(const std::string *str) : m_str(str) {} + + /** Returns the position in the string at which the match starts. */ + size_t position() const { return m_pos; } + + /** Returns the length of the matching part. */ + size_t length() const { return m_len; } + + /** Returns the matching part as a string */ + std::string str() const { return m_str ? m_str->substr(m_pos,m_len) : std::string(); } + + private: + friend class Match; + void setStart(size_t pos) { m_pos=pos; } + void setEnd(size_t pos) { m_len=pos-m_pos; } + void setMatch(size_t pos,size_t len) { m_pos=pos; m_len=len; } + size_t m_pos = std::string::npos; + size_t m_len = std::string::npos; + const std::string *m_str = nullptr; +}; + +/** Object representing the matching results. It consists of an array of + * SubMatch objects. The first entry of the array represents the whole match, any + * next elements represent each of the capture ranges. + * + * For example string `@42` and expression `@(\\d+)` will have two + * Submatches, match[0] will point to the input string as a whole, and + * match[1] will point to the number 42 only. + * + */ +class Match +{ + public: + /** Creates an empty match object */ + Match() {} + + /** Returns the position of the match or std::string::npos if no position is set. */ + size_t position() const { return m_subMatches[0].position(); } + + /** Returns the position of the match or std::string::npos if no length is set. */ + size_t length() const { return m_subMatches[0].length(); } + + /** Return a string representing the matching part. */ + std::string str() const { return m_subMatches[0].str(); } + + /** Return the part of the string after the match */ + SubMatch suffix() const { SubMatch m(m_str); m.setMatch(0,position()); return m; } + + /** Return the part of the string before the match */ + SubMatch prefix() const + { + SubMatch m(m_str); + if (m_str) + { + size_t e = position()+length(); + m.setMatch(e,m_str->length()-e); + } + return m; + } + + /** Returns the number of sub matches available in this match. */ + size_t size() const { return m_subMatches.size(); } + + /** Returns the n-th SubMatch object. Note that there is always 1 SubMatch object + * representing the whole match. + */ + const SubMatch &operator[](size_t index) const { return m_subMatches[index]; } + + private: + friend class Ex; + void init(const std::string *str) + { + m_subMatches.clear(); + m_subMatches.emplace_back(str); + m_str = str; + } + void startCapture(size_t index) + { + if (!m_insideCapture) // when backtracking we can re-entry the capture multiple times + // only update the index, example `\s*(x)` + { + m_captureIndex = m_subMatches.size(); + m_subMatches.emplace_back(m_str); + m_insideCapture = true; + } + m_subMatches.back().setStart(index); + } + void endCapture(size_t index) + { + if (index>m_subMatches.back().position()) + { + m_captureIndex=0; + m_subMatches.back().setEnd(index); + m_insideCapture = false; + } + } + void setMatch(size_t pos,size_t len) + { + m_subMatches[m_captureIndex].setMatch(pos,len); + } + + std::vector m_subMatches; + size_t m_captureIndex=0; + const std::string *m_str = nullptr; + bool m_insideCapture=false; +}; + +/** Iterator class to iterator through matches. + */ +class Iterator +{ + public: + using value_type = Match; + using difference_type = std::ptrdiff_t; + using pointer = value_type*; + using reference = value_type&; + using iterator_category = std::forward_iterator_tag; + + /** Creates an end-of-sequence iterator */ + Iterator() {} + + /** Creates an iterator for input string \a str, using regular expression \a re to search. + * @note the string and regular expression objects should remain valid while iterating. + */ + Iterator(const std::string &str, const Ex &re, size_t pos=0) + : m_str(&str), m_re(&re), m_pos(pos) { findNext(); } + + // Iterator holds pointers, so prevent temporaries to be passed as string or + // regular expression + Iterator(std::string &&str, const Ex &re) = delete; + Iterator(const std::string &str, Ex &&re) = delete; + Iterator(std::string &&str, Ex &&re) = delete; + + /** Returns true if the iterators point to the same match (or both are end-of-sequence iterators) */ + bool operator==(const Iterator &rhs) const { return rhs.m_pos==m_pos; } + + /** Returns true if the iterators are not pointing to the same match */ + bool operator!=(const Iterator &rhs) const { return rhs.m_pos!=m_pos; } + + /** Returns a reference to the current match */ + const value_type &operator*() const { return m_match; } + + /** Returns a pointer to the current match */ + const value_type *operator->() const { return &m_match; } + + /** Advances the iterator to the next match. */ + Iterator &operator++() { findNext(); return *this; } + + private: + void findNext() + { + if (!m_re || !m_str) { m_pos=std::string::npos; return; } // end marker + if (m_re->match(*m_str,m_match,m_pos)) + { + m_pos=m_match.position()+m_match.length(); // update m_pos to point beyond last match + } + else // no more matches, make the iterator point to the 'end-of-sequence' + { + m_pos=std::string::npos; + } + } + const std::string *m_str = nullptr; + const Ex *m_re = nullptr; + size_t m_pos = std::string::npos; + Match m_match; +}; + +/** Search in a given string \a str starting at position \a pos for a match against regular expression \a re. + * Returns true iff a match was found. + * Details of what part of the string has matched is returned via the \a match object. + * + * An example to show how to match all identifiers in a string. + * @code + * static reg::Ex re(R"(\a\w*)"); + * std::string = u8"void(Func是(42));"; + * while (reg::search(str,match,re,pos)) + * { + * std::cout << match.str() << std::endl; + * pos=match.position()+match.length(); + * } + * @endcode + * produces: + * @code + * void + * Func是 + * B_C + * Códe42 + * @endcode + * + * @see Ex::Ex() for details on the regular expression patterns. + */ +bool search(const std::string &str,Match &match,const Ex &re,size_t pos=0); + +/** Search in a given string \a str starting at position \a pos for a match against regular expression \a re. + * Returns true iff a match was found. + */ +bool search(const std::string &str,const Ex &re,size_t pos=0); + +/** Matches a given string \a str for a match against regular expression \a re. + * Returns true iff a match was found for the whole string. + * Any capture groups are returned via the \a match object. + */ +bool match(const std::string &str,Match &match,const Ex &re); + +/** Matches a given string \a str for a match against regular expression \a re. + * Returns true iff a match was found for the whole string. + */ +bool match(const std::string &str,const Ex &re); + +/** Searching in a given input string \a for parts that match regular expression \a re and + * replaces those parts by string \a replacement. + */ +std::string replace(const std::string &str,const Ex &re,const std::string &replacement); + +} // namespace + +#endif diff --git a/src/rtfstyle.cpp b/src/rtfstyle.cpp index cbe2468..d279eab 100644 --- a/src/rtfstyle.cpp +++ b/src/rtfstyle.cpp @@ -13,12 +13,12 @@ * */ -#include #include #include #include "rtfstyle.h" #include "message.h" +#include "regex.h" RTFListItemInfo rtf_listItemInfo[rtf_maxIndentLevels]; @@ -234,12 +234,12 @@ Rtf_Style_Default rtf_Style_Default[] = } }; -static const std::regex s_clause("\\\\s([[:digit:]]+)[[:space:]]*", std::regex::optimize); +static const reg::Ex s_clause(R"(\\s(\d+)\s*)"); // match, e.g. '\s30' and capture '30' StyleData::StyleData(const std::string &reference, const std::string &definition) { - std::smatch match; - if (std::regex_search(reference,match,s_clause)) + reg::Match match; + if (reg::search(reference,match,s_clause)) { m_index = static_cast(std::stoul(match[1].str())); } @@ -253,19 +253,19 @@ StyleData::StyleData(const std::string &reference, const std::string &definition bool StyleData::setStyle(const std::string &command, const std::string &styleName) { - std::smatch match; - if (!std::regex_search(command,match,s_clause)) + reg::Match match; + if (!reg::search(command,match,s_clause)) { err("Style sheet '%s' contains no '\\s' clause.\n{%s}", styleName.c_str(), command.c_str()); return false; } m_index = static_cast(std::stoul(match[1].str())); - static const std::regex definition_splitter("^(.*)(\\\\sbasedon[[:digit:]]+.*)$", std::regex::optimize); - if (std::regex_match(command,match,definition_splitter)) + size_t index = command.find("\\sbasedon"); + if (index!=std::string::npos) { - m_reference = match[1].str(); - m_definition = match[2].str(); + m_reference = command.substr(0,index); + m_definition = command.substr(index); } return true; @@ -287,12 +287,12 @@ void loadStylesheet(const char *name, StyleDataMap& map) for (std::string line ; getline(file,line) ; ) // for each line { if (line.empty() || line[0]=='#') continue; // skip blanks & comments - static const std::regex assignment_splitter("[[:space:]]*=[[:space:]]*", std::regex::optimize); - std::smatch match; - if (std::regex_search(line,match,assignment_splitter)) + static const reg::Ex assignment_splitter(R"(\s*=\s*)"); + reg::Match match; + if (reg::search(line,match,assignment_splitter)) { - std::string key = match.prefix(); - std::string value = match.suffix(); + std::string key = match.prefix().str(); + std::string value = match.suffix().str(); auto it = map.find(key); if (it!=map.end()) { @@ -329,12 +329,12 @@ void loadExtensions(const char *name) for (std::string line ; getline(file,line) ; ) // for each line { if (line.empty() || line[0]=='#') continue; // skip blanks & comments - std::smatch match; - static const std::regex assignment_splitter("[[:space:]]*=[[:space:]]*", std::regex::optimize); - if (std::regex_search(line,match,assignment_splitter)) + static const reg::Ex assignment_splitter(R"(\s*=\s*)"); + reg::Match match; + if (reg::search(line,match,assignment_splitter)) { - std::string key = match.prefix(); - std::string value = match.suffix(); + std::string key = match.prefix().str(); + std::string value = match.suffix().str(); auto it = g_styleMap.find(key); if (it!=g_styleMap.end()) { diff --git a/src/scanner.l b/src/scanner.l index 4a1e720..0193689 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -51,6 +50,7 @@ #include "clangparser.h" #include "markdown.h" +#include "regex.h" #define YY_NO_INPUT 1 #define YY_NO_UNISTD_H 1 @@ -3739,9 +3739,9 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } else { - static const std::regex re("@[0-9]+$", std::regex::optimize); + static const reg::Ex re(R"(@\d+$)"); if (!yyextra->isTypedef && yyextra->memspecEntry && - !std::regex_search(yyextra->memspecEntry->name.str(),re)) // not typedef or anonymous type (see bug691071) + !reg::search(yyextra->memspecEntry->name.str(),re)) // not typedef or anonymous type (see bug691071) { // enabled the next two lines for bug 623424 yyextra->current->doc.resize(0); @@ -4831,11 +4831,11 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->fileName = yyextra->yyFileName; yyextra->current->startLine = yyextra->yyBegLineNr; yyextra->current->startColumn = yyextra->yyBegColNr; - static const std::regex re("\\([^)]*[*&][^]*\\)", std::regex::optimize); - std::smatch match; + static const reg::Ex re(R"(\([^)]*[*&][^)]*\))"); + reg::Match match; std::string type = yyextra->current->type.str(); int ti=-1; - if (std::regex_search(type,match,re)) + if (reg::search(type,match,re)) { ti = (int)match.position(); } @@ -6895,16 +6895,26 @@ static void splitKnRArg(yyscan_t yyscanner,QCString &oldStyleArgPtr,QCString &ol int si = yyextra->current->args.length(); if (yyextra->oldStyleArgType.isEmpty()) // new argument { - static const std::regex re("(\\([^)]*\\))[[:space:]]*(\\([^)]*\\))?", std::regex::optimize); std::string args = yyextra->current->args.str(); - std::smatch matches; - std::regex_search(args,matches,re); + static const reg::Ex re(R"(\([^)]*\).*)"); // find first (...) + int bi1=-1; + int bi2=-1; + reg::Match match; + if (reg::search(args,match,re)) + { + bi1=(int)match.position(); + size_t secondMatchStart = match.position()+match.length(); // search again after first match + if (reg::search(args,match,re,secondMatchStart)) + { + bi2=(int)match.position(); + } + } char c; - if (matches.length()==3 && !matches[2].str().empty()) // found something like "int (*func)(int arg)" + if (bi1!=-1 && bi2!=-1) // found something like "int (*func)(int arg)" { - size_t s = matches.position()+1; // keep opening ( + int s=bi2+1; // keep opening ( yyextra->oldStyleArgType = yyextra->current->args.left(s); - int i=(int)s; + int i=s; while (icurrent->args.at(i))=='*' || isspace((uchar)c))) i++; yyextra->oldStyleArgType += yyextra->current->args.mid(s,i-s); s=i; @@ -6912,12 +6922,12 @@ static void splitKnRArg(yyscan_t yyscanner,QCString &oldStyleArgPtr,QCString &ol oldStyleArgName = yyextra->current->args.mid(s,i-s); yyextra->oldStyleArgType+=yyextra->current->args.mid(i); } - else if (matches.length()==3) // redundant braces like in "int (*var)" + else if (bi1!=-1) // redundant braces like in "int (*var)" { - size_t s = matches.position(); // strip opening ( + int s=bi1; // strip opening ( yyextra->oldStyleArgType = yyextra->current->args.left(s); s++; - int i=(int)s+1; + int i=s+1; while (icurrent->args.at(i))=='*' || isspace((uchar)c))) i++; yyextra->oldStyleArgType += yyextra->current->args.mid(s,i-s); s=i; diff --git a/src/template.cpp b/src/template.cpp index 4c296aa..9f1eb92 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include @@ -30,6 +29,7 @@ #include "util.h" #include "resourcemgr.h" #include "portable.h" +#include "regex.h" #define ENABLE_TRACING 0 @@ -4186,9 +4186,9 @@ class TemplateNodeMarkers : public TemplateNodeCreator c->push(); std::string str = patternStr.toString().str(); - static const std::regex marker("@([[:digit:]]+)", std::regex::optimize); - std::sregex_iterator re_it(str.begin(),str.end(),marker); - std::sregex_iterator end; + static const reg::Ex marker(R"(@\d+)"); + reg::Iterator re_it(str,marker); + reg::Iterator end; size_t index=0; for ( ; re_it!=end ; ++re_it) { @@ -4204,7 +4204,7 @@ class TemplateNodeMarkers : public TemplateNodeCreator { ts << part; // write text before marker } - unsigned long entryIndex = std::stoul(match[1].str()); + unsigned long entryIndex = std::stoul(match.str().substr(1)); TemplateVariant var; size_t i=0; // search for list element at position id diff --git a/src/util.cpp b/src/util.cpp index 9b76714..1677b26 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -22,7 +22,6 @@ #include #include -#include #include #include #include @@ -35,6 +34,7 @@ #include #include +#include "regex.h" #include "util.h" #include "message.h" #include "classdef.h" @@ -188,10 +188,10 @@ QCString removeAnonymousScopes(const char *str) return false; }; - static const std::regex re("[ :]*@[[:digit:]]+[: ]*", std::regex::optimize); + static const reg::Ex re(R"([\s:]*@\d+[\s:]*)"); std::string s = str; - std::sregex_iterator iter( s.begin(), s.end(), re); - std::sregex_iterator end; + reg::Iterator iter(s,re); + reg::Iterator end; size_t p=0; size_t sl=s.length(); bool needsSeparator=false; @@ -221,8 +221,8 @@ QCString removeAnonymousScopes(const char *str) QCString replaceAnonymousScopes(const char *s,const char *replacement) { if (s==0) return QCString(); - static const std::regex marker("@[[:digit:]]+", std::regex::optimize); - std::string result = std::regex_replace(s,marker,replacement?replacement:"__anonymous__"); + static const reg::Ex marker(R"(@\d+)"); + std::string result = reg::replace(s,marker,replacement?replacement:"__anonymous__"); //printf("replaceAnonymousScopes('%s')='%s'\n",s.data(),result.data()); return result; } @@ -895,9 +895,9 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, size_t strLen = txtStr.length(); if (strLen==0) return; - static const std::regex regExp("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_~!\\\\.:$]*", std::regex::optimize); - std::sregex_iterator it( txtStr.begin(), txtStr.end(), regExp); - std::sregex_iterator end; + static const reg::Ex regExp(R"(\a[\w~!\\.:$]*)"); + reg::Iterator it(txtStr,regExp); + reg::Iterator end; //printf("linkifyText scope=%s fileScope=%s strtxt=%s strlen=%d external=%d\n", // scope?scope->name().data():"", @@ -1096,9 +1096,9 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, void writeMarkerList(OutputList &ol,const std::string &markerText,size_t numMarkers, std::function replaceFunc) { - static const std::regex marker("@([[:digit:]]+)", std::regex::optimize); - std::sregex_iterator it(markerText.begin(),markerText.end(),marker); - std::sregex_iterator end; + static const reg::Ex marker(R"(@(\d+))"); + reg::Iterator it(markerText,marker); + reg::Iterator end; size_t index=0; // now replace all markers in inheritLine with links to the classes for ( ; it!=end ; ++it) @@ -1107,7 +1107,7 @@ void writeMarkerList(OutputList &ol,const std::string &markerText,size_t numMark size_t newIndex = match.position(); size_t matchLen = match.length(); ol.parseText(markerText.substr(index,newIndex-index)); - unsigned long entryIndex = std::stoul(match[1]); + unsigned long entryIndex = std::stoul(match[1].str()); if (entryIndex<(unsigned long)numMarkers) { replaceFunc(entryIndex); @@ -1279,37 +1279,6 @@ int filterCRLF(char *buf,int len) return dest; // length of the valid part of the buf } -static std::string wildcard2regex(const std::string &pattern) -{ - std::string result="^"; // match start of input - char c; - const char *p = pattern.c_str(); - while ((c=*p++)) - { - switch(c) - { - case '*': result+=".*"; break; // '*' => '.*' - case '?': result+='.'; break; // '?' => '.' - case '.': case '+': case '\\': case '$': case '^': result+='\\'; result+=c; break; // escape - case '[': if (*p=='^') { result+="[^"; p++; } else result+=c; break; // don't escape ^ after [ - default: result+=c; break; // just copy - } - } - result+='$'; // match end of input - return result; -} - -static bool isMatchingWildcard(const std::string &input,const std::string &pattern, - bool caseSensitive=false) -{ - - std::regex::flag_type flags = std::regex::ECMAScript; - if (!caseSensitive) flags |= std::regex::icase; - std::string re_str = wildcard2regex(pattern); - std::regex rePattern(re_str,flags); - return std::regex_match(input,rePattern); -} - static QCString getFilterFromList(const char *name,const StringVector &filterList,bool &found) { found=FALSE; @@ -1321,7 +1290,14 @@ static QCString getFilterFromList(const char *name,const StringVector &filterLis if (i_equals!=-1) { QCString filterPattern = fs.left(i_equals); - if (isMatchingWildcard(name,filterPattern.str(),Portable::fileSystemIsCaseSensitive())) + QCString input = name; + if (!Portable::fileSystemIsCaseSensitive()) + { + filterPattern = filterPattern.lower(); + input = input.lower(); + } + reg::Ex re(filterPattern.str(),reg::Ex::Mode::Wildcard); + if (re.isValid() && reg::match(input.str(),re)) { // found a match! QCString filterName = fs.mid(i_equals+1); @@ -1906,10 +1882,10 @@ static QCString extractCanonicalType(const Definition *d,const FileDef *fs,QCStr // (i.e. type is not a template specialization) // then resolve any identifiers inside. { - static const std::regex re("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_]*", std::regex::optimize); std::string ts = templSpec.str(); - std::sregex_iterator it(ts.begin(),ts.end(),re); - std::sregex_iterator end; + static const reg::Ex re(R"(\a\w*)"); + reg::Iterator it(ts,re); + reg::Iterator end; size_t tp=0; // for each identifier template specifier @@ -4282,14 +4258,13 @@ QCString convertCharEntitiesToUTF8(const char *str) { if (str==0) return QCString(); - static const std::regex re("&[[:alpha:]\\x80-\\xFF][[:alnum:]\\x80-\\xFF]*;", std::regex::optimize); std::string s = str; - std::sregex_iterator it(s.begin(),s.end(),re); - std::sregex_iterator end; + static const reg::Ex re(R"(&\a\w*;)"); + reg::Iterator it(s,re); + reg::Iterator end; GrowBuf growBuf; size_t p,i=0,l; - //while ((p=entityPat.match(s,i,&l))!=-1) for (; it!=end ; ++it) { const auto &match = *it; @@ -4447,9 +4422,9 @@ void addMembersToMemberGroup(MemberList *ml, */ int extractClassNameFromType(const char *type,int &pos,QCString &name,QCString &templSpec,SrcLangExt lang) { - static std::regex re_norm("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_:]*"); - static std::regex re_fortran("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_:()=]*"); - static std::regex &re = re_norm; + static reg::Ex re_norm(R"(\a[\w:]*)"); + static reg::Ex re_fortran(R"(\a[\w:()=]*)"); + static const reg::Ex *re = &re_norm; name.resize(0); templSpec.resize(0); @@ -4462,17 +4437,17 @@ int extractClassNameFromType(const char *type,int &pos,QCString &name,QCString & if (type[pos]==',') return -1; if (QCString(type).left(4).lower()!="type") { - re = re_fortran; + re = &re_fortran; } } std::string s = type; - std::sregex_iterator it(s.begin()+pos,s.end(),re); - std::sregex_iterator end; + reg::Iterator it(s,*re,(int)pos); + reg::Iterator end; if (it!=end) { const auto &match = *it; - int i = pos+(int)match.position(); + int i = (int)match.position(); int l = (int)match.length(); int ts = i+l; int te = ts; @@ -4530,10 +4505,10 @@ QCString normalizeNonTemplateArgumentsInString( p++; QCString result = name.left(p); - static const std::regex re("[[:alpha:]\\x80-\\xFF_:][[:alnum:]\\x80-\\xFF_:]*", std::regex::optimize); std::string s = result.mid(p).str(); - std::sregex_iterator it(s.begin(),s.end(),re); - std::sregex_iterator end; + static const reg::Ex re(R"([\a:][\w:]*)"); + reg::Iterator it(s,re); + reg::Iterator end; size_t pi=0; // for each identifier in the template part (e.g. B -> T) for (; it!=end ; ++it) @@ -4594,9 +4569,9 @@ QCString substituteTemplateArgumentsInString( if (formalArgs.empty()) return name; std::string result; - static const std::regex re("[[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_:]*", std::regex::optimize); - std::sregex_iterator it(name.begin(),name.end(),re); - std::sregex_iterator end; + static const reg::Ex re(R"(\a[\w:]*)"); + reg::Iterator it(name,re); + reg::Iterator end; size_t p=0; for (; it!=end ; ++it) @@ -5414,9 +5389,9 @@ QCString stripPath(const char *s) bool containsWord(const char *str,const char *word) { if (str==0 || word==0) return false; - static const std::regex re("[[:alpha:]\\x80-\\xFF_]+", std::regex::optimize); + static const reg::Ex re(R"(\a+)"); std::string s = str; - for (std::sregex_iterator it(s.begin(),s.end(),re) ; it!=std::sregex_iterator() ; ++it) + for (reg::Iterator it(s,re) ; it!=reg::Iterator() ; ++it) { if (it->str()==word) return true; } @@ -5429,36 +5404,36 @@ bool containsWord(const char *str,const char *word) */ bool findAndRemoveWord(QCString &sentence,const char *word) { - static const std::regex re("[^[:alpha:]\\x80-\\xFF_]+", std::regex::optimize); + static reg::Ex re(R"(\s*(\<\a+\>)\s*)"); std::string s = sentence.str(); - std::sregex_token_iterator it(s.begin(),s.end(),re,{-1,0}); - std::sregex_token_iterator end; - - bool found=false; + reg::Iterator it(s,re); + reg::Iterator end; std::string result; - bool keepSpaces=false; // skip leading whitespace - for (;it!=end;it++) + bool found=false; + size_t p=0; + for ( ; it!=end ; ++it) { - std::string part = it->str(); - bool whiteSpaceOnly = std::all_of(part.begin(),part.end(), - [](const auto ch) { return std::isspace(ch); }); - bool matchingWord = part==word; - if (!matchingWord && (keepSpaces || !whiteSpaceOnly)) + const auto match = *it; + std::string part = match[1].str(); + if (part!=word) { - result+=part; - keepSpaces=!whiteSpaceOnly; // skip sequences of spaces + size_t i = match.position(); + size_t l = match.length(); + result+=s.substr(p,i-p); + result+=match.str(); + p=i+l; } - else if (matchingWord) + else { found=true; + size_t i = match[1].position(); + size_t l = match[1].length(); + result+=s.substr(p,i-p); + p=i+l; } } - - // trim trailing whitespace - result.erase(std::find_if(result.rbegin(), result.rend(), - [](const auto ch) { return !std::isspace(ch); }).base(), result.end()); - - sentence = result; + result+=s.substr(p); + sentence = QCString(result).simplifyWhiteSpace(); return found; } @@ -6029,11 +6004,11 @@ static QCString escapeCommas(const QCString &s) static QCString expandAliasRec(StringUnorderedSet &aliasesProcessed,const std::string &s,bool allowRecursion) { - //QCString result; std::string result; - std::regex re("[\\\\@]([[:alpha:]\\x80-\\xFF_][[:alnum:]\\x80-\\xFF_]*)"); - std::sregex_iterator re_it(s.begin(),s.end(),re); - std::sregex_iterator end; + static const reg::Ex re(R"([\\@](\a\w*))"); + reg::Iterator re_it(s,re); + reg::Iterator end; + int p = 0; for ( ; re_it!=end ; ++re_it) { @@ -6354,9 +6329,9 @@ bool readInputFile(const char *fileName,BufStr &inBuf,bool filter,bool isSourceC QCString filterTitle(const std::string &title) { std::string tf; - std::regex re("%([A-Z_a-z]+)"); - std::sregex_iterator it(title.begin(),title.end(),re); - std::sregex_iterator end; + static const reg::Ex re(R"(%[a-z_A-Z]+)"); + reg::Iterator it(title,re); + reg::Iterator end; size_t p = 0; for (; it!=end ; ++it) { @@ -6364,7 +6339,7 @@ QCString filterTitle(const std::string &title) size_t i = match.position(); size_t l = match.length(); if (i>p) tf+=title.substr(p,i-p); - tf+=match[1].str(); // skip % + tf+=match.str().substr(1); // skip % p=i+l; } tf+=title.substr(p); @@ -6399,9 +6374,15 @@ bool patternMatch(const QFileInfo &fi,const StringVector &patList) size_t i=pattern.find('='); if (i!=std::string::npos) pattern=pattern.substr(0,i); // strip of the extension specific filter name - found = isMatchingWildcard(fn,pattern,caseSenseNames) || - isMatchingWildcard(fp,pattern,caseSenseNames) || - isMatchingWildcard(afp,pattern,caseSenseNames); + if (!caseSenseNames) + { + pattern = QCString(pattern).lower().str(); + fn = QCString(fn).lower().str(); + fp = QCString(fn).lower().str(); + afp = QCString(fn).lower().str(); + } + reg::Ex re(pattern,reg::Ex::Mode::Wildcard); + found = re.isValid() && (reg::match(fn,re) || reg::match(fp,re) || reg::match(afp,re)); if (found) break; //printf("Matching '%s' against pattern '%s' found=%d\n", // fi->fileName().data(),pattern.data(),found); @@ -6486,9 +6467,9 @@ QCString replaceColorMarkers(const char *str) if (str==0) return QCString(); std::string result; std::string s=str; - static const std::regex re("##([0-9A-Fa-f][0-9A-Fa-f])", std::regex::optimize); - std::sregex_iterator it(s.begin(),s.end(),re); - std::sregex_iterator end; + static const reg::Ex re(R"(##[0-9A-Fa-f][0-9A-Fa-f])"); + reg::Iterator it(s,re); + reg::Iterator end; static int hue = Config_getInt(HTML_COLORSTYLE_HUE); static int sat = Config_getInt(HTML_COLORSTYLE_SAT); static int gamma = Config_getInt(HTML_COLORSTYLE_GAMMA); @@ -6500,7 +6481,7 @@ QCString replaceColorMarkers(const char *str) size_t i = match.position(); size_t l = match.length(); if (i>p) result+=s.substr(p,i-p); - std::string lumStr = match[1].str(); + std::string lumStr = match.str().substr(2); #define HEXTONUM(x) (((x)>='0' && (x)<='9') ? ((x)-'0') : \ ((x)>='a' && (x)<='f') ? ((x)-'a'+10) : \ ((x)>='A' && (x)<='F') ? ((x)-'A'+10) : 0) @@ -6974,10 +6955,10 @@ bool classVisibleInIndex(const ClassDef *cd) */ QCString extractDirection(QCString &docs) { - std::regex re("\\[([ inout,]+)\\]"); std::string s = docs.str(); - std::sregex_iterator it(s.begin(),s.end(),re); - std::sregex_iterator end; + static const reg::Ex re(R"(\[([ inout,]+)\])"); + reg::Iterator it(s,re); + reg::Iterator end; if (it!=end) { const auto &match = *it; @@ -7467,15 +7448,21 @@ StringVector split(const std::string &s,const std::string &delimiter) /// split input string \a s by regular expression delimiter \a delimiter. /// returns a vector of non-empty strings that are between the delimiters -StringVector split(const std::string &s,const std::regex &delimiter) +StringVector split(const std::string &s,const reg::Ex &delimiter) { StringVector result; - std::sregex_token_iterator iter(s.begin(), s.end(), delimiter, -1); - std::sregex_token_iterator end; + reg::Iterator iter(s, delimiter); + reg::Iterator end; + size_t p=0; for ( ; iter != end; ++iter) { - result.push_back(*iter); + const auto &match = *iter; + size_t i=match.position(); + size_t l=match.length(); + if (i>p) result.push_back(s.substr(p,i-p)); + p=i+l; } + if (p #include #include -#include #include #include "types.h" @@ -36,6 +35,7 @@ #include "containers.h" #include "namespacedef.h" #include "outputgen.h" +#include "regex.h" //-------------------------------------------------------------------- @@ -460,9 +460,9 @@ void writeExtraLatexPackages(FTextStream &t); void writeLatexSpecialFormulaChars(FTextStream &t); StringVector split(const std::string &s,const std::string &delimiter); -StringVector split(const std::string &s,const std::regex &delimiter); +StringVector split(const std::string &s,const reg::Ex &delimiter); int findIndex(const StringVector &sv,const std::string &s); -int findIndex(const std::string &s,const std::regex &re); +int findIndex(const std::string &s,const reg::Ex &re); bool recognizeFixedForm(const char* contents, FortranFormat format); FortranFormat convertFileNameFortranParserCode(QCString fn); diff --git a/src/vhdlcode.l b/src/vhdlcode.l index 3e754c7..c363a23 100644 --- a/src/vhdlcode.l +++ b/src/vhdlcode.l @@ -30,7 +30,6 @@ #include #include -#include /* * includes @@ -55,6 +54,7 @@ #include "classdef.h" #include "filedef.h" #include "tooltip.h" +#include "regex.h" #define YY_NO_INPUT 1 #define YY_NO_UNISTD_H 1 @@ -359,7 +359,7 @@ XILINX "INST"|"NET"|"PIN"|"BLKNM"|"BUFG"|"COLLAPSE"|"CPLD"|"COMPGRP"|"CONFI tt=tt.lower(); VhdlDocGen::deleteAllChars(tt,';'); tt.stripWhiteSpace(); - static const std::regex regg("[[:space:]]+", std::regex::optimize); + static const reg::Ex regg(R"(\s+)"); // any number of whitespace auto ql = split(tt.str(),regg); int index=findIndex(ql,"if")+1; index+=findIndex(ql,"case")+1; @@ -959,7 +959,7 @@ static bool checkVhdlString(yyscan_t yyscanner,QCString &name) if (name.at(0)=='"' && name.at(len-1)=='"' && len > 2) { std::string inside = name.str().substr(1,len-2); - static const std::regex regg("[[:space:]]+", std::regex::optimize); + static const reg::Ex regg(R"(\s+)"); // any number of whitespace auto qrl=split(inside,regg); if (VhdlDocGen::isNumber(qrl[0])) { diff --git a/src/vhdldocgen.cpp b/src/vhdldocgen.cpp index 3bd510f..86110a8 100644 --- a/src/vhdldocgen.cpp +++ b/src/vhdldocgen.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -62,7 +61,7 @@ #include "plantuml.h" #include "vhdljjparser.h" #include "VhdlParser.h" -//#include "vhdlcode.h" +#include "regex.h" #include "plantuml.h" //#define DEBUGFLOW #define theTranslator_vhdlType theTranslator->trVhdlType @@ -1034,7 +1033,7 @@ void VhdlDocGen::parseFuncProto(const char* text,QCString& name,QCString& ret,bo QCString VhdlDocGen::getIndexWord(const char* c,int index) { - static const std::regex reg("[[:space:]:|]",std::regex::optimize); + static const reg::Ex reg(R"([\s|])"); auto ql=split(c,reg); if ((size_t)index < ql.size()) @@ -1122,7 +1121,7 @@ QCString VhdlDocGen::getProcessNumber() void VhdlDocGen::writeFormatString(const QCString& s,OutputList&ol,const MemberDef* mdef) { - static const std::regex reg("[\\[\\]\\.\\/\\<\\>\\:\\s\\,\\;\\'\\+\\-\\*\\|\\&\\=\\(\\)\"]",std::regex::optimize); + static const reg::Ex reg(R"([\[\]./<>:\s,;'+*|&=()\"-])"); QCString qcs = s; qcs+=QCString(" ");// parsing the last sign QCString find=qcs; @@ -1191,8 +1190,8 @@ void VhdlDocGen::writeFormatString(const QCString& s,OutputList&ol,const MemberD */ bool VhdlDocGen::isNumber(const std::string& s) { - static const std::regex regg("[0-9][0-9eEfFbBcCdDaA_.#-+?xXzZ]*",std::regex::optimize); - return std::regex_match(s,regg); + static const reg::Ex regg(R"([0-9][0-9eEfFbBcCdDaA_.#+?xXzZ-]*)"); + return reg::match(s,regg); }// isNumber @@ -2298,7 +2297,7 @@ void VhdlDocGen::parseUCF(const char* input, Entry* entity,QCString fileName,b } else { - static const std::regex ee("[[:space:]=]",std::regex::optimize); + static const reg::Ex ee(R"([\s=])"); int in=findIndex(temp.str(),ee); QCString ff=temp.left(in); temp.stripPrefix(ff.data()); @@ -2324,7 +2323,7 @@ static void initUCF(Entry* root,const char* type,QCString & qcs,int line,QCStr VhdlDocGen::deleteAllChars(qcs,';'); qcs=qcs.stripWhiteSpace(); - static const std::regex reg("[[:space:]=]",std::regex::optimize); + static const reg::Ex reg(R"([\s=])"); int i = findIndex(qcs.str(),reg); if (i<0) return; if (i==0) @@ -2406,7 +2405,7 @@ QCString VhdlDocGen::parseForConfig(QCString & entity,QCString & arch) QCString label; if (!entity.contains(":")) return ""; - static const std::regex exp("[:()[[:space:]]",std::regex::optimize); + static const reg::Ex exp(R"([:()\s])"); auto ql=split(entity.str(),exp); if (ql.size()<2) { @@ -2436,7 +2435,7 @@ QCString VhdlDocGen::parseForConfig(QCString & entity,QCString & arch) QCString VhdlDocGen::parseForBinding(QCString & entity,QCString & arch) { - static const std::regex exp("[()[[:space:]]",std::regex::optimize); + static const reg::Ex exp(R"([()\s])"); auto ql = split(entity.str(),exp); @@ -2704,14 +2703,14 @@ void VhdlDocGen::addBaseClass(ClassDef* cd,ClassDef *ent) bcd.usedName.append("(2)"); return; } - static const std::regex reg("[[:digit:]]+",std::regex::optimize); + static const reg::Ex reg(R"(\d+)"); QCString s=n.left(i); QCString r=n.right(n.length()-i); std::string t=r.str(); VhdlDocGen::deleteAllChars(r,')'); VhdlDocGen::deleteAllChars(r,'('); r.setNum(r.toInt()+1); - std::regex_replace(t, reg, r.str()); + reg::replace(t, reg, r.str()); s.append(t.c_str()); bcd.usedName=s; bcd.templSpecifiers=t; @@ -2952,8 +2951,8 @@ void FlowChart::printNode(const FlowChart& flo) { t=flo.text.str(); } - static const std::regex ep("[[:space:]]",std::regex::optimize); - t = std::regex_replace(t,ep,std::string("")); + static const reg::Ex ep(R"(\s)"); + t = reg::replace(t,ep,std::string()); if (t.empty()) { t=" "; diff --git a/src/vhdljjparser.cpp b/src/vhdljjparser.cpp index 3852045..9eaf167 100644 --- a/src/vhdljjparser.cpp +++ b/src/vhdljjparser.cpp @@ -10,7 +10,6 @@ * */ -#include #include #include @@ -34,6 +33,7 @@ #include "markdown.h" #include "VhdlParserTokenManager.h" #include "VhdlParserErrorHandler.hpp" +#include "regex.h" using namespace vhdl::parser; @@ -272,28 +272,28 @@ void VHDLOutlineParser::handleFlowComment(const char* doc) int VHDLOutlineParser::checkInlineCode(QCString &doc) { - static const std::regex csRe("[\\\\@]code", std::regex::optimize); - static const std::regex cendRe("[[:space:]]*[\\\\@]endcode", std::regex::optimize); - static const std::regex cbriefRe("[\\\\@]brief", std::regex::optimize); + static const reg::Ex csRe(R"([\\@]code)"); + static const reg::Ex cendRe(R"(\s*[\\@]endcode)"); + static const reg::Ex cbriefRe(R"([\\@]brief)"); // helper to simulate behavior of QString.find(const QRegExp &re,int pos) - auto findRe = [](const QCString &str,const std::regex &re,int pos=0) -> int + auto findRe = [](const QCString &str,const reg::Ex &re,int pos=0) -> int { if ((int)str.length() QCString + auto replaceRe = [](const QCString &str,const reg::Ex &re,const QCString &replacement) -> QCString { - return std::regex_replace(str.str(), re, replacement.str()); + return reg::replace(str.str(), re, replacement.str()); }; int index = findRe(doc,csRe); -- cgit v0.12 From 655b5ecb86ec961293bbe2eea9996191210afabf Mon Sep 17 00:00:00 2001 From: albert-github Date: Wed, 3 Mar 2021 09:53:00 +0100 Subject: Spelling correction Spelling corrections as found by Fossies --- src/regex.cpp | 2 +- src/regex.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/regex.cpp b/src/regex.cpp index e3aa057..62678b7 100644 --- a/src/regex.cpp +++ b/src/regex.cpp @@ -159,7 +159,7 @@ class Ex::Private #endif bool matchAt(size_t tokenPos,const std::string &str,Match &match,size_t pos,int level) const; - /** Flag indicating the expression was succesfully compiled */ + /** Flag indicating the expression was successfully compiled */ bool error = false; /** The token stream representing the compiled regular expression. */ diff --git a/src/regex.h b/src/regex.h index e4bd399..bedc052 100644 --- a/src/regex.h +++ b/src/regex.h @@ -82,7 +82,7 @@ class Ex * * @note that capture ranges cannot be nested, and `*`, `+`, and `?` do not work on * capture ranges. e.g. `(abd)?` is not valid. If multiple capture ranges are - * specified then some character has to be inbetween them, + * specified then some character has to be in between them, * e.g. this does not work `(.*)(a.*)`, but this does `(.*)a(.*)`. * * In Wildcard mode `*` is used to match any sequence of zero or more characters. -- cgit v0.12