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 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

class  TextGeneratorIntf
 Abstract interface for a hyperlinked text fragment. More...
class  TextGeneratorOLImpl
 Implements TextGeneratorIntf for an OutputDocInterface stream. More...
struct  GetDefInput
struct  GetDefResult
struct  SelectionBlock
struct  SelectionMarkerInfo
struct  KeywordSubstitution
struct  ColoredImgDataItem
 Data associated with a HSV colored image. More...

Typedefs

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

Functions

QCString langToString (SrcLangExt lang)
 Returns a string representation of lang.
QCString getLanguageSpecificSeparator (SrcLangExt lang, bool classScope=FALSE)
 Returns the scope separator to use given the programming language lang.
void linkifyText (const TextGeneratorIntf &ol, const Definition *scope, const FileDef *fileScope, const Definition *self, const QCString &text, bool autoBreak=FALSE, bool external=TRUE, bool keepSpaces=FALSE, int indentLevel=0)
QCString fileToString (const QCString &name, bool filter=FALSE, bool isSourceCode=FALSE)
GetDefResult getDefs (const GetDefInput &input)
QCString getFileFilter (const QCString &name, bool isSourceCode)
bool resolveRef (const QCString &scName, const QCString &name, bool inSeeBlock, const Definition **resContext, const MemberDef **resMember, SrcLangExt lang, bool lookForSpecializations=TRUE, const FileDef *currentFile=nullptr, bool checkScope=FALSE)
bool resolveLink (const QCString &scName, const QCString &lr, bool inSeeBlock, const Definition **resContext, QCString &resAnchor, SrcLangExt lang, const QCString &prefix=QCString())
void generateFileRef (OutputList &ol, const QCString &, const QCString &linkTxt=QCString())
void writePageRef (OutputList &ol, const QCString &cn, const QCString &mn)
bool matchArguments2 (const Definition *srcScope, const FileDef *srcFileScope, const QCString &srcReturnType, const ArgumentList *srcAl, const Definition *dstScope, const FileDef *dstFileScope, const QCString &dstReturnType, const ArgumentList *dstAl, bool checkCV, SrcLangExt lang)
void mergeArguments (ArgumentList &, ArgumentList &, bool forceNameOverwrite=FALSE)
bool matchTemplateArguments (const ArgumentList &srcAl, const ArgumentList &dstAl)
QCString substituteClassNames (const QCString &s)
QCString selectBlocks (const QCString &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 QCString &s, const QCString fileName, const SelectionMarkerInfo &markerInfo)
QCString removeEmptyLines (const QCString &s)
FileDeffindFileDef (const FileNameLinkedMap *fnMap, const QCString &n, bool &ambig)
QCString findFilePath (const QCString &file, bool &ambig)
QCString showFileDefMatches (const FileNameLinkedMap *fnMap, const QCString &n)
EntryType guessSection (const QCString &name)
bool isId (int c)
bool isIdJS (int c)
QCString removeRedundantWhiteSpace (const QCString &s)
QCString inlineArgListToDoc (const ArgumentList &al)
QCString inlineTemplateArgListToDoc (const ArgumentList &al)
QCString argListToString (const ArgumentList &al, bool useCanonicalType=FALSE, bool showDefVals=TRUE)
QCString tempArgListToString (const ArgumentList &al, SrcLangExt lang, bool includeDefaults=true)
QCString generateMarker (int id)
void writeExamples (OutputList &ol, const ExampleList &el)
QCString stripAnonymousNamespaceScope (const QCString &s)
QCString stripFromPath (const QCString &path)
QCString stripFromIncludePath (const QCString &path)
bool rightScopeMatch (const QCString &scope, const QCString &name)
bool leftScopeMatch (const QCString &scope, const QCString &name)
QCString substituteKeywords (const QCString &file, const QCString &s, const KeywordSubstitutionList &keywords)
QCString substituteKeywords (const QCString &file, const QCString &s, const QCString &title, const QCString &projName, const QCString &projNum, const QCString &projBrief)
int getPrefixIndex (const QCString &name)
QCString removeAnonymousScopes (const QCString &s)
QCString replaceAnonymousScopes (const QCString &s, const QCString &replacement=QCString())
QCString convertNameToFile (const QCString &name, bool allowDots=FALSE, bool allowUnderscore=FALSE)
QCString generateAnonymousAnchor (const QCString &fileName, int count)
void extractNamespaceName (const QCString &scopeName, QCString &className, QCString &namespaceName, bool allowEmptyClass=FALSE)
QCString insertTemplateSpecifierInScope (const QCString &scope, const QCString &templ)
QCString stripScope (const QCString &name)
QCString convertToId (const QCString &s)
QCString correctId (const QCString &s)
QCString convertToHtml (const QCString &s, bool keepEntities=true)
QCString convertToXML (const QCString &s, bool keepEntities=false)
QCString convertToJSString (const QCString &s, bool keepEntities=false, bool singleQuotes=false)
QCString getOverloadDocs ()
void addMembersToMemberGroup (MemberList *ml, MemberGroupList *pMemberGroups, const Definition *context)
int extractClassNameFromType (const QCString &type, int &pos, QCString &name, QCString &templSpec, SrcLangExt=SrcLangExt::Unknown)
QCString normalizeNonTemplateArgumentsInString (const QCString &name, const Definition *context, const ArgumentList &formalArgs)
QCString substituteTemplateArgumentsInString (const QCString &name, const ArgumentList &formalArgs, const ArgumentList *actualArgs)
QCString stripTemplateSpecifiersFromScope (const QCString &fullName, bool parentOnly=TRUE, QCString *lastScopeStripped=nullptr, QCString scopeName=QCString(), bool allowArtificial=true)
QCString resolveTypeDef (const Definition *d, const QCString &name, const Definition **typedefContext=nullptr)
QCString mergeScopes (const QCString &leftScope, const QCString &rightScope)
int getScopeFragment (const QCString &s, int p, int *l)
void addRefItem (const RefItemVector &sli, const QCString &key, const QCString &prefix, const QCString &name, const QCString &title, const QCString &args, const Definition *scope)
PageDefaddRelatedPage (const QCString &name, const QCString &ptitle, const QCString &doc, const QCString &fileName, int docLine, int startLine, const RefItemVector &sli=RefItemVector(), GroupDef *gd=nullptr, const TagInfo *tagInfo=nullptr, bool xref=FALSE, SrcLangExt lang=SrcLangExt::Unknown)
bool getCaseSenseNames ()
QCString escapeCharsInString (const QCString &name, bool allowDots, bool allowUnderscore=FALSE)
QCString unescapeCharsInString (const QCString &s)
void addGroupListToTitle (OutputList &ol, const Definition *d)
QCString linkToText (SrcLangExt lang, const QCString &link, bool isFileName)
bool checkExtension (const QCString &fName, const QCString &ext)
void addHtmlExtensionIfMissing (QCString &fName)
QCString stripExtensionGeneral (const QCString &fName, const QCString &ext)
QCString stripExtension (const QCString &fName)
int computeQualifiedIndex (const QCString &name)
 Return the index of the last :: in the string name that is still before the first <.
void addDirPrefix (QCString &fileName)
QCString relativePathToRoot (const QCString &name)
QCString determineAbsoluteIncludeName (const QCString &curFile, const QCString &incFileName)
void createSubDirs (const Dir &d)
void clearSubDirs (const Dir &d)
QCString removeLongPathMarker (QCString path)
QCString stripPath (const QCString &s)
bool containsWord (const QCString &s, const char *word)
 returns TRUE iff string s contains word w
bool findAndRemoveWord (QCString &s, const char *word)
 removes occurrences of whole word from sentence, while keeps internal spaces and reducing multiple sequences of spaces.
QCString stripLeadingAndTrailingEmptyLines (const QCString &s, int &docLine)
 Special version of QCString::stripWhiteSpace() that only strips completely blank lines.
bool updateLanguageMapping (const QCString &extension, const QCString &parser)
SrcLangExt getLanguageFromFileName (const QCString &fileName, SrcLangExt defLang=SrcLangExt::Cpp)
SrcLangExt getLanguageFromCodeLang (QCString &fileName)
 Routine to handle the language attribute of the \code command.
QCString getFileNameExtension (const QCString &fn)
void initDefaultExtensionMapping ()
void addCodeOnlyMappings ()
bool checkIfTypedef (const Definition *scope, const FileDef *fileScope, const QCString &n)
QCString parseCommentAsText (const Definition *scope, const MemberDef *member, const QCString &doc, const QCString &fileName, int lineNr)
QCString parseCommentAsHtml (const Definition *scope, const MemberDef *member, const QCString &doc, const QCString &fileName, int lineNr)
bool transcodeCharacterStringToUTF8 (std::string &input, const char *inputEncoding)
QCString recodeString (const QCString &str, const char *fromEncoding, const char *toEncoding)
void writeTypeConstraints (OutputList &ol, const Definition *d, const ArgumentList &al)
QCString convertCharEntitiesToUTF8 (const QCString &s)
void stackTrace ()
bool readInputFile (const QCString &fileName, std::string &contents, bool filter=TRUE, bool isSourceCode=FALSE)
 read a file name fileName and optionally filter and transcode it
QCString filterTitle (const QCString &title)
bool patternMatch (const FileInfo &fi, const StringVector &patList)
QCString externalLinkTarget (const bool parent=false)
QCString createHtmlUrl (const QCString &relPath, const QCString &ref, bool href, bool islocalFile, const QCString &targetFileName, const QCString &anchor)
QCString externalRef (const QCString &relPath, const QCString &ref, bool href)
int nextUtf8CharPosition (const QCString &utf8Str, uint32_t len, uint32_t startPos)
void writeMarkerList (OutputList &ol, const std::string &markerText, size_t numMarkers, std::function< void(size_t)> replaceFunc)
void writeColoredImgData (const QCString &dir, ColoredImgDataItem data[])
 Writes the intensity only bitmap represented by data as an image to directory dir using the colors defined by HTML_COLORSTYLE_*.
QCString replaceColorMarkers (const QCString &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 QCString &src, const QCString &dest)
 Copies the contents of file with name src to the newly created file with name dest.
int lineBlock (const QCString &text, const QCString &marker)
 Returns the line number of the line following the line with the marker.
bool isURL (const QCString &url)
 Checks whether the given url starts with a supported protocol.
QCString correctURL (const QCString &url, const QCString &relPath)
 Corrects URL url according to the relative path relPath.
QCString processMarkup (const QCString &s)
bool protectionLevelVisible (Protection prot)
QCString stripIndentation (const QCString &s, bool skipFirstLine=false)
void stripIndentationVerbatim (QCString &doc, const int indentationLevel)
QCString getDotImageExtension ()
bool fileVisibleInIndex (const FileDef *fd, bool &genSourceFile)
QCString extractDirection (QCString &docs)
 Strip the direction part from docs and return it as a string in canonical form The input docs string can start with e.g.
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 QCString &outFile, std::ofstream &f)
StringVector split (const std::string &s, const std::string &delimiter)
 split input string s by string delimiter delimiter.
StringVector split (const std::string &s, const reg::Ex &delimiter)
 split input string s by regular expression delimiter delimiter.
int findIndex (const StringVector &sv, const std::string &s)
 find the index of a string in a vector of strings, returns -1 if the string could not be found
int findIndex (const std::string &s, const reg::Ex &re)
 find the index of the first occurrence of pattern re in a string s returns -1 if the pattern could not be found
std::string join (const StringVector &s, const std::string &delimiter)
 create a string where the string in the vector are joined by the given delimiter
bool recognizeFixedForm (const QCString &contents, FortranFormat format)
FortranFormat convertFileNameFortranParserCode (QCString fn)
QCString integerToAlpha (int n, bool upper=true)
QCString integerToRoman (int n, bool upper=true)
QCString getEncoding (const FileInfo &fi)
QCString fixSpaces (const QCString &s)
QCString detab (const QCString &s, size_t &refIndent)
QCString getProjectId ()
QCString projectLogoFile ()
void mergeMemberOverrideOptions (MemberDefMutable *md1, MemberDefMutable *md2)
size_t updateColumnCount (const char *s, size_t col)
QCString mangleCSharpGenericName (const QCString &name)
QCString demangleCSharpGenericName (const QCString &name, const QCString &templArgs)
QCString extractBeginRawStringDelimiter (const char *rawStart)
QCString extractEndRawStringDelimiter (const char *rawEnd)

Detailed Description

A bunch of utility functions.

Definition in file util.h.

Typedef Documentation

◆ KeywordSubstitutionList

Definition at line 247 of file util.h.

◆ SelectionBlockList

using SelectionBlockList = std::vector<SelectionBlock>

Definition at line 181 of file util.h.

Function Documentation

◆ addCodeOnlyMappings()

void addCodeOnlyMappings ( )

Definition at line 5141 of file util.cpp.

5142{
5143 updateLanguageMapping(".xml", "xml");
5144 updateLanguageMapping(".sql", "sql");
5145}
bool updateLanguageMapping(const QCString &extension, const QCString &language)
Definition util.cpp:5042

References updateLanguageMapping().

Referenced by generateOutput().

◆ addDirPrefix()

void addDirPrefix ( QCString & fileName)

◆ addGroupListToTitle()

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

◆ addHtmlExtensionIfMissing()

void addHtmlExtensionIfMissing ( QCString & fName)

Definition at line 4863 of file util.cpp.

4864{
4865 if (fName.isEmpty()) return;
4866 int i_fs = fName.findRev('/');
4867 int i_bs = fName.findRev('\\');
4868 int i = fName.find('.',std::max({ i_fs, i_bs ,0})); // search for . after path part
4869 if (i==-1)
4870 {
4872 }
4873}
static QCString htmlFileExtension
Definition doxygen.h:121
int find(char c, int index=0, bool cs=TRUE) const
Definition qcstring.cpp:43
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:163
int findRev(char c, int index=-1, bool cs=TRUE) const
Definition qcstring.cpp:96

References QCString::find(), QCString::findRev(), Doxygen::htmlFileExtension, and QCString::isEmpty().

Referenced by HtmlCodeGenerator::_writeCodeLink(), Crawlmap::addContentsItem(), DocSets::addContentsItem(), EclipseHelp::addContentsItem(), HtmlHelp::addContentsItem(), Qhp::addContentsItem(), 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(), writeIndex(), 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(), VhdlDocGen::writeTagFile(), DocSets::writeToken(), HtmlCodeGenerator::writeTooltip(), and DotNode::writeUrl().

◆ addMembersToMemberGroup()

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

Definition at line 4039 of file util.cpp.

4042{
4043 ASSERT(context!=nullptr);
4044 //printf("addMemberToMemberGroup() context=%s\n",qPrint(context->name()));
4045 if (ml==nullptr) return;
4046
4047 struct MoveMemberInfo
4048 {
4049 MoveMemberInfo(MemberDef *md,MemberGroup *mg,const RefItemVector &rv)
4050 : memberDef(md), memberGroup(mg), sli(rv) {}
4051 MemberDef *memberDef;
4052 MemberGroup *memberGroup;
4053 RefItemVector sli;
4054 };
4055 std::vector<MoveMemberInfo> movedMembers;
4056
4057 for (const auto &md : *ml)
4058 {
4059 if (md->isEnumerate()) // insert enum value of this enum into groups
4060 {
4061 for (const auto &fmd : md->enumFieldList())
4062 {
4063 int groupId=fmd->getMemberGroupId();
4064 if (groupId!=-1)
4065 {
4066 auto it = Doxygen::memberGroupInfoMap.find(groupId);
4068 {
4069 const auto &info = it->second;
4070 auto mg_it = std::find_if(pMemberGroups->begin(),
4071 pMemberGroups->end(),
4072 [&groupId](const auto &g)
4073 { return g->groupId()==groupId; }
4074 );
4075 MemberGroup *mg_ptr = nullptr;
4076 if (mg_it==pMemberGroups->end())
4077 {
4078 auto mg = std::make_unique<MemberGroup>(
4079 context,
4080 groupId,
4081 info->header,
4082 info->doc,
4083 info->docFile,
4084 info->docLine,
4085 ml->container());
4086 mg_ptr = mg.get();
4087 pMemberGroups->push_back(std::move(mg));
4088 }
4089 else
4090 {
4091 mg_ptr = (*mg_it).get();
4092 }
4093 mg_ptr->insertMember(fmd); // insert in member group
4095 if (fmdm)
4096 {
4097 fmdm->setMemberGroup(mg_ptr);
4098 }
4099 }
4100 }
4101 }
4102 }
4103 int groupId=md->getMemberGroupId();
4104 if (groupId!=-1)
4105 {
4106 auto it = Doxygen::memberGroupInfoMap.find(groupId);
4108 {
4109 const auto &info = it->second;
4110 auto mg_it = std::find_if(pMemberGroups->begin(),
4111 pMemberGroups->end(),
4112 [&groupId](const auto &g)
4113 { return g->groupId()==groupId; }
4114 );
4115 MemberGroup *mg_ptr = nullptr;
4116 if (mg_it==pMemberGroups->end())
4117 {
4118 auto mg = std::make_unique<MemberGroup>(
4119 context,
4120 groupId,
4121 info->header,
4122 info->doc,
4123 info->docFile,
4124 info->docLine,
4125 ml->container());
4126 mg_ptr = mg.get();
4127 pMemberGroups->push_back(std::move(mg));
4128 }
4129 else
4130 {
4131 mg_ptr = (*mg_it).get();
4132 }
4133 movedMembers.emplace_back(md,mg_ptr,info->m_sli);
4134 }
4135 }
4136 }
4137
4138 // move the members to their group
4139 for (const auto &mmi : movedMembers)
4140 {
4141 ml->remove(mmi.memberDef); // remove from member list
4142 mmi.memberGroup->insertMember(mmi.memberDef->resolveAlias()); // insert in member group
4143 mmi.memberGroup->setRefItems(mmi.sli);
4144 MemberDefMutable *rmdm = toMemberDefMutable(mmi.memberDef);
4145 if (rmdm)
4146 {
4147 rmdm->setMemberGroup(mmi.memberGroup);
4148 }
4149 }
4150}
static MemberGroupInfoMap memberGroupInfoMap
Definition doxygen.h:117
virtual void setMemberGroup(MemberGroup *grp)=0
A class representing a group of members.
Definition membergroup.h:43
void insertMember(MemberDef *md)
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:175
MemberDefMutable * toMemberDefMutable(Definition *d)
#define ASSERT(x)
Definition qcstring.h:39
std::vector< RefItem * > RefItemVector
Definition reflist.h:133

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

◆ addRefItem()

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

Definition at line 4766 of file util.cpp.

4769{
4770 //printf("addRefItem(sli=%d,key=%s,prefix=%s,name=%s,title=%s,args=%s)\n",(int)sli.size(),key,prefix,name,title,args);
4771 if (!key.isEmpty() && key[0]!='@') // check for @ to skip anonymous stuff (see bug427012)
4772 {
4773 for (RefItem *item : sli)
4774 {
4775 item->setPrefix(prefix);
4776 item->setScope(scope);
4777 item->setName(name);
4778 item->setTitle(title);
4779 item->setArgs(args);
4780 item->setGroup(key);
4781 }
4782 }
4783}
constexpr auto prefix
Definition anchor.cpp:44
This struct represents an item in the list of references.
Definition reflist.h:32

References QCString::isEmpty(), and prefix.

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

◆ addRelatedPage()

PageDef * addRelatedPage ( const QCString & name,
const QCString & ptitle,
const QCString & doc,
const QCString & 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 4636 of file util.cpp.

4647{
4648 PageDef *pd=nullptr;
4649 //printf("addRelatedPage(name=%s gd=%p)\n",qPrint(name),gd);
4650 QCString title=ptitle.stripWhiteSpace();
4651 bool newPage = true;
4652 if ((pd=Doxygen::pageLinkedMap->find(name)) && !pd->isReference())
4653 {
4654 if (!xref && !title.isEmpty() && pd->title()!=pd->name() && pd->title()!=title)
4655 {
4656 warn(fileName,startLine,"multiple use of page label '{}' with different titles, (other occurrence: {}, line: {})",
4657 name,pd->docFile(),pd->getStartBodyLine());
4658 }
4659 if (!title.isEmpty() && pd->title()==pd->name()) // pd has no real title yet
4660 {
4661 pd->setTitle(title);
4663 if (si)
4664 {
4665 si->setTitle(title);
4666 }
4667 }
4668 // append documentation block to the page.
4669 pd->setDocumentation(doc,fileName,docLine);
4670 //printf("Adding page docs '%s' pi=%p name=%s\n",qPrint(doc),pd,name);
4671 // append (x)refitems to the page.
4672 pd->setRefItems(sli);
4673 newPage = false;
4674 }
4675
4676 if (newPage) // new page
4677 {
4678 QCString baseName=name;
4679 if (baseName.endsWith(".tex"))
4680 baseName=baseName.left(baseName.length()-4);
4681 else if (baseName.right(Doxygen::htmlFileExtension.length())==Doxygen::htmlFileExtension)
4682 baseName=baseName.left(baseName.length()-Doxygen::htmlFileExtension.length());
4683
4684 //printf("Appending page '%s'\n",qPrint(baseName));
4685 if (pd) // replace existing page
4686 {
4687 pd->setDocumentation(doc,fileName,docLine);
4689 pd->setShowLineNo(FALSE);
4690 pd->setNestingLevel(0);
4691 pd->setPageScope(nullptr);
4692 pd->setTitle(title);
4693 pd->setReference(QCString());
4694 }
4695 else // newPage
4696 {
4697 pd = Doxygen::pageLinkedMap->add(baseName,
4698 createPageDef(fileName,docLine,baseName,doc,title));
4699 }
4700 pd->setBodySegment(startLine,startLine,-1);
4701
4702 pd->setRefItems(sli);
4703 pd->setLanguage(lang);
4704
4705 if (tagInfo)
4706 {
4707 pd->setReference(tagInfo->tagName);
4708 pd->setFileName(tagInfo->fileName);
4709 }
4710
4711 if (gd) gd->addPage(pd);
4712
4713 if (pd->hasTitle())
4714 {
4715 //outputList->writeTitle(pi->name,pi->title);
4716
4717 // a page name is a label as well!
4718 QCString file;
4719 QCString orgFile;
4720 int line = -1;
4721 if (gd)
4722 {
4723 file=gd->getOutputFileBase();
4724 orgFile=gd->getOutputFileBase();
4725 }
4726 else
4727 {
4728 file=pd->getOutputFileBase();
4729 orgFile=pd->docFile();
4730 line = pd->getStartBodyLine();
4731 }
4732 const SectionInfo *si = SectionManager::instance().find(pd->name());
4733 if (si)
4734 {
4735 if (!si->ref().isEmpty()) // we are from a tag file
4736 {
4738 file,-1,pd->title(),SectionType::Page,0,pd->getReference());
4739 }
4740 else if (si->lineNr() != -1)
4741 {
4742 warn(orgFile,line,"multiple use of section label '{}', (first occurrence: {}, line {})",pd->name(),si->fileName(),si->lineNr());
4743 }
4744 else
4745 {
4746 warn(orgFile,line,"multiple use of section label '{}', (first occurrence: {})",pd->name(),si->fileName());
4747 }
4748 }
4749 else
4750 {
4752 file,-1,pd->title(),SectionType::Page,0,pd->getReference());
4753 //printf("si->label='%s' si->definition=%s si->fileName='%s'\n",
4754 // qPrint(si->label),si->definition?si->definition->name().data():"<none>",
4755 // qPrint(si->fileName));
4756 //printf(" SectionInfo: sec=%p sec->fileName=%s\n",si,qPrint(si->fileName));
4757 //printf("Adding section key=%s si->fileName=%s\n",qPrint(pageName),qPrint(si->fileName));
4758 }
4759 }
4760 }
4761 return pd;
4762}
virtual QCString docFile() const =0
virtual QCString getReference() const =0
virtual QCString getOutputFileBase() const =0
virtual int getStartBodyLine() const =0
virtual bool isReference() const =0
virtual const QCString & name() const =0
virtual void setBodySegment(int defLine, int bls, int ble)=0
virtual void setDocumentation(const QCString &d, const QCString &docFile, int docLine, bool stripWhiteSpace=TRUE)=0
virtual void setLanguage(SrcLangExt lang)=0
virtual void setReference(const QCString &r)=0
virtual void setRefItems(const RefItemVector &sli)=0
static PageLinkedMap * pageLinkedMap
Definition doxygen.h:99
virtual void addPage(PageDef *def)=0
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 QCString &title)=0
virtual void setNestingLevel(int)=0
virtual bool hasTitle() const =0
virtual void setFileName(const QCString &name)=0
virtual void setShowLineNo(bool)=0
virtual QCString title() const =0
virtual void setPageScope(Definition *)=0
This is an alternative implementation of QCString.
Definition qcstring.h:101
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:166
bool endsWith(const char *s) const
Definition qcstring.h:524
QCString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition qcstring.h:260
QCString right(size_t len) const
Definition qcstring.h:234
QCString left(size_t len) const
Definition qcstring.h:229
class that provide information about a section.
Definition section.h:57
QCString ref() const
Definition section.h:71
QCString fileName() const
Definition section.h:73
int lineNr() const
Definition section.h:72
void setTitle(const QCString &t)
Definition section.h:83
SectionInfo * replace(const QCString &label, const QCString &fileName, int lineNr, const QCString &title, SectionType type, int level, const QCString &ref=QCString())
Definition section.h:156
SectionInfo * add(const SectionInfo &si)
Definition section.h:138
static SectionManager & instance()
returns a reference to the singleton
Definition section.h:178
static constexpr int Page
Definition section.h:31
#define warn(file, line, fmt,...)
Definition message.h:97
std::unique_ptr< PageDef > createPageDef(const QCString &f, int l, const QCString &n, const QCString &d, const QCString &t)
Definition pagedef.cpp:80
#define FALSE
Definition qcstring.h:34
QCString fileName
Definition entry.h:105
QCString tagName
Definition entry.h:104
QCString convertNameToFile(const QCString &name, bool allowDots, bool allowUnderscore)
Definition util.cpp:3446

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

◆ argListToString()

QCString argListToString ( const ArgumentList & al,
bool useCanonicalType = FALSE,
bool showDefVals = TRUE )

Definition at line 1198 of file util.cpp.

1199{
1200 QCString result;
1201 if (!al.hasParameters()) return result;
1202 result+="(";
1203 for (auto it = al.begin() ; it!=al.end() ;)
1204 {
1205 Argument a = *it;
1206 QCString type1 = useCanonicalType && !a.canType.isEmpty() ? a.canType : a.type;
1207 QCString type2;
1208 int i=type1.find(")("); // hack to deal with function pointers
1209 if (i!=-1)
1210 {
1211 type2=type1.mid(i);
1212 type1=type1.left(i);
1213 }
1214 if (!a.attrib.isEmpty())
1215 {
1216 result+=a.attrib+" ";
1217 }
1218 if (!a.name.isEmpty() || !a.array.isEmpty())
1219 {
1220 result+= type1+" "+a.name+type2+a.array;
1221 }
1222 else
1223 {
1224 result+= type1+type2;
1225 }
1226 if (!a.defval.isEmpty() && showDefVals)
1227 {
1228 result+="="+a.defval;
1229 }
1230 ++it;
1231 if (it!=al.end()) result+=", ";
1232 }
1233 result+=")";
1234 if (al.constSpecifier()) result+=" const";
1235 if (al.volatileSpecifier()) result+=" volatile";
1236 if (al.refQualifier()==RefQualifierType::LValue) result+=" &";
1237 else if (al.refQualifier()==RefQualifierType::RValue) result+=" &&";
1238 if (!al.trailingReturnType().isEmpty()) result+=al.trailingReturnType();
1239 if (al.pureSpecifier()) result+=" =0";
1240 return removeRedundantWhiteSpace(result);
1241}
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
QCString 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
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:241
This class contains the information about the argument of a function or template.
Definition arguments.h:27
QCString type
Definition arguments.h:42
QCString name
Definition arguments.h:44
QCString defval
Definition arguments.h:46
QCString array
Definition arguments.h:45
QCString canType
Definition arguments.h:43
QCString attrib
Definition arguments.h:41
QCString removeRedundantWhiteSpace(const QCString &s)
Definition util.cpp:568

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

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

◆ checkBlocks()

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

Definition at line 6472 of file util.cpp.

