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, bool skipFirstLine=true)
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 5153 of file util.cpp.

5154{
5155 updateLanguageMapping(".xml", "xml");
5156 updateLanguageMapping(".sql", "sql");
5157}
bool updateLanguageMapping(const QCString &extension, const QCString &language)
Definition util.cpp:5054

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

4876{
4877 if (fName.isEmpty()) return;
4878 int i_fs = fName.findRev('/');
4879 int i_bs = fName.findRev('\\');
4880 int i = fName.find('.',std::max({ i_fs, i_bs ,0})); // search for . after path part
4881 if (i==-1)
4882 {
4884 }
4885}
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 4051 of file util.cpp.

4054{
4055 ASSERT(context!=nullptr);
4056 //printf("addMemberToMemberGroup() context=%s\n",qPrint(context->name()));
4057 if (ml==nullptr) return;
4058
4059 struct MoveMemberInfo
4060 {
4061 MoveMemberInfo(MemberDef *md,MemberGroup *mg,const RefItemVector &rv)
4062 : memberDef(md), memberGroup(mg), sli(rv) {}
4063 MemberDef *memberDef;
4064 MemberGroup *memberGroup;
4065 RefItemVector sli;
4066 };
4067 std::vector<MoveMemberInfo> movedMembers;
4068
4069 for (const auto &md : *ml)
4070 {
4071 if (md->isEnumerate()) // insert enum value of this enum into groups
4072 {
4073 for (const auto &fmd : md->enumFieldList())
4074 {
4075 int groupId=fmd->getMemberGroupId();
4076 if (groupId!=-1)
4077 {
4078 auto it = Doxygen::memberGroupInfoMap.find(groupId);
4080 {
4081 const auto &info = it->second;
4082 auto mg_it = std::find_if(pMemberGroups->begin(),
4083 pMemberGroups->end(),
4084 [&groupId](const auto &g)
4085 { return g->groupId()==groupId; }
4086 );
4087 MemberGroup *mg_ptr = nullptr;
4088 if (mg_it==pMemberGroups->end())
4089 {
4090 auto mg = std::make_unique<MemberGroup>(
4091 context,
4092 groupId,
4093 info->header,
4094 info->doc,
4095 info->docFile,
4096 info->docLine,
4097 ml->container());
4098 mg_ptr = mg.get();
4099 pMemberGroups->push_back(std::move(mg));
4100 }
4101 else
4102 {
4103 mg_ptr = (*mg_it).get();
4104 }
4105 mg_ptr->insertMember(fmd); // insert in member group
4107 if (fmdm)
4108 {
4109 fmdm->setMemberGroup(mg_ptr);
4110 }
4111 }
4112 }
4113 }
4114 }
4115 int groupId=md->getMemberGroupId();
4116 if (groupId!=-1)
4117 {
4118 auto it = Doxygen::memberGroupInfoMap.find(groupId);
4120 {
4121 const auto &info = it->second;
4122 auto mg_it = std::find_if(pMemberGroups->begin(),
4123 pMemberGroups->end(),
4124 [&groupId](const auto &g)
4125 { return g->groupId()==groupId; }
4126 );
4127 MemberGroup *mg_ptr = nullptr;
4128 if (mg_it==pMemberGroups->end())
4129 {
4130 auto mg = std::make_unique<MemberGroup>(
4131 context,
4132 groupId,
4133 info->header,
4134 info->doc,
4135 info->docFile,
4136 info->docLine,
4137 ml->container());
4138 mg_ptr = mg.get();
4139 pMemberGroups->push_back(std::move(mg));
4140 }
4141 else
4142 {
4143 mg_ptr = (*mg_it).get();
4144 }
4145 movedMembers.emplace_back(md,mg_ptr,info->m_sli);
4146 }
4147 }
4148 }
4149
4150 // move the members to their group
4151 for (const auto &mmi : movedMembers)
4152 {
4153 ml->remove(mmi.memberDef); // remove from member list
4154 mmi.memberGroup->insertMember(mmi.memberDef->resolveAlias()); // insert in member group
4155 mmi.memberGroup->setRefItems(mmi.sli);
4156 MemberDefMutable *rmdm = toMemberDefMutable(mmi.memberDef);
4157 if (rmdm)
4158 {
4159 rmdm->setMemberGroup(mmi.memberGroup);
4160 }
4161 }
4162}
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 4778 of file util.cpp.

4781{
4782 //printf("addRefItem(sli=%d,key=%s,prefix=%s,name=%s,title=%s,args=%s)\n",(int)sli.size(),key,prefix,name,title,args);
4783 if (!key.isEmpty() && key[0]!='@') // check for @ to skip anonymous stuff (see bug427012)
4784 {
4785 for (RefItem *item : sli)
4786 {
4787 item->setPrefix(prefix);
4788 item->setScope(scope);
4789 item->setName(name);
4790 item->setTitle(title);
4791 item->setArgs(args);
4792 item->setGroup(key);
4793 }
4794 }
4795}
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 4648 of file util.cpp.

4659{
4660 PageDef *pd=nullptr;
4661 //printf("addRelatedPage(name=%s gd=%p)\n",qPrint(name),gd);
4662 QCString title=ptitle.stripWhiteSpace();
4663 bool newPage = true;
4664 if ((pd=Doxygen::pageLinkedMap->find(name)) && !pd->isReference())
4665 {
4666 if (!xref && !title.isEmpty() && pd->title()!=pd->name() && pd->title()!=title)
4667 {
4668 warn(fileName,startLine,"multiple use of page label '{}' with different titles, (other occurrence: {}, line: {})",
4669 name,pd->docFile(),pd->getStartBodyLine());
4670 }
4671 if (!title.isEmpty() && pd->title()==pd->name()) // pd has no real title yet
4672 {
4673 pd->setTitle(title);
4675 if (si)
4676 {
4677 si->setTitle(title);
4678 }
4679 }
4680 // append documentation block to the page.
4681 pd->setDocumentation(doc,fileName,docLine);
4682 //printf("Adding page docs '%s' pi=%p name=%s\n",qPrint(doc),pd,name);
4683 // append (x)refitems to the page.
4684 pd->setRefItems(sli);
4685 newPage = false;
4686 }
4687
4688 if (newPage) // new page
4689 {
4690 QCString baseName=name;
4691 if (baseName.endsWith(".tex"))
4692 baseName=baseName.left(baseName.length()-4);
4693 else if (baseName.right(Doxygen::htmlFileExtension.length())==Doxygen::htmlFileExtension)
4694 baseName=baseName.left(baseName.length()-Doxygen::htmlFileExtension.length());
4695
4696 //printf("Appending page '%s'\n",qPrint(baseName));
4697 if (pd) // replace existing page
4698 {
4699 pd->setDocumentation(doc,fileName,docLine);
4701 pd->setShowLineNo(FALSE);
4702 pd->setNestingLevel(0);
4703 pd->setPageScope(nullptr);
4704 pd->setTitle(title);
4705 pd->setReference(QCString());
4706 }
4707 else // newPage
4708 {
4709 pd = Doxygen::pageLinkedMap->add(baseName,
4710 createPageDef(fileName,docLine,baseName,doc,title));
4711 }
4712 pd->setBodySegment(startLine,startLine,-1);
4713
4714 pd->setRefItems(sli);
4715 pd->setLanguage(lang);
4716
4717 if (tagInfo)
4718 {
4719 pd->setReference(tagInfo->tagName);
4720 pd->setFileName(tagInfo->fileName);
4721 }
4722
4723 if (gd) gd->addPage(pd);
4724
4725 if (pd->hasTitle())
4726 {
4727 //outputList->writeTitle(pi->name,pi->title);
4728
4729 // a page name is a label as well!
4730 QCString file;
4731 QCString orgFile;
4732 int line = -1;
4733 if (gd)
4734 {
4735 file=gd->getOutputFileBase();
4736 orgFile=gd->getOutputFileBase();
4737 }
4738 else
4739 {
4740 file=pd->getOutputFileBase();
4741 orgFile=pd->docFile();
4742 line = pd->getStartBodyLine();
4743 }
4744 const SectionInfo *si = SectionManager::instance().find(pd->name());
4745 if (si)
4746 {
4747 if (!si->ref().isEmpty()) // we are from a tag file
4748 {
4750 file,-1,pd->title(),SectionType::Page,0,pd->getReference());
4751 }
4752 else if (si->lineNr() != -1)
4753 {
4754 warn(orgFile,line,"multiple use of section label '{}', (first occurrence: {}, line {})",pd->name(),si->fileName(),si->lineNr());
4755 }
4756 else
4757 {
4758 warn(orgFile,line,"multiple use of section label '{}', (first occurrence: {})",pd->name(),si->fileName());
4759 }
4760 }
4761 else
4762 {
4764 file,-1,pd->title(),SectionType::Page,0,pd->getReference());
4765 //printf("si->label='%s' si->definition=%s si->fileName='%s'\n",
4766 // qPrint(si->label),si->definition?si->definition->name().data():"<none>",
4767 // qPrint(si->fileName));
4768 //printf(" SectionInfo: sec=%p sec->fileName=%s\n",si,qPrint(si->fileName));
4769 //printf("Adding section key=%s si->fileName=%s\n",qPrint(pageName),qPrint(si->fileName));
4770 }
4771 }
4772 }
4773 return pd;
4774}
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:3458

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

1205{
1206 QCString result;
1207 if (!al.hasParameters()) return result;
1208 result+="(";
1209 for (auto it = al.begin() ; it!=al.end() ;)
1210 {
1211 Argument a = *it;
1212 QCString type1 = useCanonicalType && !a.canType.isEmpty() ? a.canType : a.type;
1213 QCString type2;
1214 int i=type1.find(")("); // hack to deal with function pointers
1215 if (i!=-1)
1216 {
1217 type2=type1.mid(i);
1218 type1=type1.left(i);
1219 }
1220 if (!a.attrib.isEmpty())
1221 {
1222 result+=a.attrib+" ";
1223 }
1224 if (!a.name.isEmpty() || !a.array.isEmpty())
1225 {
1226 result+= type1+" "+a.name+type2+a.array;
1227 }
1228 else
1229 {
1230 result+= type1+type2;
1231 }
1232 if (!a.defval.isEmpty() && showDefVals)
1233 {
1234 result+="="+a.defval;
1235 }
1236 ++it;
1237 if (it!=al.end()) result+=", ";
1238 }
1239 result+=")";
1240 if (al.constSpecifier()) result+=" const";
1241 if (al.volatileSpecifier()) result+=" volatile";
1242 if (al.refQualifier()==RefQualifierType::LValue) result+=" &";
1243 else if (al.refQualifier()==RefQualifierType::RValue) result+=" &&";
1244 if (!al.trailingReturnType().isEmpty()) result+=al.trailingReturnType();
1245 if (al.pureSpecifier()) result+=" =0";
1246 return removeRedundantWhiteSpace(result);
1247}
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 6486 of file util.cpp.

