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

Detailed Description

A bunch of utility functions.

Definition in file util.h.

Typedef Documentation

◆ KeywordSubstitutionList

Definition at line 248 of file util.h.

◆ SelectionBlockList

using SelectionBlockList = std::vector<SelectionBlock>

Definition at line 182 of file util.h.

Function Documentation

◆ addCodeOnlyMappings()

void addCodeOnlyMappings ( )

Definition at line 5101 of file util.cpp.

5102{
5103 updateLanguageMapping(".xml", "xml");
5104 updateLanguageMapping(".sql", "sql");
5105}
bool updateLanguageMapping(const QCString &extension, const QCString &language)
Definition util.cpp:5002

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

4824{
4825 if (fName.isEmpty()) return;
4826 int i_fs = fName.findRev('/');
4827 int i_bs = fName.findRev('\\');
4828 int i = fName.find('.',std::max({ i_fs, i_bs ,0})); // search for . after path part
4829 if (i==-1)
4830 {
4832 }
4833}
static QCString htmlFileExtension
Definition doxygen.h:122
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 4018 of file util.cpp.

4021{
4022 ASSERT(context!=nullptr);
4023 //printf("addMemberToMemberGroup() context=%s\n",qPrint(context->name()));
4024 if (ml==nullptr) return;
4025
4026 struct MoveMemberInfo
4027 {
4028 MoveMemberInfo(MemberDef *md,MemberGroup *mg,const RefItemVector &rv)
4029 : memberDef(md), memberGroup(mg), sli(rv) {}
4030 MemberDef *memberDef;
4031 MemberGroup *memberGroup;
4032 RefItemVector sli;
4033 };
4034 std::vector<MoveMemberInfo> movedMembers;
4035
4036 for (const auto &md : *ml)
4037 {
4038 if (md->isEnumerate()) // insert enum value of this enum into groups
4039 {
4040 for (const auto &fmd : md->enumFieldList())
4041 {
4042 int groupId=fmd->getMemberGroupId();
4043 if (groupId!=-1)
4044 {
4045 auto it = Doxygen::memberGroupInfoMap.find(groupId);
4047 {
4048 const auto &info = it->second;
4049 auto mg_it = std::find_if(pMemberGroups->begin(),
4050 pMemberGroups->end(),
4051 [&groupId](const auto &g)
4052 { return g->groupId()==groupId; }
4053 );
4054 MemberGroup *mg_ptr = nullptr;
4055 if (mg_it==pMemberGroups->end())
4056 {
4057 auto mg = std::make_unique<MemberGroup>(
4058 context,
4059 groupId,
4060 info->header,
4061 info->doc,
4062 info->docFile,
4063 info->docLine,
4064 ml->container());
4065 mg_ptr = mg.get();
4066 pMemberGroups->push_back(std::move(mg));
4067 }
4068 else
4069 {
4070 mg_ptr = (*mg_it).get();
4071 }
4072 mg_ptr->insertMember(fmd); // insert in member group
4074 if (fmdm)
4075 {
4076 fmdm->setMemberGroup(mg_ptr);
4077 }
4078 }
4079 }
4080 }
4081 }
4082 int groupId=md->getMemberGroupId();
4083 if (groupId!=-1)
4084 {
4085 auto it = Doxygen::memberGroupInfoMap.find(groupId);
4087 {
4088 const auto &info = it->second;
4089 auto mg_it = std::find_if(pMemberGroups->begin(),
4090 pMemberGroups->end(),
4091 [&groupId](const auto &g)
4092 { return g->groupId()==groupId; }
4093 );
4094 MemberGroup *mg_ptr = nullptr;
4095 if (mg_it==pMemberGroups->end())
4096 {
4097 auto mg = std::make_unique<MemberGroup>(
4098 context,
4099 groupId,
4100 info->header,
4101 info->doc,
4102 info->docFile,
4103 info->docLine,
4104 ml->container());
4105 mg_ptr = mg.get();
4106 pMemberGroups->push_back(std::move(mg));
4107 }
4108 else
4109 {
4110 mg_ptr = (*mg_it).get();
4111 }
4112 movedMembers.emplace_back(md,mg_ptr,info->m_sli);
4113 }
4114 }
4115 }
4116
4117 // move the members to their group
4118 for (const auto &mmi : movedMembers)
4119 {
4120 ml->remove(mmi.memberDef); // remove from member list
4121 mmi.memberGroup->insertMember(mmi.memberDef->resolveAlias()); // insert in member group
4122 mmi.memberGroup->setRefItems(mmi.sli);
4123 MemberDefMutable *rmdm = toMemberDefMutable(mmi.memberDef);
4124 if (rmdm)
4125 {
4126 rmdm->setMemberGroup(mmi.memberGroup);
4127 }
4128 }
4129}
static MemberGroupInfoMap memberGroupInfoMap
Definition doxygen.h:118
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 4726 of file util.cpp.

4729{
4730 //printf("addRefItem(sli=%d,key=%s,prefix=%s,name=%s,title=%s,args=%s)\n",(int)sli.size(),key,prefix,name,title,args);
4731 if (!key.isEmpty() && key[0]!='@') // check for @ to skip anonymous stuff (see bug427012)
4732 {
4733 for (RefItem *item : sli)
4734 {
4735 item->setPrefix(prefix);
4736 item->setScope(scope);
4737 item->setName(name);
4738 item->setTitle(title);
4739 item->setArgs(args);
4740 item->setGroup(key);
4741 }
4742 }
4743}
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 4596 of file util.cpp.

4607{
4608 PageDef *pd=nullptr;
4609 //printf("addRelatedPage(name=%s gd=%p)\n",qPrint(name),gd);
4610 QCString title=ptitle.stripWhiteSpace();
4611 bool newPage = true;
4612 if ((pd=Doxygen::pageLinkedMap->find(name)) && !pd->isReference())
4613 {
4614 if (!xref && !title.isEmpty() && pd->title()!=pd->name() && pd->title()!=title)
4615 {
4616 warn(fileName,startLine,"multiple use of page label '{}' with different titles, (other occurrence: {}, line: {})",
4617 name,pd->docFile(),pd->getStartBodyLine());
4618 }
4619 if (!title.isEmpty() && pd->title()==pd->name()) // pd has no real title yet
4620 {
4621 pd->setTitle(title);
4623 if (si)
4624 {
4625 si->setTitle(title);
4626 }
4627 }
4628 // append documentation block to the page.
4629 pd->setDocumentation(doc,fileName,docLine);
4630 //printf("Adding page docs '%s' pi=%p name=%s\n",qPrint(doc),pd,name);
4631 // append (x)refitems to the page.
4632 pd->setRefItems(sli);
4633 newPage = false;
4634 }
4635
4636 if (newPage) // new page
4637 {
4638 QCString baseName=name;
4639 if (baseName.endsWith(".tex"))
4640 baseName=baseName.left(baseName.length()-4);
4641 else if (baseName.right(Doxygen::htmlFileExtension.length())==Doxygen::htmlFileExtension)
4642 baseName=baseName.left(baseName.length()-Doxygen::htmlFileExtension.length());
4643
4644 //printf("Appending page '%s'\n",qPrint(baseName));
4645 if (pd) // replace existing page
4646 {
4647 pd->setDocumentation(doc,fileName,docLine);
4649 pd->setShowLineNo(FALSE);
4650 pd->setNestingLevel(0);
4651 pd->setPageScope(nullptr);
4652 pd->setTitle(title);
4653 pd->setReference(QCString());
4654 }
4655 else // newPage
4656 {
4657 pd = Doxygen::pageLinkedMap->add(baseName,
4658 createPageDef(fileName,docLine,baseName,doc,title));
4659 }
4660 pd->setBodySegment(startLine,startLine,-1);
4661
4662 pd->setRefItems(sli);
4663 pd->setLanguage(lang);
4664
4665 if (tagInfo)
4666 {
4667 pd->setReference(tagInfo->tagName);
4668 pd->setFileName(tagInfo->fileName);
4669 }
4670
4671 if (gd) gd->addPage(pd);
4672
4673 if (pd->hasTitle())
4674 {
4675 //outputList->writeTitle(pi->name,pi->title);
4676
4677 // a page name is a label as well!
4678 QCString file;
4679 QCString orgFile;
4680 int line = -1;
4681 if (gd)
4682 {
4683 file=gd->getOutputFileBase();
4684 orgFile=gd->getOutputFileBase();
4685 }
4686 else
4687 {
4688 file=pd->getOutputFileBase();
4689 orgFile=pd->docFile();
4690 line = pd->getStartBodyLine();
4691 }
4692 const SectionInfo *si = SectionManager::instance().find(pd->name());
4693 if (si)
4694 {
4695 if (!si->ref().isEmpty()) // we are from a tag file
4696 {
4698 file,-1,pd->title(),SectionType::Page,0,pd->getReference());
4699 }
4700 else if (si->lineNr() != -1)
4701 {
4702 warn(orgFile,line,"multiple use of section label '{}', (first occurrence: {}, line {})",pd->name(),si->fileName(),si->lineNr());
4703 }
4704 else
4705 {
4706 warn(orgFile,line,"multiple use of section label '{}', (first occurrence: {})",pd->name(),si->fileName());
4707 }
4708 }
4709 else
4710 {
4712 file,-1,pd->title(),SectionType::Page,0,pd->getReference());
4713 //printf("si->label='%s' si->definition=%s si->fileName='%s'\n",
4714 // qPrint(si->label),si->definition?si->definition->name().data():"<none>",
4715 // qPrint(si->fileName));
4716 //printf(" SectionInfo: sec=%p sec->fileName=%s\n",si,qPrint(si->fileName));
4717 //printf("Adding section key=%s si->fileName=%s\n",qPrint(pageName),qPrint(si->fileName));
4718 }
4719 }
4720 }
4721 return pd;
4722}
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:100
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:3425

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

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

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

