Doxygen
Loading...
Searching...
No Matches
util.h File Reference

A bunch of utility functions. More...

#include <memory>
#include <unordered_map>
#include <algorithm>
#include <functional>
#include <fstream>
#include <variant>
#include <string_view>
#include <ctype.h>
#include "types.h"
#include "docparser.h"
#include "containers.h"
#include "outputgen.h"
#include "regex.h"
#include "conceptdef.h"
#include "construct.h"
#include "htmlentity.h"
Include dependency graph for util.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  GetDefInput
struct  GetDefResult
struct  SelectionBlock
struct  SelectionMarkerInfo
struct  KeywordSubstitution

Typedefs

using SelectionBlockList = std::vector<SelectionBlock>
using KeywordSubstitutionList = std::vector<KeywordSubstitution>

Functions

DString getLanguageSpecificSeparator (SrcLangExt lang, bool classScope=false)
DString fileToString (const DString &name, bool filter=false, bool isSourceCode=false)
bool readInputFile (const DString &fileName, std::string &contents, bool filter=true, bool isSourceCode=false)
 read a file name fileName and optionally filter and transcode it
DString writeInlineGraph (const DString &baseName, const DString &extension, const DString &content, bool &exists)
void cleanupInlineGraphs ()
GetDefResult getDefs (const GetDefInput &input)
DString getFileFilter (const DString &name, bool isSourceCode)
bool resolveRef (const DString &scName, const DString &name, bool inSeeBlock, const Definition **resContext, const MemberDef **resMember, SrcLangExt lang, bool lookForSpecializations=true, const FileDef *currentFile=nullptr, bool checkScope=false)
bool resolveLink (const DString &scName, const DString &lr, bool inSeeBlock, const Definition **resContext, DString &resAnchor, SrcLangExt lang, const DString &prefix=DString())
bool matchArguments2 (const Definition *srcScope, const FileDef *srcFileScope, const DString &srcReturnType, const ArgumentList *srcAl, const Definition *dstScope, const FileDef *dstFileScope, const DString &dstReturnType, const ArgumentList *dstAl, bool checkCV, SrcLangExt lang)
void mergeArguments (ArgumentList &srcAl, ArgumentList &dstAl, bool forceNameOverwrite=false)
bool matchTemplateArguments (const ArgumentList &srcAl, const ArgumentList &dstAl)
DString normalizeNonTemplateArgumentsInString (const DString &name, const Definition *context, const ArgumentList &formalArgs)
DString substituteTemplateArgumentsInString (const DString &name, const ArgumentList &formalArgs, const ArgumentList *actualArgs)
DString selectBlocks (const DString &s, const SelectionBlockList &blockList, const SelectionMarkerInfo &markerInfo)
 remove disabled blocks and all block markers from s and return the result as a string
void checkBlocks (const DString &s, const DString fileName, const SelectionMarkerInfo &markerInfo)
DString findExampleFilePath (const DString &file, bool &ambig)
void writeExamples (OutputList &ol, const ExampleList &el)
DString removeRedundantWhiteSpace (const DString &s)
DString inlineArgListToDoc (const ArgumentList &al)
DString inlineTemplateArgListToDoc (const ArgumentList &al)
DString argListToString (const ArgumentList &al, bool useCanonicalType=false, bool showDefVals=true)
DString tempArgListToString (const ArgumentList &al, SrcLangExt lang, bool includeDefaults=true)
DString stripAnonymousNamespaceScope (const DString &s)
DString stripFromPath (const DString &path)
DString stripFromIncludePath (const DString &path)
bool rightScopeMatch (const DString &scope, const DString &name)
bool leftScopeMatch (const DString &scope, const DString &name)
DString substituteKeywords (const DString &file, const DString &s, const KeywordSubstitutionList &keywords)
int getPrefixIndex (const DString &name)
DString removeAnonymousScopes (const DString &s)
DString replaceAnonymousScopes (const DString &s, const DString &replacement=DString())
DString convertNameToFile (const DString &name, bool allowDots=false, bool allowUnderscore=false)
DString insertTemplateSpecifierInScope (const DString &scope, const DString &templ)
DString stripScope (const DString &name)
DString convertToId (const DString &s)
DString convertToHtml (const DString &s, bool keepEntities=true)
DString convertToXML (const DString &s, bool keepEntities=false, bool citeEntry=false)
DString convertToJSString (const DString &s, bool keepEntities=false, bool singleQuotes=false)
void addMembersToMemberGroup (MemberList *ml, MemberGroupList *pMemberGroups, const Definition *context)
void extractNamespaceName (const DString &scopeName, DString &className, DString &namespaceName, bool allowEmptyClass=false)
int extractClassNameFromType (const DString &type, int &pos, DString &name, DString &templSpec, SrcLangExt=SrcLangExt::Unknown)
DString stripTemplateSpecifiersFromScope (const DString &fullName, bool parentOnly=true, DString *lastScopeStripped=nullptr, DString scopeName=DString(), bool allowArtificial=true)
DString resolveTypeDef (const Definition *d, const DString &name, const Definition **typedefContext=nullptr)
DString mergeScopes (const DString &leftScope, const DString &rightScope)
int getScopeFragment (const DString &s, int p, int *l)
void addRefItem (const RefItemVector &sli, const DString &key, const DString &prefix, const DString &name, const DString &title, const DString &args, const Definition *scope)
PageDefaddRelatedPage (const DString &name, const DString &ptitle, const DString &doc, const DString &fileName, int docLine, int startLine, const RefItemVector &sli=RefItemVector(), GroupDef *gd=nullptr, const TagInfo *tagInfo=nullptr, bool xref=false, SrcLangExt lang=SrcLangExt::Unknown)
bool useCaseSenseNames ()
 Returns true if the names of the symbols can be case sensitive.
DString escapeCharsInString (const DString &name, bool allowDots, bool allowUnderscore=false)
DString unescapeCharsInString (const DString &s)
void addGroupListToTitle (OutputList &ol, const Definition *d)
DString linkToText (SrcLangExt lang, const DString &link, bool ignoreDots)
bool checkExtension (const DString &fName, const DString &ext)
void addHtmlExtensionIfMissing (DString &fName)
DString stripExtensionGeneral (const DString &fName, const DString &ext)
DString stripExtension (const DString &fName)
DString makeBaseName (const DString &name, const DString &ext)
int computeQualifiedIndex (const DString &name)
 Return the index of the last :: in the string name that is still before the first <.
void addDirPrefix (DString &fileName)
DString relativePathToRoot (const DString &name)
DString determineAbsoluteIncludeName (const DString &curFile, const DString &incFileName)
void createSubDirs (const Dir &d)
void clearSubDirs (const Dir &d)
DString removeLongPathMarker (const DString &path)
DString stripPath (const DString &s)
bool findAndRemoveWord (DString &s, const char *word)
 removes occurrences of whole word from sentence, while keeps internal spaces and reducing multiple sequences of spaces.
DString stripLeadingAndTrailingEmptyLines (const DString &s, int &docLine)
 Special version of DString::stripWhiteSpace() that only strips completely blank lines.
bool updateLanguageMapping (const DString &extension, const DString &parser)
SrcLangExt getLanguageFromFileName (const DString &fileName, SrcLangExt defLang=SrcLangExt::Cpp)
SrcLangExt getLanguageFromCodeLang (DString &fileName)
 Routine to handle the language attribute of the \code command.
DString getFileNameExtension (const DString &fn)
void initDefaultExtensionMapping ()
void addCodeOnlyMappings ()
bool checkIfTypedef (const Definition *scope, const FileDef *fileScope, const DString &n)
DString parseCommentAsText (const Definition *scope, const MemberDef *member, const DString &doc, const DString &fileName, int lineNr)
DString parseCommentAsHtml (const Definition *scope, const MemberDef *member, const DString &doc, const DString &fileName, int lineNr)
bool transcodeCharacterStringToUTF8 (std::string &input, const char *inputEncoding)
DString recodeString (const DString &str, const char *fromEncoding, const char *toEncoding)
void writeTypeConstraints (OutputList &ol, const Definition *d, const ArgumentList &al)
void stackTrace ()
DString filterTitle (const DString &title)
bool patternMatch (const FileInfo &fi, const StringVector &patList)
DString externalLinkTarget (const bool parent=false)
DString createHtmlUrl (const DString &relPath, const DString &ref, bool href, bool islocalFile, const DString &targetFileName, const DString &anchor)
DString externalRef (const DString &relPath, const DString &ref, bool href)
void writeMarkerList (OutputList &ol, const std::string &markerText, size_t numMarkers, std::function< void(size_t)> replaceFunc)
DString writeMarkerList (const std::string &markerText, size_t numMarkers, std::function< DString(size_t)> replaceFunc)
DString replaceColorMarkers (const DString &str)
 Replaces any markers of the form ##AA in input string str by new markers of the form #AABBCC, where #AABBCC represents a valid color, based on the intensity represented by hex number AA and the current HTML_COLORSTYLE_* settings.
bool copyFile (const DString &src, const DString &dest)
 Copies the contents of file with name src to the newly created file with name dest.
int lineBlock (const DString &text, const DString &marker)
 Returns the line number of the line following the line with the marker.
bool isURL (const DString &url)
 Checks whether the given url starts with a supported protocol.
DString correctURL (const DString &url, const DString &relPath)
 Corrects URL url according to the relative path relPath.
DString processMarkup (const DString &s)
bool protectionLevelVisible (Protection prot)
DString stripIndentation (const DString &s, bool skipFirstLine=false)
void stripIndentationVerbatim (DString &doc, size_t indentationLevel, bool skipFirstLine=true)
DString getDotImageExtension ()
bool fileVisibleInIndex (const FileDef *fd, bool &genSourceFile)
void convertProtectionLevel (MemberListType inListType, Protection inProt, MemberListType *outListType1, MemberListType *outListType2)
 Computes for a given list type inListType, which are the the corresponding list type(s) in the base class that are to be added to this list.
bool mainPageHasTitle ()
bool openOutputFile (const DString &outFile, std::ofstream &f)
bool recognizeFixedForm (const DString &contents, FortranFormat format)
FortranFormat convertFileNameFortranParserCode (DString fn)
DString getEncoding (const FileInfo &fi)
DString detab (const DString &s, size_t &refIndent)
DString getProjectId ()
DString projectLogoFile ()
DString projectLogoSize ()
DString showDate (const DString &fmt)
void mergeMemberOverrideOptions (MemberDefMutable *md1, MemberDefMutable *md2)
size_t updateColumnCount (const char *s, size_t col)
DString mangleCSharpGenericName (const DString &name)
DString demangleCSharpGenericName (const DString &name, const DString &templArgs)
DString extractBeginRawStringDelimiter (const char *rawStart)
DString extractEndRawStringDelimiter (const char *rawEnd)

Detailed Description

A bunch of utility functions.

Definition in file util.h.

Typedef Documentation

◆ KeywordSubstitutionList

Definition at line 249 of file util.h.

◆ SelectionBlockList

using SelectionBlockList = std::vector<SelectionBlock>

Definition at line 199 of file util.h.

Function Documentation

◆ addCodeOnlyMappings()

void addCodeOnlyMappings ( )

Definition at line 4530 of file util.cpp.

4531{
4532 updateLanguageMapping(".xml", "xml");
4533 updateLanguageMapping(".sql", "sql");
4534}
bool updateLanguageMapping(const DString &extension, const DString &language)
Definition util.cpp:4431

References addCodeOnlyMappings(), and updateLanguageMapping().

Referenced by addCodeOnlyMappings(), addDirPrefix(), and generateOutput().

◆ addDirPrefix()

◆ addGroupListToTitle()

void addGroupListToTitle ( OutputList & ol,
const Definition * d )

◆ addHtmlExtensionIfMissing()

void addHtmlExtensionIfMissing ( DString & fName)

Definition at line 4260 of file util.cpp.

4261{
4262 if (fName.empty()) return;
4263 size_t i_fs = fName.rfind('/');
4264 size_t i_bs = fName.rfind('\\');
4265 size_t p = i_fs!=DString::npos && i_bs!=DString::npos ? std::max(i_fs, i_bs) :
4266 i_fs!=DString::npos ? i_fs : i_bs!=DString::npos ? i_bs : 0;
4267 size_t i = fName.find('.',p); // search for . after path part
4268 if (i==DString::npos)
4269 {
4271 }
4272}
A String class for use with Doxygen wrapping std::string and adding some additional functionality off...
Definition dstring.h:89
size_t rfind(char c, size_t pos=npos) const
Definition dstring.h:249
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:153
static constexpr size_t npos
value used to indicate 'not found' or 'to the end of the string', matching std::string::npos
Definition dstring.h:183
size_t find(char c, size_t pos=0) const
Definition dstring.h:244
static DString htmlFileExtension
Definition doxygen.h:122

References addHtmlExtensionIfMissing(), DString::empty(), DString::find(), Doxygen::htmlFileExtension, DString::npos, and DString::rfind().

Referenced by HtmlCodeGenerator::_writeCodeLink(), Crawlmap::addContentsItem(), DocSets::addContentsItem(), EclipseHelp::addContentsItem(), HtmlHelp::addContentsItem(), Qhp::addContentsItem(), addHtmlExtensionIfMissing(), Crawlmap::addIndexFile(), Sitemap::addIndexFile(), common_attributes(), convertMapFile(), dumpSymbol(), field2URL(), FTVHelp::Private::generateTree(), Crawlmap::initialize(), makeFileName(), makeFileName(), makeURL(), DefinitionImpl::navigationPathAsString(), node2URL(), HtmlDocVisitor::operator()(), replaceRef(), SearchIndexExternal::setCurrentDoc(), HtmlGenerator::startFile(), HtmlGenerator::startIndexItem(), HtmlDocVisitor::startLink(), HtmlGenerator::startTextLink(), LayoutNavEntry::url(), DefinitionImpl::writeDocAnchorsToTagFile(), HtmlGenerator::writeInheritedSectionTitle(), writeJavasScriptSearchDataPage(), writeMapArea(), HtmlGenerator::writeObjectLink(), ClassDefImpl::writeQuickMemberLinks(), FileDefImpl::writeQuickMemberLinks(), GroupDefImpl::writeQuickMemberLinks(), NamespaceDefImpl::writeQuickMemberLinks(), HtmlGenerator::writeSplitBarAsString(), HtmlGenerator::writeStartAnnoItem(), HtmlGenerator::writeSummaryLink(), ClassDefImpl::writeTagFile(), ConceptDefImpl::writeTagFile(), DirDefImpl::writeTagFile(), FileDefImpl::writeTagFile(), GroupDefImpl::writeTagFile(), MemberDefImpl::writeTagFile(), ModuleDefImpl::writeTagFile(), NamespaceDefImpl::writeTagFile(), PageDefImpl::writeTagFile(), RequirementManager::writeTagFile(), VhdlDocGen::writeTagFile(), DocSets::writeToken(), HtmlCodeGenerator::writeTooltip(), and DotNode::writeUrl().

◆ addMembersToMemberGroup()

void addMembersToMemberGroup ( MemberList * ml,
MemberGroupList * pMemberGroups,
const Definition * context )

Definition at line 3442 of file util.cpp.

3445{
3446 ASSERT(context!=nullptr);
3447 //printf("addMemberToMemberGroup() context=%s\n",qPrint(context->name()));
3448 if (ml==nullptr) return;
3449
3450 struct MoveMemberInfo
3451 {
3452 MoveMemberInfo(MemberDef *md,MemberGroup *mg,const RefItemVector &rv)
3453 : memberDef(md), memberGroup(mg), sli(rv) {}
3454 MemberDef *memberDef;
3455 MemberGroup *memberGroup;
3456 RefItemVector sli;
3457 };
3458 std::vector<MoveMemberInfo> movedMembers;
3459
3460 for (const auto &md : *ml)
3461 {
3462 if (md->isEnumerate()) // insert enum value of this enum into groups
3463 {
3464 for (const auto &fmd : md->enumFieldList())
3465 {
3466 int groupId=fmd->getMemberGroupId();
3467 if (groupId!=-1)
3468 {
3469 auto it = Doxygen::memberGroupInfoMap.find(groupId);
3471 {
3472 const auto &info = it->second;
3473 auto mg_it = std::find_if(pMemberGroups->begin(),
3474 pMemberGroups->end(),
3475 [&groupId](const auto &g)
3476 { return g->groupId()==groupId; }
3477 );
3478 MemberGroup *mg_ptr = nullptr;
3479 if (mg_it==pMemberGroups->end())
3480 {
3481 auto mg = std::make_unique<MemberGroup>(
3482 context,
3483 groupId,
3484 info->header,
3485 info->doc,
3486 info->docFile,
3487 info->docLine,
3488 ml->container());
3489 mg_ptr = mg.get();
3490 pMemberGroups->push_back(std::move(mg));
3491 }
3492 else
3493 {
3494 mg_ptr = (*mg_it).get();
3495 }
3496 mg_ptr->insertMember(fmd); // insert in member group
3498 if (fmdm)
3499 {
3500 fmdm->setMemberGroup(mg_ptr);
3501 }
3502 }
3503 }
3504 }
3505 }
3506 int groupId=md->getMemberGroupId();
3507 if (groupId!=-1)
3508 {
3509 auto it = Doxygen::memberGroupInfoMap.find(groupId);
3511 {
3512 const auto &info = it->second;
3513 auto mg_it = std::find_if(pMemberGroups->begin(),
3514 pMemberGroups->end(),
3515 [&groupId](const auto &g)
3516 { return g->groupId()==groupId; }
3517 );
3518 MemberGroup *mg_ptr = nullptr;
3519 if (mg_it==pMemberGroups->end())
3520 {
3521 auto mg = std::make_unique<MemberGroup>(
3522 context,
3523 groupId,
3524 info->header,
3525 info->doc,
3526 info->docFile,
3527 info->docLine,
3528 ml->container());
3529 mg_ptr = mg.get();
3530 pMemberGroups->push_back(std::move(mg));
3531 }
3532 else
3533 {
3534 mg_ptr = (*mg_it).get();
3535 }
3536 movedMembers.emplace_back(md,mg_ptr,info->m_sli);
3537 }
3538 }
3539 }
3540
3541 // move the members to their group
3542 for (const auto &mmi : movedMembers)
3543 {
3544 ml->remove(mmi.memberDef); // remove from member list
3545 mmi.memberGroup->insertMember(mmi.memberDef->resolveAlias()); // insert in member group
3546 mmi.memberGroup->setRefItems(mmi.sli);
3547 MemberDefMutable *rmdm = toMemberDefMutable(mmi.memberDef);
3548 if (rmdm)
3549 {
3550 rmdm->setMemberGroup(mmi.memberGroup);
3551 }
3552 }
3553}
static MemberGroupInfoMap memberGroupInfoMap
Definition doxygen.h:118
virtual void setMemberGroup(MemberGroup *grp)=0
A class representing a group of members.
Definition membergroup.h:44
void insertMember(MemberDef *md)
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:175
#define ASSERT(x)
Definition dstring.h:29
MemberDefMutable * toMemberDefMutable(Definition *d)
std::vector< RefItem * > RefItemVector
Definition reflist.h:133

References addMembersToMemberGroup(), ASSERT, MemberList::container(), Definition::docFile(), end(), MemberGroup::insertMember(), Doxygen::memberGroupInfoMap, MemberVector::remove(), MemberDef::setMemberGroup(), and toMemberDefMutable().

Referenced by addMembersToMemberGroup().

◆ addRefItem()

void addRefItem ( const RefItemVector & sli,
const DString & key,
const DString & prefix,
const DString & name,
const DString & title,
const DString & args,
const Definition * scope )

Definition at line 4163 of file util.cpp.

4166{
4167 //printf("addRefItem(sli=%d,key=%s,prefix=%s,name=%s,title=%s,args=%s)\n",(int)sli.size(),key,prefix,name,title,args);
4168 if (!key.empty() && key[0]!='@') // check for @ to skip anonymous stuff (see bug427012)
4169 {
4170 for (RefItem *item : sli)
4171 {
4172 item->setPrefix(prefix);
4173 item->setScope(scope);
4174 item->setName(name);
4175 item->setTitle(title);
4176 item->setArgs(args);
4177 item->setGroup(key);
4178 }
4179 }
4180}
constexpr auto prefix
Definition anchor.cpp:44
This struct represents an item in the list of references.
Definition reflist.h:32

References addRefItem(), DString::empty(), and prefix.

Referenced by MemberDefImpl::addListReference(), ClassDefImpl::addListReferences(), ConceptDefImpl::addListReferences(), DirDefImpl::addListReferences(), FileDefImpl::addListReferences(), GroupDefImpl::addListReferences(), ModuleDefImpl::addListReferences(), NamespaceDefImpl::addListReferences(), PageDefImpl::addListReferences(), addRefItem(), and buildPageList().

◆ addRelatedPage()

PageDef * addRelatedPage ( const DString & name,
const DString & ptitle,
const DString & doc,
const DString & fileName,
int docLine,
int startLine,
const RefItemVector & sli = RefItemVector(),
GroupDef * gd = nullptr,
const TagInfo * tagInfo = nullptr,
bool xref = false,
SrcLangExt lang = SrcLangExt::Unknown )

Definition at line 4033 of file util.cpp.

4044{
4045 PageDef *pd=nullptr;
4046 //printf("addRelatedPage(name=%s gd=%p)\n",qPrint(name),gd);
4047 DString title=ptitle.stripWhiteSpace();
4048 bool newPage = true;
4049 if ((pd=Doxygen::pageLinkedMap->find(name)) && !pd->isReference())
4050 {
4051 if (!xref && !title.empty() && pd->title()!=pd->name() && pd->title()!=title)
4052 {
4053 warn(fileName,startLine,"multiple use of page label '{}' with different titles, (other occurrence: {}, line: {})",
4054 name,pd->docFile(),pd->getStartBodyLine());
4055 }
4056 if (!title.empty() && pd->title()==pd->name()) // pd has no real title yet
4057 {
4058 pd->setTitle(title);
4060 if (si)
4061 {
4062 si->setTitle(title);
4063 }
4064 }
4065 // append documentation block to the page.
4066 pd->setDocumentation(doc,fileName,docLine);
4067 //printf("Adding page docs '%s' pi=%p name=%s\n",qPrint(doc),pd,name);
4068 // append (x)refitems to the page.
4069 pd->setRefItems(sli);
4070 newPage = false;
4071 }
4072
4073 if (newPage) // new page
4074 {
4075 DString baseName=name;
4076 if (baseName.endsWith(".tex"))
4077 baseName=baseName.left(baseName.length()-4);
4079 baseName=baseName.left(baseName.length()-Doxygen::htmlFileExtension.length());
4080
4081 //printf("Appending page '%s'\n",qPrint(baseName));
4082 if (pd) // replace existing page
4083 {
4084 pd->setDocumentation(doc,fileName,docLine);
4085 pd->setFileName(::convertNameToFile(baseName,false,true));
4086 pd->setShowLineNo(false);
4087 pd->setNestingLevel(0);
4088 pd->setPageScope(nullptr);
4089 pd->setTitle(title);
4090 pd->setReference(DString());
4091 }
4092 else // newPage
4093 {
4094 pd = Doxygen::pageLinkedMap->add(baseName,
4095 createPageDef(fileName,docLine,baseName,doc,title));
4096 }
4097 pd->setBodySegment(startLine,startLine,-1);
4098
4099 pd->setRefItems(sli);
4100 pd->setLanguage(lang);
4101
4102 if (tagInfo)
4103 {
4104 pd->setReference(tagInfo->tagName);
4105 pd->setFileName(tagInfo->fileName);
4106 }
4107
4108 if (gd) gd->addPage(pd);
4109
4110 if (pd->hasTitle())
4111 {
4112 //outputList->writeTitle(pi->name,pi->title);
4113
4114 // a page name is a label as well!
4115 DString file;
4116 DString orgFile;
4117 int line = -1;
4118 if (gd)
4119 {
4120 file=gd->getOutputFileBase();
4121 orgFile=gd->getOutputFileBase();
4122 }
4123 else
4124 {
4125 file=pd->getOutputFileBase();
4126 orgFile=pd->docFile();
4127 line = pd->getStartBodyLine();
4128 }
4129 const SectionInfo *si = SectionManager::instance().find(pd->name());
4130 if (si)
4131 {
4132 if (!si->ref().empty()) // we are from a tag file
4133 {
4135 file,-1,pd->title(),SectionType::Page,0,pd->getReference());
4136 }
4137 else if (si->lineNr() != -1)
4138 {
4139 warn(orgFile,line,"multiple use of section label '{}', (first occurrence: {}, line {})",pd->name(),si->fileName(),si->lineNr());
4140 }
4141 else
4142 {
4143 warn(orgFile,line,"multiple use of section label '{}', (first occurrence: {})",pd->name(),si->fileName());
4144 }
4145 }
4146 else
4147 {
4149 file,-1,pd->title(),SectionType::Page,0,pd->getReference());
4150 //printf("si->label='%s' si->definition=%s si->fileName='%s'\n",
4151 // qPrint(si->label),si->definition?si->definition->name().data():"<none>",
4152 // qPrint(si->fileName));
4153 //printf(" SectionInfo: sec=%p sec->fileName=%s\n",si,qPrint(si->fileName));
4154 //printf("Adding section key=%s si->fileName=%s\n",qPrint(pageName),qPrint(si->fileName));
4155 }
4156 }
4157 }
4158 return pd;
4159}
DString()=default
DString right(size_t len) const
Definition dstring.h:316
DString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition dstring.h:342
DString left(size_t len) const
Definition dstring.h:311
bool endsWith(const char *s) const
Definition dstring.h:606
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition dstring.h:156
virtual const DString & name() const =0
virtual DString getReference() const =0
virtual DString docFile() const =0
virtual int getStartBodyLine() const =0
virtual bool isReference() const =0
virtual DString getOutputFileBase() const =0
virtual void setBodySegment(int defLine, int bls, int ble)=0
virtual void setReference(const DString &r)=0
virtual void setDocumentation(const DString &d, const DString &docFile, int docLine, bool stripWhiteSpace=true)=0
virtual void setLanguage(SrcLangExt lang)=0
virtual void setRefItems(const RefItemVector &sli)=0
static PageLinkedMap * pageLinkedMap
Definition doxygen.h:99
virtual void addPage(PageDef *def)=0
T * add(const char *k, Args &&... args)
Definition linkedmap.h:90
const T * find(const std::string &key) const
Definition linkedmap.h:47
A model of a page symbol.
Definition pagedef.h:26
virtual void setTitle(const DString &title)=0
virtual void setNestingLevel(int)=0
virtual bool hasTitle() const =0
virtual void setFileName(const DString &name)=0
virtual void setShowLineNo(bool)=0
virtual DString title() const =0
virtual void setPageScope(Definition *)=0
class that provide information about a section.
Definition section.h:58
void setTitle(const DString &t)
Definition section.h:84
DString fileName() const
Definition section.h:74
int lineNr() const
Definition section.h:73
DString ref() const
Definition section.h:72
SectionInfo * replace(const DString &label, const DString &fileName, int lineNr, const DString &title, SectionType type, int level, const DString &ref=DString())
Definition section.h:157
SectionInfo * add(const SectionInfo &si)
Definition section.h:139
static SectionManager & instance()
returns a reference to the singleton
Definition section.h:179
static constexpr int Page
Definition section.h:31
#define warn(file, line, fmt,...)
Definition message.h:97
std::unique_ptr< PageDef > createPageDef(const DString &f, int l, const DString &n, const DString &d, const DString &t)
Definition pagedef.cpp:84
DString tagName
Definition entry.h:105
DString fileName
Definition entry.h:106
DString convertNameToFile(const DString &name, bool allowDots, bool allowUnderscore)
Definition util.cpp:2930

References LinkedMap< T, Hash, KeyEqual, Map >::add(), SectionManager::add(), GroupDef::addPage(), addRelatedPage(), convertNameToFile(), createPageDef(), Definition::docFile(), DString::DString(), DString::empty(), DString::endsWith(), SectionInfo::fileName(), TagInfo::fileName, LinkedMap< T, Hash, KeyEqual, Map >::find(), Definition::getOutputFileBase(), Definition::getReference(), Definition::getStartBodyLine(), PageDef::hasTitle(), Doxygen::htmlFileExtension, SectionManager::instance(), Definition::isReference(), DString::left(), DString::length(), SectionInfo::lineNr(), Definition::name(), SectionType::Page, Doxygen::pageLinkedMap, SectionInfo::ref(), SectionManager::replace(), DString::right(), DefinitionMutable::setBodySegment(), DefinitionMutable::setDocumentation(), PageDef::setFileName(), DefinitionMutable::setLanguage(), PageDef::setNestingLevel(), PageDef::setPageScope(), DefinitionMutable::setReference(), DefinitionMutable::setRefItems(), PageDef::setShowLineNo(), PageDef::setTitle(), SectionInfo::setTitle(), DString::stripWhiteSpace(), TagInfo::tagName, PageDef::title(), and warn.

Referenced by addRelatedPage(), RequirementManager::addRequirement(), CitationManager::generatePage(), and RefList::generatePage().

◆ argListToString()

DString argListToString ( const ArgumentList & al,
bool useCanonicalType = false,
bool showDefVals = true )

Definition at line 891 of file util.cpp.

892{
893 DString result;
894 if (!al.hasParameters()) return result;
895 result+="(";
896 for (auto it = al.begin() ; it!=al.end() ;)
897 {
898 Argument a = *it;
899 DString type1 = useCanonicalType && !a.canType.empty() ? a.canType : a.type;
900 DString type2;
901 if (size_t i=type1.find(")("); i!=DString::npos) // hack to deal with function pointers
902 {
903 type2=type1.mid(i);
904 type1=type1.left(i);
905 }
906 if (!a.attrib.empty())
907 {
908 result+=a.attrib+" ";
909 }
910 if (!a.name.empty() || !a.array.empty())
911 {
912 result+= type1+" "+a.name+type2+a.array;
913 }
914 else
915 {
916 result+= type1+type2;
917 }
918 if (!a.defval.empty() && showDefVals)
919 {
920 result+="="+a.defval;
921 }
922 ++it;
923 if (it!=al.end()) result+=", ";
924 }
925 result+=")";
926 if (al.constSpecifier()) result+=" const";
927 if (al.volatileSpecifier()) result+=" volatile";
928 if (al.refQualifier()==RefQualifierType::LValue) result+=" &";
929 else if (al.refQualifier()==RefQualifierType::RValue) result+=" &&";
930 if (!al.trailingReturnType().empty()) result+=al.trailingReturnType();
931 if (al.pureSpecifier()) result+=" =0";
932 return removeRedundantWhiteSpace(result);
933}
RefQualifierType refQualifier() const
Definition arguments.h:116
bool pureSpecifier() const
Definition arguments.h:113
iterator end()
Definition arguments.h:94
bool hasParameters() const
Definition arguments.h:76
DString trailingReturnType() const
Definition arguments.h:114
bool constSpecifier() const
Definition arguments.h:111
iterator begin()
Definition arguments.h:93
bool volatileSpecifier() const
Definition arguments.h:112
DString mid(size_t index, size_t len=npos) const
Definition dstring.h:323
This class contains the information about the argument of a function or template.
Definition arguments.h:27
DString attrib
Definition arguments.h:41
DString defval
Definition arguments.h:46
DString array
Definition arguments.h:45
DString name
Definition arguments.h:44
DString type
Definition arguments.h:42
DString canType
Definition arguments.h:43
DString removeRedundantWhiteSpace(const DString &s)
Definition util.cpp:458

References argListToString(), Argument::array, Argument::attrib, ArgumentList::begin(), Argument::canType, ArgumentList::constSpecifier(), Argument::defval, DString::empty(), ArgumentList::end(), DString::find(), ArgumentList::hasParameters(), DString::left(), LValue, DString::mid(), Argument::name, DString::npos, ArgumentList::pureSpecifier(), ArgumentList::refQualifier(), removeRedundantWhiteSpace(), RValue, ArgumentList::trailingReturnType(), Argument::type, and ArgumentList::volatileSpecifier().

Referenced by addMemberFunction(), argListToString(), DocParser::checkArgumentName(), DocParser::checkUnOrMultipleDocumentedParams(), findFriends(), findGlobalMember(), findMember(), SymbolResolver::Private::getResolvedSymbol(), matchArguments2(), matchTemplateArguments(), mergeArguments(), substituteTemplateArgumentsInString(), and ClassDefImpl::title().

◆ checkBlocks()

void checkBlocks ( const DString & s,
const DString fileName,
const SelectionMarkerInfo & markerInfo )

Definition at line 5863 of file util.cpp.