6487{
6488 if (s.isEmpty()) return;
6489
6490 const char *p = s.data();
6491 char c = 0;
6492 while ((c=*p))
6493 {
6494 if (c==markerInfo.markerChar) // potential start of marker
6495 {
6496 if (qstrncmp(p,markerInfo.beginStr,markerInfo.beginLen)==0) // start of begin marker
6497 {
6498 size_t len = markerInfo.beginLen;
6499 bool negate = *(p+len)=='!';
6500 if (negate) len++;
6501 p += len;
6502 QCString marker;
6503 while (*p)
6504 {
6505 if (markerInfo.closeLen==0 && *p=='\n') // matching end of line
6506 {
6507 warn(fileName,-1,"Remaining begin replacement with marker '{}'",marker);
6508 break;
6509 }
6510 else if (markerInfo.closeLen!= 0 && qstrncmp(p,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6511 {
6512 p += markerInfo.closeLen;
6513 warn(fileName,-1,"Remaining begin replacement with marker '{}'",marker);
6514 break;
6515 }
6516 marker += *p;
6517 p++;
6518 }
6519 }
6520 else if (qstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // start of end marker
6521 {
6522 size_t len = markerInfo.endLen;
6523 bool negate = *(p+len)=='!';
6524 if (negate) len++;
6525 p += len;
6526 QCString marker;
6527 while (*p)
6528 {
6529 if (markerInfo.closeLen==0 && *p=='\n') // matching end of line
6530 {
6531 warn(fileName,-1,"Remaining end replacement with marker '{}'",marker);
6532 break;
6533 }
6534 else if (markerInfo.closeLen!= 0 && qstrncmp(p,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6535 {
6536 p += markerInfo.closeLen;
6537 warn(fileName,-1,"Remaining end replacement with marker '{}'",marker);
6538 break;
6539 }
6540 marker += *p;
6541 p++;
6542 }
6543 }
6544 }
6545 p++;
6546 }
6547}
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 4870 of file util.cpp.

4871{
4872 return fName.right(ext.length())==ext;
4873}

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

5264{
5265 MemberDef *bestMatch = getMemberFromSymbol(scope,fileScope,n);
5266
5267 if (bestMatch && bestMatch->isTypedef())
5268 return TRUE; // closest matching symbol is a typedef
5269 else
5270 return FALSE;
5271}
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:5211

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

Referenced by isVarWithConstructor().

◆ clearSubDirs()

void clearSubDirs ( const Dir & d)

Definition at line 3621 of file util.cpp.

3622{
3623 if (Config_getBool(CREATE_SUBDIRS))
3624 {
3625 // remove empty subdirectories
3626 int createSubdirsLevelPow2 = 1 << Config_getInt(CREATE_SUBDIRS_LEVEL);
3627 for (int l1=0;l1<16;l1++)
3628 {
3629 QCString subdir;
3630 subdir.sprintf("d%x",l1);
3631 for (int l2=0; l2 < createSubdirsLevelPow2; l2++)
3632 {
3633 QCString subsubdir;
3634 subsubdir.sprintf("d%x/d%02x",l1,l2);
3635 if (d.exists(subsubdir.str()) && d.isEmpty(subsubdir.str()))
3636 {
3637 d.rmdir(subsubdir.str());
3638 }
3639 }
3640 if (d.exists(subdir.str()) && d.isEmpty(subdir.str()))
3641 {
3642 d.rmdir(subdir.str());
3643 }
3644 }
3645 }
3646}
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 6788 of file util.cpp.

6789{
6790 int l = static_cast<int>(name.length());
6791 int lastSepPos = -1;
6792 const char *p = name.data();
6793 int i=l-2;
6794 int sharpCount=0;
6795 // --- begin optimized version of ts=name.findRev(">::");
6796 int ts = -1;
6797 while (i>=0)
6798 {
6799 if (p[i]=='>')
6800 {
6801 if (sharpCount==0 && p[i+1]==':' && p[i+2]==':')
6802 {
6803 ts=i;
6804 break;
6805 }
6806 sharpCount++;
6807 }
6808 else if (p[i]=='<')
6809 {
6810 sharpCount--;
6811 }
6812 i--;
6813 }
6814 // --- end optimized version
6815 if (ts==-1) ts=0; else p+=++ts;
6816 for (i=ts;i<l-1;i++)
6817 {
6818 char c=*p++;
6819 if (c==':' && *p==':') lastSepPos=i;
6820 if (c=='<') break;
6821 }
6822 return lastSepPos;
6823}

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

4920{
4921 if (str.isEmpty() || word==nullptr) return false;
4922 static const reg::Ex re(R"(\a+)");
4923 std::string s = str.str();
4924 for (reg::Iterator it(s,re) ; it!=reg::Iterator() ; ++it)
4925 {
4926 if (it->str()==word) return true;
4927 }
4928 return false;
4929}
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 4001 of file util.cpp.

4002{
4003 if (str.isEmpty()) return QCString();
4004
4005 std::string s = str.data();
4006 static const reg::Ex re(R"(&\a\w*;)");
4007 reg::Iterator it(s,re);
4009
4010 QCString result;
4011 result.reserve(str.length()+32);
4012 size_t p=0, i=0, l=0;
4013 for (; it!=end ; ++it)
4014 {
4015 const auto &match = *it;
4016 p = match.position();
4017 l = match.length();
4018 if (p>i)
4019 {
4020 result+=s.substr(i,p-i);
4021 }
4022 QCString entity(match.str());
4024 const char *code=nullptr;
4025 if (symType!=HtmlEntityMapper::Sym_Unknown && (code=HtmlEntityMapper::instance().utf8(symType)))
4026 {
4027 result+=code;
4028 }
4029 else
4030 {
4031 result+=entity;
4032 }
4033 i=p+l;
4034 }
4035 result+=s.substr(i);
4036 //printf("convertCharEntitiesToUTF8(%s)->%s\n",qPrint(s),qPrint(result));
4037 return result;
4038}
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 6360 of file util.cpp.

6361{
6363 QCString parserName = Doxygen::parserManager->getParserName(ext);
6364
6365 if (parserName == "fortranfixed") return FortranFormat::Fixed;
6366 else if (parserName == "fortranfree") return FortranFormat::Free;
6367
6369}
static ParserManager * parserManager
Definition doxygen.h:130
QCString getFileNameExtension(const QCString &fn)
Definition util.cpp:5201

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

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

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

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

6199{
6200 bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
6201
6202 // default representing 1-1 mapping
6203 *outListType1=inListType;
6204 *outListType2=MemberListType::Invalid();
6205
6206 if (inProt==Protection::Public)
6207 {
6208 if (inListType.isPrivate())
6209 {
6210 *outListType1=MemberListType::Invalid();
6211 }
6212 }
6213 else if (inProt==Protection::Protected)
6214 {
6215 if (inListType.isPrivate() || inListType.isPublic())
6216 {
6217 *outListType1=MemberListType::Invalid();
6218 }
6219 else if (inListType.isProtected())
6220 {
6221 *outListType2=inListType.toPublic();
6222 }
6223 }
6224 else if (inProt==Protection::Private)
6225 {
6226 if (inListType.isPublic() || inListType.isProtected())
6227 {
6228 *outListType1=MemberListType::Invalid();
6229 }
6230 else if (inListType.isPrivate())
6231 {
6232 if (extractPrivate)
6233 {
6234 *outListType1=inListType.toPublic();
6235 *outListType2=inListType.toProtected();
6236 }
6237 else
6238 {
6239 *outListType1=MemberListType::Invalid();
6240 }
6241 }
6242 }
6243
6244 //printf("convertProtectionLevel(type=%s prot=%d): %s,%s\n",
6245 // qPrint(inListType.to_string()),inProt,qPrint(outListType1->to_string()),qPrint(outListType2->to_string()));
6246}
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 3917 of file util.cpp.

3918{
3919 if (s.isEmpty()) return s;
3920 QCString result;
3921 result.reserve(s.length()+32);
3922 const char *p=s.data();
3923 char c = 0;
3924 while ((c=*p++))
3925 {
3926 switch (c)
3927 {
3928 case '<': result+="&lt;"; break;
3929 case '>': result+="&gt;"; break;
3930 case '&': if (keepEntities)
3931 {
3932 const char *e=p;
3933 char ce = 0;
3934 while ((ce=*e++))
3935 {
3936 if (ce==';' || (!(isId(ce) || ce=='#'))) break;
3937 }
3938 if (ce==';') // found end of an entity
3939 {
3940 // copy entry verbatim
3941 result+=c;
3942 while (p<e) result+=*p++;
3943 }
3944 else
3945 {
3946 result+="&amp;";
3947 }
3948 }
3949 else
3950 {
3951 result+="&amp;";
3952 }
3953 break;
3954 case '\'': result+="&#39;"; break;
3955 case '"': result+="&quot;"; break;
3956 default:
3957 {
3958 uint8_t uc = static_cast<uint8_t>(c);
3959 if (uc<32 && !isspace(c))
3960 {
3961 result+="&#x24";
3962 result+=hex[uc>>4];
3963 result+=hex[uc&0xF];
3964 result+=';';
3965 }
3966 else
3967 {
3968 result+=c;
3969 }
3970 }
3971 break;
3972 }
3973 }
3974 return result;
3975}
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 3826 of file util.cpp.

3827{
3828 if (s.isEmpty()) return s;
3829 QCString result;
3830 result.reserve(s.length()+8);
3831 const char *p = s.data();
3832 char c = 0;
3833 bool first = true;
3834 while ((c=*p++))
3835 {
3836 char encChar[4];
3837 if ((c>='0' && c<='9') || (c>='a' && c<='z') || (c>='A' && c<='Z') || c=='-')
3838 { // any permissive character except _
3839 if (first && c>='0' && c<='9') result+='a'; // don't start with a digit
3840 result+=c;
3841 }
3842 else
3843 {
3844 encChar[0]='_';
3845 encChar[1]=hex[static_cast<unsigned char>(c)>>4];
3846 encChar[2]=hex[static_cast<unsigned char>(c)&0xF];
3847 encChar[3]=0;
3848 result+=encChar;
3849 }
3850 first=false;
3851 }
3852 return result;
3853}

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

3978{
3979 if (s.isEmpty()) return s;
3980 QCString result;
3981 result.reserve(s.length()+32);
3982 const char *p=s.data();
3983 char c = 0;
3984 while ((c=*p++))
3985 {
3986 switch (c)
3987 {
3988 case '"': if (!singleQuotes) result+="\\\""; else result+=c;
3989 break;
3990 case '\'': if (singleQuotes) result+="\\\'"; else result+=c;
3991 break;
3992 case '\\': if (*p=='u' && *(p+1)=='{') result+="\\"; // keep \u{..} unicode escapes
3993 else result+="\\\\";
3994 break;
3995 default: result+=c; break;
3996 }
3997 }
3998 return keepEntities ? result : convertCharEntitiesToUTF8(result);
3999}
QCString convertCharEntitiesToUTF8(const QCString &str)
Definition util.cpp:4001

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

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

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

3860{
3861 if (s.isEmpty()) return s;
3862 return "a" + s;
3863}

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

5890{
5891 QCString result = url;
5892 if (!relPath.isEmpty() && !isURL(url))
5893 {
5894 result.prepend(relPath);
5895 }
5896 return result;
5897}
bool isURL(const QCString &url)
Checks whether the given url starts with a supported protocol.
Definition util.cpp:5877

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

5690{
5691 QCString url;
5692 if (!ref.isEmpty())
5693 {
5694 url = externalRef(relPath,ref,href);
5695 }
5696 if (!targetFileName.isEmpty())
5697 {
5698 QCString fn = targetFileName;
5699 if (ref.isEmpty())
5700 {
5701 if (!anchor.isEmpty() && isLocalFile)
5702 {
5703 fn=""; // omit file name for local links
5704 }
5705 else
5706 {
5707 url = relPath;
5708 }
5709 }
5710 url+=fn;
5711 }
5712 if (!anchor.isEmpty()) url+="#"+anchor;
5713 //printf("createHtmlUrl(relPath=%s,local=%d,target=%s,anchor=%s)=%s\n",qPrint(relPath),isLocalFile,qPrint(targetFileName),qPrint(anchor),qPrint(url));
5714 return url;
5715}
QCString externalRef(const QCString &relPath, const QCString &ref, bool href)
Definition util.cpp:5717

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

3595{
3596 if (Config_getBool(CREATE_SUBDIRS))
3597 {
3598 // create up to 4096 subdirectories
3599 int createSubdirsLevelPow2 = 1 << Config_getInt(CREATE_SUBDIRS_LEVEL);
3600 for (int l1=0; l1<16; l1++)
3601 {
3602 QCString subdir;
3603 subdir.sprintf("d%x",l1);
3604 if (!d.exists(subdir.str()) && !d.mkdir(subdir.str()))
3605 {
3606 term("Failed to create output directory '{}'\n",subdir);
3607 }
3608 for (int l2=0; l2<createSubdirsLevelPow2; l2++)
3609 {
3610 QCString subsubdir;
3611 subsubdir.sprintf("d%x/d%02x",l1,l2);
3612 if (!d.exists(subsubdir.str()) && !d.mkdir(subsubdir.str()))
3613 {
3614 term("Failed to create output directory '{}'\n",subsubdir);
3615 }
3616 }
3617 }
3618 }
3619}
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 6887 of file util.cpp.

6888{
6889 QCString result=name;
6890 if (result.endsWith("-g"))
6891 {
6892 int idx = result.find('-');
6893 result = result.left(idx)+templArgs;
6894 }
6895 return result;
6896}

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

Referenced by ClassDefImpl::className().

◆ detab()

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

Definition at line 6684 of file util.cpp.

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

3555{
3556 bool searchIncludes = Config_getBool(SEARCH_INCLUDES);
3557 QCString absIncFileName = incFileName;
3558 FileInfo fi(curFile.str());
3559 if (fi.exists())
3560 {
3561 QCString absName = fi.dirPath(TRUE)+"/"+incFileName;
3562 FileInfo fi2(absName.str());
3563 if (fi2.exists())
3564 {
3565 absIncFileName=fi2.absFilePath();
3566 }
3567 else if (searchIncludes) // search in INCLUDE_PATH as well
3568 {
3569 const StringVector &includePath = Config_getList(INCLUDE_PATH);
3570 for (const auto &incPath : includePath)
3571 {
3572 FileInfo fi3(incPath);
3573 if (fi3.exists() && fi3.isDir())
3574 {
3575 absName = fi3.absFilePath()+"/"+incFileName;
3576 //printf("trying absName=%s\n",qPrint(absName));
3577 FileInfo fi4(absName.str());
3578 if (fi4.exists())
3579 {
3580 absIncFileName=fi4.absFilePath();
3581 break;
3582 }
3583 //printf( "absIncFileName = %s\n", qPrint(absIncFileName) );
3584 }
3585 }
3586 }
3587 //printf( "absIncFileName = %s\n", qPrint(absIncFileName) );
3588 }
3589 return absIncFileName;
3590}
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 ModuleManager::resolveImports().

◆ escapeCharsInString()

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

Definition at line 3283 of file util.cpp.

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

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

5674{
5675 bool extLinksInWindow = Config_getBool(EXT_LINKS_IN_WINDOW);
5676 if (extLinksInWindow)
5677 return "target=\"_blank\" ";
5678 else if (parent)
5679 return "target=\"_parent\" ";
5680 else
5681 return "";
5682}
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 5717 of file util.cpp.

5718{
5719 QCString result;
5720 if (!ref.isEmpty())
5721 {
5722 auto it = Doxygen::tagDestinationMap.find(ref.str());
5724 {
5725 result = it->second;
5726 size_t l = result.length();
5727 if (!relPath.isEmpty() && l>0 && result.at(0)=='.')
5728 { // relative path -> prepend relPath.
5729 result.prepend(relPath);
5730 l+=relPath.length();
5731 }
5732 if (l>0 && result.at(l-1)!='/') result+='/';
5733 if (!href) result.append("\" ");
5734 }
5735 }
5736 else
5737 {
5738 result = relPath;
5739 }
5740 return result;
5741}
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 6898 of file util.cpp.

6899{
6900 QCString text=rawStart;
6901 int i = text.find('"');
6902 assert(i!=-1);
6903 return text.mid(i+1,text.length()-i-2); // text=...R"xyz( -> delimiter=xyz
6904}

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

4170{
4171 AUTO_TRACE("type='{}' name='{}' lang={}",type,name,lang);
4172 static const reg::Ex re_norm(R"(\a[\w:]*)");
4173 static const reg::Ex re_fortran(R"(\a[\w:()=]*)");
4174 const reg::Ex *re = &re_norm;
4175
4176 name.clear();
4177 templSpec.clear();
4178 if (type.isEmpty())
4179 {
4180 AUTO_TRACE_EXIT("empty type");
4181 return -1;
4182 }
4183 size_t typeLen=type.length();
4184 if (typeLen>0)
4185 {
4186 if (lang == SrcLangExt::Fortran)
4187 {
4188 if (type[pos]==',')
4189 {
4190 AUTO_TRACE_EXIT("comma");
4191 return -1;
4192 }
4193 if (!type.lower().startsWith("type"))
4194 {
4195 re = &re_fortran;
4196 }
4197 }
4198 std::string s = type.str();
4199 reg::Iterator it(s,*re,static_cast<int>(pos));
4201
4202 if (it!=end)
4203 {
4204 const auto &match = *it;
4205 size_t i = match.position();
4206 size_t l = match.length();
4207 size_t ts = i+l;
4208 size_t te = ts;
4209 size_t tl = 0;
4210
4211 while (ts<typeLen && type[static_cast<uint32_t>(ts)]==' ') { ts++; tl++; } // skip any whitespace
4212 if (ts<typeLen && type[static_cast<uint32_t>(ts)]=='<') // assume template instance
4213 {
4214 // locate end of template
4215 te=ts+1;
4216 int brCount=1;
4217 while (te<typeLen && brCount!=0)
4218 {
4219 if (type[static_cast<uint32_t>(te)]=='<')
4220 {
4221 if (te<typeLen-1 && type[static_cast<uint32_t>(te)+1]=='<') te++; else brCount++;
4222 }
4223 if (type[static_cast<uint32_t>(te)]=='>')
4224 {
4225 if (te<typeLen-1 && type[static_cast<uint32_t>(te)+1]=='>') te++; else brCount--;
4226 }
4227 te++;
4228 }
4229 }
4230 name = match.str();
4231 if (te>ts)
4232 {
4233 templSpec = QCString(type).mid(ts,te-ts);
4234 tl+=te-ts;
4235 pos=static_cast<int>(i+l+tl);
4236 }
4237 else // no template part
4238 {
4239 pos=static_cast<int>(i+l);
4240 }
4241 //printf("extractClassNameFromType([in] type=%s,[out] pos=%d,[out] name=%s,[out] templ=%s)=TRUE i=%d\n",
4242 // qPrint(type),pos,qPrint(name),qPrint(templSpec),i);
4243 AUTO_TRACE_EXIT("pos={} templSpec='{}' return={}",pos,templSpec,i);
4244 return static_cast<int>(i);
4245 }
4246 }
4247 pos = static_cast<int>(typeLen);
4248 //printf("extractClassNameFromType([in] type=%s,[out] pos=%d,[out] name=%s,[out] templ=%s)=FALSE\n",
4249 // qPrint(type),pos,qPrint(name),qPrint(templSpec));
4250 AUTO_TRACE_EXIT("not found");
4251 return -1;
4252}
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(), and findUsedClassesForClass().

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

6143{
6144 std::string s = docs.str();
6145 static const reg::Ex re(R"(\‍[([ inout,]+)\‍])");
6146 reg::Iterator it(s,re);
6148 if (it!=end)
6149 {
6150 const auto &match = *it;
6151 size_t p = match.position();
6152 size_t l = match.length();
6153 if (p==0 && l>2)
6154 {
6155 // make dir the part inside [...] without separators
6156 std::string dir = match[1].str();
6157 // strip , and ' ' from dir
6158 dir.erase(std::remove_if(dir.begin(),dir.end(),
6159 [](const char c) { return c==' ' || c==','; }
6160 ),dir.end());
6161 unsigned char ioMask=0;
6162 size_t inIndex = dir.find( "in");
6163 if ( inIndex!=std::string::npos) { dir.erase( inIndex,2); ioMask|=(1<<0); }
6164 size_t outIndex = dir.find("out");
6165 if (outIndex!=std::string::npos) { dir.erase(outIndex,3); ioMask|=(1<<1); }
6166 if (dir.empty() && ioMask!=0) // only in and/or out attributes found
6167 {
6168 docs = s.substr(l); // strip attributes
6169 if (ioMask==((1<<0)|(1<<1))) return "[in,out]";
6170 else if (ioMask==(1<<0)) return "[in]";
6171 else if (ioMask==(1<<1)) return "[out]";
6172 }
6173 }
6174 }
6175 return "";
6176}

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

Referenced by inlineArgListToDoc().

◆ extractEndRawStringDelimiter()

QCString extractEndRawStringDelimiter ( const char * rawEnd)

Definition at line 6906 of file util.cpp.

6907{
6908 QCString text=rawEnd;
6909 return text.mid(1,text.length()-2); // text=)xyz" -> delimiter=xyz
6910}

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

3654{
3655 int i=0, p=0;
3656 QCString clName=scopeName;
3657 NamespaceDef *nd = nullptr;
3658 if (!clName.isEmpty() && (nd=getResolvedNamespace(clName)) && getClass(clName)==nullptr)
3659 { // the whole name is a namespace (and not a class)
3660 namespaceName=nd->name();
3661 className.clear();
3662 goto done;
3663 }
3664 p=static_cast<int>(clName.length())-2;
3665 while (p>=0 && (i=clName.findRev("::",p))!=-1)
3666 // see if the first part is a namespace (and not a class)
3667 {
3668 //printf("Trying %s\n",qPrint(clName.left(i)));
3669 if (i>0 && (nd=getResolvedNamespace(clName.left(i))) && getClass(clName.left(i))==nullptr)
3670 {
3671 //printf("found!\n");
3672 namespaceName=nd->name();
3673 className=clName.right(clName.length()-i-2);
3674 goto done;
3675 }
3676 p=i-2; // try a smaller piece of the scope
3677 }
3678 //printf("not found!\n");
3679
3680 // not found, so we just have to guess.
3681 className=scopeName;
3682 namespaceName.clear();
3683
3684done:
3685 if (className.isEmpty() && !namespaceName.isEmpty() && !allowEmptyClass)
3686 {
3687 // class and namespace with the same name, correct to return the class.
3688 className=namespaceName;
3689 namespaceName.clear();
3690 }
3691 //printf("extractNamespace '%s' => '%s|%s'\n",qPrint(scopeName),
3692 // qPrint(className),qPrint(namespaceName));
3693 if (className.endsWith("-p"))
3694 {
3695 className = className.left(className.length()-2);
3696 }
3697 return;
3698}
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 1444 of file util.cpp.

1445{
1446 if (name.isEmpty()) return QCString();
1447 bool fileOpened=false;
1448 if (name[0]=='-' && name[1]==0) // read from stdin
1449 {
1450 std::string contents;
1451 std::string line;
1452 while (getline(std::cin,line))
1453 {
1454 contents+=line+'\n';
1455 }
1456 return contents;
1457 }
1458 else // read from file
1459 {
1460 FileInfo fi(name.str());
1461 if (!fi.exists() || !fi.isFile())
1462 {
1463 err("file '{}' not found\n",name);
1464 return "";
1465 }
1466 std::string buf;
1467 fileOpened=readInputFile(name,buf,filter,isSourceCode);
1468 if (fileOpened)
1469 {
1470 addTerminalCharIfMissing(buf,'\n');
1471 return buf;
1472 }
1473 }
1474 if (!fileOpened)
1475 {
1476 err("cannot open file '{}' for reading\n",name);
1477 }
1478 return "";
1479}
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:5498

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

6054{
6055 bool allExternals = Config_getBool(ALLEXTERNALS);
6056 bool isDocFile = fd->isDocumentationFile();
6057 genSourceFile = !isDocFile && fd->generateSourceFile();
6058 return ( ((allExternals && fd->isLinkable()) ||
6060 ) &&
6061 !isDocFile
6062 );
6063}
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 5578 of file util.cpp.

5579{
5580 std::string tf;
5581 std::string t = title.str();
5582 static const reg::Ex re(R"(%[a-z_A-Z]+)");
5583 reg::Iterator it(t,re);
5585 size_t p = 0;
5586 for (; it!=end ; ++it)
5587 {
5588 const auto &match = *it;
5589 size_t i = match.position();
5590 size_t l = match.length();
5591 if (i>p) tf+=t.substr(p,i-p);
5592 tf+=match.str().substr(1); // skip %
5593 p=i+l;
5594 }
5595 tf+=t.substr(p);
5596 return tf;
5597}

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

4936{
4937 static reg::Ex re(R"(\s*(<\a+>)\s*)");
4938 std::string s = sentence.str();
4939 reg::Iterator it(s,re);
4941 std::string result;
4942 bool found=false;
4943 size_t p=0;
4944 for ( ; it!=end ; ++it)
4945 {
4946 const auto match = *it;
4947 std::string part = match[1].str();
4948 if (part!=word)
4949 {
4950 size_t i = match.position();
4951 size_t l = match.length();
4952 result+=s.substr(p,i-p);
4953 result+=match.str();
4954 p=i+l;
4955 }
4956 else
4957 {
4958 found=true;
4959 size_t i = match[1].position();
4960 size_t l = match[1].length();
4961 result+=s.substr(p,i-p);
4962 p=i+l;
4963 }
4964 }
4965 result+=s.substr(p);
4966 sentence = QCString(result).simplifyWhiteSpace();
4967 return found;
4968}
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 2844 of file util.cpp.

2845{
2846 ambig=FALSE;
2847 if (n.isEmpty()) return nullptr;
2848
2849
2850 const int maxAddrSize = 20;
2851 char addr[maxAddrSize];
2852 qsnprintf(addr,maxAddrSize,"%p:",reinterpret_cast<const void*>(fnMap));
2853 QCString key = addr;
2854 key+=n;
2855
2856 std::lock_guard<std::mutex> lock(g_findFileDefMutex);
2857 FindFileCacheElem *cachedResult = g_findFileDefCache.find(key.str());
2858 //printf("key=%s cachedResult=%p\n",qPrint(key),cachedResult);
2859 if (cachedResult)
2860 {
2861 ambig = cachedResult->isAmbig;
2862 //printf("cached: fileDef=%p\n",cachedResult->fileDef);
2863 return cachedResult->fileDef;
2864 }
2865 else
2866 {
2867 cachedResult = g_findFileDefCache.insert(key.str(),FindFileCacheElem(nullptr,FALSE));
2868 }
2869
2870 QCString name=Dir::cleanDirPath(n.str());
2871 QCString path;
2872 if (name.isEmpty()) return nullptr;
2873 int slashPos=std::max(name.findRev('/'),name.findRev('\\'));
2874 if (slashPos!=-1)
2875 {
2876 path=removeLongPathMarker(name.left(slashPos+1));
2877 name=name.right(name.length()-slashPos-1);
2878 }
2879 if (name.isEmpty()) return nullptr;
2880 const FileName *fn = fnMap->find(name);
2881 if (fn)
2882 {
2883 //printf("fn->size()=%zu\n",fn->size());
2884 if (fn->size()==1)
2885 {
2886 const std::unique_ptr<FileDef> &fd = fn->front();
2887 bool isSamePath = Portable::fileSystemIsCaseSensitive() ?
2888 fd->getPath().right(path.length())==path :
2889 fd->getPath().right(path.length()).lower()==path.lower();
2890 if (path.isEmpty() || isSamePath)
2891 {
2892 cachedResult->fileDef = fd.get();
2893 return fd.get();
2894 }
2895 }
2896 else // file name alone is ambiguous
2897 {
2898 int count=0;
2899 FileDef *lastMatch=nullptr;
2900 QCString pathStripped = stripFromIncludePath(path);
2901 for (const auto &fd_p : *fn)
2902 {
2903 FileDef *fd = fd_p.get();
2904 QCString fdStripPath = stripFromIncludePath(fd->getPath());
2905 if (path.isEmpty() ||
2906 (!pathStripped.isEmpty() && fdStripPath.endsWith(pathStripped)) ||
2907 (pathStripped.isEmpty() && fdStripPath.isEmpty()))
2908 {
2909 count++;
2910 lastMatch=fd;
2911 }
2912 }
2913
2914 ambig=(count>1);
2915 cachedResult->isAmbig = ambig;
2916 cachedResult->fileDef = lastMatch;
2917 return lastMatch;
2918 }
2919 }
2920 else
2921 {
2922 //printf("not found!\n");
2923 }
2924 return nullptr;
2925}
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:2834
FileDef * fileDef
Definition util.cpp:2836
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:2842
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(), findFilePath(), generateFileRef(), generateFileSources(), DocParser::handleLinkedWord(), DocbookDocVisitor::operator()(), XmlDocVisitor::operator()(), DocDiaFile::parse(), DocDotFile::parse(), DocMscFile::parse(), DocPlantUmlFile::parse(), parseFilesMultiThreading(), parseFilesSingleThreading(), Markdown::Private::processLink(), readTextFileByName(), ModuleManager::resolveImports(), resolveLink(), ModuleManager::resolvePartitions(), and resolveRef().

◆ findFilePath()

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

Definition at line 2929 of file util.cpp.

2930{
2931 ambig=false;
2932 QCString result;
2933 bool found=false;
2934 if (!found)
2935 {
2936 FileInfo fi(file.str());
2937 if (fi.exists())
2938 {
2939 result=fi.absFilePath();
2940 found=true;
2941 }
2942 }
2943 if (!found)
2944 {
2945 const StringVector &examplePathList = Config_getList(EXAMPLE_PATH);
2946 for (const auto &s : examplePathList)
2947 {
2948 std::string absFileName = s+(Portable::pathSeparator()+file).str();
2949 FileInfo fi(absFileName);
2950 if (fi.exists())
2951 {
2952 result=fi.absFilePath();
2953 found=true;
2954 }
2955 }
2956 }
2957
2958 if (!found)
2959 {
2960 // as a fallback we also look in the exampleNameDict
2962 if (fd && !ambig)
2963 {
2964 result=fd->absFilePath();
2965 }
2966 }
2967 return result;
2968}
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:2844

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

Referenced by 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 6626 of file util.cpp.

6627{
6629 return reg::search(s,match,re) ? static_cast<int>(match.position()) : -1;
6630}
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 6618 of file util.cpp.

6619{
6620 auto it = std::find(sv.begin(),sv.end(),s);
6621 return it!=sv.end() ? static_cast<int>(it-sv.begin()) : -1;
6622}

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

3513{
3514 QCString fn = stripFromPath(fileName)+":"+QCString().setNum(count);
3515 const int sig_size=16;
3516 uint8_t md5_sig[sig_size];
3517 MD5Buffer(fn.data(),static_cast<unsigned int>(fn.length()),md5_sig);
3518 char result[sig_size*3+2];
3519 char *p = result;
3520 *p++='@';
3521 for (int i=0;i<sig_size;i++)
3522 {
3523 static const char oct[]="01234567";
3524 uint8_t byte = md5_sig[i];
3525 *p++=oct[(byte>>6)&7];
3526 *p++=oct[(byte>>3)&7];
3527 *p++=oct[(byte>>0)&7];
3528 }
3529 *p='\0';
3530 return result;
3531}
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 2816 of file util.cpp.

2817{
2818 //printf("generateFileRef(%s,%s)\n",name,text);
2819 QCString linkText = text.isEmpty() ? text : name;
2820 //FileInfo *fi;
2821 bool ambig = false;
2823 if (fd && fd->isLinkable())
2824 // link to documented input file
2825 ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),QCString(),linkText);
2826 else
2827 ol.docify(linkText);
2828}
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 3274 of file util.cpp.

3275{
3276 auto caseSenseNames = Config_getEnum(CASE_SENSE_NAMES);
3277
3278 if (caseSenseNames == CASE_SENSE_NAMES_t::YES) return true;
3279 else if (caseSenseNames == CASE_SENSE_NAMES_t::NO) return false;
3281}
#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 2248 of file util.cpp.

2249{
2250 GetDefResult result;
2251 if (input.memberName.isEmpty()) return result;
2252 AUTO_TRACE("scopeName={},memberName={},forceEmptyScope={}",
2253 input.scopeName,input.memberName,input.forceEmptyScope);
2254
2255 //printf("@@ --- getDefsNew(%s,%s)-----------\n",qPrint(scName),qPrint(mbName));
2256 const Definition *scope = Doxygen::globalScope;
2257 SymbolResolver resolver;
2258 if (input.currentFile) resolver.setFileScope(input.currentFile);
2259 if (!input.scopeName.isEmpty() && !input.forceEmptyScope)
2260 {
2261 scope = resolver.resolveSymbol(scope,input.scopeName);
2262 }
2263 if (scope==Doxygen::globalScope)
2264 {
2265 scope = input.currentFile;
2266 }
2267 //printf("@@ -> found scope scope=%s member=%s out=%s\n",qPrint(input.scopeName),qPrint(input.memberName),qPrint(scope?scope->name():""));
2268 //
2269 const Definition *symbol = resolver.resolveSymbol(scope,input.memberName,input.args,input.checkCV,input.insideCode,true);
2270 //printf("@@ -> found symbol in=%s out=%s\n",qPrint(input.memberName),qPrint(symbol?symbol->qualifiedName():QCString()));
2271 if (symbol && symbol->definitionType()==Definition::TypeMember)
2272 {
2273 result.md = toMemberDef(symbol);
2274 result.cd = result.md->getClassDef();
2275 if (result.cd==nullptr) result.nd = result.md->getNamespaceDef();
2276 if (result.cd==nullptr && result.nd==nullptr) result.fd = result.md->getFileDef();
2277 result.gd = result.md->getGroupDef();
2278 result.found = true;
2279 }
2280 else if (symbol && symbol->definitionType()==Definition::TypeClass)
2281 {
2282 result.cd = toClassDef(symbol);
2283 result.found = true;
2284 }
2285 else if (symbol && symbol->definitionType()==Definition::TypeNamespace)
2286 {
2287 result.nd = toNamespaceDef(symbol);
2288 result.found = true;
2289 }
2290 else if (symbol && symbol->definitionType()==Definition::TypeConcept)
2291 {
2292 result.cnd = toConceptDef(symbol);
2293 result.found = true;
2294 }
2295 else if (symbol && symbol->definitionType()==Definition::TypeModule)
2296 {
2297 result.modd = toModuleDef(symbol);
2298 result.found = true;
2299 }
2300 return result;
2301}
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 6253 of file util.cpp.

6254{
6255 QCString imgExt = Config_getEnumAsString(DOT_IMAGE_FORMAT);
6256 int i= imgExt.find(':'); // strip renderer part when using e.g. 'png:cairo:gd' as format
6257 return i==-1 ? imgExt : imgExt.left(i);
6258}
#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 5659 of file util.cpp.

5660{
5661 InputFileEncoding elem;
5662 auto getter = [](const InputFileEncoding &e) -> QCString { return e.pattern; };
5663 if (genericPatternMatch(fi,Doxygen::inputFileEncodingList,elem,getter)) // check for file specific encoding
5664 {
5665 return elem.encoding;
5666 }
5667 else // fall back to default encoding
5668 {
5669 return Config_getString(INPUT_ENCODING);
5670 }
5671}
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:5602

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

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

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

5178{
5179 // try the extension
5180 auto lang = getLanguageFromFileName(fileName, SrcLangExt::Unknown);
5181 if (lang == SrcLangExt::Unknown)
5182 {
5183 // try the language names
5184 QCString langName = fileName.lower();
5185 if (langName.at(0)=='.') langName = langName.mid(1);
5186 auto it = std::find_if(g_lang2extMap.begin(),g_lang2extMap.end(),
5187 [&langName](const auto &info) { return info.langName==langName; });
5188 if (it != g_lang2extMap.end())
5189 {
5190 lang = it->parserId;
5191 fileName = it->defExt;
5192 }
5193 else // default to C++
5194 {
5195 return SrcLangExt::Cpp;
5196 }
5197 }
5198 return lang;
5199}
SrcLangExt getLanguageFromFileName(const QCString &fileName, SrcLangExt defLang)
Definition util.cpp:5159
static std::vector< Lang2ExtMap > g_lang2extMap
Definition util.cpp:5030

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

5160{
5161 FileInfo fi(fileName.str());
5162 // we need only the part after the last ".", newer implementations of FileInfo have 'suffix()' for this.
5163 QCString extName = QCString(fi.extension(FALSE)).lower();
5164 if (extName.isEmpty()) extName=".no_extension";
5165 if (extName.at(0)!='.') extName.prepend(".");
5166 auto it = g_extLookup.find(extName.str());
5167 if (it!=g_extLookup.end()) // listed extension
5168 {
5169 //printf("getLanguageFromFileName(%s)=%x\n",qPrint(fi.extension()),*pVal);
5170 return it->second;
5171 }
5172 //printf("getLanguageFromFileName(%s) not found!\n",qPrint(fileName));
5173 return defLang; // not listed => assume C-ish language.
5174}
static std::unordered_map< std::string, SrcLangExt > g_extLookup
Definition util.cpp:5020

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

Referenced by MemberDefImpl::_writeMultiLineInitializer(), ClassDefImpl::ClassDefImpl(), DocRef::DocRef(), FileDefImpl::FileDefImpl(), generateExampleDocs(), getLanguageFromCodeLang(), guessSection(), FileDefImpl::isDocumentationFile(), 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(), 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 5861 of file util.cpp.

5862{
5863 if (lang==SrcLangExt::Java || lang==SrcLangExt::CSharp || lang==SrcLangExt::VHDL || lang==SrcLangExt::Python)
5864 {
5865 return ".";
5866 }
5867 else if (lang==SrcLangExt::PHP && !classScope)
5868 {
5869 return "\\";
5870 }
5871 else
5872 {
5873 return "::";
5874 }
5875}

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

4044{
4045 return theTranslator->trOverloadText();
4046 //"This is an overloaded member function, "
4047 // "provided for convenience. It differs from the above "
4048 // "function only in what argument(s) it accepts.";
4049}
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 3185 of file util.cpp.

3186{
3187 if (name.isEmpty()) return 0;
3188 const StringVector &sl = Config_getList(IGNORE_PREFIX);
3189 for (const auto &s : sl)
3190 {
3191 const char *ps=s.c_str();
3192 const char *pd=name.data();
3193 int i=0;
3194 while (*ps!=0 && *pd!=0 && *ps==*pd)
3195 {
3196 ps++;
3197 pd++;
3198 i++;
3199 }
3200 if (*ps==0 && *pd!=0)
3201 {
3202 return i;
3203 }
3204 }
3205 return 0;
3206}

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

6776{
6777 QCString projectCookie = Config_getString(HTML_PROJECT_COOKIE);
6778 if (projectCookie.isEmpty()) return QCString();
6779 uint8_t md5_sig[16];
6780 char sigStr[34];
6781 MD5Buffer(projectCookie.data(),static_cast<unsigned int>(projectCookie.length()),md5_sig);
6782 MD5SigToString(md5_sig,sigStr);
6783 sigStr[32]='_'; sigStr[33]=0;
6784 return sigStr;
6785}

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

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

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

◆ initDefaultExtensionMapping()

void initDefaultExtensionMapping ( )

Definition at line 5086 of file util.cpp.

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

References updateLanguageMapping().

Referenced by initDoxygen().

◆ inlineArgListToDoc()

QCString inlineArgListToDoc ( const ArgumentList & al)

Definition at line 1159 of file util.cpp.

1160{
1161 QCString paramDocs;
1162 if (al.hasDocumentation())
1163 {
1164 for (const Argument &a : al)
1165 {
1166 if (a.hasDocumentation())
1167 {
1168 QCString docsWithoutDir = a.docs;
1169 QCString direction = extractDirection(docsWithoutDir);
1170 paramDocs+=" \\ilinebr @param"+direction+" "+a.name+" "+docsWithoutDir;
1171 }
1172 }
1173 }
1174 return paramDocs;
1175}
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:6142

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

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

◆ inlineTemplateArgListToDoc()

QCString inlineTemplateArgListToDoc ( const ArgumentList & al)

Definition at line 1177 of file util.cpp.

1178{
1179 QCString paramDocs;
1180 if (al.hasTemplateDocumentation())
1181 {
1182 for (const Argument &a : al)
1183 {
1184 if (!a.docs.isEmpty())
1185 {
1186 if (!a.name.isEmpty())
1187 {
1188 paramDocs+=" \\ilinebr @tparam "+a.name+" "+a.docs;
1189 }
1190 else if (!a.type.isEmpty())
1191 {
1192 QCString type = a.type;
1193 type.stripPrefix("class ");
1194 type.stripPrefix("typename ");
1195 type = type.stripWhiteSpace();
1196 paramDocs+=" \\ilinebr @tparam "+type+" "+a.docs;
1197 }
1198 }
1199 }
1200 }
1201 return paramDocs;
1202}
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 3700 of file util.cpp.

3701{
3702 QCString result=scope;
3703 if (!templ.isEmpty() && scope.find('<')==-1)
3704 {
3705 int si=0, pi=0;
3706 ClassDef *cd=nullptr;
3707 while (
3708 (si=scope.find("::",pi))!=-1 && !getClass(scope.left(si)+templ) &&
3709 ((cd=getClass(scope.left(si)))==nullptr || cd->templateArguments().empty())
3710 )
3711 {
3712 //printf("Tried '%s'\n",qPrint((scope.left(si)+templ)));
3713 pi=si+2;
3714 }
3715 if (si==-1) // not nested => append template specifier
3716 {
3717 result+=templ;
3718 }
3719 else // nested => insert template specifier before after first class name
3720 {
3721 result=scope.left(si) + templ + scope.right(scope.length()-si);
3722 }
3723 }
3724 //printf("insertTemplateSpecifierInScope('%s','%s')=%s\n",
3725 // qPrint(scope),qPrint(templ),qPrint(result));
3726 return result;
3727}
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 6646 of file util.cpp.

6647{
6648 QCString result;
6649 int residual = n;
6650
6651 char modVal[2];
6652 modVal[1] = 0;
6653 while (residual > 0)
6654 {
6655 modVal[0] = (upper ? 'A': 'a') + (residual-1)%26;
6656 result = modVal + result;
6657 residual = (residual-1) / 26;
6658 }
6659 return result;
6660}

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

◆ integerToRoman()

QCString integerToRoman ( int n,
bool upper = true )

Definition at line 6662 of file util.cpp.

6663{
6664 static const char *str_romans_upper[] = { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" };
6665 static const char *str_romans_lower[] = { "m", "cm", "d", "cd", "c", "xc", "l", "xl", "x", "ix", "v", "iv", "i" };
6666 static const int values[] = { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 };
6667 static const char **str_romans = upper ? str_romans_upper : str_romans_lower;
6668
6669 QCString result;
6670 int residual = n;
6671
6672 for (int i = 0; i < 13; ++i)
6673 {
6674 while (residual - values[i] >= 0)
6675 {
6676 result += str_romans[i];
6677 residual -= values[i];
6678 }
6679 }
6680
6681 return result;
6682}

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

5878{
5879 static const std::unordered_set<std::string> schemes = {
5880 "http", "https", "ftp", "ftps", "sftp", "file", "news", "irc", "ircs"
5881 };
5882 QCString loc_url = url.stripWhiteSpace();
5883 int colonPos = loc_url.find(':');
5884 return colonPos!=-1 && schemes.find(loc_url.left(colonPos).str())!=schemes.end();
5885}

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

6634{
6635 std::string result;
6636 bool first=true;
6637 for (const auto &s : sv)
6638 {
6639 if (!first) result+=delimiter;
6640 first=false;
6641 result+=s;
6642 }
6643 return result;
6644}

◆ langToString()

QCString langToString ( SrcLangExt lang)

Returns a string representation of lang.

Definition at line 5855 of file util.cpp.

5856{
5857 return to_string(lang);
5858}
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 5834 of file util.cpp.

5835{
5836 int result = 1;
5837
5838 // find the character positions of the first marker
5839 int m1 = text.find(marker);
5840 if (m1==-1) return result;
5841
5842 // find start line positions for the markers
5843 bool found=false;
5844 int p=0, i=0;
5845 while (!found && (i=text.find('\n',p))!=-1)
5846 {
5847 found = (p<=m1 && m1<i); // found the line with the start marker
5848 p=i+1;
5849 result++;
5850 }
5851 return result;
5852}

References QCString::find().

◆ 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 const Definition *d=nullptr;
983 //printf("** Match word '%s'\n",qPrint(matchWord));
984
985 SymbolResolver resolver(fileScope);
986 cd=resolver.resolveClass(scope,matchWord);
987 const MemberDef *typeDef = resolver.getTypedef();
988 if (typeDef) // First look at typedef then class, see bug 584184.
989 {
990 if (external ? typeDef->isLinkable() : typeDef->isLinkableInProject())
991 {
992 if (typeDef->getOuterScope()!=self)
993 {
994 //printf("Found typedef %s word='%s'\n",qPrint(typeDef->name()),qPrint(word));
995 out.writeLink(typeDef->getReference(),
996 typeDef->getOutputFileBase(),
997 typeDef->anchor(),
998 word);
999 found=TRUE;
1000 }
1001 }
1002 }
1003 auto writeCompoundName = [&](const auto *cd_) {
1004 if (external ? cd_->isLinkable() : cd_->isLinkableInProject())
1005 {
1006 if (self==nullptr || cd_->qualifiedName()!=self->qualifiedName())
1007 {
1008 //printf("Found compound %s word='%s'\n",qPrint(cd->name()),qPrint(word));
1009 out.writeLink(cd_->getReference(),cd_->getOutputFileBase(),cd_->anchor(),word);
1010 found=TRUE;
1011 }
1012 }
1013 };
1014
1015 if (found)
1016 {
1017 //printf(" -> skip\n");
1018 }
1019 else if ((cd=getClass(matchWord)))
1020 {
1021 writeCompoundName(cd);
1022 }
1023 else if ((cd=getClass(matchWord+"-p"))) // search for Obj-C protocols as well
1024 {
1025 writeCompoundName(cd);
1026 }
1027 else if ((cnd=getConcept(matchWord))) // search for concepts
1028 {
1029 writeCompoundName(cnd);
1030 }
1031 else if ((d=resolver.resolveSymbol(scope,matchWord)))
1032 {
1033 writeCompoundName(d);
1034 }
1035 else
1036 {
1037 //printf(" -> nothing\n");
1038 }
1039
1040 int m = matchWord.findRev("::");
1041 QCString scopeName;
1042 if (scope &&
1045 )
1046 )
1047 {
1048 scopeName=scope->name();
1049 }
1050 else if (m!=-1)
1051 {
1052 scopeName = matchWord.left(m);
1053 matchWord = matchWord.mid(m+2);
1054 }
1055
1056 //printf("ScopeName=%s\n",qPrint(scopeName));
1057 //if (!found) printf("Trying to link '%s' in '%s'\n",qPrint(word),qPrint(scopeName));
1058 if (!found)
1059 {
1060 GetDefInput input(scopeName,matchWord,QCString());
1061 GetDefResult result = getDefs(input);
1062 if (result.found && result.md &&
1063 (external ? result.md->isLinkable() : result.md->isLinkableInProject())
1064 )
1065 {
1066 //printf("Found ref scope=%s\n",d ? qPrint(d->name()) : "<global>");
1067 //ol.writeObjectLink(d->getReference(),d->getOutputFileBase(),
1068 // md->anchor(),word);
1069 if (result.md!=self && (self==nullptr || result.md->name()!=self->name()))
1070 // name check is needed for overloaded members, where getDefs just returns one
1071 {
1072 /* in case of Fortran scope and the variable is a non Fortran variable: don't link,
1073 * see also getLink in fortrancode.l
1074 */
1075 if (!(scope &&
1076 (scope->getLanguage() == SrcLangExt::Fortran) &&
1077 result.md->isVariable() &&
1078 (result.md->getLanguage() != SrcLangExt::Fortran)
1079 )
1080 )
1081 {
1082 //printf("found symbol %s word='%s'\n",qPrint(result.md->name()),qPrint(word));
1083 out.writeLink(result.md->getReference(),result.md->getOutputFileBase(),
1084 result.md->anchor(),word);
1085 found=TRUE;
1086 }
1087 }
1088 }
1089 }
1090 }
1091
1092 if (!found) // add word to the result
1093 {
1094 out.writeString(word,keepSpaces);
1095 }
1096 // set next start point in the string
1097 //printf("index=%d/%d\n",index,txtStr.length());
1098 skipIndex=index=newIndex+matchLen;
1099 }
1100 // add last part of the string to the result.
1101 //ol.docify(txtStr.right(txtStr.length()-skipIndex));
1102 std::string_view lastPart = txtStr.substr(skipIndex);
1103 out.writeString(lastPart,keepSpaces);
1104}
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:2248

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

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

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