6473{
6474 if (s.isEmpty()) return;
6475
6476 const char *p = s.data();
6477 char c = 0;
6478 while ((c=*p))
6479 {
6480 if (c==markerInfo.markerChar) // potential start of marker
6481 {
6482 if (qstrncmp(p,markerInfo.beginStr,markerInfo.beginLen)==0) // start of begin marker
6483 {
6484 size_t len = markerInfo.beginLen;
6485 bool negate = *(p+len)=='!';
6486 if (negate) len++;
6487 p += len;
6488 QCString marker;
6489 while (*p)
6490 {
6491 if (markerInfo.closeLen==0 && *p=='\n') // matching end of line
6492 {
6493 warn(fileName,-1,"Remaining begin replacement with marker '{}'",marker);
6494 break;
6495 }
6496 else if (markerInfo.closeLen!= 0 && qstrncmp(p,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6497 {
6498 p += markerInfo.closeLen;
6499 warn(fileName,-1,"Remaining begin replacement with marker '{}'",marker);
6500 break;
6501 }
6502 marker += *p;
6503 p++;
6504 }
6505 }
6506 else if (qstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // start of end marker
6507 {
6508 size_t len = markerInfo.endLen;
6509 bool negate = *(p+len)=='!';
6510 if (negate) len++;
6511 p += len;
6512 QCString marker;
6513 while (*p)
6514 {
6515 if (markerInfo.closeLen==0 && *p=='\n') // matching end of line
6516 {
6517 warn(fileName,-1,"Remaining end replacement with marker '{}'",marker);
6518 break;
6519 }
6520 else if (markerInfo.closeLen!= 0 && qstrncmp(p,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6521 {
6522 p += markerInfo.closeLen;
6523 warn(fileName,-1,"Remaining end replacement with marker '{}'",marker);
6524 break;
6525 }
6526 marker += *p;
6527 p++;
6528 }
6529 }
6530 }
6531 p++;
6532 }
6533}
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition qcstring.h:172
int qstrncmp(const char *str1, const char *str2, size_t len)
Definition qcstring.h:75
size_t beginLen
Definition util.h:187
const char * closeStr
Definition util.h:190
const char * beginStr
Definition util.h:186
size_t closeLen
Definition util.h:191
const char * endStr
Definition util.h:188

References SelectionMarkerInfo::beginLen, SelectionMarkerInfo::beginStr, SelectionMarkerInfo::closeLen, SelectionMarkerInfo::closeStr, QCString::data(), SelectionMarkerInfo::endLen, SelectionMarkerInfo::endStr, QCString::isEmpty(), SelectionMarkerInfo::markerChar, qstrncmp(), and warn.

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

◆ checkExtension()

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

Definition at line 4858 of file util.cpp.

4859{
4860 return fName.right(ext.length())==ext;
4861}

References QCString::length(), and QCString::right().

Referenced by copyLatexStyleSheet(), and extraLatexStyleSheet().

◆ checkIfTypedef()

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

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

Definition at line 5251 of file util.cpp.

5252{
5253 MemberDef *bestMatch = getMemberFromSymbol(scope,fileScope,n);
5254
5255 if (bestMatch && bestMatch->isTypedef())
5256 return TRUE; // closest matching symbol is a typedef
5257 else
5258 return FALSE;
5259}
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 QCString &n)
Definition util.cpp:5199

References FALSE, getMemberFromSymbol(), MemberDef::isTypedef(), and TRUE.

Referenced by isVarWithConstructor().

◆ clearSubDirs()

void clearSubDirs ( const Dir & d)

Definition at line 3609 of file util.cpp.

3610{
3611 if (Config_getBool(CREATE_SUBDIRS))
3612 {
3613 // remove empty subdirectories
3614 int createSubdirsLevelPow2 = 1 << Config_getInt(CREATE_SUBDIRS_LEVEL);
3615 for (int l1=0;l1<16;l1++)
3616 {
3617 QCString subdir;
3618 subdir.sprintf("d%x",l1);
3619 for (int l2=0; l2 < createSubdirsLevelPow2; l2++)
3620 {
3621 QCString subsubdir;
3622 subsubdir.sprintf("d%x/d%02x",l1,l2);
3623 if (d.exists(subsubdir.str()) && d.isEmpty(subsubdir.str()))
3624 {
3625 d.rmdir(subsubdir.str());
3626 }
3627 }
3628 if (d.exists(subdir.str()) && d.isEmpty(subdir.str()))
3629 {
3630 d.rmdir(subdir.str());
3631 }
3632 }
3633 }
3634}
bool isEmpty(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
const std::string & str() const
Definition qcstring.h:552
QCString & sprintf(const char *format,...)
Definition qcstring.cpp:29
#define Config_getInt(name)
Definition config.h:34
#define Config_getBool(name)
Definition config.h:33

References Config_getBool, Config_getInt, Dir::exists(), Dir::isEmpty(), Dir::rmdir(), QCString::sprintf(), and QCString::str().

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

◆ computeQualifiedIndex()

int computeQualifiedIndex ( const QCString & name)

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

Definition at line 6774 of file util.cpp.

6775{
6776 int l = static_cast<int>(name.length());
6777 int lastSepPos = -1;
6778 const char *p = name.data();
6779 int i=l-2;
6780 int sharpCount=0;
6781 // --- begin optimized version of ts=name.findRev(">::");
6782 int ts = -1;
6783 while (i>=0)
6784 {
6785 if (p[i]=='>')
6786 {
6787 if (sharpCount==0 && p[i+1]==':' && p[i+2]==':')
6788 {
6789 ts=i;
6790 break;
6791 }
6792 sharpCount++;
6793 }
6794 else if (p[i]=='<')
6795 {
6796 sharpCount--;
6797 }
6798 i--;
6799 }
6800 // --- end optimized version
6801 if (ts==-1) ts=0; else p+=++ts;
6802 for (i=ts;i<l-1;i++)
6803 {
6804 char c=*p++;
6805 if (c==':' && *p==':') lastSepPos=i;
6806 if (c=='<') break;
6807 }
6808 return lastSepPos;
6809}

References QCString::data(), and QCString::length().

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

◆ containsWord()

bool containsWord ( const QCString & s,
const char * word )

returns TRUE iff string s contains word w

Definition at line 4907 of file util.cpp.

4908{
4909 if (str.isEmpty() || word==nullptr) return false;
4910 static const reg::Ex re(R"(\a+)");
4911 std::string s = str.str();
4912 for (reg::Iterator it(s,re) ; it!=reg::Iterator() ; ++it)
4913 {
4914 if (it->str()==word) return true;
4915 }
4916 return false;
4917}
Class representing a regular expression.
Definition regex.h:39
Class to iterate through matches.
Definition regex.h:230

References QCString::isEmpty(), and QCString::str().

◆ convertCharEntitiesToUTF8()

QCString convertCharEntitiesToUTF8 ( const QCString & s)

Definition at line 3989 of file util.cpp.

3990{
3991 if (str.isEmpty()) return QCString();
3992
3993 std::string s = str.data();
3994 static const reg::Ex re(R"(&\a\w*;)");
3995 reg::Iterator it(s,re);
3997
3998 QCString result;
3999 result.reserve(str.length()+32);
4000 size_t p=0, i=0, l=0;
4001 for (; it!=end ; ++it)
4002 {
4003 const auto &match = *it;
4004 p = match.position();
4005 l = match.length();
4006 if (p>i)
4007 {
4008 result+=s.substr(i,p-i);
4009 }
4010 QCString entity(match.str());
4012 const char *code=nullptr;
4013 if (symType!=HtmlEntityMapper::Sym_Unknown && (code=HtmlEntityMapper::instance().utf8(symType)))
4014 {
4015 result+=code;
4016 }
4017 else
4018 {
4019 result+=entity;
4020 }
4021 i=p+l;
4022 }
4023 result+=s.substr(i);
4024 //printf("convertCharEntitiesToUTF8(%s)->%s\n",qPrint(s),qPrint(result));
4025 return result;
4026}
static HtmlEntityMapper & instance()
Returns the one and only instance of the HTML entity mapper.
SymType name2sym(const QCString &symName) const
Give code of the requested HTML entity name.
void reserve(size_t size)
Reserve space for size bytes without changing the string contents.
Definition qcstring.h:185
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:855

References QCString::data(), end(), HtmlEntityMapper::instance(), QCString::isEmpty(), QCString::length(), HtmlEntityMapper::name2sym(), QCString::reserve(), and HtmlEntityMapper::Sym_Unknown.

Referenced by convertToJSString(), generateSqlite3ForPage(), generateXMLForPage(), getSQLDocBlock(), and parseCommentAsText().

◆ convertFileNameFortranParserCode()

FortranFormat convertFileNameFortranParserCode ( QCString fn)

Definition at line 6346 of file util.cpp.

6347{
6349 QCString parserName = Doxygen::parserManager->getParserName(ext);
6350
6351 if (parserName == "fortranfixed") return FortranFormat::Fixed;
6352 else if (parserName == "fortranfree") return FortranFormat::Free;
6353
6355}
static ParserManager * parserManager
Definition doxygen.h:130
QCString getFileNameExtension(const QCString &fn)
Definition util.cpp:5189

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

Referenced by convertCppComments().

◆ convertNameToFile()

QCString convertNameToFile ( const QCString & 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 3446 of file util.cpp.

3447{
3448 if (name.isEmpty()) return name;
3449 bool shortNames = Config_getBool(SHORT_NAMES);
3450 bool createSubdirs = Config_getBool(CREATE_SUBDIRS);
3451 QCString result;
3452 if (shortNames) // use short names only
3453 {
3454 std::lock_guard<std::mutex> lock(g_usedNamesMutex);
3455 auto kv = g_usedNames.find(name.str());
3456 uint32_t num=0;
3457 if (kv!=g_usedNames.end())
3458 {
3459 num = kv->second;
3460 }
3461 else
3462 {
3463 num = g_usedNamesCount;
3464 g_usedNames.emplace(name.str(),g_usedNamesCount++);
3465 }
3466 result.sprintf("a%05d",num);
3467 }
3468 else // long names
3469 {
3470 result=escapeCharsInString(name,allowDots,allowUnderscore);
3471 size_t resultLen = result.length();
3472 if (resultLen>=128) // prevent names that cannot be created!
3473 {
3474 // third algorithm based on MD5 hash
3475 uint8_t md5_sig[16];
3476 char sigStr[33];
3477 MD5Buffer(result.data(),static_cast<unsigned int>(resultLen),md5_sig);
3478 MD5SigToString(md5_sig,sigStr);
3479 result=result.left(128-32)+sigStr;
3480 }
3481 }
3482 if (createSubdirs)
3483 {
3484 int l1Dir=0,l2Dir=0;
3485 int createSubdirsLevel = Config_getInt(CREATE_SUBDIRS_LEVEL);
3486 int createSubdirsBitmaskL2 = (1<<createSubdirsLevel)-1;
3487
3488 // compute md5 hash to determine sub directory to use
3489 uint8_t md5_sig[16];
3490 MD5Buffer(result.data(),static_cast<unsigned int>(result.length()),md5_sig);
3491 l1Dir = md5_sig[14] & 0xf;
3492 l2Dir = md5_sig[15] & createSubdirsBitmaskL2;
3493
3494 result.prepend(QCString().sprintf("d%x/d%02x/",l1Dir,l2Dir));
3495 }
3496 //printf("*** convertNameToFile(%s)->%s\n",qPrint(name),qPrint(result));
3497 return result;
3498}
QCString & prepend(const char *s)
Definition qcstring.h:422
static int g_usedNamesCount
Definition util.cpp:3438
QCString escapeCharsInString(const QCString &name, bool allowDots, bool allowUnderscore)
Definition util.cpp:3271
static std::mutex g_usedNamesMutex
Definition util.cpp:3437
static std::unordered_map< std::string, int > g_usedNames
Definition util.cpp:3436

References Config_getBool, Config_getInt, QCString::data(), escapeCharsInString(), g_usedNames, g_usedNamesCount, g_usedNamesMutex, QCString::isEmpty(), QCString::left(), QCString::length(), QCString::prepend(), QCString::sprintf(), and QCString::str().

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

◆ 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 6179 of file util.cpp.

6185{
6186 bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
6187
6188 // default representing 1-1 mapping
6189 *outListType1=inListType;
6190 *outListType2=MemberListType::Invalid();
6191
6192 if (inProt==Protection::Public)
6193 {
6194 if (inListType.isPrivate())
6195 {
6196 *outListType1=MemberListType::Invalid();
6197 }
6198 }
6199 else if (inProt==Protection::Protected)
6200 {
6201 if (inListType.isPrivate() || inListType.isPublic())
6202 {
6203 *outListType1=MemberListType::Invalid();
6204 }
6205 else if (inListType.isProtected())
6206 {
6207 *outListType2=inListType.toPublic();
6208 }
6209 }
6210 else if (inProt==Protection::Private)
6211 {
6212 if (inListType.isPublic() || inListType.isProtected())
6213 {
6214 *outListType1=MemberListType::Invalid();
6215 }
6216 else if (inListType.isPrivate())
6217 {
6218 if (extractPrivate)
6219 {
6220 *outListType1=inListType.toPublic();
6221 *outListType2=inListType.toProtected();
6222 }
6223 else
6224 {
6225 *outListType1=MemberListType::Invalid();
6226 }
6227 }
6228 }
6229
6230 //printf("convertProtectionLevel(type=%s prot=%d): %s,%s\n",
6231 // qPrint(inListType.to_string()),inProt,qPrint(outListType1->to_string()),qPrint(outListType2->to_string()));
6232}
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, MemberListType::Invalid(), MemberListType::isPrivate(), MemberListType::isProtected(), MemberListType::isPublic(), MemberListType::toProtected(), and MemberListType::toPublic().

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

◆ convertToHtml()

QCString convertToHtml ( const QCString & s,
bool keepEntities )

Converts a string to a HTML-encoded string

Definition at line 3905 of file util.cpp.

3906{
3907 if (s.isEmpty()) return s;
3908 QCString result;
3909 result.reserve(s.length()+32);
3910 const char *p=s.data();
3911 char c = 0;
3912 while ((c=*p++))
3913 {
3914 switch (c)
3915 {
3916 case '<': result+="&lt;"; break;
3917 case '>': result+="&gt;"; break;
3918 case '&': if (keepEntities)
3919 {
3920 const char *e=p;
3921 char ce = 0;
3922 while ((ce=*e++))
3923 {
3924 if (ce==';' || (!(isId(ce) || ce=='#'))) break;
3925 }
3926 if (ce==';') // found end of an entity
3927 {
3928 // copy entry verbatim
3929 result+=c;
3930 while (p<e) result+=*p++;
3931 }
3932 else
3933 {
3934 result+="&amp;";
3935 }
3936 }
3937 else
3938 {
3939 result+="&amp;";
3940 }
3941 break;
3942 case '\'': result+="&#39;"; break;
3943 case '"': result+="&quot;"; break;
3944 default:
3945 {
3946 uint8_t uc = static_cast<uint8_t>(c);
3947 if (uc<32 && !isspace(c))
3948 {
3949 result+="&#x24";
3950 result+=hex[uc>>4];
3951 result+=hex[uc&0xF];
3952 result+=';';
3953 }
3954 else
3955 {
3956 result+=c;
3957 }
3958 }
3959 break;
3960 }
3961 }
3962 return result;
3963}
static constexpr auto hex
bool isId(int c)
Definition util.h:207

References QCString::data(), hex, QCString::isEmpty(), isId(), QCString::length(), and QCString::reserve().

Referenced by HtmlCodeGenerator::_writeCodeLink(), HtmlHelp::addContentsItem(), addMembersToIndex(), convertToHtmlAndTruncate(), FTVHelp::Private::generateLink(), DefinitionImpl::navigationPathAsString(), 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()

QCString convertToId ( const QCString & s)

Converts a string to a HTML id string

Definition at line 3814 of file util.cpp.

3815{
3816 if (s.isEmpty()) return s;
3817 QCString result;
3818 result.reserve(s.length()+8);
3819 const char *p = s.data();
3820 char c = 0;
3821 bool first = true;
3822 while ((c=*p++))
3823 {
3824 char encChar[4];
3825 if ((c>='0' && c<='9') || (c>='a' && c<='z') || (c>='A' && c<='Z') || c=='-')
3826 { // any permissive character except _
3827 if (first && c>='0' && c<='9') result+='a'; // don't start with a digit
3828 result+=c;
3829 }
3830 else
3831 {
3832 encChar[0]='_';
3833 encChar[1]=hex[static_cast<unsigned char>(c)>>4];
3834 encChar[2]=hex[static_cast<unsigned char>(c)&0xF];
3835 encChar[3]=0;
3836 result+=encChar;
3837 }
3838 first=false;
3839 }
3840 return result;
3841}

References QCString::data(), hex, QCString::isEmpty(), QCString::length(), and QCString::reserve().

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

◆ convertToJSString()

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

Definition at line 3965 of file util.cpp.

3966{
3967 if (s.isEmpty()) return s;
3968 QCString result;
3969 result.reserve(s.length()+32);
3970 const char *p=s.data();
3971 char c = 0;
3972 while ((c=*p++))
3973 {
3974 switch (c)
3975 {
3976 case '"': if (!singleQuotes) result+="\\\""; else result+=c;
3977 break;
3978 case '\'': if (singleQuotes) result+="\\\'"; else result+=c;
3979 break;
3980 case '\\': if (*p=='u' && *(p+1)=='{') result+="\\"; // keep \u{..} unicode escapes
3981 else result+="\\\\";
3982 break;
3983 default: result+=c; break;
3984 }
3985 }
3986 return keepEntities ? result : convertCharEntitiesToUTF8(result);
3987}
QCString convertCharEntitiesToUTF8(const QCString &str)
Definition util.cpp:3989

References convertCharEntitiesToUTF8(), QCString::data(), QCString::isEmpty(), QCString::length(), and QCString::reserve().

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

◆ convertToXML()

QCString convertToXML ( const QCString & s,
bool keepEntities )

Converts a string to an XML-encoded string

Definition at line 3854 of file util.cpp.

3855{
3856 if (s.isEmpty()) return s;
3857 QCString result;
3858 result.reserve(s.length()+32);
3859 const char *p = s.data();
3860 char c = 0;
3861 while ((c=*p++))
3862 {
3863 switch (c)
3864 {
3865 case '<': result+="&lt;"; break;
3866 case '>': result+="&gt;"; break;
3867 case '&': if (keepEntities)
3868 {
3869 const char *e=p;
3870 char ce = 0;
3871 while ((ce=*e++))
3872 {
3873 if (ce==';' || (!(isId(ce) || ce=='#'))) break;
3874 }
3875 if (ce==';') // found end of an entity
3876 {
3877 // copy entry verbatim
3878 result+=c;
3879 while (p<e) result+=*p++;
3880 }
3881 else
3882 {
3883 result+="&amp;";
3884 }
3885 }
3886 else
3887 {
3888 result+="&amp;";
3889 }
3890 break;
3891 case '\'': result+="&apos;"; break;
3892 case '"': result+="&quot;"; break;
3893 case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
3894 case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18:
3895 case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26:
3896 case 27: case 28: case 29: case 30: case 31:
3897 break; // skip invalid XML characters (see http://www.w3.org/TR/2000/REC-xml-20001006#NT-Char)
3898 default: result+=c; break;
3899 }
3900 }
3901 return result;
3902}

References QCString::data(), QCString::isEmpty(), isId(), QCString::length(), and QCString::reserve().

Referenced by DocSets::addContentsItem(), EclipseHelp::addContentsItem(), Qhp::addFile(), Sitemap::addIndexFile(), Qhp::addIndexItem(), XmlDocVisitor::filter(), generateXMLForClass(), generateXMLForConcept(), generateXMLForDir(), generateXMLForFile(), generateXMLForGroup(), generateXMLForMember(), generateXMLForModule(), generateXMLForNamespace(), generateXMLForPage(), 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(), ClassDefImpl::writeTagFile(), ConceptDefImpl::writeTagFile(), DirDefImpl::writeTagFile(), FileDefImpl::writeTagFile(), GroupDefImpl::writeTagFile(), MemberDefImpl::writeTagFile(), ModuleDefImpl::writeTagFile(), NamespaceDefImpl::writeTagFile(), PageDefImpl::writeTagFile(), VhdlDocGen::writeTagFile(), writeTemplateArgumentList(), DocSets::writeToken(), DotNode::writeXML(), writeXMLLink(), and writeXMLString().

◆ copyFile()

◆ correctId()

QCString correctId ( const QCString & s)

Some strings have been corrected but the requirement regarding the fact that an id cannot have a digit at the first position. To overcome problems with double labels we always place an "a" in front

Definition at line 3847 of file util.cpp.

3848{
3849 if (s.isEmpty()) return s;
3850 return "a" + s;
3851}

References QCString::isEmpty().

Referenced by DotGraph::generateCode(), and DotFilePatcher::run().

◆ correctURL()

QCString correctURL ( const QCString & url,
const QCString & 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 5877 of file util.cpp.

5878{
5879 QCString result = url;
5880 if (!relPath.isEmpty() && !isURL(url))
5881 {
5882 result.prepend(relPath);
5883 }
5884 return result;
5885}
bool isURL(const QCString &url)
Checks whether the given url starts with a supported protocol.
Definition util.cpp:5865

References QCString::isEmpty(), isURL(), and QCString::prepend().

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

◆ createHtmlUrl()

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

Definition at line 5672 of file util.cpp.

5678{
5679 QCString url;
5680 if (!ref.isEmpty())
5681 {
5682 url = externalRef(relPath,ref,href);
5683 }
5684 if (!targetFileName.isEmpty())
5685 {
5686 QCString fn = targetFileName;
5687 if (ref.isEmpty())
5688 {
5689 if (!anchor.isEmpty() && isLocalFile)
5690 {
5691 fn=""; // omit file name for local links
5692 }
5693 else
5694 {
5695 url = relPath;
5696 }
5697 }
5698 url+=fn;
5699 }
5700 if (!anchor.isEmpty()) url+="#"+anchor;
5701 //printf("createHtmlUrl(relPath=%s,local=%d,target=%s,anchor=%s)=%s\n",qPrint(relPath),isLocalFile,qPrint(targetFileName),qPrint(anchor),qPrint(url));
5702 return url;
5703}
QCString externalRef(const QCString &relPath, const QCString &ref, bool href)
Definition util.cpp:5705

References externalRef(), and QCString::isEmpty().

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

◆ createSubDirs()

void createSubDirs ( const Dir & d)

Definition at line 3582 of file util.cpp.

3583{
3584 if (Config_getBool(CREATE_SUBDIRS))
3585 {
3586 // create up to 4096 subdirectories
3587 int createSubdirsLevelPow2 = 1 << Config_getInt(CREATE_SUBDIRS_LEVEL);
3588 for (int l1=0; l1<16; l1++)
3589 {
3590 QCString subdir;
3591 subdir.sprintf("d%x",l1);
3592 if (!d.exists(subdir.str()) && !d.mkdir(subdir.str()))
3593 {
3594 term("Failed to create output directory '{}'\n",subdir);
3595 }
3596 for (int l2=0; l2<createSubdirsLevelPow2; l2++)
3597 {
3598 QCString subsubdir;
3599 subsubdir.sprintf("d%x/d%02x",l1,l2);
3600 if (!d.exists(subsubdir.str()) && !d.mkdir(subsubdir.str()))
3601 {
3602 term("Failed to create output directory '{}'\n",subsubdir);
3603 }
3604 }
3605 }
3606 }
3607}
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, Dir::exists(), Dir::mkdir(), QCString::sprintf(), QCString::str(), and term.

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

◆ demangleCSharpGenericName()

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

Definition at line 6873 of file util.cpp.

6874{
6875 QCString result=name;
6876 if (result.endsWith("-g"))
6877 {
6878 int idx = result.find('-');
6879 result = result.left(idx)+templArgs;
6880 }
6881 return result;
6882}

References QCString::endsWith(), QCString::find(), and QCString::left().

Referenced by ClassDefImpl::className().

◆ detab()

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

Definition at line 6670 of file util.cpp.

6671{
6672 int tabSize = Config_getInt(TAB_SIZE);
6673 size_t size = s.length();
6674 QCString result;
6675 result.reserve(size+256);
6676 const char *data = s.data();
6677 size_t i=0;
6678 int col=0;
6679 constexpr auto doxy_nbsp = "&_doxy_nbsp;"; // doxygen escape command for UTF-8 nbsp
6680 const int maxIndent=1000000; // value representing infinity
6681 int minIndent=maxIndent;
6682 bool skip = false;
6683 while (i<size)
6684 {
6685 char c = data[i++];
6686 switch(c)
6687 {
6688 case '\t': // expand tab
6689 {
6690 int stop = tabSize - (col%tabSize);
6691 //printf("expand at %d stop=%d\n",col,stop);
6692 col+=stop;
6693 while (stop--) result+=' ';
6694 }
6695 break;
6696 case '\\':
6697 if (data[i] == '\\') // escaped command -> ignore
6698 {
6699 result+=c;
6700 result+=data[i++];
6701 col+=2;
6702 }
6703 else if (i+5<size && literal_at(data+i,"iskip")) // command
6704 {
6705 i+=5;
6706 skip = true;
6707 }
6708 else if (i+8<size && literal_at(data+i,"endiskip")) // command
6709 {
6710 i+=8;
6711 skip = false;
6712 }
6713 else // some other command
6714 {
6715 result+=c;
6716 col++;
6717 }
6718 break;
6719 case '\n': // reset column counter
6720 result+=c;
6721 col=0;
6722 break;
6723 case ' ': // increment column counter
6724 result+=c;
6725 col++;
6726 break;
6727 default: // non-whitespace => update minIndent
6728 if (c<0 && i<size) // multibyte sequence
6729 {
6730 // special handling of the UTF-8 nbsp character 0xC2 0xA0
6731 int nb = isUTF8NonBreakableSpace(data);
6732 if (nb>0)
6733 {
6734 result+=doxy_nbsp;
6735 i+=nb-1;
6736 }
6737 else
6738 {
6739 int bytes = getUTF8CharNumBytes(c);
6740 for (int j=0;j<bytes-1 && c;j++)
6741 {
6742 result+=c;
6743 c = data[i++];
6744 }
6745 result+=c;
6746 }
6747 }
6748 else
6749 {
6750 result+=c;
6751 }
6752 if (!skip && col<minIndent) minIndent=col;
6753 col++;
6754 }
6755 }
6756 if (minIndent!=maxIndent) refIndent=minIndent; else refIndent=0;
6757 //printf("detab(\n%s\n)=[\n%s\n]\n",qPrint(s),qPrint(out.get()));
6758 return result;
6759}
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:98
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, QCString::data(), getUTF8CharNumBytes(), isUTF8NonBreakableSpace(), QCString::length(), literal_at(), and QCString::reserve().

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

◆ determineAbsoluteIncludeName()

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

Definition at line 3542 of file util.cpp.

3543{
3544 bool searchIncludes = Config_getBool(SEARCH_INCLUDES);
3545 QCString absIncFileName = incFileName;
3546 FileInfo fi(curFile.str());
3547 if (fi.exists())
3548 {
3549 QCString absName = fi.dirPath(TRUE)+"/"+incFileName;
3550 FileInfo fi2(absName.str());
3551 if (fi2.exists())
3552 {
3553 absIncFileName=fi2.absFilePath();
3554 }
3555 else if (searchIncludes) // search in INCLUDE_PATH as well
3556 {
3557 const StringVector &includePath = Config_getList(INCLUDE_PATH);
3558 for (const auto &incPath : includePath)
3559 {
3560 FileInfo fi3(incPath);
3561 if (fi3.exists() && fi3.isDir())
3562 {
3563 absName = fi3.absFilePath()+"/"+incFileName;
3564 //printf("trying absName=%s\n",qPrint(absName));
3565 FileInfo fi4(absName.str());
3566 if (fi4.exists())
3567 {
3568 absIncFileName=fi4.absFilePath();
3569 break;
3570 }
3571 //printf( "absIncFileName = %s\n", qPrint(absIncFileName) );
3572 }
3573 }
3574 }
3575 //printf( "absIncFileName = %s\n", qPrint(absIncFileName) );
3576 }
3577 return absIncFileName;
3578}
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, FileInfo::dirPath(), FileInfo::exists(), FileInfo::isDir(), QCString::str(), and TRUE.

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

◆ escapeCharsInString()

QCString escapeCharsInString ( const QCString & name,
bool allowDots,
bool allowUnderscore = FALSE )

Definition at line 3271 of file util.cpp.

3272{
3273 if (name.isEmpty()) return name;
3274 bool caseSenseNames = getCaseSenseNames();
3275 bool allowUnicodeNames = Config_getBool(ALLOW_UNICODE_NAMES);
3276 QCString result;
3277 result.reserve(name.length()+8);
3278 signed char c = 0;
3279 const char *p=name.data();
3280 while ((c=*p++)!=0)
3281 {
3282 switch(c)
3283 {
3284 case '_': if (allowUnderscore) result+='_'; else result+="__"; break;
3285 case '-': result+='-'; break;
3286 case ':': result+="_1"; break;
3287 case '/': result+="_2"; break;
3288 case '<': result+="_3"; break;
3289 case '>': result+="_4"; break;
3290 case '*': result+="_5"; break;
3291 case '&': result+="_6"; break;
3292 case '|': result+="_7"; break;
3293 case '.': if (allowDots) result+='.'; else result+="_8"; break;
3294 case '!': result+="_9"; break;
3295 case ',': result+="_00"; break;
3296 case ' ': result+="_01"; break;
3297 case '{': result+="_02"; break;
3298 case '}': result+="_03"; break;
3299 case '?': result+="_04"; break;
3300 case '^': result+="_05"; break;
3301 case '%': result+="_06"; break;
3302 case '(': result+="_07"; break;
3303 case ')': result+="_08"; break;
3304 case '+': result+="_09"; break;
3305 case '=': result+="_0a"; break;
3306 case '$': result+="_0b"; break;
3307 case '\\': result+="_0c"; break;
3308 case '@': result+="_0d"; break;
3309 case ']': result+="_0e"; break;
3310 case '[': result+="_0f"; break;
3311 case '#': result+="_0g"; break;
3312 case '"': result+="_0h"; break;
3313 case '~': result+="_0i"; break;
3314 case '\'': result+="_0j"; break;
3315 case ';': result+="_0k"; break;
3316 case '`': result+="_0l"; break;
3317 default:
3318 if (c<0)
3319 {
3320 bool doEscape = true;
3321 if (allowUnicodeNames)
3322 {
3323 int charLen = getUTF8CharNumBytes(c);
3324 if (charLen>0)
3325 {
3326 result+=QCString(p-1,charLen);
3327 p+=charLen;
3328 doEscape = false;
3329 }
3330 }
3331 if (doEscape) // not a valid unicode char or escaping needed
3332 {
3333 char ids[5];
3334 unsigned char id = static_cast<unsigned char>(c);
3335 ids[0]='_';
3336 ids[1]='x';
3337 ids[2]=hex[id>>4];
3338 ids[3]=hex[id&0xF];
3339 ids[4]=0;
3340 result+=ids;
3341 }
3342 }
3343 else if (caseSenseNames || !isupper(c))
3344 {
3345 result+=c;
3346 }
3347 else
3348 {
3349 result+='_';
3350 result+=static_cast<char>(tolower(c));
3351 }
3352 break;
3353 }
3354 }
3355 return result;
3356}
bool getCaseSenseNames()
Definition util.cpp:3262

References Config_getBool, QCString::data(), getCaseSenseNames(), getUTF8CharNumBytes(), hex, QCString::isEmpty(), QCString::length(), and QCString::reserve().

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

◆ externalLinkTarget()

QCString externalLinkTarget ( const bool parent = false)

Definition at line 5661 of file util.cpp.

5662{
5663 bool extLinksInWindow = Config_getBool(EXT_LINKS_IN_WINDOW);
5664 if (extLinksInWindow)
5665 return "target=\"_blank\" ";
5666 else if (parent)
5667 return "target=\"_parent\" ";
5668 else
5669 return "";
5670}
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:1330

References Config_getBool, and parent().

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

◆ externalRef()

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

Definition at line 5705 of file util.cpp.

5706{
5707 QCString result;
5708 if (!ref.isEmpty())
5709 {
5710 auto it = Doxygen::tagDestinationMap.find(ref.str());
5712 {
5713 result = it->second;
5714 size_t l = result.length();
5715 if (!relPath.isEmpty() && l>0 && result.at(0)=='.')
5716 { // relative path -> prepend relPath.
5717 result.prepend(relPath);
5718 l+=relPath.length();
5719 }
5720 if (l>0 && result.at(l-1)!='/') result+='/';
5721 if (!href) result.append("\" ");
5722 }
5723 }
5724 else
5725 {
5726 result = relPath;
5727 }
5728 return result;
5729}
static StringMap tagDestinationMap
Definition doxygen.h:115
char & at(size_t i)
Returns a reference to the character at index i.
Definition qcstring.h:593
QCString & append(char c)
Definition qcstring.h:396

References QCString::append(), QCString::at(), end(), QCString::isEmpty(), QCString::length(), QCString::prepend(), QCString::str(), and Doxygen::tagDestinationMap.

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

◆ extractBeginRawStringDelimiter()

QCString extractBeginRawStringDelimiter ( const char * rawStart)

Definition at line 6884 of file util.cpp.

6885{
6886 QCString text=rawStart;
6887 int i = text.find('"');
6888 assert(i!=-1);
6889 return text.mid(i+1,text.length()-i-2); // text=...R"xyz( -> delimiter=xyz
6890}

References QCString::find(), QCString::length(), and QCString::mid().

◆ extractClassNameFromType()

int extractClassNameFromType ( const QCString & type,
int & pos,
QCString & name,
QCString & 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 4157 of file util.cpp.

4158{
4159 AUTO_TRACE("type='{}' name='{}' lang={}",type,name,lang);
4160 static const reg::Ex re_norm(R"(\a[\w:]*)");
4161 static const reg::Ex re_fortran(R"(\a[\w:()=]*)");
4162 const reg::Ex *re = &re_norm;
4163
4164 name.clear();
4165 templSpec.clear();
4166 if (type.isEmpty())
4167 {
4168 AUTO_TRACE_EXIT("empty type");
4169 return -1;
4170 }
4171 size_t typeLen=type.length();
4172 if (typeLen>0)
4173 {
4174 if (lang == SrcLangExt::Fortran)
4175 {
4176 if (type[pos]==',')
4177 {
4178 AUTO_TRACE_EXIT("comma");
4179 return -1;
4180 }
4181 if (!type.lower().startsWith("type"))
4182 {
4183 re = &re_fortran;
4184 }
4185 }
4186 std::string s = type.str();
4187 reg::Iterator it(s,*re,static_cast<int>(pos));
4189
4190 if (it!=end)
4191 {
4192 const auto &match = *it;
4193 size_t i = match.position();
4194 size_t l = match.length();
4195 size_t ts = i+l;
4196 size_t te = ts;
4197 size_t tl = 0;
4198
4199 while (ts<typeLen && type[static_cast<uint32_t>(ts)]==' ') { ts++; tl++; } // skip any whitespace
4200 if (ts<typeLen && type[static_cast<uint32_t>(ts)]=='<') // assume template instance
4201 {
4202 // locate end of template
4203 te=ts+1;
4204 int brCount=1;
4205 while (te<typeLen && brCount!=0)
4206 {
4207 if (type[static_cast<uint32_t>(te)]=='<')
4208 {
4209 if (te<typeLen-1 && type[static_cast<uint32_t>(te)+1]=='<') te++; else brCount++;
4210 }
4211 if (type[static_cast<uint32_t>(te)]=='>')
4212 {
4213 if (te<typeLen-1 && type[static_cast<uint32_t>(te)+1]=='>') te++; else brCount--;
4214 }
4215 te++;
4216 }
4217 }
4218 name = match.str();
4219 if (te>ts)
4220 {
4221 templSpec = QCString(type).mid(ts,te-ts);
4222 tl+=te-ts;
4223 pos=static_cast<int>(i+l+tl);
4224 }
4225 else // no template part
4226 {
4227 pos=static_cast<int>(i+l);
4228 }
4229 //printf("extractClassNameFromType([in] type=%s,[out] pos=%d,[out] name=%s,[out] templ=%s)=TRUE i=%d\n",
4230 // qPrint(type),pos,qPrint(name),qPrint(templSpec),i);
4231 AUTO_TRACE_EXIT("pos={} templSpec='{}' return={}",pos,templSpec,i);
4232 return static_cast<int>(i);
4233 }
4234 }
4235 pos = static_cast<int>(typeLen);
4236 //printf("extractClassNameFromType([in] type=%s,[out] pos=%d,[out] name=%s,[out] templ=%s)=FALSE\n",
4237 // qPrint(type),pos,qPrint(name),qPrint(templSpec));
4238 AUTO_TRACE_EXIT("not found");
4239 return -1;
4240}
bool startsWith(const char *s) const
Definition qcstring.h:507
QCString lower() const
Definition qcstring.h:249
void clear()
Definition qcstring.h:182
#define AUTO_TRACE(...)
Definition docnode.cpp:46
#define AUTO_TRACE_EXIT(...)
Definition docnode.cpp:48

References AUTO_TRACE, AUTO_TRACE_EXIT, QCString::clear(), end(), QCString::isEmpty(), QCString::length(), QCString::lower(), QCString::mid(), QCString::startsWith(), and QCString::str().

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

◆ extractDirection()

QCString extractDirection ( QCString & docs)

Strip the direction part from docs and return it as a string in canonical form The input docs string can start with e.g.

"[in]", "[in, out]", "[inout]", "[out,in]"...

Returns
either "[in,out]", "[in]", or "[out]" or the empty string.

Definition at line 6128 of file util.cpp.

6129{
6130 std::string s = docs.str();
6131 static const reg::Ex re(R"(\‍[([ inout,]+)\‍])");
6132 reg::Iterator it(s,re);
6134 if (it!=end)
6135 {
6136 const auto &match = *it;
6137 size_t p = match.position();
6138 size_t l = match.length();
6139 if (p==0 && l>2)
6140 {
6141 // make dir the part inside [...] without separators
6142 std::string dir = match[1].str();
6143 // strip , and ' ' from dir
6144 dir.erase(std::remove_if(dir.begin(),dir.end(),
6145 [](const char c) { return c==' ' || c==','; }
6146 ),dir.end());
6147 unsigned char ioMask=0;
6148 size_t inIndex = dir.find( "in");
6149 if ( inIndex!=std::string::npos) { dir.erase( inIndex,2); ioMask|=(1<<0); }
6150 size_t outIndex = dir.find("out");
6151 if (outIndex!=std::string::npos) { dir.erase(outIndex,3); ioMask|=(1<<1); }
6152 if (dir.empty() && ioMask!=0) // only in and/or out attributes found
6153 {
6154 docs = s.substr(l); // strip attributes
6155 if (ioMask==((1<<0)|(1<<1))) return "[in,out]";
6156 else if (ioMask==(1<<0)) return "[in]";
6157 else if (ioMask==(1<<1)) return "[out]";
6158 }
6159 }
6160 }
6161 return "";
6162}

References end(), and QCString::str().

Referenced by inlineArgListToDoc().

◆ extractEndRawStringDelimiter()

QCString extractEndRawStringDelimiter ( const char * rawEnd)

Definition at line 6892 of file util.cpp.

6893{
6894 QCString text=rawEnd;
6895 return text.mid(1,text.length()-2); // text=)xyz" -> delimiter=xyz
6896}

References QCString::length(), and QCString::mid().

◆ extractNamespaceName()

void extractNamespaceName ( const QCString & scopeName,
QCString & className,
QCString & 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 3639 of file util.cpp.

3642{
3643 int i=0, p=0;
3644 QCString clName=scopeName;
3645 NamespaceDef *nd = nullptr;
3646 if (!clName.isEmpty() && (nd=getResolvedNamespace(clName)) && getClass(clName)==nullptr)
3647 { // the whole name is a namespace (and not a class)
3648 namespaceName=nd->name();
3649 className.clear();
3650 goto done;
3651 }
3652 p=static_cast<int>(clName.length())-2;
3653 while (p>=0 && (i=clName.findRev("::",p))!=-1)
3654 // see if the first part is a namespace (and not a class)
3655 {
3656 //printf("Trying %s\n",qPrint(clName.left(i)));
3657 if (i>0 && (nd=getResolvedNamespace(clName.left(i))) && getClass(clName.left(i))==nullptr)
3658 {
3659 //printf("found!\n");
3660 namespaceName=nd->name();
3661 className=clName.right(clName.length()-i-2);
3662 goto done;
3663 }
3664 p=i-2; // try a smaller piece of the scope
3665 }
3666 //printf("not found!\n");
3667
3668 // not found, so we just have to guess.
3669 className=scopeName;
3670 namespaceName.clear();
3671
3672done:
3673 if (className.isEmpty() && !namespaceName.isEmpty() && !allowEmptyClass)
3674 {
3675 // class and namespace with the same name, correct to return the class.
3676 className=namespaceName;
3677 namespaceName.clear();
3678 }
3679 //printf("extractNamespace '%s' => '%s|%s'\n",qPrint(scopeName),
3680 // qPrint(className),qPrint(namespaceName));
3681 if (className.endsWith("-p"))
3682 {
3683 className = className.left(className.length()-2);
3684 }
3685 return;
3686}
An abstract interface of a namespace symbol.
ClassDef * getClass(const QCString &n)
NamespaceDef * getResolvedNamespace(const QCString &name)

References QCString::clear(), QCString::endsWith(), QCString::findRev(), getClass(), getResolvedNamespace(), QCString::isEmpty(), QCString::left(), QCString::length(), Definition::name(), and QCString::right().

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

◆ fileToString()

QCString fileToString ( const QCString & name,
bool filter,
bool isSourceCode )

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 1438 of file util.cpp.

1439{
1440 if (name.isEmpty()) return QCString();
1441 bool fileOpened=false;
1442 if (name[0]=='-' && name[1]==0) // read from stdin
1443 {
1444 std::string contents;
1445 std::string line;
1446 while (getline(std::cin,line))
1447 {
1448 contents+=line+'\n';
1449 }
1450 return contents;
1451 }
1452 else // read from file
1453 {
1454 FileInfo fi(name.str());
1455 if (!fi.exists() || !fi.isFile())
1456 {
1457 err("file '{}' not found\n",name);
1458 return "";
1459 }
1460 std::string buf;
1461 fileOpened=readInputFile(name,buf,filter,isSourceCode);
1462 if (fileOpened)
1463 {
1464 addTerminalCharIfMissing(buf,'\n');
1465 return buf;
1466 }
1467 }
1468 if (!fileOpened)
1469 {
1470 err("cannot open file '{}' for reading\n",name);
1471 }
1472 return "";
1473}
void addTerminalCharIfMissing(std::string &s, char c)
Definition stringutil.h:84
bool readInputFile(const QCString &fileName, std::string &contents, bool filter, bool isSourceCode)
read a file name fileName and optionally filter and transcode it
Definition util.cpp:5486

References addTerminalCharIfMissing(), err, FileInfo::exists(), QCString::isEmpty(), FileInfo::isFile(), readInputFile(), and QCString::str().

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

◆ fileVisibleInIndex()

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

Definition at line 6039 of file util.cpp.

6040{
6041 bool allExternals = Config_getBool(ALLEXTERNALS);
6042 bool isDocFile = fd->isDocumentationFile();
6043 genSourceFile = !isDocFile && fd->generateSourceFile();
6044 return ( ((allExternals && fd->isLinkable()) ||
6046 ) &&
6047 !isDocFile
6048 );
6049}
virtual bool isLinkable() const =0
virtual bool isLinkableInProject() const =0
virtual bool generateSourceFile() const =0
virtual bool isDocumentationFile() const =0

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

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

◆ filterTitle()

QCString filterTitle ( const QCString & title)

Definition at line 5566 of file util.cpp.

5567{
5568 std::string tf;
5569 std::string t = title.str();
5570 static const reg::Ex re(R"(%[a-z_A-Z]+)");
5571 reg::Iterator it(t,re);
5573 size_t p = 0;
5574 for (; it!=end ; ++it)
5575 {
5576 const auto &match = *it;
5577 size_t i = match.position();
5578 size_t l = match.length();
5579 if (i>p) tf+=t.substr(p,i-p);
5580 tf+=match.str().substr(1); // skip %
5581 p=i+l;
5582 }
5583 tf+=t.substr(p);
5584 return tf;
5585}

References end(), and QCString::str().

Referenced by addToIndices(), createJavaScriptSearchIndex(), PerlModGenerator::generatePerlModForPage(), generateSqlite3ForPage(), generateXMLForPage(), mainPageHasOwnTitle(), parseCommentAsHtml(), SearchIndexExternal::setCurrentDoc(), HtmlGenerator::startFile(), writeExampleIndex(), and writeJavasScriptSearchDataPage().

◆ findAndRemoveWord()

bool findAndRemoveWord ( QCString & 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 4923 of file util.cpp.

4924{
4925 static reg::Ex re(R"(\s*(<\a+>)\s*)");
4926 std::string s = sentence.str();
4927 reg::Iterator it(s,re);
4929 std::string result;
4930 bool found=false;
4931 size_t p=0;
4932 for ( ; it!=end ; ++it)
4933 {
4934 const auto match = *it;
4935 std::string part = match[1].str();
4936 if (part!=word)
4937 {
4938 size_t i = match.position();
4939 size_t l = match.length();
4940 result+=s.substr(p,i-p);
4941 result+=match.str();
4942 p=i+l;
4943 }
4944 else
4945 {
4946 found=true;
4947 size_t i = match[1].position();
4948 size_t l = match[1].length();
4949 result+=s.substr(p,i-p);
4950 p=i+l;
4951 }
4952 }
4953 result+=s.substr(p);
4954 sentence = QCString(result).simplifyWhiteSpace();
4955 return found;
4956}
QCString simplifyWhiteSpace() const
return a copy of this string with leading and trailing whitespace removed and multiple whitespace cha...
Definition qcstring.cpp:190

References end(), QCString::simplifyWhiteSpace(), and QCString::str().

Referenced by isVarWithConstructor().

◆ findFileDef()

FileDef * findFileDef ( const FileNameLinkedMap * fnMap,
const QCString & n,
bool & ambig )

Definition at line 2838 of file util.cpp.

2839{
2840 ambig=FALSE;
2841 if (n.isEmpty()) return nullptr;
2842
2843
2844 const int maxAddrSize = 20;
2845 char addr[maxAddrSize];
2846 qsnprintf(addr,maxAddrSize,"%p:",reinterpret_cast<const void*>(fnMap));
2847 QCString key = addr;
2848 key+=n;
2849
2850 std::lock_guard<std::mutex> lock(g_findFileDefMutex);
2851 FindFileCacheElem *cachedResult = g_findFileDefCache.find(key.str());
2852 //printf("key=%s cachedResult=%p\n",qPrint(key),cachedResult);
2853 if (cachedResult)
2854 {
2855 ambig = cachedResult->isAmbig;
2856 //printf("cached: fileDef=%p\n",cachedResult->fileDef);
2857 return cachedResult->fileDef;
2858 }
2859 else
2860 {
2861 cachedResult = g_findFileDefCache.insert(key.str(),FindFileCacheElem(nullptr,FALSE));
2862 }
2863
2864 QCString name=Dir::cleanDirPath(n.str());
2865 QCString path;
2866 if (name.isEmpty()) return nullptr;
2867 int slashPos=std::max(name.findRev('/'),name.findRev('\\'));
2868 if (slashPos!=-1)
2869 {
2870 path=removeLongPathMarker(name.left(slashPos+1));
2871 name=name.right(name.length()-slashPos-1);
2872 }
2873 if (name.isEmpty()) return nullptr;
2874 const FileName *fn = fnMap->find(name);
2875 if (fn)
2876 {
2877 //printf("fn->size()=%zu\n",fn->size());
2878 if (fn->size()==1)
2879 {
2880 const std::unique_ptr<FileDef> &fd = fn->front();
2881 bool isSamePath = Portable::fileSystemIsCaseSensitive() ?
2882 fd->getPath().right(path.length())==path :
2883 fd->getPath().right(path.length()).lower()==path.lower();
2884 if (path.isEmpty() || isSamePath)
2885 {
2886 cachedResult->fileDef = fd.get();
2887 return fd.get();
2888 }
2889 }
2890 else // file name alone is ambiguous
2891 {
2892 int count=0;
2893 FileDef *lastMatch=nullptr;
2894 QCString pathStripped = stripFromIncludePath(path);
2895 for (const auto &fd_p : *fn)
2896 {
2897 FileDef *fd = fd_p.get();
2898 QCString fdStripPath = stripFromIncludePath(fd->getPath());
2899 if (path.isEmpty() ||
2900 (!pathStripped.isEmpty() && fdStripPath.endsWith(pathStripped)) ||
2901 (pathStripped.isEmpty() && fdStripPath.isEmpty()))
2902 {
2903 count++;
2904 lastMatch=fd;
2905 }
2906 }
2907
2908 ambig=(count>1);
2909 cachedResult->isAmbig = ambig;
2910 cachedResult->fileDef = lastMatch;
2911 return lastMatch;
2912 }
2913 }
2914 else
2915 {
2916 //printf("not found!\n");
2917 }
2918 return nullptr;
2919}
static std::string cleanDirPath(const std::string &path)
Definition dir.cpp:357
A model of a file symbol.
Definition filedef.h:99
virtual QCString getPath() const =0
Class representing all files with a certain base name.
Definition filename.h:30
bool fileSystemIsCaseSensitive()
Definition portable.cpp:471
#define qsnprintf
Definition qcstring.h:49
Cache element for the file name to FileDef mapping cache.
Definition util.cpp:2828
FileDef * fileDef
Definition util.cpp:2830
QCString stripFromIncludePath(const QCString &path)
Definition util.cpp:330
static Cache< std::string, FindFileCacheElem > g_findFileDefCache(5000)
static std::mutex g_findFileDefMutex
Definition util.cpp:2836
QCString removeLongPathMarker(QCString path)
Definition util.cpp:288

References Dir::cleanDirPath(), QCString::endsWith(), FALSE, FindFileCacheElem::fileDef, Portable::fileSystemIsCaseSensitive(), LinkedMap< T, Hash, KeyEqual, Map >::find(), QCString::findRev(), g_findFileDefCache, g_findFileDefMutex, FileDef::getPath(), FindFileCacheElem::isAmbig, QCString::isEmpty(), QCString::left(), QCString::length(), QCString::lower(), qsnprintf, removeLongPathMarker(), QCString::right(), QCString::str(), and stripFromIncludePath().

Referenced by addIncludeFile(), buildFileList(), checkMarkdownMainfile(), DocParser::findAndCopyImage(), DocParser::findDocsForMemberOrCompound(), findFile(), findFilePath(), generateFileRef(), generateFileSources(), DocParser::handleLinkedWord(), DocbookDocVisitor::operator()(), XmlDocVisitor::operator()(), DocDiaFile::parse(), DocDotFile::parse(), DocMscFile::parse(), DocPlantUmlFile::parse(), parseFilesMultiThreading(), parseFilesSingleThreading(), Markdown::Private::processLink(), readIncludeFile(), readTextFileByName(), ModuleManager::resolveImports(), resolveLink(), ModuleManager::resolvePartitions(), resolveRef(), and setFileName().

◆ findFilePath()

QCString findFilePath ( const QCString & file,
bool & ambig )

Definition at line 2923 of file util.cpp.

2924{
2925 ambig=false;
2926 QCString result;
2927 bool found=false;
2928 if (!found)
2929 {
2930 FileInfo fi(file.str());
2931 if (fi.exists())
2932 {
2933 result=fi.absFilePath();
2934 found=true;
2935 }
2936 }
2937 if (!found)
2938 {
2939 const StringVector &examplePathList = Config_getList(EXAMPLE_PATH);
2940 for (const auto &s : examplePathList)
2941 {
2942 std::string absFileName = s+(Portable::pathSeparator()+file).str();
2943 FileInfo fi(absFileName);
2944 if (fi.exists())
2945 {
2946 result=fi.absFilePath();
2947 found=true;
2948 }
2949 }
2950 }
2951
2952 if (!found)
2953 {
2954 // as a fallback we also look in the exampleNameDict
2956 if (fd && !ambig)
2957 {
2958 result=fd->absFilePath();
2959 }
2960 }
2961 return result;
2962}
static FileNameLinkedMap * exampleNameLinkedMap
Definition doxygen.h:102
virtual QCString absFilePath() const =0
QCString pathSeparator()
Definition portable.cpp:375
FileDef * findFileDef(const FileNameLinkedMap *fnMap, const QCString &n, bool &ambig)
Definition util.cpp:2838

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

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

◆ findIndex() [1/2]

int findIndex ( const std::string & s,
const reg::Ex & re )

find the index of the first occurrence of pattern re in a string s returns -1 if the pattern could not be found

Definition at line 6612 of file util.cpp.

6613{
6615 return reg::search(s,match,re) ? static_cast<int>(match.position()) : -1;
6616}
Object representing the matching results.
Definition regex.h:151
bool search(std::string_view str, Match &match, const Ex &re, size_t pos)
Search in a given string str starting at position pos for a match against regular expression re.
Definition regex.cpp:844

References reg::search().

◆ findIndex() [2/2]

int findIndex ( const StringVector & sv,
const std::string & s )

find the index of a string in a vector of strings, returns -1 if the string could not be found

Definition at line 6604 of file util.cpp.

6605{
6606 auto it = std::find(sv.begin(),sv.end(),s);
6607 return it!=sv.end() ? static_cast<int>(it-sv.begin()) : -1;
6608}

Referenced by initUCF(), VhdlDocGen::parseForBinding(), VhdlDocGen::parseUCF(), DotFilePatcher::run(), and VhdlDocGen::writeFormatString().

◆ fixSpaces()

QCString fixSpaces ( const QCString & s)
inline

Definition at line 469 of file util.h.

469{ return substitute(s," ","&#160;"); }
QCString substitute(const QCString &s, const QCString &src, const QCString &dst)
substitute all occurrences of src in s by dst
Definition qcstring.cpp:571

References substitute().

Referenced by renderQuickLinksAsTabs(), renderQuickLinksAsTree(), writeClassMemberIndexFiltered(), writeFileMemberIndexFiltered(), writeModuleMemberIndexFiltered(), writeNamespaceMemberIndexFiltered(), and writeUserGroupStubPage().

◆ generateAnonymousAnchor()

QCString generateAnonymousAnchor ( const QCString & fileName,
int count )

Definition at line 3500 of file util.cpp.

3501{
3502 QCString fn = stripFromPath(fileName)+":"+QCString().setNum(count);
3503 const int sig_size=16;
3504 uint8_t md5_sig[sig_size];
3505 MD5Buffer(fn.data(),static_cast<unsigned int>(fn.length()),md5_sig);
3506 char result[sig_size*3+2];
3507 char *p = result;
3508 *p++='@';
3509 for (int i=0;i<sig_size;i++)
3510 {
3511 static const char oct[]="01234567";
3512 uint8_t byte = md5_sig[i];
3513 *p++=oct[(byte>>6)&7];
3514 *p++=oct[(byte>>3)&7];
3515 *p++=oct[(byte>>0)&7];
3516 }
3517 *p='\0';
3518 return result;
3519}
QCString & setNum(short n)
Definition qcstring.h:459
static QCString stripFromPath(const QCString &p, const StringVector &l)
Definition util.cpp:299

References QCString::data(), QCString::length(), QCString::setNum(), and stripFromPath().

◆ generateFileRef()

void generateFileRef ( OutputList & ol,
const QCString & name,
const QCString & linkTxt = QCString() )

Definition at line 2810 of file util.cpp.

2811{
2812 //printf("generateFileRef(%s,%s)\n",name,text);
2813 QCString linkText = text.isEmpty() ? text : name;
2814 //FileInfo *fi;
2815 bool ambig = false;
2817 if (fd && fd->isLinkable())
2818 // link to documented input file
2819 ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),QCString(),linkText);
2820 else
2821 ol.docify(linkText);
2822}
static FileNameLinkedMap * inputNameLinkedMap
Definition doxygen.h:104
void writeObjectLink(const QCString &ref, const QCString &file, const QCString &anchor, const QCString &name)
Definition outputlist.h:439
void docify(const QCString &s)
Definition outputlist.h:437

References OutputList::docify(), findFileDef(), Definition::getOutputFileBase(), Definition::getReference(), Doxygen::inputNameLinkedMap, QCString::isEmpty(), Definition::isLinkable(), and OutputList::writeObjectLink().

◆ generateMarker()

QCString generateMarker ( int id)

Generate a place holder for a position in a list. Used for translators to be able to specify different elements orders depending on whether text flows from left to right or visa versa.

Definition at line 280 of file util.cpp.

281{
282 const int maxMarkerStrLen = 20;
283 char result[maxMarkerStrLen];
284 qsnprintf(result,maxMarkerStrLen,"@%d",id);
285 return result;
286}

References qsnprintf.

Referenced by TranslatorAfrikaans::trWriteList(), TranslatorArabic::trWriteList(), TranslatorArmenian::trWriteList(), TranslatorBrazilian::trWriteList(), TranslatorBulgarian::trWriteList(), TranslatorCatalan::trWriteList(), TranslatorChinese::trWriteList(), TranslatorChinesetraditional::trWriteList(), TranslatorCroatian::trWriteList(), TranslatorCzech::trWriteList(), TranslatorDanish::trWriteList(), TranslatorDutch::trWriteList(), TranslatorEnglish::trWriteList(), TranslatorEsperanto::trWriteList(), TranslatorFinnish::trWriteList(), TranslatorFrench::trWriteList(), TranslatorGerman::trWriteList(), TranslatorGreek::trWriteList(), TranslatorHindi::trWriteList(), TranslatorHungarian::trWriteList(), TranslatorIndonesian::trWriteList(), TranslatorItalian::trWriteList(), TranslatorJapanese::trWriteList(), TranslatorKorean::trWriteList(), TranslatorLatvian::trWriteList(), TranslatorLithuanian::trWriteList(), TranslatorMacedonian::trWriteList(), TranslatorNorwegian::trWriteList(), TranslatorPersian::trWriteList(), TranslatorPolish::trWriteList(), TranslatorPortuguese::trWriteList(), TranslatorRomanian::trWriteList(), TranslatorRussian::trWriteList(), TranslatorSerbian::trWriteList(), TranslatorSerbianCyrillic::trWriteList(), TranslatorSlovak::trWriteList(), TranslatorSlovene::trWriteList(), TranslatorSpanish::trWriteList(), TranslatorSwedish::trWriteList(), TranslatorTurkish::trWriteList(), TranslatorUkrainian::trWriteList(), and TranslatorVietnamese::trWriteList().

◆ getCaseSenseNames()

bool getCaseSenseNames ( )

Definition at line 3262 of file util.cpp.

3263{
3264 auto caseSenseNames = Config_getEnum(CASE_SENSE_NAMES);
3265
3266 if (caseSenseNames == CASE_SENSE_NAMES_t::YES) return true;
3267 else if (caseSenseNames == CASE_SENSE_NAMES_t::NO) return false;
3269}
#define Config_getEnum(name)
Definition config.h:35

References Config_getEnum, and Portable::fileSystemIsCaseSensitive().

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

◆ getDefs()

GetDefResult getDefs ( const GetDefInput & input)

Definition at line 2242 of file util.cpp.

2243{
2244 GetDefResult result;
2245 if (input.memberName.isEmpty()) return result;
2246 AUTO_TRACE("scopeName={},memberName={},forceEmptyScope={}",
2247 input.scopeName,input.memberName,input.forceEmptyScope);
2248
2249 //printf("@@ --- getDefsNew(%s,%s)-----------\n",qPrint(scName),qPrint(mbName));
2250 const Definition *scope = Doxygen::globalScope;
2251 SymbolResolver resolver;
2252 if (input.currentFile) resolver.setFileScope(input.currentFile);
2253 if (!input.scopeName.isEmpty() && !input.forceEmptyScope)
2254 {
2255 scope = resolver.resolveSymbol(scope,input.scopeName);
2256 }
2257 if (scope==Doxygen::globalScope)
2258 {
2259 scope = input.currentFile;
2260 }
2261 //printf("@@ -> found scope scope=%s member=%s out=%s\n",qPrint(input.scopeName),qPrint(input.memberName),qPrint(scope?scope->name():""));
2262 //
2263 const Definition *symbol = resolver.resolveSymbol(scope,input.memberName,input.args,input.checkCV,input.insideCode,true);
2264 //printf("@@ -> found symbol in=%s out=%s\n",qPrint(input.memberName),qPrint(symbol?symbol->qualifiedName():QCString()));
2265 if (symbol && symbol->definitionType()==Definition::TypeMember)
2266 {
2267 result.md = toMemberDef(symbol);
2268 result.cd = result.md->getClassDef();
2269 if (result.cd==nullptr) result.nd = result.md->getNamespaceDef();
2270 if (result.cd==nullptr && result.nd==nullptr) result.fd = result.md->getFileDef();
2271 result.gd = result.md->getGroupDef();
2272 result.found = true;
2273 }
2274 else if (symbol && symbol->definitionType()==Definition::TypeClass)
2275 {
2276 result.cd = toClassDef(symbol);
2277 result.found = true;
2278 }
2279 else if (symbol && symbol->definitionType()==Definition::TypeNamespace)
2280 {
2281 result.nd = toNamespaceDef(symbol);
2282 result.found = true;
2283 }
2284 else if (symbol && symbol->definitionType()==Definition::TypeConcept)
2285 {
2286 result.cnd = toConceptDef(symbol);
2287 result.found = true;
2288 }
2289 else if (symbol && symbol->definitionType()==Definition::TypeModule)
2290 {
2291 result.modd = toModuleDef(symbol);
2292 result.found = true;
2293 }
2294 return result;
2295}
The common base class of all entity definitions found in the sources.
Definition definition.h:76
virtual DefType definitionType() const =0
static NamespaceDefMutable * globalScope
Definition doxygen.h:120
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 QCString &name, const QCString &args=QCString(), 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:115
const FileDef * currentFile
Definition util.h:116
QCString scopeName
Definition util.h:112
bool insideCode
Definition util.h:118
bool checkCV
Definition util.h:117
QCString args
Definition util.h:114
QCString memberName
Definition util.h:113
const MemberDef * md
Definition util.h:124
const ConceptDef * cnd
Definition util.h:129
const FileDef * fd
Definition util.h:126
const ModuleDef * modd
Definition util.h:130
const GroupDef * gd
Definition util.h:128
bool found
Definition util.h:123
const ClassDef * cd
Definition util.h:125
const NamespaceDef * nd
Definition util.h:127

References GetDefInput::args, AUTO_TRACE, GetDefResult::cd, GetDefInput::checkCV, GetDefResult::cnd, GetDefInput::currentFile, Definition::definitionType(), GetDefResult::fd, GetDefInput::forceEmptyScope, GetDefResult::found, GetDefResult::gd, MemberDef::getClassDef(), MemberDef::getFileDef(), MemberDef::getGroupDef(), MemberDef::getNamespaceDef(), Doxygen::globalScope, GetDefInput::insideCode, QCString::isEmpty(), 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(), getLinkInScope(), getLinkInScope(), linkifyText(), and resolveRef().

◆ getDotImageExtension()

QCString getDotImageExtension ( )

Definition at line 6239 of file util.cpp.

6240{
6241 QCString imgExt = Config_getEnumAsString(DOT_IMAGE_FORMAT);
6242 int i= imgExt.find(':'); // strip renderer part when using e.g. 'png:cairo:gd' as format
6243 return i==-1 ? imgExt : imgExt.left(i);
6244}
#define Config_getEnumAsString(name)
Definition config.h:36

References Config_getEnumAsString, QCString::find(), and QCString::left().

Referenced by RTFGenerator::endCallGraph(), RTFGenerator::endDirDepGraph(), RTFGenerator::endDotGraph(), RTFGenerator::endInclDepGraph(), DotGraph::generateCode(), DotGraph::imgName(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), 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(), writeGraphInfo(), HtmlDocVisitor::writeMscFile(), and HtmlDocVisitor::writePlantUMLFile().

◆ getEncoding()

QCString getEncoding ( const FileInfo & fi)

Definition at line 5647 of file util.cpp.

5648{
5649 InputFileEncoding elem;
5650 auto getter = [](const InputFileEncoding &e) -> QCString { return e.pattern; };
5651 if (genericPatternMatch(fi,Doxygen::inputFileEncodingList,elem,getter)) // check for file specific encoding
5652 {
5653 return elem.encoding;
5654 }
5655 else // fall back to default encoding
5656 {
5657 return Config_getString(INPUT_ENCODING);
5658 }
5659}
static InputFileEncodingList inputFileEncodingList
Definition doxygen.h:139
#define Config_getString(name)
Definition config.h:32
QCString encoding
Definition doxygen.h:70
bool genericPatternMatch(const FileInfo &fi, const PatternList &patList, PatternElem &elem, PatternGet getter)
Definition util.cpp:5590

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

Referenced by readCodeFragment(), and readInputFile().

◆ getFileFilter()

QCString getFileFilter ( const QCString & 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 1366 of file util.cpp.

1367{
1368 // sanity check
1369 if (name.isEmpty()) return "";
1370
1371 const StringVector& filterSrcList = Config_getList(FILTER_SOURCE_PATTERNS);
1372 const StringVector& filterList = Config_getList(FILTER_PATTERNS);
1373
1374 QCString filterName;
1375 bool found=FALSE;
1376 if (isSourceCode && !filterSrcList.empty())
1377 { // first look for source filter pattern list
1378 filterName = getFilterFromList(name,filterSrcList,found);
1379 }
1380 if (!found && filterName.isEmpty())
1381 { // then look for filter pattern list
1382 filterName = getFilterFromList(name,filterList,found);
1383 }
1384 if (!found)
1385 { // then use the generic input filter
1386 return Config_getString(INPUT_FILTER);
1387 }
1388 else
1389 {
1390 /* remove surrounding double quotes */
1391 if (filterName.length()>=2 && filterName[0]=='"' && filterName[static_cast<int>(filterName.length())-1]=='"')
1392 {
1393 filterName = filterName.mid(1,filterName.length()-2);
1394 }
1395 return filterName;
1396 }
1397}
static QCString getFilterFromList(const QCString &name, const StringVector &filterList, bool &found)
Definition util.cpp:1325

References Config_getList, Config_getString, FALSE, getFilterFromList(), QCString::isEmpty(), QCString::length(), and QCString::mid().

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

◆ getFileNameExtension()

◆ getLanguageFromCodeLang()

SrcLangExt getLanguageFromCodeLang ( QCString & fileName)

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

Definition at line 5165 of file util.cpp.

5166{
5167 // try the extension
5168 auto lang = getLanguageFromFileName(fileName, SrcLangExt::Unknown);
5169 if (lang == SrcLangExt::Unknown)
5170 {
5171 // try the language names
5172 QCString langName = fileName.lower();
5173 if (langName.at(0)=='.') langName = langName.mid(1);
5174 auto it = std::find_if(g_lang2extMap.begin(),g_lang2extMap.end(),
5175 [&langName](const auto &info) { return info.langName==langName; });
5176 if (it != g_lang2extMap.end())
5177 {
5178 lang = it->parserId;
5179 fileName = it->defExt;
5180 }
5181 else // default to C++
5182 {
5183 return SrcLangExt::Cpp;
5184 }
5185 }
5186 return lang;
5187}
SrcLangExt getLanguageFromFileName(const QCString &fileName, SrcLangExt defLang)
Definition util.cpp:5147
static std::vector< Lang2ExtMap > g_lang2extMap
Definition util.cpp:5018

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

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

◆ getLanguageFromFileName()

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

Definition at line 5147 of file util.cpp.

5148{
5149 FileInfo fi(fileName.str());
5150 // we need only the part after the last ".", newer implementations of FileInfo have 'suffix()' for this.
5151 QCString extName = QCString(fi.extension(FALSE)).lower();
5152 if (extName.isEmpty()) extName=".no_extension";
5153 if (extName.at(0)!='.') extName.prepend(".");
5154 auto it = g_extLookup.find(extName.str());
5155 if (it!=g_extLookup.end()) // listed extension
5156 {
5157 //printf("getLanguageFromFileName(%s)=%x\n",qPrint(fi.extension()),*pVal);
5158 return it->second;
5159 }
5160 //printf("getLanguageFromFileName(%s) not found!\n",qPrint(fileName));
5161 return defLang; // not listed => assume C-ish language.
5162}
static std::unordered_map< std::string, SrcLangExt > g_extLookup
Definition util.cpp:5008

References QCString::at(), FileInfo::extension(), FALSE, g_extLookup, QCString::isEmpty(), QCString::lower(), QCString::prepend(), and QCString::str().

Referenced by MemberDefImpl::_writeMultiLineInitializer(), ClassDefImpl::ClassDefImpl(), convertCppComments(), DocRef::DocRef(), FileDefImpl::FileDefImpl(), generateExampleDocs(), getLanguageFromCodeLang(), 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()

QCString getLanguageSpecificSeparator ( SrcLangExt lang,
bool classScope = FALSE )

Returns the scope separator to use given the programming language lang.

Definition at line 5849 of file util.cpp.

5850{
5851 if (lang==SrcLangExt::Java || lang==SrcLangExt::CSharp || lang==SrcLangExt::VHDL || lang==SrcLangExt::Python)
5852 {
5853 return ".";
5854 }
5855 else if (lang==SrcLangExt::PHP && !classScope)
5856 {
5857 return "\\";
5858 }
5859 else
5860 {
5861 return "::";
5862 }
5863}

Referenced by DefinitionImpl::_writeSourceRefList(), addGlobalFunction(), MemberDefImpl::addListReference(), addMethodToClass(), addVariableToFile(), MemberDefImpl::displayDefinition(), DefinitionAliasImpl::init(), linkToText(), makeDisplayName(), makeDisplayName(), makeQualifiedNameWithTemplateParameters(), ClassDefImpl::mergeMembersFromBaseClasses(), DefinitionImpl::qualifiedName(), MemberDefImpl::qualifiedName(), SearchIndex::setCurrentDoc(), validatingParseDoc(), MemberDefImpl::warnIfUndocumented(), writeAlphabeticalClassList(), MemberDefImpl::writeDeclaration(), writeDefArgumentList(), MemberDefImpl::writeDocumentation(), writeJavasScriptSearchDataPage(), MemberDefImpl::writeLink(), and writeMemberReference().

◆ getOverloadDocs()

QCString getOverloadDocs ( )

Returns the standard string that is generated when the \overload command is used.

Definition at line 4031 of file util.cpp.

4032{
4033 return theTranslator->trOverloadText();
4034 //"This is an overloaded member function, "
4035 // "provided for convenience. It differs from the above "
4036 // "function only in what argument(s) it accepts.";
4037}
Translator * theTranslator
Definition language.cpp:71

References theTranslator.

Referenced by addMemberDocs(), addOverloaded(), and CommentScanner::parseCommentBlock().

◆ getPrefixIndex()

int getPrefixIndex ( const QCString & 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 3173 of file util.cpp.

3174{
3175 if (name.isEmpty()) return 0;
3176 const StringVector &sl = Config_getList(IGNORE_PREFIX);
3177 for (const auto &s : sl)
3178 {
3179 const char *ps=s.c_str();
3180 const char *pd=name.data();
3181 int i=0;
3182 while (*ps!=0 && *pd!=0 && *ps==*pd)
3183 {
3184 ps++;
3185 pd++;
3186 i++;
3187 }
3188 if (*ps==0 && *pd!=0)
3189 {
3190 return i;
3191 }
3192 }
3193 return 0;
3194}

References Config_getList, QCString::data(), and QCString::isEmpty().

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

◆ getProjectId()

QCString getProjectId ( )

Definition at line 6761 of file util.cpp.

6762{
6763 QCString projectCookie = Config_getString(HTML_PROJECT_COOKIE);
6764 if (projectCookie.isEmpty()) return QCString();
6765 uint8_t md5_sig[16];
6766 char sigStr[34];
6767 MD5Buffer(projectCookie.data(),static_cast<unsigned int>(projectCookie.length()),md5_sig);
6768 MD5SigToString(md5_sig,sigStr);
6769 sigStr[32]='_'; sigStr[33]=0;
6770 return sigStr;
6771}

References Config_getString, QCString::data(), QCString::isEmpty(), and QCString::length().

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

◆ getScopeFragment()

int getScopeFragment ( const QCString & 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 4581 of file util.cpp.

4582{
4583 int sl=static_cast<int>(s.length());
4584 int sp=p;
4585 int count=0;
4586 bool done=false;
4587 if (sp>=sl) return -1;
4588 while (sp<sl)
4589 {
4590 char c=s.at(sp);
4591 if (c==':')
4592 {
4593 sp++;
4594 p++;
4595 }
4596 else
4597 {
4598 break;
4599 }
4600 }
4601 while (sp<sl)
4602 {
4603 char c=s.at(sp);
4604 switch (c)
4605 {
4606 case ':': // found next part
4607 goto found;
4608 case '<': // skip template specifier
4609 count=1;sp++;
4610 done=false;
4611 while (sp<sl && !done)
4612 {
4613 // TODO: deal with << and >> operators!
4614 c=s.at(sp++);
4615 switch(c)
4616 {
4617 case '<': count++; break;
4618 case '>': count--; if (count==0) done=true; break;
4619 default: break;
4620 }
4621 }
4622 break;
4623 default:
4624 sp++;
4625 break;
4626 }
4627 }
4628found:
4629 *l=sp-p;
4630 //printf("getScopeFragment(%s,%d)=%s\n",qPrint(s),p,qPrint(s.mid(p,*l)));
4631 return p;
4632}

References QCString::at(), and QCString::length().

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

◆ guessSection()

EntryType guessSection ( const QCString & name)

try to determine if name is a source or a header file name by looking at the extension. A number of variations is allowed in both upper and lower case) If anyone knows or uses another extension please let me know :-)

Definition at line 339 of file util.cpp.

340{
341 QCString n=name.lower();
342 static const std::unordered_set<std::string> sourceExt = {
343 "c","cc","cxx","cpp","c++","cppm","ccm","cxxm","c++m", // C/C++
344 "java", // Java
345 "cs", // C#
346 "m","mm", // Objective-C
347 "ii","ixx","ipp","i++","inl", // C/C++ inline
348 "xml","lex","sql" // others
349 };
350 static const std::unordered_set<std::string> headerExt = {
351 "h", "hh", "hxx", "hpp", "h++", "ixx", // C/C++ header
352 "idl", "ddl", "pidl", "ice" // IDL like
353 };
354 int lastDot = n.findRev('.');
355 if (lastDot!=-1)
356 {
357 QCString extension = n.mid(lastDot+1); // part after the last dot
358 if (sourceExt.find(extension.str())!=sourceExt.end())
359 {
360 return EntryType::makeSource();
361 }
362 if (headerExt.find(extension.str())!=headerExt.end())
363 {
364 return EntryType::makeHeader();
365 }
366 }
367 else
368 {
369 if (getLanguageFromFileName(name,SrcLangExt::Unknown) == SrcLangExt::Cpp) return EntryType::makeHeader();
370 }
371 return EntryType::makeEmpty();
372}

References QCString::findRev(), getLanguageFromFileName(), QCString::lower(), QCString::mid(), and QCString::str().

Referenced by addIncludeFile(), anonymous_namespace{tagreader.cpp}::TagFileParser::buildLists(), ClassDefImpl::ClassDefImpl(), computeClassRelations(), FileDefImpl::FileDefImpl(), FileDefImpl::generateSourceFile(), parseMain(), parseMain(), Preprocessor::processFile(), setFileName(), and warnUndocumentedNamespaces().

◆ initDefaultExtensionMapping()

void initDefaultExtensionMapping ( )

Definition at line 5074 of file util.cpp.

5075{
5076 // NOTE: when adding an extension, also add the extension in config.xml
5077 // extension parser id
5078 updateLanguageMapping(".dox", "c");
5079 updateLanguageMapping(".txt", "c"); // see bug 760836
5080 updateLanguageMapping(".doc", "c");
5081 updateLanguageMapping(".c", "c");
5082 updateLanguageMapping(".C", "c");
5083 updateLanguageMapping(".cc", "c");
5084 updateLanguageMapping(".CC", "c");
5085 updateLanguageMapping(".cxx", "c");
5086 updateLanguageMapping(".cpp", "c");
5087 updateLanguageMapping(".c++", "c");
5088 updateLanguageMapping(".cxxm", "c"); // C++20 modules
5089 updateLanguageMapping(".cppm", "c"); // C++20 modules
5090 updateLanguageMapping(".ccm", "c"); // C++20 modules
5091 updateLanguageMapping(".c++m", "c"); // C++20 modules
5092 updateLanguageMapping(".ii", "c");
5093 updateLanguageMapping(".ixx", "c");
5094 updateLanguageMapping(".ipp", "c");
5095 updateLanguageMapping(".i++", "c");
5096 updateLanguageMapping(".inl", "c");
5097 updateLanguageMapping(".h", "c");
5098 updateLanguageMapping(".H", "c");
5099 updateLanguageMapping(".hh", "c");
5100 updateLanguageMapping(".HH", "c");
5101 updateLanguageMapping(".hxx", "c");
5102 updateLanguageMapping(".hpp", "c");
5103 updateLanguageMapping(".h++", "c");
5104 updateLanguageMapping(".idl", "idl");
5105 updateLanguageMapping(".ddl", "idl");
5106 updateLanguageMapping(".odl", "idl");
5107 updateLanguageMapping(".java", "java");
5108 //updateLanguageMapping(".as", "javascript"); // not officially supported
5109 //updateLanguageMapping(".js", "javascript"); // not officially supported
5110 updateLanguageMapping(".cs", "csharp");
5111 updateLanguageMapping(".d", "d");
5112 updateLanguageMapping(".php", "php");
5113 updateLanguageMapping(".php4", "php");
5114 updateLanguageMapping(".php5", "php");
5115 updateLanguageMapping(".inc", "php");
5116 updateLanguageMapping(".phtml", "php");
5117 updateLanguageMapping(".m", "objective-c");
5118 updateLanguageMapping(".M", "objective-c");
5119 updateLanguageMapping(".mm", "c"); // see bug746361
5120 updateLanguageMapping(".py", "python");
5121 updateLanguageMapping(".pyw", "python");
5122 updateLanguageMapping(".f", "fortran");
5123 updateLanguageMapping(".for", "fortran");
5124 updateLanguageMapping(".f90", "fortran");
5125 updateLanguageMapping(".f95", "fortran");
5126 updateLanguageMapping(".f03", "fortran");
5127 updateLanguageMapping(".f08", "fortran");
5128 updateLanguageMapping(".f18", "fortran");
5129 updateLanguageMapping(".vhd", "vhdl");
5130 updateLanguageMapping(".vhdl", "vhdl");
5131 updateLanguageMapping(".ucf", "vhdl");
5132 updateLanguageMapping(".qsf", "vhdl");
5133 updateLanguageMapping(".md", "md");
5134 updateLanguageMapping(".markdown", "md");
5135 updateLanguageMapping(".ice", "slice");
5136 updateLanguageMapping(".l", "lex");
5137 updateLanguageMapping(".doxygen_lex_c", "c"); // this is a placeholder so we can map initializations
5138 // in the lex scanning to cpp
5139}

References updateLanguageMapping().

Referenced by initDoxygen().

◆ inlineArgListToDoc()

QCString inlineArgListToDoc ( const ArgumentList & al)

Definition at line 1153 of file util.cpp.

1154{
1155 QCString paramDocs;
1156 if (al.hasDocumentation())
1157 {
1158 for (const Argument &a : al)
1159 {
1160 if (a.hasDocumentation())
1161 {
1162 QCString docsWithoutDir = a.docs;
1163 QCString direction = extractDirection(docsWithoutDir);
1164 paramDocs+=" \\ilinebr @param"+direction+" "+a.name+" "+docsWithoutDir;
1165 }
1166 }
1167 }
1168 return paramDocs;
1169}
bool hasDocumentation() const
Definition arguments.cpp:22
QCString extractDirection(QCString &docs)
Strip the direction part from docs and return it as a string in canonical form The input docs string ...
Definition util.cpp:6128

References extractDirection(), and ArgumentList::hasDocumentation().

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

◆ inlineTemplateArgListToDoc()

QCString inlineTemplateArgListToDoc ( const ArgumentList & al)

Definition at line 1171 of file util.cpp.

1172{
1173 QCString paramDocs;
1174 if (al.hasTemplateDocumentation())
1175 {
1176 for (const Argument &a : al)
1177 {
1178 if (!a.docs.isEmpty())
1179 {
1180 if (!a.name.isEmpty())
1181 {
1182 paramDocs+=" \\ilinebr @tparam "+a.name+" "+a.docs;
1183 }
1184 else if (!a.type.isEmpty())
1185 {
1186 QCString type = a.type;
1187 type.stripPrefix("class ");
1188 type.stripPrefix("typename ");
1189 type = type.stripWhiteSpace();
1190 paramDocs+=" \\ilinebr @tparam "+type+" "+a.docs;
1191 }
1192 }
1193 }
1194 }
1195 return paramDocs;
1196}
bool hasTemplateDocumentation() const
Definition arguments.cpp:30
bool stripPrefix(const QCString &prefix)
Definition qcstring.h:213

References ArgumentList::hasTemplateDocumentation(), QCString::stripPrefix(), and QCString::stripWhiteSpace().

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

◆ insertTemplateSpecifierInScope()

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

Definition at line 3688 of file util.cpp.

3689{
3690 QCString result=scope;
3691 if (!templ.isEmpty() && scope.find('<')==-1)
3692 {
3693 int si=0, pi=0;
3694 ClassDef *cd=nullptr;
3695 while (
3696 (si=scope.find("::",pi))!=-1 && !getClass(scope.left(si)+templ) &&
3697 ((cd=getClass(scope.left(si)))==nullptr || cd->templateArguments().empty())
3698 )
3699 {
3700 //printf("Tried '%s'\n",qPrint((scope.left(si)+templ)));
3701 pi=si+2;
3702 }
3703 if (si==-1) // not nested => append template specifier
3704 {
3705 result+=templ;
3706 }
3707 else // nested => insert template specifier before after first class name
3708 {
3709 result=scope.left(si) + templ + scope.right(scope.length()-si);
3710 }
3711 }
3712 //printf("insertTemplateSpecifierInScope('%s','%s')=%s\n",
3713 // qPrint(scope),qPrint(templ),qPrint(result));
3714 return result;
3715}
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(), QCString::find(), getClass(), QCString::isEmpty(), QCString::left(), QCString::length(), QCString::right(), and ClassDef::templateArguments().

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

◆ integerToAlpha()

QCString integerToAlpha ( int n,
bool upper = true )

Definition at line 6632 of file util.cpp.

6633{
6634 QCString result;
6635 int residual = n;
6636
6637 char modVal[2];
6638 modVal[1] = 0;
6639 while (residual > 0)
6640 {
6641 modVal[0] = (upper ? 'A': 'a') + (residual-1)%26;
6642 result = modVal + result;
6643 residual = (residual-1) / 26;
6644 }
6645 return result;
6646}

Referenced by ManDocVisitor::operator()(), and RTFDocVisitor::operator()().

◆ integerToRoman()

QCString integerToRoman ( int n,
bool upper = true )

Definition at line 6648 of file util.cpp.

6649{
6650 static const char *str_romans_upper[] = { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" };
6651 static const char *str_romans_lower[] = { "m", "cm", "d", "cd", "c", "xc", "l", "xl", "x", "ix", "v", "iv", "i" };
6652 static const int values[] = { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 };
6653 static const char **str_romans = upper ? str_romans_upper : str_romans_lower;
6654
6655 QCString result;
6656 int residual = n;
6657
6658 for (int i = 0; i < 13; ++i)
6659 {
6660 while (residual - values[i] >= 0)
6661 {
6662 result += str_romans[i];
6663 residual -= values[i];
6664 }
6665 }
6666
6667 return result;
6668}

Referenced by LatexDocVisitor::operator()(), ManDocVisitor::operator()(), and RTFDocVisitor::operator()().

◆ isId()

◆ isIdJS()

bool isIdJS ( int c)
inline

Definition at line 211 of file util.h.

212{
213 return c>=128 || c<0 || isalnum(c);
214}

Referenced by SearchTerm::termEncoded().

◆ isURL()

bool isURL ( const QCString & url)

Checks whether the given url starts with a supported protocol.

Definition at line 5865 of file util.cpp.

5866{
5867 static const std::unordered_set<std::string> schemes = {
5868 "http", "https", "ftp", "ftps", "sftp", "file", "news", "irc", "ircs"
5869 };
5870 QCString loc_url = url.stripWhiteSpace();
5871 int colonPos = loc_url.find(':');
5872 return colonPos!=-1 && schemes.find(loc_url.left(colonPos).str())!=schemes.end();
5873}

References QCString::find(), QCString::left(), QCString::str(), and QCString::stripWhiteSpace().

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

◆ join()

std::string join ( const StringVector & s,
const std::string & delimiter )

create a string where the string in the vector are joined by the given delimiter

Definition at line 6619 of file util.cpp.

6620{
6621 std::string result;
6622 bool first=true;
6623 for (const auto &s : sv)
6624 {
6625 if (!first) result+=delimiter;
6626 first=false;
6627 result+=s;
6628 }
6629 return result;
6630}

Referenced by handleAnchor(), handleCite(), handleFormatBlock(), and handleImage().

◆ langToString()

QCString langToString ( SrcLangExt lang)

Returns a string representation of lang.

Definition at line 5843 of file util.cpp.

5844{
5845 return to_string(lang);
5846}
static constexpr const char * to_string(Protection prot) noexcept
Definition types.h:38

References to_string().

Referenced by buildNamespaceList(), findUsingDirectives(), generateXMLForClass(), generateXMLForFile(), and generateXMLForNamespace().

◆ leftScopeMatch()

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

Definition at line 882 of file util.cpp.

883{
884 size_t sl=scope.length();
885 size_t nl=name.length();
886 return (name==scope || // equal
887 (name.left(sl)==scope && // substring
888 nl>sl+1 && name.at(sl)==':' && name.at(sl+1)==':' // scope
889 )
890 );
891}

References QCString::at(), QCString::left(), and QCString::length().

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

◆ lineBlock()

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

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

See also
routine extractBlock

Definition at line 5822 of file util.cpp.

5823{
5824 int result = 1;
5825
5826 // find the character positions of the first marker
5827 int m1 = text.find(marker);
5828 if (m1==-1) return result;
5829
5830 // find start line positions for the markers
5831 bool found=false;
5832 int p=0, i=0;
5833 while (!found && (i=text.find('\n',p))!=-1)
5834 {
5835 found = (p<=m1 && m1<i); // found the line with the start marker
5836 p=i+1;
5837 result++;
5838 }
5839 return result;
5840}

References QCString::find().

Referenced by readIncludeFile().

◆ linkifyText()

void linkifyText ( const TextGeneratorIntf & ol,
const Definition * scope,
const FileDef * fileScope,
const Definition * self,
const QCString & text,
bool autoBreak = FALSE,
bool external = TRUE,
bool keepSpaces = FALSE,
int indentLevel = 0 )

Definition at line 894 of file util.cpp.

898{
899 AUTO_TRACE("scope={} fileScope={} text={} autoBreak={} external={} keepSpaces={} indentLevel={}",
900 scope?scope->name():"",fileScope?fileScope->name():"",
901 text,autoBreak,external,keepSpaces,indentLevel);
902 if (text.isEmpty()) return;
903 //printf("linkify='%s'\n",qPrint(text));
904 std::string_view txtStr=text.view();
905 size_t strLen = txtStr.length();
906 if (strLen==0) return;
907
908 static const reg::Ex regExp(R"((::)?\a[\w~!\\.:$"]*)");
909 reg::Iterator it(txtStr,regExp);
911
912 //printf("linkifyText scope=%s fileScope=%s strtxt=%s strlen=%zu external=%d\n",
913 // scope ? qPrint(scope->name()):"<none>",
914 // fileScope ? qPrint(fileScope->name()) : "<none>",
915 // qPrint(txtStr),strLen,external);
916 size_t index=0;
917 size_t skipIndex=0;
918 size_t floatingIndex=0;
919 for (; it!=end ; ++it) // for each word from the text string
920 {
921 const auto &match = *it;
922 size_t newIndex = match.position();
923 size_t matchLen = match.length();
924 floatingIndex+=newIndex-skipIndex+matchLen;
925 if (newIndex>0 && txtStr.at(newIndex-1)=='0') // ignore hex numbers (match x00 in 0x00)
926 {
927 std::string_view part = txtStr.substr(skipIndex,newIndex+matchLen-skipIndex);
928 out.writeString(part,keepSpaces);
929 skipIndex=index=newIndex+matchLen;
930 continue;
931 }
932
933 // add non-word part to the result
934 bool insideString=FALSE;
935 for (size_t i=index;i<newIndex;i++)
936 {
937 if (txtStr.at(i)=='"') insideString=!insideString;
938 if (txtStr.at(i)=='\\') i++; // skip next character it is escaped
939 }
940
941 //printf("floatingIndex=%d strlen=%d autoBreak=%d\n",floatingIndex,strLen,autoBreak);
942 if (strLen>35 && floatingIndex>30 && autoBreak) // try to insert a split point
943 {
944 std::string_view splitText = txtStr.substr(skipIndex,newIndex-skipIndex);
945 size_t splitLength = splitText.length();
946 size_t offset=1;
947 size_t i = splitText.find(',');
948 if (i==std::string::npos) { i=splitText.find('<'); if (i!=std::string::npos) offset=0; }
949 if (i==std::string::npos) i=splitText.find('>');
950 if (i==std::string::npos) i=splitText.find(' ');
951 //printf("splitText=[%s] len=%d i=%d offset=%d\n",qPrint(splitText),splitLength,i,offset);
952 if (i!=std::string::npos) // add a link-break at i in case of Html output
953 {
954 std::string_view part1 = splitText.substr(0,i+offset);
955 out.writeString(part1,keepSpaces);
956 out.writeBreak(indentLevel==0 ? 0 : indentLevel+1);
957 std::string_view part2 = splitText.substr(i+offset);
958 out.writeString(part2,keepSpaces);
959 floatingIndex=splitLength-i-offset+matchLen;
960 }
961 else
962 {
963 out.writeString(splitText,keepSpaces);
964 }
965 }
966 else
967 {
968 //ol.docify(txtStr.mid(skipIndex,newIndex-skipIndex));
969 std::string_view part = txtStr.substr(skipIndex,newIndex-skipIndex);
970 out.writeString(part,keepSpaces);
971 }
972 // get word from string
973 std::string_view word=txtStr.substr(newIndex,matchLen);
974 QCString matchWord = substitute(substitute(word,"\\","::"),".","::");
975 //printf("linkifyText word=%s matchWord=%s scope=%s\n",
976 // qPrint(word),qPrint(matchWord),scope ? qPrint(scope->name()) : "<none>");
977 bool found=FALSE;
978 if (!insideString)
979 {
980 const ClassDef *cd=nullptr;
981 const ConceptDef *cnd=nullptr;
982 //printf("** Match word '%s'\n",qPrint(matchWord));
983
984 SymbolResolver resolver(fileScope);
985 cd=resolver.resolveClass(scope,matchWord);
986 const MemberDef *typeDef = resolver.getTypedef();
987 if (typeDef) // First look at typedef then class, see bug 584184.
988 {
989 if (external ? typeDef->isLinkable() : typeDef->isLinkableInProject())
990 {
991 if (typeDef->getOuterScope()!=self)
992 {
993 //printf("Found typedef %s word='%s'\n",qPrint(typeDef->name()),qPrint(word));
994 out.writeLink(typeDef->getReference(),
995 typeDef->getOutputFileBase(),
996 typeDef->anchor(),
997 word);
998 found=TRUE;
999 }
1000 }
1001 }
1002 auto writeCompoundName = [&](const auto *cd_) {
1003 if (external ? cd_->isLinkable() : cd_->isLinkableInProject())
1004 {
1005 if (self==nullptr || cd_->qualifiedName()!=self->qualifiedName())
1006 {
1007 //printf("Found compound %s word='%s'\n",qPrint(cd->name()),qPrint(word));
1008 out.writeLink(cd_->getReference(),cd_->getOutputFileBase(),cd_->anchor(),word);
1009 found=TRUE;
1010 }
1011 }
1012 };
1013 if ((cd=getClass(matchWord)))
1014 {
1015 writeCompoundName(cd);
1016 }
1017 else if ((cd=getClass(matchWord+"-p"))) // search for Obj-C protocols as well
1018 {
1019 writeCompoundName(cd);
1020 }
1021 else if ((cnd=getConcept(matchWord))) // search for concepts
1022 {
1023 writeCompoundName(cnd);
1024 }
1025 else if (const Definition *d=nullptr; cd==nullptr && !found && (d=resolver.resolveSymbol(scope,matchWord)))
1026 {
1027 writeCompoundName(d);
1028 }
1029 else
1030 {
1031 //printf(" -> nothing\n");
1032 }
1033
1034 int m = matchWord.findRev("::");
1035 QCString scopeName;
1036 if (scope &&
1039 )
1040 )
1041 {
1042 scopeName=scope->name();
1043 }
1044 else if (m!=-1)
1045 {
1046 scopeName = matchWord.left(m);
1047 matchWord = matchWord.mid(m+2);
1048 }
1049
1050 //printf("ScopeName=%s\n",qPrint(scopeName));
1051 //if (!found) printf("Trying to link '%s' in '%s'\n",qPrint(word),qPrint(scopeName));
1052 if (!found)
1053 {
1054 GetDefInput input(scopeName,matchWord,QCString());
1055 GetDefResult result = getDefs(input);
1056 if (result.found && result.md &&
1057 (external ? result.md->isLinkable() : result.md->isLinkableInProject())
1058 )
1059 {
1060 //printf("Found ref scope=%s\n",d ? qPrint(d->name()) : "<global>");
1061 //ol.writeObjectLink(d->getReference(),d->getOutputFileBase(),
1062 // md->anchor(),word);
1063 if (result.md!=self && (self==nullptr || result.md->name()!=self->name()))
1064 // name check is needed for overloaded members, where getDefs just returns one
1065 {
1066 /* in case of Fortran scope and the variable is a non Fortran variable: don't link,
1067 * see also getLink in fortrancode.l
1068 */
1069 if (!(scope &&
1070 (scope->getLanguage() == SrcLangExt::Fortran) &&
1071 result.md->isVariable() &&
1072 (result.md->getLanguage() != SrcLangExt::Fortran)
1073 )
1074 )
1075 {
1076 //printf("found symbol %s word='%s'\n",qPrint(result.md->name()),qPrint(word));
1077 out.writeLink(result.md->getReference(),result.md->getOutputFileBase(),
1078 result.md->anchor(),word);
1079 found=TRUE;
1080 }
1081 }
1082 }
1083 }
1084 }
1085
1086 if (!found) // add word to the result
1087 {
1088 out.writeString(word,keepSpaces);
1089 }
1090 // set next start point in the string
1091 //printf("index=%d/%d\n",index,txtStr.length());
1092 skipIndex=index=newIndex+matchLen;
1093 }
1094 // add last part of the string to the result.
1095 //ol.docify(txtStr.right(txtStr.length()-skipIndex));
1096 std::string_view lastPart = txtStr.substr(skipIndex);
1097 out.writeString(lastPart,keepSpaces);
1098}
virtual SrcLangExt getLanguage() const =0
Returns the programming language this definition was written in.
virtual QCString anchor() const =0
virtual QCString qualifiedName() const =0
virtual Definition * getOuterScope() const =0
virtual bool isVariable() const =0
std::string_view view() const
Definition qcstring.h:174
ConceptDef * getConcept(const QCString &n)
GetDefResult getDefs(const GetDefInput &input)
Definition util.cpp:2242

References Definition::anchor(), AUTO_TRACE, Definition::definitionType(), end(), FALSE, QCString::findRev(), GetDefResult::found, getClass(), getConcept(), getDefs(), Definition::getLanguage(), Definition::getOuterScope(), Definition::getOutputFileBase(), Definition::getReference(), SymbolResolver::getTypedef(), QCString::isEmpty(), Definition::isLinkable(), Definition::isLinkableInProject(), MemberDef::isVariable(), QCString::left(), GetDefResult::md, QCString::mid(), Definition::name(), Definition::qualifiedName(), SymbolResolver::resolveClass(), SymbolResolver::resolveSymbol(), substitute(), TRUE, Definition::TypeClass, Definition::TypeNamespace, QCString::view(), TextGeneratorIntf::writeBreak(), TextGeneratorIntf::writeLink(), and TextGeneratorIntf::writeString().

Referenced by MemberDefImpl::_writeTemplatePrefix(), generateSqlite3ForMember(), generateXMLForClass(), generateXMLForConcept(), generateXMLForMember(), insertMemberFunctionParams(), MemberDefImpl::writeDeclaration(), writeDefArgumentList(), MemberDefImpl::writeDocumentation(), writeExceptionListImpl(), MemberDefImpl::writeMemberDocSimple(), writeTemplateArgumentList(), ClassDefImpl::writeTemplateSpec(), and writeTypeConstraints().

◆ linkToText()

QCString linkToText ( SrcLangExt lang,
const QCString & link,
bool isFileName )

Definition at line 2642 of file util.cpp.

2643{
2644 //bool optimizeOutputJava = Config_getBool(OPTIMIZE_OUTPUT_JAVA);
2645 QCString result=link;
2646 if (!result.isEmpty())
2647 {
2648 // replace # by ::
2649 result=substitute(result,"#","::");
2650 // replace . by ::
2651 if (!isFileName && result.find('<')==-1) result=substitute(result,".","::",3);
2652 // strip leading :: prefix if present
2653 if (result.at(0)==':' && result.at(1)==':')
2654 {
2655 result=result.right(result.length()-2);
2656 }
2658 if (sep!="::")
2659 {
2660 result=substitute(result,"::",sep);
2661 }
2662 }
2663 //printf("linkToText(%s,lang=%d)=%s\n",qPrint(link),lang,qPrint(result));
2664 return result;
2665}
QCString getLanguageSpecificSeparator(SrcLangExt lang, bool classScope)
Returns the scope separator to use given the programming language lang.
Definition util.cpp:5849

References QCString::at(), QCString::find(), getLanguageSpecificSeparator(), QCString::isEmpty(), QCString::length(), QCString::right(), and substitute().

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

◆ mainPageHasTitle()

bool mainPageHasTitle ( )

Definition at line 6234 of file util.cpp.

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

References Doxygen::mainPage.

Referenced by generateJSNavTree(), generateSqlite3ForPage(), generateXMLForPage(), mainPageHasOwnTitle(), and writeIndex().

◆ mangleCSharpGenericName()

QCString mangleCSharpGenericName ( const QCString & name)

Definition at line 6863 of file util.cpp.

6864{
6865 int idx = name.find('<');
6866 if (idx!=-1)
6867 {
6868 return name.left(idx)+"-"+QCString().setNum(name.contains(",")+1)+"-g";
6869 }
6870 return name;
6871}
int contains(char c, bool cs=TRUE) const
Definition qcstring.cpp:148

References QCString::contains(), QCString::find(), QCString::left(), and QCString::setNum().

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

◆ matchArguments2()

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

Definition at line 1965 of file util.cpp.

1968{
1969 ASSERT(srcScope!=nullptr && dstScope!=nullptr);
1970
1971 AUTO_TRACE("srcScope='{}' dstScope='{}' srcArgs='{}' dstArgs='{}' checkCV={} lang={}",
1972 srcScope->name(),dstScope->name(),srcAl?argListToString(*srcAl):"",dstAl?argListToString(*dstAl):"",checkCV,lang);
1973
1974 if (srcAl==nullptr || dstAl==nullptr)
1975 {
1976 bool match = srcAl==dstAl;
1977 if (match)
1978 {
1979 MATCH
1980 return TRUE;
1981 }
1982 else
1983 {
1984 NOMATCH
1985 return FALSE;
1986 }
1987 }
1988
1989 // handle special case with void argument
1990 if ( srcAl->empty() && dstAl->size()==1 && dstAl->front().type=="void" )
1991 { // special case for finding match between func() and func(void)
1992 Argument a;
1993 a.type = "void";
1994 const_cast<ArgumentList*>(srcAl)->push_back(a);
1995 MATCH
1996 return TRUE;
1997 }
1998 if ( dstAl->empty() && srcAl->size()==1 && srcAl->front().type=="void" )
1999 { // special case for finding match between func(void) and func()
2000 Argument a;
2001 a.type = "void";
2002 const_cast<ArgumentList*>(dstAl)->push_back(a);
2003 MATCH
2004 return TRUE;
2005 }
2006
2007 if (srcAl->size() != dstAl->size())
2008 {
2009 NOMATCH
2010 return FALSE; // different number of arguments -> no match
2011 }
2012
2013 if (checkCV)
2014 {
2015 if (srcAl->constSpecifier() != dstAl->constSpecifier())
2016 {
2017 NOMATCH
2018 return FALSE; // one member is const, the other not -> no match
2019 }
2020 if (srcAl->volatileSpecifier() != dstAl->volatileSpecifier())
2021 {
2022 NOMATCH
2023 return FALSE; // one member is volatile, the other not -> no match
2024 }
2025 }
2026
2027 if (srcAl->refQualifier() != dstAl->refQualifier())
2028 {
2029 NOMATCH
2030 return FALSE; // one member is has a different ref-qualifier than the other
2031 }
2032
2033 if (srcReturnType=="auto" && dstReturnType=="auto" && srcAl->trailingReturnType()!=dstAl->trailingReturnType())
2034 {
2035 NOMATCH
2036 return FALSE; // one member is has a different return type than the other
2037 }
2038
2039 // so far the argument list could match, so we need to compare the types of
2040 // all arguments.
2041 auto srcIt = srcAl->begin();
2042 auto dstIt = dstAl->begin();
2043 for (;srcIt!=srcAl->end() && dstIt!=dstAl->end();++srcIt,++dstIt)
2044 {
2045 Argument &srcA = const_cast<Argument&>(*srcIt);
2046 Argument &dstA = const_cast<Argument&>(*dstIt);
2047 if (!matchArgument2(srcScope,srcFileScope,srcA,
2048 dstScope,dstFileScope,dstA,
2049 lang)
2050 )
2051 {
2052 NOMATCH
2053 return FALSE;
2054 }
2055 }
2056 MATCH
2057 return TRUE; // all arguments match
2058}
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:1864
QCString argListToString(const ArgumentList &al, bool useCanonicalType, bool showDefVals)
Definition util.cpp:1198
#define NOMATCH
Definition util.cpp:1865
static bool matchArgument2(const Definition *srcScope, const FileDef *srcFileScope, Argument &srcA, const Definition *dstScope, const FileDef *dstFileScope, Argument &dstA, SrcLangExt lang)
Definition util.cpp:1899

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

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

◆ matchTemplateArguments()

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

Definition at line 2209 of file util.cpp.

2210{
2211 AUTO_TRACE("srcAl={} dstAl={}",argListToString(srcAl),argListToString(dstAl));
2212 if (srcAl.size()!=dstAl.size()) // different number of template parameters -> overload
2213 {
2214 AUTO_TRACE_EXIT("different number of parameters");
2215 return false;
2216 }
2217 auto isUnconstraintTemplate = [](const QCString &type)
2218 {
2219 return type=="typename" || type=="class" || type.startsWith("typename ") || type.startsWith("class ");
2220 };
2221 auto srcIt = srcAl.begin();
2222 auto dstIt = dstAl.begin();
2223 while (srcIt!=srcAl.end() && dstIt!=dstAl.end())
2224 {
2225 const Argument &srcA = *srcIt;
2226 const Argument &dstA = *dstIt;
2227 if ((!isUnconstraintTemplate(srcA.type) || !isUnconstraintTemplate(dstA.type)) && srcA.type!=dstA.type) // different constraints -> overload
2228 {
2229 AUTO_TRACE_EXIT("different constraints");
2230 return false;
2231 }
2232 ++srcIt;
2233 ++dstIt;
2234 }
2235 AUTO_TRACE_EXIT("same");
2236 // no overload with respect to the template parameters
2237 return true;
2238}

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

Referenced by buildFunctionList().

◆ mergeArguments()

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

Definition at line 2065 of file util.cpp.

2066{
2067 AUTO_TRACE("srcAl='{}',dstAl='{}',forceNameOverwrite={}",
2068 qPrint(argListToString(srcAl)),qPrint(argListToString(dstAl)),forceNameOverwrite);
2069
2070 if (srcAl.size()!=dstAl.size())
2071 {
2072 return; // invalid argument lists -> do not merge
2073 }
2074
2075 auto srcIt=srcAl.begin();
2076 auto dstIt=dstAl.begin();
2077 while (srcIt!=srcAl.end() && dstIt!=dstAl.end())
2078 {
2079 Argument &srcA = *srcIt;
2080 Argument &dstA = *dstIt;
2081
2082 AUTO_TRACE_ADD("before merge: src=[type='{}',name='{}',def='{}'] dst=[type='{}',name='{}',def='{}']",
2083 srcA.type,srcA.name,srcA.defval,
2084 dstA.type,dstA.name,dstA.defval);
2085 if (srcA.defval.isEmpty() && !dstA.defval.isEmpty())
2086 {
2087 //printf("Defval changing '%s'->'%s'\n",qPrint(srcA.defval),qPrint(dstA.defval));
2088 srcA.defval=dstA.defval;
2089 }
2090 else if (!srcA.defval.isEmpty() && dstA.defval.isEmpty())
2091 {
2092 //printf("Defval changing '%s'->'%s'\n",qPrint(dstA.defval),qPrint(srcA.defval));
2093 dstA.defval=srcA.defval;
2094 }
2095
2096 // fix wrongly detected const or volatile specifiers before merging.
2097 // example: "const A *const" is detected as type="const A *" name="const"
2098 if (srcA.name=="const" || srcA.name=="volatile")
2099 {
2100 srcA.type+=" "+srcA.name;
2101 srcA.name.clear();
2102 }
2103 if (dstA.name=="const" || dstA.name=="volatile")
2104 {
2105 dstA.type+=" "+dstA.name;
2106 dstA.name.clear();
2107 }
2108
2109 if (srcA.type==dstA.type)
2110 {
2111 //printf("1. merging %s:%s <-> %s:%s\n",qPrint(srcA.type),qPrint(srcA.name),qPrint(dstA.type),qPrint(dstA.name));
2112 if (srcA.name.isEmpty() && !dstA.name.isEmpty())
2113 {
2114 //printf("type: '%s':='%s'\n",qPrint(srcA.type),qPrint(dstA.type));
2115 //printf("name: '%s':='%s'\n",qPrint(srcA.name),qPrint(dstA.name));
2116 srcA.type = dstA.type;
2117 srcA.name = dstA.name;
2118 }
2119 else if (!srcA.name.isEmpty() && dstA.name.isEmpty())
2120 {
2121 //printf("type: '%s':='%s'\n",qPrint(dstA.type),qPrint(srcA.type));
2122 //printf("name: '%s':='%s'\n",qPrint(dstA.name),qPrint(srcA.name));
2123 dstA.type = srcA.type;
2124 dstA.name = srcA.name;
2125 }
2126 else if (!srcA.name.isEmpty() && !dstA.name.isEmpty())
2127 {
2128 //printf("srcA.name=%s dstA.name=%s\n",qPrint(srcA.name),qPrint(dstA.name));
2129 if (forceNameOverwrite)
2130 {
2131 srcA.name = dstA.name;
2132 }
2133 else
2134 {
2135 if (srcA.docs.isEmpty() && !dstA.docs.isEmpty())
2136 {
2137 srcA.name = dstA.name;
2138 }
2139 else if (!srcA.docs.isEmpty() && dstA.docs.isEmpty())
2140 {
2141 dstA.name = srcA.name;
2142 }
2143 }
2144 }
2145 }
2146 else
2147 {
2148 //printf("2. merging '%s':'%s' <-> '%s':'%s'\n",qPrint(srcA.type),qPrint(srcA.name),qPrint(dstA.type),qPrint(dstA.name));
2149 srcA.type=srcA.type.stripWhiteSpace();
2150 dstA.type=dstA.type.stripWhiteSpace();
2151 if (srcA.type+" "+srcA.name==dstA.type) // "unsigned long:int" <-> "unsigned long int:bla"
2152 {
2153 srcA.type+=" "+srcA.name;
2154 srcA.name=dstA.name;
2155 }
2156 else if (dstA.type+" "+dstA.name==srcA.type) // "unsigned long int bla" <-> "unsigned long int"
2157 {
2158 dstA.type+=" "+dstA.name;
2159 dstA.name=srcA.name;
2160 }
2161 else if (srcA.name.isEmpty() && !dstA.name.isEmpty())
2162 {
2163 srcA.name = dstA.name;
2164 }
2165 else if (dstA.name.isEmpty() && !srcA.name.isEmpty())
2166 {
2167 dstA.name = srcA.name;
2168 }
2169 }
2170 int i1=srcA.type.find("::"),
2171 i2=dstA.type.find("::"),
2172 j1=static_cast<int>(srcA.type.length())-i1-2,
2173 j2=static_cast<int>(dstA.type.length())-i2-2;
2174 if (i1!=-1 && i2==-1 && srcA.type.right(j1)==dstA.type)
2175 {
2176 //printf("type: '%s':='%s'\n",qPrint(dstA.type),qPrint(srcA.type));
2177 //printf("name: '%s':='%s'\n",qPrint(dstA.name),qPrint(srcA.name));
2178 dstA.type = srcA.type.left(i1+2)+dstA.type;
2179 dstA.name = srcA.name;
2180 }
2181 else if (i1==-1 && i2!=-1 && dstA.type.right(j2)==srcA.type)
2182 {
2183 //printf("type: '%s':='%s'\n",qPrint(srcA.type),qPrint(dstA.type));
2184 //printf("name: '%s':='%s'\n",qPrint(dstA.name),qPrint(srcA.name));
2185 srcA.type = dstA.type.left(i2+2)+srcA.type;
2186 srcA.name = dstA.name;
2187 }
2188 if (srcA.docs.isEmpty() && !dstA.docs.isEmpty())
2189 {
2190 srcA.docs = dstA.docs;
2191 }
2192 else if (dstA.docs.isEmpty() && !srcA.docs.isEmpty())
2193 {
2194 dstA.docs = srcA.docs;
2195 }
2196 //printf("Merge argument '%s|%s' '%s|%s'\n",
2197 // qPrint(srcA.type), qPrint(srcA.name),
2198 // qPrint(dstA.type), qPrint(dstA.name));
2199 ++srcIt;
2200 ++dstIt;
2201 AUTO_TRACE_ADD("after merge: src=[type='{}',name='{}',def='{}'] dst=[type='{}',name='{}',def='{}']",
2202 srcA.type,srcA.name,srcA.defval,
2203 dstA.type,dstA.name,dstA.defval);
2204 }
2205}
#define AUTO_TRACE_ADD(...)
Definition docnode.cpp:47
const char * qPrint(const char *s)
Definition qcstring.h:687
QCString docs
Definition arguments.h:47

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

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

◆ mergeMemberOverrideOptions()

void mergeMemberOverrideOptions ( MemberDefMutable * md1,
MemberDefMutable * md2 )

Definition at line 6811 of file util.cpp.

6812{
6813 if (Config_getBool(CALL_GRAPH) !=md1->hasCallGraph()) md2->overrideCallGraph(md1->hasCallGraph());
6814 if (Config_getBool(CALLER_GRAPH)!=md1->hasCallerGraph()) md2->overrideCallerGraph(md1->hasCallerGraph());
6815 if (Config_getBool(CALL_GRAPH) !=md2->hasCallGraph()) md1->overrideCallGraph( md2->hasCallGraph());
6816 if (Config_getBool(CALLER_GRAPH)!=md2->hasCallerGraph()) md1->overrideCallerGraph(md2->hasCallerGraph());
6817
6818 if (Config_getBool(SHOW_ENUM_VALUES) !=md1->hasEnumValues()) md2->overrideEnumValues(md1->hasEnumValues());
6819 if (Config_getBool(SHOW_ENUM_VALUES) !=md2->hasEnumValues()) md1->overrideEnumValues( md2->hasEnumValues());
6820
6821 if (Config_getBool(REFERENCED_BY_RELATION)!=md1->hasReferencedByRelation()) md2->overrideReferencedByRelation(md1->hasReferencedByRelation());
6822 if (Config_getBool(REFERENCES_RELATION) !=md1->hasReferencesRelation()) md2->overrideReferencesRelation(md1->hasReferencesRelation());
6823 if (Config_getBool(REFERENCED_BY_RELATION)!=md2->hasReferencedByRelation()) md1->overrideReferencedByRelation(md2->hasReferencedByRelation());
6824 if (Config_getBool(REFERENCES_RELATION) !=md2->hasReferencesRelation()) md1->overrideReferencesRelation(md2->hasReferencesRelation());
6825
6826 if (Config_getBool(INLINE_SOURCES)!=md1->hasInlineSource()) md2->overrideInlineSource(md1->hasInlineSource());
6827 if (Config_getBool(INLINE_SOURCES)!=md2->hasInlineSource()) md1->overrideInlineSource(md2->hasInlineSource());
6828}
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(), MemberDefMutable::overrideCallerGraph(), MemberDefMutable::overrideCallGraph(), MemberDefMutable::overrideEnumValues(), MemberDefMutable::overrideInlineSource(), MemberDefMutable::overrideReferencedByRelation(), and MemberDefMutable::overrideReferencesRelation().

Referenced by combineDeclarationAndDefinition(), and findFriends().

◆ mergeScopes()

QCString mergeScopes ( const QCString & leftScope,
const QCString & 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 4536 of file util.cpp.

4537{
4538 AUTO_TRACE("leftScope='{}' rightScope='{}'",leftScope,rightScope);
4539 // case leftScope=="A" rightScope=="A::B" => result = "A::B"
4540 if (leftScopeMatch(leftScope,rightScope))
4541 {
4542 AUTO_TRACE_EXIT("case1={}",rightScope);
4543 return rightScope;
4544 }
4545 QCString result;
4546 int i=0,p=static_cast<int>(leftScope.length());
4547
4548 // case leftScope=="A::B" rightScope=="B::C" => result = "A::B::C"
4549 // case leftScope=="A::B" rightScope=="B" => result = "A::B"
4550 bool found=FALSE;
4551 while ((i=leftScope.findRev("::",p))>0)
4552 {
4553 if (leftScopeMatch(rightScope,leftScope.right(leftScope.length()-i-2)))
4554 {
4555 result = leftScope.left(i+2)+rightScope;
4556 found=TRUE;
4557 }
4558 p=i-1;
4559 }
4560 if (found)
4561 {
4562 AUTO_TRACE_EXIT("case2={}",result);
4563 return result;
4564 }
4565
4566 // case leftScope=="A" rightScope=="B" => result = "A::B"
4567 result=leftScope;
4568 if (!result.isEmpty() && !rightScope.isEmpty()) result+="::";
4569 result+=rightScope;
4570 AUTO_TRACE_EXIT("case3={}",result);
4571 return result;
4572}
bool leftScopeMatch(const QCString &scope, const QCString &name)
Definition util.cpp:882

References AUTO_TRACE, AUTO_TRACE_EXIT, FALSE, QCString::findRev(), QCString::isEmpty(), QCString::left(), leftScopeMatch(), QCString::length(), QCString::right(), and TRUE.

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

◆ nextUtf8CharPosition()

int nextUtf8CharPosition ( const QCString & utf8Str,
uint32_t len,
uint32_t startPos )

◆ normalizeNonTemplateArgumentsInString()

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

Definition at line 4242 of file util.cpp.

4246{
4247 // skip until <
4248 int p=name.find('<');
4249 if (p==-1) return name;
4250 p++;
4251 QCString result = name.left(p);
4252
4253 std::string s = name.mid(p).str();
4254 static const reg::Ex re(R"([\a:][\w:]*)");
4255 reg::Iterator it(s,re);
4257 size_t pi=0;
4258 // for each identifier in the template part (e.g. B<T> -> T)
4259 for (; it!=end ; ++it)
4260 {
4261 const auto &match = *it;
4262 size_t i = match.position();
4263 size_t l = match.length();
4264 result += s.substr(pi,i-pi);
4265 QCString n(match.str());
4266 bool found=FALSE;
4267 for (const Argument &formArg : formalArgs)
4268 {
4269 if (formArg.name == n)
4270 {
4271 found=TRUE;
4272 break;
4273 }
4274 }
4275 if (!found)
4276 {
4277 // try to resolve the type
4278 SymbolResolver resolver;
4279 const ClassDef *cd = resolver.resolveClass(context,n);
4280 if (cd)
4281 {
4282 result+=cd->name();
4283 }
4284 else
4285 {
4286 result+=n;
4287 }
4288 }
4289 else
4290 {
4291 result+=n;
4292 }
4293 pi=i+l;
4294 }
4295 result+=s.substr(pi);
4296 //printf("normalizeNonTemplateArgumentInString(%s)=%s\n",qPrint(name),qPrint(result));
4297 return removeRedundantWhiteSpace(result);
4298}
const ClassDef * resolveClass(const Definition *scope, const QCString &name, bool maybeUnlinkable=false, bool mayBeHidden=false)
Find the class definition matching name within the scope set.

References end(), FALSE, QCString::find(), QCString::left(), QCString::mid(), Definition::name(), removeRedundantWhiteSpace(), SymbolResolver::resolveClass(), QCString::str(), and TRUE.

Referenced by findUsedClassesForClass().

◆ openOutputFile()

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

Definition at line 6246 of file util.cpp.

6247{
6248 assert(!f.is_open());
6249 bool fileOpened=FALSE;
6250 bool writeToStdout=outFile=="-";
6251 if (writeToStdout) // write to stdout
6252 {
6253 f.basic_ios<char>::rdbuf(std::cout.rdbuf());
6254 fileOpened = true;
6255 }
6256 else // write to file
6257 {
6258 FileInfo fi(outFile.str());
6259 if (fi.exists()) // create a backup
6260 {
6261 Dir dir;
6262 FileInfo backup(fi.filePath()+".bak");
6263 if (backup.exists()) // remove existing backup
6264 dir.remove(backup.filePath());
6265 dir.rename(fi.filePath(),fi.filePath()+".bak");
6266 }
6267 f = Portable::openOutputStream(outFile);
6268 fileOpened = f.is_open();
6269 }
6270 return fileOpened;
6271}
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 QCString &name, bool append=false)
Definition portable.cpp:649

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

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

◆ parseCommentAsHtml()

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

Definition at line 5361 of file util.cpp.

5362{
5363 std::lock_guard lock(g_docCacheMutex);
5364 auto it = g_docCache.find(doc.str());
5365 if (it != g_docCache.end())
5366 {
5367 //printf("Cache: [%s]->[%s]\n",qPrint(doc),qPrint(it->second));
5368 return it->second;
5369 }
5370 auto parser { createDocParser() };
5371 auto ast { validatingParseTitle(*parser.get(),fileName,lineNr,doc) };
5372 auto astImpl = dynamic_cast<const DocNodeAST*>(ast.get());
5373 QCString result;
5374 if (astImpl)
5375 {
5376 TextStream t;
5377 OutputCodeList codeList;
5378 codeList.add<HtmlCodeGenerator>(&t);
5379 HtmlDocVisitor visitor(t,codeList,scope,fileName);
5380 std::visit(visitor,astImpl->root);
5381 result = t.str();
5382 }
5383 else // fallback, should not happen
5384 {
5385 result = filterTitle(doc);
5386 }
5387 //printf("Conversion: [%s]->[%s]\n",qPrint(doc),qPrint(result));
5388 g_docCache.insert(std::make_pair(doc.str(),result));
5389 return result;
5390}
Class representing the abstract syntax tree of a documentation block.
Definition docnode.h:1466
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:165
void add(OutputCodeIntfPtr &&p)
Definition outputlist.h:195
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:216
IDocParserPtr createDocParser()
factory function to create a parser
Definition docparser.cpp:55
IDocNodeASTPtr validatingParseTitle(IDocParser &parserIntf, const QCString &fileName, int lineNr, const QCString &input)
static std::unordered_map< std::string, QCString > g_docCache
Definition util.cpp:5359
QCString filterTitle(const QCString &title)
Definition util.cpp:5566
static std::mutex g_docCacheMutex
Definition util.cpp:5358

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

Referenced by PageDefImpl::addSectionsToIndex(), SearchTerm::makeTitle(), DefinitionImpl::navigationPathAsString(), writeGroupTreeNode(), writeIndex(), writeJavasScriptSearchDataPage(), and writePages().

◆ parseCommentAsText()

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

Definition at line 5305 of file util.cpp.

5307{
5308 if (doc.isEmpty()) return "";
5309 //printf("parseCommentAsText(%s)\n",qPrint(doc));
5310 TextStream t;
5311 auto parser { createDocParser() };
5312 auto ast { validatingParseDoc(*parser.get(),
5313 fileName,
5314 lineNr,
5315 scope,
5316 md,
5317 doc,
5318 DocOptions()
5319 .setAutolinkSupport(false))
5320 };
5321 auto astImpl = dynamic_cast<const DocNodeAST*>(ast.get());
5322 if (astImpl)
5323 {
5324 TextDocVisitor visitor(t);
5325 std::visit(visitor,astImpl->root);
5326 }
5328 int i=0;
5329 int charCnt=0;
5330 int l=static_cast<int>(result.length());
5331 while ((i=nextUTF8CharPosition(result,l,i))<l)
5332 {
5333 charCnt++;
5334 if (charCnt>=80) break;
5335 }
5336 if (charCnt>=80) // try to truncate the string
5337 {
5338 while ((i=nextUTF8CharPosition(result,l,i))<l && charCnt<100)
5339 {
5340 charCnt++;
5341 if (result.at(i)==',' ||
5342 result.at(i)=='.' ||
5343 result.at(i)=='!' ||
5344 result.at(i)=='?' ||
5345 result.at(i)=='}') // good for UTF-16 characters and } otherwise also a good point to stop the string
5346 {
5347 i++; // we want to be "behind" last inspected character
5348 break;
5349 }
5350 }
5351 }
5352 if ( i < l) result=result.left(i)+"...";
5353 return result.data();
5354}
Concrete visitor implementation for TEXT output.
IDocNodeASTPtr validatingParseDoc(IDocParser &parserIntf, const QCString &fileName, int startLine, const Definition *ctx, const MemberDef *md, const QCString &input, const DocOptions &options)
static int nextUTF8CharPosition(const QCString &utf8Str, uint32_t len, uint32_t startPos)
Definition util.cpp:5261

References QCString::at(), convertCharEntitiesToUTF8(), createDocParser(), QCString::data(), QCString::isEmpty(), QCString::left(), QCString::length(), nextUTF8CharPosition(), TextStream::str(), QCString::stripWhiteSpace(), and validatingParseDoc().

Referenced by PageDefImpl::addSectionsToIndex(), DefinitionImpl::computeTooltip(), writeGroupTreeNode(), writeIndex(), and writePages().

◆ patternMatch()

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

Definition at line 5640 of file util.cpp.

5641{
5642 std::string elem;
5643 auto getter = [](std::string s) -> QCString { return s; };
5644 return genericPatternMatch(fi,patList,elem,getter);
5645}

References genericPatternMatch().

Referenced by checkAndOpenFile(), and readDir().

◆ processMarkup()

QCString processMarkup ( const QCString & s)

◆ projectLogoFile()

QCString projectLogoFile ( )

Definition at line 3082 of file util.cpp.

3083{
3084 QCString projectLogo = Config_getString(PROJECT_LOGO);
3085 if (!projectLogo.isEmpty())
3086 {
3087 // check for optional width= and height= specifier
3088 int wi = projectLogo.find(" width=");
3089 if (wi!=-1) // and strip them
3090 {
3091 projectLogo = projectLogo.left(wi);
3092 }
3093 int hi = projectLogo.find(" height=");
3094 if (hi!=-1)
3095 {
3096 projectLogo = projectLogo.left(hi);
3097 }
3098 }
3099 //printf("projectlogo='%s'\n",qPrint(projectLogo));
3100 return projectLogo;
3101}

References Config_getString, QCString::find(), QCString::isEmpty(), and QCString::left().

Referenced by copyLogo(), and substituteKeywords().

◆ protectionLevelVisible()

bool protectionLevelVisible ( Protection prot)

Definition at line 5889 of file util.cpp.

5890{
5891 bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
5892 bool extractPackage = Config_getBool(EXTRACT_PACKAGE);
5893
5894 return (prot!=Protection::Private && prot!=Protection::Package) ||
5895 (prot==Protection::Private && extractPrivate) ||
5896 (prot==Protection::Package && extractPackage);
5897}

References Config_getBool.

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

◆ readInputFile()

bool readInputFile ( const QCString & fileName,
std::string & contents,
bool filter = TRUE,
bool isSourceCode = FALSE )

read a file name fileName and optionally filter and transcode it

Definition at line 5486 of file util.cpp.

5487{
5488 // try to open file
5489 FileInfo fi(fileName.str());
5490 if (!fi.exists()) return FALSE;
5491 QCString filterName = getFileFilter(fileName,isSourceCode);
5492 if (filterName.isEmpty() || !filter)
5493 {
5494 std::ifstream f = Portable::openInputStream(fileName,true);
5495 if (!f.is_open())
5496 {
5497 err("could not open file {}\n",fileName);
5498 return FALSE;
5499 }
5500 // read the file
5501 auto fileSize = fi.size();
5502 contents.resize(fileSize);
5503 f.read(contents.data(),fileSize);
5504 if (f.fail())
5505 {
5506 err("problems while reading file {}\n",fileName);
5507 return FALSE;
5508 }
5509 }
5510 else
5511 {
5512 QCString cmd=filterName+" \""+fileName+"\"";
5513 Debug::print(Debug::ExtCmd,0,"Executing popen(`{}`)\n",cmd);
5514 FILE *f=Portable::popen(cmd,"r");
5515 if (!f)
5516 {
5517 err("could not execute filter {}\n",filterName);
5518 return FALSE;
5519 }
5520 const int bufSize=4096;
5521 char buf[bufSize];
5522 int numRead = 0;
5523 while ((numRead=static_cast<int>(fread(buf,1,bufSize,f)))>0)
5524 {
5525 //printf(">>>>>>>>Reading %d bytes\n",numRead);
5526 contents.append(buf,numRead);
5527 }
5529 Debug::print(Debug::FilterOutput, 0, "Filter output\n");
5530 Debug::print(Debug::FilterOutput,0,"-------------\n{}\n-------------\n",contents);
5531 }
5532
5533 if (contents.size()>=2 &&
5534 static_cast<uint8_t>(contents[0])==0xFF &&
5535 static_cast<uint8_t>(contents[1])==0xFE // Little endian BOM
5536 ) // UCS-2LE encoded file
5537 {
5538 transcodeCharacterBuffer(fileName,contents,"UCS-2LE","UTF-8");
5539 }
5540 else if (contents.size()>=2 &&
5541 static_cast<uint8_t>(contents[0])==0xFE &&
5542 static_cast<uint8_t>(contents[1])==0xFF // big endian BOM
5543 ) // UCS-2BE encoded file
5544 {
5545 transcodeCharacterBuffer(fileName,contents,"UCS-2BE","UTF-8");
5546 }
5547 else if (contents.size()>=3 &&
5548 static_cast<uint8_t>(contents[0])==0xEF &&
5549 static_cast<uint8_t>(contents[1])==0xBB &&
5550 static_cast<uint8_t>(contents[2])==0xBF
5551 ) // UTF-8 encoded file
5552 {
5553 contents.erase(0,3); // remove UTF-8 BOM: no translation needed
5554 }
5555 else // transcode according to the INPUT_ENCODING setting
5556 {
5557 // do character transcoding if needed.
5558 transcodeCharacterBuffer(fileName,contents,getEncoding(fi),"UTF-8");
5559 }
5560
5561 filterCRLF(contents);
5562 return true;
5563}
@ 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:76
std::ifstream openInputStream(const QCString &name, bool binary=false, bool openAtEnd=false)
Definition portable.cpp:660
FILE * popen(const QCString &name, const QCString &type)
Definition portable.cpp:480
int pclose(FILE *stream)
Definition portable.cpp:489
static void filterCRLF(std::string &contents)
Definition util.cpp:1299
static void transcodeCharacterBuffer(const QCString &fileName, std::string &contents, const QCString &inputEncoding, const QCString &outputEncoding)
Definition util.cpp:5450
QCString getEncoding(const FileInfo &fi)
Definition util.cpp:5647
QCString getFileFilter(const QCString &name, bool isSourceCode)
Definition util.cpp:1366

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

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

◆ recodeString()

QCString recodeString ( const QCString & str,
const char * fromEncoding,
const char * toEncoding )

References FALSE, parent(), and TRUE.

◆ recognizeFixedForm()

bool recognizeFixedForm ( const QCString & contents,
FortranFormat format )

Definition at line 6293 of file util.cpp.

6294{
6295 int column=0;
6296 bool skipLine=FALSE;
6297
6298 if (format == FortranFormat::Fixed) return TRUE;
6299 if (format == FortranFormat::Free) return FALSE;
6300
6301 int tabSize=Config_getInt(TAB_SIZE);
6302 size_t sizCont = contents.length();
6303 for (size_t i=0;i<sizCont;i++)
6304 {
6305 column++;
6306
6307 switch(contents.at(i))
6308 {
6309 case '\n':
6310 column=0;
6311 skipLine=FALSE;
6312 break;
6313 case '\t':
6314 column += tabSize-1;
6315 break;
6316 case ' ':
6317 break;
6318 case '\000':
6319 return FALSE;
6320 case '#':
6321 skipLine=TRUE;
6322 break;
6323 case 'C':
6324 case 'c':
6325 if (column==1)
6326 {
6327 return !keyWordsFortranC(contents.data()+i);
6328 }
6329 // fallthrough
6330 case '*':
6331 if (column==1) return TRUE;
6332 if (skipLine) break;
6333 return FALSE;
6334 case '!':
6335 if (column!=6) skipLine=TRUE;
6336 break;
6337 default:
6338 if (skipLine) break;
6339 if (column>=7) return TRUE;
6340 return FALSE;
6341 }
6342 }
6343 return FALSE;
6344}
static bool keyWordsFortranC(const char *contents)
Definition util.cpp:6273

References QCString::at(), Config_getInt, QCString::data(), FALSE, Fixed, Free, keyWordsFortranC(), QCString::length(), and TRUE.

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

◆ relativePathToRoot()

QCString relativePathToRoot ( const QCString & name)

Definition at line 3521 of file util.cpp.

3522{
3523 QCString result;
3524 if (Config_getBool(CREATE_SUBDIRS))
3525 {
3526 if (name.isEmpty())
3527 {
3528 return REL_PATH_TO_ROOT;
3529 }
3530 else
3531 {
3532 int i = name.findRev('/');
3533 if (i!=-1)
3534 {
3535 result=REL_PATH_TO_ROOT;
3536 }
3537 }
3538 }
3539 return result;
3540}
#define REL_PATH_TO_ROOT
Definition util.cpp:95

References Config_getBool, QCString::findRev(), QCString::isEmpty(), and REL_PATH_TO_ROOT.

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

◆ removeAnonymousScopes()

QCString removeAnonymousScopes ( const QCString & 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 162 of file util.cpp.

163{
164 std::string result;
165 if (str.isEmpty()) return result;
166
167 // helper to check if the found delimiter starts with a colon
168 auto startsWithColon = [](const std::string &del)
169 {
170 for (size_t i=0;i<del.size();i++)
171 {
172 if (del[i]=='@') return false;
173 else if (del[i]==':') return true;
174 }
175 return false;
176 };
177
178 // helper to check if the found delimiter ends with a colon
179 auto endsWithColon = [](const std::string &del)
180 {
181 for (int i=static_cast<int>(del.size())-1;i>=0;i--)
182 {
183 if (del[i]=='@') return false;
184 else if (del[i]==':') return true;
185 }
186 return false;
187 };
188
189 static const reg::Ex re(R"([\s:]*@\d+[\s:]*)");
190 std::string s = str.str();
191 reg::Iterator iter(s,re);
193 size_t p=0;
194 size_t sl=s.length();
195 bool needsSeparator=false;
196 for ( ; iter!=end ; ++iter)
197 {
198 const auto &match = *iter;
199 size_t i = match.position();
200 if (i>p) // add non-matching prefix
201 {
202 if (needsSeparator) result+="::";
203 needsSeparator=false;
204 result+=s.substr(p,i-p);
205 }
206 std::string delim = match.str();
207 needsSeparator = needsSeparator || (startsWithColon(delim) && endsWithColon(delim));
208 p = match.position()+match.length();
209 }
210 if (p<sl) // add trailing remainder
211 {
212 if (needsSeparator) result+="::";
213 result+=s.substr(p);
214 }
215 return result;
216}

References end(), QCString::isEmpty(), and QCString::str().

Referenced by createTagLessInstance(), MemberDefImpl::displayDefinition(), generateClassMemberLink(), makeDisplayName(), makeDisplayName(), simplifyTypeForTable(), MemberDefImpl::writeDeclaration(), and MemberDefImpl::writeDocumentation().

◆ removeEmptyLines()

QCString removeEmptyLines ( const QCString & s)

Definition at line 6536 of file util.cpp.

6537{
6538 std::string out;
6539 out.reserve(s.length());
6540 const char *p=s.data();
6541 if (p)
6542 {
6543 char c = 0;
6544 while ((c=*p++))
6545 {
6546 if (c=='\n')
6547 {
6548 const char *e = p;
6549 while (*e==' ' || *e=='\t') e++;
6550 if (*e=='\n')
6551 {
6552 p=e;
6553 }
6554 else out+=c;
6555 }
6556 else
6557 {
6558 out+=c;
6559 }
6560 }
6561 }
6562 //printf("removeEmptyLines(%s)=%s\n",qPrint(s),qPrint(out));
6563 return out;
6564}

References QCString::data(), QCString::length(), and QCString::reserve().

Referenced by substituteHtmlKeywords(), and substituteLatexKeywords().

◆ removeLongPathMarker()

QCString removeLongPathMarker ( QCString path)

Definition at line 288 of file util.cpp.

289{
290#if defined(_WIN32)
291 if (path.startsWith("//?/")) // strip leading "\\?\" part from path
292 {
293 path=path.mid(4);
294 }
295#endif
296 return path;
297}

References QCString::mid(), and QCString::startsWith().

Referenced by computeCommonDirPrefix(), FileDefImpl::FileDefImpl(), findFileDef(), DirDefImpl::mergeDirectoryInTree(), and stripFromPath().

◆ removeRedundantWhiteSpace()

QCString removeRedundantWhiteSpace ( const QCString & s)

Definition at line 568 of file util.cpp.

569{
570 bool cliSupport = Config_getBool(CPP_CLI_SUPPORT);
571 bool vhdl = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
572
573 if (s.isEmpty() || vhdl) return s;
574
575 // We use a static character array to
576 // improve the performance of this function
577 // and thread_local is needed to make it multi-thread safe
578 static THREAD_LOCAL char *growBuf = nullptr;
579 static THREAD_LOCAL size_t growBufLen = 0;
580 if (s.length()*3>growBufLen) // For input character we produce at most 3 output characters,
581 {
582 growBufLen = s.length()*3;
583 growBuf = static_cast<char *>(realloc(growBuf,growBufLen+1)); // add 1 for 0-terminator
584 }
585 if (growBuf==nullptr) return s; // should not happen, only we run out of memory
586
587 const char *src=s.data();
588 char *dst=growBuf;
589
590 size_t i=0;
591 size_t l=s.length();
592 size_t csp=0;
593 size_t vosp=0;
594 size_t vsp=0;
595 size_t osp=0;
596 char pc=0;
597 // skip leading whitespace
598 while (i<l && isspace(static_cast<uint8_t>(src[i])))
599 {
600 i++;
601 }
602 for (;i<l;i++)
603 {
604 char c=src[i];
605 char nc=i+1<l ? src[i+1] : ' ';
606
607 auto searchForKeyword = [&](const char *kw,size_t &matchLen,size_t totalLen)
608 {
609 if (matchLen<=totalLen && c==kw[matchLen] && // character matches substring kw
610 (matchLen>0 || // inside search string
611 i==0 || // if it is the first character
612 !isId(pc) // the previous may not be a digit
613 )
614 )
615 matchLen++;
616 else // reset counter
617 matchLen=0;
618 };
619 searchForKeyword(constScope, csp, 5); // keyword: const
620 searchForKeyword(volatileScope, vosp, 8); // keyword: volatile
621 searchForKeyword(virtualScope, vsp, 7); // keyword: virtual
622
623 // search for "operator"
624 if (osp<11 && (osp>=8 || c==operatorScope[osp]) && // character matches substring "operator" followed by 3 arbitrary characters
625 (osp>0 || // inside search string
626 i==0 || // if it is the first character
627 !isId(pc) // the previous may not be a digit
628 )
629 )
630 osp++;
631 else // reset counter
632 osp=0;
633
634 switch(c)
635 {
636 case '"': // quoted string
637 {
638 *dst++=c;
639 i++;
640 for (;i<l;i++) // find end of string
641 {
642 c = src[i];
643 *dst++=c;
644 if (c=='\\' && i+1<l)
645 {
646 i++;
647 c = src[i];
648 *dst++=c;
649 }
650 else if (c=='"')
651 {
652 break;
653 }
654 }
655 }
656 break;
657 case '<': // current char is a <
658 *dst++=c;
659 if (i+1<l &&
660 (isId(nc)) && // next char is an id char
661 (osp<8) // string in front is not "operator"
662 )
663 {
664 *dst++=' '; // add extra space
665 }
666 break;
667 case '>': // current char is a >
668 if (i>0 && !isspace(static_cast<uint8_t>(pc)) &&
669 (isId(pc) || pc=='*' || pc=='&' || pc=='.' || pc=='>') && // prev char is an id char or space or *&.
670 (osp<8 || (osp==8 && pc!='-')) // string in front is not "operator>" or "operator->"
671 )
672 {
673 *dst++=' '; // add extra space in front
674 }
675 *dst++=c;
676 if (i+1<l && (nc=='-' || nc=='&')) // '>-' -> '> -'
677 {
678 *dst++=' '; // add extra space after
679 }
680 break;
681 case ',': // current char is a ,
682 *dst++=c;
683 if (i>0 && !isspace(static_cast<uint8_t>(pc)) &&
684 ((i+1<l && (isId(nc) || nc=='[')) || // the [ is for attributes (see bug702170)
685 (i+2<l && nc=='$' && isId(src[i+2])) || // for PHP: ',$name' -> ', $name'
686 (i+3<l && nc=='&' && src[i+2]=='$' && isId(src[i+3])) // for PHP: ',&$name' -> ', &$name'
687 )
688 )
689 {
690 *dst++=' '; // add extra space after
691 }
692 break;
693 case '^': // CLI 'Type^name' -> 'Type^ name'
694 case '%': // CLI 'Type%name' -> 'Type% name'
695 *dst++=c;
696 if (cliSupport && i+1<l && (isId(nc) || nc=='-'))
697 {
698 *dst++=' '; // add extra space after
699 }
700 break;
701 case ')': // current char is a ) -> ')name' -> ') name'
702 *dst++=c;
703 if (i+1<l && (isId(nc) || nc=='-'))
704 {
705 *dst++=' '; // add extra space after
706 }
707 break;
708 case '*':
709 if (i>0 && pc!=' ' && pc!='\t' && pc!=':' &&
710 pc!='*' && pc!='&' && pc!='(' && pc!='/' &&
711 pc!='.' && osp<9
712 )
713 // avoid splitting &&, **, .*, operator*, operator->*
714 {
715 *dst++=' ';
716 }
717 *dst++=c;
718 break;
719 case '&':
720 if (i>0 && isId(pc) && osp<9)
721 {
722 if (nc != '=')
723 // avoid splitting operator&=
724 {
725 *dst++=' ';
726 }
727 }
728 *dst++=c;
729 break;
730 case '$': // '$name' -> ' $name'
731 // 'name$name' -> 'name$name'
732 if (isId(pc))
733 {
734 *dst++=c;
735 break;
736 }
737 // else fallthrough
738 case '@': // '@name' -> ' @name'
739 case '\'': // ''name' -> '' name'
740 if (i>0 && i+1<l && pc!='=' && pc!=':' && !isspace(static_cast<uint8_t>(pc)) &&
741 isId(nc) && osp<8) // ")id" -> ") id"
742 {
743 *dst++=' ';
744 }
745 *dst++=c;
746 break;
747 case ':': // current char is a :
748 if (csp==6) // replace const::A by const ::A
749 {
750 *dst++=' ';
751 csp=0;
752 }
753 else if (vosp==9) // replace volatile::A by volatile ::A
754 {
755 *dst++=' ';
756 vosp=0;
757 }
758 else if (vsp==8) // replace virtual::A by virtual ::A
759 {
760 *dst++=' ';
761 vsp=0;
762 }
763 *dst++=c;
764 break;
765 case ' ': // fallthrough
766 case '\n': // fallthrough
767 case '\t':
768 {
769 if (g_charAroundSpace.charMap[static_cast<uint8_t>(pc)].before &&
770 g_charAroundSpace.charMap[static_cast<uint8_t>(nc)].after &&
771 !(pc==',' && nc=='.') &&
772 (osp<8 || (osp>=8 && isId(pc) && isId(nc)))
773 // e.g. 'operator >>' -> 'operator>>',
774 // 'operator "" _x' -> 'operator""_x',
775 // but not 'operator int' -> 'operatorint'
776 )
777 { // keep space
778 *dst++=' ';
779 }
780 else if ((pc=='*' || pc=='&' || pc=='.') && nc=='>')
781 {
782 *dst++=' ';
783 }
784 }
785 break;
786 default:
787 *dst++=c;
788 auto correctKeywordAllowedInsideScope = [&](char cc,size_t &matchLen,size_t totalLen) {
789 if (c==cc && matchLen==totalLen)
790 {
791 if ((i+2<l && src[i+1] == ':' && src[i+2] == ':') || // keyword::
792 ((i>matchLen && src[i-matchLen] == ':' && src[i-matchLen-1] == ':')) // ::keyword
793 ) matchLen = 0;
794 };
795 };
796 correctKeywordAllowedInsideScope('t',csp, 5); // keyword: const
797 correctKeywordAllowedInsideScope('e',vosp,8); // keyword: volatile
798 correctKeywordAllowedInsideScope('l',vsp, 7); // keyword: virtual
799
800 auto correctKeywordNotPartOfScope = [&](char cc,size_t &matchLen,size_t totalLen)
801 {
802 if (c==cc && matchLen==totalLen && i+1<l && // found matching keyword
803 !(isId(nc) || nc==')' || nc==',' || qisspace(nc))
804 ) // prevent keyword ::A from being converted to keyword::A
805 {
806 *dst++=' ';
807 matchLen=0;
808 }
809 };
810 correctKeywordNotPartOfScope('t',csp, 5); // keyword: const
811 correctKeywordNotPartOfScope('e',vosp,8); // keyword: volatile
812 correctKeywordNotPartOfScope('l',vsp, 7); // keyword: virtual
813 break;
814 }
815 pc=c;
816 }
817 *dst++='\0';
818 //printf("removeRedundantWhitespace(%s)->%s\n",qPrint(s),growBuf);
819 return growBuf;
820}
#define THREAD_LOCAL
Definition doxygen.h:30
Token literal values and constants.
Definition CharStream.h:12
bool qisspace(char c)
Definition qcstring.h:81
static const char constScope[]
Definition util.cpp:521
static const char virtualScope[]
Definition util.cpp:523
static const char volatileScope[]
Definition util.cpp:522
static CharAroundSpace g_charAroundSpace
Definition util.cpp:565
static const char operatorScope[]
Definition util.cpp:524

References Config_getBool, constScope, QCString::data(), g_charAroundSpace, QCString::isEmpty(), isId(), QCString::length(), operatorScope, qisspace(), 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(), resolveRef(), tempArgListToString(), and writeExceptionListImpl().

◆ replaceAnonymousScopes()

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

Definition at line 219 of file util.cpp.

220{
221 if (s.isEmpty()) return s;
222 static const reg::Ex marker(R"(@\d+)");
223 std::string result = reg::replace(s.str(),marker,
224 !replacement.isEmpty() ? replacement.data() : "__anonymous__");
225 //printf("replaceAnonymousScopes('%s')='%s'\n",qPrint(s),qPrint(result));
226 return result;
227}
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:866

References QCString::data(), QCString::isEmpty(), reg::replace(), and QCString::str().

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

◆ replaceColorMarkers()

QCString replaceColorMarkers ( const QCString & 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 5758 of file util.cpp.

5759{
5760 if (str.isEmpty()) return QCString();
5761 std::string result;
5762 std::string s=str.str();
5763 static const reg::Ex re(R"(##[0-9A-Fa-f][0-9A-Fa-f])");
5764 reg::Iterator it(s,re);
5766 int hue = Config_getInt(HTML_COLORSTYLE_HUE);
5767 int sat = Config_getInt(HTML_COLORSTYLE_SAT);
5768 int gamma = Config_getInt(HTML_COLORSTYLE_GAMMA);
5769 size_t sl=s.length();
5770 size_t p=0;
5771 for (; it!=end ; ++it)
5772 {
5773 const auto &match = *it;
5774 size_t i = match.position();
5775 size_t l = match.length();
5776 if (i>p) result+=s.substr(p,i-p);
5777 std::string lumStr = match.str().substr(2);
5778#define HEXTONUM(x) (((x)>='0' && (x)<='9') ? ((x)-'0') : \
5779 ((x)>='a' && (x)<='f') ? ((x)-'a'+10) : \
5780 ((x)>='A' && (x)<='F') ? ((x)-'A'+10) : 0)
5781
5782 double r = 0,g = 0,b = 0;
5783 int level = HEXTONUM(lumStr[0])*16+HEXTONUM(lumStr[1]);
5784 ColoredImage::hsl2rgb(hue/360.0,sat/255.0,
5785 pow(level/255.0,gamma/100.0),&r,&g,&b);
5786 int red = static_cast<int>(r*255.0);
5787 int green = static_cast<int>(g*255.0);
5788 int blue = static_cast<int>(b*255.0);
5789 char colStr[8];
5790 colStr[0]='#';
5791 colStr[1]=hex[red>>4];
5792 colStr[2]=hex[red&0xf];
5793 colStr[3]=hex[green>>4];
5794 colStr[4]=hex[green&0xf];
5795 colStr[5]=hex[blue>>4];
5796 colStr[6]=hex[blue&0xf];
5797 colStr[7]=0;
5798 //printf("replacing %s->%s (level=%d)\n",qPrint(lumStr),colStr,level);
5799 result+=colStr;
5800 p=i+l;
5801 }
5802 if (p<sl) result+=s.substr(p);
5803 return result;
5804}
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, end(), hex, HEXTONUM, ColoredImage::hsl2rgb(), QCString::isEmpty(), and QCString::str().

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

◆ resolveLink()

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

Definition at line 2668 of file util.cpp.

2676{
2677 *resContext=nullptr;
2678
2679 QCString linkRef=lr;
2680 if (lang==SrcLangExt::CSharp)
2681 {
2682 linkRef = mangleCSharpGenericName(linkRef);
2683 }
2684 QCString linkRefWithoutTemplates = stripTemplateSpecifiersFromScope(linkRef,FALSE);
2685 AUTO_TRACE("scName='{}',ref='{}'",scName,lr);
2686 const FileDef *fd = nullptr;
2687 const GroupDef *gd = nullptr;
2688 const PageDef *pd = nullptr;
2689 const ClassDef *cd = nullptr;
2690 const DirDef *dir = nullptr;
2691 const ConceptDef *cnd = nullptr;
2692 const ModuleDef *modd = nullptr;
2693 const NamespaceDef *nd = nullptr;
2694 const SectionInfo *si = nullptr;
2695 bool ambig = false;
2696 if (linkRef.isEmpty()) // no reference name!
2697 {
2698 AUTO_TRACE_EXIT("no_ref");
2699 return FALSE;
2700 }
2701 else if ((pd=Doxygen::pageLinkedMap->find(linkRef))) // link to a page
2702 {
2703 gd = pd->getGroupDef();
2704 if (gd)
2705 {
2706 if (!pd->name().isEmpty()) si=SectionManager::instance().find(pd->name());
2707 *resContext=gd;
2708 if (si) resAnchor = si->label();
2709 }
2710 else
2711 {
2712 *resContext=pd;
2713 }
2714 AUTO_TRACE_EXIT("page");
2715 return TRUE;
2716 }
2717 else if ((si=SectionManager::instance().find(prefix+linkRef)))
2718 {
2719 *resContext=si->definition();
2720 resAnchor = si->label();
2721 AUTO_TRACE_EXIT("section");
2722 return TRUE;
2723 }
2724 else if ((si=SectionManager::instance().find(linkRef)))
2725 {
2726 *resContext=si->definition();
2727 resAnchor = si->label();
2728 AUTO_TRACE_EXIT("section");
2729 return TRUE;
2730 }
2731 else if ((pd=Doxygen::exampleLinkedMap->find(linkRef))) // link to an example
2732 {
2733 *resContext=pd;
2734 AUTO_TRACE_EXIT("example");
2735 return TRUE;
2736 }
2737 else if ((gd=Doxygen::groupLinkedMap->find(linkRef))) // link to a group
2738 {
2739 *resContext=gd;
2740 AUTO_TRACE_EXIT("group");
2741 return TRUE;
2742 }
2743 else if ((fd=findFileDef(Doxygen::inputNameLinkedMap,linkRef,ambig)) // file link
2744 && fd->isLinkable())
2745 {
2746 *resContext=fd;
2747 AUTO_TRACE_EXIT("file");
2748 return TRUE;
2749 }
2750 else if ((cd=getClass(linkRef))) // class link
2751 {
2752 *resContext=cd;
2753 resAnchor=cd->anchor();
2754 AUTO_TRACE_EXIT("class");
2755 return TRUE;
2756 }
2757 else if (lang==SrcLangExt::Java &&
2758 (cd=getClass(linkRefWithoutTemplates))) // Java generic class link
2759 {
2760 *resContext=cd;
2761 resAnchor=cd->anchor();
2762 AUTO_TRACE_EXIT("generic");
2763 return TRUE;
2764 }
2765 else if ((cd=getClass(linkRef+"-p"))) // Obj-C protocol link
2766 {
2767 *resContext=cd;
2768 resAnchor=cd->anchor();
2769 AUTO_TRACE_EXIT("protocol");
2770 return TRUE;
2771 }
2772 else if ((cnd=getConcept(linkRef))) // C++20 concept definition
2773 {
2774 *resContext=cnd;
2775 resAnchor=cnd->anchor();
2776 AUTO_TRACE_EXIT("concept");
2777 return TRUE;
2778 }
2779 else if ((modd=ModuleManager::instance().modules().find(linkRef)))
2780 {
2781 *resContext=modd;
2782 resAnchor=modd->anchor();
2783 AUTO_TRACE_EXIT("module");
2784 return TRUE;
2785 }
2786 else if ((nd=Doxygen::namespaceLinkedMap->find(linkRef)))
2787 {
2788 *resContext=nd;
2789 AUTO_TRACE_EXIT("namespace");
2790 return TRUE;
2791 }
2792 else if ((dir=Doxygen::dirLinkedMap->find(FileInfo(linkRef.str()).absFilePath()+"/"))
2793 && dir->isLinkable()) // TODO: make this location independent like filedefs
2794 {
2795 *resContext=dir;
2796 AUTO_TRACE_EXIT("directory");
2797 return TRUE;
2798 }
2799 else // probably a member reference
2800 {
2801 const MemberDef *md = nullptr;
2802 bool res = resolveRef(scName,lr,TRUE,resContext,&md,lang);
2803 if (md) resAnchor=md->anchor();
2804 AUTO_TRACE_EXIT("member? res={}",res);
2805 return res;
2806 }
2807}
A model of a directory symbol.
Definition dirdef.h:110
static NamespaceLinkedMap * namespaceLinkedMap
Definition doxygen.h:114
static PageLinkedMap * exampleLinkedMap
Definition doxygen.h:98
static DirLinkedMap * dirLinkedMap
Definition doxygen.h:128
static GroupLinkedMap * groupLinkedMap
Definition doxygen.h:113
std::string absFilePath() const
Definition fileinfo.cpp:101
A model of a group of symbols.
Definition groupdef.h:52
static ModuleManager & instance()
virtual const GroupDef * getGroupDef() const =0
QCString label() const
Definition section.h:68
Definition * definition() const
Definition section.h:76
bool resolveRef(const QCString &scName, const QCString &name, bool inSeeBlock, const Definition **resContext, const MemberDef **resMember, SrcLangExt lang, bool lookForSpecialization, const FileDef *currentFile, bool checkScope)
Definition util.cpp:2386
QCString mangleCSharpGenericName(const QCString &name)
Definition util.cpp:6863
QCString stripTemplateSpecifiersFromScope(const QCString &fullName, bool parentOnly, QCString *pLastScopeStripped, QCString scopeName, bool allowArtificial)
Definition util.cpp:4469

References FileInfo::absFilePath(), Definition::anchor(), AUTO_TRACE, AUTO_TRACE_EXIT, SectionInfo::definition(), Doxygen::dirLinkedMap, Doxygen::exampleLinkedMap, FALSE, LinkedMap< T, Hash, KeyEqual, Map >::find(), findFileDef(), getClass(), getConcept(), PageDef::getGroupDef(), Doxygen::groupLinkedMap, Doxygen::inputNameLinkedMap, ModuleManager::instance(), SectionManager::instance(), QCString::isEmpty(), Definition::isLinkable(), SectionInfo::label(), mangleCSharpGenericName(), Definition::name(), Doxygen::namespaceLinkedMap, Doxygen::pageLinkedMap, prefix, resolveRef(), QCString::str(), stripTemplateSpecifiersFromScope(), and TRUE.

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

◆ resolveRef()

bool resolveRef ( const QCString & scName,
const QCString & name,
bool inSeeBlock,
const Definition ** resContext,
const MemberDef ** resMember,
SrcLangExt lang,
bool lookForSpecialization,
const FileDef * currentFile,
bool checkScope )

Returns an object to reference to given its name and context

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

Definition at line 2386 of file util.cpp.

2396{
2397 AUTO_TRACE("scope={} name={} inSeeBlock={} lang={} lookForSpecialization={} currentFile={} checkScope={}",
2398 scName,name,inSeeBlock,lang,lookForSpecialization,currentFile ? currentFile->name() : "", checkScope);
2399 //printf("resolveRef(scope=%s,name=%s,inSeeBlock=%d)\n",qPrint(scName),qPrint(name),inSeeBlock);
2400 QCString tsName = name;
2401 //bool memberScopeFirst = tsName.find('#')!=-1;
2402 QCString fullName = substitute(tsName,"#","::");
2403 if (fullName.find("anonymous_namespace{")==-1)
2404 {
2405 fullName = removeRedundantWhiteSpace(substitute(fullName,".","::",3));
2406 }
2407 else
2408 {
2409 fullName = removeRedundantWhiteSpace(fullName);
2410 }
2411
2412 int templStartPos;
2413 if (lang==SrcLangExt::CSharp && (templStartPos=fullName.find('<'))!=-1)
2414 {
2415 int templEndPos = fullName.findRev('>');
2416 if (templEndPos!=-1)
2417 {
2418 fullName = mangleCSharpGenericName(fullName.left(templEndPos+1))+fullName.mid(templEndPos+1);
2419 AUTO_TRACE_ADD("C# mangled name='{}'",fullName);
2420 }
2421 }
2422
2423 int bracePos=findParameterList(fullName);
2424 int endNamePos=bracePos!=-1 ? bracePos : static_cast<int>(fullName.length());
2425 int scopePos=fullName.findRev("::",endNamePos);
2426 bool explicitScope = fullName.startsWith("::") && // ::scope or #scope
2427 (scopePos>2 || // ::N::A
2428 tsName.startsWith("::") || // ::foo in local scope
2429 scName==nullptr // #foo in global scope
2430 );
2431 bool allowTypeOnly=false;
2432
2433 // default result values
2434 *resContext=nullptr;
2435 *resMember=nullptr;
2436
2437 if (bracePos==-1) // simple name
2438 {
2439 // the following if() was commented out for releases in the range
2440 // 1.5.2 to 1.6.1, but has been restored as a result of bug report 594787.
2441 if (!inSeeBlock && scopePos==-1 && isLowerCase(tsName))
2442 { // link to lower case only name => do not try to autolink
2443 AUTO_TRACE_ADD("false");
2444 return FALSE;
2445 }
2446
2447 ClassDef *cd=nullptr;
2448 NamespaceDef *nd=nullptr;
2449 ConceptDef *cnd=nullptr;
2450 ModuleDef *modd=nullptr;
2451
2452 //printf("scName=%s fullName=%s\n",qPrint(scName),qPrint(fullName));
2453
2454 // check if this is a class or namespace reference
2455 if (scName!=fullName && getScopeDefs(scName,fullName,cd,cnd,nd,modd))
2456 {
2457 //printf("found scopeDef\n");
2458 if (cd) // scope matches that of a class
2459 {
2460 *resContext = cd;
2461 }
2462 else if (cnd)
2463 {
2464 *resContext = cnd;
2465 }
2466 else if (modd)
2467 {
2468 *resContext = modd;
2469 }
2470 else // scope matches that of a namespace
2471 {
2472 ASSERT(nd!=nullptr);
2473 *resContext = nd;
2474 }
2475 AUTO_TRACE_ADD("true");
2476 return TRUE;
2477 }
2478 else if (scName==fullName || (!inSeeBlock && scopePos==-1))
2479 // nothing to link => output plain text
2480 {
2481 //printf("found scName=%s fullName=%s scName==fullName=%d "
2482 // "inSeeBlock=%d scopePos=%d!\n",
2483 // qPrint(scName),qPrint(fullName),scName==fullName,inSeeBlock,scopePos);
2484
2485 // at this point we have a bare word that is not a class or namespace
2486 // we should also allow typedefs or enums to be linked, but not for instance member
2487 // functions, otherwise 'Foo' would always link to the 'Foo()' constructor instead of the
2488 // 'Foo' class. So we use this flag as a filter.
2489 allowTypeOnly=true;
2490 }
2491
2492 // continue search...
2493 }
2494
2495 // extract userscope+name
2496 QCString nameStr=fullName.left(endNamePos);
2497 if (explicitScope) nameStr=nameStr.mid(2);
2498
2499
2500 // extract arguments
2501 QCString argsStr;
2502 if (bracePos!=-1) argsStr=fullName.right(fullName.length()-bracePos);
2503
2504 // strip template specifier
2505 // TODO: match against the correct partial template instantiation
2506 int templPos=nameStr.find('<');
2507 bool tryUnspecializedVersion = FALSE;
2508 if (templPos!=-1 && nameStr.find("operator")==-1)
2509 {
2510 int endTemplPos=nameStr.findRev('>');
2511 if (endTemplPos!=-1)
2512 {
2513 if (!lookForSpecialization)
2514 {
2515 nameStr=nameStr.left(templPos)+nameStr.right(nameStr.length()-endTemplPos-1);
2516 }
2517 else
2518 {
2519 tryUnspecializedVersion = TRUE;
2520 }
2521 }
2522 }
2523
2524 QCString scopeStr=scName;
2525 if (!explicitScope && nameStr.length()>scopeStr.length() && leftScopeMatch(scopeStr,nameStr))
2526 {
2527 nameStr=nameStr.mid(scopeStr.length()+2);
2528 }
2529
2530 const GroupDef *gd = nullptr;
2531 const ConceptDef *cnd = nullptr;
2532 const ModuleDef *modd = nullptr;
2533
2534 // check if nameStr is a member or global.
2535 //printf("getDefs(scope=%s,name=%s,args=%s checkScope=%d)\n",
2536 // qPrint(scopeStr), qPrint(nameStr), qPrint(argsStr),checkScope);
2537 GetDefInput input(scopeStr,nameStr,argsStr);
2538 input.forceEmptyScope = explicitScope;
2539 input.currentFile = currentFile;
2540 input.checkCV = true;
2541 GetDefResult result = getDefs(input);
2542 if (result.found)
2543 {
2544 //printf("after getDefs checkScope=%d nameStr=%s\n",checkScope,qPrint(nameStr));
2545 if (checkScope && result.md && result.md->getOuterScope()==Doxygen::globalScope &&
2546 !result.md->isStrongEnumValue() &&
2547 (!scopeStr.isEmpty() || nameStr.find("::")>0))
2548 {
2549 // we did find a member, but it is a global one while we were explicitly
2550 // looking for a scoped variable. See bug 616387 for an example why this check is needed.
2551 // note we do need to support autolinking to "::symbol" hence the >0
2552 //printf("not global member!\n");
2553 *resContext=nullptr;
2554 *resMember=nullptr;
2555 AUTO_TRACE_ADD("false");
2556 return FALSE;
2557 }
2558 //printf("after getDefs md=%p cd=%p fd=%p nd=%p gd=%p\n",md,cd,fd,nd,gd);
2559 if (result.md)
2560 {
2561 if (!allowTypeOnly || result.md->isTypedef() || result.md->isEnumerate())
2562 {
2563 *resMember=result.md;
2564 *resContext=result.md;
2565 }
2566 else // md is not a type, but we explicitly expect one
2567 {
2568 *resContext=nullptr;
2569 *resMember=nullptr;
2570 AUTO_TRACE_ADD("false");
2571 return FALSE;
2572 }
2573 }
2574 else if (result.cd) *resContext=result.cd;
2575 else if (result.nd) *resContext=result.nd;
2576 else if (result.fd) *resContext=result.fd;
2577 else if (result.gd) *resContext=result.gd;
2578 else if (result.cnd) *resContext=result.cnd;
2579 else if (result.modd) *resContext=result.modd;
2580 else
2581 {
2582 *resContext=nullptr; *resMember=nullptr;
2583 AUTO_TRACE_ADD("false");
2584 return FALSE;
2585 }
2586 //printf("member=%s (md=%p) anchor=%s linkable()=%d context=%s\n",
2587 // qPrint(md->name()), md, qPrint(md->anchor()), md->isLinkable(), qPrint((*resContext)->name()));
2588 AUTO_TRACE_ADD("true");
2589 return TRUE;
2590 }
2591 else if (inSeeBlock && !nameStr.isEmpty() && (gd=Doxygen::groupLinkedMap->find(nameStr)))
2592 { // group link
2593 *resContext=gd;
2594 AUTO_TRACE_ADD("true");
2595 return TRUE;
2596 }
2597 else if ((cnd=Doxygen::conceptLinkedMap->find(nameStr)))
2598 {
2599 *resContext=cnd;
2600 AUTO_TRACE_ADD("true");
2601 return TRUE;
2602 }
2603 else if ((modd=ModuleManager::instance().modules().find(nameStr)))
2604 {
2605 *resContext=modd;
2606 AUTO_TRACE_ADD("true");
2607 return TRUE;
2608 }
2609 else if (tsName.find('.')!=-1) // maybe a link to a file
2610 {
2611 bool ambig = false;
2612 const FileDef *fd=findFileDef(Doxygen::inputNameLinkedMap,tsName,ambig);
2613 if (fd && !ambig)
2614 {
2615 *resContext=fd;
2616 AUTO_TRACE_ADD("true");
2617 return TRUE;
2618 }
2619 }
2620
2621 if (tryUnspecializedVersion)
2622 {
2623 bool b = resolveRef(scName,name,inSeeBlock,resContext,resMember,lang,FALSE,nullptr,checkScope);
2624 AUTO_TRACE_ADD("{}",b);
2625 return b;
2626 }
2627 if (bracePos!=-1) // Try without parameters as well, could be a constructor invocation
2628 {
2629 *resContext=getClass(fullName.left(bracePos));
2630 if (*resContext)
2631 {
2632 AUTO_TRACE_ADD("true");
2633 return TRUE;
2634 }
2635 }
2636 //printf("resolveRef: %s not found!\n",qPrint(name));
2637
2638 AUTO_TRACE_ADD("false");
2639 return FALSE;
2640}
static ConceptLinkedMap * conceptLinkedMap
Definition doxygen.h:97
virtual bool isStrongEnumValue() const =0
virtual bool isEnumerate() const =0
static bool isLowerCase(QCString &s)
Definition util.cpp:2374
int findParameterList(const QCString &name)
Returns the position in the string where a function parameter list begins, or -1 if one is not found.
Definition util.cpp:826
static bool getScopeDefs(const QCString &docScope, const QCString &scope, ClassDef *&cd, ConceptDef *&cnd, NamespaceDef *&nd, ModuleDef *&modd)
Definition util.cpp:2312

References ASSERT, AUTO_TRACE, AUTO_TRACE_ADD, GetDefResult::cd, GetDefInput::checkCV, GetDefResult::cnd, Doxygen::conceptLinkedMap, GetDefInput::currentFile, FALSE, GetDefResult::fd, QCString::find(), findFileDef(), findParameterList(), QCString::findRev(), GetDefInput::forceEmptyScope, GetDefResult::found, GetDefResult::gd, getClass(), getDefs(), Definition::getOuterScope(), getScopeDefs(), Doxygen::globalScope, Doxygen::groupLinkedMap, Doxygen::inputNameLinkedMap, ModuleManager::instance(), QCString::isEmpty(), MemberDef::isEnumerate(), isLowerCase(), MemberDef::isStrongEnumValue(), MemberDef::isTypedef(), QCString::left(), leftScopeMatch(), QCString::length(), mangleCSharpGenericName(), GetDefResult::md, QCString::mid(), GetDefResult::modd, Definition::name(), GetDefResult::nd, removeRedundantWhiteSpace(), resolveRef(), QCString::right(), QCString::startsWith(), substitute(), and TRUE.

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

◆ resolveTypeDef()

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

Definition at line 374 of file util.cpp.

376{
377 AUTO_TRACE("context='{}' qualifiedName='{}'",context?context->name():"",qualifiedName);
378 QCString result;
379 if (qualifiedName.isEmpty())
380 {
381 AUTO_TRACE_EXIT("empty name");
382 return result;
383 }
384
385 const Definition *mContext=context;
386 if (typedefContext) *typedefContext=context;
387
388 // see if the qualified name has a scope part
389 if (qualifiedName.find('<')!=-1)
390 {
391 AUTO_TRACE_EXIT("template");
392 return result;
393 }
394 int scopeIndex = qualifiedName.findRev("::");
395 QCString resName=qualifiedName;
396 if (scopeIndex!=-1) // strip scope part for the name
397 {
398 resName=qualifiedName.right(qualifiedName.length()-scopeIndex-2);
399 if (resName.isEmpty())
400 {
401 AUTO_TRACE_EXIT("invalid format");
402 return result;
403 }
404 }
405 const MemberDef *md=nullptr;
406 while (mContext && md==nullptr)
407 {
408 // step 1: get the right scope
409 const Definition *resScope=mContext;
410 if (scopeIndex!=-1)
411 {
412 // split-off scope part
413 QCString resScopeName = qualifiedName.left(scopeIndex);
414 //printf("resScopeName='%s'\n",qPrint(resScopeName));
415
416 // look-up scope in context
417 int is=0,ps=0,l=0;
418 while ((is=getScopeFragment(resScopeName,ps,&l))!=-1)
419 {
420 QCString qualScopePart = resScopeName.mid(is,l);
421 QCString tmp = resolveTypeDef(mContext,qualScopePart);
422 if (!tmp.isEmpty()) qualScopePart=tmp;
423 resScope = resScope->findInnerCompound(qualScopePart);
424 //printf("qualScopePart='%s' resScope=%p\n",qPrint(qualScopePart),resScope);
425 if (resScope==nullptr) break;
426 ps=is+l;
427 }
428 }
429 AUTO_TRACE_ADD("resScope='{}' resName='{}'",resScope?resScope->name():"",resName);
430
431 // step 2: get the member
432 if (resScope) // no scope or scope found in the current context
433 {
434 //printf("scope found: %s, look for typedef %s\n",
435 // qPrint(resScope->qualifiedName()),qPrint(resName));
436 MemberNameLinkedMap *mnd=nullptr;
437 bool searchRelated=false;
438 bool mustBeRelated=false;
439 if (resScope->definitionType()==Definition::TypeClass)
440 {
442 }
443 else
444 {
446 searchRelated=true;
447 }
448 MemberName *mn=mnd->find(resName);
449 if (mn==0 && searchRelated)
450 {
451 mn=Doxygen::memberNameLinkedMap->find(resName);
452 mustBeRelated=true;
453 }
454 if (mn)
455 {
456 int minDist=-1;
457 for (const auto &tmd_p : *mn)
458 {
459 const MemberDef *tmd = tmd_p.get();
460 AUTO_TRACE_ADD("found candidate member '{}' isTypeDef={}' isRelated={} mustBeRelated={}",
461 tmd->name(),tmd->isTypedef(),tmd->isRelated(),mustBeRelated);
462 //printf("Found member %s resScope=%s outerScope=%s mContext=%p\n",
463 // qPrint(tmd->name()),qPrint( resScope->name()),
464 // qPrint(tmd->getOuterScope()->name()), mContext);
465 if (tmd->isTypedef())
466 {
467 if (resScope==Doxygen::globalScope && tmd->isRelated() && mustBeRelated)
468 {
469 md = tmd;
470 }
471 else
472 {
473 SymbolResolver resolver;
474 int dist=resolver.isAccessibleFrom(resScope,tmd);
475 if (dist!=-1 && (md==nullptr || dist<minDist))
476 {
477 md = tmd;
478 minDist = dist;
479 }
480 }
481 }
482 }
483 }
484 }
485 mContext=mContext->getOuterScope();
486 }
487
488 AUTO_TRACE_ADD("md='{}'",md?md->name():"");
489 // step 3: get the member's type
490 if (md)
491 {
492 //printf(">>resolveTypeDef: Found typedef name '%s' in scope '%s' value='%s' args='%s'\n",
493 // qPrint(qualifiedName),qPrint(context->name()),qPrint(md->typeString()),qPrint(md->argsString())
494 // );
495 result=md->typeString();
496 QCString args = md->argsString();
497 if (args.find(")(")!=-1) // typedef of a function/member pointer
498 {
499 result+=args;
500 }
501 else if (args.find('[')!=-1) // typedef of an array
502 {
503 result+=args;
504 }
505 if (typedefContext) *typedefContext=md->getOuterScope();
506 }
507 else
508 {
509 //printf(">>resolveTypeDef: Typedef '%s' not found in scope '%s'!\n",
510 // qPrint(qualifiedName),context ? qPrint(context->name()) : "<global>");
511 }
512 AUTO_TRACE_EXIT("result='{}'",result);
513 return result;
514}
virtual const Definition * findInnerCompound(const QCString &name) const =0
static MemberNameLinkedMap * functionNameLinkedMap
Definition doxygen.h:111
static MemberNameLinkedMap * memberNameLinkedMap
Definition doxygen.h:110
virtual QCString typeString() const =0
virtual bool isRelated() const =0
virtual QCString argsString() 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.
QCString resolveTypeDef(const Definition *context, const QCString &qualifiedName, const Definition **typedefContext)
Definition util.cpp:374
int getScopeFragment(const QCString &s, int p, int *l)
Definition util.cpp:4581

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

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

◆ rightScopeMatch()

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

Definition at line 871 of file util.cpp.

872{
873 size_t sl=scope.length();
874 size_t nl=name.length();
875 return (name==scope || // equal
876 (scope.right(nl)==name && // substring
877 sl>1+nl && scope.at(sl-nl-1)==':' && scope.at(sl-nl-2)==':' // scope
878 )
879 );
880}

References QCString::at(), QCString::length(), and QCString::right().

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

◆ selectBlocks()

QCString selectBlocks ( const QCString & 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 6359 of file util.cpp.

6360{
6361 if (s.isEmpty()) return s;
6362
6363 // helper to find the end of a block
6364 auto skipBlock = [&markerInfo](const char *p,const SelectionBlock &blk)
6365 {
6366 char c = 0;
6367 while ((c=*p))
6368 {
6369 if (c==markerInfo.markerChar && qstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // end marker
6370 {
6371 size_t len = markerInfo.endLen;
6372 bool negate = *(p+markerInfo.endLen)=='!';
6373 if (negate) len++;
6374 size_t blkNameLen = qstrlen(blk.name);
6375 if (qstrncmp(p+len,blk.name,blkNameLen)==0 && // matching marker name
6376 qstrncmp(p+len+blkNameLen,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6377 {
6378 //printf("Found end marker %s enabled=%d negate=%d\n",blk.name,blk.enabled,negate);
6379 return p+len+blkNameLen+markerInfo.closeLen;
6380 }
6381 else // not the right marker id
6382 {
6383 p++;
6384 }
6385 }
6386 else // not and end marker
6387 {
6388 p++;
6389 }
6390 }
6391 return p;
6392 };
6393
6394 QCString result;
6395 result.reserve(s.length());
6396 const char *p = s.data();
6397 char c = 0;
6398 while ((c=*p))
6399 {
6400 if (c==markerInfo.markerChar) // potential start of marker
6401 {
6402 if (qstrncmp(p,markerInfo.beginStr,markerInfo.beginLen)==0) // start of begin marker
6403 {
6404 bool found = false;
6405 size_t len = markerInfo.beginLen;
6406 bool negate = *(p+len)=='!';
6407 if (negate) len++;
6408 for (const auto &blk : blockList)
6409 {
6410 size_t blkNameLen = qstrlen(blk.name);
6411 if (qstrncmp(p+len,blk.name,blkNameLen)==0 && // matching marker name
6412 qstrncmp(p+len+blkNameLen,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6413 {
6414 bool blockEnabled = blk.enabled!=negate;
6415 //printf("Found start marker %s enabled=%d negate=%d\n",blk.name,blk.enabled,negate);
6416 p+=len+blkNameLen+markerInfo.closeLen;
6417 if (!blockEnabled) // skip until the end of the block
6418 {
6419 //printf("skipping block\n");
6420 p=skipBlock(p,blk);
6421 }
6422 found=true;
6423 break;
6424 }
6425 }
6426 if (!found) // unknown marker id
6427 {
6428 result+=c;
6429 p++;
6430 }
6431 }
6432 else if (qstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // start of end marker
6433 {
6434 bool found = false;
6435 size_t len = markerInfo.endLen;
6436 bool negate = *(p+len)=='!';
6437 if (negate) len++;
6438 for (const auto &blk : blockList)
6439 {
6440 size_t blkNameLen = qstrlen(blk.name);
6441 if (qstrncmp(p+len,blk.name,blkNameLen)==0 && // matching marker name
6442 qstrncmp(p+len+blkNameLen,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6443 {
6444 //printf("Found end marker %s enabled=%d negate=%d\n",blk.name,blk.enabled,negate);
6445 p+=len+blkNameLen+markerInfo.closeLen;
6446 found=true;
6447 break;
6448 }
6449 }
6450 if (!found) // unknown marker id
6451 {
6452 result+=c;
6453 p++;
6454 }
6455 }
6456 else // not a start or end marker
6457 {
6458 result+=c;
6459 p++;
6460 }
6461 }
6462 else // not a marker character
6463 {
6464 result+=c;
6465 p++;
6466 }
6467 }
6468 //printf("====\n%s\n-----\n%s\n~~~~\n",qPrint(s),qPrint(result));
6469 return result;
6470}
uint32_t qstrlen(const char *str)
Returns the length of string str, or 0 if a null pointer is passed.
Definition qcstring.h:58

References SelectionMarkerInfo::beginLen, SelectionMarkerInfo::beginStr, SelectionMarkerInfo::closeLen, SelectionMarkerInfo::closeStr, QCString::data(), SelectionMarkerInfo::endLen, SelectionMarkerInfo::endStr, QCString::isEmpty(), QCString::length(), SelectionMarkerInfo::markerChar, qstrlen(), qstrncmp(), and QCString::reserve().

Referenced by substituteHtmlKeywords(), and substituteLatexKeywords().

◆ showFileDefMatches()

QCString showFileDefMatches ( const FileNameLinkedMap * fnMap,
const QCString & n )

Definition at line 2966 of file util.cpp.

2967{
2968 QCString result;
2969 QCString name=n;
2970 QCString path;
2971 int slashPos=std::max(name.findRev('/'),name.findRev('\\'));
2972 if (slashPos!=-1)
2973 {
2974 path=name.left(slashPos+1);
2975 name=name.right(name.length()-slashPos-1);
2976 }
2977 const FileName *fn=fnMap->find(name);
2978 if (fn)
2979 {
2980 bool first = true;
2981 for (const auto &fd : *fn)
2982 {
2983 if (path.isEmpty() || fd->getPath().right(path.length())==path)
2984 {
2985 if (!first) result += "\n";
2986 else first = false;
2987 result+=" "+fd->absFilePath();
2988 }
2989 }
2990 }
2991 return result;
2992}

References LinkedMap< T, Hash, KeyEqual, Map >::find(), QCString::findRev(), QCString::isEmpty(), QCString::left(), QCString::length(), and QCString::right().

Referenced by addIncludeFile(), buildFileList(), DocParser::findAndCopyImage(), DocDiaFile::parse(), DocDotFile::parse(), DocMscFile::parse(), DocPlantUmlFile::parse(), readIncludeFile(), DocParser::readTextFileByName(), and readTextFileByName().

◆ split() [1/2]

StringVector split ( const std::string & s,
const reg::Ex & delimiter )

split input string s by regular expression delimiter delimiter.

returns a vector of non-empty strings that are between the delimiters

Definition at line 6585 of file util.cpp.

6586{
6587 StringVector result;
6588 reg::Iterator iter(s, delimiter);
6590 size_t p=0;
6591 for ( ; iter != end; ++iter)
6592 {
6593 const auto &match = *iter;
6594 size_t i=match.position();
6595 size_t l=match.length();
6596 if (i>p) result.push_back(s.substr(p,i-p));
6597 p=i+l;
6598 }
6599 if (p<s.length()) result.push_back(s.substr(p));
6600 return result;
6601}

References end().

◆ split() [2/2]

StringVector split ( const std::string & s,
const std::string & delimiter )

split input string s by string delimiter delimiter.

returns a vector of non-empty strings that are between the delimiters

Definition at line 6568 of file util.cpp.

6569{
6570 StringVector result;
6571 size_t prev = 0, pos = 0, len = s.length();
6572 do
6573 {
6574 pos = s.find(delimiter, prev);
6575 if (pos == std::string::npos) pos = len;
6576 if (pos>prev) result.push_back(s.substr(prev,pos-prev));
6577 prev = pos + delimiter.length();
6578 }
6579 while (pos<len && prev<len);
6580 return result;
6581}

Referenced by VHDLOutlineParser::addProto(), VHDLOutlineParser::addVhdlType(), FlowChart::alignCommentNode(), anonymous_namespace{tagreader.cpp}::TagFileParser::buildLists(), VHDLOutlineParser::checkInlineCode(), checkVhdlString(), VHDLOutlineParser::createFunction(), VhdlDocGen::findArchitecture(), CitationManager::generatePage(), getFilteredImageAttributes(), VhdlDocGen::getIndexWord(), DocPara::handleCite(), DocPara::handleCommand(), DocParser::handleImage(), DocPara::handleInclude(), Qhp::initialize(), VhdlDocGen::parseForBinding(), VhdlDocGen::parseForConfig(), parseIncludeOptions(), writeFuncProto(), VhdlDocGen::writeInlineClassLink(), and VhdlDocGen::writeRecUnitDocu().

◆ stackTrace()

void stackTrace ( )

Definition at line 5422 of file util.cpp.

5423{
5424#ifdef TRACINGSUPPORT
5425 void *backtraceFrames[128];
5426 int frameCount = backtrace(backtraceFrames, 128);
5427 const size_t cmdLen = 40960;
5428 static char cmd[cmdLen];
5429 char *p = cmd;
5430 p += qsnprintf(p,cmdLen,"/usr/bin/atos -p %d ", (int)getpid());
5431 for (int x = 0; x < frameCount; x++)
5432 {
5433 p += qsnprintf(p,cmdLen,"%p ", backtraceFrames[x]);
5434 }
5435 fprintf(stderr,"========== STACKTRACE START ==============\n");
5436 if (FILE *fp = Portable::popen(cmd, "r"))
5437 {
5438 char resBuf[512];
5439 while (size_t len = fread(resBuf, 1, sizeof(resBuf), fp))
5440 {
5441 fwrite(resBuf, 1, len, stderr);
5442 }
5443 Portable::pclose(fp);
5444 }
5445 fprintf(stderr,"============ STACKTRACE END ==============\n");
5446 //fprintf(stderr,"%s\n", frameStrings[x]);
5447#endif
5448}

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

◆ stripAnonymousNamespaceScope()

QCString stripAnonymousNamespaceScope ( const QCString & s)

Definition at line 231 of file util.cpp.

232{
233 int i=0,p=0,l=0;
234 QCString newScope;
235 int sl = static_cast<int>(s.length());
236 while ((i=getScopeFragment(s,p,&l))!=-1)
237 {
238 //printf("Scope fragment %s\n",qPrint(s.mid(i,l)));
239 if (Doxygen::namespaceLinkedMap->find(s.left(i+l))!=nullptr)
240 {
241 if (s.at(i)!='@')
242 {
243 if (!newScope.isEmpty()) newScope+="::";
244 newScope+=s.mid(i,l);
245 }
246 }
247 else if (i<sl)
248 {
249 if (!newScope.isEmpty()) newScope+="::";
250 newScope+=s.right(sl-i);
251 goto done;
252 }
253 p=i+l;
254 }
255done:
256 //printf("stripAnonymousNamespaceScope('%s')='%s'\n",qPrint(s),qPrint(newScope));
257 return newScope;
258}

References QCString::at(), getScopeFragment(), QCString::isEmpty(), QCString::left(), QCString::length(), QCString::mid(), Doxygen::namespaceLinkedMap, and QCString::right().

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

◆ stripExtension()

QCString stripExtension ( const QCString & fName)

Definition at line 4885 of file util.cpp.

4886{
4888}
QCString stripExtensionGeneral(const QCString &fName, const QCString &ext)
Definition util.cpp:4875

References Doxygen::htmlFileExtension, and stripExtensionGeneral().

Referenced by anonymous_namespace{tagreader.cpp}::TagFileParser::buildLists(), ClassDefImpl::ClassDefImpl(), and MemberDefImpl::setTagInfo().

◆ stripExtensionGeneral()

QCString stripExtensionGeneral ( const QCString & fName,
const QCString & ext )

◆ stripFromIncludePath()

QCString stripFromIncludePath ( const QCString & path)

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

Definition at line 330 of file util.cpp.

331{
332 return stripFromPath(path,Config_getList(STRIP_FROM_INC_PATH));
333}

References Config_getList, and stripFromPath().

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

◆ stripFromPath()

QCString stripFromPath ( const QCString & path)

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

Definition at line 322 of file util.cpp.

323{
324 return stripFromPath(path,Config_getList(STRIP_FROM_PATH));
325}

References Config_getList, and stripFromPath().

◆ stripIndentation()

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

Definition at line 5901 of file util.cpp.

5902{
5903 if (s.isEmpty()) return s; // empty string -> we're done
5904
5905 //printf("stripIndentation:\n%s\n------\n",qPrint(s));
5906 // compute minimum indentation over all lines
5907 const char *p=s.data();
5908 char c=0;
5909 int indent=0;
5910 int minIndent=1000000; // "infinite"
5911 bool searchIndent=true;
5912 int tabSize=Config_getInt(TAB_SIZE);
5913 bool skipFirst = skipFirstLine;
5914 while ((c=*p++))
5915 {
5916 if (c=='\t') { indent+=tabSize - (indent%tabSize); }
5917 else if (c=='\n') { indent=0; searchIndent=true; skipFirst=false; }
5918 else if (c==' ') { indent++; }
5919 else if (searchIndent && !skipFirst)
5920 {
5921 searchIndent=false;
5922 if (indent<minIndent) minIndent=indent;
5923 }
5924 }
5925
5926 // no indent to remove -> we're done
5927 if (minIndent==0) return substitute(s,"@ilinebr","\\ilinebr");
5928
5929 // remove minimum indentation for each line
5930 TextStream result;
5931 p=s.data();
5932 indent=0;
5933 skipFirst=skipFirstLine;
5934 while ((c=*p++))
5935 {
5936 if (c=='\n') // start of new line
5937 {
5938 indent=0;
5939 result << c;
5940 skipFirst=false;
5941 }
5942 else if (indent<minIndent && !skipFirst) // skip until we reach minIndent
5943 {
5944 if (c=='\t')
5945 {
5946 int newIndent = indent+tabSize-(indent%tabSize);
5947 int i=newIndent;
5948 while (i>minIndent) // if a tab crosses the minIndent boundary fill the rest with spaces
5949 {
5950 result << ' ';
5951 i--;
5952 }
5953 indent=newIndent;
5954 }
5955 else // space
5956 {
5957 indent++;
5958 }
5959 }
5960 else if (c=='\\' && literal_at(p,"ilinebr "))
5961 // we also need to remove the indentation after a \ilinebr command at the end of a line
5962 {
5963 result << "\\ilinebr ";
5964 p+=8;
5965 int skipAmount=0;
5966 for (int j=0;j<minIndent;j++) if (*(p+j)==' ') skipAmount++; // test to see if we have the indent
5967 if (skipAmount==minIndent)
5968 {
5969 p+=skipAmount; // remove the indent
5970 }
5971 }
5972 else if (c=='@' && literal_at(p,"ilinebr"))
5973 {
5974 result << "\\ilinebr";
5975 p+=7;
5976 }
5977 else // copy anything until the end of the line
5978 {
5979 result << c;
5980 }
5981 }
5982
5983 //printf("stripIndentation: result=\n%s\n------\n",qPrint(result.str()));
5984
5985 return result.str();
5986}

References Config_getInt, QCString::data(), QCString::isEmpty(), literal_at(), TextStream::str(), and substitute().

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

◆ stripIndentationVerbatim()

void stripIndentationVerbatim ( QCString & doc,
const int indentationLevel )

Definition at line 5989 of file util.cpp.

5990{
5991 //printf("stripIndentationVerbatim(level=%d):\n%s\n------\n",indentationLevel,qPrint(doc));
5992 if (indentationLevel <= 0 || doc.isEmpty()) return; // nothing to strip
5993
5994 // by stripping content the string will only become shorter so we write the results
5995 // back into the input string and then resize it at the end.
5996 char c = 0;
5997 const char *src = doc.data();
5998 char *dst = doc.rawData();
5999 bool insideIndent = false; // skip the initial line from stripping
6000 int cnt = 0;
6001 while ((c=*src++))
6002 {
6003 // invariant: dst<=src
6004 switch(c)
6005 {
6006 case '\n':
6007 *dst++ = c;
6008 insideIndent = true;
6009 cnt = indentationLevel;
6010 break;
6011 case ' ':
6012 if (insideIndent)
6013 {
6014 if (cnt>0) // count down the spacing until the end of the indent
6015 {
6016 cnt--;
6017 }
6018 else // reached the end of the indent, start of the part of the line to keep
6019 {
6020 insideIndent = false;
6021 *dst++ = c;
6022 }
6023 }
6024 else // part after indent, copy to the output
6025 {
6026 *dst++ = c;
6027 }
6028 break;
6029 default:
6030 insideIndent = false;
6031 *dst++ = c;
6032 break;
6033 }
6034 }
6035 doc.resize(static_cast<uint32_t>(dst-doc.data()));
6036 //printf("stripIndentationVerbatim: result=\n%s\n------\n",qPrint(doc));
6037}
char * rawData()
Returns a writable pointer to the data.
Definition qcstring.h:178
void resize(size_t newlen)
Definition qcstring.h:180

References QCString::data(), QCString::isEmpty(), QCString::rawData(), and QCString::resize().

◆ stripLeadingAndTrailingEmptyLines()

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

Special version of QCString::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 4966 of file util.cpp.

4967{
4968 if (s.isEmpty()) return QCString();
4969 const char *p = s.data();
4970
4971 // search for leading empty lines
4972 int i=0,li=-1,l=static_cast<int>(s.length());
4973 char c = 0;
4974 while ((c=*p))
4975 {
4976 if (c==' ' || c=='\t' || c=='\r') { i++; p++; }
4977 else if (c=='\\' && literal_at(p,"\\ilinebr")) { i+=8; li=i; p+=8; }
4978 else if (c=='\n') { i++; li=i; docLine++; p++; }
4979 else break;
4980 }
4981
4982 // search for trailing empty lines
4983 int b=l-1,bi=-1;
4984 p=s.data()+b;
4985 while (b>=0)
4986 {
4987 c=*p;
4988 if (c==' ' || c=='\t' || c=='\r') { b--; p--; }
4989 else if (c=='r' && b>=7 && literal_at(p-7,"\\ilinebr")) { bi=b-7; b-=8; p-=8; }
4990 else if (c=='>' && b>=11 && literal_at(p-11,"\\ilinebr<br>")) { bi=b-11; b-=12; p-=12; }
4991 else if (c=='\n') { bi=b; b--; p--; }
4992 else break;
4993 }
4994
4995 // return whole string if no leading or trailing lines where found
4996 if (li==-1 && bi==-1) return s;
4997
4998 // return substring
4999 if (bi==-1) bi=l;
5000 if (li==-1) li=0;
5001 if (bi<=li) return QCString(); // only empty lines
5002 //printf("docLine='%s' len=%d li=%d bi=%d\n",qPrint(s),s.length(),li,bi);
5003 return s.mid(li,bi-li);
5004}

References QCString::data(), QCString::isEmpty(), QCString::length(), literal_at(), and QCString::mid().

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

◆ stripPath()

QCString stripPath ( const QCString & s)

Definition at line 4890 of file util.cpp.

4891{
4892 QCString result=s;
4893 int i=result.findRev('/');
4894 if (i!=-1)
4895 {
4896 result=result.mid(i+1);
4897 }
4898 i=result.findRev('\\');
4899 if (i!=-1)
4900 {
4901 result=result.mid(i+1);
4902 }
4903 return result;
4904}

References QCString::findRev(), and QCString::mid().

Referenced by LatexGenerator::addLabel(), anonymous_namespace{tagreader.cpp}::TagFileParser::buildLists(), RTFGenerator::endDoxyAnchor(), LatexGenerator::endIndexItem(), LatexGenerator::endIndexValue(), LatexGenerator::endTitleHead(), objectLinkToString(), objectLinkToString(), objectLinkToString(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), DocbookDocVisitor::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()(), 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()(), DotFilePatcher::run(), SearchIndexExternal::setCurrentDoc(), DocbookGenerator::startDoxyAnchor(), LatexGenerator::startDoxyAnchor(), DocbookGenerator::startFile(), LatexGenerator::startFile(), RTFGenerator::startFile(), DocbookDocVisitor::startLink(), LatexDocVisitor::startLink(), RTFDocVisitor::startLink(), DocbookGenerator::startSection(), LatexGenerator::startSection(), LatexGenerator::startTextLink(), RTFGenerator::startTextLink(), substituteHtmlKeywords(), substituteKeywords(), LatexGenerator::writeAnchor(), RTFGenerator::writeAnchor(), LatexCodeGenerator::writeCodeLink(), RTFCodeGenerator::writeCodeLink(), DocbookCodeGenerator::writeCodeLinkLine(), MemberList::writeDeclarations(), writeDocbookLink(), LatexCodeGenerator::writeLineNumber(), RTFCodeGenerator::writeLineNumber(), RTFGenerator::writeRTFReference(), and RTFGenerator::writeStartAnnoItem().

◆ stripScope()

QCString stripScope ( const QCString & 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 3721 of file util.cpp.

3722{
3723 QCString result = name;
3724 int l = static_cast<int>(result.length());
3725 int p = 0;
3726 bool done = FALSE;
3727 bool skipBracket=FALSE; // if brackets do not match properly, ignore them altogether
3728 int count=0;
3729 int round=0;
3730
3731 do
3732 {
3733 p=l-1; // start at the end of the string
3734 while (p>=0 && count>=0)
3735 {
3736 char c=result.at(p);
3737 switch (c)
3738 {
3739 case ':':
3740 // only exit in the case of ::
3741 //printf("stripScope(%s)=%s\n",name,qPrint(result.right(l-p-1)));
3742 if (p>0 && result.at(p-1)==':' && (count==0 || skipBracket))
3743 {
3744 return result.right(l-p-1);
3745 }
3746 p--;
3747 break;
3748 case '>':
3749 if (skipBracket) // we don't care about brackets
3750 {
3751 p--;
3752 }
3753 else // count open/close brackets
3754 {
3755 if (p>0 && result.at(p-1)=='>') // skip >> operator
3756 {
3757 p-=2;
3758 break;
3759 }
3760 count=1;
3761 //printf("pos < = %d\n",p);
3762 p--;
3763 bool foundMatch=false;
3764 while (p>=0 && !foundMatch)
3765 {
3766 c=result.at(p--);
3767 switch (c)
3768 {
3769 case ')':
3770 round++;
3771 break;
3772 case '(':
3773 round--;
3774 break;
3775 case '>': // ignore > inside (...) to support e.g. (sizeof(T)>0) inside template parameters
3776 if (round==0) count++;
3777 break;
3778 case '<':
3779 if (round==0)
3780 {
3781 if (p>0)
3782 {
3783 if (result.at(p-1) == '<') // skip << operator
3784 {
3785 p--;
3786 break;
3787 }
3788 }
3789 count--;
3790 foundMatch = count==0;
3791 }
3792 break;
3793 default:
3794 //printf("c=%c count=%d\n",c,count);
3795 break;
3796 }
3797 }
3798 }
3799 //printf("pos > = %d\n",p+1);
3800 break;
3801 default:
3802 p--;
3803 }
3804 }
3805 done = count==0 || skipBracket; // reparse if brackets do not match
3806 skipBracket=TRUE;
3807 }
3808 while (!done); // if < > unbalanced repeat ignoring them
3809 //printf("stripScope(%s)=%s\n",name,name);
3810 return name;
3811}

References QCString::at(), FALSE, QCString::length(), QCString::right(), and TRUE.

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

◆ stripTemplateSpecifiersFromScope()

QCString stripTemplateSpecifiersFromScope ( const QCString & fullName,
bool parentOnly,
QCString * pLastScopeStripped,
QCString 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 4469 of file util.cpp.

4474{
4475 //printf("stripTemplateSpecifiersFromScope(name=%s,scopeName=%s)\n",qPrint(fullName),qPrint(scopeName));
4476 int i=fullName.find('<');
4477 if (i==-1) return fullName;
4478 QCString result;
4479 int p=0;
4480 int l=static_cast<int>(fullName.length());
4481 while (i!=-1)
4482 {
4483 //printf("1:result+=%s\n",qPrint(fullName.mid(p,i-p)));
4484 int e=i+1;
4485 int count=1;
4486 int round=0;
4487 while (e<l && count>0)
4488 {
4489 char c=fullName.at(e++);
4490 switch (c)
4491 {
4492 case '(': round++; break;
4493 case ')': if (round>0) round--; break;
4494 case '<': if (round==0) count++; break;
4495 case '>': if (round==0) count--; break;
4496 default:
4497 break;
4498 }
4499 }
4500 int si= fullName.find("::",e);
4501
4502 if (parentOnly && si==-1) break;
4503 // we only do the parent scope, so we stop here if needed
4504
4505 result+=fullName.mid(p,i-p);
4506 //printf(" trying %s\n",qPrint(mergeScopes(scopeName,result+fullName.mid(i,e-i))));
4507 ClassDef *cd = getClass(mergeScopes(scopeName,result+fullName.mid(i,e-i)));
4508 if (cd!=nullptr && (allowArtificial || !cd->isArtificial()))
4509 {
4510 result+=fullName.mid(i,e-i);
4511 //printf(" 2:result+=%s\n",qPrint(fullName.mid(i,e-i-1)));
4512 }
4513 else if (pLastScopeStripped)
4514 {
4515 //printf(" last stripped scope '%s'\n",qPrint(fullName.mid(i,e-i)));
4516 *pLastScopeStripped=fullName.mid(i,e-i);
4517 }
4518 p=e;
4519 i=fullName.find('<',p);
4520 }
4521 result+=fullName.right(l-p);
4522 //printf("3:result+=%s\n",qPrint(fullName.right(l-p)));
4523 //printf("end result=%s\n",qPrint(result));
4524 return result;
4525}
virtual bool isArtificial() const =0
QCString mergeScopes(const QCString &leftScope, const QCString &rightScope)
Definition util.cpp:4536

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

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

◆ substituteClassNames()

QCString substituteClassNames ( const QCString & s)

◆ substituteKeywords() [1/2]

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

Definition at line 2996 of file util.cpp.

2997{
2998 std::string substRes;
2999 int line = 1;
3000 const char *p = s.data();
3001 if (p)
3002 {
3003 // reserve some room for expansion
3004 substRes.reserve(s.length()+1024);
3005 char c = 0;
3006 while ((c=*p))
3007 {
3008 bool found = false;
3009 if (c=='$')
3010 {
3011 for (const auto &kw : keywords)
3012 {
3013 size_t keyLen = qstrlen(kw.keyword);
3014 if (qstrncmp(p,kw.keyword,keyLen)==0)
3015 {
3016 const char *startArg = p+keyLen;
3017 bool expectParam = std::holds_alternative<KeywordSubstitution::GetValueWithParam>(kw.getValueVariant);
3018 //printf("%s: expectParam=%d *startArg=%c\n",kw.keyword,expectParam,*startArg);
3019 if (expectParam && *startArg=='(') // $key(value)
3020 {
3021 size_t j=1;
3022 const char *endArg = nullptr;
3023 while ((c=*(startArg+j)) && c!=')' && c!='\n' && c!=0) j++;
3024 if (c==')') endArg=startArg+j;
3025 if (endArg)
3026 {
3027 QCString value = QCString(startArg+1).left(endArg-startArg-1);
3028 auto &&getValue = std::get<KeywordSubstitution::GetValueWithParam>(kw.getValueVariant);
3029 substRes+=getValue(value).str();
3030 p=endArg+1;
3031 //printf("found '%s'->'%s'\n",kw.keyword,qPrint(getValue(value)));
3032 }
3033 else
3034 {
3035 //printf("missing argument\n");
3036 warn(file,line,"Missing argument for '{}'",kw.keyword);
3037 p+=keyLen;
3038 }
3039 }
3040 else if (!expectParam) // $key
3041 {
3042 auto &&getValue = std::get<KeywordSubstitution::GetValue>(kw.getValueVariant);
3043 substRes+=getValue().str();
3044 //printf("found '%s'->'%s'\n",kw.keyword,qPrint(getValue()));
3045 p+=keyLen;
3046 }
3047 else
3048 {
3049 //printf("%s %d Expected arguments, none specified '%s'\n",qPrint(file), line, qPrint(kw.keyword));
3050 warn(file,line,"Expected arguments for '{}' but none were specified",kw.keyword);
3051 p+=keyLen;
3052 }
3053 found = true;
3054 break;
3055 }
3056 }
3057 }
3058 if (!found) // copy
3059 {
3060 if (c=='\n') line++;
3061 substRes+=c;
3062 p++;
3063 }
3064 }
3065 }
3066 return substRes;
3067}

References QCString::data(), QCString::left(), QCString::length(), qstrlen(), qstrncmp(), and warn.

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

◆ substituteKeywords() [2/2]

QCString substituteKeywords ( const QCString & file,
const QCString & s,
const QCString & title,
const QCString & projName,
const QCString & projNum,
const QCString & projBrief )

Definition at line 3148 of file util.cpp.

3150{
3151 return substituteKeywords(file,s,
3152 {
3153 // keyword value getter
3154 { "$title", [&]() { return !title.isEmpty() ? title : projName; } },
3155 { "$doxygenversion", [&]() { return getDoxygenVersion(); } },
3156 { "$projectname", [&]() { return projName; } },
3157 { "$projectnumber", [&]() { return projNum; } },
3158 { "$projectbrief", [&]() { return projBrief; } },
3159 { "$projectlogo", [&]() { return stripPath(projectLogoFile()); } },
3160 { "$logosize", [&]() { return projectLogoSize(); } },
3161 { "$projecticon", [&]() { return stripPath(Config_getString(PROJECT_ICON)); } },
3162 { "$langISO", [&]() { return theTranslator->trISOLang(); } },
3163 { "$showdate", [&](const QCString &fmt) { return showDate(fmt); } }
3164 });
3165}
Definition message.h:144
QCString stripPath(const QCString &s)
Definition util.cpp:4890
QCString substituteKeywords(const QCString &file, const QCString &s, const KeywordSubstitutionList &keywords)
Definition util.cpp:2996
QCString projectLogoFile()
Definition util.cpp:3082
static QCString projectLogoSize()
Definition util.cpp:3103
static QCString showDate(const QCString &fmt)
Definition util.cpp:3069

References Config_getString, QCString::isEmpty(), projectLogoFile(), projectLogoSize(), showDate(), stripPath(), substituteKeywords(), and theTranslator.

◆ substituteTemplateArgumentsInString()

QCString substituteTemplateArgumentsInString ( const QCString & nm,
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 4307 of file util.cpp.

4311{
4312 AUTO_TRACE("name={} formalArgs={} actualArgs={}",nm,argListToString(formalArgs),actualArgs ? argListToString(*actualArgs) : QCString());
4313 if (formalArgs.empty()) return nm;
4314 QCString result;
4315
4316 static const reg::Ex re(R"(\a\w*)");
4317 std::string name = nm.str();
4318 reg::Iterator it(name,re);
4320 size_t p=0;
4321
4322 for (; it!=end ; ++it)
4323 {
4324 const auto &match = *it;
4325 size_t i = match.position();
4326 size_t l = match.length();
4327 if (i>p) result += name.substr(p,i-p);
4328 QCString n(match.str());
4330 if (actualArgs)
4331 {
4332 actIt = actualArgs->begin();
4333 }
4334 //printf(": name=%s\n",qPrint(name));
4335
4336 // if n is a template argument, then we substitute it
4337 // for its template instance argument.
4338 bool found=FALSE;
4339 for (auto formIt = formalArgs.begin();
4340 formIt!=formalArgs.end() && !found;
4341 ++formIt
4342 )
4343 {
4344 Argument formArg = *formIt;
4345 Argument actArg;
4346 if (actualArgs && actIt!=actualArgs->end())
4347 {
4348 actArg = *actIt;
4349 }
4350 if (formArg.type.startsWith("class ") && formArg.name.isEmpty())
4351 {
4352 formArg.name = formArg.type.mid(6);
4353 formArg.type = "class";
4354 }
4355 else if (formArg.type.startsWith("typename ") && formArg.name.isEmpty())
4356 {
4357 formArg.name = formArg.type.mid(9);
4358 formArg.type = "typename";
4359 }
4360 else if (formArg.type.startsWith("class...")) // match 'class... name' to 'name...'
4361 {
4362 formArg.name += "...";
4363 formArg.type = formArg.type.left(5)+formArg.type.mid(8);
4364 }
4365 else if (formArg.type.startsWith("typename...")) // match 'typename... name' to 'name...'
4366 {
4367 formArg.name += "...";
4368 formArg.type = formArg.type.left(8)+formArg.type.mid(11);
4369 }
4370 //printf(": n=%s formArg->type='%s' formArg->name='%s' formArg->defval='%s' actArg->type='%s' actArg->name='%s' \n",
4371 // qPrint(n),qPrint(formArg.type),qPrint(formArg.name),qPrint(formArg.defval),qPrint(actArg.type),qPrint(actArg.name));
4372 if (formArg.type=="class" || formArg.type=="typename" || formArg.type.startsWith("template"))
4373 {
4374 if (formArg.name==n && actualArgs && actIt!=actualArgs->end() && !actArg.type.isEmpty()) // base class is a template argument
4375 {
4376 static constexpr auto hasRecursion = [](const QCString &prefix,const QCString &nameArg,const QCString &subst) -> bool
4377 {
4378 int ii=0;
4379 int pp=0;
4380
4381 ii = subst.find('<');
4382 //printf("prefix='%s' subst='%s'\n",qPrint(prefix.mid(prefix.length()-ii-2,ii+1)),qPrint(subst.left(ii+1)));
4383 if (ii!=-1 && static_cast<int>(prefix.length())>=ii+2 && prefix.mid(prefix.length()-ii-2,ii+1)==subst.left(ii+1))
4384 {
4385 return true; // don't replace 'A< ' with 'A< A<...', see issue #10951
4386 }
4387
4388 while ((ii=subst.find(nameArg,pp))!=-1)
4389 {
4390 bool beforeNonWord = ii==0 || !isId(subst.at(ii-1));
4391 bool afterNonWord = subst.length()==ii+nameArg.length() || !isId(subst.at(ii+nameArg.length()));
4392 if (beforeNonWord && afterNonWord)
4393 {
4394 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
4395 }
4396 pp=ii+static_cast<int>(nameArg.length());
4397 }
4398 return false;
4399 };
4400 // replace formal argument with the actual argument of the instance
4401 AUTO_TRACE_ADD("result={} n={} type={} hasRecursion={}",result,n,actArg.type,hasRecursion(result,n,actArg.type));
4402 if (!hasRecursion(result,n,actArg.type))
4403 // the scope guard is to prevent recursive lockup for
4404 // template<class A> class C : public<A::T>,
4405 // where A::T would become A::T::T here,
4406 // since n==A and actArg->type==A::T
4407 // see bug595833 for an example
4408 //
4409 // Also prevent recursive substitution if n is part of actArg.type, i.e.
4410 // n='A' in argType='S< A >' would produce 'S< S< A > >'
4411 {
4412 if (actArg.name.isEmpty())
4413 {
4414 result += actArg.type;
4415 }
4416 else
4417 // for case where the actual arg is something like "unsigned int"
4418 // the "int" part is in actArg->name.
4419 {
4420 result += actArg.type+" "+actArg.name;
4421 }
4422 found=TRUE;
4423 }
4424 }
4425 else if (formArg.name==n &&
4426 (actualArgs==nullptr || actIt==actualArgs->end()) &&
4427 !formArg.defval.isEmpty() &&
4428 formArg.defval!=nm /* to prevent recursion */
4429 )
4430 {
4431 result += substituteTemplateArgumentsInString(formArg.defval,formalArgs,actualArgs);
4432 found=TRUE;
4433 }
4434 }
4435 else if (formArg.name==n &&
4436 (actualArgs==nullptr || actIt==actualArgs->end()) &&
4437 !formArg.defval.isEmpty() &&
4438 formArg.defval!=nm /* to prevent recursion */
4439 )
4440 {
4441 result += substituteTemplateArgumentsInString(formArg.defval,formalArgs,actualArgs);
4442 found=TRUE;
4443 }
4444 if (actualArgs && actIt!=actualArgs->end())
4445 {
4446 actIt++;
4447 }
4448 }
4449 if (!found)
4450 {
4451 result += n;
4452 }
4453 p=i+l;
4454 }
4455 result+=name.substr(p);
4456 result=result.simplifyWhiteSpace();
4457 AUTO_TRACE_EXIT("result={}",result);
4458 return result.stripWhiteSpace();
4459}
typename Vec::const_iterator const_iterator
Definition arguments.h:69
QCString substituteTemplateArgumentsInString(const QCString &nm, const ArgumentList &formalArgs, const ArgumentList *actualArgs)
Definition util.cpp:4307

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

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

◆ tempArgListToString()

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

Definition at line 1243 of file util.cpp.

1244{
1245 QCString result;
1246 if (al.empty()) return result;
1247 result="<";
1248 bool first=true;
1249 for (const auto &a : al)
1250 {
1251 if (a.defval.isEmpty() || includeDefault)
1252 {
1253 if (!first) result+=", ";
1254 if (!a.name.isEmpty()) // add template argument name
1255 {
1256 if (lang==SrcLangExt::Java || lang==SrcLangExt::CSharp)
1257 {
1258 result+=a.type+" ";
1259 }
1260 result+=a.name;
1261 }
1262 else // extract name from type
1263 {
1264 int i = static_cast<int>(a.type.length())-1;
1265 while (i>=0 && isId(a.type.at(i))) i--;
1266 if (i>0)
1267 {
1268 result+=a.type.right(a.type.length()-i-1);
1269 if (a.type.find("...")!=-1)
1270 {
1271 result+="...";
1272 }
1273 }
1274 else // nothing found -> take whole name
1275 {
1276 result+=a.type;
1277 }
1278 }
1279 if (!a.typeConstraint.isEmpty() && lang==SrcLangExt::Java)
1280 {
1281 result+=" extends "; // TODO: now Java specific, C# has where...
1282 result+=a.typeConstraint;
1283 }
1284 first=false;
1285 }
1286 }
1287 result+=">";
1288 return removeRedundantWhiteSpace(result);
1289}

References ArgumentList::empty(), isId(), removeRedundantWhiteSpace(), and QCString::right().

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

◆ transcodeCharacterStringToUTF8()

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

Definition at line 1400 of file util.cpp.

1401{
1402 const char *outputEncoding = "UTF-8";
1403 if (inputEncoding==nullptr || qstricmp(inputEncoding,outputEncoding)==0) return true;
1404 size_t inputSize=input.length();
1405 size_t outputSize=inputSize*4;
1406 QCString output(outputSize, QCString::ExplicitSize);
1407 void *cd = portable_iconv_open(outputEncoding,inputEncoding);
1408 if (cd==reinterpret_cast<void *>(-1))
1409 {
1410 return false;
1411 }
1412 bool ok=true;
1413 size_t iLeft=inputSize;
1414 size_t oLeft=outputSize;
1415 const char *inputPtr = input.data();
1416 char *outputPtr = output.rawData();
1417 if (!portable_iconv(cd, &inputPtr, &iLeft, &outputPtr, &oLeft))
1418 {
1419 outputSize-=static_cast<int>(oLeft);
1420 output.resize(outputSize);
1421 output.at(outputSize)='\0';
1422 // replace input
1423 input=output.str();
1424 //printf("iconv: input size=%d output size=%d\n[%s]\n",size,newSize,qPrint(srcBuf));
1425 }
1426 else
1427 {
1428 ok=false;
1429 }
1431 return ok;
1432}
@ ExplicitSize
Definition qcstring.h:146
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)
int qstricmp(const char *s1, const char *s2)
Definition qcstring.cpp:530

References QCString::at(), QCString::ExplicitSize, portable_iconv(), portable_iconv_close(), portable_iconv_open(), qstricmp(), QCString::rawData(), QCString::resize(), and QCString::str().

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

◆ unescapeCharsInString()

QCString unescapeCharsInString ( const QCString & s)

Definition at line 3358 of file util.cpp.

3359{
3360 if (s.isEmpty()) return s;
3361 bool caseSenseNames = getCaseSenseNames();
3362 QCString result;
3363 result.reserve(s.length());
3364 const char *p = s.data();
3365 if (p)
3366 {
3367 char c = 0;
3368 while ((c=*p++))
3369 {
3370 if (c=='_') // 2 or 3 character escape
3371 {
3372 switch (*p)
3373 {
3374 case '_': result+=c; p++; break; // __ -> '_'
3375 case '1': result+=':'; p++; break; // _1 -> ':'
3376 case '2': result+='/'; p++; break; // _2 -> '/'
3377 case '3': result+='<'; p++; break; // _3 -> '<'
3378 case '4': result+='>'; p++; break; // _4 -> '>'
3379 case '5': result+='*'; p++; break; // _5 -> '*'
3380 case '6': result+='&'; p++; break; // _6 -> '&'
3381 case '7': result+='|'; p++; break; // _7 -> '|'
3382 case '8': result+='.'; p++; break; // _8 -> '.'
3383 case '9': result+='!'; p++; break; // _9 -> '!'
3384 case '0': // 3 character escape
3385 switch (*(p+1))
3386 {
3387 case '0': result+=','; p+=2; break; // _00 -> ','
3388 case '1': result+=' '; p+=2; break; // _01 -> ' '
3389 case '2': result+='{'; p+=2; break; // _02 -> '{'
3390 case '3': result+='}'; p+=2; break; // _03 -> '}'
3391 case '4': result+='?'; p+=2; break; // _04 -> '?'
3392 case '5': result+='^'; p+=2; break; // _05 -> '^'
3393 case '6': result+='%'; p+=2; break; // _06 -> '%'
3394 case '7': result+='('; p+=2; break; // _07 -> '('
3395 case '8': result+=')'; p+=2; break; // _08 -> ')'
3396 case '9': result+='+'; p+=2; break; // _09 -> '+'
3397 case 'a': result+='='; p+=2; break; // _0a -> '='
3398 case 'b': result+='$'; p+=2; break; // _0b -> '$'
3399 case 'c': result+='\\'; p+=2; break;// _0c -> '\'
3400 case 'd': result+='@'; p+=2; break; // _0d -> '@'
3401 case 'e': result+=']'; p+=2; break; // _0e -> ']'
3402 case 'f': result+='['; p+=2; break; // _0f -> '['
3403 case 'g': result+='#'; p+=2; break; // _0g -> '#'
3404 case 'h': result+='"'; p+=2; break; // _0h -> '"'
3405 case 'i': result+='~'; p+=2; break; // _0i -> '~'
3406 case 'j': result+='\''; p+=2; break;// _0j -> '\'
3407 case 'k': result+=';'; p+=2; break; // _0k -> ';'
3408 case 'l': result+='`'; p+=2; break; // _0l -> '`'
3409 default: // unknown escape, just pass underscore character as-is
3410 result+=c;
3411 break;
3412 }
3413 break;
3414 default:
3415 if (!caseSenseNames && c>='a' && c<='z') // lower to upper case escape, _a -> 'A'
3416 {
3417 result+=static_cast<char>(toupper(*p));
3418 p++;
3419 }
3420 else // unknown escape, pass underscore character as-is
3421 {
3422 result+=c;
3423 }
3424 break;
3425 }
3426 }
3427 else // normal character; pass as is
3428 {
3429 result+=c;
3430 }
3431 }
3432 }
3433 return result;
3434}

References QCString::data(), getCaseSenseNames(), QCString::isEmpty(), QCString::length(), and QCString::reserve().

◆ updateColumnCount()

size_t updateColumnCount ( const char * s,
size_t col )

Definition at line 6830 of file util.cpp.

6831{
6832 if (s)
6833 {
6834 const int tabSize = Config_getInt(TAB_SIZE);
6835 char c;
6836 while ((c=*s++))
6837 {
6838 switch(c)
6839 {
6840 case '\t': col+=tabSize - (col%tabSize);
6841 break;
6842 case '\n': col=0;
6843 break;
6844 default:
6845 col++;
6846 if (c<0) // multi-byte character
6847 {
6848 int numBytes = getUTF8CharNumBytes(c);
6849 for (int i=0;i<numBytes-1 && (c=*s++);i++) {} // skip over extra chars
6850 if (c==0) return col; // end of string half way a multibyte char
6851 }
6852 break;
6853 }
6854 }
6855 }
6856 return col;
6857}

References Config_getInt, and getUTF8CharNumBytes().

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

◆ updateLanguageMapping()

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

Definition at line 5042 of file util.cpp.

5043{
5044 QCString langName = language.lower();
5045 auto it1 = std::find_if(g_lang2extMap.begin(),g_lang2extMap.end(),
5046 [&langName](const auto &info) { return info.langName==langName; });
5047 if (it1 == g_lang2extMap.end()) return false;
5048
5049 // found the language
5050 SrcLangExt parserId = it1->parserId;
5051 QCString extName = extension.lower();
5052 if (extName.isEmpty()) return FALSE;
5053 if (extName.at(0)!='.') extName.prepend(".");
5054 auto it2 = g_extLookup.find(extName.str());
5055 if (it2!=g_extLookup.end())
5056 {
5057 g_extLookup.erase(it2); // language was already register for this ext
5058 }
5059 //printf("registering extension %s\n",qPrint(extName));
5060 g_extLookup.emplace(extName.str(),parserId);
5061 if (!Doxygen::parserManager->registerExtension(extName,it1->parserName))
5062 {
5063 err("Failed to assign extension {} to parser {} for language {}\n",
5064 extName.data(),it1->parserName,language);
5065 }
5066 else
5067 {
5068 //msg("Registered extension {} to language parser {}...\n",
5069 // extName,language);
5070 }
5071 return TRUE;
5072}
SrcLangExt
Definition types.h:207

References QCString::at(), QCString::data(), err, FALSE, g_extLookup, g_lang2extMap, QCString::isEmpty(), QCString::lower(), Doxygen::parserManager, QCString::prepend(), QCString::str(), and TRUE.

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

◆ writeColoredImgData()

void writeColoredImgData ( const QCString & dir,
ColoredImgDataItem data[] )

Writes the intensity only bitmap represented by data as an image to directory dir using the colors defined by HTML_COLORSTYLE_*.

Definition at line 5734 of file util.cpp.

5735{
5736 int hue = Config_getInt(HTML_COLORSTYLE_HUE);
5737 int sat = Config_getInt(HTML_COLORSTYLE_SAT);
5738 int gamma = Config_getInt(HTML_COLORSTYLE_GAMMA);
5739 while (data->name)
5740 {
5741 QCString fileName = dir+"/"+data->name;
5742 ColoredImage img(data->width,data->height,data->content,data->alpha,
5743 sat,hue,gamma);
5744 if (!img.save(fileName))
5745 {
5746 fprintf(stderr,"Warning: Cannot open file %s for writing\n",data->name);
5747 }
5748 Doxygen::indexList->addImageFile(data->name);
5749 data++;
5750 }
5751}
Class representing a bitmap image colored based on hue/sat/gamma settings.
Definition image.h:56
static IndexList * indexList
Definition doxygen.h:133
const unsigned char * content
Definition util.h:417
unsigned short height
Definition util.h:416
const unsigned char * alpha
Definition util.h:418
unsigned short width
Definition util.h:415
const char * name
Definition util.h:414

References ColoredImgDataItem::alpha, Config_getInt, ColoredImgDataItem::content, ColoredImgDataItem::height, Doxygen::indexList, ColoredImgDataItem::name, ColoredImage::save(), and ColoredImgDataItem::width.

◆ writeExamples()

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

Definition at line 1124 of file util.cpp.

1125{
1126 auto replaceFunc = [&list,&ol](size_t entryIndex)
1127 {
1128 const auto &e = list[entryIndex];
1129 ol.pushGeneratorState();
1133 // link for Html / man
1134 //printf("writeObjectLink(file=%s)\n",qPrint(e->file));
1135 ol.writeObjectLink(QCString(),e.file,e.anchor,e.name);
1136 ol.popGeneratorState();
1137
1138 ol.pushGeneratorState();
1141 // link for Latex / pdf with anchor because the sources
1142 // are not hyperlinked (not possible with a verbatim environment).
1143 ol.writeObjectLink(QCString(),e.file,QCString(),e.name);
1144 ol.popGeneratorState();
1145 };
1146
1147 writeMarkerList(ol, theTranslator->trWriteList(static_cast<int>(list.size())).str(), list.size(), replaceFunc);
1148
1149 ol.writeString(".");
1150}
void writeString(const QCString &text)
Definition outputlist.h:411
void disable(OutputType o)
void pushGeneratorState()
void popGeneratorState()
void writeMarkerList(OutputList &ol, const std::string &markerText, size_t numMarkers, std::function< void(size_t)> replaceFunc)
Definition util.cpp:1100

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

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

◆ writeMarkerList()

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

Definition at line 1100 of file util.cpp.

1102{
1103 static const reg::Ex marker(R"(@(\d+))");
1104 reg::Iterator it(markerText,marker);
1106 size_t index=0;
1107 // now replace all markers in inheritLine with links to the classes
1108 for ( ; it!=end ; ++it)
1109 {
1110 const auto &match = *it;
1111 size_t newIndex = match.position();
1112 size_t matchLen = match.length();
1113 ol.parseText(markerText.substr(index,newIndex-index));
1114 unsigned long entryIndex = std::stoul(match[1].str());
1115 if (entryIndex<static_cast<unsigned long>(numMarkers))
1116 {
1117 replaceFunc(entryIndex);
1118 }
1119 index=newIndex+matchLen;
1120 }
1121 ol.parseText(markerText.substr(index));
1122}
void parseText(const QCString &textStr)

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

Referenced by MemberDefImpl::_writeReimplementedBy(), DefinitionImpl::_writeSourceRefList(), writeExamples(), and ClassDefImpl::writeInheritanceGraph().

◆ writePageRef()

void writePageRef ( OutputList & ol,
const QCString & cn,
const QCString & mn )

◆ writeTypeConstraints()

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

Definition at line 5395 of file util.cpp.

5396{
5397 if (al.empty()) return;
5398 ol.startConstraintList(theTranslator->trTypeConstraints());
5399 for (const Argument &a : al)
5400 {
5402 ol.parseText(a.name);
5403 ol.endConstraintParam();
5405 linkifyText(TextGeneratorOLImpl(ol),d,nullptr,nullptr,a.type);
5406 ol.endConstraintType();
5408 ol.generateDoc(d->docFile(),
5409 d->docLine(),
5410 d,
5411 nullptr,
5412 a.docs,
5413 DocOptions()
5414 .setIndexWords(true));
5415 ol.endConstraintDocs();
5416 }
5417 ol.endConstraintList();
5418}
virtual int docLine() const =0
void endConstraintType()
Definition outputlist.h:714
void endConstraintList()
Definition outputlist.h:720
void startConstraintParam()
Definition outputlist.h:708
void generateDoc(const QCString &fileName, int startLine, const Definition *ctx, const MemberDef *md, const QCString &docStr, const DocOptions &options)
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 startConstraintList(const QCString &header)
Definition outputlist.h:706
Implements TextGeneratorIntf for an OutputDocInterface stream.
Definition util.h:76
void linkifyText(const TextGeneratorIntf &out, const Definition *scope, const FileDef *fileScope, const Definition *self, const QCString &text, bool autoBreak, bool external, bool keepSpaces, int indentLevel)
Definition util.cpp:894

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(), and theTranslator.

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