5864{
5865 if (s.empty()) return;
5866
5867 const char *p = s.data();
5868 char c = 0;
5869 while ((c=*p))
5870 {
5871 if (c==markerInfo.markerChar) // potential start of marker
5872 {
5873 if (dstrncmp(p,markerInfo.beginStr,markerInfo.beginLen)==0) // start of begin marker
5874 {
5875 size_t len = markerInfo.beginLen;
5876 bool negate = *(p+len)=='!';
5877 if (negate) len++;
5878 p += len;
5879 DString marker;
5880 while (*p)
5881 {
5882 if (markerInfo.closeLen==0 && *p=='\n') // matching end of line
5883 {
5884 warn(fileName,-1,"Remaining begin replacement with marker '{}'",marker);
5885 break;
5886 }
5887 else if (markerInfo.closeLen!= 0 && dstrncmp(p,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
5888 {
5889 p += markerInfo.closeLen;
5890 warn(fileName,-1,"Remaining begin replacement with marker '{}'",marker);
5891 break;
5892 }
5893 marker += *p;
5894 p++;
5895 }
5896 }
5897 else if (dstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // start of end marker
5898 {
5899 size_t len = markerInfo.endLen;
5900 bool negate = *(p+len)=='!';
5901 if (negate) len++;
5902 p += len;
5903 DString marker;
5904 while (*p)
5905 {
5906 if (markerInfo.closeLen==0 && *p=='\n') // matching end of line
5907 {
5908 warn(fileName,-1,"Remaining end replacement with marker '{}'",marker);
5909 break;
5910 }
5911 else if (markerInfo.closeLen!= 0 && dstrncmp(p,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
5912 {
5913 p += markerInfo.closeLen;
5914 warn(fileName,-1,"Remaining end replacement with marker '{}'",marker);
5915 break;
5916 }
5917 marker += *p;
5918 p++;
5919 }
5920 }
5921 }
5922 p++;
5923 }
5924}
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition dstring.h:162
int dstrncmp(const char *str1, const char *str2, size_t len)
Definition dstring.h:61
size_t beginLen
Definition util.h:205
const char * closeStr
Definition util.h:208
const char * beginStr
Definition util.h:204
size_t closeLen
Definition util.h:209
const char * endStr
Definition util.h:206

References SelectionMarkerInfo::beginLen, SelectionMarkerInfo::beginStr, checkBlocks(), SelectionMarkerInfo::closeLen, SelectionMarkerInfo::closeStr, DString::data(), dstrncmp(), DString::empty(), SelectionMarkerInfo::endLen, SelectionMarkerInfo::endStr, SelectionMarkerInfo::markerChar, and warn.

Referenced by checkBlocks(), HtmlGenerator::init(), and LatexGenerator::init().

◆ checkExtension()

bool checkExtension ( const DString & fName,
const DString & ext )

Definition at line 4255 of file util.cpp.

4256{
4257 return fName.right(ext.length())==ext;
4258}

References checkExtension(), DString::length(), and DString::right().

Referenced by checkExtension(), copyLatexStyleSheet(), and extraLatexStyleSheet().

◆ checkIfTypedef()

bool checkIfTypedef ( const Definition * scope,
const FileDef * fileScope,
const DString & n )

Returns true iff the given name string appears to be a typedef in scope.

Definition at line 4639 of file util.cpp.

4640{
4641 MemberDef *bestMatch = getMemberFromSymbol(scope,fileScope,n);
4642
4643 if (bestMatch && bestMatch->isTypedef())
4644 return true; // closest matching symbol is a typedef
4645 else
4646 return false;
4647}
A model of a class/file/namespace member symbol.
Definition memberdef.h:48
virtual bool isTypedef() const =0
static MemberDef * getMemberFromSymbol(const Definition *scope, const FileDef *fileScope, const DString &n)
Definition util.cpp:4587

References checkIfTypedef(), getMemberFromSymbol(), and MemberDef::isTypedef().

Referenced by addDirPrefix(), checkIfTypedef(), and isVarWithConstructor().

◆ cleanupInlineGraphs()

void cleanupInlineGraphs ( )

Deletes all graph files written with writeInlineGraph()

Definition at line 6180 of file util.cpp.

6181{
6182 if (Config_getBool(DOT_CLEANUP))
6183 {
6184 for (const auto& fileName: writeFileContents_set)
6185 {
6186 Dir().remove(qPrint(fileName));
6187 }
6188 }
6189}
Dir()
Definition dir.cpp:189
#define Config_getBool(name)
Definition config.h:33
const char * qPrint(const char *s)
Definition dstring.h:772
static StringUnorderedSet writeFileContents_set
Definition util.cpp:6153

References cleanupInlineGraphs(), Config_getBool, Dir::Dir(), qPrint(), and writeFileContents_set.

Referenced by cleanupInlineGraphs(), and generateOutput().

◆ clearSubDirs()

void clearSubDirs ( const Dir & d)

Definition at line 3063 of file util.cpp.

3064{
3065 if (Config_getBool(CREATE_SUBDIRS))
3066 {
3067 // remove empty subdirectories
3068 int createSubdirsLevelPow2 = 1 << Config_getInt(CREATE_SUBDIRS_LEVEL);
3069 for (int l1=0;l1<16;l1++)
3070 {
3071 DString subdir;
3072 subdir.sprintf("d%x",l1);
3073 for (int l2=0; l2 < createSubdirsLevelPow2; l2++)
3074 {
3075 DString subsubdir;
3076 subsubdir.sprintf("d%x/d%02x",l1,l2);
3077 if (d.exists(subsubdir.str()) && d.empty(subsubdir.str()))
3078 {
3079 d.rmdir(subsubdir.str());
3080 }
3081 }
3082 if (d.exists(subdir.str()) && d.empty(subdir.str()))
3083 {
3084 d.rmdir(subdir.str());
3085 }
3086 }
3087 }
3088}
DString & sprintf(const char *format,...)
Definition dstring.cpp:29
const std::string & str() const
Definition dstring.h:634
bool empty(const std::string &subdir) const
Definition dir.cpp:263
bool rmdir(const std::string &path, bool acceptsAbsPath=true) const
Definition dir.cpp:309
bool exists() const
Definition dir.cpp:257
#define Config_getInt(name)
Definition config.h:34

References clearSubDirs(), Config_getBool, Config_getInt, Dir::empty(), Dir::exists(), Dir::rmdir(), DString::sprintf(), and DString::str().

Referenced by addDirPrefix(), DocbookGenerator::cleanup(), HtmlGenerator::cleanup(), LatexGenerator::cleanup(), ManGenerator::cleanup(), RTFGenerator::cleanup(), clearSubDirs(), and generateXML().

◆ computeQualifiedIndex()

int computeQualifiedIndex ( const DString & name)

Return the index of the last :: in the string name that is still before the first <.

Definition at line 6027 of file util.cpp.

6028{
6029 int l = static_cast<int>(name.length());
6030 int lastSepPos = -1;
6031 const char *p = name.data();
6032 int i=l-2;
6033 int sharpCount=0;
6034 // --- begin optimized version of ts=name.findRev(">::");
6035 int ts = -1;
6036 while (i>=0)
6037 {
6038 if (p[i]=='>')
6039 {
6040 if (sharpCount==0 && p[i+1]==':' && p[i+2]==':')
6041 {
6042 ts=i;
6043 break;
6044 }
6045 sharpCount++;
6046 }
6047 else if (p[i]=='<')
6048 {
6049 sharpCount--;
6050 }
6051 i--;
6052 }
6053 // --- end optimized version
6054 if (ts==-1) ts=0; else p+=++ts;
6055 for (i=ts;i<l-1;i++)
6056 {
6057 char c=*p++;
6058 if (c==':' && *p==':') lastSepPos=i;
6059 if (c=='<') break;
6060 }
6061 return lastSepPos;
6062}

References computeQualifiedIndex(), DString::data(), and DString::length().

Referenced by addToMap(), addVariable(), buildFunctionList(), buildTypedefList(), computeQualifiedIndex(), getMemberFromSymbol(), SymbolResolver::Private::getResolvedSymbolRec(), and SymbolResolver::Private::getResolvedTypeRec().

◆ convertFileNameFortranParserCode()

FortranFormat convertFileNameFortranParserCode ( DString fn)

Definition at line 5737 of file util.cpp.

5738{
5739 DString ext = getFileNameExtension(fn);
5740 DString parserName = Doxygen::parserManager->getParserName(ext);
5741
5742 if (parserName == "fortranfixed") return FortranFormat::Fixed;
5743 else if (parserName == "fortranfree") return FortranFormat::Free;
5744
5746}
static ParserManager * parserManager
Definition doxygen.h:129
DString getParserName(const DString &extension)
Gets the name of the parser associated with given extension.
Definition parserintf.h:269
DString getFileNameExtension(const DString &fn)
Definition util.cpp:4578

References convertFileNameFortranParserCode(), Fixed, Free, getFileNameExtension(), ParserManager::getParserName(), Doxygen::parserManager, and Unknown.

Referenced by convertCppComments(), convertFileNameFortranParserCode(), processMarkup(), and setFileName().

◆ convertNameToFile()

DString convertNameToFile ( const DString & name,
bool allowDots,
bool allowUnderscore )

This function determines the file name on disk of an item given its name, which could be a class name with template arguments, so special characters need to be escaped.

Definition at line 2930 of file util.cpp.

2931{
2932 if (name.empty()) return name;
2933 bool shortNames = Config_getBool(SHORT_NAMES);
2934 bool createSubdirs = Config_getBool(CREATE_SUBDIRS);
2935 DString result;
2936 if (shortNames) // use short names only
2937 {
2938 std::lock_guard<std::mutex> lock(g_usedNamesMutex);
2939 auto kv = g_usedNames.find(name.str());
2940 uint32_t num=0;
2941 if (kv!=g_usedNames.end())
2942 {
2943 num = kv->second;
2944 }
2945 else
2946 {
2947 num = g_usedNamesCount;
2948 g_usedNames.emplace(name.str(),g_usedNamesCount++);
2949 }
2950 result.sprintf("a%05d",num);
2951 }
2952 else // long names
2953 {
2954 result=escapeCharsInString(name,allowDots,allowUnderscore);
2955 size_t resultLen = result.length();
2956 if (resultLen>=128) // prevent names that cannot be created!
2957 {
2958 // third algorithm based on MD5 hash
2959 result=result.left(128-32)+md5str(result.view());
2960 }
2961 }
2962 if (createSubdirs)
2963 {
2964 int l1Dir=0,l2Dir=0;
2965 int createSubdirsLevel = Config_getInt(CREATE_SUBDIRS_LEVEL);
2966 int createSubdirsBitmaskL2 = (1<<createSubdirsLevel)-1;
2967
2968 // compute md5 hash to determine sub directory to use
2969 auto md5_sig = md5hash(result.view());
2970 l1Dir = md5_sig[14] & 0xf;
2971 l2Dir = md5_sig[15] & createSubdirsBitmaskL2;
2972
2973 result.prepend(DString().sprintf("d%x/d%02x/",l1Dir,l2Dir));
2974 }
2975 //printf("*** convertNameToFile(%s)->%s\n",qPrint(name),qPrint(result));
2976 return result;
2977}
std::string_view view() const
Definition dstring.h:167
DString & prepend(const char *s)
Definition dstring.h:504
DString md5str(const std::string_view &str)
Definition md5hash.h:33
std::array< uint8_t, 16 > md5hash(const std::string_view &str)
Definition md5hash.h:26
static int g_usedNamesCount
Definition util.cpp:2922
DString escapeCharsInString(const DString &name, bool allowDots, bool allowUnderscore)
Definition util.cpp:2755
static std::mutex g_usedNamesMutex
Definition util.cpp:2921
static std::unordered_map< std::string, int > g_usedNames
Definition util.cpp:2920

References Config_getBool, Config_getInt, convertNameToFile(), DString::DString(), DString::empty(), escapeCharsInString(), g_usedNames, g_usedNamesCount, g_usedNamesMutex, DString::left(), DString::length(), md5hash(), md5str(), DString::prepend(), DString::sprintf(), DString::str(), and DString::view().

Referenced by addRelatedPage(), buildExampleList(), ClassDefImpl::ClassDefImpl(), convertNameToFile(), ClassDefImpl::deepCopy(), DocAnchor::DocAnchor(), DocCite::DocCite(), ModuleDefImpl::getOutputFileBase(), DocParser::handleAHref(), PageDefImpl::PageDefImpl(), CCodeParser::parseCode(), FortranCodeParser::parseCode(), VHDLCodeParser::parseCode(), RefList::RefList(), FileDefImpl::setDiskNameLocal(), NamespaceDefImpl::setFileNameLocal(), and xmlRequirementId().

◆ convertProtectionLevel()

void convertProtectionLevel ( MemberListType inListType,
Protection inProt,
MemberListType * outListType1,
MemberListType * outListType2 )

Computes for a given list type inListType, which are the the corresponding list type(s) in the base class that are to be added to this list.

So for public inheritance, the mapping is 1-1, so outListType1=inListType Private members are to be hidden completely.

For protected inheritance, both protected and public members of the base class should be joined in the protected member section.

For private inheritance, both protected and public members of the base class should be joined in the private member section.

Definition at line 5570 of file util.cpp.

5576{
5577 bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
5578
5579 // default representing 1-1 mapping
5580 *outListType1=inListType;
5581 *outListType2=MemberListType::Invalid();
5582
5583 if (inProt==Protection::Public)
5584 {
5585 if (inListType.isPrivate())
5586 {
5587 *outListType1=MemberListType::Invalid();
5588 }
5589 }
5590 else if (inProt==Protection::Protected)
5591 {
5592 if (inListType.isPrivate() || inListType.isPublic())
5593 {
5594 *outListType1=MemberListType::Invalid();
5595 }
5596 else if (inListType.isProtected())
5597 {
5598 *outListType2=inListType.toPublic();
5599 }
5600 }
5601 else if (inProt==Protection::Private)
5602 {
5603 if (inListType.isPublic() || inListType.isProtected())
5604 {
5605 *outListType1=MemberListType::Invalid();
5606 }
5607 else if (inListType.isPrivate())
5608 {
5609 if (extractPrivate)
5610 {
5611 *outListType1=inListType.toPublic();
5612 *outListType2=inListType.toProtected();
5613 }
5614 else
5615 {
5616 *outListType1=MemberListType::Invalid();
5617 }
5618 }
5619 }
5620
5621 //printf("convertProtectionLevel(type=%s prot=%d): %s,%s\n",
5622 // qPrint(inListType.to_string()),inProt,qPrint(outListType1->to_string()),qPrint(outListType2->to_string()));
5623}
constexpr bool isPrivate() const noexcept
Definition types.h:382
constexpr MemberListType toPublic() const noexcept
Definition types.h:426
static constexpr MemberListType Invalid() noexcept
Definition types.h:371
constexpr MemberListType toProtected() const noexcept
Definition types.h:438
constexpr bool isProtected() const noexcept
Definition types.h:380
ML_TYPES constexpr bool isPublic() const noexcept
Definition types.h:378

References Config_getBool, convertProtectionLevel(), MemberListType::Invalid(), MemberListType::isPrivate(), MemberListType::isProtected(), MemberListType::isPublic(), MemberListType::toProtected(), and MemberListType::toPublic().

Referenced by convertProtectionLevel(), ClassDefImpl::countInheritedDecMembers(), processMarkup(), and ClassDefImpl::writeInheritedMemberDeclarations().

◆ convertToHtml()

DString convertToHtml ( const DString & s,
bool keepEntities )

Converts a string to a HTML-encoded string

Definition at line 3358 of file util.cpp.

3359{
3360 if (s.empty()) return s;
3361 DString result;
3362 result.reserve(s.length()+32);
3363 const char *p=s.data();
3364 char c = 0;
3365 while ((c=*p++))
3366 {
3367 switch (c)
3368 {
3369 case '<': result+="&lt;"; break;
3370 case '>': result+="&gt;"; break;
3371 case '&': if (keepEntities)
3372 {
3373 const char *e=p;
3374 char ce = 0;
3375 while ((ce=*e++))
3376 {
3377 if (ce==';' || (!(isId(ce) || ce=='#'))) break;
3378 }
3379 if (ce==';') // found end of an entity
3380 {
3381 // copy entry verbatim
3382 result+=c;
3383 while (p<e) result+=*p++;
3384 }
3385 else
3386 {
3387 result+="&amp;";
3388 }
3389 }
3390 else
3391 {
3392 result+="&amp;";
3393 }
3394 break;
3395 case '\'': result+="&#39;"; break;
3396 case '"': result+="&quot;"; break;
3397 default:
3398 {
3399 uint8_t uc = static_cast<uint8_t>(c);
3400 if (uc<32 && !isspace(c))
3401 {
3402 result+="&#x24";
3403 result+=hex[uc>>4];
3404 result+=hex[uc&0xF];
3405 result+=';';
3406 }
3407 else
3408 {
3409 result+=c;
3410 }
3411 }
3412 break;
3413 }
3414 }
3415 return result;
3416}
void reserve(size_t size)
Reserve space for size bytes without changing the string contents.
Definition dstring.h:222
bool isId(int c)
Returns true if c is a valid character for an identifier.
Definition dstring.h:884
static const char * hex

References convertToHtml(), DString::data(), DString::empty(), hex, isId(), DString::length(), and DString::reserve().

Referenced by HtmlCodeGenerator::_writeCodeLink(), HtmlHelp::addContentsItem(), addMembersToIndex(), convertToHtml(), convertToHtmlAndTruncate(), FTVHelp::Private::generateLink(), DefinitionImpl::navigationPathAsString(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlGenerator::startFile(), HtmlDocVisitor::startLink(), substituteHtmlKeywords(), writeClassTree(), writeClassTreeForList(), writeClassTreeToOutput(), HtmlHelpIndex::writeFields(), HtmlGenerator::writeInheritedSectionTitle(), HtmlGenerator::writeLogoAsString(), writeMapArea(), HtmlGenerator::writePageFooter(), ClassDefImpl::writeQuickMemberLinks(), FileDefImpl::writeQuickMemberLinks(), GroupDefImpl::writeQuickMemberLinks(), NamespaceDefImpl::writeQuickMemberLinks(), and HtmlGenerator::writeSearchPage().

◆ convertToId()

DString convertToId ( const DString & s)

Converts a string to a HTML id string

Definition at line 3269 of file util.cpp.

3270{
3271 if (s.empty()) return s;
3272 DString result;
3273 result.reserve(s.length()+8);
3274 const char *p = s.data();
3275 char c = 0;
3276 bool first = true;
3277 while ((c=*p++))
3278 {
3279 char encChar[4];
3280 if ((c>='0' && c<='9') || (c>='a' && c<='z') || (c>='A' && c<='Z') || c=='-')
3281 { // any permissive character except _
3282 if (first && c>='0' && c<='9') result+='a'; // don't start with a digit
3283 result+=c;
3284 }
3285 else
3286 {
3287 encChar[0]='_';
3288 encChar[1]=hex[static_cast<unsigned char>(c)>>4];
3289 encChar[2]=hex[static_cast<unsigned char>(c)&0xF];
3290 encChar[3]=0;
3291 result+=encChar;
3292 }
3293 first=false;
3294 }
3295 return result;
3296}

References convertToId(), DString::data(), DString::empty(), hex, DString::length(), and DString::reserve().

Referenced by convertToId(), HtmlGenerator::endClassDiagram(), HtmlGenerator::endMemberTemplateParams(), renderQuickLinksAsJs(), HtmlGenerator::startGroupHeader(), HtmlGenerator::startMemberItem(), writeMemberList(), writeQuickMemberIndex(), ClassDefImpl::writeSummaryLinks(), and VhdlDocGen::writeVHDLDeclarations().

◆ convertToJSString()

DString convertToJSString ( const DString & s,
bool keepEntities = false,
bool singleQuotes = false )

Definition at line 3418 of file util.cpp.

3419{
3420 if (s.empty()) return s;
3421 DString result;
3422 result.reserve(s.length()+32);
3423 const char *p=s.data();
3424 char c = 0;
3425 while ((c=*p++))
3426 {
3427 switch (c)
3428 {
3429 case '"': if (!singleQuotes) result+="\\\""; else result+=c;
3430 break;
3431 case '\'': if (singleQuotes) result+="\\\'"; else result+=c;
3432 break;
3433 case '\\': if (*p=='u' && *(p+1)=='{') result+="\\"; // keep \u{..} unicode escapes
3434 else result+="\\\\";
3435 break;
3436 default: result+=c; break;
3437 }
3438 }
3439 return keepEntities ? result : HtmlEntityMapper::instance().convertCharEntitiesToUTF8(result);
3440}
static HtmlEntityMapper & instance()
Returns the one and only instance of the HTML entity mapper.
DString convertCharEntitiesToUTF8(const DString &s) const

References HtmlEntityMapper::convertCharEntitiesToUTF8(), convertToJSString(), DString::data(), DString::empty(), HtmlEntityMapper::instance(), DString::length(), and DString::reserve().

Referenced by convertToJSString(), generateJSLink(), generateJSNavTree(), renderQuickLinksAsJs(), writeJavascriptSearchData(), and writeJavasScriptSearchDataPage().

◆ convertToXML()

DString convertToXML ( const DString & s,
bool keepEntities,
const bool citeEntry )

Converts a string to an XML-encoded string

Definition at line 3299 of file util.cpp.

3300{
3301 if (s.empty()) return s;
3302 DString result;
3303 result.reserve(s.length()+32);
3304 const char *p = s.data();
3305 char c = 0;
3306 while ((c=*p++))
3307 {
3308 switch (c)
3309 {
3310 case '<': result+="&lt;"; break;
3311 case '>': result+="&gt;"; break;
3312 case '&': if (keepEntities)
3313 {
3314 const char *e=p;
3315 char ce = 0;
3316 while ((ce=*e++))
3317 {
3318 if (ce==';' || (!(isId(ce) || ce=='#'))) break;
3319 }
3320 if (ce==';') // found end of an entity
3321 {
3322 // copy entry verbatim
3323 result+=c;
3324 while (p<e) result+=*p++;
3325 }
3326 else
3327 {
3328 result+="&amp;";
3329 }
3330 }
3331 else if (citeEntry)
3332 {
3334 result,
3335 p-1,
3336 [](HtmlEntityMapper::SymType symType) { return HtmlEntityMapper::instance().xml(symType); },
3337 "&amp;");
3338 }
3339 else
3340 {
3341 result+="&amp;";
3342 }
3343 break;
3344 case '\'': result+="&apos;"; break;
3345 case '"': result+="&quot;"; break;
3346 case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
3347 case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18:
3348 case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26:
3349 case 27: case 28: case 29: case 30: case 31:
3350 break; // skip invalid XML characters (see http://www.w3.org/TR/2000/REC-xml-20001006#NT-Char)
3351 default: result+=c; break;
3352 }
3353 }
3354 return result;
3355}
const char * writeHtmlEntity(T &result, const char *s, HtmlEntityMapperFunc &&mapper, const char *fallback)
Definition htmlentity.h:127
const char * xml(SymType symb) const
Access routine to the XML code of the HTML entity.

References convertToXML(), DString::data(), DString::empty(), HtmlEntityMapper::instance(), isId(), DString::length(), DString::reserve(), HtmlEntityMapper::writeHtmlEntity(), and HtmlEntityMapper::xml().

Referenced by DocSets::addContentsItem(), EclipseHelp::addContentsItem(), Qhp::addFile(), Sitemap::addIndexFile(), Qhp::addIndexItem(), convertToXML(), XmlDocVisitor::filter(), generateXMLForClass(), generateXMLForConcept(), generateXMLForDir(), generateXMLForFile(), generateXMLForGroup(), generateXMLForMember(), generateXMLForModule(), generateXMLForNamespace(), generateXMLForPage(), generateXMLForRequirement(), generateXMLForRequirements(), generateXMLSection(), DotDirDeps::getImgAltText(), EclipseHelp::initialize(), Qhp::initialize(), XmlDocVisitor::operator()(), XmlDocVisitor::operator()(), HtmlAttribList::toString(), QhpSectionTree::traverse(), visitPreStart(), SearchIndexExternal::write(), FileDefImpl::writeClassesToTagFile(), NamespaceDefImpl::writeClassesToTagFile(), NamespaceDefImpl::writeConceptsToTagFile(), DefinitionImpl::writeDocAnchorsToTagFile(), DotNode::writeDocbook(), DotGraph::writeGraphHeader(), writeInnerClasses(), writeInnerConcepts(), writeInnerDirs(), writeInnerFiles(), writeInnerGroups(), writeInnerModules(), writeInnerNamespaces(), writeInnerPages(), writeJavascriptSearchData(), writeJavasScriptSearchDataPage(), DotNode::writeLabel(), writeListOfAllMembers(), writeMapArea(), writeMemberReference(), writeRequirementRefs(), ClassDefImpl::writeTagFile(), ConceptDefImpl::writeTagFile(), DirDefImpl::writeTagFile(), FileDefImpl::writeTagFile(), GroupDefImpl::writeTagFile(), MemberDefImpl::writeTagFile(), ModuleDefImpl::writeTagFile(), NamespaceDefImpl::writeTagFile(), PageDefImpl::writeTagFile(), RequirementManager::writeTagFile(), VhdlDocGen::writeTagFile(), writeTemplateArgumentList(), DocSets::writeToken(), DotNode::writeXML(), writeXMLLink(), and writeXMLString().

◆ copyFile()

◆ correctURL()

DString correctURL ( const DString & url,
const DString & relPath )

Corrects URL url according to the relative path relPath.

Returns the corrected URL. For absolute URLs no correction will be done.

Definition at line 5242 of file util.cpp.

5243{
5244 DString result = url;
5245 if (!relPath.empty() && !isURL(url))
5246 {
5247 result.prepend(relPath);
5248 }
5249 return result;
5250}
bool isURL(const DString &url)
Checks whether the given url starts with a supported protocol.
Definition util.cpp:5229

References correctURL(), DString::empty(), isURL(), and DString::prepend().

Referenced by correctURL(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), XmlDocVisitor::operator()(), recodeString(), and startQuickIndexItem().

◆ createHtmlUrl()

DString createHtmlUrl ( const DString & relPath,
const DString & ref,
bool href,
bool islocalFile,
const DString & targetFileName,
const DString & anchor )

Definition at line 5060 of file util.cpp.

5066{
5067 DString url;
5068 if (!ref.empty())
5069 {
5070 url = externalRef(relPath,ref,href);
5071 }
5072 if (!targetFileName.empty())
5073 {
5074 DString fn = targetFileName;
5075 if (ref.empty())
5076 {
5077 if (!anchor.empty() && isLocalFile)
5078 {
5079 fn=""; // omit file name for local links
5080 }
5081 else
5082 {
5083 url = relPath;
5084 }
5085 }
5086 url+=fn;
5087 }
5088 if (!anchor.empty())
5089 {
5090 if (!url.endsWith("=")) url+="#";
5091 url+=anchor;
5092 }
5093 //printf("createHtmlUrl(relPath=%s,local=%d,target=%s,anchor=%s)=%s\n",qPrint(relPath),isLocalFile,qPrint(targetFileName),qPrint(anchor),qPrint(url));
5094 return url;
5095}
DString externalRef(const DString &relPath, const DString &ref, bool href)
Definition util.cpp:5097

References createHtmlUrl(), DString::empty(), DString::endsWith(), and externalRef().

Referenced by HtmlCodeGenerator::_writeCodeLink(), createHtmlUrl(), RequirementManager::generatePage(), recodeString(), HtmlDocVisitor::startLink(), HtmlGenerator::startTextLink(), HtmlGenerator::writeObjectLink(), and HtmlCodeGenerator::writeTooltip().

◆ createSubDirs()

void createSubDirs ( const Dir & d)

Definition at line 3036 of file util.cpp.

3037{
3038 if (Config_getBool(CREATE_SUBDIRS))
3039 {
3040 // create up to 4096 subdirectories
3041 int createSubdirsLevelPow2 = 1 << Config_getInt(CREATE_SUBDIRS_LEVEL);
3042 for (int l1=0; l1<16; l1++)
3043 {
3044 DString subdir;
3045 subdir.sprintf("d%x",l1);
3046 if (!d.exists(subdir.str()) && !d.mkdir(subdir.str()))
3047 {
3048 term("Failed to create output directory '{}'\n",subdir);
3049 }
3050 for (int l2=0; l2<createSubdirsLevelPow2; l2++)
3051 {
3052 DString subsubdir;
3053 subsubdir.sprintf("d%x/d%02x",l1,l2);
3054 if (!d.exists(subsubdir.str()) && !d.mkdir(subsubdir.str()))
3055 {
3056 term("Failed to create output directory '{}'\n",subsubdir);
3057 }
3058 }
3059 }
3060 }
3061}
bool mkdir(const std::string &path, bool acceptsAbsPath=true) const
Definition dir.cpp:295
#define term(fmt,...)
Definition message.h:137

References Config_getBool, Config_getInt, createSubDirs(), Dir::exists(), Dir::mkdir(), DString::sprintf(), DString::str(), and term.

Referenced by addDirPrefix(), createSubDirs(), generateXML(), DocbookGenerator::init(), HtmlGenerator::init(), LatexGenerator::init(), ManGenerator::init(), RTFGenerator::init(), ClassDefImpl::writeQuickMemberLinks(), FileDefImpl::writeQuickMemberLinks(), GroupDefImpl::writeQuickMemberLinks(), and NamespaceDefImpl::writeQuickMemberLinks().

◆ demangleCSharpGenericName()

DString demangleCSharpGenericName ( const DString & name,
const DString & templArgs )

Definition at line 6125 of file util.cpp.

6126{
6127 DString result=name;
6128 if (result.endsWith("-g"))
6129 {
6130 size_t idx = result.find('-');
6131 result = result.left(idx)+templArgs;
6132 }
6133 return result;
6134}

References demangleCSharpGenericName(), DString::endsWith(), DString::find(), and DString::left().

Referenced by ClassDefImpl::className(), demangleCSharpGenericName(), and processMarkup().

◆ detab()

DString detab ( const DString & s,
size_t & refIndent )

Definition at line 5928 of file util.cpp.

5929{
5930 int tabSize = Config_getInt(TAB_SIZE);
5931 size_t size = s.length();
5932 DString result;
5933 result.reserve(size+256);
5934 const char *data = s.data();
5935 size_t i=0;
5936 int col=0;
5937 constexpr auto doxy_nbsp = "&_doxy_nbsp;"; // doxygen escape command for UTF-8 nbsp
5938 const int maxIndent=1000000; // value representing infinity
5939 int minIndent=maxIndent;
5940 bool skip = false;
5941 while (i<size)
5942 {
5943 char c = data[i++];
5944 switch(c)
5945 {
5946 case '\t': // expand tab
5947 {
5948 int stop = tabSize - (col%tabSize);
5949 //printf("expand at %d stop=%d\n",col,stop);
5950 col+=stop;
5951 while (stop--) result+=' ';
5952 }
5953 break;
5954 case '\\':
5955 if (data[i] == '\\') // escaped command -> ignore
5956 {
5957 result+=c;
5958 result+=data[i++];
5959 col+=2;
5960 }
5961 else if (i+5<size && literal_at(data+i,"iskip")) // command
5962 {
5963 i+=5;
5964 skip = true;
5965 }
5966 else if (i+8<size && literal_at(data+i,"endiskip")) // command
5967 {
5968 i+=8;
5969 skip = false;
5970 }
5971 else // some other command
5972 {
5973 result+=c;
5974 col++;
5975 }
5976 break;
5977 case '\n': // reset column counter
5978 result+=c;
5979 col=0;
5980 break;
5981 case ' ': // increment column counter
5982 result+=c;
5983 col++;
5984 break;
5985 default: // non-whitespace => update minIndent
5986 if (c<0 && i<size) // multibyte sequence
5987 {
5988 // special handling of the UTF-8 nbsp character 0xC2 0xA0
5989 int nb = isUTF8NonBreakableSpace(data);
5990 if (nb>0)
5991 {
5992 result+=doxy_nbsp;
5993 i+=nb-1;
5994 }
5995 else
5996 {
5997 int bytes = getUTF8CharNumBytes(c);
5998 for (int j=0;j<bytes-1 && c;j++)
5999 {
6000 result+=c;
6001 c = data[i++];
6002 }
6003 result+=c;
6004 }
6005 }
6006 else
6007 {
6008 result+=c;
6009 }
6010 if (!skip && col<minIndent) minIndent=col;
6011 col++;
6012 }
6013 }
6014 if (minIndent!=maxIndent) refIndent=minIndent; else refIndent=0;
6015 //printf("detab(\n%s\n)=[\n%s\n]\n",qPrint(s),qPrint(out.get()));
6016 return result;
6017}
bool literal_at(const char *data, const char(&str)[N])
returns true iff data points to a substring that matches string literal str
Definition stringutil.h:101
int isUTF8NonBreakableSpace(const char *input)
Check if the first character pointed at by input is a non-breakable whitespace character.
Definition utf8.cpp:228
uint8_t getUTF8CharNumBytes(char c)
Returns the number of bytes making up a single UTF8 character given the first byte in the sequence.
Definition utf8.cpp:23

References Config_getInt, DString::data(), detab(), getUTF8CharNumBytes(), isUTF8NonBreakableSpace(), DString::length(), literal_at(), and DString::reserve().

Referenced by detab(), FileDefImpl::parseSource(), Markdown::process(), processMarkup(), DocParser::readTextFileByName(), readTextFileByName(), MemberDefImpl::setInitializer(), DefinitionImpl::writeInlineCode(), and FileDefImpl::writeSourceBody().

◆ determineAbsoluteIncludeName()

DString determineAbsoluteIncludeName ( const DString & curFile,
const DString & incFileName )

Definition at line 2996 of file util.cpp.

2997{
2998 bool searchIncludes = Config_getBool(SEARCH_INCLUDES);
2999 DString absIncFileName = incFileName;
3000 FileInfo fi(curFile.str());
3001 if (fi.exists())
3002 {
3003 DString absName = fi.dirPath(true)+"/"+incFileName;
3004 FileInfo fi2(absName.str());
3005 if (fi2.exists())
3006 {
3007 absIncFileName=fi2.absFilePath();
3008 }
3009 else if (searchIncludes) // search in INCLUDE_PATH as well
3010 {
3011 StringVector includePath = Config_getList(INCLUDE_PATH);
3012 for (const auto &incPath : includePath)
3013 {
3014 FileInfo fi3(incPath);
3015 if (fi3.exists() && fi3.isDir())
3016 {
3017 absName = fi3.absFilePath()+"/"+incFileName;
3018 //printf("trying absName=%s\n",qPrint(absName));
3019 FileInfo fi4(absName.str());
3020 if (fi4.exists())
3021 {
3022 absIncFileName=fi4.absFilePath();
3023 break;
3024 }
3025 //printf( "absIncFileName = %s\n", qPrint(absIncFileName) );
3026 }
3027 }
3028 }
3029 //printf( "absIncFileName = %s\n", qPrint(absIncFileName) );
3030 }
3031 return absIncFileName;
3032}
Minimal replacement for QFileInfo.
Definition fileinfo.h:23
#define Config_getList(name)
Definition config.h:38
std::vector< std::string > StringVector
Definition containers.h:33

References FileInfo::absFilePath(), Config_getBool, Config_getList, determineAbsoluteIncludeName(), FileInfo::dirPath(), FileInfo::exists(), FileInfo::isDir(), and DString::str().

Referenced by addDirPrefix(), determineAbsoluteIncludeName(), readIncludeFile(), and ModuleManager::resolveImports().

◆ escapeCharsInString()

DString escapeCharsInString ( const DString & name,
bool allowDots,
bool allowUnderscore = false )

Definition at line 2755 of file util.cpp.

2756{
2757 if (name.empty()) return name;
2758 bool caseSenseNames = useCaseSenseNames();
2759 bool allowUnicodeNames = Config_getBool(ALLOW_UNICODE_NAMES);
2760 DString result;
2761 result.reserve(name.length()+8);
2762 signed char c = 0;
2763 const char *p=name.data();
2764 while ((c=*p++)!=0)
2765 {
2766 switch(c)
2767 {
2768 case '_': if (allowUnderscore) result+='_'; else result+="__"; break;
2769 case '-': result+='-'; break;
2770 case ':': result+="_1"; break;
2771 case '/': result+="_2"; break;
2772 case '<': result+="_3"; break;
2773 case '>': result+="_4"; break;
2774 case '*': result+="_5"; break;
2775 case '&': result+="_6"; break;
2776 case '|': result+="_7"; break;
2777 case '.': if (allowDots) result+='.'; else result+="_8"; break;
2778 case '!': result+="_9"; break;
2779 case ',': result+="_00"; break;
2780 case ' ': result+="_01"; break;
2781 case '{': result+="_02"; break;
2782 case '}': result+="_03"; break;
2783 case '?': result+="_04"; break;
2784 case '^': result+="_05"; break;
2785 case '%': result+="_06"; break;
2786 case '(': result+="_07"; break;
2787 case ')': result+="_08"; break;
2788 case '+': result+="_09"; break;
2789 case '=': result+="_0a"; break;
2790 case '$': result+="_0b"; break;
2791 case '\\': result+="_0c"; break;
2792 case '@': result+="_0d"; break;
2793 case ']': result+="_0e"; break;
2794 case '[': result+="_0f"; break;
2795 case '#': result+="_0g"; break;
2796 case '"': result+="_0h"; break;
2797 case '~': result+="_0i"; break;
2798 case '\'': result+="_0j"; break;
2799 case ';': result+="_0k"; break;
2800 case '`': result+="_0l"; break;
2801 default:
2802 if (c<0)
2803 {
2804 bool doEscape = true;
2805 if (allowUnicodeNames)
2806 {
2807 int charLen = getUTF8CharNumBytes(c);
2808 if (charLen>0)
2809 {
2810 result+=DString(p-1,charLen);
2811 p+=charLen;
2812 doEscape = false;
2813 }
2814 }
2815 if (doEscape) // not a valid unicode char or escaping needed
2816 {
2817 char ids[5];
2818 unsigned char id = static_cast<unsigned char>(c);
2819 ids[0]='_';
2820 ids[1]='x';
2821 ids[2]=hex[id>>4];
2822 ids[3]=hex[id&0xF];
2823 ids[4]=0;
2824 result+=ids;
2825 }
2826 }
2827 else if (caseSenseNames || !isupper(c))
2828 {
2829 result+=c;
2830 }
2831 else
2832 {
2833 result+='_';
2834 result+=static_cast<char>(tolower(c));
2835 }
2836 break;
2837 }
2838 }
2839 return result;
2840}
bool useCaseSenseNames()
Returns true if the names of the symbols can be case sensitive.
Definition util.cpp:2746

References Config_getBool, DString::data(), DString::DString(), DString::empty(), escapeCharsInString(), getUTF8CharNumBytes(), hex, DString::length(), DString::reserve(), and useCaseSenseNames().

Referenced by convertNameToFile(), escapeCharsInString(), DotClassGraph::getMapLabel(), DotDirDeps::getMapLabel(), DotGfxHierarchyTable::getMapLabel(), DotGroupCollaboration::getMapLabel(), DotInclDepGraph::getMapLabel(), markdownFileNameToId(), and PageDefImpl::writeDocumentation().

◆ externalLinkTarget()

DString externalLinkTarget ( const bool parent = false)

Definition at line 5049 of file util.cpp.

5050{
5051 bool extLinksInWindow = Config_getBool(EXT_LINKS_IN_WINDOW);
5052 if (extLinksInWindow)
5053 return "target=\"_blank\" ";
5054 else if (parent)
5055 return "target=\"_parent\" ";
5056 else
5057 return "";
5058}
constexpr DocNodeVariant * parent(DocNodeVariant *n)
returns the parent node of a given node n or nullptr if the node has no parent.
Definition docnode.h:1335

References Config_getBool, externalLinkTarget(), and parent().

Referenced by HtmlCodeGenerator::_writeCodeLink(), externalLinkTarget(), FTVHelp::Private::generateLink(), Markdown::Private::processLink(), recodeString(), replaceRef(), HtmlGenerator::startIndexItem(), HtmlDocVisitor::startLink(), HtmlGenerator::writeInheritedSectionTitle(), writeMapArea(), and HtmlGenerator::writeObjectLink().

◆ externalRef()

DString externalRef ( const DString & relPath,
const DString & ref,
bool href )

Definition at line 5097 of file util.cpp.

5098{
5099 DString result;
5100 if (!ref.empty())
5101 {
5102 auto it = Doxygen::tagDestinationMap.find(ref.str());
5104 {
5105 result = it->second;
5106 size_t l = result.length();
5107 if (!relPath.empty() && l>0 && result.at(0)=='.')
5108 { // relative path -> prepend relPath.
5109 result.prepend(relPath);
5110 l+=relPath.length();
5111 }
5112 if (l>0 && result.at(l-1)!='/') result+='/';
5113 if (!href) result.append("\" ");
5114 }
5115 }
5116 else
5117 {
5118 result = relPath;
5119 }
5120 return result;
5121}
char & at(size_t i)
Returns a reference to the character at index i.
Definition dstring.h:675
DString & append(char c)
Definition dstring.h:478
static StringMap tagDestinationMap
Definition doxygen.h:116

References DString::append(), DString::at(), DString::empty(), end(), externalRef(), DString::length(), DString::prepend(), DString::str(), and Doxygen::tagDestinationMap.

Referenced by HtmlHelp::addContentsItem(), convertMapFile(), createHtmlUrl(), externalRef(), generateJSLink(), FTVHelp::Private::generateLink(), recodeString(), replaceRef(), HtmlGenerator::startIndexItem(), LayoutNavEntry::url(), HtmlGenerator::writeInheritedSectionTitle(), writeJavasScriptSearchDataPage(), and writeMapArea().

◆ extractBeginRawStringDelimiter()

DString extractBeginRawStringDelimiter ( const char * rawStart)

Definition at line 6136 of file util.cpp.

6137{
6138 DString text=rawStart;
6139 size_t i = text.find('"');
6140 assert(i!=DString::npos);
6141 return text.mid(i+1,text.length()-i-2); // text=...R"xyz( -> delimiter=xyz
6142}

References extractBeginRawStringDelimiter(), DString::find(), DString::length(), DString::mid(), and DString::npos.

Referenced by extractBeginRawStringDelimiter(), and processMarkup().

◆ extractClassNameFromType()

int extractClassNameFromType ( const DString & type,
int & pos,
DString & name,
DString & templSpec,
SrcLangExt lang )

Extracts a (sub-)string from type starting at pos that could form a class. The index of the match is returned and the found class name and a template argument list templSpec. If -1 is returned there are no more matches.

Definition at line 3560 of file util.cpp.

3561{
3562 AUTO_TRACE("type='{}' pos={} name='{}' lang={}",type,pos,name,lang);
3563 static const reg::Ex re_norm(R"(\a[\w:]*)");
3564 static const reg::Ex re_fortran(R"(\a[\w:()=]*)");
3565 const reg::Ex *re = &re_norm;
3566
3567 name.clear();
3568 templSpec.clear();
3569 if (type.empty())
3570 {
3571 AUTO_TRACE_EXIT("empty type");
3572 return -1;
3573 }
3574 size_t typeLen=type.length();
3575 if (typeLen>0)
3576 {
3577 if (lang == SrcLangExt::Fortran)
3578 {
3579 if (type[pos]==',')
3580 {
3581 AUTO_TRACE_EXIT("comma");
3582 return -1;
3583 }
3584 if (!type.lower().startsWith("type"))
3585 {
3586 re = &re_fortran;
3587 }
3588 }
3589 std::string s = type.str();
3590 reg::Iterator it(s,*re,static_cast<int>(pos));
3592
3593 if (it!=end)
3594 {
3595 const auto &match = *it;
3596 size_t i = match.position();
3597 size_t l = match.length();
3598 size_t ts = i+l;
3599 size_t te = ts;
3600 size_t tl = 0;
3601
3602 while (ts<typeLen && type[static_cast<uint32_t>(ts)]==' ') { ts++; tl++; } // skip any whitespace
3603 if (ts<typeLen && type[static_cast<uint32_t>(ts)]=='<') // assume template instance
3604 {
3605 // locate end of template
3606 te=ts+1;
3607 int brCount=1;
3608 while (te<typeLen && brCount!=0)
3609 {
3610 if (type[static_cast<uint32_t>(te)]=='<')
3611 {
3612 if (te<typeLen-1 && type[static_cast<uint32_t>(te)+1]=='<') te++; else brCount++;
3613 }
3614 if (type[static_cast<uint32_t>(te)]=='>')
3615 {
3616 if (te<typeLen-1 && type[static_cast<uint32_t>(te)+1]=='>') te++; else brCount--;
3617 }
3618 te++;
3619 }
3620 }
3621 name = match.str();
3622 if (te>ts)
3623 {
3624 templSpec = DString(type).mid(ts,te-ts);
3625 tl+=te-ts;
3626 pos=static_cast<int>(i+l+tl);
3627 }
3628 else // no template part
3629 {
3630 pos=static_cast<int>(i+l);
3631 }
3632 //printf("extractClassNameFromType([in] type=%s,[out] pos=%d,[out] name=%s,[out] templ=%s)=true i=%d\n",
3633 // qPrint(type),pos,qPrint(name),qPrint(templSpec),i);
3634 AUTO_TRACE_EXIT("pos={} templSpec='{}' return={}",pos,templSpec,i);
3635 return static_cast<int>(i);
3636 }
3637 }
3638 pos = static_cast<int>(typeLen);
3639 //printf("extractClassNameFromType([in] type=%s,[out] pos=%d,[out] name=%s,[out] templ=%s)=false\n",
3640 // qPrint(type),pos,qPrint(name),qPrint(templSpec));
3641 AUTO_TRACE_EXIT("not found");
3642 return -1;
3643}
void clear()
Definition dstring.h:219
DString lower() const
Definition dstring.h:331
bool startsWith(const char *s) const
Definition dstring.h:589
Class representing a regular expression.
Definition regex.h:39
Class to iterate through matches.
Definition regex.h:239
#define AUTO_TRACE(...)
Definition docnode.cpp:50
#define AUTO_TRACE_EXIT(...)
Definition docnode.cpp:52
bool match(std::string_view str, Match &match, const Ex &re)
Matches a given string str for a match against regular expression re.
Definition regex.cpp:858

References AUTO_TRACE, AUTO_TRACE_EXIT, DString::clear(), DString::DString(), DString::empty(), end(), extractClassNameFromType(), DString::length(), DString::lower(), DString::mid(), DString::startsWith(), and DString::str().

Referenced by extractCanonicalType(), extractClassNameFromType(), findUsedClassesForClass(), stripClassName(), and stripClassName().

◆ extractEndRawStringDelimiter()

DString extractEndRawStringDelimiter ( const char * rawEnd)

Definition at line 6144 of file util.cpp.

6145{
6146 DString text=rawEnd;
6147 return text.mid(1,text.length()-2); // text=)xyz" -> delimiter=xyz
6148}

References extractEndRawStringDelimiter(), DString::length(), and DString::mid().

Referenced by extractEndRawStringDelimiter(), and processMarkup().

◆ extractNamespaceName()

void extractNamespaceName ( const DString & scopeName,
DString & className,
DString & namespaceName,
bool allowEmptyClass )

Input is a scopeName, output is the scopename split into a namespace part (as large as possible) and a classname part.

Definition at line 3093 of file util.cpp.

3096{
3097 DString clName=scopeName;
3098 NamespaceDef *nd = nullptr;
3099 size_t i=0;
3100 int p=0;
3101 if (!clName.empty() && (nd=getResolvedNamespace(clName)) && getClass(clName)==nullptr)
3102 { // the whole name is a namespace (and not a class)
3103 namespaceName=nd->name();
3104 className.clear();
3105 goto done;
3106 }
3107 p=static_cast<int>(clName.length())-2;
3108 while (p>=0 && (i=clName.rfind("::",p))!=DString::npos)
3109 // see if the first part is a namespace (and not a class)
3110 {
3111 //printf("Trying %s\n",qPrint(clName.left(i)));
3112 if (i>0 && (nd=getResolvedNamespace(clName.left(i))) && getClass(clName.left(i))==nullptr)
3113 {
3114 //printf("found!\n");
3115 namespaceName=nd->name();
3116 className=clName.mid(i+2);
3117 goto done;
3118 }
3119 p=static_cast<int>(i)-2; // try a smaller piece of the scope
3120 }
3121 //printf("not found!\n");
3122
3123 // not found, so we just have to guess.
3124 className=scopeName;
3125 namespaceName.clear();
3126
3127done:
3128 if (className.empty() && !namespaceName.empty() && !allowEmptyClass)
3129 {
3130 // class and namespace with the same name, correct to return the class.
3131 className=namespaceName;
3132 namespaceName.clear();
3133 }
3134 //printf("extractNamespace '%s' => '%s|%s'\n",qPrint(scopeName),
3135 // qPrint(className),qPrint(namespaceName));
3136 if (className.endsWith("-p"))
3137 {
3138 className = className.left(className.length()-2);
3139 }
3140 return;
3141}
An abstract interface of a namespace symbol.
ClassDef * getClass(const DString &n)
NamespaceDef * getResolvedNamespace(const DString &name)

References DString::clear(), DString::empty(), DString::endsWith(), extractNamespaceName(), getClass(), getResolvedNamespace(), DString::left(), DString::length(), DString::mid(), Definition::name(), DString::npos, and DString::rfind().

Referenced by addClassToContext(), addConceptToContext(), extractNamespaceName(), findMember(), and writeAlphabeticalClassList().

◆ fileToString()

DString fileToString ( const DString & name,
bool filter = false,
bool isSourceCode = false )

reads a file with name name and returns it as a string. If filter is true the file will be filtered by any user specified input filter. If name is "-" the string will be read from standard input.

Definition at line 1120 of file util.cpp.

1121{
1122 if (name.empty()) return DString();
1123 bool fileOpened=false;
1124 if (name[0]=='-' && name[1]==0) // read from stdin
1125 {
1126 std::string contents;
1127 std::string line;
1128 while (getline(std::cin,line))
1129 {
1130 contents+=line+'\n';
1131 }
1132 return contents;
1133 }
1134 else // read from file
1135 {
1136 FileInfo fi(name.str());
1137 if (!fi.exists() || !fi.isFile())
1138 {
1139 err("file '{}' not found\n",name);
1140 return "";
1141 }
1142 std::string buf;
1143 fileOpened=readInputFile(name,buf,filter,isSourceCode);
1144 if (fileOpened)
1145 {
1146 addTerminalCharIfMissing(buf,'\n');
1147 return buf;
1148 }
1149 }
1150 if (!fileOpened)
1151 {
1152 err("cannot open file '{}' for reading\n",name);
1153 }
1154 return "";
1155}
void addTerminalCharIfMissing(std::string &s, char c)
Definition stringutil.h:87
bool readInputFile(const DString &fileName, std::string &contents, bool filter, bool isSourceCode)
read a file name fileName and optionally filter and transcode it
Definition util.cpp:4874

References addTerminalCharIfMissing(), DString::DString(), DString::empty(), err, FileInfo::exists(), fileToString(), FileInfo::isFile(), readInputFile(), and DString::str().

Referenced by createDVIFile(), extractBoundingBox(), fileToString(), getConvertLatexMacro(), HtmlGenerator::init(), LatexGenerator::init(), LayoutDocManager::parse(), parseInput(), FileDefImpl::parseSource(), parseTagFile(), DocParser::readTextFileByName(), readTextFileByName(), runMermaid(), runPlantumlContent(), FileDefImpl::writeSourceBody(), HtmlGenerator::writeStyleInfo(), and writeXMLCodeBlock().

◆ fileVisibleInIndex()

bool fileVisibleInIndex ( const FileDef * fd,
bool & genSourceFile )

Definition at line 5406 of file util.cpp.

5407{
5408 bool allExternals = Config_getBool(ALLEXTERNALS);
5409 bool isDocFile = fd->isDocumentationFile();
5410 genSourceFile = !isDocFile && fd->generateSourceFile();
5411 return ( ((allExternals && fd->isLinkable()) ||
5413 ) &&
5414 !isDocFile
5415 );
5416}
virtual bool isLinkable() const =0
virtual bool isLinkableInProject() const =0
virtual bool generateSourceFile() const =0
virtual bool isDocumentationFile() const =0

References Config_getBool, fileVisibleInIndex(), FileDef::generateSourceFile(), FileDef::isDocumentationFile(), Definition::isLinkable(), and Definition::isLinkableInProject().

Referenced by countFiles(), dirHasVisibleChildren(), fileVisibleInIndex(), generateJSTree(), processMarkup(), writeDirHierarchy(), writeDirTreeNode(), and DirDefImpl::writeFileList().

◆ filterTitle()

DString filterTitle ( const DString & title)

Definition at line 4954 of file util.cpp.

4955{
4956 std::string tf;
4957 std::string t = title.str();
4958 static const reg::Ex re(R"(%[a-z_A-Z]+)");
4959 reg::Iterator it(t,re);
4961 size_t p = 0;
4962 for (; it!=end ; ++it)
4963 {
4964 const auto &match = *it;
4965 size_t i = match.position();
4966 size_t l = match.length();
4967 if (i>p) tf+=t.substr(p,i-p);
4968 tf+=match.str().substr(1); // skip %
4969 p=i+l;
4970 }
4971 tf+=t.substr(p);
4972 return tf;
4973}

References end(), filterTitle(), and DString::str().

Referenced by addToIndices(), createJavaScriptSearchIndex(), filterTitle(), PerlModGenerator::generatePerlModForPage(), generateSqlite3ForPage(), generateXMLForPage(), generateXMLForRequirement(), generateXMLForRequirements(), parseCommentAsHtml(), recodeString(), SearchIndexExternal::setCurrentDoc(), HtmlGenerator::startFile(), and writeJavasScriptSearchDataPage().

◆ findAndRemoveWord()

bool findAndRemoveWord ( DString & sentence,
const char * word )

removes occurrences of whole word from sentence, while keeps internal spaces and reducing multiple sequences of spaces.

Example: sentence= cat+ catfish cat cat concat cat, word=cat returns: + catfish concat

Definition at line 4312 of file util.cpp.

4313{
4314 static reg::Ex re(R"(\s*(<\a+>)\s*)");
4315 std::string s = sentence.str();
4316 reg::Iterator it(s,re);
4318 std::string result;
4319 bool found=false;
4320 size_t p=0;
4321 for ( ; it!=end ; ++it)
4322 {
4323 const auto match = *it;
4324 std::string part = match[1].str();
4325 if (part!=word)
4326 {
4327 size_t i = match.position();
4328 size_t l = match.length();
4329 result+=s.substr(p,i-p);
4330 result+=match.str();
4331 p=i+l;
4332 }
4333 else
4334 {
4335 found=true;
4336 size_t i = match[1].position();
4337 size_t l = match[1].length();
4338 result+=s.substr(p,i-p);
4339 p=i+l;
4340 }
4341 }
4342 result+=s.substr(p);
4343 sentence = DString(result).simplifyWhiteSpace();
4344 return found;
4345}
DString simplifyWhiteSpace() const
return a copy of this string with leading and trailing whitespace removed and multiple whitespace cha...
Definition dstring.cpp:122

References DString::DString(), end(), findAndRemoveWord(), DString::simplifyWhiteSpace(), and DString::str().

Referenced by addDirPrefix(), findAndRemoveWord(), and isVarWithConstructor().

◆ findExampleFilePath()

DString findExampleFilePath ( const DString & file,
bool & ambig )

Definition at line 2518 of file util.cpp.

2519{
2520 ambig=false;
2521 DString result;
2522 bool found=false;
2523 if (!found)
2524 {
2525 FileInfo fi(file.str());
2526 if (fi.exists())
2527 {
2528 result=fi.absFilePath();
2529 found=true;
2530 }
2531 }
2532 if (!found)
2533 {
2534 StringVector examplePathList = Config_getList(EXAMPLE_PATH);
2535 for (const auto &s : examplePathList)
2536 {
2537 std::string absFileName = s+(Portable::pathSeparator()+file).str();
2538 FileInfo fi(absFileName);
2539 if (fi.exists())
2540 {
2541 result=fi.absFilePath();
2542 found=true;
2543 }
2544 }
2545 }
2546
2547 if (!found)
2548 {
2549 // as a fallback we also look in the exampleNameDict
2551 if (fd && !ambig)
2552 {
2553 result=fd->absFilePath();
2554 }
2555 }
2556 return result;
2557}
static FileNameLinkedMap * exampleNameLinkedMap
Definition doxygen.h:102
A model of a file symbol.
Definition filedef.h:99
virtual DString absFilePath() const =0
FileDef * findFileDef(const DString &n, bool &ambig) const
Returns the file definition in fnMap that matches the file name n.
Definition filename.cpp:36
DString pathSeparator()
Definition portable.cpp:374

References FileDef::absFilePath(), FileInfo::absFilePath(), Config_getList, Doxygen::exampleNameLinkedMap, FileInfo::exists(), findExampleFilePath(), FileNameLinkedMap::findFileDef(), Portable::pathSeparator(), and DString::str().

Referenced by findExampleFilePath(), readIncludeFile(), and DocParser::readTextFileByName().

◆ getDefs()

GetDefResult getDefs ( const GetDefInput & input)

Definition at line 1933 of file util.cpp.

1934{
1935 GetDefResult result;
1936 if (input.memberName.empty()) return result;
1937 AUTO_TRACE("scopeName={},memberName={},forceEmptyScope={}",
1938 input.scopeName,input.memberName,input.forceEmptyScope);
1939
1940 //printf("@@ --- getDefsNew(%s,%s)-----------\n",qPrint(scName),qPrint(mbName));
1941 const Definition *scope = Doxygen::globalScope;
1942 SymbolResolver resolver;
1943 if (input.currentFile) resolver.setFileScope(input.currentFile);
1944 if (!input.scopeName.empty() && !input.forceEmptyScope)
1945 {
1946 scope = resolver.resolveSymbol(scope,input.scopeName);
1947 }
1948 if (scope==Doxygen::globalScope)
1949 {
1950 scope = input.currentFile;
1951 }
1952 //printf("@@ -> found scope scope=%s member=%s out=%s\n",qPrint(input.scopeName),qPrint(input.memberName),qPrint(scope?scope->name():""));
1953 //
1954 const Definition *symbol = resolver.resolveSymbol(scope,input.memberName,input.args,input.checkCV,input.insideCode,true);
1955 //printf("@@ -> found symbol in=%s out=%s\n",qPrint(input.memberName),qPrint(symbol?symbol->qualifiedName():DString()));
1956 if (symbol && symbol->definitionType()==Definition::TypeMember)
1957 {
1958 result.md = toMemberDef(symbol);
1959 result.cd = result.md->getClassDef();
1960 if (result.cd==nullptr) result.nd = result.md->getNamespaceDef();
1961 if (result.cd==nullptr && result.nd==nullptr) result.fd = result.md->getFileDef();
1962 result.gd = result.md->getGroupDef();
1963 result.found = true;
1964 }
1965 else if (symbol && symbol->definitionType()==Definition::TypeClass)
1966 {
1967 result.cd = toClassDef(symbol);
1968 result.found = true;
1969 }
1970 else if (symbol && symbol->definitionType()==Definition::TypeNamespace)
1971 {
1972 result.nd = toNamespaceDef(symbol);
1973 result.found = true;
1974 }
1975 else if (symbol && symbol->definitionType()==Definition::TypeConcept)
1976 {
1977 result.cnd = toConceptDef(symbol);
1978 result.found = true;
1979 }
1980 else if (symbol && symbol->definitionType()==Definition::TypeModule)
1981 {
1982 result.modd = toModuleDef(symbol);
1983 result.found = true;
1984 }
1985 return result;
1986}
The common base class of all entity definitions found in the sources.
Definition definition.h:77
virtual DefType definitionType() const =0
static NamespaceDefMutable * globalScope
Definition doxygen.h:121
virtual const ClassDef * getClassDef() const =0
virtual GroupDef * getGroupDef()=0
virtual const FileDef * getFileDef() const =0
virtual const NamespaceDef * getNamespaceDef() const =0
const Definition * resolveSymbol(const Definition *scope, const DString &name, const DString &args=DString(), bool checkCV=false, bool insideCode=false, bool onlyLinkable=false)
Find the symbool definition matching name within the scope set.
void setFileScope(const FileDef *fd)
Sets or updates the file scope using when resolving symbols.
ClassDef * toClassDef(Definition *d)
ConceptDef * toConceptDef(Definition *d)
MemberDef * toMemberDef(Definition *d)
ModuleDef * toModuleDef(Definition *d)
NamespaceDef * toNamespaceDef(Definition *d)
bool forceEmptyScope
Definition util.h:98
const FileDef * currentFile
Definition util.h:99
bool insideCode
Definition util.h:101
DString args
Definition util.h:97
DString memberName
Definition util.h:96
bool checkCV
Definition util.h:100
DString scopeName
Definition util.h:95
const MemberDef * md
Definition util.h:108
const ConceptDef * cnd
Definition util.h:113
const FileDef * fd
Definition util.h:110
const ModuleDef * modd
Definition util.h:114
const GroupDef * gd
Definition util.h:112
bool found
Definition util.h:107
const ClassDef * cd
Definition util.h:109
const NamespaceDef * nd
Definition util.h:111

References GetDefInput::args, AUTO_TRACE, GetDefResult::cd, GetDefInput::checkCV, GetDefResult::cnd, GetDefInput::currentFile, Definition::definitionType(), DString::empty(), GetDefResult::fd, GetDefInput::forceEmptyScope, GetDefResult::found, GetDefResult::gd, MemberDef::getClassDef(), getDefs(), MemberDef::getFileDef(), MemberDef::getGroupDef(), MemberDef::getNamespaceDef(), Doxygen::globalScope, GetDefInput::insideCode, GetDefResult::md, GetDefInput::memberName, GetDefResult::modd, GetDefResult::nd, SymbolResolver::resolveSymbol(), GetDefInput::scopeName, SymbolResolver::setFileScope(), toClassDef(), toConceptDef(), toMemberDef(), toModuleDef(), toNamespaceDef(), Definition::TypeClass, Definition::TypeConcept, Definition::TypeMember, Definition::TypeModule, and Definition::TypeNamespace.

Referenced by DocParser::findDocsForMemberOrCompound(), getDefs(), getLinkInScope(), getLinkInScope(), linkifyText(), and resolveRef().

◆ getDotImageExtension()

DString getDotImageExtension ( )

Definition at line 5630 of file util.cpp.

5631{
5632 DString imgExt = Config_getEnumAsString(DOT_IMAGE_FORMAT);
5633 size_t i= imgExt.find(':'); // strip renderer part when using e.g. 'png:cairo:gd' as format
5634 return i==DString::npos ? imgExt : imgExt.left(i);
5635}
#define Config_getEnumAsString(name)
Definition config.h:36

References Config_getEnumAsString, DString::find(), getDotImageExtension(), DString::left(), and DString::npos.

Referenced by MermaidManager::convertToImageFormat(), RTFGenerator::endCallGraph(), RTFGenerator::endDirDepGraph(), RTFGenerator::endDotGraph(), RTFGenerator::endInclDepGraph(), DotGraph::generateCode(), getDotImageExtension(), DotGraph::imgName(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), processMarkup(), DocbookDocVisitor::startDotFile(), TranslatorAfrikaans::trLegendDocs(), TranslatorArabic::trLegendDocs(), TranslatorArmenian::trLegendDocs(), TranslatorBrazilian::trLegendDocs(), TranslatorBulgarian::trLegendDocs(), TranslatorCatalan::trLegendDocs(), TranslatorChinese::trLegendDocs(), TranslatorChinesetraditional::trLegendDocs(), TranslatorCroatian::trLegendDocs(), TranslatorCzech::trLegendDocs(), TranslatorDanish::trLegendDocs(), TranslatorDutch::trLegendDocs(), TranslatorEnglish::trLegendDocs(), TranslatorEsperanto::trLegendDocs(), TranslatorFinnish::trLegendDocs(), TranslatorFrench::trLegendDocs(), TranslatorGerman::trLegendDocs(), TranslatorGreek::trLegendDocs(), TranslatorHindi::trLegendDocs(), TranslatorHungarian::trLegendDocs(), TranslatorIndonesian::trLegendDocs(), TranslatorItalian::trLegendDocs(), TranslatorJapanese::trLegendDocs(), TranslatorKorean::trLegendDocs(), TranslatorLatvian::trLegendDocs(), TranslatorLithuanian::trLegendDocs(), TranslatorMacedonian::trLegendDocs(), TranslatorNorwegian::trLegendDocs(), TranslatorPersian::trLegendDocs(), TranslatorPolish::trLegendDocs(), TranslatorPortuguese::trLegendDocs(), TranslatorRomanian::trLegendDocs(), TranslatorRussian::trLegendDocs(), TranslatorSerbian::trLegendDocs(), TranslatorSerbianCyrillic::trLegendDocs(), TranslatorSlovak::trLegendDocs(), TranslatorSlovene::trLegendDocs(), TranslatorSpanish::trLegendDocs(), TranslatorSwedish::trLegendDocs(), TranslatorTurkish::trLegendDocs(), TranslatorUkrainian::trLegendDocs(), TranslatorVietnamese::trLegendDocs(), DocbookDocVisitor::writeDotFile(), RTFDocVisitor::writeDotFile(), writeDotGraphFromFile(), writeDotImageMapFromFile(), DotLegendGraph::writeGraph(), HtmlDocVisitor::writeMscFile(), and HtmlDocVisitor::writePlantUMLFile().

◆ getEncoding()

DString getEncoding ( const FileInfo & fi)

Definition at line 5035 of file util.cpp.

5036{
5037 InputFileEncoding elem;
5038 auto getter = [](const InputFileEncoding &e) -> DString { return e.pattern; };
5039 if (genericPatternMatch(fi,Doxygen::inputFileEncodingList,elem,getter)) // check for file specific encoding
5040 {
5041 return elem.encoding;
5042 }
5043 else // fall back to default encoding
5044 {
5045 return Config_getString(INPUT_ENCODING);
5046 }
5047}
static InputFileEncodingList inputFileEncodingList
Definition doxygen.h:138
#define Config_getString(name)
Definition config.h:32
DString encoding
Definition doxygen.h:70
bool genericPatternMatch(const FileInfo &fi, const PatternList &patList, PatternElem &elem, PatternGet getter)
Definition util.cpp:4978

References Config_getString, InputFileEncoding::encoding, genericPatternMatch(), getEncoding(), and Doxygen::inputFileEncodingList.

Referenced by getEncoding(), processMarkup(), readCodeFragment(), and readInputFile().

◆ getFileFilter()

DString getFileFilter ( const DString & name,
bool isSourceCode )

looks for a filter for the file name. Returns the name of the filter if there is a match for the file name, otherwise an empty string. In case inSourceCode is true then first the source filter list is considered.

Definition at line 1052 of file util.cpp.

1053{
1054 // sanity check
1055 if (name.empty()) return "";
1056
1057 StringVector filterSrcList = Config_getList(FILTER_SOURCE_PATTERNS);
1058 StringVector filterList = Config_getList(FILTER_PATTERNS);
1059
1060 DString filterName;
1061 bool found=false;
1062 if (isSourceCode && !filterSrcList.empty())
1063 { // first look for source filter pattern list
1064 filterName = getFilterFromList(name,filterSrcList,found);
1065 }
1066 if (!found && filterName.empty())
1067 { // then look for filter pattern list
1068 filterName = getFilterFromList(name,filterList,found);
1069 }
1070 if (!found)
1071 { // then use the generic input filter
1072 return Config_getString(INPUT_FILTER);
1073 }
1074 else
1075 {
1076 /* remove surrounding double quotes */
1077 if (filterName.length()>=2 && filterName[0]=='"' && filterName[static_cast<int>(filterName.length())-1]=='"')
1078 {
1079 filterName = filterName.mid(1,filterName.length()-2);
1080 }
1081 return filterName;
1082 }
1083}
static DString getFilterFromList(const DString &name, const StringVector &filterList, bool &found)
Definition util.cpp:1017

References Config_getList, Config_getString, DString::empty(), getFileFilter(), getFilterFromList(), DString::length(), and DString::mid().

Referenced by FilterCache::getFileContents(), getFileFilter(), CodeFragmentManager::parseCodeFragment(), readCodeFragment(), readInputFile(), and FileDefImpl::writeSourceBody().

◆ getFileNameExtension()

◆ getLanguageFromCodeLang()

SrcLangExt getLanguageFromCodeLang ( DString & fileName)

Routine to handle the language attribute of the \code command.

Definition at line 4554 of file util.cpp.

4555{
4556 // try the extension
4557 auto lang = getLanguageFromFileName(fileName, SrcLangExt::Unknown);
4558 if (lang == SrcLangExt::Unknown)
4559 {
4560 // try the language names
4561 DString langName = fileName.lower();
4562 if (langName.at(0)=='.') langName = langName.mid(1);
4563 auto it = std::find_if(g_lang2extMap.begin(),g_lang2extMap.end(),
4564 [&langName](const auto &info) { return info.langName==langName; });
4565 if (it != g_lang2extMap.end())
4566 {
4567 lang = it->parserId;
4568 fileName = it->defExt;
4569 }
4570 else // default to C++
4571 {
4572 return SrcLangExt::Cpp;
4573 }
4574 }
4575 return lang;
4576}
SrcLangExt getLanguageFromFileName(const DString &fileName, SrcLangExt defLang)
Definition util.cpp:4536
static std::vector< Lang2ExtMap > g_lang2extMap
Definition util.cpp:4407

References DString::at(), g_lang2extMap, getLanguageFromCodeLang(), getLanguageFromFileName(), DString::lower(), and DString::mid().

Referenced by addDirPrefix(), getLanguageFromCodeLang(), DocbookDocVisitor::operator()(), HtmlDocVisitor::operator()(), LatexDocVisitor::operator()(), ManDocVisitor::operator()(), RTFDocVisitor::operator()(), and XmlDocVisitor::operator()().

◆ getLanguageFromFileName()

SrcLangExt getLanguageFromFileName ( const DString & fileName,
SrcLangExt defLang = SrcLangExt::Cpp )

Definition at line 4536 of file util.cpp.

4537{
4538 FileInfo fi(fileName.str());
4539 // we need only the part after the last ".", newer implementations of FileInfo have 'suffix()' for this.
4540 DString extName = DString(fi.extension(false)).lower();
4541 if (extName.empty()) extName=".no_extension";
4542 if (extName.at(0)!='.') extName.prepend(".");
4543 auto it = g_extLookup.find(extName.str());
4544 if (it!=g_extLookup.end()) // listed extension
4545 {
4546 //printf("getLanguageFromFileName(%s)=%x\n",qPrint(fi.extension()),*pVal);
4547 return it->second;
4548 }
4549 //printf("getLanguageFromFileName(%s) not found!\n",qPrint(fileName));
4550 return defLang; // not listed => assume C-ish language.
4551}
static std::unordered_map< std::string, SrcLangExt > g_extLookup
Definition util.cpp:4397

References DString::at(), DString::DString(), DString::empty(), FileInfo::extension(), g_extLookup, getLanguageFromFileName(), DString::lower(), DString::prepend(), and DString::str().

Referenced by MemberDefImpl::_writeMultiLineInitializer(), addDirPrefix(), ClassDefImpl::ClassDefImpl(), convertCppComments(), DocRef::DocRef(), FileDefImpl::FileDefImpl(), generateExampleDocs(), getLanguageFromCodeLang(), getLanguageFromFileName(), EntryType::guessSection(), FileDefImpl::isDocumentationFile(), COutlineParser::needsPreprocessing(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), ManDocVisitor::operator()(), ManDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), XmlDocVisitor::operator()(), XmlDocVisitor::operator()(), CodeFragmentManager::parseCodeFragment(), parseFilesMultiThreading(), parseFilesSingleThreading(), parseMain(), Markdown::Private::processLink(), readCodeFragment(), setContext(), setFileName(), validatingParseDoc(), and writeXMLCodeBlock().

◆ getLanguageSpecificSeparator()

DString getLanguageSpecificSeparator ( SrcLangExt lang,
bool classScope = false )

◆ getPrefixIndex()

int getPrefixIndex ( const DString & name)

Returns the character index within name of the first prefix in Config_getList(IGNORE_PREFIX) that matches name at the left hand side, or zero if no match was found

Definition at line 2718 of file util.cpp.

2719{
2720 if (name.empty()) return 0;
2721 int result=0;
2722 StringVector sl = Config_getList(IGNORE_PREFIX);
2723 for (const auto &s : sl)
2724 {
2725 const char *ps=s.c_str();
2726 const char *pd=name.data();
2727 int i=0;
2728 while (*ps!=0 && *pd!=0 && *ps==*pd)
2729 {
2730 ps++;
2731 pd++;
2732 i++;
2733 }
2734 if (*ps==0 && *pd!=0)
2735 {
2736 result=i;
2737 break;
2738 }
2739 }
2740 if (result<static_cast<int>(name.length())-1 && name.at(result)=='[') result++; // for e.g. [union] return u
2741 return result;
2742}

References DString::at(), Config_getList, DString::data(), DString::empty(), getPrefixIndex(), and DString::length().

Referenced by Index::addClassMemberNameToIndex(), Index::addFileMemberNameToIndex(), Index::addModuleMemberNameToIndex(), Index::addNamespaceMemberNameToIndex(), SearchIndex::addWordRec(), getPrefixIndex(), parseInput(), writeAlphabeticalClassList(), and writeMemberList().

◆ getProjectId()

DString getProjectId ( )

Definition at line 6019 of file util.cpp.

6020{
6021 DString projectCookie = Config_getString(HTML_PROJECT_COOKIE);
6022 if (projectCookie.empty()) return DString();
6023 return md5str(projectCookie.view())+"_";
6024}

References Config_getString, DString::DString(), DString::empty(), getProjectId(), md5str(), and DString::view().

Referenced by generateJSNavTree(), getProjectId(), HtmlGenerator::init(), processMarkup(), and writeJavaScriptSearchIndex().

◆ getScopeFragment()

int getScopeFragment ( const DString & s,
int p,
int * l )

Returns a fragment from scope s, starting at position p.

Parameters
sthe scope name as a string.
pthe start position (0 is the first).
lthe resulting length of the fragment.
Returns
the location of the fragment, or -1 if non is found.

Definition at line 3978 of file util.cpp.

3979{
3980 int sl=static_cast<int>(s.length());
3981 int sp=p;
3982 int count=0;
3983 bool done=false;
3984 if (sp>=sl) return -1;
3985 while (sp<sl)
3986 {
3987 char c=s.at(sp);
3988 if (c==':')
3989 {
3990 sp++;
3991 p++;
3992 }
3993 else
3994 {
3995 break;
3996 }
3997 }
3998 while (sp<sl)
3999 {
4000 char c=s.at(sp);
4001 switch (c)
4002 {
4003 case ':': // found next part
4004 goto found;
4005 case '<': // skip template specifier
4006 count=1;sp++;
4007 done=false;
4008 while (sp<sl && !done)
4009 {
4010 // TODO: deal with << and >> operators!
4011 c=s.at(sp++);
4012 switch(c)
4013 {
4014 case '<': count++; break;
4015 case '>': count--; if (count==0) done=true; break;
4016 default: break;
4017 }
4018 }
4019 break;
4020 default:
4021 sp++;
4022 break;
4023 }
4024 }
4025found:
4026 *l=sp-p;
4027 //printf("getScopeFragment(%s,%d)=%s\n",qPrint(s),p,qPrint(s.mid(p,*l)));
4028 return p;
4029}

References DString::at(), getScopeFragment(), and DString::length().

Referenced by buildScopeFromQualifiedName(), findScopeFromQualifiedName(), SymbolResolver::Private::followPath(), getScopeFragment(), resolveTypeDef(), and stripAnonymousNamespaceScope().

◆ initDefaultExtensionMapping()

void initDefaultExtensionMapping ( )

Definition at line 4463 of file util.cpp.

4464{
4465 // NOTE: when adding an extension, also add the extension in config.xml
4466 // extension parser id
4467 updateLanguageMapping(".dox", "c");
4468 updateLanguageMapping(".txt", "c"); // see bug 760836
4469 updateLanguageMapping(".doc", "c");
4470 updateLanguageMapping(".c", "c");
4471 updateLanguageMapping(".C", "c");
4472 updateLanguageMapping(".cc", "c");
4473 updateLanguageMapping(".CC", "c");
4474 updateLanguageMapping(".cxx", "c");
4475 updateLanguageMapping(".cpp", "c");
4476 updateLanguageMapping(".c++", "c");
4477 updateLanguageMapping(".cxxm", "c"); // C++20 modules
4478 updateLanguageMapping(".cppm", "c"); // C++20 modules
4479 updateLanguageMapping(".ccm", "c"); // C++20 modules
4480 updateLanguageMapping(".c++m", "c"); // C++20 modules
4481 updateLanguageMapping(".ii", "c");
4482 updateLanguageMapping(".ixx", "c");
4483 updateLanguageMapping(".ipp", "c");
4484 updateLanguageMapping(".i++", "c");
4485 updateLanguageMapping(".inl", "c");
4486 updateLanguageMapping(".h", "c");
4487 updateLanguageMapping(".H", "c");
4488 updateLanguageMapping(".hh", "c");
4489 updateLanguageMapping(".HH", "c");
4490 updateLanguageMapping(".hxx", "c");
4491 updateLanguageMapping(".hpp", "c");
4492 updateLanguageMapping(".h++", "c");
4493 updateLanguageMapping(".idl", "idl");
4494 updateLanguageMapping(".ddl", "idl");
4495 updateLanguageMapping(".odl", "idl");
4496 updateLanguageMapping(".java", "java");
4497 //updateLanguageMapping(".as", "javascript"); // not officially supported
4498 //updateLanguageMapping(".js", "javascript"); // not officially supported
4499 updateLanguageMapping(".cs", "csharp");
4500 updateLanguageMapping(".d", "d");
4501 updateLanguageMapping(".php", "php");
4502 updateLanguageMapping(".php4", "php");
4503 updateLanguageMapping(".php5", "php");
4504 updateLanguageMapping(".inc", "php");
4505 updateLanguageMapping(".phtml", "php");
4506 updateLanguageMapping(".m", "objective-c");
4507 updateLanguageMapping(".M", "objective-c");
4508 updateLanguageMapping(".mm", "c"); // see bug746361
4509 updateLanguageMapping(".py", "python");
4510 updateLanguageMapping(".pyw", "python");
4511 updateLanguageMapping(".f", "fortran");
4512 updateLanguageMapping(".for", "fortran");
4513 updateLanguageMapping(".f90", "fortran");
4514 updateLanguageMapping(".f95", "fortran");
4515 updateLanguageMapping(".f03", "fortran");
4516 updateLanguageMapping(".f08", "fortran");
4517 updateLanguageMapping(".f18", "fortran");
4518 updateLanguageMapping(".vhd", "vhdl");
4519 updateLanguageMapping(".vhdl", "vhdl");
4520 updateLanguageMapping(".ucf", "vhdl");
4521 updateLanguageMapping(".qsf", "vhdl");
4522 updateLanguageMapping(".md", "md");
4523 updateLanguageMapping(".markdown", "md");
4524 updateLanguageMapping(".ice", "slice");
4525 updateLanguageMapping(".l", "lex");
4526 updateLanguageMapping(".doxygen_lex_c", "c"); // this is a placeholder so we can map initializations
4527 // in the lex scanning to cpp
4528}

References initDefaultExtensionMapping(), and updateLanguageMapping().

Referenced by addDirPrefix(), initDefaultExtensionMapping(), and initDoxygen().

◆ inlineArgListToDoc()

DString inlineArgListToDoc ( const ArgumentList & al)

Definition at line 5531 of file util.cpp.

5532{
5533 DString paramDocs;
5534 if (al.hasDocumentation(true))
5535 {
5536 for (const Argument &a : al)
5537 {
5538 if (a.hasDocumentation(true))
5539 {
5540 DString docsWithoutDir = a.docs;
5541 DString direction = extractDirection(docsWithoutDir);
5542 DString name = a.name;
5543 if (name.empty())
5544 {
5545 name = "-";
5546 }
5547 paramDocs+=" \\ilinebr @param"+direction+" "+name+" "+docsWithoutDir;
5548 }
5549 }
5550 }
5551 return paramDocs;
5552}
bool hasDocumentation(bool allowEmptyNames=false) const
Definition arguments.cpp:22
static DString extractDirection(DString &docs)
Strip the direction part from docs and return it as a string in canonical form.
Definition util.cpp:5495

References DString::empty(), extractDirection(), ArgumentList::hasDocumentation(), and inlineArgListToDoc().

Referenced by inlineArgListToDoc(), DocParser::processCopyDoc(), and MemberDefImpl::writeDocumentation().

◆ inlineTemplateArgListToDoc()

DString inlineTemplateArgListToDoc ( const ArgumentList & al)

Definition at line 864 of file util.cpp.

865{
866 DString paramDocs;
868 {
869 for (const Argument &a : al)
870 {
871 if (!a.docs.empty())
872 {
873 if (!a.name.empty())
874 {
875 paramDocs+=" \\ilinebr @tparam "+a.name+" "+a.docs;
876 }
877 else if (!a.type.empty())
878 {
879 DString type = a.type;
880 type.stripPrefix("class ");
881 type.stripPrefix("typename ");
882 type = type.stripWhiteSpace();
883 paramDocs+=" \\ilinebr @tparam "+type+" "+a.docs;
884 }
885 }
886 }
887 }
888 return paramDocs;
889}
bool hasTemplateDocumentation() const
Definition arguments.cpp:30
bool stripPrefix(const DString &prefix)
Definition dstring.h:295

References ArgumentList::hasTemplateDocumentation(), inlineTemplateArgListToDoc(), DString::stripPrefix(), and DString::stripWhiteSpace().

Referenced by inlineTemplateArgListToDoc(), ClassDefImpl::writeDetailedDocumentationBody(), and MemberDefImpl::writeDocumentation().

◆ insertTemplateSpecifierInScope()

DString insertTemplateSpecifierInScope ( const DString & scope,
const DString & templ )

Definition at line 3143 of file util.cpp.

3144{
3145 DString result=scope;
3146 if (!templ.empty() && scope.find('<')==DString::npos)
3147 {
3148 size_t si=0, pi=0;
3149 ClassDef *cd=nullptr;
3150 while (
3151 (si=scope.find("::",pi))!=DString::npos && !getClass(scope.left(si)+templ) &&
3152 ((cd=getClass(scope.left(si)))==nullptr || cd->templateArguments().empty())
3153 )
3154 {
3155 //printf("Tried '%s'\n",qPrint((scope.left(si)+templ)));
3156 pi=si+2;
3157 }
3158 if (si==DString::npos) // not nested => append template specifier
3159 {
3160 result+=templ;
3161 }
3162 else // nested => insert template specifier before after first class name
3163 {
3164 result=scope.left(si) + templ + scope.mid(si);
3165 }
3166 }
3167 //printf("insertTemplateSpecifierInScope('%s','%s')=%s\n",
3168 // qPrint(scope),qPrint(templ),qPrint(result));
3169 return result;
3170}
bool empty() const
Definition arguments.h:99
A abstract class representing of a compound symbol.
Definition classdef.h:104
virtual const ArgumentList & templateArguments() const =0
Returns the template arguments of this class.

References ArgumentList::empty(), DString::empty(), DString::find(), getClass(), insertTemplateSpecifierInScope(), DString::left(), DString::mid(), DString::npos, and ClassDef::templateArguments().

Referenced by DotClassGraph::addClass(), generateXMLForClass(), insertTemplateSpecifierInScope(), DiagramItem::label(), ClassDefImpl::writeInheritanceGraph(), and ClassDefImpl::writeTagFile().

◆ isURL()

bool isURL ( const DString & url)

Checks whether the given url starts with a supported protocol.

Definition at line 5229 of file util.cpp.

5230{
5231 static const std::unordered_set<std::string> schemes = {
5232 "http", "https", "ftp", "ftps", "sftp", "file", "news", "irc", "ircs"
5233 };
5234 DString loc_url = url.stripWhiteSpace();
5235 size_t colonPos = loc_url.find(':');
5236 return colonPos!=DString::npos && schemes.find(loc_url.left(colonPos).str())!=schemes.end();
5237}

References DString::find(), isURL(), DString::left(), DString::npos, DString::str(), and DString::stripWhiteSpace().

Referenced by correctURL(), isURL(), Markdown::Private::processLink(), and recodeString().

◆ leftScopeMatch()

bool leftScopeMatch ( const DString & scope,
const DString & name )

Definition at line 772 of file util.cpp.

773{
774 size_t sl=scope.length();
775 size_t nl=name.length();
776 return (name==scope || // equal
777 (name.left(sl)==scope && // substring
778 nl>sl+1 && name.at(sl)==':' && name.at(sl+1)==':' // scope
779 )
780 );
781}

References DString::at(), DString::left(), leftScopeMatch(), and DString::length().

Referenced by addClassToContext(), addConceptToContext(), buildFunctionList(), leftScopeMatch(), mergeScopes(), pushScope(), and resolveRef().

◆ lineBlock()

int lineBlock ( const DString & text,
const DString & marker )

Returns the line number of the line following the line with the marker.

See also
routine extractBlock

Definition at line 5192 of file util.cpp.

5193{
5194 int result = 1;
5195
5196 // find the character positions of the first marker
5197 size_t m1 = text.find(marker);
5198 if (m1==DString::npos) return result;
5199
5200 // find start line positions for the markers
5201 bool found=false;
5202 size_t p=0, i=0;
5203 while (!found && (i=text.find('\n',p))!=DString::npos)
5204 {
5205 found = (p<=m1 && m1<i); // found the line with the start marker
5206 p=i+1;
5207 result++;
5208 }
5209 return result;
5210}

References DString::find(), lineBlock(), and DString::npos.

Referenced by lineBlock(), readIncludeFile(), and recodeString().

◆ linkToText()

DString linkToText ( SrcLangExt lang,
const DString & link,
bool ignoreDots )

Definition at line 2332 of file util.cpp.

2333{
2334 //bool optimizeOutputJava = Config_getBool(OPTIMIZE_OUTPUT_JAVA);
2335 DString result=link;
2336 if (!result.empty())
2337 {
2338 // replace # by ::
2339 result=substitute(result,"#","::");
2340 // replace . by ::
2341 if (!ignoreDots && result.find('<')==DString::npos) result=substitute(result,".","::",3);
2342 // strip leading :: prefix if present
2343 if (result.at(0)==':' && result.at(1)==':')
2344 {
2345 result=result.mid(2);
2346 }
2348 if (sep!="::")
2349 {
2350 result=substitute(result,"::",sep);
2351 }
2352 }
2353 //printf("linkToText(%s,lang=%d)=%s\n",qPrint(link),lang,qPrint(result));
2354 return result;
2355}
DString substitute(const DString &s, const DString &src, const DString &dst)
substitute all occurrences of src in s by dst
Definition dstring.cpp:480
DString getLanguageSpecificSeparator(SrcLangExt lang, bool classScope)
Definition util.cpp:5212

References DString::at(), DString::empty(), DString::find(), getLanguageSpecificSeparator(), linkToText(), DString::mid(), DString::npos, and substitute().

Referenced by DotCallGraph::buildGraph(), DocRef::DocRef(), DotCallGraph::DotCallGraph(), DocParser::handleLinkedWord(), and linkToText().

◆ mainPageHasTitle()

bool mainPageHasTitle ( )

Definition at line 5625 of file util.cpp.

5626{
5627 return Doxygen::mainPage!=nullptr && Doxygen::mainPage->hasTitle();
5628}
static std::unique_ptr< PageDef > mainPage
Definition doxygen.h:100

References Doxygen::mainPage, and mainPageHasTitle().

Referenced by generateJSNavTree(), generateSqlite3ForPage(), generateXMLForPage(), mainPageHasTitle(), and processMarkup().

◆ makeBaseName()

◆ mangleCSharpGenericName()

DString mangleCSharpGenericName ( const DString & name)

Definition at line 6116 of file util.cpp.

6117{
6118 if (size_t idx = name.find('<'); idx!=DString::npos)
6119 {
6120 return name.left(idx)+"-"+DString().setNum(name.contains(",")+1)+"-g";
6121 }
6122 return name;
6123}
DString & setNum(short n)
Definition dstring.h:541
int contains(char c, bool cs=true) const
Definition dstring.cpp:80

References DString::contains(), DString::DString(), DString::find(), DString::left(), mangleCSharpGenericName(), DString::npos, and DString::setNum().

Referenced by addClassToContext(), addEnumValuesToEnums(), addVariable(), buildFunctionList(), extractClassName(), findClassRelation(), findEnums(), mangleCSharpGenericName(), processMarkup(), SymbolResolver::resolveClass(), resolveLink(), and resolveRef().

◆ matchArguments2()

bool matchArguments2 ( const Definition * srcScope,
const FileDef * srcFileScope,
const DString & srcReturnType,
const ArgumentList * srcAl,
const Definition * dstScope,
const FileDef * dstFileScope,
const DString & dstReturnType,
const ArgumentList * dstAl,
bool checkCV,
SrcLangExt lang )

Compares two parameter lists srcAl and dstAl and returns true if they match.

Definition at line 1656 of file util.cpp.

1659{
1660 ASSERT(srcScope!=nullptr && dstScope!=nullptr);
1661
1662 AUTO_TRACE("srcScope='{}' dstScope='{}' srcArgs='{}' dstArgs='{}' checkCV={} lang={}",
1663 srcScope->name(),dstScope->name(),srcAl?argListToString(*srcAl):"",dstAl?argListToString(*dstAl):"",checkCV,lang);
1664
1665 if (srcAl==nullptr || dstAl==nullptr)
1666 {
1667 bool match = srcAl==dstAl;
1668 if (match)
1669 {
1670 MATCH
1671 return true;
1672 }
1673 else
1674 {
1675 NOMATCH
1676 return false;
1677 }
1678 }
1679
1680 // handle special case with void argument
1681 if ( srcAl->empty() && dstAl->size()==1 && dstAl->front().type=="void" )
1682 { // special case for finding match between func() and func(void)
1683 Argument a;
1684 a.type = "void";
1685 const_cast<ArgumentList*>(srcAl)->push_back(a);
1686 MATCH
1687 return true;
1688 }
1689 if ( dstAl->empty() && srcAl->size()==1 && srcAl->front().type=="void" )
1690 { // special case for finding match between func(void) and func()
1691 Argument a;
1692 a.type = "void";
1693 const_cast<ArgumentList*>(dstAl)->push_back(a);
1694 MATCH
1695 return true;
1696 }
1697
1698 if (srcAl->size() != dstAl->size())
1699 {
1700 NOMATCH
1701 return false; // different number of arguments -> no match
1702 }
1703
1704 if (checkCV)
1705 {
1706 if (srcAl->constSpecifier() != dstAl->constSpecifier())
1707 {
1708 NOMATCH
1709 return false; // one member is const, the other not -> no match
1710 }
1711 if (srcAl->volatileSpecifier() != dstAl->volatileSpecifier())
1712 {
1713 NOMATCH
1714 return false; // one member is volatile, the other not -> no match
1715 }
1716 }
1717
1718 if (srcAl->refQualifier() != dstAl->refQualifier())
1719 {
1720 NOMATCH
1721 return false; // one member is has a different ref-qualifier than the other
1722 }
1723
1724 if (srcReturnType=="auto" && dstReturnType=="auto" && srcAl->trailingReturnType()!=dstAl->trailingReturnType())
1725 {
1726 NOMATCH
1727 return false; // one member is has a different return type than the other
1728 }
1729
1730 // so far the argument list could match, so we need to compare the types of
1731 // all arguments.
1732 auto srcIt = srcAl->begin();
1733 auto dstIt = dstAl->begin();
1734 for (;srcIt!=srcAl->end() && dstIt!=dstAl->end();++srcIt,++dstIt)
1735 {
1736 Argument &srcA = const_cast<Argument&>(*srcIt);
1737 Argument &dstA = const_cast<Argument&>(*dstIt);
1738 if (!matchArgument2(srcScope,srcFileScope,srcA,
1739 dstScope,dstFileScope,dstA,
1740 lang)
1741 )
1742 {
1743 NOMATCH
1744 return false;
1745 }
1746 }
1747 MATCH
1748 return true; // all arguments match
1749}
This class represents an function or template argument list.
Definition arguments.h:65
Argument & front()
Definition arguments.h:105
size_t size() const
Definition arguments.h:100
#define MATCH
Definition util.cpp:1555
DString argListToString(const ArgumentList &al, bool useCanonicalType, bool showDefVals)
Definition util.cpp:891
#define NOMATCH
Definition util.cpp:1556
static bool matchArgument2(const Definition *srcScope, const FileDef *srcFileScope, Argument &srcA, const Definition *dstScope, const FileDef *dstFileScope, Argument &dstA, SrcLangExt lang)
Definition util.cpp:1590

References argListToString(), ASSERT, AUTO_TRACE, ArgumentList::begin(), ArgumentList::constSpecifier(), ArgumentList::empty(), ArgumentList::end(), ArgumentList::front(), MATCH, matchArgument2(), matchArguments2(), Definition::name(), NOMATCH, ArgumentList::refQualifier(), ArgumentList::size(), ArgumentList::trailingReturnType(), Argument::type, and ArgumentList::volatileSpecifier().

Referenced by addMemberDocs(), addMemberFunction(), buildFunctionList(), combineDeclarationAndDefinition(), computeMemberRelationsForBaseClass(), ClassDefImpl::containsOverload(), findFriends(), findGlobalMember(), findMember(), SymbolResolver::Private::getResolvedSymbol(), GroupDefImpl::insertMember(), matchArguments2(), matchCanonicalTypes(), ClassDefImpl::mergeMembersFromBaseClasses(), transferFunctionReferences(), and transferRelatedFunctionDocumentation().

◆ matchTemplateArguments()

bool matchTemplateArguments ( const ArgumentList & srcAl,
const ArgumentList & dstAl )

Returns true if the template parameter lists srcAl and dstAl match. The lists are considered to match if they have the same number of parameters and each matching parameter in srcAl and dstAl has the same constraints (or at least one parameter has no constraints).

Definition at line 1900 of file util.cpp.

1901{
1902 AUTO_TRACE("srcAl={} dstAl={}",argListToString(srcAl),argListToString(dstAl));
1903 if (srcAl.size()!=dstAl.size()) // different number of template parameters -> overload
1904 {
1905 AUTO_TRACE_EXIT("different number of parameters");
1906 return false;
1907 }
1908 auto isUnconstraintTemplate = [](const DString &type)
1909 {
1910 return type=="typename" || type=="class" || type.startsWith("typename ") || type.startsWith("class ");
1911 };
1912 auto srcIt = srcAl.begin();
1913 auto dstIt = dstAl.begin();
1914 while (srcIt!=srcAl.end() && dstIt!=dstAl.end())
1915 {
1916 const Argument &srcA = *srcIt;
1917 const Argument &dstA = *dstIt;
1918 if ((!isUnconstraintTemplate(srcA.type) || !isUnconstraintTemplate(dstA.type)) && srcA.type!=dstA.type) // different constraints -> overload
1919 {
1920 AUTO_TRACE_EXIT("different constraints");
1921 return false;
1922 }
1923 ++srcIt;
1924 ++dstIt;
1925 }
1926 AUTO_TRACE_EXIT("same");
1927 // no overload with respect to the template parameters
1928 return true;
1929}

References argListToString(), AUTO_TRACE, AUTO_TRACE_EXIT, ArgumentList::begin(), ArgumentList::end(), matchTemplateArguments(), ArgumentList::size(), and Argument::type.

Referenced by buildFunctionList(), and matchTemplateArguments().

◆ mergeArguments()

void mergeArguments ( ArgumentList & srcAl,
ArgumentList & dstAl,
bool forceNameOverwrite = false )

Merges the information of two parameter lists (typically a declaration and a definition). Missing information is added to either list. The name of parameter of srcAl is only overwritten if forceNameOverwrite is true.

Definition at line 1756 of file util.cpp.

1757{
1758 AUTO_TRACE("srcAl='{}',dstAl='{}',forceNameOverwrite={}",
1759 qPrint(argListToString(srcAl)),qPrint(argListToString(dstAl)),forceNameOverwrite);
1760
1761 if (srcAl.size()!=dstAl.size())
1762 {
1763 return; // invalid argument lists -> do not merge
1764 }
1765
1766 auto srcIt=srcAl.begin();
1767 auto dstIt=dstAl.begin();
1768 while (srcIt!=srcAl.end() && dstIt!=dstAl.end())
1769 {
1770 Argument &srcA = *srcIt;
1771 Argument &dstA = *dstIt;
1772
1773 AUTO_TRACE_ADD("before merge: src=[type='{}',name='{}',def='{}'] dst=[type='{}',name='{}',def='{}']",
1774 srcA.type,srcA.name,srcA.defval,
1775 dstA.type,dstA.name,dstA.defval);
1776 if (srcA.defval.empty() && !dstA.defval.empty())
1777 {
1778 //printf("Defval changing '%s'->'%s'\n",qPrint(srcA.defval),qPrint(dstA.defval));
1779 srcA.defval=dstA.defval;
1780 }
1781 else if (!srcA.defval.empty() && dstA.defval.empty())
1782 {
1783 //printf("Defval changing '%s'->'%s'\n",qPrint(dstA.defval),qPrint(srcA.defval));
1784 dstA.defval=srcA.defval;
1785 }
1786
1787 // fix wrongly detected const or volatile specifiers before merging.
1788 // example: "const A *const" is detected as type="const A *" name="const"
1789 if (srcA.name=="const" || srcA.name=="volatile")
1790 {
1791 srcA.type+=" "+srcA.name;
1792 srcA.name.clear();
1793 }
1794 if (dstA.name=="const" || dstA.name=="volatile")
1795 {
1796 dstA.type+=" "+dstA.name;
1797 dstA.name.clear();
1798 }
1799
1800 if (srcA.type==dstA.type)
1801 {
1802 //printf("1. merging %s:%s <-> %s:%s\n",qPrint(srcA.type),qPrint(srcA.name),qPrint(dstA.type),qPrint(dstA.name));
1803 if (srcA.name.empty() && !dstA.name.empty())
1804 {
1805 //printf("type: '%s':='%s'\n",qPrint(srcA.type),qPrint(dstA.type));
1806 //printf("name: '%s':='%s'\n",qPrint(srcA.name),qPrint(dstA.name));
1807 srcA.type = dstA.type;
1808 srcA.name = dstA.name;
1809 }
1810 else if (!srcA.name.empty() && dstA.name.empty())
1811 {
1812 //printf("type: '%s':='%s'\n",qPrint(dstA.type),qPrint(srcA.type));
1813 //printf("name: '%s':='%s'\n",qPrint(dstA.name),qPrint(srcA.name));
1814 dstA.type = srcA.type;
1815 dstA.name = srcA.name;
1816 }
1817 else if (!srcA.name.empty() && !dstA.name.empty())
1818 {
1819 //printf("srcA.name=%s dstA.name=%s\n",qPrint(srcA.name),qPrint(dstA.name));
1820 if (forceNameOverwrite)
1821 {
1822 srcA.name = dstA.name;
1823 }
1824 else
1825 {
1826 if (srcA.docs.empty() && !dstA.docs.empty())
1827 {
1828 srcA.name = dstA.name;
1829 }
1830 else if (!srcA.docs.empty() && dstA.docs.empty())
1831 {
1832 dstA.name = srcA.name;
1833 }
1834 }
1835 }
1836 }
1837 else
1838 {
1839 //printf("2. merging '%s':'%s' <-> '%s':'%s'\n",qPrint(srcA.type),qPrint(srcA.name),qPrint(dstA.type),qPrint(dstA.name));
1840 srcA.type=srcA.type.stripWhiteSpace();
1841 dstA.type=dstA.type.stripWhiteSpace();
1842 if (srcA.type+" "+srcA.name==dstA.type) // "unsigned long:int" <-> "unsigned long int:bla"
1843 {
1844 srcA.type+=" "+srcA.name;
1845 srcA.name=dstA.name;
1846 }
1847 else if (dstA.type+" "+dstA.name==srcA.type) // "unsigned long int bla" <-> "unsigned long int"
1848 {
1849 dstA.type+=" "+dstA.name;
1850 dstA.name=srcA.name;
1851 }
1852 else if (srcA.name.empty() && !dstA.name.empty())
1853 {
1854 srcA.name = dstA.name;
1855 }
1856 else if (dstA.name.empty() && !srcA.name.empty())
1857 {
1858 dstA.name = srcA.name;
1859 }
1860 }
1861 size_t i1=srcA.type.find("::"),
1862 i2=dstA.type.find("::"),
1863 j1=srcA.type.length()-i1-2,
1864 j2=dstA.type.length()-i2-2;
1865 if (i1!=DString::npos && i2==DString::npos && srcA.type.right(j1)==dstA.type)
1866 {
1867 //printf("type: '%s':='%s'\n",qPrint(dstA.type),qPrint(srcA.type));
1868 //printf("name: '%s':='%s'\n",qPrint(dstA.name),qPrint(srcA.name));
1869 dstA.type = srcA.type.left(i1+2)+dstA.type;
1870 dstA.name = srcA.name;
1871 }
1872 else if (i1==DString::npos && i2!=DString::npos && dstA.type.right(j2)==srcA.type)
1873 {
1874 //printf("type: '%s':='%s'\n",qPrint(srcA.type),qPrint(dstA.type));
1875 //printf("name: '%s':='%s'\n",qPrint(dstA.name),qPrint(srcA.name));
1876 srcA.type = dstA.type.left(i2+2)+srcA.type;
1877 srcA.name = dstA.name;
1878 }
1879 if (srcA.docs.empty() && !dstA.docs.empty())
1880 {
1881 srcA.docs = dstA.docs;
1882 }
1883 else if (dstA.docs.empty() && !srcA.docs.empty())
1884 {
1885 dstA.docs = srcA.docs;
1886 }
1887 //printf("Merge argument '%s|%s' '%s|%s'\n",
1888 // qPrint(srcA.type), qPrint(srcA.name),
1889 // qPrint(dstA.type), qPrint(dstA.name));
1890 ++srcIt;
1891 ++dstIt;
1892 AUTO_TRACE_ADD("after merge: src=[type='{}',name='{}',def='{}'] dst=[type='{}',name='{}',def='{}']",
1893 srcA.type,srcA.name,srcA.defval,
1894 dstA.type,dstA.name,dstA.defval);
1895 }
1896}
#define AUTO_TRACE_ADD(...)
Definition docnode.cpp:51
DString docs
Definition arguments.h:47

References argListToString(), AUTO_TRACE, AUTO_TRACE_ADD, ArgumentList::begin(), DString::clear(), Argument::defval, Argument::docs, DString::empty(), ArgumentList::end(), DString::find(), DString::left(), DString::length(), mergeArguments(), Argument::name, DString::npos, qPrint(), DString::right(), ArgumentList::size(), DString::stripWhiteSpace(), and Argument::type.

Referenced by addMemberDocs(), buildFunctionList(), findFriends(), and mergeArguments().

◆ mergeMemberOverrideOptions()

void mergeMemberOverrideOptions ( MemberDefMutable * md1,
MemberDefMutable * md2 )

Definition at line 6064 of file util.cpp.

6065{
6066 if (Config_getBool(CALL_GRAPH) !=md1->hasCallGraph()) md2->overrideCallGraph(md1->hasCallGraph());
6067 if (Config_getBool(CALLER_GRAPH)!=md1->hasCallerGraph()) md2->overrideCallerGraph(md1->hasCallerGraph());
6068 if (Config_getBool(CALL_GRAPH) !=md2->hasCallGraph()) md1->overrideCallGraph( md2->hasCallGraph());
6069 if (Config_getBool(CALLER_GRAPH)!=md2->hasCallerGraph()) md1->overrideCallerGraph(md2->hasCallerGraph());
6070
6071 if (Config_getBool(SHOW_ENUM_VALUES) !=md1->hasEnumValues()) md2->overrideEnumValues(md1->hasEnumValues());
6072 if (Config_getBool(SHOW_ENUM_VALUES) !=md2->hasEnumValues()) md1->overrideEnumValues( md2->hasEnumValues());
6073
6074 if (Config_getBool(REFERENCED_BY_RELATION)!=md1->hasReferencedByRelation()) md2->overrideReferencedByRelation(md1->hasReferencedByRelation());
6075 if (Config_getBool(REFERENCES_RELATION) !=md1->hasReferencesRelation()) md2->overrideReferencesRelation(md1->hasReferencesRelation());
6076 if (Config_getBool(REFERENCED_BY_RELATION)!=md2->hasReferencedByRelation()) md1->overrideReferencedByRelation(md2->hasReferencedByRelation());
6077 if (Config_getBool(REFERENCES_RELATION) !=md2->hasReferencesRelation()) md1->overrideReferencesRelation(md2->hasReferencesRelation());
6078
6079 if (Config_getBool(INLINE_SOURCES)!=md1->hasInlineSource()) md2->overrideInlineSource(md1->hasInlineSource());
6080 if (Config_getBool(INLINE_SOURCES)!=md2->hasInlineSource()) md1->overrideInlineSource(md2->hasInlineSource());
6081}
virtual bool hasReferencesRelation() const =0
virtual bool hasCallGraph() const =0
virtual bool hasInlineSource() const =0
virtual bool hasEnumValues() const =0
virtual bool hasCallerGraph() const =0
virtual bool hasReferencedByRelation() const =0
virtual void overrideReferencesRelation(bool e)=0
virtual void overrideReferencedByRelation(bool e)=0
virtual void overrideCallGraph(bool e)=0
virtual void overrideInlineSource(bool e)=0
virtual void overrideEnumValues(bool e)=0
virtual void overrideCallerGraph(bool e)=0

References Config_getBool, MemberDef::hasCallerGraph(), MemberDef::hasCallGraph(), MemberDef::hasEnumValues(), MemberDef::hasInlineSource(), MemberDef::hasReferencedByRelation(), MemberDef::hasReferencesRelation(), mergeMemberOverrideOptions(), MemberDefMutable::overrideCallerGraph(), MemberDefMutable::overrideCallGraph(), MemberDefMutable::overrideEnumValues(), MemberDefMutable::overrideInlineSource(), MemberDefMutable::overrideReferencedByRelation(), and MemberDefMutable::overrideReferencesRelation().

Referenced by combineDeclarationAndDefinition(), findFriends(), mergeMemberOverrideOptions(), and processMarkup().

◆ mergeScopes()

DString mergeScopes ( const DString & leftScope,
const DString & rightScope )

Merges two scope parts together. The parts may (partially) overlap. Example1: A::B and B::C will result in A::B::C
Example2: A and B will be A::B
Example3: A::B and B will be A::B

Parameters
leftScopethe left hand part of the scope.
rightScopethe right hand part of the scope.
Returns
the merged scope.

Definition at line 3933 of file util.cpp.

3934{
3935 AUTO_TRACE("leftScope='{}' rightScope='{}'",leftScope,rightScope);
3936 // case leftScope=="A" rightScope=="A::B" => result = "A::B"
3937 if (leftScopeMatch(leftScope,rightScope))
3938 {
3939 AUTO_TRACE_EXIT("case1={}",rightScope);
3940 return rightScope;
3941 }
3942 DString result;
3943 size_t i=0,p=leftScope.length();
3944
3945 // case leftScope=="A::B" rightScope=="B::C" => result = "A::B::C"
3946 // case leftScope=="A::B" rightScope=="B" => result = "A::B"
3947 bool found=false;
3948 while ((i=leftScope.rfind("::",p))!=DString::npos && i>0)
3949 {
3950 if (leftScopeMatch(rightScope,leftScope.mid(i+2)))
3951 {
3952 result = leftScope.left(i+2)+rightScope;
3953 found=true;
3954 }
3955 p=i-1;
3956 }
3957 if (found)
3958 {
3959 AUTO_TRACE_EXIT("case2={}",result);
3960 return result;
3961 }
3962
3963 // case leftScope=="A" rightScope=="B" => result = "A::B"
3964 result=leftScope;
3965 if (!result.empty() && !rightScope.empty()) result+="::";
3966 result+=rightScope;
3967 AUTO_TRACE_EXIT("case3={}",result);
3968 return result;
3969}
bool leftScopeMatch(const DString &scope, const DString &name)
Definition util.cpp:772

References AUTO_TRACE, AUTO_TRACE_EXIT, DString::empty(), DString::left(), leftScopeMatch(), DString::length(), mergeScopes(), DString::mid(), DString::npos, and DString::rfind().

Referenced by addEnumValuesToEnums(), addVariable(), findEnums(), findMember(), mergeScopes(), and stripTemplateSpecifiersFromScope().

◆ normalizeNonTemplateArgumentsInString()

DString normalizeNonTemplateArgumentsInString ( const DString & name,
const Definition * context,
const ArgumentList & formalArgs )

Returns a representation of name where all known types have been normalized to their canonical form. The normalization is done in the context of context and using the formal arguments in formalArgs.

Definition at line 3645 of file util.cpp.

3649{
3650 // skip until <
3651 size_t p=name.find('<');
3652 if (p==DString::npos) return name;
3653 p++;
3654 DString result = name.left(p);
3655
3656 std::string s = name.mid(p).str();
3657 static const reg::Ex re(R"([\a:][\w:]*)");
3658 reg::Iterator it(s,re);
3660 size_t pi=0;
3661 // for each identifier in the template part (e.g. B<T> -> T)
3662 for (; it!=end ; ++it)
3663 {
3664 const auto &match = *it;
3665 size_t i = match.position();
3666 size_t l = match.length();
3667 result += s.substr(pi,i-pi);
3668 DString n(match.str());
3669 bool found=false;
3670 for (const Argument &formArg : formalArgs)
3671 {
3672 if (formArg.name == n)
3673 {
3674 found=true;
3675 break;
3676 }
3677 }
3678 if (!found)
3679 {
3680 // try to resolve the type
3681 SymbolResolver resolver;
3682 const ClassDef *cd = resolver.resolveClass(context,n);
3683 if (cd)
3684 {
3685 result+=cd->name();
3686 }
3687 else
3688 {
3689 result+=n;
3690 }
3691 }
3692 else
3693 {
3694 result+=n;
3695 }
3696 pi=i+l;
3697 }
3698 result+=s.substr(pi);
3699 //printf("normalizeNonTemplateArgumentInString(%s)=%s\n",qPrint(name),qPrint(result));
3700 return removeRedundantWhiteSpace(result);
3701}
DString substr(size_t pos=0, size_t count=npos) const
Returns a substring of length count starting at pos.
Definition dstring.h:228
const ClassDef * resolveClass(const Definition *scope, const DString &name, bool maybeUnlinkable=false, bool mayBeHidden=false)
Find the class definition matching name within the scope set.

References end(), DString::find(), DString::left(), DString::mid(), Definition::name(), normalizeNonTemplateArgumentsInString(), DString::npos, removeRedundantWhiteSpace(), SymbolResolver::resolveClass(), DString::str(), and DString::substr().

Referenced by findUsedClassesForClass(), and normalizeNonTemplateArgumentsInString().

◆ openOutputFile()

bool openOutputFile ( const DString & outFile,
std::ofstream & f )

Definition at line 5637 of file util.cpp.

5638{
5639 assert(!f.is_open());
5640 bool fileOpened=false;
5641 bool writeToStdout=outFile=="-";
5642 if (writeToStdout) // write to stdout
5643 {
5644 f.basic_ios<char>::rdbuf(std::cout.rdbuf());
5645 fileOpened = true;
5646 }
5647 else // write to file
5648 {
5649 FileInfo fi(outFile.str());
5650 if (fi.exists()) // create a backup
5651 {
5652 Dir dir;
5653 FileInfo backup(fi.filePath()+".bak");
5654 if (backup.exists()) // remove existing backup
5655 dir.remove(backup.filePath());
5656 dir.rename(fi.filePath(),fi.filePath()+".bak");
5657 }
5658 f = Portable::openOutputStream(outFile);
5659 fileOpened = f.is_open();
5660 }
5661 return fileOpened;
5662}
Class representing a directory in the file system.
Definition dir.h:75
bool remove(const std::string &path, bool acceptsAbsPath=true) const
Definition dir.cpp:314
bool rename(const std::string &orgName, const std::string &newName, bool acceptsAbsPath=true) const
Definition dir.cpp:321
std::ofstream openOutputStream(const DString &name, bool append=false)
Definition portable.cpp:648

References FileInfo::exists(), FileInfo::filePath(), openOutputFile(), Portable::openOutputStream(), Dir::remove(), Dir::rename(), and DString::str().

Referenced by compareDoxyfile(), generateConfigFile(), openOutputFile(), processMarkup(), readConfiguration(), and writeDefaultLayoutFile().

◆ parseCommentAsHtml()

DString parseCommentAsHtml ( const Definition * scope,
const MemberDef * member,
const DString & doc,
const DString & fileName,
int lineNr )

Definition at line 4749 of file util.cpp.

4750{
4751 std::lock_guard lock(g_docCacheMutex);
4752 auto it = g_docCache.find(doc.str());
4753 if (it != g_docCache.end())
4754 {
4755 //printf("Cache: [%s]->[%s]\n",qPrint(doc),qPrint(it->second));
4756 return it->second;
4757 }
4758 auto parser { createDocParser() };
4759 auto ast { validatingParseTitle(*parser.get(),fileName,lineNr,doc) };
4760 auto astImpl = dynamic_cast<const DocNodeAST*>(ast.get());
4761 DString result;
4762 if (astImpl)
4763 {
4764 TextStream t;
4765 OutputCodeList codeList;
4766 codeList.add<HtmlCodeGenerator>(&t);
4767 HtmlDocVisitor visitor(t,codeList,scope,fileName);
4768 std::visit(visitor,astImpl->root);
4769 result = t.str();
4770 }
4771 else // fallback, should not happen
4772 {
4773 result = filterTitle(doc);
4774 }
4775 //printf("Conversion: [%s]->[%s]\n",qPrint(doc),qPrint(result));
4776 g_docCache.insert(std::make_pair(doc.str(),result));
4777 return result;
4778}
Class representing the abstract syntax tree of a documentation block.
Definition docnode.h:1471
Generator for HTML code fragments.
Definition htmlgen.h:26
Concrete visitor implementation for HTML output.
Class representing a list of different code generators.
Definition outputlist.h:166
void add(OutputCodeIntfPtr &&p)
Definition outputlist.h:196
Text streaming class that buffers data.
Definition textstream.h:36
std::string str() const
Return the contents of the buffer as a std::string object.
Definition textstream.h:232
IDocNodeASTPtr validatingParseTitle(IDocParser &parserIntf, const DString &fileName, int lineNr, const DString &input)
IDocParserPtr createDocParser()
factory function to create a parser
Definition docparser.cpp:56
DString filterTitle(const DString &title)
Definition util.cpp:4954
static std::unordered_map< std::string, DString > g_docCache
Definition util.cpp:4747
static std::mutex g_docCacheMutex
Definition util.cpp:4746

References OutputCodeList::add(), createDocParser(), filterTitle(), g_docCache, g_docCacheMutex, parseCommentAsHtml(), DString::str(), TextStream::str(), and validatingParseTitle().

Referenced by addDirPrefix(), PageDefImpl::addSectionsToIndex(), SearchTerm::makeTitle(), DefinitionImpl::navigationPathAsString(), parseCommentAsHtml(), and writeJavasScriptSearchDataPage().

◆ parseCommentAsText()

DString parseCommentAsText ( const Definition * scope,
const MemberDef * member,
const DString & doc,
const DString & fileName,
int lineNr )

Definition at line 4693 of file util.cpp.

4695{
4696 if (doc.empty()) return "";
4697 //printf("parseCommentAsText(%s)\n",qPrint(doc));
4698 TextStream t;
4699 auto parser { createDocParser() };
4700 auto ast { validatingParseDoc(*parser.get(),
4701 fileName,
4702 lineNr,
4703 scope,
4704 md,
4705 doc,
4706 DocOptions()
4707 .setAutolinkSupport(false))
4708 };
4709 auto astImpl = dynamic_cast<const DocNodeAST*>(ast.get());
4710 if (astImpl)
4711 {
4712 TextDocVisitor visitor(t);
4713 std::visit(visitor,astImpl->root);
4714 }
4716 int i=0;
4717 int charCnt=0;
4718 int l=static_cast<int>(result.length());
4719 while ((i=nextUTF8CharPosition(result,l,i))<l)
4720 {
4721 charCnt++;
4722 if (charCnt>=80) break;
4723 }
4724 if (charCnt>=80) // try to truncate the string
4725 {
4726 while ((i=nextUTF8CharPosition(result,l,i))<l && charCnt<100)
4727 {
4728 charCnt++;
4729 if (result.at(i)==',' ||
4730 result.at(i)=='.' ||
4731 result.at(i)=='!' ||
4732 result.at(i)=='?' ||
4733 result.at(i)=='}') // good for UTF-16 characters and } otherwise also a good point to stop the string
4734 {
4735 i++; // we want to be "behind" last inspected character
4736 break;
4737 }
4738 }
4739 }
4740 if ( i < l) result=result.left(i)+"...";
4741 return result.data();
4742}
Concrete visitor implementation for TEXT output.
IDocNodeASTPtr validatingParseDoc(IDocParser &parserIntf, const DString &fileName, int startLine, const Definition *ctx, const MemberDef *md, const DString &input, const DocOptions &options)
Helper class to pass options when calling OutputList::generateDoc().
Definition docoptions.h:24
static int nextUTF8CharPosition(const DString &utf8Str, uint32_t len, uint32_t startPos)
Definition util.cpp:4649

References DString::at(), HtmlEntityMapper::convertCharEntitiesToUTF8(), createDocParser(), DString::data(), DString::empty(), HtmlEntityMapper::instance(), DString::left(), DString::length(), nextUTF8CharPosition(), parseCommentAsText(), TextStream::str(), DString::stripWhiteSpace(), and validatingParseDoc().

Referenced by addDirPrefix(), RequirementManager::addRequirement(), PageDefImpl::addSectionsToIndex(), DefinitionImpl::computeTooltip(), parseCommentAsText(), GroupDefImpl::setGroupTitleLocal(), PageDefImpl::setTitle(), and RequirementManager::writeRef().

◆ patternMatch()

bool patternMatch ( const FileInfo & fi,
const StringVector & patList )

Definition at line 5028 of file util.cpp.

5029{
5030 std::string elem;
5031 auto getter = [](std::string s) -> DString { return s; };
5032 return genericPatternMatch(fi,patList,elem,getter);
5033}

References genericPatternMatch(), and patternMatch().

Referenced by checkAndOpenFile(), patternMatch(), readDir(), and recodeString().

◆ processMarkup()

◆ projectLogoFile()

DString projectLogoFile ( )

Definition at line 2647 of file util.cpp.

2648{
2649 DString projectLogo = Config_getString(PROJECT_LOGO);
2650 if (!projectLogo.empty())
2651 {
2652 // check for optional width= and height= specifier
2653 if (size_t wi = projectLogo.find(" width="); wi!=DString::npos) // and strip them
2654 {
2655 projectLogo = projectLogo.left(wi);
2656 }
2657 if (size_t hi = projectLogo.find(" height="); hi!=DString::npos)
2658 {
2659 projectLogo = projectLogo.left(hi);
2660 }
2661 }
2662 //printf("projectlogo='%s'\n",qPrint(projectLogo));
2663 return projectLogo;
2664}

References Config_getString, DString::empty(), DString::find(), DString::left(), DString::npos, and projectLogoFile().

Referenced by copyLogo(), processMarkup(), projectLogoFile(), substituteHtmlKeywords(), and substituteLatexKeywords().

◆ projectLogoSize()

DString projectLogoSize ( )

Definition at line 2666 of file util.cpp.

2667{
2668 DString sizeVal;
2669 DString projectLogo = Config_getString(PROJECT_LOGO);
2670 if (!projectLogo.empty())
2671 {
2672 auto extractDimension = [&projectLogo](const char *startMarker,size_t startPos,size_t endPos) -> DString
2673 {
2674 DString result = projectLogo.mid(startPos,endPos-startPos).stripWhiteSpace().quoted();
2675 if (result.length()>=2 && result.at(0)!='"' && result.at(result.length()-1)!='"')
2676 {
2677 result="\""+result+"\"";
2678 }
2679 result.prepend(startMarker);
2680 return result;
2681 };
2682 // check for optional width= and height= specifier
2683 size_t wi = projectLogo.find(" width=");
2684 size_t hi = projectLogo.find(" height=");
2685 if (wi!=DString::npos && hi!=DString::npos)
2686 {
2687 if (wi<hi) // "... width=x height=y..."
2688 {
2689 sizeVal = extractDimension(" width=", wi+7, hi) + " "
2690 + extractDimension(" height=", hi+8, projectLogo.length());
2691 }
2692 else // "... height=y width=x..."
2693 {
2694 sizeVal = extractDimension(" height=", hi+8, wi) + " "
2695 + extractDimension(" width=", wi+7, projectLogo.length());
2696 }
2697 }
2698 else if (wi!=DString::npos) // ... width=x..."
2699 {
2700 sizeVal = extractDimension(" width=", wi+7, projectLogo.length());
2701 }
2702 else if (hi!=DString::npos) // ... height=x..."
2703 {
2704 sizeVal = extractDimension(" height=", hi+8, projectLogo.length());
2705 }
2706 }
2707 //printf("projectsize='%s'\n",qPrint(sizeVal));
2708 return sizeVal;
2709}
DString quoted() const
Definition dstring.h:357

References DString::at(), Config_getString, DString::empty(), DString::find(), DString::length(), DString::mid(), DString::npos, DString::prepend(), projectLogoSize(), DString::quoted(), and DString::stripWhiteSpace().

Referenced by processMarkup(), projectLogoSize(), substituteHtmlKeywords(), and substituteLatexKeywords().

◆ protectionLevelVisible()

bool protectionLevelVisible ( Protection prot)

Definition at line 5254 of file util.cpp.

5255{
5256 bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
5257 bool extractPackage = Config_getBool(EXTRACT_PACKAGE);
5258
5259 return (prot!=Protection::Private && prot!=Protection::Package) ||
5260 (prot==Protection::Private && extractPrivate) ||
5261 (prot==Protection::Package && extractPackage);
5262}

References Config_getBool, and protectionLevelVisible().

Referenced by MemberDefImpl::_computeLinkableInProject(), addClassAndNestedClasses(), computeClassRelations(), MemberDefImpl::hasDetailedDescription(), ClassDefImpl::internalInsertMember(), MemberDefImpl::isBriefSectionVisible(), ClassDefImpl::isLinkableInProject(), ClassDefImpl::isVisibleInHierarchy(), processMarkup(), protectionLevelVisible(), MemberDefImpl::warnIfUndocumented(), MemberDefImpl::writeDeclaration(), ClassDefImpl::writeDocumentationForInnerClasses(), ClassDefImpl::writeMemberList(), and ClassDefImpl::writeTagFile().

◆ readInputFile()

bool readInputFile ( const DString & fileName,
std::string & contents,
bool filter = true,
bool isSourceCode = false )

read a file name fileName and optionally filter and transcode it

Definition at line 4874 of file util.cpp.

4875{
4876 // try to open file
4877 FileInfo fi(fileName.str());
4878 if (!fi.exists()) return false;
4879 DString filterName = getFileFilter(fileName,isSourceCode);
4880 if (filterName.empty() || !filter)
4881 {
4882 std::ifstream f = Portable::openInputStream(fileName,true);
4883 if (!f.is_open())
4884 {
4885 err("could not open file {}\n",fileName);
4886 return false;
4887 }
4888 // read the file
4889 auto fileSize = fi.size();
4890 contents.resize(fileSize);
4891 f.read(contents.data(),fileSize);
4892 if (f.fail())
4893 {
4894 err("problems while reading file {}\n",fileName);
4895 return false;
4896 }
4897 }
4898 else
4899 {
4900 DString cmd=filterName+" \""+fileName+"\"";
4901 Debug::print(Debug::ExtCmd,0,"Executing popen(`{}`)\n",cmd);
4902 FILE *f=Portable::popen(cmd,"r");
4903 if (!f)
4904 {
4905 err("could not execute filter {}\n",filterName);
4906 return false;
4907 }
4908 const int bufSize=4096;
4909 char buf[bufSize];
4910 int numRead = 0;
4911 while ((numRead=static_cast<int>(fread(buf,1,bufSize,f)))>0)
4912 {
4913 //printf(">>>>>>>>Reading %d bytes\n",numRead);
4914 contents.append(buf,numRead);
4915 }
4917 Debug::print(Debug::FilterOutput, 0, "Filter output\n");
4918 Debug::print(Debug::FilterOutput,0,"-------------\n{}\n-------------\n",contents);
4919 }
4920
4921 if (contents.size()>=2 &&
4922 static_cast<uint8_t>(contents[0])==0xFF &&
4923 static_cast<uint8_t>(contents[1])==0xFE // Little endian BOM
4924 ) // UCS-2LE encoded file
4925 {
4926 transcodeCharacterBuffer(fileName,contents,"UCS-2LE","UTF-8");
4927 }
4928 else if (contents.size()>=2 &&
4929 static_cast<uint8_t>(contents[0])==0xFE &&
4930 static_cast<uint8_t>(contents[1])==0xFF // big endian BOM
4931 ) // UCS-2BE encoded file
4932 {
4933 transcodeCharacterBuffer(fileName,contents,"UCS-2BE","UTF-8");
4934 }
4935 else if (contents.size()>=3 &&
4936 static_cast<uint8_t>(contents[0])==0xEF &&
4937 static_cast<uint8_t>(contents[1])==0xBB &&
4938 static_cast<uint8_t>(contents[2])==0xBF
4939 ) // UTF-8 encoded file
4940 {
4941 contents.erase(0,3); // remove UTF-8 BOM: no translation needed
4942 }
4943 else // transcode according to the INPUT_ENCODING setting
4944 {
4945 // do character transcoding if needed.
4946 transcodeCharacterBuffer(fileName,contents,getEncoding(fi),"UTF-8");
4947 }
4948
4949 filterCRLF(contents);
4950 return true;
4951}
@ FilterOutput
Definition debug.h:38
@ ExtCmd
Definition debug.h:36
static void print(DebugMask mask, int prio, fmt::format_string< Args... > fmt, Args &&... args)
Definition debug.h:77
FILE * popen(const DString &name, const DString &type)
Definition portable.cpp:479
std::ifstream openInputStream(const DString &name, bool binary=false, bool openAtEnd=false)
Definition portable.cpp:659
int pclose(FILE *stream)
Definition portable.cpp:488
static void filterCRLF(std::string &contents)
Definition util.cpp:991
DString getFileFilter(const DString &name, bool isSourceCode)
Definition util.cpp:1052
static void transcodeCharacterBuffer(const DString &fileName, std::string &contents, const DString &inputEncoding, const DString &outputEncoding)
Definition util.cpp:4838
DString getEncoding(const FileInfo &fi)
Definition util.cpp:5035

References DString::empty(), err, FileInfo::exists(), Debug::ExtCmd, filterCRLF(), Debug::FilterOutput, getEncoding(), getFileFilter(), Portable::openInputStream(), Portable::pclose(), Portable::popen(), Debug::print(), readInputFile(), FileInfo::size(), DString::str(), and transcodeCharacterBuffer().

Referenced by checkAndOpenFile(), fileToString(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), parseFile(), parseInput(), readIncludeFile(), readInputFile(), DocbookDocVisitor::startMermaidFile(), LatexDocVisitor::startMermaidFile(), DocbookDocVisitor::startPlantUmlFile(), and LatexDocVisitor::startPlantUmlFile().

◆ recodeString()

◆ recognizeFixedForm()

bool recognizeFixedForm ( const DString & contents,
FortranFormat format )

Definition at line 5684 of file util.cpp.

5685{
5686 int column=0;
5687 bool skipLine=false;
5688
5689 if (format == FortranFormat::Fixed) return true;
5690 if (format == FortranFormat::Free) return false;
5691
5692 int tabSize=Config_getInt(TAB_SIZE);
5693 size_t sizCont = contents.length();
5694 for (size_t i=0;i<sizCont;i++)
5695 {
5696 column++;
5697
5698 switch(contents.at(i))
5699 {
5700 case '\n':
5701 column=0;
5702 skipLine=false;
5703 break;
5704 case '\t':
5705 column += tabSize-1;
5706 break;
5707 case ' ':
5708 break;
5709 case '\000':
5710 return false;
5711 case '#':
5712 skipLine=true;
5713 break;
5714 case 'C':
5715 case 'c':
5716 if (column==1)
5717 {
5718 return !keyWordsFortranC(contents.data()+i);
5719 }
5720 // fallthrough
5721 case '*':
5722 if (column==1) return true;
5723 if (skipLine) break;
5724 return false;
5725 case '!':
5726 if (column!=6) skipLine=true;
5727 break;
5728 default:
5729 if (skipLine) break;
5730 if (column>=7) return true;
5731 return false;
5732 }
5733 }
5734 return false;
5735}
static bool keyWordsFortranC(const char *contents)
Definition util.cpp:5664

References DString::at(), Config_getInt, DString::data(), Fixed, Free, keyWordsFortranC(), DString::length(), and recognizeFixedForm().

Referenced by convertCppComments(), FortranCodeParser::parseCode(), parseMain(), processMarkup(), recognizeFixedForm(), and setFileName().

◆ relativePathToRoot()

DString relativePathToRoot ( const DString & name)

Definition at line 2979 of file util.cpp.

2980{
2981 DString result;
2982 if (Config_getBool(CREATE_SUBDIRS))
2983 {
2984 if (name.empty())
2985 {
2986 return REL_PATH_TO_ROOT;
2987 }
2988 else if (size_t i = name.rfind('/'); i!=DString::npos)
2989 {
2990 result=REL_PATH_TO_ROOT;
2991 }
2992 }
2993 return result;
2994}
#define REL_PATH_TO_ROOT
Definition util.cpp:94

References Config_getBool, DString::empty(), DString::npos, REL_PATH_TO_ROOT, relativePathToRoot(), and DString::rfind().

Referenced by addDirPrefix(), generateBriefDoc(), relativePathToRoot(), DocbookGenerator::startFile(), HtmlGenerator::startFile(), LatexGenerator::startFile(), RTFGenerator::startFile(), and validatingParseDoc().

◆ removeAnonymousScopes()

DString removeAnonymousScopes ( const DString & str)

Removes all anonymous scopes from string s Possible examples:

   "bla::@10::blep"      => "bla::blep"
   "bla::@10::@11::blep" => "bla::blep"
   "@10::blep"           => "blep"
   " @10::blep"          => "blep"
   "@9::@10::blep"       => "blep"
   "bla::@1"             => "bla"
   "bla::@1::@2"         => "bla"
   "bla @1"              => "bla"

Definition at line 114 of file util.cpp.

115{
116 std::string result;
117 if (str.empty()) return result;
118
119 // helper to check if the found delimiter starts with a colon
120 auto startsWithColon = [](const std::string &del)
121 {
122 for (size_t i=0;i<del.size();i++)
123 {
124 if (del[i]=='@') return false;
125 else if (del[i]==':') return true;
126 }
127 return false;
128 };
129
130 // helper to check if the found delimiter ends with a colon
131 auto endsWithColon = [](const std::string &del)
132 {
133 for (int i=static_cast<int>(del.size())-1;i>=0;i--)
134 {
135 if (del[i]=='@') return false;
136 else if (del[i]==':') return true;
137 }
138 return false;
139 };
140
141 static const reg::Ex re(R"([\s:]*@\d+[\s:]*)");
142 std::string s = str.str();
143 reg::Iterator iter(s,re);
145 size_t p=0;
146 size_t sl=s.length();
147 bool needsSeparator=false;
148 for ( ; iter!=end ; ++iter)
149 {
150 const auto &match = *iter;
151 size_t i = match.position();
152 if (i>p) // add non-matching prefix
153 {
154 if (needsSeparator) result+="::";
155 needsSeparator=false;
156 result+=s.substr(p,i-p);
157 }
158 std::string delim = match.str();
159 needsSeparator = needsSeparator || (startsWithColon(delim) && endsWithColon(delim));
160 p = match.position()+match.length();
161 }
162 if (p<sl) // add trailing remainder
163 {
164 if (needsSeparator) result+="::";
165 result+=s.substr(p);
166 }
167 return result;
168}

References DString::empty(), end(), removeAnonymousScopes(), and DString::str().

Referenced by MemberDefImpl::displayDefinition(), generateClassMemberLink(), ClassDefImpl::internalInsertMember(), makeDisplayName(), makeDisplayName(), removeAnonymousScopes(), simplifyTypeForTable(), MemberDefImpl::writeDeclaration(), and MemberDefImpl::writeDocumentation().

◆ removeLongPathMarker()

DString removeLongPathMarker ( const DString & path)

Definition at line 212 of file util.cpp.

213{
214 DString result;
215#if defined(_WIN32)
216 if (path.startsWith("//?/")) // strip leading "\\?\" part from path
217 {
218 result = path.mid(4);
219 }
220 else
221#endif
222 {
223 result = path;
224 }
225 return result;
226}

References DString::mid(), removeLongPathMarker(), and DString::startsWith().

Referenced by addDirPrefix(), computeCommonDirPrefix(), FileDefImpl::FileDefImpl(), FileNameLinkedMap::findFileDef(), DirDefImpl::mergeDirectoryInTree(), removeLongPathMarker(), FileNameLinkedMap::showFileDefMatches(), and stripFromPath().

◆ removeRedundantWhiteSpace()

DString removeRedundantWhiteSpace ( const DString & s)

Definition at line 458 of file util.cpp.

459{
460 bool cliSupport = Config_getBool(CPP_CLI_SUPPORT);
461 bool vhdl = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
462
463 if (s.empty() || vhdl) return s;
464
465 // We use a static character array to
466 // improve the performance of this function
467 // and thread_local is needed to make it multi-thread safe
468 static THREAD_LOCAL char *growBuf = nullptr;
469 static THREAD_LOCAL size_t growBufLen = 0;
470 if (s.length()*3>growBufLen) // For input character we produce at most 3 output characters,
471 {
472 growBufLen = s.length()*3;
473 growBuf = static_cast<char *>(realloc(growBuf,growBufLen+1)); // add 1 for 0-terminator
474 }
475 if (growBuf==nullptr) return s; // should not happen, only we run out of memory
476
477 const char *src=s.data();
478 char *dst=growBuf;
479
480 size_t i=0;
481 size_t l=s.length();
482 size_t csp=0;
483 size_t vosp=0;
484 size_t vsp=0;
485 size_t osp=0;
486 char pc=0;
487 // skip leading whitespace
488 while (i<l && isspace(static_cast<uint8_t>(src[i])))
489 {
490 i++;
491 }
492 for (;i<l;i++)
493 {
494 char c=src[i];
495 char nc=i+1<l ? src[i+1] : ' ';
496
497 auto searchForKeyword = [&](const char *kw,size_t &matchLen,size_t totalLen)
498 {
499 if (matchLen<=totalLen && c==kw[matchLen] && // character matches substring kw
500 (matchLen>0 || // inside search string
501 i==0 || // if it is the first character
502 !isId(pc) // the previous may not be a digit
503 )
504 )
505 matchLen++;
506 else // reset counter
507 matchLen=0;
508 };
509 searchForKeyword(constScope, csp, 5); // keyword: const
510 searchForKeyword(volatileScope, vosp, 8); // keyword: volatile
511 searchForKeyword(virtualScope, vsp, 7); // keyword: virtual
512
513 // search for "operator"
514 if (osp<11 && (osp>=8 || c==operatorScope[osp]) && // character matches substring "operator" followed by 3 arbitrary characters
515 (osp>0 || // inside search string
516 i==0 || // if it is the first character
517 !isId(pc) // the previous may not be a digit
518 )
519 )
520 osp++;
521 else // reset counter
522 osp=0;
523
524 switch(c)
525 {
526 case '"': // quoted string
527 {
528 *dst++=c;
529 i++;
530 for (;i<l;i++) // find end of string
531 {
532 c = src[i];
533 *dst++=c;
534 if (c=='\\' && i+1<l)
535 {
536 i++;
537 c = src[i];
538 *dst++=c;
539 }
540 else if (c=='"')
541 {
542 break;
543 }
544 }
545 }
546 break;
547 case '<': // current char is a <
548 *dst++=c;
549 if (i+1<l &&
550 (isId(nc)) && // next char is an id char
551 (osp<8) // string in front is not "operator"
552 )
553 {
554 *dst++=' '; // add extra space
555 }
556 break;
557 case '>': // current char is a >
558 if (i>0 && !isspace(static_cast<uint8_t>(pc)) &&
559 (isId(pc) || pc=='*' || pc=='&' || pc=='.' || pc=='>') && // prev char is an id char or space or *&.
560 (osp<8 || (osp==8 && pc!='-')) // string in front is not "operator>" or "operator->"
561 )
562 {
563 *dst++=' '; // add extra space in front
564 }
565 *dst++=c;
566 if (i+1<l && (nc=='-' || nc=='&')) // '>-' -> '> -'
567 {
568 *dst++=' '; // add extra space after
569 }
570 break;
571 case ',': // current char is a ,
572 *dst++=c;
573 if (i>0 && !isspace(static_cast<uint8_t>(pc)) &&
574 ((i+1<l && (isId(nc) || nc=='[')) || // the [ is for attributes (see bug702170)
575 (i+2<l && nc=='$' && isId(src[i+2])) || // for PHP: ',$name' -> ', $name'
576 (i+3<l && nc=='&' && src[i+2]=='$' && isId(src[i+3])) // for PHP: ',&$name' -> ', &$name'
577 )
578 )
579 {
580 *dst++=' '; // add extra space after
581 }
582 break;
583 case '^': // CLI 'Type^name' -> 'Type^ name'
584 case '%': // CLI 'Type%name' -> 'Type% name'
585 *dst++=c;
586 if (cliSupport && i+1<l && (isId(nc) || nc=='-'))
587 {
588 *dst++=' '; // add extra space after
589 }
590 break;
591 case ')': // current char is a ) -> ')name' -> ') name'
592 *dst++=c;
593 if (i+1<l && (isId(nc) || nc=='-'))
594 {
595 *dst++=' '; // add extra space after
596 }
597 break;
598 case '*':
599 if (i>0 && pc!=' ' && pc!='\t' && pc!=':' &&
600 pc!='*' && pc!='&' && pc!='(' && pc!='/' && pc!='[' &&
601 pc!='.' && osp<9
602 )
603 // avoid splitting &&, **, .*, operator*, operator->*
604 {
605 *dst++=' ';
606 }
607 *dst++=c;
608 break;
609 case '&':
610 if (i>0 && isId(pc) && osp<9)
611 {
612 if (nc != '=')
613 // avoid splitting operator&=
614 {
615 *dst++=' ';
616 }
617 }
618 *dst++=c;
619 break;
620 case '$': // '$name' -> ' $name'
621 // 'name$name' -> 'name$name'
622 if (isId(pc))
623 {
624 *dst++=c;
625 break;
626 }
627 // else fallthrough
628 case '@': // '@name' -> ' @name'
629 case '\'': // ''name' -> '' name'
630 if (i>0 && i+1<l && pc!='=' && pc!=':' && !isspace(static_cast<uint8_t>(pc)) &&
631 isId(nc) && osp<8) // ")id" -> ") id"
632 {
633 *dst++=' ';
634 }
635 *dst++=c;
636 break;
637 case ':': // current char is a :
638 if (csp==6) // replace const::A by const ::A
639 {
640 *dst++=' ';
641 csp=0;
642 }
643 else if (vosp==9) // replace volatile::A by volatile ::A
644 {
645 *dst++=' ';
646 vosp=0;
647 }
648 else if (vsp==8) // replace virtual::A by virtual ::A
649 {
650 *dst++=' ';
651 vsp=0;
652 }
653 *dst++=c;
654 break;
655 case ' ': // fallthrough
656 case '\n': // fallthrough
657 case '\t':
658 {
659 if (g_charAroundSpace.charMap[static_cast<uint8_t>(pc)].before &&
660 g_charAroundSpace.charMap[static_cast<uint8_t>(nc)].after &&
661 !(pc==',' && nc=='.') &&
662 (osp<8 || (osp>=8 && isId(pc) && isId(nc)))
663 // e.g. 'operator >>' -> 'operator>>',
664 // 'operator "" _x' -> 'operator""_x',
665 // but not 'operator int' -> 'operatorint'
666 )
667 { // keep space
668 *dst++=' ';
669 }
670 else if ((pc=='*' || pc=='&' || pc=='.') && nc=='>')
671 {
672 *dst++=' ';
673 }
674 }
675 break;
676 default:
677 *dst++=c;
678 auto correctKeywordAllowedInsideScope = [&](char cc,size_t &matchLen,size_t totalLen) {
679 if (c==cc && matchLen==totalLen)
680 {
681 if ((i+2<l && src[i+1] == ':' && src[i+2] == ':') || // keyword::
682 ((i>matchLen && src[i-matchLen] == ':' && src[i-matchLen-1] == ':')) // ::keyword
683 ) matchLen = 0;
684 };
685 };
686 correctKeywordAllowedInsideScope('t',csp, 5); // keyword: const
687 correctKeywordAllowedInsideScope('e',vosp,8); // keyword: volatile
688 correctKeywordAllowedInsideScope('l',vsp, 7); // keyword: virtual
689
690 auto correctKeywordNotPartOfScope = [&](char cc,size_t &matchLen,size_t totalLen)
691 {
692 if (c==cc && matchLen==totalLen && i+1<l && // found matching keyword
693 !(isId(nc) || nc==')' || nc==',' || disspace(nc))
694 ) // prevent keyword ::A from being converted to keyword::A
695 {
696 *dst++=' ';
697 matchLen=0;
698 }
699 };
700 correctKeywordNotPartOfScope('t',csp, 5); // keyword: const
701 correctKeywordNotPartOfScope('e',vosp,8); // keyword: volatile
702 correctKeywordNotPartOfScope('l',vsp, 7); // keyword: virtual
703 break;
704 }
705 pc=c;
706 }
707 *dst++='\0';
708 //printf("removeRedundantWhitespace(%s)->%s\n",qPrint(s),growBuf);
709 return growBuf;
710}
#define THREAD_LOCAL
Definition doxygen.h:30
bool disspace(char c)
Definition dstring.h:67
Token literal values and constants.
Definition CharStream.h:12
CharElem charMap[256]
Definition util.cpp:452
static const char constScope[]
Definition util.cpp:411
static const char virtualScope[]
Definition util.cpp:413
static const char volatileScope[]
Definition util.cpp:412
static CharAroundSpace g_charAroundSpace
Definition util.cpp:455
static const char operatorScope[]
Definition util.cpp:414

References CharAroundSpace::CharElem::after, CharAroundSpace::CharElem::before, CharAroundSpace::charMap, Config_getBool, constScope, DString::data(), disspace(), DString::empty(), g_charAroundSpace, isId(), DString::length(), operatorScope, removeRedundantWhiteSpace(), THREAD_LOCAL, virtualScope, and volatileScope.

Referenced by addFrom(), addGlobalFunction(), addMethodToClass(), addVariable(), addVariableToClass(), argListToString(), buildFunctionList(), buildInterfaceAndServiceList(), buildTypedefList(), ClassDefImpl::ClassDefImpl(), extractCanonicalType(), findClassRelation(), DocParser::findDocsForMemberOrCompound(), findMember(), findUsedClassesForClass(), findUsingDeclImports(), ArgumentList::finishTrailingReturnType(), generateFunctionLink(), generateFunctionLink(), generateLink(), getCanonicalTypeForIdentifier(), getLink(), getLink(), getLink(), MemberDefImpl::init(), ClassDefImpl::insertTemplateInstance(), MemberDefImpl::MemberDefImpl(), normalizeNonTemplateArgumentsInString(), parseFuncDecl(), removeRedundantWhiteSpace(), resolveRef(), tempArgListToString(), and writeExceptionListImpl().

◆ replaceAnonymousScopes()

DString replaceAnonymousScopes ( const DString & s,
const DString & replacement = DString() )

Definition at line 171 of file util.cpp.

172{
173 if (s.empty()) return s;
174 static const reg::Ex marker(R"(@\d+)");
175 std::string result = reg::replace(s.str(),marker,
176 !replacement.empty() ? replacement.data() : "__anonymous__");
177 //printf("replaceAnonymousScopes('%s')='%s'\n",qPrint(s),qPrint(result));
178 return result;
179}
std::string replace(std::string_view str, const Ex &re, std::string_view replacement)
Searching in a given input string for parts that match regular expression re and replaces those parts...
Definition regex.cpp:869

References DString::data(), DString::empty(), reg::replace(), replaceAnonymousScopes(), and DString::str().

Referenced by addMemberFunction(), findGlobalMember(), generateDEFForMember(), and replaceAnonymousScopes().

◆ replaceColorMarkers()

DString replaceColorMarkers ( const DString & str)

Replaces any markers of the form ##AA in input string str by new markers of the form #AABBCC, where #AABBCC represents a valid color, based on the intensity represented by hex number AA and the current HTML_COLORSTYLE_* settings.

Definition at line 5128 of file util.cpp.

5129{
5130 if (str.empty()) return DString();
5131 std::string result;
5132 std::string s=str.str();
5133 static const reg::Ex re(R"(##[0-9A-Fa-f][0-9A-Fa-f])");
5134 reg::Iterator it(s,re);
5136 int hue = Config_getInt(HTML_COLORSTYLE_HUE);
5137 int sat = Config_getInt(HTML_COLORSTYLE_SAT);
5138 int gamma = Config_getInt(HTML_COLORSTYLE_GAMMA);
5139 size_t sl=s.length();
5140 size_t p=0;
5141 for (; it!=end ; ++it)
5142 {
5143 const auto &match = *it;
5144 size_t i = match.position();
5145 size_t l = match.length();
5146 if (i>p) result+=s.substr(p,i-p);
5147 std::string lumStr = match.str().substr(2);
5148#define HEXTONUM(x) (((x)>='0' && (x)<='9') ? ((x)-'0') : \
5149 ((x)>='a' && (x)<='f') ? ((x)-'a'+10) : \
5150 ((x)>='A' && (x)<='F') ? ((x)-'A'+10) : 0)
5151
5152 double r = 0,g = 0,b = 0;
5153 int level = HEXTONUM(lumStr[0])*16+HEXTONUM(lumStr[1]);
5154 ColoredImage::hsl2rgb(hue/360.0,sat/255.0,
5155 pow(level/255.0,gamma/100.0),&r,&g,&b);
5156 int red = static_cast<int>(r*255.0);
5157 int green = static_cast<int>(g*255.0);
5158 int blue = static_cast<int>(b*255.0);
5159 char colStr[8];
5160 colStr[0]='#';
5161 colStr[1]=hex[red>>4];
5162 colStr[2]=hex[red&0xf];
5163 colStr[3]=hex[green>>4];
5164 colStr[4]=hex[green&0xf];
5165 colStr[5]=hex[blue>>4];
5166 colStr[6]=hex[blue&0xf];
5167 colStr[7]=0;
5168 //printf("replacing %s->%s (level=%d)\n",qPrint(lumStr),colStr,level);
5169 result+=colStr;
5170 p=i+l;
5171 }
5172 if (p<sl) result+=s.substr(p);
5173 return result;
5174}
static void hsl2rgb(double h, double s, double l, double *pRed, double *pGreen, double *pBlue)
Definition image.cpp:368
#define HEXTONUM(x)

References Config_getInt, DString::DString(), DString::empty(), end(), hex, HEXTONUM, ColoredImage::hsl2rgb(), replaceColorMarkers(), and DString::str().

Referenced by ResourceMgr::copyResourceAs(), fillColorStyleMaps(), HtmlGenerator::init(), recodeString(), replaceColorMarkers(), and writeDefaultStyleSheet().

◆ resolveLink()

bool resolveLink ( const DString & scName,
const DString & lr,
bool inSeeBlock,
const Definition ** resContext,
DString & resAnchor,
SrcLangExt lang,
const DString & prefix = DString() )

Returns an symbol definition given its name and context for an explicitly linked symbol.

Postcondition
return value true implies *resContext!=0

Definition at line 2375 of file util.cpp.

2383{
2384 *resContext=nullptr;
2385
2386 DString linkRef=lr;
2387 if (lang==SrcLangExt::CSharp)
2388 {
2389 linkRef = mangleCSharpGenericName(linkRef);
2390 }
2391 DString linkRefWithoutTemplates = stripTemplateSpecifiersFromScope(linkRef,false);
2392 AUTO_TRACE("scName='{}',ref='{}'",scName,lr);
2393 const FileDef *fd = nullptr;
2394 const GroupDef *gd = nullptr;
2395 const PageDef *pd = nullptr;
2396 const ClassDef *cd = nullptr;
2397 const DirDef *dir = nullptr;
2398 const ConceptDef *cnd = nullptr;
2399 const ModuleDef *modd = nullptr;
2400 const NamespaceDef *nd = nullptr;
2401 const SectionInfo *si = nullptr;
2402 bool ambig = false;
2403 if (linkRef.empty()) // no reference name!
2404 {
2405 AUTO_TRACE_EXIT("no_ref");
2406 return false;
2407 }
2408 else if ((pd=Doxygen::pageLinkedMap->find(linkRef))) // link to a page
2409 {
2410 gd = pd->getGroupDef();
2411 if (gd)
2412 {
2413 if (!pd->name().empty()) si=SectionManager::instance().find(pd->name());
2414 *resContext=gd;
2415 if (si) resAnchor = si->label();
2416 }
2417 else
2418 {
2419 *resContext=pd;
2420 }
2421 AUTO_TRACE_EXIT("page");
2422 return true;
2423 }
2424 else if ((si=SectionManager::instance().find(prefix+linkRef)))
2425 {
2426 *resContext=si->definition();
2427 resAnchor = si->label();
2428 AUTO_TRACE_EXIT("section anchor={} def={}",resAnchor,si->definition()?si->definition()->name():"<none>");
2429 return true;
2430 }
2431 else if (!prefix.empty() && (si=SectionManager::instance().find(linkRef)))
2432 {
2433 *resContext=si->definition();
2434 resAnchor = si->label();
2435 AUTO_TRACE_EXIT("section anchor={} def={}",resAnchor,si->definition()?si->definition()->name():"<none>");
2436 return true;
2437 }
2438 else if ((pd=Doxygen::exampleLinkedMap->find(linkRef))) // link to an example
2439 {
2440 *resContext=pd;
2441 AUTO_TRACE_EXIT("example");
2442 return true;
2443 }
2444 else if ((gd=Doxygen::groupLinkedMap->find(linkRef))) // link to a group
2445 {
2446 *resContext=gd;
2447 AUTO_TRACE_EXIT("group");
2448 return true;
2449 }
2450 else if ((fd=Doxygen::inputNameLinkedMap->findFileDef(linkRef,ambig)) // file link
2451 && fd->isLinkable())
2452 {
2453 *resContext=fd;
2454 AUTO_TRACE_EXIT("file");
2455 return true;
2456 }
2457 else if ((cd=getClass(linkRef))) // class link
2458 {
2459 *resContext=cd;
2460 resAnchor=cd->anchor();
2461 AUTO_TRACE_EXIT("class");
2462 return true;
2463 }
2464 else if (lang==SrcLangExt::Java &&
2465 (cd=getClass(linkRefWithoutTemplates))) // Java generic class link
2466 {
2467 *resContext=cd;
2468 resAnchor=cd->anchor();
2469 AUTO_TRACE_EXIT("generic");
2470 return true;
2471 }
2472 else if ((cd=getClass(linkRef+"-p"))) // Obj-C protocol link
2473 {
2474 *resContext=cd;
2475 resAnchor=cd->anchor();
2476 AUTO_TRACE_EXIT("protocol");
2477 return true;
2478 }
2479 else if ((cnd=getConcept(linkRef))) // C++20 concept definition
2480 {
2481 *resContext=cnd;
2482 resAnchor=cnd->anchor();
2483 AUTO_TRACE_EXIT("concept");
2484 return true;
2485 }
2486 else if ((modd=ModuleManager::instance().modules().find(linkRef)))
2487 {
2488 *resContext=modd;
2489 resAnchor=modd->anchor();
2490 AUTO_TRACE_EXIT("module");
2491 return true;
2492 }
2493 else if ((nd=Doxygen::namespaceLinkedMap->find(linkRef)))
2494 {
2495 *resContext=nd;
2496 AUTO_TRACE_EXIT("namespace");
2497 return true;
2498 }
2499 else if ((dir=resolveDirLink(linkRef)) && dir->isLinkable())
2500 {
2501 *resContext=dir;
2502 AUTO_TRACE_EXIT("directory");
2503 return true;
2504 }
2505 else // probably a member reference
2506 {
2507 const MemberDef *md = nullptr;
2508 bool res = resolveRef(scName,lr,true,resContext,&md,lang);
2509 if (md) resAnchor=md->anchor();
2510 AUTO_TRACE_EXIT("member? res={}",res);
2511 return res;
2512 }
2513}
virtual DString anchor() const =0
A model of a directory symbol.
Definition dirdef.h:110
static NamespaceLinkedMap * namespaceLinkedMap
Definition doxygen.h:115
static FileNameLinkedMap * inputNameLinkedMap
Definition doxygen.h:104
static PageLinkedMap * exampleLinkedMap
Definition doxygen.h:98
static GroupLinkedMap * groupLinkedMap
Definition doxygen.h:114
A model of a group of symbols.
Definition groupdef.h:52
static ModuleManager & instance()
virtual const GroupDef * getGroupDef() const =0
Definition * definition() const
Definition section.h:77
DString label() const
Definition section.h:69
ConceptDef * getConcept(const DString &n)
bool resolveRef(const DString &scName, const DString &name, bool inSeeBlock, const Definition **resContext, const MemberDef **resMember, SrcLangExt lang, bool lookForSpecialization, const FileDef *currentFile, bool checkScope)
Definition util.cpp:2075
DString stripTemplateSpecifiersFromScope(const DString &fullName, bool parentOnly, DString *pLastScopeStripped, DString scopeName, bool allowArtificial)
Definition util.cpp:3866
static const DirDef * resolveDirLink(const DString &linkRef)
Definition util.cpp:2357
DString mangleCSharpGenericName(const DString &name)
Definition util.cpp:6116

References Definition::anchor(), AUTO_TRACE, AUTO_TRACE_EXIT, SectionInfo::definition(), DString::empty(), Doxygen::exampleLinkedMap, LinkedMap< T, Hash, KeyEqual, Map >::find(), getClass(), getConcept(), PageDef::getGroupDef(), Doxygen::groupLinkedMap, Doxygen::inputNameLinkedMap, ModuleManager::instance(), SectionManager::instance(), Definition::isLinkable(), SectionInfo::label(), mangleCSharpGenericName(), Definition::name(), Doxygen::namespaceLinkedMap, Doxygen::pageLinkedMap, prefix, resolveDirLink(), resolveLink(), resolveRef(), and stripTemplateSpecifiersFromScope().

Referenced by DocLink::DocLink(), DocRef::DocRef(), and resolveLink().

◆ resolveRef()

bool resolveRef ( const DString & scName,
const DString & name,
bool inSeeBlock,
const Definition ** resContext,
const MemberDef ** resMember,
SrcLangExt lang,
bool lookForSpecializations = true,
const FileDef * currentFile = nullptr,
bool checkScope = false )

Returns a symbol definition (compound and/or member) given its name and context.

Postcondition
return value true implies *resContext!=0 or *resMember!=0

Definition at line 2075 of file util.cpp.

2085{
2086 AUTO_TRACE("scope={} name={} inSeeBlock={} lang={} lookForSpecialization={} currentFile={} checkScope={}",
2087 scName,name,inSeeBlock,lang,lookForSpecialization,currentFile ? currentFile->name() : "", checkScope);
2088 //printf("resolveRef(scope=%s,name=%s,inSeeBlock=%d)\n",qPrint(scName),qPrint(name),inSeeBlock);
2089 DString tsName = name;
2090 //bool memberScopeFirst = tsName.find('#')!=-1;
2091 DString fullName = substitute(tsName,"#","::");
2092 if (fullName.find("anonymous_namespace{")==DString::npos)
2093 {
2094 fullName = removeRedundantWhiteSpace(substitute(fullName,".","::",3));
2095 }
2096 else
2097 {
2098 fullName = removeRedundantWhiteSpace(fullName);
2099 }
2100
2101 size_t templStartPos;
2102 if (lang==SrcLangExt::CSharp && (templStartPos=fullName.find('<'))!=DString::npos)
2103 {
2104 size_t templEndPos = fullName.rfind('>');
2105 if (templEndPos!=DString::npos)
2106 {
2107 fullName = mangleCSharpGenericName(fullName.left(templEndPos+1))+fullName.mid(templEndPos+1);
2108 AUTO_TRACE_ADD("C# mangled name='{}'",fullName);
2109 }
2110 }
2111
2112 size_t bracePos = findParameterList(fullName);
2113 size_t endNamePos = bracePos!=DString::npos ? bracePos : fullName.length();
2114 size_t scopePos = fullName.rfind("::",endNamePos);
2115 bool explicitScope = fullName.startsWith("::") && // ::scope or #scope
2116 ((scopePos!=DString::npos && scopePos>2) || // ::N::A
2117 tsName.startsWith("::") || // ::foo in local scope
2118 scName==nullptr // #foo in global scope
2119 );
2120 bool allowTypeOnly=false;
2121
2122 // default result values
2123 *resContext=nullptr;
2124 *resMember=nullptr;
2125
2126 if (bracePos==DString::npos) // simple name
2127 {
2128 // the following if() was commented out for releases in the range
2129 // 1.5.2 to 1.6.1, but has been restored as a result of bug report 594787.
2130 if (!inSeeBlock && scopePos==DString::npos && isLowerCase(tsName))
2131 { // link to lower case only name => do not try to autolink
2132 AUTO_TRACE_ADD("false");
2133 return false;
2134 }
2135
2136 ClassDef *cd=nullptr;
2137 NamespaceDef *nd=nullptr;
2138 ConceptDef *cnd=nullptr;
2139 ModuleDef *modd=nullptr;
2140
2141 //printf("scName=%s fullName=%s\n",qPrint(scName),qPrint(fullName));
2142
2143 // check if this is a class or namespace reference
2144 if (scName!=fullName && getScopeDefs(scName,fullName,cd,cnd,nd,modd))
2145 {
2146 //printf("found scopeDef\n");
2147 if (cd) // scope matches that of a class
2148 {
2149 *resContext = cd;
2150 }
2151 else if (cnd)
2152 {
2153 *resContext = cnd;
2154 }
2155 else if (modd)
2156 {
2157 *resContext = modd;
2158 }
2159 else // scope matches that of a namespace
2160 {
2161 ASSERT(nd!=nullptr);
2162 *resContext = nd;
2163 }
2164 AUTO_TRACE_ADD("true");
2165 return true;
2166 }
2167 else if (scName==fullName || (!inSeeBlock && scopePos==DString::npos))
2168 // nothing to link => output plain text
2169 {
2170 //printf("found scName=%s fullName=%s scName==fullName=%d "
2171 // "inSeeBlock=%d scopePos=%d!\n",
2172 // qPrint(scName),qPrint(fullName),scName==fullName,inSeeBlock,scopePos);
2173
2174 // at this point we have a bare word that is not a class or namespace
2175 // we should also allow typedefs or enums to be linked, but not for instance member
2176 // functions, otherwise 'Foo' would always link to the 'Foo()' constructor instead of the
2177 // 'Foo' class. So we use this flag as a filter.
2178 allowTypeOnly=true;
2179 }
2180
2181 // continue search...
2182 }
2183
2184 // extract userscope+name
2185 DString nameStr=fullName.left(endNamePos);
2186 if (explicitScope) nameStr=nameStr.mid(2);
2187
2188
2189 // extract arguments
2190 DString argsStr;
2191 if (bracePos!=DString::npos) argsStr=fullName.mid(bracePos);
2192
2193 // strip template specifier
2194 // TODO: match against the correct partial template instantiation
2195 size_t templPos = nameStr.find('<');
2196 bool tryUnspecializedVersion = false;
2197 if (templPos!=DString::npos && nameStr.find("operator")==DString::npos)
2198 {
2199 size_t endTemplPos=nameStr.rfind('>');
2200 if (endTemplPos!=DString::npos)
2201 {
2202 if (!lookForSpecialization)
2203 {
2204 nameStr=nameStr.left(templPos)+nameStr.mid(endTemplPos+1);
2205 }
2206 else
2207 {
2208 tryUnspecializedVersion = true;
2209 }
2210 }
2211 }
2212
2213 DString scopeStr=scName;
2214 if (!explicitScope && nameStr.length()>scopeStr.length() && leftScopeMatch(scopeStr,nameStr))
2215 {
2216 nameStr=nameStr.mid(scopeStr.length()+2);
2217 }
2218
2219 const GroupDef *gd = nullptr;
2220 const ConceptDef *cnd = nullptr;
2221 const ModuleDef *modd = nullptr;
2222
2223 // check if nameStr is a member or global.
2224 //printf("getDefs(scope=%s,name=%s,args=%s checkScope=%d)\n",
2225 // qPrint(scopeStr), qPrint(nameStr), qPrint(argsStr),checkScope);
2226 GetDefInput input(scopeStr,nameStr,argsStr);
2227 input.forceEmptyScope = explicitScope;
2228 input.currentFile = currentFile;
2229 input.checkCV = true;
2230 GetDefResult result = getDefs(input);
2231 if (result.found)
2232 {
2233 //printf("after getDefs checkScope=%d nameStr=%s\n",checkScope,qPrint(nameStr));
2234 size_t np = nameStr.find("::");
2235 if (checkScope && result.md && result.md->getOuterScope()==Doxygen::globalScope &&
2236 !result.md->isStrongEnumValue() &&
2237 (!scopeStr.empty() || (np!=DString::npos && np>0)))
2238 {
2239 // we did find a member, but it is a global one while we were explicitly
2240 // looking for a scoped variable. See bug 616387 for an example why this check is needed.
2241 // note we do need to support autolinking to "::symbol" hence the >0
2242 //printf("not global member!\n");
2243 *resContext=nullptr;
2244 *resMember=nullptr;
2245 AUTO_TRACE_ADD("false");
2246 return false;
2247 }
2248 //printf("after getDefs md=%p cd=%p fd=%p nd=%p gd=%p\n",md,cd,fd,nd,gd);
2249 if (result.md)
2250 {
2251 if (!allowTypeOnly || result.md->isTypedef() || result.md->isEnumerate())
2252 {
2253 *resMember=result.md;
2254 *resContext=result.md;
2255 }
2256 else // md is not a type, but we explicitly expect one
2257 {
2258 *resContext=nullptr;
2259 *resMember=nullptr;
2260 AUTO_TRACE_ADD("false");
2261 return false;
2262 }
2263 }
2264 else if (result.cd) *resContext=result.cd;
2265 else if (result.nd) *resContext=result.nd;
2266 else if (result.fd) *resContext=result.fd;
2267 else if (result.gd) *resContext=result.gd;
2268 else if (result.cnd) *resContext=result.cnd;
2269 else if (result.modd) *resContext=result.modd;
2270 else
2271 {
2272 *resContext=nullptr; *resMember=nullptr;
2273 AUTO_TRACE_ADD("false");
2274 return false;
2275 }
2276 //printf("member=%s (md=%p) anchor=%s linkable()=%d context=%s\n",
2277 // qPrint(md->name()), md, qPrint(md->anchor()), md->isLinkable(), qPrint((*resContext)->name()));
2278 AUTO_TRACE_ADD("true");
2279 return true;
2280 }
2281 else if (inSeeBlock && !nameStr.empty() && (gd=Doxygen::groupLinkedMap->find(nameStr)))
2282 { // group link
2283 *resContext=gd;
2284 AUTO_TRACE_ADD("true");
2285 return true;
2286 }
2287 else if ((cnd=Doxygen::conceptLinkedMap->find(nameStr)))
2288 {
2289 *resContext=cnd;
2290 AUTO_TRACE_ADD("true");
2291 return true;
2292 }
2293 else if ((modd=ModuleManager::instance().modules().find(nameStr)))
2294 {
2295 *resContext=modd;
2296 AUTO_TRACE_ADD("true");
2297 return true;
2298 }
2299 else if (tsName.find('.')!=DString::npos) // maybe a link to a file
2300 {
2301 bool ambig = false;
2302 const FileDef *fd=Doxygen::inputNameLinkedMap->findFileDef(tsName,ambig);
2303 if (fd && !ambig)
2304 {
2305 *resContext=fd;
2306 AUTO_TRACE_ADD("true");
2307 return true;
2308 }
2309 }
2310
2311 if (tryUnspecializedVersion)
2312 {
2313 bool b = resolveRef(scName,name,inSeeBlock,resContext,resMember,lang,false,nullptr,checkScope);
2314 AUTO_TRACE_ADD("{}",b);
2315 return b;
2316 }
2317 if (bracePos!=DString::npos) // Try without parameters as well, could be a constructor invocation
2318 {
2319 *resContext=getClass(fullName.left(bracePos));
2320 if (*resContext)
2321 {
2322 AUTO_TRACE_ADD("true");
2323 return true;
2324 }
2325 }
2326 //printf("resolveRef: %s not found!\n",qPrint(name));
2327
2328 AUTO_TRACE_ADD("false");
2329 return false;
2330}
virtual Definition * getOuterScope() const =0
static ConceptLinkedMap * conceptLinkedMap
Definition doxygen.h:97
virtual bool isStrongEnumValue() const =0
virtual bool isEnumerate() const =0
static size_t findParameterList(const DString &name)
Returns the position in the string where a function parameter list begins, or DString::npos if one is...
Definition util.cpp:716
GetDefResult getDefs(const GetDefInput &input)
Definition util.cpp:1933
static bool getScopeDefs(const DString &docScope, const DString &scope, ClassDef *&cd, ConceptDef *&cnd, NamespaceDef *&nd, ModuleDef *&modd)
Definition util.cpp:2003
static bool isLowerCase(DString &s)
Definition util.cpp:2066

References ASSERT, AUTO_TRACE, AUTO_TRACE_ADD, GetDefResult::cd, GetDefInput::checkCV, GetDefResult::cnd, Doxygen::conceptLinkedMap, GetDefInput::currentFile, DString::empty(), GetDefResult::fd, DString::find(), LinkedMap< T, Hash, KeyEqual, Map >::find(), FileNameLinkedMap::findFileDef(), findParameterList(), GetDefInput::forceEmptyScope, GetDefResult::found, GetDefResult::gd, getClass(), getDefs(), Definition::getOuterScope(), getScopeDefs(), Doxygen::globalScope, Doxygen::groupLinkedMap, Doxygen::inputNameLinkedMap, ModuleManager::instance(), MemberDef::isEnumerate(), isLowerCase(), MemberDef::isStrongEnumValue(), MemberDef::isTypedef(), DString::left(), leftScopeMatch(), DString::length(), mangleCSharpGenericName(), GetDefResult::md, DString::mid(), GetDefResult::modd, Definition::name(), GetDefResult::nd, DString::npos, removeRedundantWhiteSpace(), resolveRef(), DString::rfind(), DString::startsWith(), and substitute().

Referenced by DocParser::handleLinkedWord(), resolveLink(), and resolveRef().

◆ resolveTypeDef()

DString resolveTypeDef ( const Definition * d,
const DString & name,
const Definition ** typedefContext = nullptr )

Definition at line 264 of file util.cpp.

266{
267 AUTO_TRACE("context='{}' qualifiedName='{}'",context?context->name():"",qualifiedName);
268 DString result;
269 if (qualifiedName.empty())
270 {
271 AUTO_TRACE_EXIT("empty name");
272 return result;
273 }
274
275 const Definition *mContext=context;
276 if (typedefContext) *typedefContext=context;
277
278 // see if the qualified name has a scope part
279 if (qualifiedName.find('<')!=DString::npos)
280 {
281 AUTO_TRACE_EXIT("template");
282 return result;
283 }
284 size_t scopeIndex = qualifiedName.rfind("::");
285 DString resName=qualifiedName;
286 if (scopeIndex!=DString::npos) // strip scope part for the name
287 {
288 resName=qualifiedName.mid(scopeIndex+2);
289 if (resName.empty())
290 {
291 AUTO_TRACE_EXIT("invalid format");
292 return result;
293 }
294 }
295 const MemberDef *md=nullptr;
296 while (mContext && md==nullptr)
297 {
298 // step 1: get the right scope
299 const Definition *resScope=mContext;
300 if (scopeIndex!=DString::npos)
301 {
302 // split-off scope part
303 DString resScopeName = qualifiedName.left(scopeIndex);
304 //printf("resScopeName='%s'\n",qPrint(resScopeName));
305
306 // look-up scope in context
307 int is=0,ps=0,l=0;
308 while ((is=getScopeFragment(resScopeName,ps,&l))!=-1)
309 {
310 DString qualScopePart = resScopeName.mid(is,l);
311 DString tmp = resolveTypeDef(mContext,qualScopePart);
312 if (!tmp.empty()) qualScopePart=tmp;
313 resScope = resScope->findInnerCompound(qualScopePart);
314 //printf("qualScopePart='%s' resScope=%p\n",qPrint(qualScopePart),resScope);
315 if (resScope==nullptr) break;
316 ps=is+l;
317 }
318 }
319 AUTO_TRACE_ADD("resScope='{}' resName='{}'",resScope?resScope->name():"",resName);
320
321 // step 2: get the member
322 if (resScope) // no scope or scope found in the current context
323 {
324 //printf("scope found: %s, look for typedef %s\n",
325 // qPrint(resScope->qualifiedName()),qPrint(resName));
326 MemberNameLinkedMap *mnd=nullptr;
327 bool searchRelated=false;
328 bool mustBeRelated=false;
329 if (resScope->definitionType()==Definition::TypeClass)
330 {
332 }
333 else
334 {
336 searchRelated=true;
337 }
338 MemberName *mn=mnd->find(resName);
339 if (mn==0 && searchRelated)
340 {
342 mustBeRelated=true;
343 }
344 if (mn)
345 {
346 int minDist=-1;
347 for (const auto &tmd_p : *mn)
348 {
349 const MemberDef *tmd = tmd_p.get();
350 AUTO_TRACE_ADD("found candidate member '{}' isTypeDef={}' isRelated={} mustBeRelated={}",
351 tmd->name(),tmd->isTypedef(),tmd->isRelated(),mustBeRelated);
352 //printf("Found member %s resScope=%s outerScope=%s mContext=%p\n",
353 // qPrint(tmd->name()),qPrint( resScope->name()),
354 // qPrint(tmd->getOuterScope()->name()), mContext);
355 if (tmd->isTypedef())
356 {
357 if (resScope==Doxygen::globalScope && tmd->isRelated() && mustBeRelated)
358 {
359 md = tmd;
360 }
361 else
362 {
363 SymbolResolver resolver;
364 int dist=resolver.isAccessibleFrom(resScope,tmd);
365 if (dist!=-1 && (md==nullptr || dist<minDist))
366 {
367 md = tmd;
368 minDist = dist;
369 }
370 }
371 }
372 }
373 }
374 }
375 mContext=mContext->getOuterScope();
376 }
377
378 AUTO_TRACE_ADD("md='{}'",md?md->name():"");
379 // step 3: get the member's type
380 if (md)
381 {
382 //printf(">>resolveTypeDef: Found typedef name '%s' in scope '%s' value='%s' args='%s'\n",
383 // qPrint(qualifiedName),qPrint(context->name()),qPrint(md->typeString()),qPrint(md->argsString())
384 // );
385 result=md->typeString();
386 DString args = md->argsString();
387 if (args.find(")(")!=DString::npos) // typedef of a function/member pointer
388 {
389 result+=args;
390 }
391 else if (args.find('[')!=DString::npos) // typedef of an array
392 {
393 result+=args;
394 }
395 if (typedefContext) *typedefContext=md->getOuterScope();
396 }
397 else
398 {
399 //printf(">>resolveTypeDef: Typedef '%s' not found in scope '%s'!\n",
400 // qPrint(qualifiedName),context ? qPrint(context->name()) : "<global>");
401 }
402 AUTO_TRACE_EXIT("result='{}'",result);
403 return result;
404}
virtual const Definition * findInnerCompound(const DString &name) const =0
static MemberNameLinkedMap * functionNameLinkedMap
Definition doxygen.h:112
static MemberNameLinkedMap * memberNameLinkedMap
Definition doxygen.h:111
virtual DString argsString() const =0
virtual bool isRelated() const =0
virtual DString typeString() const =0
Ordered dictionary of MemberName objects.
Definition membername.h:63
int isAccessibleFrom(const Definition *scope, const Definition *item)
Checks if symbol item is accessible from within scope.
DString resolveTypeDef(const Definition *context, const DString &qualifiedName, const Definition **typedefContext)
Definition util.cpp:264
int getScopeFragment(const DString &s, int p, int *l)
Definition util.cpp:3978

References MemberDef::argsString(), AUTO_TRACE, AUTO_TRACE_ADD, AUTO_TRACE_EXIT, Definition::definitionType(), DString::empty(), DString::find(), LinkedMap< T, Hash, KeyEqual, Map >::find(), Definition::findInnerCompound(), Doxygen::functionNameLinkedMap, Definition::getOuterScope(), getScopeFragment(), Doxygen::globalScope, SymbolResolver::isAccessibleFrom(), MemberDef::isRelated(), MemberDef::isTypedef(), DString::left(), Doxygen::memberNameLinkedMap, DString::mid(), Definition::name(), DString::npos, resolveTypeDef(), DString::rfind(), Definition::TypeClass, and MemberDef::typeString().

Referenced by findUsedClassesForClass(), getCanonicalTemplateSpec(), getCanonicalTypeForIdentifier(), isVarWithConstructor(), and resolveTypeDef().

◆ rightScopeMatch()

bool rightScopeMatch ( const DString & scope,
const DString & name )

Definition at line 761 of file util.cpp.

762{
763 size_t sl=scope.length();
764 size_t nl=name.length();
765 return (name==scope || // equal
766 (scope.right(nl)==name && // substring
767 sl>1+nl && scope.at(sl-nl-1)==':' && scope.at(sl-nl-2)==':' // scope
768 )
769 );
770}

References DString::at(), DString::length(), DString::right(), and rightScopeMatch().

Referenced by addMemberFunction(), findScopeFromQualifiedName(), isRecursiveBaseClass(), and rightScopeMatch().

◆ selectBlocks()

DString selectBlocks ( const DString & s,
const SelectionBlockList & blockList,
const SelectionMarkerInfo & markerInfo )

remove disabled blocks and all block markers from s and return the result as a string

Definition at line 5750 of file util.cpp.

5751{
5752 if (s.empty()) return s;
5753
5754 // helper to find the end of a block
5755 auto skipBlock = [&markerInfo](const char *p,const SelectionBlock &blk)
5756 {
5757 char c = 0;
5758 while ((c=*p))
5759 {
5760 if (c==markerInfo.markerChar && dstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // end marker
5761 {
5762 size_t len = markerInfo.endLen;
5763 bool negate = *(p+markerInfo.endLen)=='!';
5764 if (negate) len++;
5765 size_t blkNameLen = dstrlen(blk.name);
5766 if (dstrncmp(p+len,blk.name,blkNameLen)==0 && // matching marker name
5767 dstrncmp(p+len+blkNameLen,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
5768 {
5769 //printf("Found end marker %s enabled=%d negate=%d\n",blk.name,blk.enabled,negate);
5770 return p+len+blkNameLen+markerInfo.closeLen;
5771 }
5772 else // not the right marker id
5773 {
5774 p++;
5775 }
5776 }
5777 else // not and end marker
5778 {
5779 p++;
5780 }
5781 }
5782 return p;
5783 };
5784
5785 DString result;
5786 result.reserve(s.length());
5787 const char *p = s.data();
5788 char c = 0;
5789 while ((c=*p))
5790 {
5791 if (c==markerInfo.markerChar) // potential start of marker
5792 {
5793 if (dstrncmp(p,markerInfo.beginStr,markerInfo.beginLen)==0) // start of begin marker
5794 {
5795 bool found = false;
5796 size_t len = markerInfo.beginLen;
5797 bool negate = *(p+len)=='!';
5798 if (negate) len++;
5799 for (const auto &blk : blockList)
5800 {
5801 size_t blkNameLen = dstrlen(blk.name);
5802 if (dstrncmp(p+len,blk.name,blkNameLen)==0 && // matching marker name
5803 dstrncmp(p+len+blkNameLen,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
5804 {
5805 bool blockEnabled = blk.enabled!=negate;
5806 //printf("Found start marker %s enabled=%d negate=%d\n",blk.name,blk.enabled,negate);
5807 p+=len+blkNameLen+markerInfo.closeLen;
5808 if (!blockEnabled) // skip until the end of the block
5809 {
5810 //printf("skipping block\n");
5811 p=skipBlock(p,blk);
5812 }
5813 found=true;
5814 break;
5815 }
5816 }
5817 if (!found) // unknown marker id
5818 {
5819 result+=c;
5820 p++;
5821 }
5822 }
5823 else if (dstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // start of end marker
5824 {
5825 bool found = false;
5826 size_t len = markerInfo.endLen;
5827 bool negate = *(p+len)=='!';
5828 if (negate) len++;
5829 for (const auto &blk : blockList)
5830 {
5831 size_t blkNameLen = dstrlen(blk.name);
5832 if (dstrncmp(p+len,blk.name,blkNameLen)==0 && // matching marker name
5833 dstrncmp(p+len+blkNameLen,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
5834 {
5835 //printf("Found end marker %s enabled=%d negate=%d\n",blk.name,blk.enabled,negate);
5836 p+=len+blkNameLen+markerInfo.closeLen;
5837 found=true;
5838 break;
5839 }
5840 }
5841 if (!found) // unknown marker id
5842 {
5843 result+=c;
5844 p++;
5845 }
5846 }
5847 else // not a start or end marker
5848 {
5849 result+=c;
5850 p++;
5851 }
5852 }
5853 else // not a marker character
5854 {
5855 result+=c;
5856 p++;
5857 }
5858 }
5859 //printf("====\n%s\n-----\n%s\n~~~~\n",qPrint(s),qPrint(result));
5860 return result;
5861}
uint32_t dstrlen(const char *str)
Returns the length of string str, or 0 if a null pointer is passed.
Definition dstring.h:44

References SelectionMarkerInfo::beginLen, SelectionMarkerInfo::beginStr, SelectionMarkerInfo::closeLen, SelectionMarkerInfo::closeStr, DString::data(), dstrlen(), dstrncmp(), DString::empty(), SelectionMarkerInfo::endLen, SelectionMarkerInfo::endStr, DString::length(), SelectionMarkerInfo::markerChar, DString::reserve(), and selectBlocks().

Referenced by selectBlocks(), substituteHtmlKeywords(), and substituteLatexKeywords().

◆ showDate()

DString showDate ( const DString & fmt)

Definition at line 2634 of file util.cpp.

2635{
2636 // get the current date and time
2637 std::tm dat{};
2638 int specFormat=0;
2639 DString specDate = "";
2640 DString err = dateTimeFromString(specDate,dat,specFormat);
2641
2642 // do the conversion
2643 int usedFormat=0;
2644 return formatDateTime(fmt,dat,usedFormat);
2645}
DString formatDateTime(const DString &format, const std::tm &dt, int &formatUsed)
Return a string representation for a given std::tm value that is formatted according to the pattern g...
Definition datetime.cpp:174
DString dateTimeFromString(const DString &spec, std::tm &dt, int &format)
Returns the filled in std::tm for a given string representing a date and/or time.
Definition datetime.cpp:133
Definition message.h:144

References dateTimeFromString(), err, formatDateTime(), and showDate().

Referenced by processMarkup(), showDate(), substituteHtmlKeywords(), and substituteLatexKeywords().

◆ stackTrace()

void stackTrace ( )

Definition at line 4810 of file util.cpp.

4811{
4812#ifdef TRACINGSUPPORT
4813 void *backtraceFrames[128];
4814 int frameCount = backtrace(backtraceFrames, 128);
4815 const size_t cmdLen = 40960;
4816 static char cmd[cmdLen];
4817 char *p = cmd;
4818 p += snprintf(p,cmdLen,"/usr/bin/atos -p %d ", (int)getpid());
4819 for (int x = 0; x < frameCount; x++)
4820 {
4821 p += snprintf(p,cmdLen,"%p ", backtraceFrames[x]);
4822 }
4823 fprintf(stderr,"========== STACKTRACE START ==============\n");
4824 if (FILE *fp = Portable::popen(cmd, "r"))
4825 {
4826 char resBuf[512];
4827 while (size_t len = fread(resBuf, 1, sizeof(resBuf), fp))
4828 {
4829 fwrite(resBuf, 1, len, stderr);
4830 }
4831 Portable::pclose(fp);
4832 }
4833 fprintf(stderr,"============ STACKTRACE END ==============\n");
4834 //fprintf(stderr,"%s\n", frameStrings[x]);
4835#endif
4836}

References Portable::pclose(), Portable::popen(), and stackTrace().

Referenced by recodeString(), and stackTrace().

◆ stripAnonymousNamespaceScope()

DString stripAnonymousNamespaceScope ( const DString & s)

Definition at line 183 of file util.cpp.

184{
185 int i=0,p=0,l=0;
186 DString newScope;
187 int sl = static_cast<int>(s.length());
188 while ((i=getScopeFragment(s,p,&l))!=-1)
189 {
190 //printf("Scope fragment %s\n",qPrint(s.mid(i,l)));
191 if (Doxygen::namespaceLinkedMap->find(s.left(i+l))!=nullptr)
192 {
193 if (s.at(i)!='@')
194 {
195 if (!newScope.empty()) newScope+="::";
196 newScope+=s.mid(i,l);
197 }
198 }
199 else if (i<sl)
200 {
201 if (!newScope.empty()) newScope+="::";
202 newScope+=s.right(sl-i);
203 goto done;
204 }
205 p=i+l;
206 }
207done:
208 //printf("stripAnonymousNamespaceScope('%s')='%s'\n",qPrint(s),qPrint(newScope));
209 return newScope;
210}

References DString::at(), DString::empty(), getScopeFragment(), DString::left(), DString::length(), DString::mid(), Doxygen::namespaceLinkedMap, DString::right(), and stripAnonymousNamespaceScope().

Referenced by addMemberFunction(), addPageToContext(), addVariable(), buildNamespaceList(), computeTemplateClassRelations(), extractClassName(), findGroupScope(), findUsingDeclImports(), findUsingDirectives(), resolveClassNestingRelations(), and stripAnonymousNamespaceScope().

◆ stripExtension()

◆ stripExtensionGeneral()

◆ stripFromIncludePath()

DString stripFromIncludePath ( const DString & path)

strip part of path if it matches one of the paths in the Config_getList(INCLUDE_PATH) list

Definition at line 259 of file util.cpp.

260{
261 return stripFromPath(path,Config_getList(STRIP_FROM_INC_PATH));
262}
DString stripFromPath(const DString &path)
Definition util.cpp:251

References Config_getList, stripFromIncludePath(), and stripFromPath().

Referenced by MemberDefImpl::_writeGroupInclude(), addIncludeFile(), FileNameLinkedMap::findFileDef(), FileNameLinkedMap::showFileDefMatches(), and stripFromIncludePath().

◆ stripFromPath()

◆ stripIndentation()

DString stripIndentation ( const DString & s,
bool skipFirstLine = false )

Definition at line 5266 of file util.cpp.

5267{
5268 if (s.empty()) return s; // empty string -> we're done
5269
5270 //printf("stripIndentation:\n%s\n------\n",qPrint(s));
5271 // compute minimum indentation over all lines
5272 const char *p=s.data();
5273 char c=0;
5274 int indent=0;
5275 int minIndent=1000000; // "infinite"
5276 bool searchIndent=true;
5277 int tabSize=Config_getInt(TAB_SIZE);
5278 bool skipFirst = skipFirstLine;
5279 while ((c=*p++))
5280 {
5281 if (c=='\t') { indent+=tabSize - (indent%tabSize); }
5282 else if (c=='\n') { indent=0; searchIndent=true; skipFirst=false; }
5283 else if (c==' ') { indent++; }
5284 else if (searchIndent && !skipFirst)
5285 {
5286 searchIndent=false;
5287 if (indent<minIndent) minIndent=indent;
5288 }
5289 }
5290
5291 // no indent to remove -> we're done
5292 if (minIndent==0) return substitute(s,"@ilinebr","\\ilinebr");
5293
5294 // remove minimum indentation for each line
5295 TextStream result;
5296 p=s.data();
5297 indent=0;
5298 skipFirst=skipFirstLine;
5299 while ((c=*p++))
5300 {
5301 if (c=='\n') // start of new line
5302 {
5303 indent=0;
5304 result << c;
5305 skipFirst=false;
5306 }
5307 else if (indent<minIndent && !skipFirst) // skip until we reach minIndent
5308 {
5309 if (c=='\t')
5310 {
5311 int newIndent = indent+tabSize-(indent%tabSize);
5312 int i=newIndent;
5313 while (i>minIndent) // if a tab crosses the minIndent boundary fill the rest with spaces
5314 {
5315 result << ' ';
5316 i--;
5317 }
5318 indent=newIndent;
5319 }
5320 else // space
5321 {
5322 indent++;
5323 }
5324 }
5325 else if (c=='\\' && literal_at(p,"ilinebr "))
5326 // we also need to remove the indentation after a \ilinebr command at the end of a line
5327 {
5328 result << "\\ilinebr ";
5329 p+=8;
5330 int skipAmount=0;
5331 for (int j=0;j<minIndent;j++) if (*(p+j)==' ') skipAmount++; // test to see if we have the indent
5332 if (skipAmount==minIndent)
5333 {
5334 p+=skipAmount; // remove the indent
5335 }
5336 }
5337 else if (c=='@' && literal_at(p,"ilinebr"))
5338 {
5339 result << "\\ilinebr";
5340 p+=7;
5341 }
5342 else // copy anything until the end of the line
5343 {
5344 result << c;
5345 }
5346 }
5347
5348 //printf("stripIndentation: result=\n%s\n------\n",qPrint(result.str()));
5349
5350 return result.str();
5351}

References Config_getInt, DString::data(), DString::empty(), literal_at(), TextStream::str(), stripIndentation(), and substitute().

Referenced by handleCommentBlock(), handleCommentBlock(), handleCommentBlock(), handleParametersCommentBlocks(), DocPara::handleStartCode(), MarkdownOutlineParser::parseInput(), processMarkup(), and stripIndentation().

◆ stripIndentationVerbatim()

void stripIndentationVerbatim ( DString & doc,
size_t indentationLevel,
bool skipFirstLine = true )

Definition at line 5355 of file util.cpp.

5356{
5357 //printf("stripIndentationVerbatim(level=%d):\n%s\n------\n",indentationLevel,qPrint(doc));
5358 if (indentationLevel <= 0 || doc.empty()) return; // nothing to strip
5359
5360 // by stripping content the string will only become shorter so we write the results
5361 // back into the input string and then resize it at the end.
5362 char c = 0;
5363 const char *src = doc.data();
5364 char *dst = doc.rawData();
5365 bool insideIndent = !skipFirstLine; // skip the initial line from stripping
5366 size_t cnt = 0;
5367 if (!skipFirstLine) cnt = indentationLevel;
5368 while ((c=*src++))
5369 {
5370 // invariant: dst<=src
5371 switch(c)
5372 {
5373 case '\n':
5374 *dst++ = c;
5375 insideIndent = true;
5376 cnt = indentationLevel;
5377 break;
5378 case ' ':
5379 if (insideIndent)
5380 {
5381 if (cnt>0) // count down the spacing until the end of the indent
5382 {
5383 cnt--;
5384 }
5385 else // reached the end of the indent, start of the part of the line to keep
5386 {
5387 insideIndent = false;
5388 *dst++ = c;
5389 }
5390 }
5391 else // part after indent, copy to the output
5392 {
5393 *dst++ = c;
5394 }
5395 break;
5396 default:
5397 insideIndent = false;
5398 *dst++ = c;
5399 break;
5400 }
5401 }
5402 doc.resize(static_cast<uint32_t>(dst-doc.data()));
5403 //printf("stripIndentationVerbatim: result=\n%s\n------\n",qPrint(doc));
5404}
void resize(size_t newlen)
Definition dstring.h:214
char * rawData()
Returns a writable pointer to the data.
Definition dstring.h:171

References DString::data(), DString::empty(), DString::rawData(), DString::resize(), and stripIndentationVerbatim().

Referenced by processMarkup(), MemberDefImpl::setInitializer(), and stripIndentationVerbatim().

◆ stripLeadingAndTrailingEmptyLines()

DString stripLeadingAndTrailingEmptyLines ( const DString & s,
int & docLine )

Special version of DString::stripWhiteSpace() that only strips completely blank lines.

Parameters
sthe string to be stripped
docLinethe line number corresponding to the start of the string. This will be adjusted based on the number of lines stripped from the start.
Returns
The stripped string.

Definition at line 4355 of file util.cpp.

4356{
4357 if (s.empty()) return DString();
4358 const char *p = s.data();
4359
4360 // search for leading empty lines
4361 int i=0,li=-1,l=static_cast<int>(s.length());
4362 char c = 0;
4363 while ((c=*p))
4364 {
4365 if (c==' ' || c=='\t' || c=='\r') { i++; p++; }
4366 else if (c=='\\' && literal_at(p,"\\ilinebr")) { i+=8; li=i; p+=8; }
4367 else if (c=='\n') { i++; li=i; docLine++; p++; }
4368 else break;
4369 }
4370
4371 // search for trailing empty lines
4372 int b=l-1,bi=-1;
4373 p=s.data()+b;
4374 while (b>=0)
4375 {
4376 c=*p;
4377 if (c==' ' || c=='\t' || c=='\r') { b--; p--; }
4378 else if (c=='r' && b>=7 && literal_at(p-7,"\\ilinebr")) { bi=b-7; b-=8; p-=8; }
4379 else if (c=='>' && b>=11 && literal_at(p-11,"\\ilinebr<br>")) { bi=b-11; b-=12; p-=12; }
4380 else if (c=='\n') { bi=b; b--; p--; }
4381 else break;
4382 }
4383
4384 // return whole string if no leading or trailing lines where found
4385 if (li==-1 && bi==-1) return s;
4386
4387 // return substring
4388 if (bi==-1) bi=l;
4389 if (li==-1) li=0;
4390 if (bi<=li) return DString(); // only empty lines
4391 //printf("docLine='%s' len=%d li=%d bi=%d\n",qPrint(s),s.length(),li,bi);
4392 return s.mid(li,bi-li);
4393}

References DString::data(), DString::DString(), DString::empty(), DString::length(), literal_at(), DString::mid(), and stripLeadingAndTrailingEmptyLines().

Referenced by DefinitionImpl::_setBriefDescription(), DefinitionImpl::_setDocumentation(), addDirPrefix(), DocGroup::addDocs(), VHDLOutlineParser::checkInlineCode(), DocPara::handleCommand(), CommentScanner::parseCommentBlock(), and stripLeadingAndTrailingEmptyLines().

◆ stripPath()

DString stripPath ( const DString & s)

Definition at line 4289 of file util.cpp.

4290{
4291 DString result=s;
4292 if (size_t i=result.rfind('/'); i!=DString::npos)
4293 {
4294 result=result.mid(i+1);
4295 }
4296 if (size_t i=result.rfind('\\'); i!=DString::npos)
4297 {
4298 result=result.mid(i+1);
4299 }
4300 return result;
4301}

References DString::mid(), DString::npos, DString::rfind(), and stripPath().

Referenced by addDirPrefix(), LatexGenerator::addLabel(), anonymous_namespace{tagreader.cpp}::TagFileParser::buildLists(), RTFGenerator::endDoxyAnchor(), LatexGenerator::endIndexItem(), LatexGenerator::endIndexValue(), LatexGenerator::endTitleHead(), makeBaseName(), objectLinkToString(), objectLinkToString(), objectLinkToString(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), XmlDocVisitor::operator()(), XmlDocVisitor::operator()(), XmlDocVisitor::operator()(), XmlDocVisitor::operator()(), XmlDocVisitor::operator()(), XmlDocVisitor::operator()(), DotFilePatcher::run(), SearchIndexExternal::setCurrentDoc(), DocbookGenerator::startDoxyAnchor(), LatexGenerator::startDoxyAnchor(), DocbookGenerator::startFile(), LatexGenerator::startFile(), RTFGenerator::startFile(), DocbookDocVisitor::startLink(), LatexDocVisitor::startLink(), RTFDocVisitor::startLink(), DocbookDocVisitor::startMermaidFile(), LatexDocVisitor::startMermaidFile(), LatexDocVisitor::startPlantUmlFile(), DocbookGenerator::startSection(), LatexGenerator::startSection(), LatexGenerator::startTextLink(), RTFGenerator::startTextLink(), stripPath(), substituteHtmlKeywords(), substituteLatexKeywords(), LatexGenerator::writeAnchor(), RTFGenerator::writeAnchor(), LatexCodeGenerator::writeCodeLink(), RTFCodeGenerator::writeCodeLink(), DocbookCodeGenerator::writeCodeLinkLine(), MemberList::writeDeclarations(), DocbookDocVisitor::writeDiaFile(), writeDocbookLink(), LatexCodeGenerator::writeLineNumber(), RTFCodeGenerator::writeLineNumber(), DocbookDocVisitor::writeMermaidFile(), LatexDocVisitor::writeMermaidFile(), DocbookDocVisitor::writePlantUMLFile(), LatexDocVisitor::writePlantUMLFile(), RTFGenerator::writeRTFReference(), and RTFGenerator::writeStartAnnoItem().

◆ stripScope()

DString stripScope ( const DString & name)

Strips the scope from a name. Examples: A::B will return A and A<T>::B<N::C<D> > will return A<T>.

Definition at line 3176 of file util.cpp.

3177{
3178 DString result = name;
3179 int l = static_cast<int>(result.length());
3180 int p = 0;
3181 bool done = false;
3182 bool skipBracket=false; // if brackets do not match properly, ignore them altogether
3183 int count=0;
3184 int round=0;
3185
3186 do
3187 {
3188 p=l-1; // start at the end of the string
3189 while (p>=0 && count>=0)
3190 {
3191 char c=result.at(p);
3192 switch (c)
3193 {
3194 case ':':
3195 // only exit in the case of ::
3196 //printf("stripScope(%s)=%s\n",name,qPrint(result.right(l-p-1)));
3197 if (p>0 && result.at(p-1)==':' && (count==0 || skipBracket))
3198 {
3199 return result.right(l-p-1);
3200 }
3201 p--;
3202 break;
3203 case '>':
3204 if (skipBracket) // we don't care about brackets
3205 {
3206 p--;
3207 }
3208 else // count open/close brackets
3209 {
3210 if (p>0 && result.at(p-1)=='>') // skip >> operator
3211 {
3212 p-=2;
3213 break;
3214 }
3215 count=1;
3216 //printf("pos < = %d\n",p);
3217 p--;
3218 bool foundMatch=false;
3219 while (p>=0 && !foundMatch)
3220 {
3221 c=result.at(p--);
3222 switch (c)
3223 {
3224 case ')':
3225 round++;
3226 break;
3227 case '(':
3228 round--;
3229 break;
3230 case '>': // ignore > inside (...) to support e.g. (sizeof(T)>0) inside template parameters
3231 if (round==0) count++;
3232 break;
3233 case '<':
3234 if (round==0)
3235 {
3236 if (p>0)
3237 {
3238 if (result.at(p-1) == '<') // skip << operator
3239 {
3240 p--;
3241 break;
3242 }
3243 }
3244 count--;
3245 foundMatch = count==0;
3246 }
3247 break;
3248 default:
3249 //printf("c=%c count=%d\n",c,count);
3250 break;
3251 }
3252 }
3253 }
3254 //printf("pos > = %d\n",p+1);
3255 break;
3256 default:
3257 p--;
3258 }
3259 }
3260 done = count==0 || skipBracket; // reparse if brackets do not match
3261 skipBracket=true;
3262 }
3263 while (!done); // if < > unbalanced repeat ignoring them
3264 //printf("stripScope(%s)=%s\n",name,name);
3265 return name;
3266}

References DString::at(), DString::length(), DString::right(), and stripScope().

Referenced by DotClassGraph::addClass(), DocRef::DocRef(), getCanonicalTypeForIdentifier(), DefinitionImpl::Private::init(), DiagramItem::label(), stripScope(), NamespaceDefImpl::writeBriefDescription(), and ClassDefImpl::writeIncludeFilesForSlice().

◆ stripTemplateSpecifiersFromScope()

DString stripTemplateSpecifiersFromScope ( const DString & fullName,
bool parentOnly,
DString * pLastScopeStripped,
DString scopeName,
bool allowArtificial )

Strips template specifiers from scope fullName, except those that make up specialized classes. The switch parentOnly determines whether or not a template "at the end" of a scope should be considered, e.g. with parentOnly is true, A<T>::B<S> will try to strip <T> and not <S>, while parentOnly is false will strip both unless A<T> or B<S> are specialized template classes.

Definition at line 3866 of file util.cpp.

3871{
3872 //printf("stripTemplateSpecifiersFromScope(name=%s,scopeName=%s)\n",qPrint(fullName),qPrint(scopeName));
3873 size_t i=fullName.find('<');
3874 if (i==DString::npos) return fullName;
3875 DString result;
3876 size_t p=0;
3877 size_t l=fullName.length();
3878 while (i!=DString::npos)
3879 {
3880 //printf("1:result+=%s\n",qPrint(fullName.mid(p,i-p)));
3881 size_t e=i+1;
3882 int count=1;
3883 int round=0;
3884 while (e<l && count>0)
3885 {
3886 char c=fullName.at(e++);
3887 switch (c)
3888 {
3889 case '(': round++; break;
3890 case ')': if (round>0) round--; break;
3891 case '<': if (round==0) count++; break;
3892 case '>': if (round==0) count--; break;
3893 default:
3894 break;
3895 }
3896 }
3897 size_t si = fullName.find("::",e);
3898
3899 if (parentOnly && si==DString::npos) break;
3900 // we only do the parent scope, so we stop here if needed
3901
3902 result+=fullName.mid(p,i-p);
3903 //printf(" trying %s\n",qPrint(mergeScopes(scopeName,result+fullName.mid(i,e-i))));
3904 ClassDef *cd = getClass(mergeScopes(scopeName,result+fullName.mid(i,e-i)));
3905 if (cd!=nullptr && (allowArtificial || !cd->isArtificial()))
3906 {
3907 result+=fullName.mid(i,e-i);
3908 //printf(" 2:result+=%s\n",qPrint(fullName.mid(i,e-i-1)));
3909 }
3910 else if (pLastScopeStripped)
3911 {
3912 //printf(" last stripped scope '%s'\n",qPrint(fullName.mid(i,e-i)));
3913 *pLastScopeStripped=fullName.mid(i,e-i);
3914 }
3915 p=e;
3916 i=fullName.find('<',p);
3917 }
3918 result+=fullName.right(l-p);
3919 //printf("3:result+=%s\n",qPrint(fullName.right(l-p)));
3920 //printf("end result=%s\n",qPrint(result));
3921 return result;
3922}
virtual bool isArtificial() const =0
DString mergeScopes(const DString &leftScope, const DString &rightScope)
Definition util.cpp:3933

References DString::at(), DString::find(), getClass(), Definition::isArtificial(), DString::length(), mergeScopes(), DString::mid(), DString::npos, DString::right(), and stripTemplateSpecifiersFromScope().

Referenced by addClassToContext(), addMemberFunction(), addVariable(), buildFunctionList(), computeTemplateClassRelations(), extractClassName(), findMember(), findScopeFromQualifiedName(), findUsingDeclImports(), getCanonicalTypeForIdentifier(), SymbolResolver::Private::getResolvedSymbolRec(), SymbolResolver::Private::getResolvedTypeRec(), SymbolResolver::Private::newResolveTypedef(), resolveLink(), and stripTemplateSpecifiersFromScope().

◆ substituteKeywords()

DString substituteKeywords ( const DString & file,
const DString & s,
const KeywordSubstitutionList & keywords )

Definition at line 2561 of file util.cpp.

2562{
2563 std::string substRes;
2564 int line = 1;
2565 const char *p = s.data();
2566 if (p)
2567 {
2568 // reserve some room for expansion
2569 substRes.reserve(s.length()+1024);
2570 char c = 0;
2571 while ((c=*p))
2572 {
2573 bool found = false;
2574 if (c=='$')
2575 {
2576 for (const auto &kw : keywords)
2577 {
2578 size_t keyLen = dstrlen(kw.keyword);
2579 if (dstrncmp(p,kw.keyword,keyLen)==0)
2580 {
2581 const char *startArg = p+keyLen;
2582 bool expectParam = std::holds_alternative<KeywordSubstitution::GetValueWithParam>(kw.getValueVariant);
2583 //printf("%s: expectParam=%d *startArg=%c\n",kw.keyword,expectParam,*startArg);
2584 if (expectParam && *startArg=='(') // $key(value)
2585 {
2586 size_t j=1;
2587 const char *endArg = nullptr;
2588 while ((c=*(startArg+j)) && c!=')' && c!='\n' && c!=0) j++;
2589 if (c==')') endArg=startArg+j;
2590 if (endArg)
2591 {
2592 DString value = DString(startArg+1).left(endArg-startArg-1);
2593 auto &&getValue = std::get<KeywordSubstitution::GetValueWithParam>(kw.getValueVariant);
2594 substRes+=getValue(value).str();
2595 p=endArg+1;
2596 //printf("found '%s'->'%s'\n",kw.keyword,qPrint(getValue(value)));
2597 }
2598 else
2599 {
2600 //printf("missing argument\n");
2601 warn(file,line,"Missing argument for '{}'",kw.keyword);
2602 p+=keyLen;
2603 }
2604 }
2605 else if (!expectParam) // $key
2606 {
2607 auto &&getValue = std::get<KeywordSubstitution::GetValue>(kw.getValueVariant);
2608 substRes+=getValue().str();
2609 //printf("found '%s'->'%s'\n",kw.keyword,qPrint(getValue()));
2610 p+=keyLen;
2611 }
2612 else
2613 {
2614 //printf("%s %d Expected arguments, none specified '%s'\n",qPrint(file), line, qPrint(kw.keyword));
2615 warn(file,line,"Expected arguments for '{}' but none were specified",kw.keyword);
2616 p+=keyLen;
2617 }
2618 found = true;
2619 break;
2620 }
2621 }
2622 }
2623 if (!found) // copy
2624 {
2625 if (c=='\n') line++;
2626 substRes+=c;
2627 p++;
2628 }
2629 }
2630 }
2631 return substRes;
2632}

References DString::data(), DString::DString(), dstrlen(), dstrncmp(), DString::left(), DString::length(), substituteKeywords(), and warn.

Referenced by substituteHtmlKeywords(), substituteKeywords(), and substituteLatexKeywords().

◆ substituteTemplateArgumentsInString()

DString substituteTemplateArgumentsInString ( const DString & name,
const ArgumentList & formalArgs,
const ArgumentList * actualArgs )

Substitutes any occurrence of a formal argument from argument list formalArgs in name by the corresponding actual argument in argument list actualArgs. The result after substitution is returned as a string. The argument name is used to prevent recursive substitution.

Definition at line 3704 of file util.cpp.

3708{
3709 AUTO_TRACE("name={} formalArgs={} actualArgs={}",nm,argListToString(formalArgs),actualArgs ? argListToString(*actualArgs) : DString());
3710 if (formalArgs.empty()) return nm;
3711 DString result;
3712
3713 static const reg::Ex re(R"(\a\w*)");
3714 std::string name = nm.str();
3715 reg::Iterator it(name,re);
3717 size_t p=0;
3718
3719 for (; it!=end ; ++it)
3720 {
3721 const auto &match = *it;
3722 size_t i = match.position();
3723 size_t l = match.length();
3724 if (i>p) result += name.substr(p,i-p);
3725 DString n(match.str());
3727 if (actualArgs)
3728 {
3729 actIt = actualArgs->begin();
3730 }
3731 //printf(": name=%s\n",qPrint(name));
3732
3733 // if n is a template argument, then we substitute it
3734 // for its template instance argument.
3735 bool found=false;
3736 for (auto formIt = formalArgs.begin();
3737 formIt!=formalArgs.end() && !found;
3738 ++formIt
3739 )
3740 {
3741 Argument formArg = *formIt;
3742 Argument actArg;
3743 if (actualArgs && actIt!=actualArgs->end())
3744 {
3745 actArg = *actIt;
3746 }
3747 if (formArg.type.startsWith("class ") && formArg.name.empty())
3748 {
3749 formArg.name = formArg.type.mid(6);
3750 formArg.type = "class";
3751 }
3752 else if (formArg.type.startsWith("typename ") && formArg.name.empty())
3753 {
3754 formArg.name = formArg.type.mid(9);
3755 formArg.type = "typename";
3756 }
3757 else if (formArg.type.startsWith("class...")) // match 'class... name' to 'name...'
3758 {
3759 formArg.name += "...";
3760 formArg.type = formArg.type.left(5)+formArg.type.mid(8);
3761 }
3762 else if (formArg.type.startsWith("typename...")) // match 'typename... name' to 'name...'
3763 {
3764 formArg.name += "...";
3765 formArg.type = formArg.type.left(8)+formArg.type.mid(11);
3766 }
3767 //printf(": n=%s formArg->type='%s' formArg->name='%s' formArg->defval='%s' actArg->type='%s' actArg->name='%s' \n",
3768 // qPrint(n),qPrint(formArg.type),qPrint(formArg.name),qPrint(formArg.defval),qPrint(actArg.type),qPrint(actArg.name));
3769 if (formArg.type=="class" || formArg.type=="typename" || formArg.type.startsWith("template"))
3770 {
3771 if (formArg.name==n && actualArgs && actIt!=actualArgs->end() && !actArg.type.empty()) // base class is a template argument
3772 {
3773 static constexpr auto hasRecursion = [](const DString &prefix,const DString &nameArg,const DString &subst) -> bool
3774 {
3775 size_t ii=0;
3776 size_t pp=0;
3777
3778 ii = subst.find('<');
3779 //printf("prefix='%s' subst='%s'\n",qPrint(prefix.mid(prefix.length()-ii-2,ii+1)),qPrint(subst.left(ii+1)));
3780 if (ii!=DString::npos && prefix.length()>=ii+2 && prefix.mid(prefix.length()-ii-2,ii+1)==subst.left(ii+1))
3781 {
3782 return true; // don't replace 'A< ' with 'A< A<...', see issue #10951
3783 }
3784
3785 while ((ii=subst.find(nameArg,pp))!=DString::npos)
3786 {
3787 bool beforeNonWord = ii==0 || !isId(subst.at(ii-1));
3788 bool afterNonWord = subst.length()==ii+nameArg.length() || !isId(subst.at(ii+nameArg.length()));
3789 if (beforeNonWord && afterNonWord)
3790 {
3791 return true; // if nameArg=='A' then subst=='A::Z' or 'S<A>' or 'Z::A' should return true, but 'AA::ZZ' or 'BAH' should not match
3792 }
3793 pp=ii+nameArg.length();
3794 }
3795 return false;
3796 };
3797 // replace formal argument with the actual argument of the instance
3798 AUTO_TRACE_ADD("result={} n={} type={} hasRecursion={}",result,n,actArg.type,hasRecursion(result,n,actArg.type));
3799 if (!hasRecursion(result,n,actArg.type))
3800 // the scope guard is to prevent recursive lockup for
3801 // template<class A> class C : public<A::T>,
3802 // where A::T would become A::T::T here,
3803 // since n==A and actArg->type==A::T
3804 // see bug595833 for an example
3805 //
3806 // Also prevent recursive substitution if n is part of actArg.type, i.e.
3807 // n='A' in argType='S< A >' would produce 'S< S< A > >'
3808 {
3809 if (actArg.name.empty())
3810 {
3811 result += actArg.type;
3812 }
3813 else
3814 // for case where the actual arg is something like "unsigned int"
3815 // the "int" part is in actArg->name.
3816 {
3817 result += actArg.type+" "+actArg.name;
3818 }
3819 found=true;
3820 }
3821 }
3822 else if (formArg.name==n &&
3823 (actualArgs==nullptr || actIt==actualArgs->end()) &&
3824 !formArg.defval.empty() &&
3825 formArg.defval!=nm /* to prevent recursion */
3826 )
3827 {
3828 result += substituteTemplateArgumentsInString(formArg.defval,formalArgs,actualArgs);
3829 found=true;
3830 }
3831 }
3832 else if (formArg.name==n &&
3833 (actualArgs==nullptr || actIt==actualArgs->end()) &&
3834 !formArg.defval.empty() &&
3835 formArg.defval!=nm /* to prevent recursion */
3836 )
3837 {
3838 result += substituteTemplateArgumentsInString(formArg.defval,formalArgs,actualArgs);
3839 found=true;
3840 }
3841 if (actualArgs && actIt!=actualArgs->end())
3842 {
3843 actIt++;
3844 }
3845 }
3846 if (!found)
3847 {
3848 result += n;
3849 }
3850 p=i+l;
3851 }
3852 result+=name.substr(p);
3853 result=result.simplifyWhiteSpace();
3854 AUTO_TRACE_EXIT("result={}",result);
3855 return result.stripWhiteSpace();
3856}
typename Vec::const_iterator const_iterator
Definition arguments.h:69
DString substituteTemplateArgumentsInString(const DString &nm, const ArgumentList &formalArgs, const ArgumentList *actualArgs)
Definition util.cpp:3704

References argListToString(), AUTO_TRACE, AUTO_TRACE_ADD, AUTO_TRACE_EXIT, ArgumentList::begin(), Argument::defval, DString::DString(), ArgumentList::empty(), DString::empty(), ArgumentList::end(), end(), isId(), DString::left(), DString::mid(), Argument::name, DString::npos, prefix, DString::simplifyWhiteSpace(), DString::startsWith(), DString::str(), DString::stripWhiteSpace(), substituteTemplateArgumentsInString(), DString::substr(), and Argument::type.

Referenced by computeTemplateClassRelations(), MemberDefImpl::createTemplateInstanceMember(), findBaseClassesForClass(), findUsedClassesForClass(), SymbolResolver::Private::getResolvedSymbol(), SymbolResolver::Private::newResolveTypedef(), and substituteTemplateArgumentsInString().

◆ tempArgListToString()

DString tempArgListToString ( const ArgumentList & al,
SrcLangExt lang,
bool includeDefaults = true )

Definition at line 935 of file util.cpp.

936{
937 DString result;
938 if (al.empty()) return result;
939 result="<";
940 bool first=true;
941 for (const auto &a : al)
942 {
943 if (a.defval.empty() || includeDefault)
944 {
945 if (!first) result+=", ";
946 if (!a.name.empty()) // add template argument name
947 {
948 if (lang==SrcLangExt::Java || lang==SrcLangExt::CSharp)
949 {
950 result+=a.type+" ";
951 }
952 result+=a.name;
953 }
954 else // extract name from type
955 {
956 int i = static_cast<int>(a.type.length())-1;
957 while (i>=0 && isId(a.type.at(i))) i--;
958 if (i>0)
959 {
960 result+=a.type.right(a.type.length()-i-1);
961 if (a.type.find("...")!=DString::npos)
962 {
963 result+="...";
964 }
965 }
966 else // nothing found -> take whole name
967 {
968 result+=a.type;
969 }
970 }
971 if (!a.typeConstraint.empty() && lang==SrcLangExt::Java)
972 {
973 result+=" extends "; // TODO: now Java specific, C# has where...
974 result+=a.typeConstraint;
975 }
976 first=false;
977 }
978 }
979 result+=">";
980 return removeRedundantWhiteSpace(result);
981}

References ArgumentList::empty(), isId(), DString::npos, removeRedundantWhiteSpace(), DString::right(), and tempArgListToString().

Referenced by addMemberFunction(), ClassDefImpl::className(), findTemplateInstanceRelation(), makeQualifiedNameWithTemplateParameters(), searchTemplateSpecs(), tempArgListToString(), and writeDefArgumentList().

◆ transcodeCharacterStringToUTF8()

bool transcodeCharacterStringToUTF8 ( std::string & input,
const char * inputEncoding )

Definition at line 1086 of file util.cpp.

1087{
1088 const char *outputEncoding = "UTF-8";
1089 if (inputEncoding==nullptr || dstricmp(inputEncoding,outputEncoding)==0) return true;
1090 size_t inputSize=input.length();
1091 size_t outputSize=inputSize*4;
1092 DString output(outputSize, DString::ExplicitSize);
1093 void *cd = portable_iconv_open(outputEncoding,inputEncoding);
1094 if (cd==reinterpret_cast<void *>(-1))
1095 {
1096 return false;
1097 }
1098 bool ok=true;
1099 size_t iLeft=inputSize;
1100 size_t oLeft=outputSize;
1101 const char *inputPtr = input.data();
1102 char *outputPtr = output.rawData();
1103 if (!portable_iconv(cd, &inputPtr, &iLeft, &outputPtr, &oLeft))
1104 {
1105 outputSize-=static_cast<int>(oLeft);
1106 output.resize(outputSize);
1107 output.at(outputSize)='\0';
1108 // replace input
1109 input=output.str();
1110 //printf("iconv: input size=%d output size=%d\n[%s]\n",size,newSize,qPrint(srcBuf));
1111 }
1112 else
1113 {
1114 ok=false;
1115 }
1117 return ok;
1118}
@ ExplicitSize
Definition dstring.h:136
int dstricmp(const char *s1, const char *s2)
Definition dstring.cpp:439
int portable_iconv_close(void *cd)
size_t portable_iconv(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)
void * portable_iconv_open(const char *tocode, const char *fromcode)

References DString::at(), dstricmp(), DString::ExplicitSize, portable_iconv(), portable_iconv_close(), portable_iconv_open(), DString::rawData(), DString::resize(), DString::str(), and transcodeCharacterStringToUTF8().

Referenced by addDirPrefix(), LayoutDocManager::parse(), readCodeFragment(), and transcodeCharacterStringToUTF8().

◆ unescapeCharsInString()

DString unescapeCharsInString ( const DString & s)

Definition at line 2842 of file util.cpp.

2843{
2844 if (s.empty()) return s;
2845 bool caseSenseNames = useCaseSenseNames();
2846 DString result;
2847 result.reserve(s.length());
2848 const char *p = s.data();
2849 if (p)
2850 {
2851 char c = 0;
2852 while ((c=*p++))
2853 {
2854 if (c=='_') // 2 or 3 character escape
2855 {
2856 switch (*p)
2857 {
2858 case '_': result+=c; p++; break; // __ -> '_'
2859 case '1': result+=':'; p++; break; // _1 -> ':'
2860 case '2': result+='/'; p++; break; // _2 -> '/'
2861 case '3': result+='<'; p++; break; // _3 -> '<'
2862 case '4': result+='>'; p++; break; // _4 -> '>'
2863 case '5': result+='*'; p++; break; // _5 -> '*'
2864 case '6': result+='&'; p++; break; // _6 -> '&'
2865 case '7': result+='|'; p++; break; // _7 -> '|'
2866 case '8': result+='.'; p++; break; // _8 -> '.'
2867 case '9': result+='!'; p++; break; // _9 -> '!'
2868 case '0': // 3 character escape
2869 switch (*(p+1))
2870 {
2871 case '0': result+=','; p+=2; break; // _00 -> ','
2872 case '1': result+=' '; p+=2; break; // _01 -> ' '
2873 case '2': result+='{'; p+=2; break; // _02 -> '{'
2874 case '3': result+='}'; p+=2; break; // _03 -> '}'
2875 case '4': result+='?'; p+=2; break; // _04 -> '?'
2876 case '5': result+='^'; p+=2; break; // _05 -> '^'
2877 case '6': result+='%'; p+=2; break; // _06 -> '%'
2878 case '7': result+='('; p+=2; break; // _07 -> '('
2879 case '8': result+=')'; p+=2; break; // _08 -> ')'
2880 case '9': result+='+'; p+=2; break; // _09 -> '+'
2881 case 'a': result+='='; p+=2; break; // _0a -> '='
2882 case 'b': result+='$'; p+=2; break; // _0b -> '$'
2883 case 'c': result+='\\'; p+=2; break;// _0c -> '\'
2884 case 'd': result+='@'; p+=2; break; // _0d -> '@'
2885 case 'e': result+=']'; p+=2; break; // _0e -> ']'
2886 case 'f': result+='['; p+=2; break; // _0f -> '['
2887 case 'g': result+='#'; p+=2; break; // _0g -> '#'
2888 case 'h': result+='"'; p+=2; break; // _0h -> '"'
2889 case 'i': result+='~'; p+=2; break; // _0i -> '~'
2890 case 'j': result+='\''; p+=2; break;// _0j -> '\'
2891 case 'k': result+=';'; p+=2; break; // _0k -> ';'
2892 case 'l': result+='`'; p+=2; break; // _0l -> '`'
2893 default: // unknown escape, just pass underscore character as-is
2894 result+=c;
2895 break;
2896 }
2897 break;
2898 default:
2899 if (!caseSenseNames && c>='a' && c<='z') // lower to upper case escape, _a -> 'A'
2900 {
2901 result+=static_cast<char>(toupper(*p));
2902 p++;
2903 }
2904 else // unknown escape, pass underscore character as-is
2905 {
2906 result+=c;
2907 }
2908 break;
2909 }
2910 }
2911 else // normal character; pass as is
2912 {
2913 result+=c;
2914 }
2915 }
2916 }
2917 return result;
2918}

References DString::data(), DString::empty(), DString::length(), DString::reserve(), unescapeCharsInString(), and useCaseSenseNames().

Referenced by unescapeCharsInString().

◆ updateColumnCount()

size_t updateColumnCount ( const char * s,
size_t col )

Definition at line 6083 of file util.cpp.

6084{
6085 if (s)
6086 {
6087 const int tabSize = Config_getInt(TAB_SIZE);
6088 char c;
6089 while ((c=*s++))
6090 {
6091 switch(c)
6092 {
6093 case '\t': col+=tabSize - (col%tabSize);
6094 break;
6095 case '\n': col=0;
6096 break;
6097 default:
6098 col++;
6099 if (c<0) // multi-byte character
6100 {
6101 int numBytes = getUTF8CharNumBytes(c);
6102 for (int i=0;i<numBytes-1 && (c=*s++);i++) {} // skip over extra chars
6103 if (c==0) return col; // end of string half way a multibyte char
6104 }
6105 break;
6106 }
6107 }
6108 }
6109 return col;
6110}

References Config_getInt, getUTF8CharNumBytes(), and updateColumnCount().

Referenced by HtmlCodeGenerator::codify(), LatexCodeGenerator::codify(), ManCodeGenerator::codify(), RTFCodeGenerator::codify(), processMarkup(), updateColumnCount(), writeDocbookCodeString(), and writeXMLCodeString().

◆ updateLanguageMapping()

bool updateLanguageMapping ( const DString & extension,
const DString & parser )

Definition at line 4431 of file util.cpp.

4432{
4433 DString langName = language.lower();
4434 auto it1 = std::find_if(g_lang2extMap.begin(),g_lang2extMap.end(),
4435 [&langName](const auto &info) { return info.langName==langName; });
4436 if (it1 == g_lang2extMap.end()) return false;
4437
4438 // found the language
4439 SrcLangExt parserId = it1->parserId;
4440 DString extName = extension.lower();
4441 if (extName.empty()) return false;
4442 if (extName.at(0)!='.') extName.prepend(".");
4443 auto it2 = g_extLookup.find(extName.str());
4444 if (it2!=g_extLookup.end())
4445 {
4446 g_extLookup.erase(it2); // language was already register for this ext
4447 }
4448 //printf("registering extension %s\n",qPrint(extName));
4449 g_extLookup.emplace(extName.str(),parserId);
4450 if (!Doxygen::parserManager->registerExtension(extName,it1->parserName))
4451 {
4452 err("Failed to assign extension {} to parser {} for language {}\n",
4453 extName.data(),it1->parserName,language);
4454 }
4455 else
4456 {
4457 //msg("Registered extension {} to language parser {}...\n",
4458 // extName,language);
4459 }
4460 return true;
4461}
SrcLangExt
Definition types.h:207

References DString::at(), DString::data(), DString::empty(), err, g_extLookup, g_lang2extMap, DString::lower(), Doxygen::parserManager, DString::prepend(), DString::str(), and updateLanguageMapping().

Referenced by addCodeOnlyMappings(), addDirPrefix(), adjustConfiguration(), initDefaultExtensionMapping(), and updateLanguageMapping().

◆ useCaseSenseNames()

bool useCaseSenseNames ( )

Returns true if the names of the symbols can be case sensitive.

Definition at line 2746 of file util.cpp.

2747{
2748 auto caseSenseNames = Config_getEnum(CASE_SENSE_NAMES);
2749
2750 if (caseSenseNames == CASE_SENSE_NAMES_t::YES) return true;
2751 else if (caseSenseNames == CASE_SENSE_NAMES_t::NO) return false;
2753}
#define Config_getEnum(name)
Definition config.h:35
bool fileSystemIsCaseSensitive()
Definition portable.cpp:470

References Config_getEnum, Portable::fileSystemIsCaseSensitive(), and useCaseSenseNames().

Referenced by escapeCharsInString(), genericPatternMatch(), FileNameFn::searchKey(), unescapeCharsInString(), and useCaseSenseNames().

◆ writeExamples()

void writeExamples ( OutputList & ol,
const ExampleList & el )

Definition at line 836 of file util.cpp.

837{
838 auto replaceFunc = [&list,&ol](size_t entryIndex)
839 {
840 const auto &e = list[entryIndex];
845 // link for Html / man
846 //printf("writeObjectLink(file=%s)\n",qPrint(e->file));
847 ol.writeObjectLink(DString(),e.file,e.anchor,e.name);
849
853 // link for Latex / pdf with anchor because the sources
854 // are not hyperlinked (not possible with a verbatim environment).
855 ol.writeObjectLink(DString(),e.file,DString(),e.name);
857 };
858
859 writeMarkerList(ol, theTranslator->trWriteList(static_cast<int>(list.size())).str(), list.size(), replaceFunc);
860
861 ol.writeString(".");
862}
void disable(OutputType o)
void writeObjectLink(const DString &ref, const DString &file, const DString &anchor, const DString &name)
Definition outputlist.h:439
void writeString(const DString &text)
Definition outputlist.h:411
void pushGeneratorState()
void popGeneratorState()
virtual DString trWriteList(int numEntries)=0
Translator * theTranslator
Definition language.cpp:71
void writeMarkerList(OutputList &ol, const std::string &markerText, size_t numMarkers, std::function< void(size_t)> replaceFunc)
Definition util.cpp:785

References OutputList::disable(), Docbook, DString::DString(), Html, Latex, Man, OutputList::popGeneratorState(), OutputList::pushGeneratorState(), RTF, DString::str(), theTranslator, Translator::trWriteList(), writeExamples(), writeMarkerList(), OutputList::writeObjectLink(), and OutputList::writeString().

Referenced by MemberDefImpl::_writeExamples(), ClassDefImpl::writeDetailedDocumentationBody(), and writeExamples().

◆ writeInlineGraph()

DString writeInlineGraph ( const DString & baseName,
const DString & extension,
const DString & content,
bool & exists )

Thread-safe function to write a string representing an inline graph to a file. The contents will be used to create a hash that will be used to make the name unique.

Parameters
[in]baseNamethe base name of the file to write including path.
[in]extensionthe file extension to use.
[in]contentthe data to write to the file
[out]existsis set to true if the file was already written before.
Returns
the name of the file written or an empty string in case of an error.

Definition at line 6155 of file util.cpp.

6156{
6157 DString fileName = baseName + md5str(content.view()) + extension;
6158 { // ==== start atomic section
6159 std::lock_guard lock(writeFileContents_lock);
6160 auto it=writeFileContents_set.find(fileName.str());
6161 exists = it!=writeFileContents_set.end();
6162 if (!exists)
6163 {
6164 writeFileContents_set.insert(fileName.str());
6165 if (auto file = Portable::openOutputStream(fileName); file.is_open())
6166 {
6167 file.write( content.data(), content.length() );
6168 file.close();
6169 }
6170 else
6171 {
6172 err("Could not open file {} for writing\n",fileName);
6173 return DString();
6174 }
6175 }
6176 } // ==== end atomic section
6177 return fileName;
6178}
static std::mutex writeFileContents_lock
Definition util.cpp:6152

References DString::data(), DString::DString(), err, DString::length(), md5str(), Portable::openOutputStream(), DString::str(), DString::view(), writeFileContents_lock, writeFileContents_set, and writeInlineGraph().

Referenced by DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), and writeInlineGraph().

◆ writeMarkerList() [1/2]

DString writeMarkerList ( const std::string & markerText,
size_t numMarkers,
std::function< DString(size_t)> replaceFunc )

Definition at line 808 of file util.cpp.

810{
811 DString result;
812 static const reg::Ex marker(R"(@(\d+))");
813 reg::Iterator it(markerText,marker);
815 size_t index=0;
816 for ( ; it!=end ; ++it)
817 {
818 const auto &match = *it;
819 size_t newIndex = match.position();
820 size_t matchLen = match.length();
821 result += markerText.substr(index,newIndex-index);
822 unsigned long entryIndex = std::stoul(match[1].str());
823 if (entryIndex<static_cast<unsigned long>(numMarkers))
824 {
825 result+=replaceFunc(entryIndex);
826 }
827 index=newIndex+matchLen;
828 }
829 if (index<markerText.size())
830 {
831 result += markerText.substr(index);
832 }
833 return result;
834}

References end(), DString::substr(), and writeMarkerList().

◆ writeMarkerList() [2/2]

void writeMarkerList ( OutputList & ol,
const std::string & markerText,
size_t numMarkers,
std::function< void(size_t)> replaceFunc )

Definition at line 785 of file util.cpp.

787{
788 static const reg::Ex marker(R"(@(\d+))");
789 reg::Iterator it(markerText,marker);
791 size_t index=0;
792 for ( ; it!=end ; ++it)
793 {
794 const auto &match = *it;
795 size_t newIndex = match.position();
796 size_t matchLen = match.length();
797 ol.parseText(markerText.substr(index,newIndex-index));
798 unsigned long entryIndex = std::stoul(match[1].str());
799 if (entryIndex<static_cast<unsigned long>(numMarkers))
800 {
801 replaceFunc(entryIndex);
802 }
803 index=newIndex+matchLen;
804 }
805 ol.parseText(markerText.substr(index));
806}
void parseText(const DString &textStr)

References end(), OutputList::parseText(), and writeMarkerList().

Referenced by MemberDefImpl::_writeReimplementedBy(), DefinitionImpl::_writeSourceRefList(), RequirementManager::generatePage(), recodeString(), writeExamples(), ClassDefImpl::writeInheritanceGraph(), writeMarkerList(), writeMarkerList(), and DefinitionImpl::writeRequirementRefs().

◆ writeTypeConstraints()

void writeTypeConstraints ( OutputList & ol,
const Definition * d,
const ArgumentList & al )

Definition at line 4783 of file util.cpp.

4784{
4785 if (al.empty()) return;
4787 for (const Argument &a : al)
4788 {
4790 ol.parseText(a.name);
4791 ol.endConstraintParam();
4793 linkifyText(TextGeneratorOLImpl(ol),a.type,LinkifyTextOptions().setScope(d));
4794 ol.endConstraintType();
4796 ol.generateDoc(d->docFile(),
4797 d->docLine(),
4798 d,
4799 nullptr,
4800 a.docs,
4801 DocOptions()
4802 .setIndexWords(true));
4803 ol.endConstraintDocs();
4804 }
4805 ol.endConstraintList();
4806}
virtual int docLine() const =0
void endConstraintType()
Definition outputlist.h:714
void endConstraintList()
Definition outputlist.h:720
void startConstraintList(const DString &header)
Definition outputlist.h:706
void startConstraintParam()
Definition outputlist.h:708
void startConstraintDocs()
Definition outputlist.h:716
void startConstraintType()
Definition outputlist.h:712
void endConstraintDocs()
Definition outputlist.h:718
void endConstraintParam()
Definition outputlist.h:710
void generateDoc(const DString &fileName, int startLine, const Definition *ctx, const MemberDef *md, const DString &docStr, const DocOptions &options)
TextGeneratorOLImpl(OutputList &ol)
virtual DString trTypeConstraints()=0
void linkifyText(const TextGeneratorIntf &out, const DString &text, const LinkifyTextOptions &options)

References Definition::docFile(), Definition::docLine(), ArgumentList::empty(), OutputList::endConstraintDocs(), OutputList::endConstraintList(), OutputList::endConstraintParam(), OutputList::endConstraintType(), OutputList::generateDoc(), linkifyText(), OutputList::parseText(), OutputList::startConstraintDocs(), OutputList::startConstraintList(), OutputList::startConstraintParam(), OutputList::startConstraintType(), TextGeneratorOLImpl::TextGeneratorOLImpl(), theTranslator, Translator::trTypeConstraints(), and writeTypeConstraints().

Referenced by MemberDefImpl::_writeTypeConstraints(), recodeString(), ClassDefImpl::writeDetailedDocumentationBody(), and writeTypeConstraints().