6249{
6250 return Doxygen::mainPage!=nullptr && Doxygen::mainPage->hasTitle();
6251}
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 6877 of file util.cpp.

6878{
6879 int idx = name.find('<');
6880 if (idx!=-1)
6881 {
6882 return name.left(idx)+"-"+QCString().setNum(name.contains(",")+1)+"-g";
6883 }
6884 return name;
6885}
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 1971 of file util.cpp.

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

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

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

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

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

6826{
6827 if (Config_getBool(CALL_GRAPH) !=md1->hasCallGraph()) md2->overrideCallGraph(md1->hasCallGraph());
6828 if (Config_getBool(CALLER_GRAPH)!=md1->hasCallerGraph()) md2->overrideCallerGraph(md1->hasCallerGraph());
6829 if (Config_getBool(CALL_GRAPH) !=md2->hasCallGraph()) md1->overrideCallGraph( md2->hasCallGraph());
6830 if (Config_getBool(CALLER_GRAPH)!=md2->hasCallerGraph()) md1->overrideCallerGraph(md2->hasCallerGraph());
6831
6832 if (Config_getBool(SHOW_ENUM_VALUES) !=md1->hasEnumValues()) md2->overrideEnumValues(md1->hasEnumValues());
6833 if (Config_getBool(SHOW_ENUM_VALUES) !=md2->hasEnumValues()) md1->overrideEnumValues( md2->hasEnumValues());
6834
6835 if (Config_getBool(REFERENCED_BY_RELATION)!=md1->hasReferencedByRelation()) md2->overrideReferencedByRelation(md1->hasReferencedByRelation());
6836 if (Config_getBool(REFERENCES_RELATION) !=md1->hasReferencesRelation()) md2->overrideReferencesRelation(md1->hasReferencesRelation());
6837 if (Config_getBool(REFERENCED_BY_RELATION)!=md2->hasReferencedByRelation()) md1->overrideReferencedByRelation(md2->hasReferencedByRelation());
6838 if (Config_getBool(REFERENCES_RELATION) !=md2->hasReferencesRelation()) md1->overrideReferencesRelation(md2->hasReferencesRelation());
6839
6840 if (Config_getBool(INLINE_SOURCES)!=md1->hasInlineSource()) md2->overrideInlineSource(md1->hasInlineSource());
6841 if (Config_getBool(INLINE_SOURCES)!=md2->hasInlineSource()) md1->overrideInlineSource(md2->hasInlineSource());
6842}
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 4548 of file util.cpp.