6433{
6434 if (s.isEmpty()) return;
6435
6436 const char *p = s.data();
6437 char c = 0;
6438 while ((c=*p))
6439 {
6440 if (c==markerInfo.markerChar) // potential start of marker
6441 {
6442 if (qstrncmp(p,markerInfo.beginStr,markerInfo.beginLen)==0) // start of begin marker
6443 {
6444 size_t len = markerInfo.beginLen;
6445 bool negate = *(p+len)=='!';
6446 if (negate) len++;
6447 p += len;
6448 QCString marker;
6449 while (*p)
6450 {
6451 if (markerInfo.closeLen==0 && *p=='\n') // matching end of line
6452 {
6453 warn(fileName,-1,"Remaining begin replacement with marker '{}'",marker);
6454 break;
6455 }
6456 else if (markerInfo.closeLen!= 0 && qstrncmp(p,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6457 {
6458 p += markerInfo.closeLen;
6459 warn(fileName,-1,"Remaining begin replacement with marker '{}'",marker);
6460 break;
6461 }
6462 marker += *p;
6463 p++;
6464 }
6465 }
6466 else if (qstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // start of end marker
6467 {
6468 size_t len = markerInfo.endLen;
6469 bool negate = *(p+len)=='!';
6470 if (negate) len++;
6471 p += len;
6472 QCString marker;
6473 while (*p)
6474 {
6475 if (markerInfo.closeLen==0 && *p=='\n') // matching end of line
6476 {
6477 warn(fileName,-1,"Remaining end replacement with marker '{}'",marker);
6478 break;
6479 }
6480 else if (markerInfo.closeLen!= 0 && qstrncmp(p,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6481 {
6482 p += markerInfo.closeLen;
6483 warn(fileName,-1,"Remaining end replacement with marker '{}'",marker);
6484 break;
6485 }
6486 marker += *p;
6487 p++;
6488 }
6489 }
6490 }
6491 p++;
6492 }
6493}
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:188
const char * closeStr
Definition util.h:191
const char * beginStr
Definition util.h:187
size_t closeLen
Definition util.h:192
const char * endStr
Definition util.h:189

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

4819{
4820 return fName.right(ext.length())==ext;
4821}

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

5212{
5213 MemberDef *bestMatch = getMemberFromSymbol(scope,fileScope,n);
5214
5215 if (bestMatch && bestMatch->isTypedef())
5216 return TRUE; // closest matching symbol is a typedef
5217 else
5218 return FALSE;
5219}
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:5159

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

Referenced by isVarWithConstructor().

◆ clearSubDirs()

void clearSubDirs ( const Dir & d)

Definition at line 3588 of file util.cpp.

3589{
3590 if (Config_getBool(CREATE_SUBDIRS))
3591 {
3592 // remove empty subdirectories
3593 int createSubdirsLevelPow2 = 1 << Config_getInt(CREATE_SUBDIRS_LEVEL);
3594 for (int l1=0;l1<16;l1++)
3595 {
3596 QCString subdir;
3597 subdir.sprintf("d%x",l1);
3598 for (int l2=0; l2 < createSubdirsLevelPow2; l2++)
3599 {
3600 QCString subsubdir;
3601 subsubdir.sprintf("d%x/d%02x",l1,l2);
3602 if (d.exists(subsubdir.str()) && d.isEmpty(subsubdir.str()))
3603 {
3604 d.rmdir(subsubdir.str());
3605 }
3606 }
3607 if (d.exists(subdir.str()) && d.isEmpty(subdir.str()))
3608 {
3609 d.rmdir(subdir.str());
3610 }
3611 }
3612 }
3613}
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 6734 of file util.cpp.

6735{
6736 int l = static_cast<int>(name.length());
6737 int lastSepPos = -1;
6738 const char *p = name.data();
6739 int i=l-2;
6740 int sharpCount=0;
6741 // --- begin optimized version of ts=name.findRev(">::");
6742 int ts = -1;
6743 while (i>=0)
6744 {
6745 if (p[i]=='>')
6746 {
6747 if (sharpCount==0 && p[i+1]==':' && p[i+2]==':')
6748 {
6749 ts=i;
6750 break;
6751 }
6752 sharpCount++;
6753 }
6754 else if (p[i]=='<')
6755 {
6756 sharpCount--;
6757 }
6758 i--;
6759 }
6760 // --- end optimized version
6761 if (ts==-1) ts=0; else p+=++ts;
6762 for (i=ts;i<l-1;i++)
6763 {
6764 char c=*p++;
6765 if (c==':' && *p==':') lastSepPos=i;
6766 if (c=='<') break;
6767 }
6768 return lastSepPos;
6769}

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

4868{
4869 if (str.isEmpty() || word==nullptr) return false;
4870 static const reg::Ex re(R"(\a+)");
4871 std::string s = str.str();
4872 for (reg::Iterator it(s,re) ; it!=reg::Iterator() ; ++it)
4873 {
4874 if (it->str()==word) return true;
4875 }
4876 return false;
4877}
Class representing a regular expression.
Definition regex.h:39
Class to iterate through matches.
Definition regex.h:232

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

◆ convertCharEntitiesToUTF8()

QCString convertCharEntitiesToUTF8 ( const QCString & s)

Definition at line 3968 of file util.cpp.

3969{
3970 if (str.isEmpty()) return QCString();
3971
3972 std::string s = str.data();
3973 static const reg::Ex re(R"(&\a\w*;)");
3974 reg::Iterator it(s,re);
3976
3977 GrowBuf growBuf;
3978 size_t p=0, i=0, l=0;
3979 for (; it!=end ; ++it)
3980 {
3981 const auto &match = *it;
3982 p = match.position();
3983 l = match.length();
3984 if (p>i)
3985 {
3986 growBuf.addStr(s.substr(i,p-i));
3987 }
3988 QCString entity(match.str());
3990 const char *code=nullptr;
3991 if (symType!=HtmlEntityMapper::Sym_Unknown && (code=HtmlEntityMapper::instance().utf8(symType)))
3992 {
3993 growBuf.addStr(code);
3994 }
3995 else
3996 {
3997 growBuf.addStr(entity);
3998 }
3999 i=p+l;
4000 }
4001 growBuf.addStr(s.substr(i));
4002 growBuf.addChar(0);
4003 //printf("convertCharEntitiesToUTF8(%s)->%s\n",qPrint(s),growBuf.get());
4004 return growBuf.get();
4005}
Class representing a string buffer optimized for growing.
Definition growbuf.h:28
void addChar(char c)
Definition growbuf.h:69
void addStr(const QCString &s)
Definition growbuf.h:72
char * get()
Definition growbuf.h:114
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.
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:759

References GrowBuf::addChar(), GrowBuf::addStr(), QCString::data(), end(), GrowBuf::get(), HtmlEntityMapper::instance(), QCString::isEmpty(), HtmlEntityMapper::name2sym(), and HtmlEntityMapper::Sym_Unknown.

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

◆ convertFileNameFortranParserCode()

FortranFormat convertFileNameFortranParserCode ( QCString fn)

Definition at line 6306 of file util.cpp.

6307{
6309 QCString parserName = Doxygen::parserManager->getParserName(ext);
6310
6311 if (parserName == "fortranfixed") return FortranFormat::Fixed;
6312 else if (parserName == "fortranfree") return FortranFormat::Free;
6313
6315}
static ParserManager * parserManager
Definition doxygen.h:131
QCString getFileNameExtension(const QCString &fn)
Definition util.cpp:5149

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

Referenced by convertCppComments().

◆ convertNameToFile()

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

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

Definition at line 3425 of file util.cpp.

3426{
3427 if (name.isEmpty()) return name;
3428 bool shortNames = Config_getBool(SHORT_NAMES);
3429 bool createSubdirs = Config_getBool(CREATE_SUBDIRS);
3430 QCString result;
3431 if (shortNames) // use short names only
3432 {
3433 std::lock_guard<std::mutex> lock(g_usedNamesMutex);
3434 auto kv = g_usedNames.find(name.str());
3435 uint32_t num=0;
3436 if (kv!=g_usedNames.end())
3437 {
3438 num = kv->second;
3439 }
3440 else
3441 {
3442 num = g_usedNamesCount;
3443 g_usedNames.emplace(name.str(),g_usedNamesCount++);
3444 }
3445 result.sprintf("a%05d",num);
3446 }
3447 else // long names
3448 {
3449 result=escapeCharsInString(name,allowDots,allowUnderscore);
3450 size_t resultLen = result.length();
3451 if (resultLen>=128) // prevent names that cannot be created!
3452 {
3453 // third algorithm based on MD5 hash
3454 uint8_t md5_sig[16];
3455 char sigStr[33];
3456 MD5Buffer(result.data(),static_cast<unsigned int>(resultLen),md5_sig);
3457 MD5SigToString(md5_sig,sigStr);
3458 result=result.left(128-32)+sigStr;
3459 }
3460 }
3461 if (createSubdirs)
3462 {
3463 int l1Dir=0,l2Dir=0;
3464 int createSubdirsLevel = Config_getInt(CREATE_SUBDIRS_LEVEL);
3465 int createSubdirsBitmaskL2 = (1<<createSubdirsLevel)-1;
3466
3467 // compute md5 hash to determine sub directory to use
3468 uint8_t md5_sig[16];
3469 MD5Buffer(result.data(),static_cast<unsigned int>(result.length()),md5_sig);
3470 l1Dir = md5_sig[14] & 0xf;
3471 l2Dir = md5_sig[15] & createSubdirsBitmaskL2;
3472
3473 result.prepend(QCString().sprintf("d%x/d%02x/",l1Dir,l2Dir));
3474 }
3475 //printf("*** convertNameToFile(%s)->%s\n",qPrint(name),qPrint(result));
3476 return result;
3477}
QCString & prepend(const char *s)
Definition qcstring.h:422
static int g_usedNamesCount
Definition util.cpp:3417
QCString escapeCharsInString(const QCString &name, bool allowDots, bool allowUnderscore)
Definition util.cpp:3251
static std::mutex g_usedNamesMutex
Definition util.cpp:3416
static std::unordered_map< std::string, int > g_usedNames
Definition util.cpp:3415

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

6145{
6146 bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
6147
6148 // default representing 1-1 mapping
6149 *outListType1=inListType;
6150 *outListType2=MemberListType::Invalid();
6151
6152 if (inProt==Protection::Public)
6153 {
6154 if (inListType.isPrivate())
6155 {
6156 *outListType1=MemberListType::Invalid();
6157 }
6158 }
6159 else if (inProt==Protection::Protected)
6160 {
6161 if (inListType.isPrivate() || inListType.isPublic())
6162 {
6163 *outListType1=MemberListType::Invalid();
6164 }
6165 else if (inListType.isProtected())
6166 {
6167 *outListType2=inListType.toPublic();
6168 }
6169 }
6170 else if (inProt==Protection::Private)
6171 {
6172 if (inListType.isPublic() || inListType.isProtected())
6173 {
6174 *outListType1=MemberListType::Invalid();
6175 }
6176 else if (inListType.isPrivate())
6177 {
6178 if (extractPrivate)
6179 {
6180 *outListType1=inListType.toPublic();
6181 *outListType2=inListType.toProtected();
6182 }
6183 else
6184 {
6185 *outListType1=MemberListType::Invalid();
6186 }
6187 }
6188 }
6189
6190 //printf("convertProtectionLevel(type=%s prot=%d): %s,%s\n",
6191 // qPrint(inListType.to_string()),inProt,qPrint(outListType1->to_string()),qPrint(outListType2->to_string()));
6192}
constexpr bool isProtected() const
Definition types.h:380
MemberListType toProtected() const
Definition types.h:438
MemberListType toPublic() const
Definition types.h:426
static MemberListType Invalid()
Definition types.h:371
constexpr bool isPrivate() const
Definition types.h:382
ML_TYPES constexpr bool isPublic() const
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 3884 of file util.cpp.

3885{
3886 if (s.isEmpty()) return s;
3887 GrowBuf growBuf;
3888 const char *p=s.data();
3889 char c = 0;
3890 while ((c=*p++))
3891 {
3892 switch (c)
3893 {
3894 case '<': growBuf.addStr("&lt;"); break;
3895 case '>': growBuf.addStr("&gt;"); break;
3896 case '&': if (keepEntities)
3897 {
3898 const char *e=p;
3899 char ce = 0;
3900 while ((ce=*e++))
3901 {
3902 if (ce==';' || (!(isId(ce) || ce=='#'))) break;
3903 }
3904 if (ce==';') // found end of an entity
3905 {
3906 // copy entry verbatim
3907 growBuf.addChar(c);
3908 while (p<e) growBuf.addChar(*p++);
3909 }
3910 else
3911 {
3912 growBuf.addStr("&amp;");
3913 }
3914 }
3915 else
3916 {
3917 growBuf.addStr("&amp;");
3918 }
3919 break;
3920 case '\'': growBuf.addStr("&#39;"); break;
3921 case '"': growBuf.addStr("&quot;"); break;
3922 default:
3923 {
3924 uint8_t uc = static_cast<uint8_t>(c);
3925 if (uc<32 && !isspace(c))
3926 {
3927 growBuf.addStr("&#x24");
3928 growBuf.addChar(hex[uc>>4]);
3929 growBuf.addChar(hex[uc&0xF]);
3930 growBuf.addChar(';');
3931 }
3932 else
3933 {
3934 growBuf.addChar(c);
3935 }
3936 }
3937 break;
3938 }
3939 }
3940 growBuf.addChar(0);
3941 return growBuf.get();
3942}
static constexpr auto hex
bool isId(int c)
Definition util.h:208

References GrowBuf::addChar(), GrowBuf::addStr(), QCString::data(), GrowBuf::get(), hex, QCString::isEmpty(), and isId().

Referenced by HtmlCodeGenerator::_writeCodeLink(), HtmlHelp::addContentsItem(), convertToHtmlAndTruncate(), FTVHelp::Private::generateLink(), DefinitionImpl::navigationPathAsString(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlGenerator::startFile(), HtmlDocVisitor::startLink(), substituteHtmlKeywords(), 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 3793 of file util.cpp.

3794{
3795 if (s.isEmpty()) return s;
3796 GrowBuf growBuf;
3797 const char *p = s.data();
3798 char c = 0;
3799 bool first = true;
3800 while ((c=*p++))
3801 {
3802 char encChar[4];
3803 if ((c>='0' && c<='9') || (c>='a' && c<='z') || (c>='A' && c<='Z') || c=='-')
3804 { // any permissive character except _
3805 if (first && c>='0' && c<='9') growBuf.addChar('a'); // don't start with a digit
3806 growBuf.addChar(c);
3807 }
3808 else
3809 {
3810 encChar[0]='_';
3811 encChar[1]=hex[static_cast<unsigned char>(c)>>4];
3812 encChar[2]=hex[static_cast<unsigned char>(c)&0xF];
3813 encChar[3]=0;
3814 growBuf.addStr(encChar);
3815 }
3816 first=FALSE;
3817 }
3818 growBuf.addChar(0);
3819 return growBuf.get();
3820}

References GrowBuf::addChar(), GrowBuf::addStr(), QCString::data(), FALSE, GrowBuf::get(), hex, and QCString::isEmpty().

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

3945{
3946 if (s.isEmpty()) return s;
3947 GrowBuf growBuf;
3948 const char *p=s.data();
3949 char c = 0;
3950 while ((c=*p++))
3951 {
3952 switch (c)
3953 {
3954 case '"': if (!singleQuotes) growBuf.addStr("\\\""); else growBuf.addChar(c);
3955 break;
3956 case '\'': if (singleQuotes) growBuf.addStr("\\\'"); else growBuf.addChar(c);
3957 break;
3958 case '\\': if (*p=='u' && *(p+1)=='{') growBuf.addStr("\\"); // keep \u{..} unicode escapes
3959 else growBuf.addStr("\\\\");
3960 break;
3961 default: growBuf.addChar(c); break;
3962 }
3963 }
3964 growBuf.addChar(0);
3965 return keepEntities ? growBuf.get() : convertCharEntitiesToUTF8(growBuf.get());
3966}
QCString convertCharEntitiesToUTF8(const QCString &str)
Definition util.cpp:3968

References GrowBuf::addChar(), GrowBuf::addStr(), convertCharEntitiesToUTF8(), QCString::data(), GrowBuf::get(), and QCString::isEmpty().

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

3834{
3835 if (s.isEmpty()) return s;
3836 GrowBuf growBuf;
3837 const char *p = s.data();
3838 char c = 0;
3839 while ((c=*p++))
3840 {
3841 switch (c)
3842 {
3843 case '<': growBuf.addStr("&lt;"); break;
3844 case '>': growBuf.addStr("&gt;"); break;
3845 case '&': if (keepEntities)
3846 {
3847 const char *e=p;
3848 char ce = 0;
3849 while ((ce=*e++))
3850 {
3851 if (ce==';' || (!(isId(ce) || ce=='#'))) break;
3852 }
3853 if (ce==';') // found end of an entity
3854 {
3855 // copy entry verbatim
3856 growBuf.addChar(c);
3857 while (p<e) growBuf.addChar(*p++);
3858 }
3859 else
3860 {
3861 growBuf.addStr("&amp;");
3862 }
3863 }
3864 else
3865 {
3866 growBuf.addStr("&amp;");
3867 }
3868 break;
3869 case '\'': growBuf.addStr("&apos;"); break;
3870 case '"': growBuf.addStr("&quot;"); break;
3871 case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
3872 case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18:
3873 case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26:
3874 case 27: case 28: case 29: case 30: case 31:
3875 break; // skip invalid XML characters (see http://www.w3.org/TR/2000/REC-xml-20001006#NT-Char)
3876 default: growBuf.addChar(c); break;
3877 }
3878 }
3879 growBuf.addChar(0);
3880 return growBuf.get();
3881}

References GrowBuf::addChar(), GrowBuf::addStr(), QCString::data(), GrowBuf::get(), QCString::isEmpty(), and isId().

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

3827{
3828 if (s.isEmpty()) return s;
3829 return "a" + s;
3830}

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

5838{
5839 QCString result = url;
5840 if (!relPath.isEmpty() && !isURL(url))
5841 {
5842 result.prepend(relPath);
5843 }
5844 return result;
5845}
bool isURL(const QCString &url)
Checks whether the given url starts with a supported protocol.
Definition util.cpp:5825

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

5638{
5639 QCString url;
5640 if (!ref.isEmpty())
5641 {
5642 url = externalRef(relPath,ref,href);
5643 }
5644 if (!targetFileName.isEmpty())
5645 {
5646 QCString fn = targetFileName;
5647 if (ref.isEmpty())
5648 {
5649 if (!anchor.isEmpty() && isLocalFile)
5650 {
5651 fn=""; // omit file name for local links
5652 }
5653 else
5654 {
5655 url = relPath;
5656 }
5657 }
5658 url+=fn;
5659 }
5660 if (!anchor.isEmpty()) url+="#"+anchor;
5661 //printf("createHtmlUrl(relPath=%s,local=%d,target=%s,anchor=%s)=%s\n",qPrint(relPath),isLocalFile,qPrint(targetFileName),qPrint(anchor),qPrint(url));
5662 return url;
5663}
QCString externalRef(const QCString &relPath, const QCString &ref, bool href)
Definition util.cpp:5665

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

3562{
3563 if (Config_getBool(CREATE_SUBDIRS))
3564 {
3565 // create up to 4096 subdirectories
3566 int createSubdirsLevelPow2 = 1 << Config_getInt(CREATE_SUBDIRS_LEVEL);
3567 for (int l1=0; l1<16; l1++)
3568 {
3569 QCString subdir;
3570 subdir.sprintf("d%x",l1);
3571 if (!d.exists(subdir.str()) && !d.mkdir(subdir.str()))
3572 {
3573 term("Failed to create output directory '{}'\n",subdir);
3574 }
3575 for (int l2=0; l2<createSubdirsLevelPow2; l2++)
3576 {
3577 QCString subsubdir;
3578 subsubdir.sprintf("d%x/d%02x",l1,l2);
3579 if (!d.exists(subsubdir.str()) && !d.mkdir(subsubdir.str()))
3580 {
3581 term("Failed to create output directory '{}'\n",subsubdir);
3582 }
3583 }
3584 }
3585 }
3586}
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 6833 of file util.cpp.

6834{
6835 QCString result=name;
6836 if (result.endsWith("-g"))
6837 {
6838 int idx = result.find('-');
6839 result = result.left(idx)+templArgs;
6840 }
6841 return result;
6842}

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

Referenced by ClassDefImpl::className().

◆ detab()

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

Definition at line 6630 of file util.cpp.

6631{
6632 int tabSize = Config_getInt(TAB_SIZE);
6633 size_t size = s.length();
6634 GrowBuf out(size);
6635 const char *data = s.data();
6636 size_t i=0;
6637 int col=0;
6638 constexpr auto doxy_nbsp = "&_doxy_nbsp;"; // doxygen escape command for UTF-8 nbsp
6639 const int maxIndent=1000000; // value representing infinity
6640 int minIndent=maxIndent;
6641 bool skip = false;
6642 while (i<size)
6643 {
6644 char c = data[i++];
6645 switch(c)
6646 {
6647 case '\t': // expand tab
6648 {
6649 int stop = tabSize - (col%tabSize);
6650 //printf("expand at %d stop=%d\n",col,stop);
6651 col+=stop;
6652 while (stop--) out.addChar(' ');
6653 }
6654 break;
6655 case '\\':
6656 if (data[i] == '\\') // escaped command -> ignore
6657 {
6658 out.addChar(c);
6659 out.addChar(data[i++]);
6660 col+=2;
6661 }
6662 else if (i+5<size && literal_at(data+i,"iskip")) // \iskip command
6663 {
6664 i+=5;
6665 skip = true;
6666 }
6667 else if (i+8<size && literal_at(data+i,"endiskip")) // \endiskip command
6668 {
6669 i+=8;
6670 skip = false;
6671 }
6672 else // some other command
6673 {
6674 out.addChar(c);
6675 col++;
6676 }
6677 break;
6678 case '\n': // reset column counter
6679 out.addChar(c);
6680 col=0;
6681 break;
6682 case ' ': // increment column counter
6683 out.addChar(c);
6684 col++;
6685 break;
6686 default: // non-whitespace => update minIndent
6687 if (c<0 && i<size) // multibyte sequence
6688 {
6689 // special handling of the UTF-8 nbsp character 0xC2 0xA0
6690 int nb = isUTF8NonBreakableSpace(data);
6691 if (nb>0)
6692 {
6693 out.addStr(doxy_nbsp);
6694 i+=nb-1;
6695 }
6696 else
6697 {
6698 int bytes = getUTF8CharNumBytes(c);
6699 for (int j=0;j<bytes-1 && c;j++)
6700 {
6701 out.addChar(c);
6702 c = data[i++];
6703 }
6704 out.addChar(c);
6705 }
6706 }
6707 else
6708 {
6709 out.addChar(c);
6710 }
6711 if (!skip && col<minIndent) minIndent=col;
6712 col++;
6713 }
6714 }
6715 if (minIndent!=maxIndent) refIndent=minIndent; else refIndent=0;
6716 out.addChar(0);
6717 //printf("detab(\n%s\n)=[\n%s\n]\n",qPrint(s),qPrint(out.get()));
6718 return out.get();
6719}
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 GrowBuf::addChar(), GrowBuf::addStr(), Config_getInt, QCString::data(), GrowBuf::get(), getUTF8CharNumBytes(), isUTF8NonBreakableSpace(), QCString::length(), and literal_at().

Referenced by Markdown::process().

◆ determineAbsoluteIncludeName()

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

Definition at line 3521 of file util.cpp.

3522{
3523 bool searchIncludes = Config_getBool(SEARCH_INCLUDES);
3524 QCString absIncFileName = incFileName;
3525 FileInfo fi(curFile.str());
3526 if (fi.exists())
3527 {
3528 QCString absName = fi.dirPath(TRUE)+"/"+incFileName;
3529 FileInfo fi2(absName.str());
3530 if (fi2.exists())
3531 {
3532 absIncFileName=fi2.absFilePath();
3533 }
3534 else if (searchIncludes) // search in INCLUDE_PATH as well
3535 {
3536 const StringVector &includePath = Config_getList(INCLUDE_PATH);
3537 for (const auto &incPath : includePath)
3538 {
3539 FileInfo fi3(incPath);
3540 if (fi3.exists() && fi3.isDir())
3541 {
3542 absName = fi3.absFilePath()+"/"+incFileName;
3543 //printf("trying absName=%s\n",qPrint(absName));
3544 FileInfo fi4(absName.str());
3545 if (fi4.exists())
3546 {
3547 absIncFileName=fi4.absFilePath();
3548 break;
3549 }
3550 //printf( "absIncFileName = %s\n", qPrint(absIncFileName) );
3551 }
3552 }
3553 }
3554 //printf( "absIncFileName = %s\n", qPrint(absIncFileName) );
3555 }
3556 return absIncFileName;
3557}
Minimal replacement for QFileInfo.
Definition fileinfo.h:23
#define Config_getList(name)
Definition config.h:38
std::vector< std::string > StringVector
Definition containers.h:33

References FileInfo::absFilePath(), Config_getBool, Config_getList, FileInfo::dirPath(), FileInfo::exists(), FileInfo::isDir(), QCString::str(), and TRUE.

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

◆ escapeCharsInString()

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

Definition at line 3251 of file util.cpp.

3252{
3253 if (name.isEmpty()) return name;
3254 bool caseSenseNames = getCaseSenseNames();
3255 bool allowUnicodeNames = Config_getBool(ALLOW_UNICODE_NAMES);
3256 GrowBuf growBuf;
3257 signed char c = 0;
3258 const char *p=name.data();
3259 while ((c=*p++)!=0)
3260 {
3261 switch(c)
3262 {
3263 case '_': if (allowUnderscore) growBuf.addChar('_'); else growBuf.addStr("__"); break;
3264 case '-': growBuf.addChar('-'); break;
3265 case ':': growBuf.addStr("_1"); break;
3266 case '/': growBuf.addStr("_2"); break;
3267 case '<': growBuf.addStr("_3"); break;
3268 case '>': growBuf.addStr("_4"); break;
3269 case '*': growBuf.addStr("_5"); break;
3270 case '&': growBuf.addStr("_6"); break;
3271 case '|': growBuf.addStr("_7"); break;
3272 case '.': if (allowDots) growBuf.addChar('.'); else growBuf.addStr("_8"); break;
3273 case '!': growBuf.addStr("_9"); break;
3274 case ',': growBuf.addStr("_00"); break;
3275 case ' ': growBuf.addStr("_01"); break;
3276 case '{': growBuf.addStr("_02"); break;
3277 case '}': growBuf.addStr("_03"); break;
3278 case '?': growBuf.addStr("_04"); break;
3279 case '^': growBuf.addStr("_05"); break;
3280 case '%': growBuf.addStr("_06"); break;
3281 case '(': growBuf.addStr("_07"); break;
3282 case ')': growBuf.addStr("_08"); break;
3283 case '+': growBuf.addStr("_09"); break;
3284 case '=': growBuf.addStr("_0a"); break;
3285 case '$': growBuf.addStr("_0b"); break;
3286 case '\\': growBuf.addStr("_0c"); break;
3287 case '@': growBuf.addStr("_0d"); break;
3288 case ']': growBuf.addStr("_0e"); break;
3289 case '[': growBuf.addStr("_0f"); break;
3290 case '#': growBuf.addStr("_0g"); break;
3291 case '"': growBuf.addStr("_0h"); break;
3292 case '~': growBuf.addStr("_0i"); break;
3293 case '\'': growBuf.addStr("_0j"); break;
3294 case ';': growBuf.addStr("_0k"); break;
3295 case '`': growBuf.addStr("_0l"); break;
3296 default:
3297 if (c<0)
3298 {
3299 bool doEscape = true;
3300 if (allowUnicodeNames)
3301 {
3302 int charLen = getUTF8CharNumBytes(c);
3303 if (charLen>0)
3304 {
3305 growBuf.addStr(p-1,charLen);
3306 p+=charLen;
3307 doEscape = false;
3308 }
3309 }
3310 if (doEscape) // not a valid unicode char or escaping needed
3311 {
3312 char ids[5];
3313 unsigned char id = static_cast<unsigned char>(c);
3314 ids[0]='_';
3315 ids[1]='x';
3316 ids[2]=hex[id>>4];
3317 ids[3]=hex[id&0xF];
3318 ids[4]=0;
3319 growBuf.addStr(ids);
3320 }
3321 }
3322 else if (caseSenseNames || !isupper(c))
3323 {
3324 growBuf.addChar(c);
3325 }
3326 else
3327 {
3328 growBuf.addChar('_');
3329 growBuf.addChar(static_cast<char>(tolower(c)));
3330 }
3331 break;
3332 }
3333 }
3334 growBuf.addChar(0);
3335 return growBuf.get();
3336}
bool getCaseSenseNames()
Definition util.cpp:3242

References GrowBuf::addChar(), GrowBuf::addStr(), Config_getBool, QCString::data(), GrowBuf::get(), getCaseSenseNames(), getUTF8CharNumBytes(), hex, and QCString::isEmpty().

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

5622{
5623 bool extLinksInWindow = Config_getBool(EXT_LINKS_IN_WINDOW);
5624 if (extLinksInWindow)
5625 return "target=\"_blank\" ";
5626 else if (parent)
5627 return "target=\"_parent\" ";
5628 else
5629 return "";
5630}
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 5665 of file util.cpp.

5666{
5667 QCString result;
5668 if (!ref.isEmpty())
5669 {
5670 auto it = Doxygen::tagDestinationMap.find(ref.str());
5672 {
5673 result = it->second;
5674 size_t l = result.length();
5675 if (!relPath.isEmpty() && l>0 && result.at(0)=='.')
5676 { // relative path -> prepend relPath.
5677 result.prepend(relPath);
5678 l+=relPath.length();
5679 }
5680 if (l>0 && result.at(l-1)!='/') result+='/';
5681 if (!href) result.append("\" ");
5682 }
5683 }
5684 else
5685 {
5686 result = relPath;
5687 }
5688 return result;
5689}
static StringMap tagDestinationMap
Definition doxygen.h:116
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 6844 of file util.cpp.

6845{
6846 QCString text=rawStart;
6847 int i = text.find('"');
6848 assert(i!=-1);
6849 return text.mid(i+1,text.length()-i-2); // text=...R"xyz( -> delimiter=xyz
6850}

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

4137{
4138 static const reg::Ex re_norm(R"(\a[\w:]*)");
4139 static const reg::Ex re_fortran(R"(\a[\w:()=]*)");
4140 const reg::Ex *re = &re_norm;
4141
4142 name.clear();
4143 templSpec.clear();
4144 if (type.isEmpty()) return -1;
4145 size_t typeLen=type.length();
4146 if (typeLen>0)
4147 {
4148 if (lang == SrcLangExt::Fortran)
4149 {
4150 if (type[pos]==',') return -1;
4151 if (!type.lower().startsWith("type"))
4152 {
4153 re = &re_fortran;
4154 }
4155 }
4156 std::string s = type.str();
4157 reg::Iterator it(s,*re,static_cast<int>(pos));
4159
4160 if (it!=end)
4161 {
4162 const auto &match = *it;
4163 size_t i = match.position();
4164 size_t l = match.length();
4165 size_t ts = i+l;
4166 size_t te = ts;
4167 size_t tl = 0;
4168
4169 while (ts<typeLen && type[static_cast<uint32_t>(ts)]==' ') ts++,tl++; // skip any whitespace
4170 if (ts<typeLen && type[static_cast<uint32_t>(ts)]=='<') // assume template instance
4171 {
4172 // locate end of template
4173 te=ts+1;
4174 int brCount=1;
4175 while (te<typeLen && brCount!=0)
4176 {
4177 if (type[static_cast<uint32_t>(te)]=='<')
4178 {
4179 if (te<typeLen-1 && type[static_cast<uint32_t>(te)+1]=='<') te++; else brCount++;
4180 }
4181 if (type[static_cast<uint32_t>(te)]=='>')
4182 {
4183 if (te<typeLen-1 && type[static_cast<uint32_t>(te)+1]=='>') te++; else brCount--;
4184 }
4185 te++;
4186 }
4187 }
4188 name = match.str();
4189 if (te>ts)
4190 {
4191 templSpec = QCString(type).mid(ts,te-ts);
4192 tl+=te-ts;
4193 pos=static_cast<int>(i+l+tl);
4194 }
4195 else // no template part
4196 {
4197 pos=static_cast<int>(i+l);
4198 }
4199 //printf("extractClassNameFromType([in] type=%s,[out] pos=%d,[out] name=%s,[out] templ=%s)=TRUE i=%d\n",
4200 // qPrint(type),pos,qPrint(name),qPrint(templSpec),i);
4201 return static_cast<int>(i);
4202 }
4203 }
4204 pos = static_cast<int>(typeLen);
4205 //printf("extractClassNameFromType([in] type=%s,[out] pos=%d,[out] name=%s,[out] templ=%s)=FALSE\n",
4206 // qPrint(type),pos,qPrint(name),qPrint(templSpec));
4207 return -1;
4208}
bool startsWith(const char *s) const
Definition qcstring.h:507
QCString lower() const
Definition qcstring.h:249
void clear()
Definition qcstring.h:182

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

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

◆ extractDirection()

QCString extractDirection ( QCString & docs)

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

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

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

Definition at line 6088 of file util.cpp.

6089{
6090 std::string s = docs.str();
6091 static const reg::Ex re(R"(\‍[([ inout,]+)\‍])");
6092 reg::Iterator it(s,re);
6094 if (it!=end)
6095 {
6096 const auto &match = *it;
6097 size_t p = match.position();
6098 size_t l = match.length();
6099 if (p==0 && l>2)
6100 {
6101 // make dir the part inside [...] without separators
6102 std::string dir = match[1].str();
6103 // strip , and ' ' from dir
6104 dir.erase(std::remove_if(dir.begin(),dir.end(),
6105 [](const char c) { return c==' ' || c==','; }
6106 ),dir.end());
6107 unsigned char ioMask=0;
6108 size_t inIndex = dir.find( "in");
6109 if ( inIndex!=std::string::npos) dir.erase( inIndex,2),ioMask|=(1<<0);
6110 size_t outIndex = dir.find("out");
6111 if (outIndex!=std::string::npos) dir.erase(outIndex,3),ioMask|=(1<<1);
6112 if (dir.empty() && ioMask!=0) // only in and/or out attributes found
6113 {
6114 docs = s.substr(l); // strip attributes
6115 if (ioMask==((1<<0)|(1<<1))) return "[in,out]";
6116 else if (ioMask==(1<<0)) return "[in]";
6117 else if (ioMask==(1<<1)) return "[out]";
6118 }
6119 }
6120 }
6121 return "";
6122}

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

Referenced by inlineArgListToDoc().

◆ extractEndRawStringDelimiter()

QCString extractEndRawStringDelimiter ( const char * rawEnd)

Definition at line 6852 of file util.cpp.

6853{
6854 QCString text=rawEnd;
6855 return text.mid(1,text.length()-2); // text=)xyz" -> delimiter=xyz
6856}

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

3621{
3622 int i=0, p=0;
3623 QCString clName=scopeName;
3624 NamespaceDef *nd = nullptr;
3625 if (!clName.isEmpty() && (nd=getResolvedNamespace(clName)) && getClass(clName)==nullptr)
3626 { // the whole name is a namespace (and not a class)
3627 namespaceName=nd->name();
3628 className.clear();
3629 goto done;
3630 }
3631 p=static_cast<int>(clName.length())-2;
3632 while (p>=0 && (i=clName.findRev("::",p))!=-1)
3633 // see if the first part is a namespace (and not a class)
3634 {
3635 //printf("Trying %s\n",qPrint(clName.left(i)));
3636 if (i>0 && (nd=getResolvedNamespace(clName.left(i))) && getClass(clName.left(i))==nullptr)
3637 {
3638 //printf("found!\n");
3639 namespaceName=nd->name();
3640 className=clName.right(clName.length()-i-2);
3641 goto done;
3642 }
3643 p=i-2; // try a smaller piece of the scope
3644 }
3645 //printf("not found!\n");
3646
3647 // not found, so we just have to guess.
3648 className=scopeName;
3649 namespaceName.clear();
3650
3651done:
3652 if (className.isEmpty() && !namespaceName.isEmpty() && !allowEmptyClass)
3653 {
3654 // class and namespace with the same name, correct to return the class.
3655 className=namespaceName;
3656 namespaceName.clear();
3657 }
3658 //printf("extractNamespace '%s' => '%s|%s'\n",qPrint(scopeName),
3659 // qPrint(className),qPrint(namespaceName));
3660 if (className.endsWith("-p"))
3661 {
3662 className = className.left(className.length()-2);
3663 }
3664 return;
3665}
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 1439 of file util.cpp.

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

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

6000{
6001 bool allExternals = Config_getBool(ALLEXTERNALS);
6002 bool isDocFile = fd->isDocumentationFile();
6003 genSourceFile = !isDocFile && fd->generateSourceFile();
6004 return ( ((allExternals && fd->isLinkable()) ||
6006 ) &&
6007 !isDocFile
6008 );
6009}
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 5526 of file util.cpp.

5527{
5528 std::string tf;
5529 std::string t = title.str();
5530 static const reg::Ex re(R"(%[a-z_A-Z]+)");
5531 reg::Iterator it(t,re);
5533 size_t p = 0;
5534 for (; it!=end ; ++it)
5535 {
5536 const auto &match = *it;
5537 size_t i = match.position();
5538 size_t l = match.length();
5539 if (i>p) tf+=t.substr(p,i-p);
5540 tf+=match.str().substr(1); // skip %
5541 p=i+l;
5542 }
5543 tf+=t.substr(p);
5544 return tf;
5545}

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

4884{
4885 static reg::Ex re(R"(\s*(<\a+>)\s*)");
4886 std::string s = sentence.str();
4887 reg::Iterator it(s,re);
4889 std::string result;
4890 bool found=false;
4891 size_t p=0;
4892 for ( ; it!=end ; ++it)
4893 {
4894 const auto match = *it;
4895 std::string part = match[1].str();
4896 if (part!=word)
4897 {
4898 size_t i = match.position();
4899 size_t l = match.length();
4900 result+=s.substr(p,i-p);
4901 result+=match.str();
4902 p=i+l;
4903 }
4904 else
4905 {
4906 found=true;
4907 size_t i = match[1].position();
4908 size_t l = match[1].length();
4909 result+=s.substr(p,i-p);
4910 p=i+l;
4911 }
4912 }
4913 result+=s.substr(p);
4914 sentence = QCString(result).simplifyWhiteSpace();
4915 return found;
4916}
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 2823 of file util.cpp.

2824{
2825 ambig=FALSE;
2826 if (n.isEmpty()) return nullptr;
2827
2828
2829 const int maxAddrSize = 20;
2830 char addr[maxAddrSize];
2831 qsnprintf(addr,maxAddrSize,"%p:",reinterpret_cast<const void*>(fnMap));
2832 QCString key = addr;
2833 key+=n;
2834
2835 std::lock_guard<std::mutex> lock(g_findFileDefMutex);
2836 FindFileCacheElem *cachedResult = g_findFileDefCache.find(key.str());
2837 //printf("key=%s cachedResult=%p\n",qPrint(key),cachedResult);
2838 if (cachedResult)
2839 {
2840 ambig = cachedResult->isAmbig;
2841 //printf("cached: fileDef=%p\n",cachedResult->fileDef);
2842 return cachedResult->fileDef;
2843 }
2844 else
2845 {
2846 cachedResult = g_findFileDefCache.insert(key.str(),FindFileCacheElem(nullptr,FALSE));
2847 }
2848
2849 QCString name=Dir::cleanDirPath(n.str());
2850 QCString path;
2851 if (name.isEmpty()) return nullptr;
2852 int slashPos=std::max(name.findRev('/'),name.findRev('\\'));
2853 if (slashPos!=-1)
2854 {
2855 path=removeLongPathMarker(name.left(slashPos+1));
2856 name=name.right(name.length()-slashPos-1);
2857 }
2858 if (name.isEmpty()) return nullptr;
2859 const FileName *fn = fnMap->find(name);
2860 if (fn)
2861 {
2862 //printf("fn->size()=%zu\n",fn->size());
2863 if (fn->size()==1)
2864 {
2865 const std::unique_ptr<FileDef> &fd = fn->front();
2866 bool isSamePath = Portable::fileSystemIsCaseSensitive() ?
2867 fd->getPath().right(path.length())==path :
2868 fd->getPath().right(path.length()).lower()==path.lower();
2869 if (path.isEmpty() || isSamePath)
2870 {
2871 cachedResult->fileDef = fd.get();
2872 return fd.get();
2873 }
2874 }
2875 else // file name alone is ambiguous
2876 {
2877 int count=0;
2878 FileDef *lastMatch=nullptr;
2879 QCString pathStripped = stripFromIncludePath(path);
2880 for (const auto &fd_p : *fn)
2881 {
2882 FileDef *fd = fd_p.get();
2883 QCString fdStripPath = stripFromIncludePath(fd->getPath());
2884 if (path.isEmpty() ||
2885 (!pathStripped.isEmpty() && fdStripPath.endsWith(pathStripped)) ||
2886 (pathStripped.isEmpty() && fdStripPath.isEmpty()))
2887 {
2888 count++;
2889 lastMatch=fd;
2890 }
2891 }
2892
2893 ambig=(count>1);
2894 cachedResult->isAmbig = ambig;
2895 cachedResult->fileDef = lastMatch;
2896 return lastMatch;
2897 }
2898 }
2899 else
2900 {
2901 //printf("not found!\n");
2902 }
2903 return nullptr;
2904}
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:2813
FileDef * fileDef
Definition util.cpp:2815
QCString stripFromIncludePath(const QCString &path)
Definition util.cpp:338
static Cache< std::string, FindFileCacheElem > g_findFileDefCache(5000)
static std::mutex g_findFileDefMutex
Definition util.cpp:2821
QCString removeLongPathMarker(QCString path)
Definition util.cpp:296

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

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

◆ findFilePath()

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

Definition at line 2908 of file util.cpp.

2909{
2910 ambig=false;
2911 QCString result;
2912 bool found=false;
2913 if (!found)
2914 {
2915 FileInfo fi(file.str());
2916 if (fi.exists())
2917 {
2918 result=fi.absFilePath();
2919 found=true;
2920 }
2921 }
2922 if (!found)
2923 {
2924 const StringVector &examplePathList = Config_getList(EXAMPLE_PATH);
2925 for (const auto &s : examplePathList)
2926 {
2927 std::string absFileName = s+(Portable::pathSeparator()+file).str();
2928 FileInfo fi(absFileName);
2929 if (fi.exists())
2930 {
2931 result=fi.absFilePath();
2932 found=true;
2933 }
2934 }
2935 }
2936
2937 if (!found)
2938 {
2939 // as a fallback we also look in the exampleNameDict
2941 if (fd && !ambig)
2942 {
2943 result=fd->absFilePath();
2944 }
2945 }
2946 return result;
2947}
static FileNameLinkedMap * exampleNameLinkedMap
Definition doxygen.h:103
virtual QCString absFilePath() const =0
QCString pathSeparator()
Definition portable.cpp:375
FileDef * findFileDef(const FileNameLinkedMap *fnMap, const QCString &n, bool &ambig)
Definition util.cpp:2823

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

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

◆ findIndex() [1/2]

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

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

Definition at line 6572 of file util.cpp.

6573{
6575 return reg::search(s,match,re) ? static_cast<int>(match.position()) : -1;
6576}
Object representing the matching results.
Definition regex.h:153
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:748

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

6565{
6566 auto it = std::find(sv.begin(),sv.end(),s);
6567 return it!=sv.end() ? static_cast<int>(it-sv.begin()) : -1;
6568}

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

◆ fixSpaces()

QCString fixSpaces ( const QCString & s)
inline

Definition at line 470 of file util.h.

470{ 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:482

References substitute().

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

◆ generateAnonymousAnchor()

QCString generateAnonymousAnchor ( const QCString & fileName,
int count )

Definition at line 3479 of file util.cpp.

3480{
3481 QCString fn = stripFromPath(fileName)+":"+QCString().setNum(count);
3482 const int sig_size=16;
3483 uint8_t md5_sig[sig_size];
3484 MD5Buffer(fn.data(),static_cast<unsigned int>(fn.length()),md5_sig);
3485 char result[sig_size*3+2];
3486 char *p = result;
3487 *p++='@';
3488 for (int i=0;i<sig_size;i++)
3489 {
3490 static const char oct[]="01234567";
3491 uint8_t byte = md5_sig[i];
3492 *p++=oct[(byte>>6)&7];
3493 *p++=oct[(byte>>3)&7];
3494 *p++=oct[(byte>>0)&7];
3495 }
3496 *p='\0';
3497 return result;
3498}
QCString & setNum(short n)
Definition qcstring.h:459
static QCString stripFromPath(const QCString &p, const StringVector &l)
Definition util.cpp:307

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

◆ generateFileRef()

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

Definition at line 2795 of file util.cpp.

2796{
2797 //printf("generateFileRef(%s,%s)\n",name,text);
2798 QCString linkText = text.isEmpty() ? text : name;
2799 //FileInfo *fi;
2800 bool ambig = false;
2802 if (fd && fd->isLinkable())
2803 // link to documented input file
2804 ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),QCString(),linkText);
2805 else
2806 ol.docify(linkText);
2807}
static FileNameLinkedMap * inputNameLinkedMap
Definition doxygen.h:105
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 288 of file util.cpp.

289{
290 const int maxMarkerStrLen = 20;
291 char result[maxMarkerStrLen];
292 qsnprintf(result,maxMarkerStrLen,"@%d",id);
293 return result;
294}

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

3243{
3244 auto caseSenseNames = Config_getEnum(CASE_SENSE_NAMES);
3245
3246 if (caseSenseNames == CASE_SENSE_NAMES_t::YES) return true;
3247 else if (caseSenseNames == CASE_SENSE_NAMES_t::NO) return false;
3249}
#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 2227 of file util.cpp.

2228{
2229 GetDefResult result;
2230 if (input.memberName.isEmpty()) return result;
2231 AUTO_TRACE("getDefsNew(scopeName={},memberName={},forceEmptyScope={})",
2232 input.scopeName,input.memberName,input.forceEmptyScope);
2233
2234 //printf("@@ --- getDefsNew(%s,%s)-----------\n",qPrint(scName),qPrint(mbName));
2235 const Definition *scope = Doxygen::globalScope;
2236 SymbolResolver resolver;
2237 if (input.currentFile) resolver.setFileScope(input.currentFile);
2238 if (!input.scopeName.isEmpty() && !input.forceEmptyScope)
2239 {
2240 scope = resolver.resolveSymbol(scope,input.scopeName);
2241 }
2242 if (scope==Doxygen::globalScope)
2243 {
2244 scope = input.currentFile;
2245 }
2246 //printf("@@ -> found scope scope=%s member=%s out=%s\n",qPrint(input.scopeName),qPrint(input.memberName),qPrint(scope?scope->name():""));
2247 //
2248 const Definition *symbol = resolver.resolveSymbol(scope,input.memberName,input.args,input.checkCV,input.insideCode,true);
2249 //printf("@@ -> found symbol in=%s out=%s\n",qPrint(input.memberName),qPrint(symbol?symbol->qualifiedName():QCString()));
2250 if (symbol && symbol->definitionType()==Definition::TypeMember)
2251 {
2252 result.md = toMemberDef(symbol);
2253 result.cd = result.md->getClassDef();
2254 if (result.cd==nullptr) result.nd = result.md->getNamespaceDef();
2255 if (result.cd==nullptr && result.nd==nullptr) result.fd = result.md->getFileDef();
2256 result.gd = result.md->getGroupDef();
2257 result.found = true;
2258 }
2259 else if (symbol && symbol->definitionType()==Definition::TypeClass)
2260 {
2261 result.cd = toClassDef(symbol);
2262 result.found = true;
2263 }
2264 else if (symbol && symbol->definitionType()==Definition::TypeNamespace)
2265 {
2266 result.nd = toNamespaceDef(symbol);
2267 result.found = true;
2268 }
2269 else if (symbol && symbol->definitionType()==Definition::TypeConcept)
2270 {
2271 result.cnd = toConceptDef(symbol);
2272 result.found = true;
2273 }
2274 else if (symbol && symbol->definitionType()==Definition::TypeModule)
2275 {
2276 result.modd = toModuleDef(symbol);
2277 result.found = true;
2278 }
2279 return result;
2280}
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:121
virtual const ClassDef * getClassDef() const =0
virtual GroupDef * getGroupDef()=0
virtual const FileDef * getFileDef() const =0
virtual const NamespaceDef * getNamespaceDef() const =0
const Definition * resolveSymbol(const Definition *scope, const 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)
#define AUTO_TRACE(...)
Definition docnode.cpp:46
MemberDef * toMemberDef(Definition *d)
ModuleDef * toModuleDef(Definition *d)
NamespaceDef * toNamespaceDef(Definition *d)
bool forceEmptyScope
Definition util.h:116
const FileDef * currentFile
Definition util.h:117
QCString scopeName
Definition util.h:113
bool insideCode
Definition util.h:119
bool checkCV
Definition util.h:118
QCString args
Definition util.h:115
QCString memberName
Definition util.h:114
const MemberDef * md
Definition util.h:125
const ConceptDef * cnd
Definition util.h:130
const FileDef * fd
Definition util.h:127
const ModuleDef * modd
Definition util.h:131
const GroupDef * gd
Definition util.h:129
bool found
Definition util.h:124
const ClassDef * cd
Definition util.h:126
const NamespaceDef * nd
Definition util.h:128

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

6200{
6201 QCString imgExt = Config_getEnumAsString(DOT_IMAGE_FORMAT);
6202 int i= imgExt.find(':'); // strip renderer part when using e.g. 'png:cairo:gd' as format
6203 return i==-1 ? imgExt : imgExt.left(i);
6204}
#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 5607 of file util.cpp.

5608{
5609 InputFileEncoding elem;
5610 auto getter = [](const InputFileEncoding &e) -> QCString { return e.pattern; };
5611 if (genericPatternMatch(fi,Doxygen::inputFileEncodingList,elem,getter)) // check for file specific encoding
5612 {
5613 return elem.encoding;
5614 }
5615 else // fall back to default encoding
5616 {
5617 return Config_getString(INPUT_ENCODING);
5618 }
5619}
static InputFileEncodingList inputFileEncodingList
Definition doxygen.h:140
#define Config_getString(name)
Definition config.h:32
QCString encoding
Definition doxygen.h:71
bool genericPatternMatch(const FileInfo &fi, const PatternList &patList, PatternElem &elem, PatternGet getter)
Definition util.cpp:5550

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

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

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

5126{
5127 // try the extension
5128 auto lang = getLanguageFromFileName(fileName, SrcLangExt::Unknown);
5129 if (lang == SrcLangExt::Unknown)
5130 {
5131 // try the language names
5132 QCString langName = fileName.lower();
5133 if (langName.at(0)=='.') langName = langName.mid(1);
5134 auto it = std::find_if(g_lang2extMap.begin(),g_lang2extMap.end(),
5135 [&langName](const auto &info) { return info.langName==langName; });
5136 if (it != g_lang2extMap.end())
5137 {
5138 lang = it->parserId;
5139 fileName = it->defExt;
5140 }
5141 else // default to C++
5142 {
5143 return SrcLangExt::Cpp;
5144 }
5145 }
5146 return lang;
5147}
SrcLangExt getLanguageFromFileName(const QCString &fileName, SrcLangExt defLang)
Definition util.cpp:5107
static std::vector< Lang2ExtMap > g_lang2extMap
Definition util.cpp:4978

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

5108{
5109 FileInfo fi(fileName.str());
5110 // we need only the part after the last ".", newer implementations of FileInfo have 'suffix()' for this.
5111 QCString extName = QCString(fi.extension(FALSE)).lower();
5112 if (extName.isEmpty()) extName=".no_extension";
5113 if (extName.at(0)!='.') extName.prepend(".");
5114 auto it = g_extLookup.find(extName.str());
5115 if (it!=g_extLookup.end()) // listed extension
5116 {
5117 //printf("getLanguageFromFileName(%s)=%x\n",qPrint(fi.extension()),*pVal);
5118 return it->second;
5119 }
5120 //printf("getLanguageFromFileName(%s) not found!\n",qPrint(fileName));
5121 return defLang; // not listed => assume C-ish language.
5122}
static std::unordered_map< std::string, SrcLangExt > g_extLookup
Definition util.cpp:4968

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

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

◆ getLanguageSpecificSeparator()

QCString getLanguageSpecificSeparator ( SrcLangExt lang,
bool classScope = FALSE )

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

Definition at line 5809 of file util.cpp.

5810{
5811 if (lang==SrcLangExt::Java || lang==SrcLangExt::CSharp || lang==SrcLangExt::VHDL || lang==SrcLangExt::Python)
5812 {
5813 return ".";
5814 }
5815 else if (lang==SrcLangExt::PHP && !classScope)
5816 {
5817 return "\\";
5818 }
5819 else
5820 {
5821 return "::";
5822 }
5823}

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

4011{
4012 return theTranslator->trOverloadText();
4013 //"This is an overloaded member function, "
4014 // "provided for convenience. It differs from the above "
4015 // "function only in what argument(s) it accepts.";
4016}
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 3158 of file util.cpp.

3159{
3160 if (name.isEmpty()) return 0;
3161 const StringVector &sl = Config_getList(IGNORE_PREFIX);
3162 for (const auto &s : sl)
3163 {
3164 const char *ps=s.c_str();
3165 const char *pd=name.data();
3166 int i=0;
3167 while (*ps!=0 && *pd!=0 && *ps==*pd) ps++,pd++,i++;
3168 if (*ps==0 && *pd!=0)
3169 {
3170 return i;
3171 }
3172 }
3173 return 0;
3174}

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

6722{
6723 QCString projectCookie = Config_getString(HTML_PROJECT_COOKIE);
6724 if (projectCookie.isEmpty()) return QCString();
6725 uint8_t md5_sig[16];
6726 char sigStr[34];
6727 MD5Buffer(projectCookie.data(),static_cast<unsigned int>(projectCookie.length()),md5_sig);
6728 MD5SigToString(md5_sig,sigStr);
6729 sigStr[32]='_'; sigStr[33]=0;
6730 return sigStr;
6731}

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

4550{
4551 int sl=static_cast<int>(s.length());
4552 int sp=p;
4553 int count=0;
4554 bool done=false;
4555 if (sp>=sl) return -1;
4556 while (sp<sl)
4557 {
4558 char c=s.at(sp);
4559 if (c==':') sp++,p++; else break;
4560 }
4561 while (sp<sl)
4562 {
4563 char c=s.at(sp);
4564 switch (c)
4565 {
4566 case ':': // found next part
4567 goto found;
4568 case '<': // skip template specifier
4569 count=1;sp++;
4570 done=false;
4571 while (sp<sl && !done)
4572 {
4573 // TODO: deal with << and >> operators!
4574 c=s.at(sp++);
4575 switch(c)
4576 {
4577 case '<': count++; break;
4578 case '>': count--; if (count==0) done=true; break;
4579 default: break;
4580 }
4581 }
4582 break;
4583 default:
4584 sp++;
4585 break;
4586 }
4587 }
4588found:
4589 *l=sp-p;
4590 //printf("getScopeFragment(%s,%d)=%s\n",qPrint(s),p,qPrint(s.mid(p,*l)));
4591 return p;
4592}

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

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

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

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

◆ initDefaultExtensionMapping()

void initDefaultExtensionMapping ( )

Definition at line 5034 of file util.cpp.

5035{
5036 // NOTE: when adding an extension, also add the extension in config.xml
5037 // extension parser id
5038 updateLanguageMapping(".dox", "c");
5039 updateLanguageMapping(".txt", "c"); // see bug 760836
5040 updateLanguageMapping(".doc", "c");
5041 updateLanguageMapping(".c", "c");
5042 updateLanguageMapping(".C", "c");
5043 updateLanguageMapping(".cc", "c");
5044 updateLanguageMapping(".CC", "c");
5045 updateLanguageMapping(".cxx", "c");
5046 updateLanguageMapping(".cpp", "c");
5047 updateLanguageMapping(".c++", "c");
5048 updateLanguageMapping(".cxxm", "c"); // C++20 modules
5049 updateLanguageMapping(".cppm", "c"); // C++20 modules
5050 updateLanguageMapping(".ccm", "c"); // C++20 modules
5051 updateLanguageMapping(".c++m", "c"); // C++20 modules
5052 updateLanguageMapping(".ii", "c");
5053 updateLanguageMapping(".ixx", "c");
5054 updateLanguageMapping(".ipp", "c");
5055 updateLanguageMapping(".i++", "c");
5056 updateLanguageMapping(".inl", "c");
5057 updateLanguageMapping(".h", "c");
5058 updateLanguageMapping(".H", "c");
5059 updateLanguageMapping(".hh", "c");
5060 updateLanguageMapping(".HH", "c");
5061 updateLanguageMapping(".hxx", "c");
5062 updateLanguageMapping(".hpp", "c");
5063 updateLanguageMapping(".h++", "c");
5064 updateLanguageMapping(".idl", "idl");
5065 updateLanguageMapping(".ddl", "idl");
5066 updateLanguageMapping(".odl", "idl");
5067 updateLanguageMapping(".java", "java");
5068 //updateLanguageMapping(".as", "javascript"); // not officially supported
5069 //updateLanguageMapping(".js", "javascript"); // not officially supported
5070 updateLanguageMapping(".cs", "csharp");
5071 updateLanguageMapping(".d", "d");
5072 updateLanguageMapping(".php", "php");
5073 updateLanguageMapping(".php4", "php");
5074 updateLanguageMapping(".php5", "php");
5075 updateLanguageMapping(".inc", "php");
5076 updateLanguageMapping(".phtml", "php");
5077 updateLanguageMapping(".m", "objective-c");
5078 updateLanguageMapping(".M", "objective-c");
5079 updateLanguageMapping(".mm", "c"); // see bug746361
5080 updateLanguageMapping(".py", "python");
5081 updateLanguageMapping(".pyw", "python");
5082 updateLanguageMapping(".f", "fortran");
5083 updateLanguageMapping(".for", "fortran");
5084 updateLanguageMapping(".f90", "fortran");
5085 updateLanguageMapping(".f95", "fortran");
5086 updateLanguageMapping(".f03", "fortran");
5087 updateLanguageMapping(".f08", "fortran");
5088 updateLanguageMapping(".f18", "fortran");
5089 updateLanguageMapping(".vhd", "vhdl");
5090 updateLanguageMapping(".vhdl", "vhdl");
5091 updateLanguageMapping(".ucf", "vhdl");
5092 updateLanguageMapping(".qsf", "vhdl");
5093 updateLanguageMapping(".md", "md");
5094 updateLanguageMapping(".markdown", "md");
5095 updateLanguageMapping(".ice", "slice");
5096 updateLanguageMapping(".l", "lex");
5097 updateLanguageMapping(".doxygen_lex_c", "c"); // this is a placeholder so we can map initializations
5098 // in the lex scanning to cpp
5099}

References updateLanguageMapping().

Referenced by initDoxygen().

◆ inlineArgListToDoc()

QCString inlineArgListToDoc ( const ArgumentList & al)

Definition at line 1154 of file util.cpp.

1155{
1156 QCString paramDocs;
1157 if (al.hasDocumentation())
1158 {
1159 for (const Argument &a : al)
1160 {
1161 if (a.hasDocumentation())
1162 {
1163 QCString docsWithoutDir = a.docs;
1164 QCString direction = extractDirection(docsWithoutDir);
1165 paramDocs+=" \\ilinebr @param"+direction+" "+a.name+" "+docsWithoutDir;
1166 }
1167 }
1168 }
1169 return paramDocs;
1170}
bool hasDocumentation() const
Definition arguments.cpp:21
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:6088

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

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

◆ inlineTemplateArgListToDoc()

QCString inlineTemplateArgListToDoc ( const ArgumentList & al)

Definition at line 1172 of file util.cpp.

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

3668{
3669 QCString result=scope;
3670 if (!templ.isEmpty() && scope.find('<')==-1)
3671 {
3672 int si=0, pi=0;
3673 ClassDef *cd=nullptr;
3674 while (
3675 (si=scope.find("::",pi))!=-1 && !getClass(scope.left(si)+templ) &&
3676 ((cd=getClass(scope.left(si)))==nullptr || cd->templateArguments().empty())
3677 )
3678 {
3679 //printf("Tried '%s'\n",qPrint((scope.left(si)+templ)));
3680 pi=si+2;
3681 }
3682 if (si==-1) // not nested => append template specifier
3683 {
3684 result+=templ;
3685 }
3686 else // nested => insert template specifier before after first class name
3687 {
3688 result=scope.left(si) + templ + scope.right(scope.length()-si);
3689 }
3690 }
3691 //printf("insertTemplateSpecifierInScope('%s','%s')=%s\n",
3692 // qPrint(scope),qPrint(templ),qPrint(result));
3693 return result;
3694}
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 6592 of file util.cpp.

6593{
6594 QCString result;
6595 int residual = n;
6596
6597 char modVal[2];
6598 modVal[1] = 0;
6599 while (residual > 0)
6600 {
6601 modVal[0] = (upper ? 'A': 'a') + (residual-1)%26;
6602 result = modVal + result;
6603 residual = (residual-1) / 26;
6604 }
6605 return result;
6606}

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

◆ integerToRoman()

QCString integerToRoman ( int n,
bool upper = true )

Definition at line 6608 of file util.cpp.

6609{
6610 static const char *str_romans_upper[] = { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" };
6611 static const char *str_romans_lower[] = { "m", "cm", "d", "cd", "c", "xc", "l", "xl", "x", "ix", "v", "iv", "i" };
6612 static const int values[] = { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 };
6613 static const char **str_romans = upper ? str_romans_upper : str_romans_lower;
6614
6615 QCString result;
6616 int residual = n;
6617
6618 for (int i = 0; i < 13; ++i)
6619 {
6620 while (residual - values[i] >= 0)
6621 {
6622 result += str_romans[i];
6623 residual -= values[i];
6624 }
6625 }
6626
6627 return result;
6628}

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

◆ isId()

◆ isIdJS()

bool isIdJS ( int c)
inline

Definition at line 212 of file util.h.

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

Referenced by SearchTerm::termEncoded().

◆ isURL()

bool isURL ( const QCString & url)

Checks whether the given url starts with a supported protocol.

Definition at line 5825 of file util.cpp.

5826{
5827 static const std::unordered_set<std::string> schemes = {
5828 "http", "https", "ftp", "ftps", "sftp", "file", "news", "irc", "ircs"
5829 };
5830 QCString loc_url = url.stripWhiteSpace();
5831 int colonPos = loc_url.find(':');
5832 return colonPos!=-1 && schemes.find(loc_url.left(colonPos).str())!=schemes.end();
5833}

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

6580{
6581 std::string result;
6582 bool first=true;
6583 for (const auto &s : sv)
6584 {
6585 if (!first) result+=delimiter;
6586 first=false;
6587 result+=s;
6588 }
6589 return result;
6590}

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

◆ langToString()

QCString langToString ( SrcLangExt lang)

Returns a string representation of lang.

Definition at line 5803 of file util.cpp.

5804{
5805 return to_string(lang);
5806}
static const char * to_string(Protection prot)
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 890 of file util.cpp.

891{
892 size_t sl=scope.length();
893 size_t nl=name.length();
894 return (name==scope || // equal
895 (name.left(sl)==scope && // substring
896 nl>sl+1 && name.at(sl)==':' && name.at(sl+1)==':' // scope
897 )
898 );
899}

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

5783{
5784 int result = 1;
5785
5786 // find the character positions of the first marker
5787 int m1 = text.find(marker);
5788 if (m1==-1) return result;
5789
5790 // find start line positions for the markers
5791 bool found=false;
5792 int p=0, i=0;
5793 while (!found && (i=text.find('\n',p))!=-1)
5794 {
5795 found = (p<=m1 && m1<i); // found the line with the start marker
5796 p=i+1;
5797 result++;
5798 }
5799 return result;
5800}

References QCString::find().

Referenced by readIncludeFile().

◆ linkifyText()

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

Definition at line 902 of file util.cpp.

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

References Definition::anchor(), 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(), 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 2627 of file util.cpp.

2628{
2629 //bool optimizeOutputJava = Config_getBool(OPTIMIZE_OUTPUT_JAVA);
2630 QCString result=link;
2631 if (!result.isEmpty())
2632 {
2633 // replace # by ::
2634 result=substitute(result,"#","::");
2635 // replace . by ::
2636 if (!isFileName && result.find('<')==-1) result=substitute(result,".","::",3);
2637 // strip leading :: prefix if present
2638 if (result.at(0)==':' && result.at(1)==':')
2639 {
2640 result=result.right(result.length()-2);
2641 }
2643 if (sep!="::")
2644 {
2645 result=substitute(result,"::",sep);
2646 }
2647 }
2648 //printf("linkToText(%s,lang=%d)=%s\n",qPrint(link),lang,qPrint(result));
2649 return result;
2650}
QCString getLanguageSpecificSeparator(SrcLangExt lang, bool classScope)
Returns the scope separator to use given the programming language lang.
Definition util.cpp:5809

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

6195{
6196 return Doxygen::mainPage!=nullptr && Doxygen::mainPage->hasTitle();
6197}
static std::unique_ptr< PageDef > mainPage
Definition doxygen.h:101

References Doxygen::mainPage.

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

◆ mangleCSharpGenericName()

QCString mangleCSharpGenericName ( const QCString & name)

Definition at line 6823 of file util.cpp.

6824{
6825 int idx = name.find('<');
6826 if (idx!=-1)
6827 {
6828 return name.left(idx)+"-"+QCString().setNum(name.contains(",")+1)+"-g";
6829 }
6830 return name;
6831}
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 ArgumentList * srcAl,
const Definition * dstScope,
const FileDef * dstFileScope,
const ArgumentList * dstAl,
bool checkCV,
SrcLangExt lang )

Definition at line 1956 of file util.cpp.

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

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(), 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 2194 of file util.cpp.

2195{
2196 AUTO_TRACE("srcAl=%s dstAl=%s",argListToString(srcAl),argListToString(dstAl));
2197 if (srcAl.size()!=dstAl.size()) // different number of template parameters -> overload
2198 {
2199 AUTO_TRACE_EXIT("different number of parameters");
2200 return false;
2201 }
2202 auto isUnconstraintTemplate = [](const QCString &type)
2203 {
2204 return type=="typename" || type=="class" || type.startsWith("typename ") || type.startsWith("class ");
2205 };
2206 auto srcIt = srcAl.begin();
2207 auto dstIt = dstAl.begin();
2208 while (srcIt!=srcAl.end() && dstIt!=dstAl.end())
2209 {
2210 const Argument &srcA = *srcIt;
2211 const Argument &dstA = *dstIt;
2212 if ((!isUnconstraintTemplate(srcA.type) || !isUnconstraintTemplate(dstA.type)) && srcA.type!=dstA.type) // different constraints -> overload
2213 {
2214 AUTO_TRACE_EXIT("different constraints");
2215 return false;
2216 }
2217 ++srcIt;
2218 ++dstIt;
2219 }
2220 AUTO_TRACE_EXIT("same");
2221 // no overload with respect to the template parameters
2222 return true;
2223}
#define AUTO_TRACE_EXIT(...)
Definition docnode.cpp:48

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

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

6772{
6773 if (Config_getBool(CALL_GRAPH) !=md1->hasCallGraph()) md2->overrideCallGraph(md1->hasCallGraph());
6774 if (Config_getBool(CALLER_GRAPH)!=md1->hasCallerGraph()) md2->overrideCallerGraph(md1->hasCallerGraph());
6775 if (Config_getBool(CALL_GRAPH) !=md2->hasCallGraph()) md1->overrideCallGraph( md2->hasCallGraph());
6776 if (Config_getBool(CALLER_GRAPH)!=md2->hasCallerGraph()) md1->overrideCallerGraph(md2->hasCallerGraph());
6777
6778 if (Config_getBool(SHOW_ENUM_VALUES) !=md1->hasEnumValues()) md2->overrideEnumValues(md1->hasEnumValues());
6779 if (Config_getBool(SHOW_ENUM_VALUES) !=md2->hasEnumValues()) md1->overrideEnumValues( md2->hasEnumValues());
6780
6781 if (Config_getBool(REFERENCED_BY_RELATION)!=md1->hasReferencedByRelation()) md2->overrideReferencedByRelation(md1->hasReferencedByRelation());
6782 if (Config_getBool(REFERENCES_RELATION) !=md1->hasReferencesRelation()) md2->overrideReferencesRelation(md1->hasReferencesRelation());
6783 if (Config_getBool(REFERENCED_BY_RELATION)!=md2->hasReferencedByRelation()) md1->overrideReferencedByRelation(md2->hasReferencedByRelation());
6784 if (Config_getBool(REFERENCES_RELATION) !=md2->hasReferencesRelation()) md1->overrideReferencesRelation(md2->hasReferencesRelation());
6785
6786 if (Config_getBool(INLINE_SOURCES)!=md1->hasInlineSource()) md2->overrideInlineSource(md1->hasInlineSource());
6787 if (Config_getBool(INLINE_SOURCES)!=md2->hasInlineSource()) md1->overrideInlineSource(md2->hasInlineSource());
6788}
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 4504 of file util.cpp.

4505{
4506 AUTO_TRACE("leftScope='{}' rightScope='{}'",leftScope,rightScope);
4507 // case leftScope=="A" rightScope=="A::B" => result = "A::B"
4508 if (leftScopeMatch(leftScope,rightScope))
4509 {
4510 AUTO_TRACE_EXIT("case1={}",rightScope);
4511 return rightScope;
4512 }
4513 QCString result;
4514 int i=0,p=static_cast<int>(leftScope.length());
4515
4516 // case leftScope=="A::B" rightScope=="B::C" => result = "A::B::C"
4517 // case leftScope=="A::B" rightScope=="B" => result = "A::B"
4518 bool found=FALSE;
4519 while ((i=leftScope.findRev("::",p))>0)
4520 {
4521 if (leftScopeMatch(rightScope,leftScope.right(leftScope.length()-i-2)))
4522 {
4523 result = leftScope.left(i+2)+rightScope;
4524 found=TRUE;
4525 }
4526 p=i-1;
4527 }
4528 if (found)
4529 {
4530 AUTO_TRACE_EXIT("case2={}",result);
4531 return result;
4532 }
4533
4534 // case leftScope=="A" rightScope=="B" => result = "A::B"
4535 result=leftScope;
4536 if (!result.isEmpty() && !rightScope.isEmpty()) result+="::";
4537 result+=rightScope;
4538 AUTO_TRACE_EXIT("case3={}",result);
4539 return result;
4540}
bool leftScopeMatch(const QCString &scope, const QCString &name)
Definition util.cpp:890

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

4214{
4215 // skip until <
4216 int p=name.find('<');
4217 if (p==-1) return name;
4218 p++;
4219 QCString result = name.left(p);
4220
4221 std::string s = name.mid(p).str();
4222 static const reg::Ex re(R"([\a:][\w:]*)");
4223 reg::Iterator it(s,re);
4225 size_t pi=0;
4226 // for each identifier in the template part (e.g. B<T> -> T)
4227 for (; it!=end ; ++it)
4228 {
4229 const auto &match = *it;
4230 size_t i = match.position();
4231 size_t l = match.length();
4232 result += s.substr(pi,i-pi);
4233 QCString n(match.str());
4234 bool found=FALSE;
4235 for (const Argument &formArg : formalArgs)
4236 {
4237 if (formArg.name == n)
4238 {
4239 found=TRUE;
4240 break;
4241 }
4242 }
4243 if (!found)
4244 {
4245 // try to resolve the type
4246 SymbolResolver resolver;
4247 const ClassDef *cd = resolver.resolveClass(context,n);
4248 if (cd)
4249 {
4250 result+=cd->name();
4251 }
4252 else
4253 {
4254 result+=n;
4255 }
4256 }
4257 else
4258 {
4259 result+=n;
4260 }
4261 pi=i+l;
4262 }
4263 result+=s.substr(pi);
4264 //printf("normalizeNonTemplateArgumentInString(%s)=%s\n",qPrint(name),qPrint(result));
4265 return removeRedundantWhiteSpace(result);
4266}
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 6206 of file util.cpp.

6207{
6208 assert(!f.is_open());
6209 bool fileOpened=FALSE;
6210 bool writeToStdout=outFile=="-";
6211 if (writeToStdout) // write to stdout
6212 {
6213 f.basic_ios<char>::rdbuf(std::cout.rdbuf());
6214 fileOpened = true;
6215 }
6216 else // write to file
6217 {
6218 FileInfo fi(outFile.str());
6219 if (fi.exists()) // create a backup
6220 {
6221 Dir dir;
6222 FileInfo backup(fi.filePath()+".bak");
6223 if (backup.exists()) // remove existing backup
6224 dir.remove(backup.filePath());
6225 dir.rename(fi.filePath(),fi.filePath()+".bak");
6226 }
6227 f = Portable::openOutputStream(outFile);
6228 fileOpened = f.is_open();
6229 }
6230 return fileOpened;
6231}
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 5321 of file util.cpp.

5322{
5323 std::lock_guard lock(g_docCacheMutex);
5324 auto it = g_docCache.find(doc.str());
5325 if (it != g_docCache.end())
5326 {
5327 //printf("Cache: [%s]->[%s]\n",qPrint(doc),qPrint(it->second));
5328 return it->second;
5329 }
5330 auto parser { createDocParser() };
5331 auto ast { validatingParseTitle(*parser.get(),fileName,lineNr,doc) };
5332 auto astImpl = dynamic_cast<const DocNodeAST*>(ast.get());
5333 QCString result;
5334 if (astImpl)
5335 {
5336 TextStream t;
5337 OutputCodeList codeList;
5338 codeList.add<HtmlCodeGenerator>(&t);
5339 HtmlDocVisitor visitor(t,codeList,scope,fileName);
5340 std::visit(visitor,astImpl->root);
5341 result = t.str();
5342 }
5343 else // fallback, should not happen
5344 {
5345 result = filterTitle(doc);
5346 }
5347 //printf("Conversion: [%s]->[%s]\n",qPrint(doc),qPrint(result));
5348 g_docCache.insert(std::make_pair(doc.str(),result));
5349 return result;
5350}
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:229
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:5319
QCString filterTitle(const QCString &title)
Definition util.cpp:5526
static std::mutex g_docCacheMutex
Definition util.cpp:5318

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

5267{
5268 if (doc.isEmpty()) return "";
5269 //printf("parseCommentAsText(%s)\n",qPrint(doc));
5270 TextStream t;
5271 auto parser { createDocParser() };
5272 auto ast { validatingParseDoc(*parser.get(),
5273 fileName,
5274 lineNr,
5275 scope,
5276 md,
5277 doc,
5278 DocOptions()
5279 .setAutolinkSupport(false))
5280 };
5281 auto astImpl = dynamic_cast<const DocNodeAST*>(ast.get());
5282 if (astImpl)
5283 {
5284 TextDocVisitor visitor(t);
5285 std::visit(visitor,astImpl->root);
5286 }
5288 int i=0;
5289 int charCnt=0;
5290 int l=static_cast<int>(result.length());
5291 while ((i=nextUTF8CharPosition(result,l,i))<l)
5292 {
5293 charCnt++;
5294 if (charCnt>=80) break;
5295 }
5296 if (charCnt>=80) // try to truncate the string
5297 {
5298 while ((i=nextUTF8CharPosition(result,l,i))<l && charCnt<100)
5299 {
5300 charCnt++;
5301 if (result.at(i)==',' ||
5302 result.at(i)=='.' ||
5303 result.at(i)=='!' ||
5304 result.at(i)=='?' ||
5305 result.at(i)=='}') // good for UTF-16 characters and } otherwise also a good point to stop the string
5306 {
5307 i++; // we want to be "behind" last inspected character
5308 break;
5309 }
5310 }
5311 }
5312 if ( i < l) result=result.left(i)+"...";
5313 return result.data();
5314}
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:5221

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

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

◆ patternMatch()

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

Definition at line 5600 of file util.cpp.

5601{
5602 std::string elem;
5603 auto getter = [](std::string s) -> QCString { return s; };
5604 return genericPatternMatch(fi,patList,elem,getter);
5605}

References genericPatternMatch().

Referenced by checkAndOpenFile(), and readDir().

◆ processMarkup()

QCString processMarkup ( const QCString & s)

◆ projectLogoFile()

QCString projectLogoFile ( )

Definition at line 3067 of file util.cpp.

3068{
3069 QCString projectLogo = Config_getString(PROJECT_LOGO);
3070 if (!projectLogo.isEmpty())
3071 {
3072 // check for optional width= and height= specifier
3073 int wi = projectLogo.find(" width=");
3074 if (wi!=-1) // and strip them
3075 {
3076 projectLogo = projectLogo.left(wi);
3077 }
3078 int hi = projectLogo.find(" height=");
3079 if (hi!=-1)
3080 {
3081 projectLogo = projectLogo.left(hi);
3082 }
3083 }
3084 //printf("projectlogo='%s'\n",qPrint(projectLogo));
3085 return projectLogo;
3086}

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

Referenced by copyLogo(), and substituteKeywords().

◆ protectionLevelVisible()

bool protectionLevelVisible ( Protection prot)

Definition at line 5849 of file util.cpp.

5850{
5851 bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
5852 bool extractPackage = Config_getBool(EXTRACT_PACKAGE);
5853
5854 return (prot!=Protection::Private && prot!=Protection::Package) ||
5855 (prot==Protection::Private && extractPrivate) ||
5856 (prot==Protection::Package && extractPackage);
5857}

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

5447{
5448 // try to open file
5449 FileInfo fi(fileName.str());
5450 if (!fi.exists()) return FALSE;
5451 QCString filterName = getFileFilter(fileName,isSourceCode);
5452 if (filterName.isEmpty() || !filter)
5453 {
5454 std::ifstream f = Portable::openInputStream(fileName,true);
5455 if (!f.is_open())
5456 {
5457 err("could not open file {}\n",fileName);
5458 return FALSE;
5459 }
5460 // read the file
5461 auto fileSize = fi.size();
5462 contents.resize(fileSize);
5463 f.read(contents.data(),fileSize);
5464 if (f.fail())
5465 {
5466 err("problems while reading file {}\n",fileName);
5467 return FALSE;
5468 }
5469 }
5470 else
5471 {
5472 QCString cmd=filterName+" \""+fileName+"\"";
5473 Debug::print(Debug::ExtCmd,0,"Executing popen(`{}`)\n",cmd);
5474 FILE *f=Portable::popen(cmd,"r");
5475 if (!f)
5476 {
5477 err("could not execute filter {}\n",filterName);
5478 return FALSE;
5479 }
5480 const int bufSize=4096;
5481 char buf[bufSize];
5482 int numRead = 0;
5483 while ((numRead=static_cast<int>(fread(buf,1,bufSize,f)))>0)
5484 {
5485 //printf(">>>>>>>>Reading %d bytes\n",numRead);
5486 contents.append(buf,numRead);
5487 }
5489 Debug::print(Debug::FilterOutput, 0, "Filter output\n");
5490 Debug::print(Debug::FilterOutput,0,"-------------\n{}\n-------------\n",contents);
5491 }
5492
5493 if (contents.size()>=2 &&
5494 static_cast<uint8_t>(contents[0])==0xFF &&
5495 static_cast<uint8_t>(contents[1])==0xFE // Little endian BOM
5496 ) // UCS-2LE encoded file
5497 {
5498 transcodeCharacterBuffer(fileName,contents,"UCS-2LE","UTF-8");
5499 }
5500 else if (contents.size()>=2 &&
5501 static_cast<uint8_t>(contents[0])==0xFE &&
5502 static_cast<uint8_t>(contents[1])==0xFF // big endian BOM
5503 ) // UCS-2BE encoded file
5504 {
5505 transcodeCharacterBuffer(fileName,contents,"UCS-2BE","UTF-8");
5506 }
5507 else if (contents.size()>=3 &&
5508 static_cast<uint8_t>(contents[0])==0xEF &&
5509 static_cast<uint8_t>(contents[1])==0xBB &&
5510 static_cast<uint8_t>(contents[2])==0xBF
5511 ) // UTF-8 encoded file
5512 {
5513 contents.erase(0,3); // remove UTF-8 BOM: no translation needed
5514 }
5515 else // transcode according to the INPUT_ENCODING setting
5516 {
5517 // do character transcoding if needed.
5518 transcodeCharacterBuffer(fileName,contents,getEncoding(fi),"UTF-8");
5519 }
5520
5521 filterCRLF(contents);
5522 return true;
5523}
@ 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:1300
static void transcodeCharacterBuffer(const QCString &fileName, std::string &contents, const QCString &inputEncoding, const QCString &outputEncoding)
Definition util.cpp:5410
QCString getEncoding(const FileInfo &fi)
Definition util.cpp:5607
QCString getFileFilter(const QCString &name, bool isSourceCode)
Definition util.cpp:1367

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

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

◆ recodeString()

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

References FALSE, parent(), and TRUE.

◆ recognizeFixedForm()

bool recognizeFixedForm ( const QCString & contents,
FortranFormat format )

Definition at line 6253 of file util.cpp.

6254{
6255 int column=0;
6256 bool skipLine=FALSE;
6257
6258 if (format == FortranFormat::Fixed) return TRUE;
6259 if (format == FortranFormat::Free) return FALSE;
6260
6261 int tabSize=Config_getInt(TAB_SIZE);
6262 size_t sizCont = contents.length();
6263 for (size_t i=0;i<sizCont;i++)
6264 {
6265 column++;
6266
6267 switch(contents.at(i))
6268 {
6269 case '\n':
6270 column=0;
6271 skipLine=FALSE;
6272 break;
6273 case '\t':
6274 column += tabSize-1;
6275 break;
6276 case ' ':
6277 break;
6278 case '\000':
6279 return FALSE;
6280 case '#':
6281 skipLine=TRUE;
6282 break;
6283 case 'C':
6284 case 'c':
6285 if (column==1)
6286 {
6287 return !keyWordsFortranC(contents.data()+i);
6288 }
6289 // fallthrough
6290 case '*':
6291 if (column==1) return TRUE;
6292 if (skipLine) break;
6293 return FALSE;
6294 case '!':
6295 if (column!=6) skipLine=TRUE;
6296 break;
6297 default:
6298 if (skipLine) break;
6299 if (column>=7) return TRUE;
6300 return FALSE;
6301 }
6302 }
6303 return FALSE;
6304}
static bool keyWordsFortranC(const char *contents)
Definition util.cpp:6233

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

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

◆ relativePathToRoot()

QCString relativePathToRoot ( const QCString & name)

Definition at line 3500 of file util.cpp.

3501{
3502 QCString result;
3503 if (Config_getBool(CREATE_SUBDIRS))
3504 {
3505 if (name.isEmpty())
3506 {
3507 return REL_PATH_TO_ROOT;
3508 }
3509 else
3510 {
3511 int i = name.findRev('/');
3512 if (i!=-1)
3513 {
3514 result=REL_PATH_TO_ROOT;
3515 }
3516 }
3517 }
3518 return result;
3519}
#define REL_PATH_TO_ROOT
Definition util.cpp:96

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

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

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

6497{
6498 std::string out;
6499 out.reserve(s.length());
6500 const char *p=s.data();
6501 if (p)
6502 {
6503 char c = 0;
6504 while ((c=*p++))
6505 {
6506 if (c=='\n')
6507 {
6508 const char *e = p;
6509 while (*e==' ' || *e=='\t') e++;
6510 if (*e=='\n')
6511 {
6512 p=e;
6513 }
6514 else out+=c;
6515 }
6516 else
6517 {
6518 out+=c;
6519 }
6520 }
6521 }
6522 //printf("removeEmptyLines(%s)=%s\n",qPrint(s),qPrint(out));
6523 return out;
6524}

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

Referenced by substituteHtmlKeywords(), and substituteLatexKeywords().

◆ removeLongPathMarker()

QCString removeLongPathMarker ( QCString path)

Definition at line 296 of file util.cpp.

297{
298#if defined(_WIN32)
299 if (path.startsWith("//?/")) // strip leading "\\?\" part from path
300 {
301 path=path.mid(4);
302 }
303#endif
304 return path;
305}

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

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

◆ removeRedundantWhiteSpace()

QCString removeRedundantWhiteSpace ( const QCString & s)

Definition at line 576 of file util.cpp.

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

References Config_getBool, constScope, QCString::data(), g_charAroundSpace, QCString::isEmpty(), isId(), QCString::length(), operatorScope, qisspace(), THREAD_LOCAL, virtualScope, and volatileScope.

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

◆ replaceAnonymousScopes()

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

Definition at line 227 of file util.cpp.

228{
229 if (s.isEmpty()) return s;
230 static const reg::Ex marker(R"(@\d+)");
231 std::string result = reg::replace(s.str(),marker,
232 !replacement.isEmpty() ? replacement.data() : "__anonymous__");
233 //printf("replaceAnonymousScopes('%s')='%s'\n",qPrint(s),qPrint(result));
234 return result;
235}
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:770

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

5719{
5720 if (str.isEmpty()) return QCString();
5721 std::string result;
5722 std::string s=str.str();
5723 static const reg::Ex re(R"(##[0-9A-Fa-f][0-9A-Fa-f])");
5724 reg::Iterator it(s,re);
5726 int hue = Config_getInt(HTML_COLORSTYLE_HUE);
5727 int sat = Config_getInt(HTML_COLORSTYLE_SAT);
5728 int gamma = Config_getInt(HTML_COLORSTYLE_GAMMA);
5729 size_t sl=s.length();
5730 size_t p=0;
5731 for (; it!=end ; ++it)
5732 {
5733 const auto &match = *it;
5734 size_t i = match.position();
5735 size_t l = match.length();
5736 if (i>p) result+=s.substr(p,i-p);
5737 std::string lumStr = match.str().substr(2);
5738#define HEXTONUM(x) (((x)>='0' && (x)<='9') ? ((x)-'0') : \
5739 ((x)>='a' && (x)<='f') ? ((x)-'a'+10) : \
5740 ((x)>='A' && (x)<='F') ? ((x)-'A'+10) : 0)
5741
5742 double r = 0,g = 0,b = 0;
5743 int level = HEXTONUM(lumStr[0])*16+HEXTONUM(lumStr[1]);
5744 ColoredImage::hsl2rgb(hue/360.0,sat/255.0,
5745 pow(level/255.0,gamma/100.0),&r,&g,&b);
5746 int red = static_cast<int>(r*255.0);
5747 int green = static_cast<int>(g*255.0);
5748 int blue = static_cast<int>(b*255.0);
5749 char colStr[8];
5750 colStr[0]='#';
5751 colStr[1]=hex[red>>4];
5752 colStr[2]=hex[red&0xf];
5753 colStr[3]=hex[green>>4];
5754 colStr[4]=hex[green&0xf];
5755 colStr[5]=hex[blue>>4];
5756 colStr[6]=hex[blue&0xf];
5757 colStr[7]=0;
5758 //printf("replacing %s->%s (level=%d)\n",qPrint(lumStr),colStr,level);
5759 result+=colStr;
5760 p=i+l;
5761 }
5762 if (p<sl) result+=s.substr(p);
5763 return result;
5764}
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 2653 of file util.cpp.

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

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

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

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

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

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

880{
881 size_t sl=scope.length();
882 size_t nl=name.length();
883 return (name==scope || // equal
884 (scope.right(nl)==name && // substring
885 sl>1+nl && scope.at(sl-nl-1)==':' && scope.at(sl-nl-2)==':' // scope
886 )
887 );
888}

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

6320{
6321 if (s.isEmpty()) return s;
6322
6323 // helper to find the end of a block
6324 auto skipBlock = [&markerInfo](const char *p,const SelectionBlock &blk)
6325 {
6326 char c = 0;
6327 while ((c=*p))
6328 {
6329 if (c==markerInfo.markerChar && qstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // end marker
6330 {
6331 size_t len = markerInfo.endLen;
6332 bool negate = *(p+markerInfo.endLen)=='!';
6333 if (negate) len++;
6334 size_t blkNameLen = qstrlen(blk.name);
6335 if (qstrncmp(p+len,blk.name,blkNameLen)==0 && // matching marker name
6336 qstrncmp(p+len+blkNameLen,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6337 {
6338 //printf("Found end marker %s enabled=%d negate=%d\n",blk.name,blk.enabled,negate);
6339 return p+len+blkNameLen+markerInfo.closeLen;
6340 }
6341 else // not the right marker id
6342 {
6343 p++;
6344 }
6345 }
6346 else // not and end marker
6347 {
6348 p++;
6349 }
6350 }
6351 return p;
6352 };
6353
6354 QCString result;
6355 result.reserve(s.length());
6356 const char *p = s.data();
6357 char c = 0;
6358 while ((c=*p))
6359 {
6360 if (c==markerInfo.markerChar) // potential start of marker
6361 {
6362 if (qstrncmp(p,markerInfo.beginStr,markerInfo.beginLen)==0) // start of begin marker
6363 {
6364 bool found = false;
6365 size_t len = markerInfo.beginLen;
6366 bool negate = *(p+len)=='!';
6367 if (negate) len++;
6368 for (const auto &blk : blockList)
6369 {
6370 size_t blkNameLen = qstrlen(blk.name);
6371 if (qstrncmp(p+len,blk.name,blkNameLen)==0 && // matching marker name
6372 qstrncmp(p+len+blkNameLen,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6373 {
6374 bool blockEnabled = blk.enabled!=negate;
6375 //printf("Found start marker %s enabled=%d negate=%d\n",blk.name,blk.enabled,negate);
6376 p+=len+blkNameLen+markerInfo.closeLen;
6377 if (!blockEnabled) // skip until the end of the block
6378 {
6379 //printf("skipping block\n");
6380 p=skipBlock(p,blk);
6381 }
6382 found=true;
6383 break;
6384 }
6385 }
6386 if (!found) // unknown marker id
6387 {
6388 result+=c;
6389 p++;
6390 }
6391 }
6392 else if (qstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // start of end marker
6393 {
6394 bool found = false;
6395 size_t len = markerInfo.endLen;
6396 bool negate = *(p+len)=='!';
6397 if (negate) len++;
6398 for (const auto &blk : blockList)
6399 {
6400 size_t blkNameLen = qstrlen(blk.name);
6401 if (qstrncmp(p+len,blk.name,blkNameLen)==0 && // matching marker name
6402 qstrncmp(p+len+blkNameLen,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6403 {
6404 //printf("Found end marker %s enabled=%d negate=%d\n",blk.name,blk.enabled,negate);
6405 p+=len+blkNameLen+markerInfo.closeLen;
6406 found=true;
6407 break;
6408 }
6409 }
6410 if (!found) // unknown marker id
6411 {
6412 result+=c;
6413 p++;
6414 }
6415 }
6416 else // not a start or end marker
6417 {
6418 result+=c;
6419 p++;
6420 }
6421 }
6422 else // not a marker character
6423 {
6424 result+=c;
6425 p++;
6426 }
6427 }
6428 //printf("====\n%s\n-----\n%s\n~~~~\n",qPrint(s),qPrint(result));
6429 return result;
6430}
void reserve(size_t size)
Reserve space for size bytes without changing the string contents.
Definition qcstring.h:185
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 2951 of file util.cpp.

2952{
2953 QCString result;
2954 QCString name=n;
2955 QCString path;
2956 int slashPos=std::max(name.findRev('/'),name.findRev('\\'));
2957 if (slashPos!=-1)
2958 {
2959 path=name.left(slashPos+1);
2960 name=name.right(name.length()-slashPos-1);
2961 }
2962 const FileName *fn=fnMap->find(name);
2963 if (fn)
2964 {
2965 bool first = true;
2966 for (const auto &fd : *fn)
2967 {
2968 if (path.isEmpty() || fd->getPath().right(path.length())==path)
2969 {
2970 if (!first) result += "\n";
2971 else first = false;
2972 result+=" "+fd->absFilePath();
2973 }
2974 }
2975 }
2976 return result;
2977}

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

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

◆ split() [1/2]

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

split input string s by regular expression delimiter delimiter.

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

Definition at line 6545 of file util.cpp.

6546{
6547 StringVector result;
6548 reg::Iterator iter(s, delimiter);
6550 size_t p=0;
6551 for ( ; iter != end; ++iter)
6552 {
6553 const auto &match = *iter;
6554 size_t i=match.position();
6555 size_t l=match.length();
6556 if (i>p) result.push_back(s.substr(p,i-p));
6557 p=i+l;
6558 }
6559 if (p<s.length()) result.push_back(s.substr(p));
6560 return result;
6561}

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

6529{
6530 StringVector result;
6531 size_t prev = 0, pos = 0, len = s.length();
6532 do
6533 {
6534 pos = s.find(delimiter, prev);
6535 if (pos == std::string::npos) pos = len;
6536 if (pos>prev) result.push_back(s.substr(prev,pos-prev));
6537 prev = pos + delimiter.length();
6538 }
6539 while (pos<len && prev<len);
6540 return result;
6541}

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

◆ stackTrace()

void stackTrace ( )

Definition at line 5382 of file util.cpp.

5383{
5384#ifdef TRACINGSUPPORT
5385 void *backtraceFrames[128];
5386 int frameCount = backtrace(backtraceFrames, 128);
5387 const size_t cmdLen = 40960;
5388 static char cmd[cmdLen];
5389 char *p = cmd;
5390 p += qsnprintf(p,cmdLen,"/usr/bin/atos -p %d ", (int)getpid());
5391 for (int x = 0; x < frameCount; x++)
5392 {
5393 p += qsnprintf(p,cmdLen,"%p ", backtraceFrames[x]);
5394 }
5395 fprintf(stderr,"========== STACKTRACE START ==============\n");
5396 if (FILE *fp = Portable::popen(cmd, "r"))
5397 {
5398 char resBuf[512];
5399 while (size_t len = fread(resBuf, 1, sizeof(resBuf), fp))
5400 {
5401 fwrite(resBuf, 1, len, stderr);
5402 }
5403 Portable::pclose(fp);
5404 }
5405 fprintf(stderr,"============ STACKTRACE END ==============\n");
5406 //fprintf(stderr,"%s\n", frameStrings[x]);
5407#endif
5408}

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

◆ stripAnonymousNamespaceScope()

QCString stripAnonymousNamespaceScope ( const QCString & s)

Definition at line 239 of file util.cpp.

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

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

4846{
4848}
QCString stripExtensionGeneral(const QCString &fName, const QCString &ext)
Definition util.cpp:4835

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

339{
340 return stripFromPath(path,Config_getList(STRIP_FROM_INC_PATH));
341}

References Config_getList, and stripFromPath().

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

◆ stripFromPath()

QCString stripFromPath ( const QCString & path)

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

Definition at line 330 of file util.cpp.

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

References Config_getList, and stripFromPath().

◆ stripIndentation()

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

Definition at line 5861 of file util.cpp.

5862{
5863 if (s.isEmpty()) return s; // empty string -> we're done
5864
5865 //printf("stripIndentation:\n%s\n------\n",qPrint(s));
5866 // compute minimum indentation over all lines
5867 const char *p=s.data();
5868 char c=0;
5869 int indent=0;
5870 int minIndent=1000000; // "infinite"
5871 bool searchIndent=true;
5872 int tabSize=Config_getInt(TAB_SIZE);
5873 bool skipFirst = skipFirstLine;
5874 while ((c=*p++))
5875 {
5876 if (c=='\t') indent+=tabSize - (indent%tabSize);
5877 else if (c=='\n') indent=0,searchIndent=true,skipFirst=false;
5878 else if (c==' ') indent++;
5879 else if (searchIndent && !skipFirst)
5880 {
5881 searchIndent=false;
5882 if (indent<minIndent) minIndent=indent;
5883 }
5884 }
5885
5886 // no indent to remove -> we're done
5887 if (minIndent==0) return substitute(s,"@ilinebr","\\ilinebr");
5888
5889 // remove minimum indentation for each line
5890 TextStream result;
5891 p=s.data();
5892 indent=0;
5893 skipFirst=skipFirstLine;
5894 while ((c=*p++))
5895 {
5896 if (c=='\n') // start of new line
5897 {
5898 indent=0;
5899 result << c;
5900 skipFirst=false;
5901 }
5902 else if (indent<minIndent && !skipFirst) // skip until we reach minIndent
5903 {
5904 if (c=='\t')
5905 {
5906 int newIndent = indent+tabSize-(indent%tabSize);
5907 int i=newIndent;
5908 while (i>minIndent) // if a tab crosses the minIndent boundary fill the rest with spaces
5909 {
5910 result << ' ';
5911 i--;
5912 }
5913 indent=newIndent;
5914 }
5915 else // space
5916 {
5917 indent++;
5918 }
5919 }
5920 else if (c=='\\' && literal_at(p,"ilinebr "))
5921 // we also need to remove the indentation after a \ilinebr command at the end of a line
5922 {
5923 result << "\\ilinebr ";
5924 p+=8;
5925 int skipAmount=0;
5926 for (int j=0;j<minIndent;j++) if (*(p+j)==' ') skipAmount++; // test to see if we have the indent
5927 if (skipAmount==minIndent)
5928 {
5929 p+=skipAmount; // remove the indent
5930 }
5931 }
5932 else if (c=='@' && literal_at(p,"ilinebr"))
5933 {
5934 result << "\\ilinebr";
5935 p+=7;
5936 }
5937 else // copy anything until the end of the line
5938 {
5939 result << c;
5940 }
5941 }
5942
5943 //printf("stripIndentation: result=\n%s\n------\n",qPrint(result.str()));
5944
5945 return result.str();
5946}

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

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

◆ stripIndentationVerbatim()

void stripIndentationVerbatim ( QCString & doc,
const int indentationLevel )

Definition at line 5949 of file util.cpp.

5950{
5951 //printf("stripIndentationVerbatim(level=%d):\n%s\n------\n",indentationLevel,qPrint(doc));
5952 if (indentationLevel <= 0 || doc.isEmpty()) return; // nothing to strip
5953
5954 // by stripping content the string will only become shorter so we write the results
5955 // back into the input string and then resize it at the end.
5956 char c = 0;
5957 const char *src = doc.data();
5958 char *dst = doc.rawData();
5959 bool insideIndent = false; // skip the initial line from stripping
5960 int cnt = 0;
5961 while ((c=*src++))
5962 {
5963 // invariant: dst<=src
5964 switch(c)
5965 {
5966 case '\n':
5967 *dst++ = c;
5968 insideIndent = true;
5969 cnt = indentationLevel;
5970 break;
5971 case ' ':
5972 if (insideIndent)
5973 {
5974 if (cnt>0) // count down the spacing until the end of the indent
5975 {
5976 cnt--;
5977 }
5978 else // reached the end of the indent, start of the part of the line to keep
5979 {
5980 insideIndent = false;
5981 *dst++ = c;
5982 }
5983 }
5984 else // part after indent, copy to the output
5985 {
5986 *dst++ = c;
5987 }
5988 break;
5989 default:
5990 insideIndent = false;
5991 *dst++ = c;
5992 break;
5993 }
5994 }
5995 doc.resize(static_cast<uint32_t>(dst-doc.data()));
5996 //printf("stripIndentationVerbatim: result=\n%s\n------\n",qPrint(doc));
5997}
char * rawData()
Returns a writable pointer to the data.
Definition qcstring.h:178
void resize(size_t newlen)
Definition qcstring.h:180

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

◆ stripLeadingAndTrailingEmptyLines()

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

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

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

Definition at line 4926 of file util.cpp.

4927{
4928 if (s.isEmpty()) return QCString();
4929 const char *p = s.data();
4930
4931 // search for leading empty lines
4932 int i=0,li=-1,l=static_cast<int>(s.length());
4933 char c = 0;
4934 while ((c=*p))
4935 {
4936 if (c==' ' || c=='\t' || c=='\r') i++,p++;
4937 else if (c=='\\' && literal_at(p,"\\ilinebr")) i+=8,li=i,p+=8;
4938 else if (c=='\n') i++,li=i,docLine++,p++;
4939 else break;
4940 }
4941
4942 // search for trailing empty lines
4943 int b=l-1,bi=-1;
4944 p=s.data()+b;
4945 while (b>=0)
4946 {
4947 c=*p;
4948 if (c==' ' || c=='\t' || c=='\r') b--,p--;
4949 else if (c=='r' && b>=7 && literal_at(p-7,"\\ilinebr")) bi=b-7,b-=8,p-=8;
4950 else if (c=='>' && b>=11 && literal_at(p-11,"\\ilinebr<br>")) bi=b-11,b-=12,p-=12;
4951 else if (c=='\n') bi=b,b--,p--;
4952 else break;
4953 }
4954
4955 // return whole string if no leading or trailing lines where found
4956 if (li==-1 && bi==-1) return s;
4957
4958 // return substring
4959 if (bi==-1) bi=l;
4960 if (li==-1) li=0;
4961 if (bi<=li) return QCString(); // only empty lines
4962 //printf("docLine='%s' len=%d li=%d bi=%d\n",qPrint(s),s.length(),li,bi);
4963 return s.mid(li,bi-li);
4964}

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

4851{
4852 QCString result=s;
4853 int i=result.findRev('/');
4854 if (i!=-1)
4855 {
4856 result=result.mid(i+1);
4857 }
4858 i=result.findRev('\\');
4859 if (i!=-1)
4860 {
4861 result=result.mid(i+1);
4862 }
4863 return result;
4864}

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

3701{
3702 QCString result = name;
3703 int l = static_cast<int>(result.length());
3704 int p = 0;
3705 bool done = FALSE;
3706 bool skipBracket=FALSE; // if brackets do not match properly, ignore them altogether
3707 int count=0;
3708 int round=0;
3709
3710 do
3711 {
3712 p=l-1; // start at the end of the string
3713 while (p>=0 && count>=0)
3714 {
3715 char c=result.at(p);
3716 switch (c)
3717 {
3718 case ':':
3719 // only exit in the case of ::
3720 //printf("stripScope(%s)=%s\n",name,qPrint(result.right(l-p-1)));
3721 if (p>0 && result.at(p-1)==':' && (count==0 || skipBracket))
3722 {
3723 return result.right(l-p-1);
3724 }
3725 p--;
3726 break;
3727 case '>':
3728 if (skipBracket) // we don't care about brackets
3729 {
3730 p--;
3731 }
3732 else // count open/close brackets
3733 {
3734 if (p>0 && result.at(p-1)=='>') // skip >> operator
3735 {
3736 p-=2;
3737 break;
3738 }
3739 count=1;
3740 //printf("pos < = %d\n",p);
3741 p--;
3742 bool foundMatch=false;
3743 while (p>=0 && !foundMatch)
3744 {
3745 c=result.at(p--);
3746 switch (c)
3747 {
3748 case ')':
3749 round++;
3750 break;
3751 case '(':
3752 round--;
3753 break;
3754 case '>': // ignore > inside (...) to support e.g. (sizeof(T)>0) inside template parameters
3755 if (round==0) count++;
3756 break;
3757 case '<':
3758 if (round==0)
3759 {
3760 if (p>0)
3761 {
3762 if (result.at(p-1) == '<') // skip << operator
3763 {
3764 p--;
3765 break;
3766 }
3767 }
3768 count--;
3769 foundMatch = count==0;
3770 }
3771 break;
3772 default:
3773 //printf("c=%c count=%d\n",c,count);
3774 break;
3775 }
3776 }
3777 }
3778 //printf("pos > = %d\n",p+1);
3779 break;
3780 default:
3781 p--;
3782 }
3783 }
3784 done = count==0 || skipBracket; // reparse if brackets do not match
3785 skipBracket=TRUE;
3786 }
3787 while (!done); // if < > unbalanced repeat ignoring them
3788 //printf("stripScope(%s)=%s\n",name,name);
3789 return name;
3790}

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

4442{
4443 //printf("stripTemplateSpecifiersFromScope(name=%s,scopeName=%s)\n",qPrint(fullName),qPrint(scopeName));
4444 int i=fullName.find('<');
4445 if (i==-1) return fullName;
4446 QCString result;
4447 int p=0;
4448 int l=static_cast<int>(fullName.length());
4449 while (i!=-1)
4450 {
4451 //printf("1:result+=%s\n",qPrint(fullName.mid(p,i-p)));
4452 int e=i+1;
4453 int count=1;
4454 int round=0;
4455 while (e<l && count>0)
4456 {
4457 char c=fullName.at(e++);
4458 switch (c)
4459 {
4460 case '(': round++; break;
4461 case ')': if (round>0) round--; break;
4462 case '<': if (round==0) count++; break;
4463 case '>': if (round==0) count--; break;
4464 default:
4465 break;
4466 }
4467 }
4468 int si= fullName.find("::",e);
4469
4470 if (parentOnly && si==-1) break;
4471 // we only do the parent scope, so we stop here if needed
4472
4473 result+=fullName.mid(p,i-p);
4474 //printf(" trying %s\n",qPrint(mergeScopes(scopeName,result+fullName.mid(i,e-i))));
4475 ClassDef *cd = getClass(mergeScopes(scopeName,result+fullName.mid(i,e-i)));
4476 if (cd!=nullptr && (allowArtificial || !cd->isArtificial()))
4477 {
4478 result+=fullName.mid(i,e-i);
4479 //printf(" 2:result+=%s\n",qPrint(fullName.mid(i,e-i-1)));
4480 }
4481 else if (pLastScopeStripped)
4482 {
4483 //printf(" last stripped scope '%s'\n",qPrint(fullName.mid(i,e-i)));
4484 *pLastScopeStripped=fullName.mid(i,e-i);
4485 }
4486 p=e;
4487 i=fullName.find('<',p);
4488 }
4489 result+=fullName.right(l-p);
4490 //printf("3:result+=%s\n",qPrint(fullName.right(l-p)));
4491 //printf("end result=%s\n",qPrint(result));
4492 return result;
4493}
virtual bool isArtificial() const =0
QCString mergeScopes(const QCString &leftScope, const QCString &rightScope)
Definition util.cpp:4504

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

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

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

3135{
3136 return substituteKeywords(file,s,
3137 {
3138 // keyword value getter
3139 { "$title", [&]() { return !title.isEmpty() ? title : projName; } },
3140 { "$doxygenversion", [&]() { return getDoxygenVersion(); } },
3141 { "$projectname", [&]() { return projName; } },
3142 { "$projectnumber", [&]() { return projNum; } },
3143 { "$projectbrief", [&]() { return projBrief; } },
3144 { "$projectlogo", [&]() { return stripPath(projectLogoFile()); } },
3145 { "$logosize", [&]() { return projectLogoSize(); } },
3146 { "$projecticon", [&]() { return stripPath(Config_getString(PROJECT_ICON)); } },
3147 { "$langISO", [&]() { return theTranslator->trISOLang(); } },
3148 { "$showdate", [&](const QCString &fmt) { return showDate(fmt); } }
3149 });
3150}
Definition message.h:144
QCString stripPath(const QCString &s)
Definition util.cpp:4850
QCString substituteKeywords(const QCString &file, const QCString &s, const KeywordSubstitutionList &keywords)
Definition util.cpp:2981
QCString projectLogoFile()
Definition util.cpp:3067
static QCString projectLogoSize()
Definition util.cpp:3088
static QCString showDate(const QCString &fmt)
Definition util.cpp:3054

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

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

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

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

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

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

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

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

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

◆ updateColumnCount()

size_t updateColumnCount ( const char * s,
size_t col )

Definition at line 6790 of file util.cpp.

6791{
6792 if (s)
6793 {
6794 const int tabSize = Config_getInt(TAB_SIZE);
6795 char c;
6796 while ((c=*s++))
6797 {
6798 switch(c)
6799 {
6800 case '\t': col+=tabSize - (col%tabSize);
6801 break;
6802 case '\n': col=0;
6803 break;
6804 default:
6805 col++;
6806 if (c<0) // multi-byte character
6807 {
6808 int numBytes = getUTF8CharNumBytes(c);
6809 for (int i=0;i<numBytes-1 && (c=*s++);i++) {} // skip over extra chars
6810 if (c==0) return col; // end of string half way a multibyte char
6811 }
6812 break;
6813 }
6814 }
6815 }
6816 return col;
6817}

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

5003{
5004 QCString langName = language.lower();
5005 auto it1 = std::find_if(g_lang2extMap.begin(),g_lang2extMap.end(),
5006 [&langName](const auto &info) { return info.langName==langName; });
5007 if (it1 == g_lang2extMap.end()) return false;
5008
5009 // found the language
5010 SrcLangExt parserId = it1->parserId;
5011 QCString extName = extension.lower();
5012 if (extName.isEmpty()) return FALSE;
5013 if (extName.at(0)!='.') extName.prepend(".");
5014 auto it2 = g_extLookup.find(extName.str());
5015 if (it2!=g_extLookup.end())
5016 {
5017 g_extLookup.erase(it2); // language was already register for this ext
5018 }
5019 //printf("registering extension %s\n",qPrint(extName));
5020 g_extLookup.emplace(extName.str(),parserId);
5021 if (!Doxygen::parserManager->registerExtension(extName,it1->parserName))
5022 {
5023 err("Failed to assign extension {} to parser {} for language {}\n",
5024 extName.data(),it1->parserName,language);
5025 }
5026 else
5027 {
5028 //msg("Registered extension {} to language parser {}...\n",
5029 // extName,language);
5030 }
5031 return TRUE;
5032}
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 5694 of file util.cpp.

5695{
5696 int hue = Config_getInt(HTML_COLORSTYLE_HUE);
5697 int sat = Config_getInt(HTML_COLORSTYLE_SAT);
5698 int gamma = Config_getInt(HTML_COLORSTYLE_GAMMA);
5699 while (data->name)
5700 {
5701 QCString fileName = dir+"/"+data->name;
5702 ColoredImage img(data->width,data->height,data->content,data->alpha,
5703 sat,hue,gamma);
5704 if (!img.save(fileName))
5705 {
5706 fprintf(stderr,"Warning: Cannot open file %s for writing\n",data->name);
5707 }
5708 Doxygen::indexList->addImageFile(data->name);
5709 data++;
5710 }
5711}
Class representing a bitmap image colored based on hue/sat/gamma settings.
Definition image.h:56
static IndexList * indexList
Definition doxygen.h:134
const unsigned char * content
Definition util.h:418
unsigned short height
Definition util.h:417
const unsigned char * alpha
Definition util.h:419
unsigned short width
Definition util.h:416
const char * name
Definition util.h:415

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

1126{
1127 auto replaceFunc = [&list,&ol](size_t entryIndex)
1128 {
1129 const auto &e = list[entryIndex];
1130 ol.pushGeneratorState();
1134 // link for Html / man
1135 //printf("writeObjectLink(file=%s)\n",qPrint(e->file));
1136 ol.writeObjectLink(QCString(),e.file,e.anchor,e.name);
1137 ol.popGeneratorState();
1138
1139 ol.pushGeneratorState();
1142 // link for Latex / pdf with anchor because the sources
1143 // are not hyperlinked (not possible with a verbatim environment).
1144 ol.writeObjectLink(QCString(),e.file,QCString(),e.name);
1145 ol.popGeneratorState();
1146 };
1147
1148 writeMarkerList(ol, theTranslator->trWriteList(static_cast<int>(list.size())).str(), list.size(), replaceFunc);
1149
1150 ol.writeString(".");
1151}
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:1101

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

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

5356{
5357 if (al.empty()) return;
5358 ol.startConstraintList(theTranslator->trTypeConstraints());
5359 for (const Argument &a : al)
5360 {
5362 ol.parseText(a.name);
5363 ol.endConstraintParam();
5365 linkifyText(TextGeneratorOLImpl(ol),d,nullptr,nullptr,a.type);
5366 ol.endConstraintType();
5368 ol.generateDoc(d->docFile(),
5369 d->docLine(),
5370 d,
5371 nullptr,
5372 a.docs,
5373 DocOptions()
5374 .setIndexWords(true));
5375 ol.endConstraintDocs();
5376 }
5377 ol.endConstraintList();
5378}
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:77
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:902

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().