4549{
4550 AUTO_TRACE("leftScope='{}' rightScope='{}'",leftScope,rightScope);
4551 // case leftScope=="A" rightScope=="A::B" => result = "A::B"
4552 if (leftScopeMatch(leftScope,rightScope))
4553 {
4554 AUTO_TRACE_EXIT("case1={}",rightScope);
4555 return rightScope;
4556 }
4557 QCString result;
4558 int i=0,p=static_cast<int>(leftScope.length());
4559
4560 // case leftScope=="A::B" rightScope=="B::C" => result = "A::B::C"
4561 // case leftScope=="A::B" rightScope=="B" => result = "A::B"
4562 bool found=FALSE;
4563 while ((i=leftScope.findRev("::",p))>0)
4564 {
4565 if (leftScopeMatch(rightScope,leftScope.right(leftScope.length()-i-2)))
4566 {
4567 result = leftScope.left(i+2)+rightScope;
4568 found=TRUE;
4569 }
4570 p=i-1;
4571 }
4572 if (found)
4573 {
4574 AUTO_TRACE_EXIT("case2={}",result);
4575 return result;
4576 }
4577
4578 // case leftScope=="A" rightScope=="B" => result = "A::B"
4579 result=leftScope;
4580 if (!result.isEmpty() && !rightScope.isEmpty()) result+="::";
4581 result+=rightScope;
4582 AUTO_TRACE_EXIT("case3={}",result);
4583 return result;
4584}
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 4254 of file util.cpp.

4258{
4259 // skip until <
4260 int p=name.find('<');
4261 if (p==-1) return name;
4262 p++;
4263 QCString result = name.left(p);
4264
4265 std::string s = name.mid(p).str();
4266 static const reg::Ex re(R"([\a:][\w:]*)");
4267 reg::Iterator it(s,re);
4269 size_t pi=0;
4270 // for each identifier in the template part (e.g. B<T> -> T)
4271 for (; it!=end ; ++it)
4272 {
4273 const auto &match = *it;
4274 size_t i = match.position();
4275 size_t l = match.length();
4276 result += s.substr(pi,i-pi);
4277 QCString n(match.str());
4278 bool found=FALSE;
4279 for (const Argument &formArg : formalArgs)
4280 {
4281 if (formArg.name == n)
4282 {
4283 found=TRUE;
4284 break;
4285 }
4286 }
4287 if (!found)
4288 {
4289 // try to resolve the type
4290 SymbolResolver resolver;
4291 const ClassDef *cd = resolver.resolveClass(context,n);
4292 if (cd)
4293 {
4294 result+=cd->name();
4295 }
4296 else
4297 {
4298 result+=n;
4299 }
4300 }
4301 else
4302 {
4303 result+=n;
4304 }
4305 pi=i+l;
4306 }
4307 result+=s.substr(pi);
4308 //printf("normalizeNonTemplateArgumentInString(%s)=%s\n",qPrint(name),qPrint(result));
4309 return removeRedundantWhiteSpace(result);
4310}
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 6260 of file util.cpp.

6261{
6262 assert(!f.is_open());
6263 bool fileOpened=FALSE;
6264 bool writeToStdout=outFile=="-";
6265 if (writeToStdout) // write to stdout
6266 {
6267 f.basic_ios<char>::rdbuf(std::cout.rdbuf());
6268 fileOpened = true;
6269 }
6270 else // write to file
6271 {
6272 FileInfo fi(outFile.str());
6273 if (fi.exists()) // create a backup
6274 {
6275 Dir dir;
6276 FileInfo backup(fi.filePath()+".bak");
6277 if (backup.exists()) // remove existing backup
6278 dir.remove(backup.filePath());
6279 dir.rename(fi.filePath(),fi.filePath()+".bak");
6280 }
6281 f = Portable::openOutputStream(outFile);
6282 fileOpened = f.is_open();
6283 }
6284 return fileOpened;
6285}
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 5373 of file util.cpp.

5374{
5375 std::lock_guard lock(g_docCacheMutex);
5376 auto it = g_docCache.find(doc.str());
5377 if (it != g_docCache.end())
5378 {
5379 //printf("Cache: [%s]->[%s]\n",qPrint(doc),qPrint(it->second));
5380 return it->second;
5381 }
5382 auto parser { createDocParser() };
5383 auto ast { validatingParseTitle(*parser.get(),fileName,lineNr,doc) };
5384 auto astImpl = dynamic_cast<const DocNodeAST*>(ast.get());
5385 QCString result;
5386 if (astImpl)
5387 {
5388 TextStream t;
5389 OutputCodeList codeList;
5390 codeList.add<HtmlCodeGenerator>(&t);
5391 HtmlDocVisitor visitor(t,codeList,scope,fileName);
5392 std::visit(visitor,astImpl->root);
5393 result = t.str();
5394 }
5395 else // fallback, should not happen
5396 {
5397 result = filterTitle(doc);
5398 }
5399 //printf("Conversion: [%s]->[%s]\n",qPrint(doc),qPrint(result));
5400 g_docCache.insert(std::make_pair(doc.str(),result));
5401 return result;
5402}
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:5371
QCString filterTitle(const QCString &title)
Definition util.cpp:5578
static std::mutex g_docCacheMutex
Definition util.cpp:5370

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

5319{
5320 if (doc.isEmpty()) return "";
5321 //printf("parseCommentAsText(%s)\n",qPrint(doc));
5322 TextStream t;
5323 auto parser { createDocParser() };
5324 auto ast { validatingParseDoc(*parser.get(),
5325 fileName,
5326 lineNr,
5327 scope,
5328 md,
5329 doc,
5330 DocOptions()
5331 .setAutolinkSupport(false))
5332 };
5333 auto astImpl = dynamic_cast<const DocNodeAST*>(ast.get());
5334 if (astImpl)
5335 {
5336 TextDocVisitor visitor(t);
5337 std::visit(visitor,astImpl->root);
5338 }
5340 int i=0;
5341 int charCnt=0;
5342 int l=static_cast<int>(result.length());
5343 while ((i=nextUTF8CharPosition(result,l,i))<l)
5344 {
5345 charCnt++;
5346 if (charCnt>=80) break;
5347 }
5348 if (charCnt>=80) // try to truncate the string
5349 {
5350 while ((i=nextUTF8CharPosition(result,l,i))<l && charCnt<100)
5351 {
5352 charCnt++;
5353 if (result.at(i)==',' ||
5354 result.at(i)=='.' ||
5355 result.at(i)=='!' ||
5356 result.at(i)=='?' ||
5357 result.at(i)=='}') // good for UTF-16 characters and } otherwise also a good point to stop the string
5358 {
5359 i++; // we want to be "behind" last inspected character
5360 break;
5361 }
5362 }
5363 }
5364 if ( i < l) result=result.left(i)+"...";
5365 return result.data();
5366}
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:5273

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(), GroupDefImpl::setGroupTitleLocal(), writeGroupTreeNode(), writeIndex(), and writePages().

◆ patternMatch()

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

Definition at line 5652 of file util.cpp.

5653{
5654 std::string elem;
5655 auto getter = [](std::string s) -> QCString { return s; };
5656 return genericPatternMatch(fi,patList,elem,getter);
5657}

References genericPatternMatch().

Referenced by readDir().

◆ processMarkup()

QCString processMarkup ( const QCString & s)

◆ projectLogoFile()

QCString projectLogoFile ( )

Definition at line 3094 of file util.cpp.

3095{
3096 QCString projectLogo = Config_getString(PROJECT_LOGO);
3097 if (!projectLogo.isEmpty())
3098 {
3099 // check for optional width= and height= specifier
3100 int wi = projectLogo.find(" width=");
3101 if (wi!=-1) // and strip them
3102 {
3103 projectLogo = projectLogo.left(wi);
3104 }
3105 int hi = projectLogo.find(" height=");
3106 if (hi!=-1)
3107 {
3108 projectLogo = projectLogo.left(hi);
3109 }
3110 }
3111 //printf("projectlogo='%s'\n",qPrint(projectLogo));
3112 return projectLogo;
3113}

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

Referenced by copyLogo(), and substituteKeywords().

◆ protectionLevelVisible()

bool protectionLevelVisible ( Protection prot)

Definition at line 5901 of file util.cpp.

5902{
5903 bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
5904 bool extractPackage = Config_getBool(EXTRACT_PACKAGE);
5905
5906 return (prot!=Protection::Private && prot!=Protection::Package) ||
5907 (prot==Protection::Private && extractPrivate) ||
5908 (prot==Protection::Package && extractPackage);
5909}

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

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

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 fileToString(), HtmlDocVisitor::operator()(), RTFDocVisitor::operator()(), parseFile(), parseInput(), 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 6307 of file util.cpp.

6308{
6309 int column=0;
6310 bool skipLine=FALSE;
6311
6312 if (format == FortranFormat::Fixed) return TRUE;
6313 if (format == FortranFormat::Free) return FALSE;
6314
6315 int tabSize=Config_getInt(TAB_SIZE);
6316 size_t sizCont = contents.length();
6317 for (size_t i=0;i<sizCont;i++)
6318 {
6319 column++;
6320
6321 switch(contents.at(i))
6322 {
6323 case '\n':
6324 column=0;
6325 skipLine=FALSE;
6326 break;
6327 case '\t':
6328 column += tabSize-1;
6329 break;
6330 case ' ':
6331 break;
6332 case '\000':
6333 return FALSE;
6334 case '#':
6335 skipLine=TRUE;
6336 break;
6337 case 'C':
6338 case 'c':
6339 if (column==1)
6340 {
6341 return !keyWordsFortranC(contents.data()+i);
6342 }
6343 // fallthrough
6344 case '*':
6345 if (column==1) return TRUE;
6346 if (skipLine) break;
6347 return FALSE;
6348 case '!':
6349 if (column!=6) skipLine=TRUE;
6350 break;
6351 default:
6352 if (skipLine) break;
6353 if (column>=7) return TRUE;
6354 return FALSE;
6355 }
6356 }
6357 return FALSE;
6358}
static bool keyWordsFortranC(const char *contents)
Definition util.cpp:6287

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

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

◆ relativePathToRoot()

QCString relativePathToRoot ( const QCString & name)

Definition at line 3533 of file util.cpp.

3534{
3535 QCString result;
3536 if (Config_getBool(CREATE_SUBDIRS))
3537 {
3538 if (name.isEmpty())
3539 {
3540 return REL_PATH_TO_ROOT;
3541 }
3542 else
3543 {
3544 int i = name.findRev('/');
3545 if (i!=-1)
3546 {
3547 result=REL_PATH_TO_ROOT;
3548 }
3549 }
3550 }
3551 return result;
3552}
#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 6550 of file util.cpp.

6551{
6552 std::string out;
6553 out.reserve(s.length());
6554 const char *p=s.data();
6555 if (p)
6556 {
6557 char c = 0;
6558 while ((c=*p++))
6559 {
6560 if (c=='\n')
6561 {
6562 const char *e = p;
6563 while (*e==' ' || *e=='\t') e++;
6564 if (*e=='\n')
6565 {
6566 p=e;
6567 }
6568 else out+=c;
6569 }
6570 else
6571 {
6572 out+=c;
6573 }
6574 }
6575 }
6576 //printf("removeEmptyLines(%s)=%s\n",qPrint(s),qPrint(out));
6577 return out;
6578}

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(), showFileDefMatches(), 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 addGlobalFunction(), addMethodToClass(), addVariable(), addVariableToClass(), argListToString(), buildFunctionList(), buildInterfaceAndServiceList(), buildTypedefList(), ClassDefImpl::ClassDefImpl(), extractCanonicalType(), findClassRelation(), DocParser::findDocsForMemberOrCompound(), findMember(), findUsedClassesForClass(), findUsingDeclImports(), ArgumentList::finishTrailingReturnType(), generateFunctionLink(), 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 5770 of file util.cpp.

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

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

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

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

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

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

6374{
6375 if (s.isEmpty()) return s;
6376
6377 // helper to find the end of a block
6378 auto skipBlock = [&markerInfo](const char *p,const SelectionBlock &blk)
6379 {
6380 char c = 0;
6381 while ((c=*p))
6382 {
6383 if (c==markerInfo.markerChar && qstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // end marker
6384 {
6385 size_t len = markerInfo.endLen;
6386 bool negate = *(p+markerInfo.endLen)=='!';
6387 if (negate) len++;
6388 size_t blkNameLen = qstrlen(blk.name);
6389 if (qstrncmp(p+len,blk.name,blkNameLen)==0 && // matching marker name
6390 qstrncmp(p+len+blkNameLen,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6391 {
6392 //printf("Found end marker %s enabled=%d negate=%d\n",blk.name,blk.enabled,negate);
6393 return p+len+blkNameLen+markerInfo.closeLen;
6394 }
6395 else // not the right marker id
6396 {
6397 p++;
6398 }
6399 }
6400 else // not and end marker
6401 {
6402 p++;
6403 }
6404 }
6405 return p;
6406 };
6407
6408 QCString result;
6409 result.reserve(s.length());
6410 const char *p = s.data();
6411 char c = 0;
6412 while ((c=*p))
6413 {
6414 if (c==markerInfo.markerChar) // potential start of marker
6415 {
6416 if (qstrncmp(p,markerInfo.beginStr,markerInfo.beginLen)==0) // start of begin marker
6417 {
6418 bool found = false;
6419 size_t len = markerInfo.beginLen;
6420 bool negate = *(p+len)=='!';
6421 if (negate) len++;
6422 for (const auto &blk : blockList)
6423 {
6424 size_t blkNameLen = qstrlen(blk.name);
6425 if (qstrncmp(p+len,blk.name,blkNameLen)==0 && // matching marker name
6426 qstrncmp(p+len+blkNameLen,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6427 {
6428 bool blockEnabled = blk.enabled!=negate;
6429 //printf("Found start marker %s enabled=%d negate=%d\n",blk.name,blk.enabled,negate);
6430 p+=len+blkNameLen+markerInfo.closeLen;
6431 if (!blockEnabled) // skip until the end of the block
6432 {
6433 //printf("skipping block\n");
6434 p=skipBlock(p,blk);
6435 }
6436 found=true;
6437 break;
6438 }
6439 }
6440 if (!found) // unknown marker id
6441 {
6442 result+=c;
6443 p++;
6444 }
6445 }
6446 else if (qstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // start of end marker
6447 {
6448 bool found = false;
6449 size_t len = markerInfo.endLen;
6450 bool negate = *(p+len)=='!';
6451 if (negate) len++;
6452 for (const auto &blk : blockList)
6453 {
6454 size_t blkNameLen = qstrlen(blk.name);
6455 if (qstrncmp(p+len,blk.name,blkNameLen)==0 && // matching marker name
6456 qstrncmp(p+len+blkNameLen,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6457 {
6458 //printf("Found end marker %s enabled=%d negate=%d\n",blk.name,blk.enabled,negate);
6459 p+=len+blkNameLen+markerInfo.closeLen;
6460 found=true;
6461 break;
6462 }
6463 }
6464 if (!found) // unknown marker id
6465 {
6466 result+=c;
6467 p++;
6468 }
6469 }
6470 else // not a start or end marker
6471 {
6472 result+=c;
6473 p++;
6474 }
6475 }
6476 else // not a marker character
6477 {
6478 result+=c;
6479 p++;
6480 }
6481 }
6482 //printf("====\n%s\n-----\n%s\n~~~~\n",qPrint(s),qPrint(result));
6483 return result;
6484}
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 2972 of file util.cpp.

2973{
2974 QCString result;
2975 QCString name=Dir::cleanDirPath(n.str());
2976 QCString path;
2977 int slashPos=std::max(name.findRev('/'),name.findRev('\\'));
2978 if (slashPos!=-1)
2979 {
2980 path=removeLongPathMarker(name.left(slashPos+1));
2981 name=name.right(name.length()-slashPos-1);
2982 }
2983 const FileName *fn=fnMap->find(name);
2984 if (fn)
2985 {
2986 bool first = true;
2987 QCString pathStripped = stripFromIncludePath(path);
2988 for (const auto &fd_p : *fn)
2989 {
2990 FileDef *fd = fd_p.get();
2991 QCString fdStripPath = stripFromIncludePath(fd->getPath());
2992 if (path.isEmpty() ||
2993 (!pathStripped.isEmpty() && fdStripPath.endsWith(pathStripped)) ||
2994 (pathStripped.isEmpty() && fdStripPath.isEmpty()))
2995 {
2996 if (!first) result += "\n";
2997 else first = false;
2998 result+=" "+fd->absFilePath();
2999 }
3000 }
3001
3002 }
3003 return result;
3004}

References FileDef::absFilePath(), Dir::cleanDirPath(), QCString::endsWith(), LinkedMap< T, Hash, KeyEqual, Map >::find(), QCString::findRev(), FileDef::getPath(), QCString::isEmpty(), QCString::left(), QCString::length(), removeLongPathMarker(), QCString::right(), QCString::str(), and stripFromIncludePath().

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

6600{
6601 StringVector result;
6602 reg::Iterator iter(s, delimiter);
6604 size_t p=0;
6605 for ( ; iter != end; ++iter)
6606 {
6607 const auto &match = *iter;
6608 size_t i=match.position();
6609 size_t l=match.length();
6610 if (i>p) result.push_back(s.substr(p,i-p));
6611 p=i+l;
6612 }
6613 if (p<s.length()) result.push_back(s.substr(p));
6614 return result;
6615}

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

6583{
6584 StringVector result;
6585 size_t prev = 0, pos = 0, len = s.length();
6586 do
6587 {
6588 pos = s.find(delimiter, prev);
6589 if (pos == std::string::npos) pos = len;
6590 if (pos>prev) result.push_back(s.substr(prev,pos-prev));
6591 prev = pos + delimiter.length();
6592 }
6593 while (pos<len && prev<len);
6594 return result;
6595}

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(), VhdlDocGen::writeInlineClassLink(), and VhdlDocGen::writeRecUnitDocu().

◆ stackTrace()

void stackTrace ( )

Definition at line 5434 of file util.cpp.

5435{
5436#ifdef TRACINGSUPPORT
5437 void *backtraceFrames[128];
5438 int frameCount = backtrace(backtraceFrames, 128);
5439 const size_t cmdLen = 40960;
5440 static char cmd[cmdLen];
5441 char *p = cmd;
5442 p += qsnprintf(p,cmdLen,"/usr/bin/atos -p %d ", (int)getpid());
5443 for (int x = 0; x < frameCount; x++)
5444 {
5445 p += qsnprintf(p,cmdLen,"%p ", backtraceFrames[x]);
5446 }
5447 fprintf(stderr,"========== STACKTRACE START ==============\n");
5448 if (FILE *fp = Portable::popen(cmd, "r"))
5449 {
5450 char resBuf[512];
5451 while (size_t len = fread(resBuf, 1, sizeof(resBuf), fp))
5452 {
5453 fwrite(resBuf, 1, len, stderr);
5454 }
5455 Portable::pclose(fp);
5456 }
5457 fprintf(stderr,"============ STACKTRACE END ==============\n");
5458 //fprintf(stderr,"%s\n", frameStrings[x]);
5459#endif
5460}

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

4898{
4900}
QCString stripExtensionGeneral(const QCString &fName, const QCString &ext)
Definition util.cpp:4887

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

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

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

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

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

◆ stripIndentationVerbatim()

void stripIndentationVerbatim ( QCString & doc,
const int indentationLevel,
bool skipFirstLine = true )

Definition at line 6002 of file util.cpp.

6003{
6004 //printf("stripIndentationVerbatim(level=%d):\n%s\n------\n",indentationLevel,qPrint(doc));
6005 if (indentationLevel <= 0 || doc.isEmpty()) return; // nothing to strip
6006
6007 // by stripping content the string will only become shorter so we write the results
6008 // back into the input string and then resize it at the end.
6009 char c = 0;
6010 const char *src = doc.data();
6011 char *dst = doc.rawData();
6012 bool insideIndent = !skipFirstLine; // skip the initial line from stripping
6013 int cnt = 0;
6014 if (!skipFirstLine) cnt = indentationLevel;
6015 while ((c=*src++))
6016 {
6017 // invariant: dst<=src
6018 switch(c)
6019 {
6020 case '\n':
6021 *dst++ = c;
6022 insideIndent = true;
6023 cnt = indentationLevel;
6024 break;
6025 case ' ':
6026 if (insideIndent)
6027 {
6028 if (cnt>0) // count down the spacing until the end of the indent
6029 {
6030 cnt--;
6031 }
6032 else // reached the end of the indent, start of the part of the line to keep
6033 {
6034 insideIndent = false;
6035 *dst++ = c;
6036 }
6037 }
6038 else // part after indent, copy to the output
6039 {
6040 *dst++ = c;
6041 }
6042 break;
6043 default:
6044 insideIndent = false;
6045 *dst++ = c;
6046 break;
6047 }
6048 }
6049 doc.resize(static_cast<uint32_t>(dst-doc.data()));
6050 //printf("stripIndentationVerbatim: result=\n%s\n------\n",qPrint(doc));
6051}
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().

Referenced by MemberDefImpl::setInitializer().

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

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

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

4903{
4904 QCString result=s;
4905 int i=result.findRev('/');
4906 if (i!=-1)
4907 {
4908 result=result.mid(i+1);
4909 }
4910 i=result.findRev('\\');
4911 if (i!=-1)
4912 {
4913 result=result.mid(i+1);
4914 }
4915 return result;
4916}

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

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

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

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

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

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

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

3162{
3163 return substituteKeywords(file,s,
3164 {
3165 // keyword value getter
3166 { "$title", [&]() { return !title.isEmpty() ? title : projName; } },
3167 { "$doxygenversion", [&]() { return getDoxygenVersion(); } },
3168 { "$projectname", [&]() { return projName; } },
3169 { "$projectnumber", [&]() { return projNum; } },
3170 { "$projectbrief", [&]() { return projBrief; } },
3171 { "$projectlogo", [&]() { return stripPath(projectLogoFile()); } },
3172 { "$logosize", [&]() { return projectLogoSize(); } },
3173 { "$projecticon", [&]() { return stripPath(Config_getString(PROJECT_ICON)); } },
3174 { "$langISO", [&]() { return theTranslator->trISOLang(); } },
3175 { "$showdate", [&](const QCString &fmt) { return showDate(fmt); } }
3176 });
3177}
Definition message.h:144
QCString stripPath(const QCString &s)
Definition util.cpp:4902
QCString substituteKeywords(const QCString &file, const QCString &s, const KeywordSubstitutionList &keywords)
Definition util.cpp:3008
QCString projectLogoFile()
Definition util.cpp:3094
static QCString projectLogoSize()
Definition util.cpp:3115
static QCString showDate(const QCString &fmt)
Definition util.cpp:3081

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

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

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

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

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

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

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

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

◆ updateColumnCount()

size_t updateColumnCount ( const char * s,
size_t col )

Definition at line 6844 of file util.cpp.

6845{
6846 if (s)
6847 {
6848 const int tabSize = Config_getInt(TAB_SIZE);
6849 char c;
6850 while ((c=*s++))
6851 {
6852 switch(c)
6853 {
6854 case '\t': col+=tabSize - (col%tabSize);
6855 break;
6856 case '\n': col=0;
6857 break;
6858 default:
6859 col++;
6860 if (c<0) // multi-byte character
6861 {
6862 int numBytes = getUTF8CharNumBytes(c);
6863 for (int i=0;i<numBytes-1 && (c=*s++);i++) {} // skip over extra chars
6864 if (c==0) return col; // end of string half way a multibyte char
6865 }
6866 break;
6867 }
6868 }
6869 }
6870 return col;
6871}

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

5055{
5056 QCString langName = language.lower();
5057 auto it1 = std::find_if(g_lang2extMap.begin(),g_lang2extMap.end(),
5058 [&langName](const auto &info) { return info.langName==langName; });
5059 if (it1 == g_lang2extMap.end()) return false;
5060
5061 // found the language
5062 SrcLangExt parserId = it1->parserId;
5063 QCString extName = extension.lower();
5064 if (extName.isEmpty()) return FALSE;
5065 if (extName.at(0)!='.') extName.prepend(".");
5066 auto it2 = g_extLookup.find(extName.str());
5067 if (it2!=g_extLookup.end())
5068 {
5069 g_extLookup.erase(it2); // language was already register for this ext
5070 }
5071 //printf("registering extension %s\n",qPrint(extName));
5072 g_extLookup.emplace(extName.str(),parserId);
5073 if (!Doxygen::parserManager->registerExtension(extName,it1->parserName))
5074 {
5075 err("Failed to assign extension {} to parser {} for language {}\n",
5076 extName.data(),it1->parserName,language);
5077 }
5078 else
5079 {
5080 //msg("Registered extension {} to language parser {}...\n",
5081 // extName,language);
5082 }
5083 return TRUE;
5084}
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 5746 of file util.cpp.

5747{
5748 int hue = Config_getInt(HTML_COLORSTYLE_HUE);
5749 int sat = Config_getInt(HTML_COLORSTYLE_SAT);
5750 int gamma = Config_getInt(HTML_COLORSTYLE_GAMMA);
5751 while (data->name)
5752 {
5753 QCString fileName = dir+"/"+data->name;
5754 ColoredImage img(data->width,data->height,data->content,data->alpha,
5755 sat,hue,gamma);
5756 if (!img.save(fileName))
5757 {
5758 fprintf(stderr,"Warning: Cannot open file %s for writing\n",data->name);
5759 }
5760 Doxygen::indexList->addImageFile(data->name);
5761 data++;
5762 }
5763}
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 1130 of file util.cpp.

1131{
1132 auto replaceFunc = [&list,&ol](size_t entryIndex)
1133 {
1134 const auto &e = list[entryIndex];
1135 ol.pushGeneratorState();
1139 // link for Html / man
1140 //printf("writeObjectLink(file=%s)\n",qPrint(e->file));
1141 ol.writeObjectLink(QCString(),e.file,e.anchor,e.name);
1142 ol.popGeneratorState();
1143
1144 ol.pushGeneratorState();
1147 // link for Latex / pdf with anchor because the sources
1148 // are not hyperlinked (not possible with a verbatim environment).
1149 ol.writeObjectLink(QCString(),e.file,QCString(),e.name);
1150 ol.popGeneratorState();
1151 };
1152
1153 writeMarkerList(ol, theTranslator->trWriteList(static_cast<int>(list.size())).str(), list.size(), replaceFunc);
1154
1155 ol.writeString(".");
1156}
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:1106

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

1108{
1109 static const reg::Ex marker(R"(@(\d+))");
1110 reg::Iterator it(markerText,marker);
1112 size_t index=0;
1113 // now replace all markers in inheritLine with links to the classes
1114 for ( ; it!=end ; ++it)
1115 {
1116 const auto &match = *it;
1117 size_t newIndex = match.position();
1118 size_t matchLen = match.length();
1119 ol.parseText(markerText.substr(index,newIndex-index));
1120 unsigned long entryIndex = std::stoul(match[1].str());
1121 if (entryIndex<static_cast<unsigned long>(numMarkers))
1122 {
1123 replaceFunc(entryIndex);
1124 }
1125 index=newIndex+matchLen;
1126 }
1127 ol.parseText(markerText.substr(index));
1128}
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 5407 of file util.cpp.

5408{
5409 if (al.empty()) return;
5410 ol.startConstraintList(theTranslator->trTypeConstraints());
5411 for (const Argument &a : al)
5412 {
5414 ol.parseText(a.name);
5415 ol.endConstraintParam();
5417 linkifyText(TextGeneratorOLImpl(ol),d,nullptr,nullptr,a.type);
5418 ol.endConstraintType();
5420 ol.generateDoc(d->docFile(),
5421 d->docLine(),
5422 d,
5423 nullptr,
5424 a.docs,
5425 DocOptions()
5426 .setIndexWords(true));
5427 ol.endConstraintDocs();
5428 }
5429 ol.endConstraintList();
5430}
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().