Doxygen
Loading...
Searching...
No Matches
util.cpp File Reference
#include <stdlib.h>
#include <errno.h>
#include <math.h>
#include <limits.h>
#include <string.h>
#include <assert.h>
#include <mutex>
#include <unordered_set>
#include <codecvt>
#include <algorithm>
#include <ctime>
#include <cctype>
#include <cinttypes>
#include <sstream>
#include "md5.h"
#include "regex.h"
#include "util.h"
#include "message.h"
#include "classdef.h"
#include "filedef.h"
#include "doxygen.h"
#include "outputlist.h"
#include "defargs.h"
#include "language.h"
#include "config.h"
#include "htmlhelp.h"
#include "example.h"
#include "version.h"
#include "groupdef.h"
#include "reflist.h"
#include "pagedef.h"
#include "debug.h"
#include "searchindex.h"
#include "textdocvisitor.h"
#include "latexdocvisitor.h"
#include "htmldocvisitor.h"
#include "portable.h"
#include "parserintf.h"
#include "image.h"
#include "entry.h"
#include "arguments.h"
#include "memberlist.h"
#include "classlist.h"
#include "namespacedef.h"
#include "membername.h"
#include "filename.h"
#include "membergroup.h"
#include "dirdef.h"
#include "htmlentity.h"
#include "symbolresolver.h"
#include "fileinfo.h"
#include "dir.h"
#include "utf8.h"
#include "textstream.h"
#include "indexlist.h"
#include "datetime.h"
#include "moduledef.h"
#include "trace.h"
#include "stringutil.h"
Include dependency graph for util.cpp:

Go to the source code of this file.

Classes

struct  CharAroundSpace
struct  CharAroundSpace::CharElem
struct  FindFileCacheElem
 Cache element for the file name to FileDef mapping cache. More...
struct  Lang2ExtMap

Macros

#define ENABLE_TRACINGSUPPORT   0
#define REL_PATH_TO_ROOT   "../../"
#define MATCH   AUTO_TRACE_EXIT("match at line {}",__LINE__);
#define NOMATCH   AUTO_TRACE_EXIT("no match at line {}",__LINE__);
#define HEXTONUM(x)

Functions

QCString removeAnonymousScopes (const QCString &str)
QCString replaceAnonymousScopes (const QCString &s, const QCString &replacement)
QCString stripAnonymousNamespaceScope (const QCString &s)
void writePageRef (OutputList &ol, const QCString &cn, const QCString &mn)
QCString generateMarker (int id)
QCString removeLongPathMarker (QCString path)
static QCString stripFromPath (const QCString &p, const StringVector &l)
QCString stripFromPath (const QCString &path)
QCString stripFromIncludePath (const QCString &path)
EntryType guessSection (const QCString &name)
QCString resolveTypeDef (const Definition *context, const QCString &qualifiedName, const Definition **typedefContext)
QCString removeRedundantWhiteSpace (const QCString &s)
int findParameterList (const QCString &name)
 Returns the position in the string where a function parameter list begins, or -1 if one is not found.
bool rightScopeMatch (const QCString &scope, const QCString &name)
bool leftScopeMatch (const QCString &scope, const QCString &name)
void linkifyText (const TextGeneratorIntf &out, const QCString &text, const LinkifyTextOptions &options)
void writeMarkerList (OutputList &ol, const std::string &markerText, size_t numMarkers, std::function< void(size_t)> replaceFunc)
QCString writeMarkerList (const std::string &markerText, size_t numMarkers, std::function< QCString(size_t)> replaceFunc)
void writeExamples (OutputList &ol, const ExampleList &list)
QCString inlineArgListToDoc (const ArgumentList &al)
QCString inlineTemplateArgListToDoc (const ArgumentList &al)
QCString argListToString (const ArgumentList &al, bool useCanonicalType, bool showDefVals)
QCString tempArgListToString (const ArgumentList &al, SrcLangExt lang, bool includeDefault)
static void filterCRLF (std::string &contents)
static QCString getFilterFromList (const QCString &name, const StringVector &filterList, bool &found)
QCString getFileFilter (const QCString &name, bool isSourceCode)
bool transcodeCharacterStringToUTF8 (std::string &input, const char *inputEncoding)
QCString fileToString (const QCString &name, bool filter, bool isSourceCode)
void trimBaseClassScope (const BaseClassList &bcl, QCString &s, int level=0)
static void stripIrrelevantString (QCString &target, const QCString &str, bool insideTemplate)
void stripIrrelevantConstVolatile (QCString &s, bool insideTemplate)
static QCString stripDeclKeywords (const QCString &s)
static QCString extractCanonicalType (const Definition *d, const FileDef *fs, QCString type, SrcLangExt lang, bool insideTemplate)
static QCString getCanonicalTemplateSpec (const Definition *d, const FileDef *fs, const QCString &spec, SrcLangExt lang)
static QCString getCanonicalTypeForIdentifier (const Definition *d, const FileDef *fs, const QCString &word, SrcLangExt lang, QCString *tSpec, int count=0)
static QCString extractCanonicalArgType (const Definition *d, const FileDef *fs, const Argument &arg, SrcLangExt lang)
static bool matchCanonicalTypes (const Definition *srcScope, const FileDef *srcFileScope, const QCString &srcType, const Definition *dstScope, const FileDef *dstFileScope, const QCString &dstType, SrcLangExt lang)
static bool matchArgument2 (const Definition *srcScope, const FileDef *srcFileScope, Argument &srcA, const Definition *dstScope, const FileDef *dstFileScope, Argument &dstA, SrcLangExt lang)
bool matchArguments2 (const Definition *srcScope, const FileDef *srcFileScope, const QCString &srcReturnType, const ArgumentList *srcAl, const Definition *dstScope, const FileDef *dstFileScope, const QCString &dstReturnType, const ArgumentList *dstAl, bool checkCV, SrcLangExt lang)
void mergeArguments (ArgumentList &srcAl, ArgumentList &dstAl, bool forceNameOverwrite)
bool matchTemplateArguments (const ArgumentList &srcAl, const ArgumentList &dstAl)
GetDefResult getDefs (const GetDefInput &input)
static bool getScopeDefs (const QCString &docScope, const QCString &scope, ClassDef *&cd, ConceptDef *&cnd, NamespaceDef *&nd, ModuleDef *&modd)
static bool isLowerCase (QCString &s)
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)
QCString linkToText (SrcLangExt lang, const QCString &link, bool isFileName)
bool resolveLink (const QCString &scName, const QCString &lr, bool, const Definition **resContext, QCString &resAnchor, SrcLangExt lang, const QCString &prefix)
void generateFileRef (OutputList &ol, const QCString &name, const QCString &text)
FileDeffindFileDef (const FileNameLinkedMap *fnMap, const QCString &n, bool &ambig)
QCString findFilePath (const QCString &file, bool &ambig)
QCString showFileDefMatches (const FileNameLinkedMap *fnMap, const QCString &n)
QCString substituteKeywords (const QCString &file, const QCString &s, const KeywordSubstitutionList &keywords)
static QCString showDate (const QCString &fmt)
QCString projectLogoFile ()
static QCString projectLogoSize ()
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)
bool getCaseSenseNames ()
QCString escapeCharsInString (const QCString &name, bool allowDots, bool allowUnderscore)
QCString unescapeCharsInString (const QCString &s)
QCString convertNameToFile (const QCString &name, bool allowDots, bool allowUnderscore)
QCString generateAnonymousAnchor (const QCString &fileName, int count)
QCString relativePathToRoot (const QCString &name)
QCString determineAbsoluteIncludeName (const QCString &curFile, const QCString &incFileName)
void createSubDirs (const Dir &d)
void clearSubDirs (const Dir &d)
void extractNamespaceName (const QCString &scopeName, QCString &className, QCString &namespaceName, bool allowEmptyClass)
QCString insertTemplateSpecifierInScope (const QCString &scope, const QCString &templ)
QCString stripScope (const QCString &name)
QCString convertToId (const QCString &s)
QCString correctId (const QCString &s)
QCString convertToXML (const QCString &s, bool keepEntities)
QCString convertToHtml (const QCString &s, bool keepEntities)
QCString convertToJSString (const QCString &s, bool keepEntities, bool singleQuotes)
QCString convertCharEntitiesToUTF8 (const QCString &str)
QCString getOverloadDocs ()
void addMembersToMemberGroup (MemberList *ml, MemberGroupList *pMemberGroups, const Definition *context)
int extractClassNameFromType (const QCString &type, int &pos, QCString &name, QCString &templSpec, SrcLangExt lang)
QCString normalizeNonTemplateArgumentsInString (const QCString &name, const Definition *context, const ArgumentList &formalArgs)
QCString substituteTemplateArgumentsInString (const QCString &nm, const ArgumentList &formalArgs, const ArgumentList *actualArgs)
QCString stripTemplateSpecifiersFromScope (const QCString &fullName, bool parentOnly, QCString *pLastScopeStripped, QCString scopeName, bool allowArtificial)
QCString mergeScopes (const QCString &leftScope, const QCString &rightScope)
int getScopeFragment (const QCString &s, int p, int *l)
PageDefaddRelatedPage (const QCString &name, const QCString &ptitle, const QCString &doc, const QCString &fileName, int docLine, int startLine, const RefItemVector &sli, GroupDef *gd, const TagInfo *tagInfo, bool xref, SrcLangExt lang)
void addRefItem (const RefItemVector &sli, const QCString &key, const QCString &prefix, const QCString &name, const QCString &title, const QCString &args, const Definition *scope)
static ModuleDeffindModuleDef (const Definition *d)
static bool recursivelyAddGroupListToTitle (OutputList &ol, const Definition *d, bool root)
void addGroupListToTitle (OutputList &ol, const Definition *d)
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)
QCString stripPath (const QCString &s)
QCString makeBaseName (const QCString &name, const QCString &ext)
bool containsWord (const QCString &str, const char *word)
 returns TRUE iff string s contains word w
bool findAndRemoveWord (QCString &sentence, 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 &language)
void initDefaultExtensionMapping ()
void addCodeOnlyMappings ()
SrcLangExt getLanguageFromFileName (const QCString &fileName, SrcLangExt defLang)
SrcLangExt getLanguageFromCodeLang (QCString &fileName)
 Routine to handle the language attribute of the \code command.
QCString getFileNameExtension (const QCString &fn)
static MemberDefgetMemberFromSymbol (const Definition *scope, const FileDef *fileScope, const QCString &n)
bool checkIfTypedef (const Definition *scope, const FileDef *fileScope, const QCString &n)
static int nextUTF8CharPosition (const QCString &utf8Str, uint32_t len, uint32_t startPos)
QCString parseCommentAsText (const Definition *scope, const MemberDef *md, const QCString &doc, const QCString &fileName, int lineNr)
QCString parseCommentAsHtml (const Definition *scope, const MemberDef *member, const QCString &doc, const QCString &fileName, int lineNr)
void writeTypeConstraints (OutputList &ol, const Definition *d, const ArgumentList &al)
void stackTrace ()
static void transcodeCharacterBuffer (const QCString &fileName, std::string &contents, const QCString &inputEncoding, const QCString &outputEncoding)
bool readInputFile (const QCString &fileName, std::string &contents, bool filter, bool isSourceCode)
 read a file name fileName and optionally filter and transcode it
QCString filterTitle (const QCString &title)
template<class PatternList, class PatternElem, typename PatternGet = QCString(*)(const PatternElem &)>
bool genericPatternMatch (const FileInfo &fi, const PatternList &patList, PatternElem &elem, PatternGet getter)
bool patternMatch (const FileInfo &fi, const StringVector &patList)
QCString getEncoding (const FileInfo &fi)
QCString externalLinkTarget (const bool parent)
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)
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.
QCString langToString (SrcLangExt lang)
 Returns a string representation of lang.
QCString getLanguageSpecificSeparator (SrcLangExt lang, bool classScope)
 Returns the scope separator to use given the programming language lang.
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.
bool protectionLevelVisible (Protection prot)
QCString stripIndentation (const QCString &s, bool skipFirstLine)
void stripIndentationVerbatim (QCString &doc, const int indentationLevel, bool skipFirstLine)
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 ()
QCString getDotImageExtension ()
bool openOutputFile (const QCString &outFile, std::ofstream &f)
static bool keyWordsFortranC (const char *contents)
bool recognizeFixedForm (const QCString &contents, FortranFormat format)
FortranFormat convertFileNameFortranParserCode (QCString fn)
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)
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 &sv, const std::string &delimiter)
 create a string where the string in the vector are joined by the given delimiter
QCString integerToAlpha (int n, bool upper)
QCString integerToRoman (int n, bool upper)
QCString detab (const QCString &s, size_t &refIndent)
QCString getProjectId ()
int computeQualifiedIndex (const QCString &name)
 Return the index of the last :: in the string name that is still before the first <.
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)
QCString writeFileContents (const QCString &baseName, const QCString &extension, const QCString &content, bool &exists)
 Thread-safe function to write a string to a file.
void cleanupInlineGraph ()

Variables

static const char * hex = "0123456789ABCDEF"
static const char constScope [] = { 'c', 'o', 'n', 's', 't', ':' }
static const char volatileScope [] = { 'v', 'o', 'l', 'a', 't', 'i', 'l', 'e', ':' }
static const char virtualScope [] = { 'v', 'i', 'r', 't', 'u', 'a', 'l', ':' }
static const char operatorScope [] = { 'o', 'p', 'e', 'r', 'a', 't', 'o', 'r', '?', '?', '?' }
static CharAroundSpace g_charAroundSpace
static std::mutex g_matchArgsMutex
static Cache< std::string, FindFileCacheElemg_findFileDefCache (5000)
static std::mutex g_findFileDefMutex
static std::unordered_map< std::string, int > g_usedNames
static std::mutex g_usedNamesMutex
static int g_usedNamesCount =1
static std::unordered_map< std::string, SrcLangExtg_extLookup
static std::vector< Lang2ExtMapg_lang2extMap
static std::mutex g_docCacheMutex
static std::unordered_map< std::string, QCStringg_docCache
static std::mutex writeFileContents_lock
static StringUnorderedSet writeFileContents_set

Macro Definition Documentation

◆ ENABLE_TRACINGSUPPORT

#define ENABLE_TRACINGSUPPORT   0

Definition at line 80 of file util.cpp.

◆ HEXTONUM

#define HEXTONUM ( x)
Value:
(((x)>='0' && (x)<='9') ? ((x)-'0') : \
((x)>='a' && (x)<='f') ? ((x)-'a'+10) : \
((x)>='A' && (x)<='F') ? ((x)-'A'+10) : 0)

Referenced by replaceColorMarkers().

◆ MATCH

#define MATCH   AUTO_TRACE_EXIT("match at line {}",__LINE__);

Definition at line 1920 of file util.cpp.

Referenced by matchArgument2(), and matchArguments2().

◆ NOMATCH

#define NOMATCH   AUTO_TRACE_EXIT("no match at line {}",__LINE__);

Definition at line 1921 of file util.cpp.

Referenced by matchArgument2(), and matchArguments2().

◆ REL_PATH_TO_ROOT

#define REL_PATH_TO_ROOT   "../../"

Definition at line 94 of file util.cpp.

Referenced by relativePathToRoot().

Function Documentation

◆ addCodeOnlyMappings()

void addCodeOnlyMappings ( )

Definition at line 5215 of file util.cpp.

5216{
5217 updateLanguageMapping(".xml", "xml");
5218 updateLanguageMapping(".sql", "sql");
5219}
bool updateLanguageMapping(const QCString &extension, const QCString &language)
Definition util.cpp:5116

References updateLanguageMapping().

Referenced by generateOutput().

◆ addGroupListToTitle()

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

◆ addHtmlExtensionIfMissing()

void addHtmlExtensionIfMissing ( QCString & fName)

Definition at line 4932 of file util.cpp.

4933{
4934 if (fName.isEmpty()) return;
4935 int i_fs = fName.findRev('/');
4936 int i_bs = fName.findRev('\\');
4937 int i = fName.find('.',std::max({ i_fs, i_bs ,0})); // search for . after path part
4938 if (i==-1)
4939 {
4941 }
4942}
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(), HtmlGenerator::writeInheritedSectionTitle(), writeJavasScriptSearchDataPage(), writeMapArea(), HtmlGenerator::writeObjectLink(), ClassDefImpl::writeQuickMemberLinks(), FileDefImpl::writeQuickMemberLinks(), GroupDefImpl::writeQuickMemberLinks(), NamespaceDefImpl::writeQuickMemberLinks(), HtmlGenerator::writeSplitBarAsString(), HtmlGenerator::writeStartAnnoItem(), HtmlGenerator::writeSummaryLink(), ClassDefImpl::writeTagFile(), ConceptDefImpl::writeTagFile(), DirDefImpl::writeTagFile(), FileDefImpl::writeTagFile(), GroupDefImpl::writeTagFile(), MemberDefImpl::writeTagFile(), ModuleDefImpl::writeTagFile(), NamespaceDefImpl::writeTagFile(), PageDefImpl::writeTagFile(), RequirementManager::writeTagFile(), VhdlDocGen::writeTagFile(), DocSets::writeToken(), HtmlCodeGenerator::writeTooltip(), and DotNode::writeUrl().

◆ addMembersToMemberGroup()

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

Definition at line 4108 of file util.cpp.

4111{
4112 ASSERT(context!=nullptr);
4113 //printf("addMemberToMemberGroup() context=%s\n",qPrint(context->name()));
4114 if (ml==nullptr) return;
4115
4116 struct MoveMemberInfo
4117 {
4118 MoveMemberInfo(MemberDef *md,MemberGroup *mg,const RefItemVector &rv)
4119 : memberDef(md), memberGroup(mg), sli(rv) {}
4120 MemberDef *memberDef;
4121 MemberGroup *memberGroup;
4122 RefItemVector sli;
4123 };
4124 std::vector<MoveMemberInfo> movedMembers;
4125
4126 for (const auto &md : *ml)
4127 {
4128 if (md->isEnumerate()) // insert enum value of this enum into groups
4129 {
4130 for (const auto &fmd : md->enumFieldList())
4131 {
4132 int groupId=fmd->getMemberGroupId();
4133 if (groupId!=-1)
4134 {
4135 auto it = Doxygen::memberGroupInfoMap.find(groupId);
4137 {
4138 const auto &info = it->second;
4139 auto mg_it = std::find_if(pMemberGroups->begin(),
4140 pMemberGroups->end(),
4141 [&groupId](const auto &g)
4142 { return g->groupId()==groupId; }
4143 );
4144 MemberGroup *mg_ptr = nullptr;
4145 if (mg_it==pMemberGroups->end())
4146 {
4147 auto mg = std::make_unique<MemberGroup>(
4148 context,
4149 groupId,
4150 info->header,
4151 info->doc,
4152 info->docFile,
4153 info->docLine,
4154 ml->container());
4155 mg_ptr = mg.get();
4156 pMemberGroups->push_back(std::move(mg));
4157 }
4158 else
4159 {
4160 mg_ptr = (*mg_it).get();
4161 }
4162 mg_ptr->insertMember(fmd); // insert in member group
4164 if (fmdm)
4165 {
4166 fmdm->setMemberGroup(mg_ptr);
4167 }
4168 }
4169 }
4170 }
4171 }
4172 int groupId=md->getMemberGroupId();
4173 if (groupId!=-1)
4174 {
4175 auto it = Doxygen::memberGroupInfoMap.find(groupId);
4177 {
4178 const auto &info = it->second;
4179 auto mg_it = std::find_if(pMemberGroups->begin(),
4180 pMemberGroups->end(),
4181 [&groupId](const auto &g)
4182 { return g->groupId()==groupId; }
4183 );
4184 MemberGroup *mg_ptr = nullptr;
4185 if (mg_it==pMemberGroups->end())
4186 {
4187 auto mg = std::make_unique<MemberGroup>(
4188 context,
4189 groupId,
4190 info->header,
4191 info->doc,
4192 info->docFile,
4193 info->docLine,
4194 ml->container());
4195 mg_ptr = mg.get();
4196 pMemberGroups->push_back(std::move(mg));
4197 }
4198 else
4199 {
4200 mg_ptr = (*mg_it).get();
4201 }
4202 movedMembers.emplace_back(md,mg_ptr,info->m_sli);
4203 }
4204 }
4205 }
4206
4207 // move the members to their group
4208 for (const auto &mmi : movedMembers)
4209 {
4210 ml->remove(mmi.memberDef); // remove from member list
4211 mmi.memberGroup->insertMember(mmi.memberDef->resolveAlias()); // insert in member group
4212 mmi.memberGroup->setRefItems(mmi.sli);
4213 MemberDefMutable *rmdm = toMemberDefMutable(mmi.memberDef);
4214 if (rmdm)
4215 {
4216 rmdm->setMemberGroup(mmi.memberGroup);
4217 }
4218 }
4219}
static MemberGroupInfoMap memberGroupInfoMap
Definition doxygen.h:118
virtual void setMemberGroup(MemberGroup *grp)=0
A class representing a group of members.
Definition membergroup.h:44
void insertMember(MemberDef *md)
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:175
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 4835 of file util.cpp.

4838{
4839 //printf("addRefItem(sli=%d,key=%s,prefix=%s,name=%s,title=%s,args=%s)\n",(int)sli.size(),key,prefix,name,title,args);
4840 if (!key.isEmpty() && key[0]!='@') // check for @ to skip anonymous stuff (see bug427012)
4841 {
4842 for (RefItem *item : sli)
4843 {
4844 item->setPrefix(prefix);
4845 item->setScope(scope);
4846 item->setName(name);
4847 item->setTitle(title);
4848 item->setArgs(args);
4849 item->setGroup(key);
4850 }
4851 }
4852}
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(), ClassDefImpl::addListReferences(), ConceptDefImpl::addListReferences(), DirDefImpl::addListReferences(), FileDefImpl::addListReferences(), GroupDefImpl::addListReferences(), ModuleDefImpl::addListReferences(), NamespaceDefImpl::addListReferences(), PageDefImpl::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,
GroupDef * gd,
const TagInfo * tagInfo,
bool xref,
SrcLangExt lang )

Definition at line 4705 of file util.cpp.

4716{
4717 PageDef *pd=nullptr;
4718 //printf("addRelatedPage(name=%s gd=%p)\n",qPrint(name),gd);
4719 QCString title=ptitle.stripWhiteSpace();
4720 bool newPage = true;
4721 if ((pd=Doxygen::pageLinkedMap->find(name)) && !pd->isReference())
4722 {
4723 if (!xref && !title.isEmpty() && pd->title()!=pd->name() && pd->title()!=title)
4724 {
4725 warn(fileName,startLine,"multiple use of page label '{}' with different titles, (other occurrence: {}, line: {})",
4726 name,pd->docFile(),pd->getStartBodyLine());
4727 }
4728 if (!title.isEmpty() && pd->title()==pd->name()) // pd has no real title yet
4729 {
4730 pd->setTitle(title);
4732 if (si)
4733 {
4734 si->setTitle(title);
4735 }
4736 }
4737 // append documentation block to the page.
4738 pd->setDocumentation(doc,fileName,docLine);
4739 //printf("Adding page docs '%s' pi=%p name=%s\n",qPrint(doc),pd,name);
4740 // append (x)refitems to the page.
4741 pd->setRefItems(sli);
4742 newPage = false;
4743 }
4744
4745 if (newPage) // new page
4746 {
4747 QCString baseName=name;
4748 if (baseName.endsWith(".tex"))
4749 baseName=baseName.left(baseName.length()-4);
4750 else if (baseName.right(Doxygen::htmlFileExtension.length())==Doxygen::htmlFileExtension)
4751 baseName=baseName.left(baseName.length()-Doxygen::htmlFileExtension.length());
4752
4753 //printf("Appending page '%s'\n",qPrint(baseName));
4754 if (pd) // replace existing page
4755 {
4756 pd->setDocumentation(doc,fileName,docLine);
4758 pd->setShowLineNo(FALSE);
4759 pd->setNestingLevel(0);
4760 pd->setPageScope(nullptr);
4761 pd->setTitle(title);
4762 pd->setReference(QCString());
4763 }
4764 else // newPage
4765 {
4766 pd = Doxygen::pageLinkedMap->add(baseName,
4767 createPageDef(fileName,docLine,baseName,doc,title));
4768 }
4769 pd->setBodySegment(startLine,startLine,-1);
4770
4771 pd->setRefItems(sli);
4772 pd->setLanguage(lang);
4773
4774 if (tagInfo)
4775 {
4776 pd->setReference(tagInfo->tagName);
4777 pd->setFileName(tagInfo->fileName);
4778 }
4779
4780 if (gd) gd->addPage(pd);
4781
4782 if (pd->hasTitle())
4783 {
4784 //outputList->writeTitle(pi->name,pi->title);
4785
4786 // a page name is a label as well!
4787 QCString file;
4788 QCString orgFile;
4789 int line = -1;
4790 if (gd)
4791 {
4792 file=gd->getOutputFileBase();
4793 orgFile=gd->getOutputFileBase();
4794 }
4795 else
4796 {
4797 file=pd->getOutputFileBase();
4798 orgFile=pd->docFile();
4799 line = pd->getStartBodyLine();
4800 }
4801 const SectionInfo *si = SectionManager::instance().find(pd->name());
4802 if (si)
4803 {
4804 if (!si->ref().isEmpty()) // we are from a tag file
4805 {
4807 file,-1,pd->title(),SectionType::Page,0,pd->getReference());
4808 }
4809 else if (si->lineNr() != -1)
4810 {
4811 warn(orgFile,line,"multiple use of section label '{}', (first occurrence: {}, line {})",pd->name(),si->fileName(),si->lineNr());
4812 }
4813 else
4814 {
4815 warn(orgFile,line,"multiple use of section label '{}', (first occurrence: {})",pd->name(),si->fileName());
4816 }
4817 }
4818 else
4819 {
4821 file,-1,pd->title(),SectionType::Page,0,pd->getReference());
4822 //printf("si->label='%s' si->definition=%s si->fileName='%s'\n",
4823 // qPrint(si->label),si->definition?si->definition->name().data():"<none>",
4824 // qPrint(si->fileName));
4825 //printf(" SectionInfo: sec=%p sec->fileName=%s\n",si,qPrint(si->fileName));
4826 //printf("Adding section key=%s si->fileName=%s\n",qPrint(pageName),qPrint(si->fileName));
4827 }
4828 }
4829 }
4830 return pd;
4831}
virtual QCString docFile() const =0
virtual QCString getReference() const =0
virtual QCString getOutputFileBase() const =0
virtual int getStartBodyLine() const =0
virtual bool isReference() const =0
virtual const QCString & name() const =0
virtual void setBodySegment(int defLine, int bls, int ble)=0
virtual void setDocumentation(const QCString &d, const QCString &docFile, int docLine, bool stripWhiteSpace=TRUE)=0
virtual void setLanguage(SrcLangExt lang)=0
virtual void setReference(const QCString &r)=0
virtual void setRefItems(const RefItemVector &sli)=0
static PageLinkedMap * pageLinkedMap
Definition doxygen.h:99
virtual void addPage(PageDef *def)=0
const T * find(const std::string &key) const
Definition linkedmap.h:47
A model of a page symbol.
Definition pagedef.h:26
virtual void setTitle(const QCString &title)=0
virtual void setNestingLevel(int)=0
virtual bool hasTitle() const =0
virtual void setFileName(const QCString &name)=0
virtual void setShowLineNo(bool)=0
virtual QCString title() const =0
virtual void setPageScope(Definition *)=0
This is an alternative implementation of QCString.
Definition qcstring.h:101
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:166
bool endsWith(const char *s) const
Definition qcstring.h:524
QCString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition qcstring.h:260
QCString right(size_t len) const
Definition qcstring.h:234
QCString left(size_t len) const
Definition qcstring.h:229
class that provide information about a section.
Definition section.h:58
QCString ref() const
Definition section.h:72
QCString fileName() const
Definition section.h:74
int lineNr() const
Definition section.h:73
void setTitle(const QCString &t)
Definition section.h:84
SectionInfo * replace(const QCString &label, const QCString &fileName, int lineNr, const QCString &title, SectionType type, int level, const QCString &ref=QCString())
Definition section.h:157
SectionInfo * add(const SectionInfo &si)
Definition section.h:139
static SectionManager & instance()
returns a reference to the singleton
Definition section.h:179
static constexpr int Page
Definition section.h:31
#define warn(file, line, fmt,...)
Definition message.h:97
std::unique_ptr< PageDef > createPageDef(const QCString &f, int l, const QCString &n, const QCString &d, const QCString &t)
Definition pagedef.cpp:82
#define FALSE
Definition qcstring.h:34
QCString fileName
Definition entry.h:106
QCString tagName
Definition entry.h:105
QCString convertNameToFile(const QCString &name, bool allowDots, bool allowUnderscore)
Definition util.cpp:3515

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,
bool showDefVals )

Definition at line 1254 of file util.cpp.

1255{
1256 QCString result;
1257 if (!al.hasParameters()) return result;
1258 result+="(";
1259 for (auto it = al.begin() ; it!=al.end() ;)
1260 {
1261 Argument a = *it;
1262 QCString type1 = useCanonicalType && !a.canType.isEmpty() ? a.canType : a.type;
1263 QCString type2;
1264 int i=type1.find(")("); // hack to deal with function pointers
1265 if (i!=-1)
1266 {
1267 type2=type1.mid(i);
1268 type1=type1.left(i);
1269 }
1270 if (!a.attrib.isEmpty())
1271 {
1272 result+=a.attrib+" ";
1273 }
1274 if (!a.name.isEmpty() || !a.array.isEmpty())
1275 {
1276 result+= type1+" "+a.name+type2+a.array;
1277 }
1278 else
1279 {
1280 result+= type1+type2;
1281 }
1282 if (!a.defval.isEmpty() && showDefVals)
1283 {
1284 result+="="+a.defval;
1285 }
1286 ++it;
1287 if (it!=al.end()) result+=", ";
1288 }
1289 result+=")";
1290 if (al.constSpecifier()) result+=" const";
1291 if (al.volatileSpecifier()) result+=" volatile";
1292 if (al.refQualifier()==RefQualifierType::LValue) result+=" &";
1293 else if (al.refQualifier()==RefQualifierType::RValue) result+=" &&";
1294 if (!al.trailingReturnType().isEmpty()) result+=al.trailingReturnType();
1295 if (al.pureSpecifier()) result+=" =0";
1296 return removeRedundantWhiteSpace(result);
1297}
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:567

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(), substituteTemplateArgumentsInString(), and ClassDefImpl::title().

◆ checkBlocks()

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

Definition at line 6552 of file util.cpp.

6553{
6554 if (s.isEmpty()) return;
6555
6556 const char *p = s.data();
6557 char c = 0;
6558 while ((c=*p))
6559 {
6560 if (c==markerInfo.markerChar) // potential start of marker
6561 {
6562 if (qstrncmp(p,markerInfo.beginStr,markerInfo.beginLen)==0) // start of begin marker
6563 {
6564 size_t len = markerInfo.beginLen;
6565 bool negate = *(p+len)=='!';
6566 if (negate) len++;
6567 p += len;
6568 QCString marker;
6569 while (*p)
6570 {
6571 if (markerInfo.closeLen==0 && *p=='\n') // matching end of line
6572 {
6573 warn(fileName,-1,"Remaining begin replacement with marker '{}'",marker);
6574 break;
6575 }
6576 else if (markerInfo.closeLen!= 0 && qstrncmp(p,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6577 {
6578 p += markerInfo.closeLen;
6579 warn(fileName,-1,"Remaining begin replacement with marker '{}'",marker);
6580 break;
6581 }
6582 marker += *p;
6583 p++;
6584 }
6585 }
6586 else if (qstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // start of end marker
6587 {
6588 size_t len = markerInfo.endLen;
6589 bool negate = *(p+len)=='!';
6590 if (negate) len++;
6591 p += len;
6592 QCString marker;
6593 while (*p)
6594 {
6595 if (markerInfo.closeLen==0 && *p=='\n') // matching end of line
6596 {
6597 warn(fileName,-1,"Remaining end replacement with marker '{}'",marker);
6598 break;
6599 }
6600 else if (markerInfo.closeLen!= 0 && qstrncmp(p,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6601 {
6602 p += markerInfo.closeLen;
6603 warn(fileName,-1,"Remaining end replacement with marker '{}'",marker);
6604 break;
6605 }
6606 marker += *p;
6607 p++;
6608 }
6609 }
6610 }
6611 p++;
6612 }
6613}
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:236
const char * closeStr
Definition util.h:239
const char * beginStr
Definition util.h:235
size_t closeLen
Definition util.h:240
const char * endStr
Definition util.h:237

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

4928{
4929 return fName.right(ext.length())==ext;
4930}

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

5326{
5327 MemberDef *bestMatch = getMemberFromSymbol(scope,fileScope,n);
5328
5329 if (bestMatch && bestMatch->isTypedef())
5330 return TRUE; // closest matching symbol is a typedef
5331 else
5332 return FALSE;
5333}
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:5273

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

Referenced by isVarWithConstructor().

◆ cleanupInlineGraph()

void cleanupInlineGraph ( )

Definition at line 7020 of file util.cpp.

7021{
7022 if (Config_getBool(DOT_CLEANUP))
7023 {
7024 for (const auto& fileName: writeFileContents_set)
7025 {
7026 Dir().remove(qPrint(fileName));
7027 }
7028 }
7029}
Class representing a directory in the file system.
Definition dir.h:75
bool remove(const std::string &path, bool acceptsAbsPath=true) const
Definition dir.cpp:314
#define Config_getBool(name)
Definition config.h:33
const char * qPrint(const char *s)
Definition qcstring.h:687
static StringUnorderedSet writeFileContents_set
Definition util.cpp:6979

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

Referenced by generateOutput().

◆ clearSubDirs()

void clearSubDirs ( const Dir & d)

Definition at line 3678 of file util.cpp.

3679{
3680 if (Config_getBool(CREATE_SUBDIRS))
3681 {
3682 // remove empty subdirectories
3683 int createSubdirsLevelPow2 = 1 << Config_getInt(CREATE_SUBDIRS_LEVEL);
3684 for (int l1=0;l1<16;l1++)
3685 {
3686 QCString subdir;
3687 subdir.sprintf("d%x",l1);
3688 for (int l2=0; l2 < createSubdirsLevelPow2; l2++)
3689 {
3690 QCString subsubdir;
3691 subsubdir.sprintf("d%x/d%02x",l1,l2);
3692 if (d.exists(subsubdir.str()) && d.isEmpty(subsubdir.str()))
3693 {
3694 d.rmdir(subsubdir.str());
3695 }
3696 }
3697 if (d.exists(subdir.str()) && d.isEmpty(subdir.str()))
3698 {
3699 d.rmdir(subdir.str());
3700 }
3701 }
3702 }
3703}
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

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

6855{
6856 int l = static_cast<int>(name.length());
6857 int lastSepPos = -1;
6858 const char *p = name.data();
6859 int i=l-2;
6860 int sharpCount=0;
6861 // --- begin optimized version of ts=name.findRev(">::");
6862 int ts = -1;
6863 while (i>=0)
6864 {
6865 if (p[i]=='>')
6866 {
6867 if (sharpCount==0 && p[i+1]==':' && p[i+2]==':')
6868 {
6869 ts=i;
6870 break;
6871 }
6872 sharpCount++;
6873 }
6874 else if (p[i]=='<')
6875 {
6876 sharpCount--;
6877 }
6878 i--;
6879 }
6880 // --- end optimized version
6881 if (ts==-1) ts=0; else p+=++ts;
6882 for (i=ts;i<l-1;i++)
6883 {
6884 char c=*p++;
6885 if (c==':' && *p==':') lastSepPos=i;
6886 if (c=='<') break;
6887 }
6888 return lastSepPos;
6889}

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 & str,
const char * word )

returns TRUE iff string s contains word w

Definition at line 4981 of file util.cpp.

4982{
4983 if (str.isEmpty() || word==nullptr) return false;
4984 static const reg::Ex re(R"(\a+)");
4985 std::string s = str.str();
4986 for (reg::Iterator it(s,re) ; it!=reg::Iterator() ; ++it)
4987 {
4988 if (it->str()==word) return true;
4989 }
4990 return false;
4991}
Class representing a regular expression.
Definition regex.h:39
Class to iterate through matches.
Definition regex.h:230

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

◆ convertCharEntitiesToUTF8()

QCString convertCharEntitiesToUTF8 ( const QCString & str)

Definition at line 4058 of file util.cpp.

4059{
4060 if (str.isEmpty()) return QCString();
4061
4062 std::string s = str.data();
4063 static const reg::Ex re(R"(&\a\w*;)");
4064 reg::Iterator it(s,re);
4066
4067 QCString result;
4068 result.reserve(str.length()+32);
4069 size_t p=0, i=0, l=0;
4070 for (; it!=end ; ++it)
4071 {
4072 const auto &match = *it;
4073 p = match.position();
4074 l = match.length();
4075 if (p>i)
4076 {
4077 result+=s.substr(i,p-i);
4078 }
4079 QCString entity(match.str());
4081 const char *code=nullptr;
4082 if (symType!=HtmlEntityMapper::Sym_Unknown && (code=HtmlEntityMapper::instance().utf8(symType)))
4083 {
4084 result+=code;
4085 }
4086 else
4087 {
4088 result+=entity;
4089 }
4090 i=p+l;
4091 }
4092 result+=s.substr(i);
4093 //printf("convertCharEntitiesToUTF8(%s)->%s\n",qPrint(s),qPrint(result));
4094 return result;
4095}
static HtmlEntityMapper & instance()
Returns the one and only instance of the HTML entity mapper.
SymType name2sym(const QCString &symName) const
Give code of the requested HTML entity name.
void reserve(size_t size)
Reserve space for size bytes without changing the string contents.
Definition qcstring.h:185
bool match(std::string_view str, Match &match, const Ex &re)
Matches a given string str for a match against regular expression re.
Definition regex.cpp:855

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

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

◆ convertFileNameFortranParserCode()

FortranFormat convertFileNameFortranParserCode ( QCString fn)

Definition at line 6426 of file util.cpp.

6427{
6429 QCString parserName = Doxygen::parserManager->getParserName(ext);
6430
6431 if (parserName == "fortranfixed") return FortranFormat::Fixed;
6432 else if (parserName == "fortranfree") return FortranFormat::Free;
6433
6435}
static ParserManager * parserManager
Definition doxygen.h:129
QCString getFileNameExtension(const QCString &fn)
Definition util.cpp:5263

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

3516{
3517 if (name.isEmpty()) return name;
3518 bool shortNames = Config_getBool(SHORT_NAMES);
3519 bool createSubdirs = Config_getBool(CREATE_SUBDIRS);
3520 QCString result;
3521 if (shortNames) // use short names only
3522 {
3523 std::lock_guard<std::mutex> lock(g_usedNamesMutex);
3524 auto kv = g_usedNames.find(name.str());
3525 uint32_t num=0;
3526 if (kv!=g_usedNames.end())
3527 {
3528 num = kv->second;
3529 }
3530 else
3531 {
3532 num = g_usedNamesCount;
3533 g_usedNames.emplace(name.str(),g_usedNamesCount++);
3534 }
3535 result.sprintf("a%05d",num);
3536 }
3537 else // long names
3538 {
3539 result=escapeCharsInString(name,allowDots,allowUnderscore);
3540 size_t resultLen = result.length();
3541 if (resultLen>=128) // prevent names that cannot be created!
3542 {
3543 // third algorithm based on MD5 hash
3544 uint8_t md5_sig[16];
3545 char sigStr[33];
3546 MD5Buffer(result.data(),static_cast<unsigned int>(resultLen),md5_sig);
3547 MD5SigToString(md5_sig,sigStr);
3548 result=result.left(128-32)+sigStr;
3549 }
3550 }
3551 if (createSubdirs)
3552 {
3553 int l1Dir=0,l2Dir=0;
3554 int createSubdirsLevel = Config_getInt(CREATE_SUBDIRS_LEVEL);
3555 int createSubdirsBitmaskL2 = (1<<createSubdirsLevel)-1;
3556
3557 // compute md5 hash to determine sub directory to use
3558 uint8_t md5_sig[16];
3559 MD5Buffer(result.data(),static_cast<unsigned int>(result.length()),md5_sig);
3560 l1Dir = md5_sig[14] & 0xf;
3561 l2Dir = md5_sig[15] & createSubdirsBitmaskL2;
3562
3563 result.prepend(QCString().sprintf("d%x/d%02x/",l1Dir,l2Dir));
3564 }
3565 //printf("*** convertNameToFile(%s)->%s\n",qPrint(name),qPrint(result));
3566 return result;
3567}
QCString & prepend(const char *s)
Definition qcstring.h:422
static int g_usedNamesCount
Definition util.cpp:3507
QCString escapeCharsInString(const QCString &name, bool allowDots, bool allowUnderscore)
Definition util.cpp:3340
static std::mutex g_usedNamesMutex
Definition util.cpp:3506
static std::unordered_map< std::string, int > g_usedNames
Definition util.cpp:3505

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(), NamespaceDefImpl::setFileNameLocal(), and xmlRequirementId().

◆ convertProtectionLevel()

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

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

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

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

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

Definition at line 6259 of file util.cpp.

6265{
6266 bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
6267
6268 // default representing 1-1 mapping
6269 *outListType1=inListType;
6270 *outListType2=MemberListType::Invalid();
6271
6272 if (inProt==Protection::Public)
6273 {
6274 if (inListType.isPrivate())
6275 {
6276 *outListType1=MemberListType::Invalid();
6277 }
6278 }
6279 else if (inProt==Protection::Protected)
6280 {
6281 if (inListType.isPrivate() || inListType.isPublic())
6282 {
6283 *outListType1=MemberListType::Invalid();
6284 }
6285 else if (inListType.isProtected())
6286 {
6287 *outListType2=inListType.toPublic();
6288 }
6289 }
6290 else if (inProt==Protection::Private)
6291 {
6292 if (inListType.isPublic() || inListType.isProtected())
6293 {
6294 *outListType1=MemberListType::Invalid();
6295 }
6296 else if (inListType.isPrivate())
6297 {
6298 if (extractPrivate)
6299 {
6300 *outListType1=inListType.toPublic();
6301 *outListType2=inListType.toProtected();
6302 }
6303 else
6304 {
6305 *outListType1=MemberListType::Invalid();
6306 }
6307 }
6308 }
6309
6310 //printf("convertProtectionLevel(type=%s prot=%d): %s,%s\n",
6311 // qPrint(inListType.to_string()),inProt,qPrint(outListType1->to_string()),qPrint(outListType2->to_string()));
6312}
constexpr bool isPrivate() const noexcept
Definition types.h:382
constexpr MemberListType toPublic() const noexcept
Definition types.h:426
static constexpr MemberListType Invalid() noexcept
Definition types.h:371
constexpr MemberListType toProtected() const noexcept
Definition types.h:438
constexpr bool isProtected() const noexcept
Definition types.h:380
ML_TYPES constexpr bool isPublic() const noexcept
Definition types.h:378

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

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

◆ convertToHtml()

QCString convertToHtml ( const QCString & s,
bool keepEntities )

Converts a string to a HTML-encoded string

Definition at line 3974 of file util.cpp.

3975{
3976 if (s.isEmpty()) return s;
3977 QCString result;
3978 result.reserve(s.length()+32);
3979 const char *p=s.data();
3980 char c = 0;
3981 while ((c=*p++))
3982 {
3983 switch (c)
3984 {
3985 case '<': result+="&lt;"; break;
3986 case '>': result+="&gt;"; break;
3987 case '&': if (keepEntities)
3988 {
3989 const char *e=p;
3990 char ce = 0;
3991 while ((ce=*e++))
3992 {
3993 if (ce==';' || (!(isId(ce) || ce=='#'))) break;
3994 }
3995 if (ce==';') // found end of an entity
3996 {
3997 // copy entry verbatim
3998 result+=c;
3999 while (p<e) result+=*p++;
4000 }
4001 else
4002 {
4003 result+="&amp;";
4004 }
4005 }
4006 else
4007 {
4008 result+="&amp;";
4009 }
4010 break;
4011 case '\'': result+="&#39;"; break;
4012 case '"': result+="&quot;"; break;
4013 default:
4014 {
4015 uint8_t uc = static_cast<uint8_t>(c);
4016 if (uc<32 && !isspace(c))
4017 {
4018 result+="&#x24";
4019 result+=hex[uc>>4];
4020 result+=hex[uc&0xF];
4021 result+=';';
4022 }
4023 else
4024 {
4025 result+=c;
4026 }
4027 }
4028 break;
4029 }
4030 }
4031 return result;
4032}
static constexpr auto hex
bool isId(int c)
Definition util.h:256

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

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

◆ convertToId()

QCString convertToId ( const QCString & s)

Converts a string to a HTML id string

Definition at line 3883 of file util.cpp.

3884{
3885 if (s.isEmpty()) return s;
3886 QCString result;
3887 result.reserve(s.length()+8);
3888 const char *p = s.data();
3889 char c = 0;
3890 bool first = true;
3891 while ((c=*p++))
3892 {
3893 char encChar[4];
3894 if ((c>='0' && c<='9') || (c>='a' && c<='z') || (c>='A' && c<='Z') || c=='-')
3895 { // any permissive character except _
3896 if (first && c>='0' && c<='9') result+='a'; // don't start with a digit
3897 result+=c;
3898 }
3899 else
3900 {
3901 encChar[0]='_';
3902 encChar[1]=hex[static_cast<unsigned char>(c)>>4];
3903 encChar[2]=hex[static_cast<unsigned char>(c)&0xF];
3904 encChar[3]=0;
3905 result+=encChar;
3906 }
3907 first=false;
3908 }
3909 return result;
3910}

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

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

◆ convertToJSString()

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

Definition at line 4034 of file util.cpp.

4035{
4036 if (s.isEmpty()) return s;
4037 QCString result;
4038 result.reserve(s.length()+32);
4039 const char *p=s.data();
4040 char c = 0;
4041 while ((c=*p++))
4042 {
4043 switch (c)
4044 {
4045 case '"': if (!singleQuotes) result+="\\\""; else result+=c;
4046 break;
4047 case '\'': if (singleQuotes) result+="\\\'"; else result+=c;
4048 break;
4049 case '\\': if (*p=='u' && *(p+1)=='{') result+="\\"; // keep \u{..} unicode escapes
4050 else result+="\\\\";
4051 break;
4052 default: result+=c; break;
4053 }
4054 }
4055 return keepEntities ? result : convertCharEntitiesToUTF8(result);
4056}
QCString convertCharEntitiesToUTF8(const QCString &str)
Definition util.cpp:4058

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

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

◆ convertToXML()

QCString convertToXML ( const QCString & s,
bool keepEntities )

Converts a string to an XML-encoded string

Definition at line 3923 of file util.cpp.

3924{
3925 if (s.isEmpty()) return s;
3926 QCString result;
3927 result.reserve(s.length()+32);
3928 const char *p = s.data();
3929 char c = 0;
3930 while ((c=*p++))
3931 {
3932 switch (c)
3933 {
3934 case '<': result+="&lt;"; break;
3935 case '>': result+="&gt;"; break;
3936 case '&': if (keepEntities)
3937 {
3938 const char *e=p;
3939 char ce = 0;
3940 while ((ce=*e++))
3941 {
3942 if (ce==';' || (!(isId(ce) || ce=='#'))) break;
3943 }
3944 if (ce==';') // found end of an entity
3945 {
3946 // copy entry verbatim
3947 result+=c;
3948 while (p<e) result+=*p++;
3949 }
3950 else
3951 {
3952 result+="&amp;";
3953 }
3954 }
3955 else
3956 {
3957 result+="&amp;";
3958 }
3959 break;
3960 case '\'': result+="&apos;"; break;
3961 case '"': result+="&quot;"; break;
3962 case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
3963 case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18:
3964 case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26:
3965 case 27: case 28: case 29: case 30: case 31:
3966 break; // skip invalid XML characters (see http://www.w3.org/TR/2000/REC-xml-20001006#NT-Char)
3967 default: result+=c; break;
3968 }
3969 }
3970 return result;
3971}

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

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

◆ copyFile()

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

3917{
3918 if (s.isEmpty()) return s;
3919 return "a" + s;
3920}

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

5956{
5957 QCString result = url;
5958 if (!relPath.isEmpty() && !isURL(url))
5959 {
5960 result.prepend(relPath);
5961 }
5962 return result;
5963}
bool isURL(const QCString &url)
Checks whether the given url starts with a supported protocol.
Definition util.cpp:5943

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

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

◆ createHtmlUrl()

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

Definition at line 5746 of file util.cpp.

5752{
5753 QCString url;
5754 if (!ref.isEmpty())
5755 {
5756 url = externalRef(relPath,ref,href);
5757 }
5758 if (!targetFileName.isEmpty())
5759 {
5760 QCString fn = targetFileName;
5761 if (ref.isEmpty())
5762 {
5763 if (!anchor.isEmpty() && isLocalFile)
5764 {
5765 fn=""; // omit file name for local links
5766 }
5767 else
5768 {
5769 url = relPath;
5770 }
5771 }
5772 url+=fn;
5773 }
5774 if (!anchor.isEmpty())
5775 {
5776 if (!url.endsWith("=")) url+="#";
5777 url+=anchor;
5778 }
5779 //printf("createHtmlUrl(relPath=%s,local=%d,target=%s,anchor=%s)=%s\n",qPrint(relPath),isLocalFile,qPrint(targetFileName),qPrint(anchor),qPrint(url));
5780 return url;
5781}
QCString externalRef(const QCString &relPath, const QCString &ref, bool href)
Definition util.cpp:5783

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

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

◆ createSubDirs()

void createSubDirs ( const Dir & d)

Definition at line 3651 of file util.cpp.

3652{
3653 if (Config_getBool(CREATE_SUBDIRS))
3654 {
3655 // create up to 4096 subdirectories
3656 int createSubdirsLevelPow2 = 1 << Config_getInt(CREATE_SUBDIRS_LEVEL);
3657 for (int l1=0; l1<16; l1++)
3658 {
3659 QCString subdir;
3660 subdir.sprintf("d%x",l1);
3661 if (!d.exists(subdir.str()) && !d.mkdir(subdir.str()))
3662 {
3663 term("Failed to create output directory '{}'\n",subdir);
3664 }
3665 for (int l2=0; l2<createSubdirsLevelPow2; l2++)
3666 {
3667 QCString subsubdir;
3668 subsubdir.sprintf("d%x/d%02x",l1,l2);
3669 if (!d.exists(subsubdir.str()) && !d.mkdir(subsubdir.str()))
3670 {
3671 term("Failed to create output directory '{}'\n",subsubdir);
3672 }
3673 }
3674 }
3675 }
3676}
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 6953 of file util.cpp.

6954{
6955 QCString result=name;
6956 if (result.endsWith("-g"))
6957 {
6958 int idx = result.find('-');
6959 result = result.left(idx)+templArgs;
6960 }
6961 return result;
6962}

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

Referenced by ClassDefImpl::className().

◆ detab()

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

Definition at line 6750 of file util.cpp.

6751{
6752 int tabSize = Config_getInt(TAB_SIZE);
6753 size_t size = s.length();
6754 QCString result;
6755 result.reserve(size+256);
6756 const char *data = s.data();
6757 size_t i=0;
6758 int col=0;
6759 constexpr auto doxy_nbsp = "&_doxy_nbsp;"; // doxygen escape command for UTF-8 nbsp
6760 const int maxIndent=1000000; // value representing infinity
6761 int minIndent=maxIndent;
6762 bool skip = false;
6763 while (i<size)
6764 {
6765 char c = data[i++];
6766 switch(c)
6767 {
6768 case '\t': // expand tab
6769 {
6770 int stop = tabSize - (col%tabSize);
6771 //printf("expand at %d stop=%d\n",col,stop);
6772 col+=stop;
6773 while (stop--) result+=' ';
6774 }
6775 break;
6776 case '\\':
6777 if (data[i] == '\\') // escaped command -> ignore
6778 {
6779 result+=c;
6780 result+=data[i++];
6781 col+=2;
6782 }
6783 else if (i+5<size && literal_at(data+i,"iskip")) // command
6784 {
6785 i+=5;
6786 skip = true;
6787 }
6788 else if (i+8<size && literal_at(data+i,"endiskip")) // command
6789 {
6790 i+=8;
6791 skip = false;
6792 }
6793 else // some other command
6794 {
6795 result+=c;
6796 col++;
6797 }
6798 break;
6799 case '\n': // reset column counter
6800 result+=c;
6801 col=0;
6802 break;
6803 case ' ': // increment column counter
6804 result+=c;
6805 col++;
6806 break;
6807 default: // non-whitespace => update minIndent
6808 if (c<0 && i<size) // multibyte sequence
6809 {
6810 // special handling of the UTF-8 nbsp character 0xC2 0xA0
6811 int nb = isUTF8NonBreakableSpace(data);
6812 if (nb>0)
6813 {
6814 result+=doxy_nbsp;
6815 i+=nb-1;
6816 }
6817 else
6818 {
6819 int bytes = getUTF8CharNumBytes(c);
6820 for (int j=0;j<bytes-1 && c;j++)
6821 {
6822 result+=c;
6823 c = data[i++];
6824 }
6825 result+=c;
6826 }
6827 }
6828 else
6829 {
6830 result+=c;
6831 }
6832 if (!skip && col<minIndent) minIndent=col;
6833 col++;
6834 }
6835 }
6836 if (minIndent!=maxIndent) refIndent=minIndent; else refIndent=0;
6837 //printf("detab(\n%s\n)=[\n%s\n]\n",qPrint(s),qPrint(out.get()));
6838 return result;
6839}
bool literal_at(const char *data, const char(&str)[N])
returns TRUE iff data points to a substring that matches string literal str
Definition stringutil.h:98
int isUTF8NonBreakableSpace(const char *input)
Check if the first character pointed at by input is a non-breakable whitespace character.
Definition utf8.cpp:228
uint8_t getUTF8CharNumBytes(char c)
Returns the number of bytes making up a single UTF8 character given the first byte in the sequence.
Definition utf8.cpp:23

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

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

◆ determineAbsoluteIncludeName()

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

Definition at line 3611 of file util.cpp.

3612{
3613 bool searchIncludes = Config_getBool(SEARCH_INCLUDES);
3614 QCString absIncFileName = incFileName;
3615 FileInfo fi(curFile.str());
3616 if (fi.exists())
3617 {
3618 QCString absName = fi.dirPath(TRUE)+"/"+incFileName;
3619 FileInfo fi2(absName.str());
3620 if (fi2.exists())
3621 {
3622 absIncFileName=fi2.absFilePath();
3623 }
3624 else if (searchIncludes) // search in INCLUDE_PATH as well
3625 {
3626 const StringVector &includePath = Config_getList(INCLUDE_PATH);
3627 for (const auto &incPath : includePath)
3628 {
3629 FileInfo fi3(incPath);
3630 if (fi3.exists() && fi3.isDir())
3631 {
3632 absName = fi3.absFilePath()+"/"+incFileName;
3633 //printf("trying absName=%s\n",qPrint(absName));
3634 FileInfo fi4(absName.str());
3635 if (fi4.exists())
3636 {
3637 absIncFileName=fi4.absFilePath();
3638 break;
3639 }
3640 //printf( "absIncFileName = %s\n", qPrint(absIncFileName) );
3641 }
3642 }
3643 }
3644 //printf( "absIncFileName = %s\n", qPrint(absIncFileName) );
3645 }
3646 return absIncFileName;
3647}
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 )

Definition at line 3340 of file util.cpp.

3341{
3342 if (name.isEmpty()) return name;
3343 bool caseSenseNames = getCaseSenseNames();
3344 bool allowUnicodeNames = Config_getBool(ALLOW_UNICODE_NAMES);
3345 QCString result;
3346 result.reserve(name.length()+8);
3347 signed char c = 0;
3348 const char *p=name.data();
3349 while ((c=*p++)!=0)
3350 {
3351 switch(c)
3352 {
3353 case '_': if (allowUnderscore) result+='_'; else result+="__"; break;
3354 case '-': result+='-'; break;
3355 case ':': result+="_1"; break;
3356 case '/': result+="_2"; break;
3357 case '<': result+="_3"; break;
3358 case '>': result+="_4"; break;
3359 case '*': result+="_5"; break;
3360 case '&': result+="_6"; break;
3361 case '|': result+="_7"; break;
3362 case '.': if (allowDots) result+='.'; else result+="_8"; break;
3363 case '!': result+="_9"; break;
3364 case ',': result+="_00"; break;
3365 case ' ': result+="_01"; break;
3366 case '{': result+="_02"; break;
3367 case '}': result+="_03"; break;
3368 case '?': result+="_04"; break;
3369 case '^': result+="_05"; break;
3370 case '%': result+="_06"; break;
3371 case '(': result+="_07"; break;
3372 case ')': result+="_08"; break;
3373 case '+': result+="_09"; break;
3374 case '=': result+="_0a"; break;
3375 case '$': result+="_0b"; break;
3376 case '\\': result+="_0c"; break;
3377 case '@': result+="_0d"; break;
3378 case ']': result+="_0e"; break;
3379 case '[': result+="_0f"; break;
3380 case '#': result+="_0g"; break;
3381 case '"': result+="_0h"; break;
3382 case '~': result+="_0i"; break;
3383 case '\'': result+="_0j"; break;
3384 case ';': result+="_0k"; break;
3385 case '`': result+="_0l"; break;
3386 default:
3387 if (c<0)
3388 {
3389 bool doEscape = true;
3390 if (allowUnicodeNames)
3391 {
3392 int charLen = getUTF8CharNumBytes(c);
3393 if (charLen>0)
3394 {
3395 result+=QCString(p-1,charLen);
3396 p+=charLen;
3397 doEscape = false;
3398 }
3399 }
3400 if (doEscape) // not a valid unicode char or escaping needed
3401 {
3402 char ids[5];
3403 unsigned char id = static_cast<unsigned char>(c);
3404 ids[0]='_';
3405 ids[1]='x';
3406 ids[2]=hex[id>>4];
3407 ids[3]=hex[id&0xF];
3408 ids[4]=0;
3409 result+=ids;
3410 }
3411 }
3412 else if (caseSenseNames || !isupper(c))
3413 {
3414 result+=c;
3415 }
3416 else
3417 {
3418 result+='_';
3419 result+=static_cast<char>(tolower(c));
3420 }
3421 break;
3422 }
3423 }
3424 return result;
3425}
bool getCaseSenseNames()
Definition util.cpp:3331

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

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

◆ externalLinkTarget()

QCString externalLinkTarget ( const bool parent)

Definition at line 5735 of file util.cpp.

5736{
5737 bool extLinksInWindow = Config_getBool(EXT_LINKS_IN_WINDOW);
5738 if (extLinksInWindow)
5739 return "target=\"_blank\" ";
5740 else if (parent)
5741 return "target=\"_parent\" ";
5742 else
5743 return "";
5744}
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:1336

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

5784{
5785 QCString result;
5786 if (!ref.isEmpty())
5787 {
5788 auto it = Doxygen::tagDestinationMap.find(ref.str());
5790 {
5791 result = it->second;
5792 size_t l = result.length();
5793 if (!relPath.isEmpty() && l>0 && result.at(0)=='.')
5794 { // relative path -> prepend relPath.
5795 result.prepend(relPath);
5796 l+=relPath.length();
5797 }
5798 if (l>0 && result.at(l-1)!='/') result+='/';
5799 if (!href) result.append("\" ");
5800 }
5801 }
5802 else
5803 {
5804 result = relPath;
5805 }
5806 return result;
5807}
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 6964 of file util.cpp.

6965{
6966 QCString text=rawStart;
6967 int i = text.find('"');
6968 assert(i!=-1);
6969 return text.mid(i+1,text.length()-i-2); // text=...R"xyz( -> delimiter=xyz
6970}

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

◆ extractCanonicalArgType()

QCString extractCanonicalArgType ( const Definition * d,
const FileDef * fs,
const Argument & arg,
SrcLangExt lang )
static

Definition at line 1890 of file util.cpp.

1891{
1892 QCString type = arg.type.stripWhiteSpace();
1893 QCString name = arg.name;
1894 //printf("----- extractCanonicalArgType(type=%s,name=%s)\n",qPrint(type),qPrint(name));
1895 if ((type=="const" || type=="volatile") && !name.isEmpty())
1896 { // name is part of type => correct
1897 type+=" ";
1898 type+=name;
1899 }
1900 if (name=="const" || name=="volatile")
1901 { // name is part of type => correct
1902 if (!type.isEmpty()) type+=" ";
1903 type+=name;
1904 }
1905 if (!arg.array.isEmpty())
1906 {
1907 type+=arg.array;
1908 }
1909
1910 return extractCanonicalType(d,fs,type,lang,false);
1911}
static QCString extractCanonicalType(const Definition *d, const FileDef *fs, QCString type, SrcLangExt lang, bool insideTemplate)
Definition util.cpp:1814

References Argument::array, extractCanonicalType(), QCString::isEmpty(), Argument::name, QCString::stripWhiteSpace(), and Argument::type.

Referenced by matchArgument2().

◆ extractCanonicalType()

QCString extractCanonicalType ( const Definition * d,
const FileDef * fs,
QCString type,
SrcLangExt lang,
bool insideTemplate )
static

Definition at line 1814 of file util.cpp.

1815{
1816 AUTO_TRACE("d={} fs={} type='{}'",d?d->name():"",fs?fs->name():"",type);
1817 type = type.stripWhiteSpace();
1818
1819 // strip const and volatile keywords that are not relevant for the type
1820 stripIrrelevantConstVolatile(type,insideTemplate);
1821
1822 // strip leading keywords
1823 type.stripPrefix("class ");
1824 type.stripPrefix("struct ");
1825 type.stripPrefix("union ");
1826 type.stripPrefix("enum ");
1827 type.stripPrefix("typename ");
1828
1829 type = removeRedundantWhiteSpace(type);
1830 //printf("extractCanonicalType(type=%s) start: def=%s file=%s\n",qPrint(type),
1831 // d ? qPrint(d->name()) : "<null>", fs ? qPrint(fs->name()) : "<null>");
1832
1833 QCString canType;
1834 QCString templSpec,word;
1835 int i=0,p=0,pp=0;
1836 while ((i=extractClassNameFromType(type,p,word,templSpec))!=-1)
1837 // foreach identifier in the type
1838 {
1839 //printf(" i=%d p=%d\n",i,p);
1840 if (i>pp) canType += type.mid(pp,i-pp);
1841
1842 QCString ct = getCanonicalTypeForIdentifier(d,fs,word,lang,&templSpec);
1843
1844 // in case the ct is empty it means that "word" represents scope "d"
1845 // and this does not need to be added to the canonical
1846 // type (it is redundant), so/ we skip it. This solves problem 589616.
1847 if (ct.isEmpty() && type.mid(p,2)=="::")
1848 {
1849 p+=2;
1850 }
1851 else
1852 {
1853 canType += ct;
1854 }
1855 //printf(" word=%s templSpec=%s canType=%s ct=%s\n",
1856 // qPrint(word), qPrint(templSpec), qPrint(canType), qPrint(ct));
1857 if (!templSpec.isEmpty()) // if we didn't use up the templSpec already
1858 // (i.e. type is not a template specialization)
1859 // then resolve any identifiers inside.
1860 {
1861 std::string ts = templSpec.str();
1862 static const reg::Ex re(R"(\a\w*)");
1863 reg::Iterator it(ts,re);
1865
1866 size_t tp=0;
1867 // for each identifier template specifier
1868 //printf("adding resolved %s to %s\n",qPrint(templSpec),qPrint(canType));
1869 for (; it!=end ; ++it)
1870 {
1871 const auto &match = *it;
1872 size_t ti = match.position();
1873 size_t tl = match.length();
1874 std::string matchStr = match.str();
1875 canType += ts.substr(tp,ti-tp);
1876 canType += getCanonicalTypeForIdentifier(d,fs,matchStr,lang,nullptr);
1877 tp=ti+tl;
1878 }
1879 canType+=ts.substr(tp);
1880 }
1881
1882 pp=p;
1883 }
1884 canType += type.right(type.length()-pp);
1885 AUTO_TRACE_EXIT("canType='{}'",canType);
1886
1887 return removeRedundantWhiteSpace(canType);
1888}
bool stripPrefix(const QCString &prefix)
Definition qcstring.h:213
#define AUTO_TRACE(...)
Definition docnode.cpp:48
#define AUTO_TRACE_EXIT(...)
Definition docnode.cpp:50
int extractClassNameFromType(const QCString &type, int &pos, QCString &name, QCString &templSpec, SrcLangExt lang)
Definition util.cpp:4226
static QCString getCanonicalTypeForIdentifier(const Definition *d, const FileDef *fs, const QCString &word, SrcLangExt lang, QCString *tSpec, int count=0)
Definition util.cpp:1660
void stripIrrelevantConstVolatile(QCString &s, bool insideTemplate)
Definition util.cpp:1613

References AUTO_TRACE, AUTO_TRACE_EXIT, end(), extractClassNameFromType(), getCanonicalTypeForIdentifier(), QCString::isEmpty(), QCString::length(), QCString::mid(), Definition::name(), removeRedundantWhiteSpace(), QCString::right(), QCString::str(), stripIrrelevantConstVolatile(), QCString::stripPrefix(), and QCString::stripWhiteSpace().

Referenced by extractCanonicalArgType(), and getCanonicalTemplateSpec().

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

4227{
4228 AUTO_TRACE("type='{}' name='{}' lang={}",type,name,lang);
4229 static const reg::Ex re_norm(R"(\a[\w:]*)");
4230 static const reg::Ex re_fortran(R"(\a[\w:()=]*)");
4231 const reg::Ex *re = &re_norm;
4232
4233 name.clear();
4234 templSpec.clear();
4235 if (type.isEmpty())
4236 {
4237 AUTO_TRACE_EXIT("empty type");
4238 return -1;
4239 }
4240 size_t typeLen=type.length();
4241 if (typeLen>0)
4242 {
4243 if (lang == SrcLangExt::Fortran)
4244 {
4245 if (type[pos]==',')
4246 {
4247 AUTO_TRACE_EXIT("comma");
4248 return -1;
4249 }
4250 if (!type.lower().startsWith("type"))
4251 {
4252 re = &re_fortran;
4253 }
4254 }
4255 std::string s = type.str();
4256 reg::Iterator it(s,*re,static_cast<int>(pos));
4258
4259 if (it!=end)
4260 {
4261 const auto &match = *it;
4262 size_t i = match.position();
4263 size_t l = match.length();
4264 size_t ts = i+l;
4265 size_t te = ts;
4266 size_t tl = 0;
4267
4268 while (ts<typeLen && type[static_cast<uint32_t>(ts)]==' ') { ts++; tl++; } // skip any whitespace
4269 if (ts<typeLen && type[static_cast<uint32_t>(ts)]=='<') // assume template instance
4270 {
4271 // locate end of template
4272 te=ts+1;
4273 int brCount=1;
4274 while (te<typeLen && brCount!=0)
4275 {
4276 if (type[static_cast<uint32_t>(te)]=='<')
4277 {
4278 if (te<typeLen-1 && type[static_cast<uint32_t>(te)+1]=='<') te++; else brCount++;
4279 }
4280 if (type[static_cast<uint32_t>(te)]=='>')
4281 {
4282 if (te<typeLen-1 && type[static_cast<uint32_t>(te)+1]=='>') te++; else brCount--;
4283 }
4284 te++;
4285 }
4286 }
4287 name = match.str();
4288 if (te>ts)
4289 {
4290 templSpec = QCString(type).mid(ts,te-ts);
4291 tl+=te-ts;
4292 pos=static_cast<int>(i+l+tl);
4293 }
4294 else // no template part
4295 {
4296 pos=static_cast<int>(i+l);
4297 }
4298 //printf("extractClassNameFromType([in] type=%s,[out] pos=%d,[out] name=%s,[out] templ=%s)=TRUE i=%d\n",
4299 // qPrint(type),pos,qPrint(name),qPrint(templSpec),i);
4300 AUTO_TRACE_EXIT("pos={} templSpec='{}' return={}",pos,templSpec,i);
4301 return static_cast<int>(i);
4302 }
4303 }
4304 pos = static_cast<int>(typeLen);
4305 //printf("extractClassNameFromType([in] type=%s,[out] pos=%d,[out] name=%s,[out] templ=%s)=FALSE\n",
4306 // qPrint(type),pos,qPrint(name),qPrint(templSpec));
4307 AUTO_TRACE_EXIT("not found");
4308 return -1;
4309}
bool startsWith(const char *s) const
Definition qcstring.h:507
QCString lower() const
Definition qcstring.h:249
void clear()
Definition qcstring.h:182

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

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

◆ extractDirection()

QCString extractDirection ( QCString & docs)

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

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

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

Definition at line 6208 of file util.cpp.

6209{
6210 std::string s = docs.str();
6211 static const reg::Ex re(R"(\‍[([ inout,]+)\‍])");
6212 reg::Iterator it(s,re);
6214 if (it!=end)
6215 {
6216 const auto &match = *it;
6217 size_t p = match.position();
6218 size_t l = match.length();
6219 if (p==0 && l>2)
6220 {
6221 // make dir the part inside [...] without separators
6222 std::string dir = match[1].str();
6223 // strip , and ' ' from dir
6224 dir.erase(std::remove_if(dir.begin(),dir.end(),
6225 [](const char c) { return c==' ' || c==','; }
6226 ),dir.end());
6227 unsigned char ioMask=0;
6228 size_t inIndex = dir.find( "in");
6229 if ( inIndex!=std::string::npos) { dir.erase( inIndex,2); ioMask|=(1<<0); }
6230 size_t outIndex = dir.find("out");
6231 if (outIndex!=std::string::npos) { dir.erase(outIndex,3); ioMask|=(1<<1); }
6232 if (dir.empty() && ioMask!=0) // only in and/or out attributes found
6233 {
6234 docs = s.substr(l); // strip attributes
6235 if (ioMask==((1<<0)|(1<<1))) return "[in,out]";
6236 else if (ioMask==(1<<0)) return "[in]";
6237 else if (ioMask==(1<<1)) return "[out]";
6238 }
6239 }
6240 }
6241 return "";
6242}

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

Referenced by inlineArgListToDoc().

◆ extractEndRawStringDelimiter()

QCString extractEndRawStringDelimiter ( const char * rawEnd)

Definition at line 6972 of file util.cpp.

6973{
6974 QCString text=rawEnd;
6975 return text.mid(1,text.length()-2); // text=)xyz" -> delimiter=xyz
6976}

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

3711{
3712 int i=0, p=0;
3713 QCString clName=scopeName;
3714 NamespaceDef *nd = nullptr;
3715 if (!clName.isEmpty() && (nd=getResolvedNamespace(clName)) && getClass(clName)==nullptr)
3716 { // the whole name is a namespace (and not a class)
3717 namespaceName=nd->name();
3718 className.clear();
3719 goto done;
3720 }
3721 p=static_cast<int>(clName.length())-2;
3722 while (p>=0 && (i=clName.findRev("::",p))!=-1)
3723 // see if the first part is a namespace (and not a class)
3724 {
3725 //printf("Trying %s\n",qPrint(clName.left(i)));
3726 if (i>0 && (nd=getResolvedNamespace(clName.left(i))) && getClass(clName.left(i))==nullptr)
3727 {
3728 //printf("found!\n");
3729 namespaceName=nd->name();
3730 className=clName.right(clName.length()-i-2);
3731 goto done;
3732 }
3733 p=i-2; // try a smaller piece of the scope
3734 }
3735 //printf("not found!\n");
3736
3737 // not found, so we just have to guess.
3738 className=scopeName;
3739 namespaceName.clear();
3740
3741done:
3742 if (className.isEmpty() && !namespaceName.isEmpty() && !allowEmptyClass)
3743 {
3744 // class and namespace with the same name, correct to return the class.
3745 className=namespaceName;
3746 namespaceName.clear();
3747 }
3748 //printf("extractNamespace '%s' => '%s|%s'\n",qPrint(scopeName),
3749 // qPrint(className),qPrint(namespaceName));
3750 if (className.endsWith("-p"))
3751 {
3752 className = className.left(className.length()-2);
3753 }
3754 return;
3755}
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 1494 of file util.cpp.

1495{
1496 if (name.isEmpty()) return QCString();
1497 bool fileOpened=false;
1498 if (name[0]=='-' && name[1]==0) // read from stdin
1499 {
1500 std::string contents;
1501 std::string line;
1502 while (getline(std::cin,line))
1503 {
1504 contents+=line+'\n';
1505 }
1506 return contents;
1507 }
1508 else // read from file
1509 {
1510 FileInfo fi(name.str());
1511 if (!fi.exists() || !fi.isFile())
1512 {
1513 err("file '{}' not found\n",name);
1514 return "";
1515 }
1516 std::string buf;
1517 fileOpened=readInputFile(name,buf,filter,isSourceCode);
1518 if (fileOpened)
1519 {
1520 addTerminalCharIfMissing(buf,'\n');
1521 return buf;
1522 }
1523 }
1524 if (!fileOpened)
1525 {
1526 err("cannot open file '{}' for reading\n",name);
1527 }
1528 return "";
1529}
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:5560

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(), runMermaidContent(), runPlantumlContent(), FileDefImpl::writeSourceBody(), HtmlGenerator::writeStyleInfo(), and writeXMLCodeBlock().

◆ fileVisibleInIndex()

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

Definition at line 6119 of file util.cpp.

6120{
6121 bool allExternals = Config_getBool(ALLEXTERNALS);
6122 bool isDocFile = fd->isDocumentationFile();
6123 genSourceFile = !isDocFile && fd->generateSourceFile();
6124 return ( ((allExternals && fd->isLinkable()) ||
6126 ) &&
6127 !isDocFile
6128 );
6129}
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().

◆ filterCRLF()

void filterCRLF ( std::string & contents)
static

takes the buf of the given length len and converts CR LF (DOS) or CR (MAC) line ending to LF (Unix). Returns the length of the converted content (i.e. the same as len (Unix, MAC) or smaller (DOS).

Definition at line 1355 of file util.cpp.

1356{
1357 size_t src = 0; // source index
1358 size_t dest = 0; // destination index
1359 size_t len = contents.length();
1360
1361 while (src<len)
1362 {
1363 char c = contents[src++]; // Remember the processed character.
1364 if (c == '\r') // CR to be solved (MAC, DOS)
1365 {
1366 c = '\n'; // each CR to LF
1367 if (src<len && contents[src] == '\n')
1368 {
1369 ++src; // skip LF just after CR (DOS)
1370 }
1371 }
1372 else if ( c == '\0' && src<len-1) // filter out internal \0 characters, as it will confuse the parser
1373 {
1374 c = ' '; // turn into a space
1375 }
1376 contents[dest++] = c; // copy the (modified) character to dest
1377 }
1378 contents.resize(dest);
1379}

Referenced by readInputFile().

◆ filterTitle()

QCString filterTitle ( const QCString & title)

Definition at line 5640 of file util.cpp.

5641{
5642 std::string tf;
5643 std::string t = title.str();
5644 static const reg::Ex re(R"(%[a-z_A-Z]+)");
5645 reg::Iterator it(t,re);
5647 size_t p = 0;
5648 for (; it!=end ; ++it)
5649 {
5650 const auto &match = *it;
5651 size_t i = match.position();
5652 size_t l = match.length();
5653 if (i>p) tf+=t.substr(p,i-p);
5654 tf+=match.str().substr(1); // skip %
5655 p=i+l;
5656 }
5657 tf+=t.substr(p);
5658 return tf;
5659}

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

Referenced by addToIndices(), createJavaScriptSearchIndex(), PerlModGenerator::generatePerlModForPage(), generateSqlite3ForPage(), generateXMLForPage(), generateXMLForRequirement(), generateXMLForRequirements(), parseCommentAsHtml(), SearchIndexExternal::setCurrentDoc(), HtmlGenerator::startFile(), 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 4997 of file util.cpp.

4998{
4999 static reg::Ex re(R"(\s*(<\a+>)\s*)");
5000 std::string s = sentence.str();
5001 reg::Iterator it(s,re);
5003 std::string result;
5004 bool found=false;
5005 size_t p=0;
5006 for ( ; it!=end ; ++it)
5007 {
5008 const auto match = *it;
5009 std::string part = match[1].str();
5010 if (part!=word)
5011 {
5012 size_t i = match.position();
5013 size_t l = match.length();
5014 result+=s.substr(p,i-p);
5015 result+=match.str();
5016 p=i+l;
5017 }
5018 else
5019 {
5020 found=true;
5021 size_t i = match[1].position();
5022 size_t l = match[1].length();
5023 result+=s.substr(p,i-p);
5024 p=i+l;
5025 }
5026 }
5027 result+=s.substr(p);
5028 sentence = QCString(result).simplifyWhiteSpace();
5029 return found;
5030}
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 2894 of file util.cpp.

2895{
2896 ambig=FALSE;
2897 if (n.isEmpty()) return nullptr;
2898
2899
2900 const int maxAddrSize = 20;
2901 char addr[maxAddrSize];
2902 qsnprintf(addr,maxAddrSize,"%p:",reinterpret_cast<const void*>(fnMap));
2903 QCString key = addr;
2904 key+=n;
2905
2906 std::lock_guard<std::mutex> lock(g_findFileDefMutex);
2907 FindFileCacheElem *cachedResult = g_findFileDefCache.find(key.str());
2908 //printf("key=%s cachedResult=%p\n",qPrint(key),cachedResult);
2909 if (cachedResult)
2910 {
2911 ambig = cachedResult->isAmbig;
2912 //printf("cached: fileDef=%p\n",cachedResult->fileDef);
2913 return cachedResult->fileDef;
2914 }
2915 else
2916 {
2917 cachedResult = g_findFileDefCache.insert(key.str(),FindFileCacheElem(nullptr,FALSE));
2918 }
2919
2920 QCString name=Dir::cleanDirPath(n.str());
2921 QCString path;
2922 if (name.isEmpty()) return nullptr;
2923 int slashPos=std::max(name.findRev('/'),name.findRev('\\'));
2924 if (slashPos!=-1)
2925 {
2926 path=removeLongPathMarker(name.left(slashPos+1));
2927 name=name.right(name.length()-slashPos-1);
2928 }
2929 if (name.isEmpty()) return nullptr;
2930 const FileName *fn = fnMap->find(name);
2931 if (fn)
2932 {
2933 //printf("fn->size()=%zu\n",fn->size());
2934 if (fn->size()==1)
2935 {
2936 const std::unique_ptr<FileDef> &fd = fn->front();
2937 bool isSamePath = Portable::fileSystemIsCaseSensitive() ?
2938 fd->getPath().right(path.length())==path :
2939 fd->getPath().right(path.length()).lower()==path.lower();
2940 if (path.isEmpty() || isSamePath)
2941 {
2942 cachedResult->fileDef = fd.get();
2943 return fd.get();
2944 }
2945 }
2946 else // file name alone is ambiguous
2947 {
2948 int count=0;
2949 FileDef *lastMatch=nullptr;
2950 QCString pathStripped = stripFromIncludePath(path);
2951 for (const auto &fd_p : *fn)
2952 {
2953 FileDef *fd = fd_p.get();
2954 QCString fdStripPath = stripFromIncludePath(fd->getPath());
2955 if (fdStripPath == pathStripped)
2956 {
2957 // if the stripped paths are equal, we have a perfect match
2958 count = 1;
2959 lastMatch=fd;
2960 break;
2961 }
2962 if (path.isEmpty() ||
2963 (!pathStripped.isEmpty() && fdStripPath.endsWith(pathStripped)) ||
2964 (pathStripped.isEmpty() && fdStripPath.isEmpty()))
2965 {
2966 count++;
2967 lastMatch=fd;
2968 }
2969 }
2970
2971 ambig=(count>1);
2972 cachedResult->isAmbig = ambig;
2973 cachedResult->fileDef = lastMatch;
2974 return lastMatch;
2975 }
2976 }
2977 else
2978 {
2979 //printf("not found!\n");
2980 }
2981 return nullptr;
2982}
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:470
#define qsnprintf
Definition qcstring.h:49
Cache element for the file name to FileDef mapping cache.
Definition util.cpp:2884
FileDef * fileDef
Definition util.cpp:2886
QCString stripFromIncludePath(const QCString &path)
Definition util.cpp:329
static Cache< std::string, FindFileCacheElem > g_findFileDefCache(5000)
static std::mutex g_findFileDefMutex
Definition util.cpp:2892
QCString removeLongPathMarker(QCString path)
Definition util.cpp:287

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

2987{
2988 ambig=false;
2989 QCString result;
2990 bool found=false;
2991 if (!found)
2992 {
2993 FileInfo fi(file.str());
2994 if (fi.exists())
2995 {
2996 result=fi.absFilePath();
2997 found=true;
2998 }
2999 }
3000 if (!found)
3001 {
3002 const StringVector &examplePathList = Config_getList(EXAMPLE_PATH);
3003 for (const auto &s : examplePathList)
3004 {
3005 std::string absFileName = s+(Portable::pathSeparator()+file).str();
3006 FileInfo fi(absFileName);
3007 if (fi.exists())
3008 {
3009 result=fi.absFilePath();
3010 found=true;
3011 }
3012 }
3013 }
3014
3015 if (!found)
3016 {
3017 // as a fallback we also look in the exampleNameDict
3019 if (fd && !ambig)
3020 {
3021 result=fd->absFilePath();
3022 }
3023 }
3024 return result;
3025}
static FileNameLinkedMap * exampleNameLinkedMap
Definition doxygen.h:102
virtual QCString absFilePath() const =0
QCString pathSeparator()
Definition portable.cpp:374
FileDef * findFileDef(const FileNameLinkedMap *fnMap, const QCString &n, bool &ambig)
Definition util.cpp:2894

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

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

References reg::search().

◆ findIndex() [2/2]

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

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

Definition at line 6684 of file util.cpp.

6685{
6686 auto it = std::find(sv.begin(),sv.end(),s);
6687 return it!=sv.end() ? static_cast<int>(it-sv.begin()) : -1;
6688}

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

◆ findModuleDef()

ModuleDef * findModuleDef ( const Definition * d)
static

Definition at line 4854 of file util.cpp.

4855{
4856 ModuleDef *mod = nullptr;
4858 {
4859 const FileDef *fd = toFileDef(d);
4860 if (fd) mod = fd->getModuleDef();
4861 }
4863 {
4864 const ClassDef *cd = toClassDef(d);
4865 if (cd)
4866 {
4867 const FileDef *fd = cd->getFileDef();
4868 if (fd) mod = fd->getModuleDef();
4869 }
4870 }
4872 {
4873 const ConceptDef *cd = toConceptDef(d);
4874 if (cd)
4875 {
4876 const FileDef *fd = cd->getFileDef();
4877 if (fd) mod = fd->getModuleDef();
4878 }
4879 }
4880 return mod;
4881}
A abstract class representing of a compound symbol.
Definition classdef.h:104
virtual FileDef * getFileDef() const =0
Returns the namespace this compound is in, or 0 if it has a global scope.
virtual const FileDef * getFileDef() const =0
virtual DefType definitionType() const =0
virtual ModuleDef * getModuleDef() const =0
ClassDef * toClassDef(Definition *d)
ConceptDef * toConceptDef(Definition *d)
FileDef * toFileDef(Definition *d)
Definition filedef.cpp:1966

References Definition::definitionType(), ClassDef::getFileDef(), ConceptDef::getFileDef(), FileDef::getModuleDef(), toClassDef(), toConceptDef(), toFileDef(), Definition::TypeClass, Definition::TypeConcept, and Definition::TypeFile.

Referenced by recursivelyAddGroupListToTitle().

◆ findParameterList()

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 at line 825 of file util.cpp.

826{
827 int pos=-1;
828 int templateDepth=0;
829 do
830 {
831 if (templateDepth > 0)
832 {
833 int nextOpenPos=name.findRev('>', pos);
834 int nextClosePos=name.findRev('<', pos);
835 if (nextOpenPos!=-1 && nextOpenPos>nextClosePos)
836 {
837 ++templateDepth;
838 pos=nextOpenPos-1;
839 }
840 else if (nextClosePos!=-1)
841 {
842 --templateDepth;
843 pos=nextClosePos-1;
844 }
845 else // more >'s than <'s, see bug701295
846 {
847 return -1;
848 }
849 }
850 else
851 {
852 int lastAnglePos=name.findRev('>', pos);
853 int bracePos=name.findRev('(', pos);
854 if (lastAnglePos!=-1 && lastAnglePos>bracePos)
855 {
856 ++templateDepth;
857 pos=lastAnglePos-1;
858 }
859 else
860 {
861 int bp = bracePos>0 ? name.findRev('(',bracePos-1) : -1;
862 // bp test is to allow foo(int(&)[10]), but we need to make an exception for operator()
863 return bp==-1 || (bp>=8 && name.mid(bp-8,10)=="operator()") ? bracePos : bp;
864 }
865 }
866 } while (pos!=-1);
867 return -1;
868}

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

Referenced by resolveRef().

◆ generateAnonymousAnchor()

QCString generateAnonymousAnchor ( const QCString & fileName,
int count )

Definition at line 3569 of file util.cpp.

3570{
3571 QCString fn = stripFromPath(fileName)+":"+QCString().setNum(count);
3572 const int sig_size=16;
3573 uint8_t md5_sig[sig_size];
3574 MD5Buffer(fn.data(),static_cast<unsigned int>(fn.length()),md5_sig);
3575 char result[sig_size*3+2];
3576 char *p = result;
3577 *p++='@';
3578 for (int i=0;i<sig_size;i++)
3579 {
3580 static const char oct[]="01234567";
3581 uint8_t byte = md5_sig[i];
3582 *p++=oct[(byte>>6)&7];
3583 *p++=oct[(byte>>3)&7];
3584 *p++=oct[(byte>>0)&7];
3585 }
3586 *p='\0';
3587 return result;
3588}
QCString & setNum(short n)
Definition qcstring.h:459
static QCString stripFromPath(const QCString &p, const StringVector &l)
Definition util.cpp:298

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

◆ generateFileRef()

void generateFileRef ( OutputList & ol,
const QCString & name,
const QCString & text )

Definition at line 2866 of file util.cpp.

2867{
2868 //printf("generateFileRef(%s,%s)\n",name,text);
2869 QCString linkText = text.isEmpty() ? text : name;
2870 //FileInfo *fi;
2871 bool ambig = false;
2873 if (fd && fd->isLinkable())
2874 // link to documented input file
2875 ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),QCString(),linkText);
2876 else
2877 ol.docify(linkText);
2878}
static FileNameLinkedMap * inputNameLinkedMap
Definition doxygen.h:104
void writeObjectLink(const QCString &ref, const QCString &file, const QCString &anchor, const QCString &name)
Definition outputlist.h:439
void docify(const QCString &s)
Definition outputlist.h:437

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

◆ generateMarker()

QCString generateMarker ( int id)

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

Definition at line 279 of file util.cpp.

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

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

◆ genericPatternMatch()

template<class PatternList, class PatternElem, typename PatternGet = QCString(*)(const PatternElem &)>
bool genericPatternMatch ( const FileInfo & fi,
const PatternList & patList,
PatternElem & elem,
PatternGet getter )

Definition at line 5664 of file util.cpp.

5668{
5669 bool caseSenseNames = getCaseSenseNames();
5670 bool found = FALSE;
5671
5672 if (!patList.empty())
5673 {
5674 std::string fn = fi.fileName();
5675 std::string fp = fi.filePath();
5676 std::string afp= fi.absFilePath();
5677
5678 for (const auto &li : patList)
5679 {
5680 std::string pattern = getter(li).str();
5681 if (!pattern.empty())
5682 {
5683 size_t i=pattern.find('=');
5684 if (i!=std::string::npos) pattern=pattern.substr(0,i); // strip of the extension specific filter name
5685
5686 if (!caseSenseNames)
5687 {
5688 pattern = QCString(pattern).lower().str();
5689 fn = QCString(fn).lower().str();
5690 fp = QCString(fp).lower().str();
5691 afp = QCString(afp).lower().str();
5692 }
5693 reg::Ex re(pattern,reg::Ex::Mode::Wildcard);
5694 found = re.isValid() && (reg::match(fn,re) ||
5695 (fn!=fp && reg::match(fp,re)) ||
5696 (fn!=afp && fp!=afp && reg::match(afp,re)));
5697 if (found)
5698 {
5699 elem = li;
5700 break;
5701 }
5702 //printf("Matching '%s' against pattern '%s' found=%d\n",
5703 // qPrint(fi->fileName()),qPrint(pattern),found);
5704 }
5705 }
5706 }
5707 return found;
5708}
std::string fileName() const
Definition fileinfo.cpp:118
std::string filePath() const
Definition fileinfo.cpp:91
std::string absFilePath() const
Definition fileinfo.cpp:101
@ Wildcard
simple globbing pattern.
Definition regex.h:45

References FileInfo::absFilePath(), FALSE, FileInfo::fileName(), FileInfo::filePath(), getCaseSenseNames(), reg::Ex::isValid(), QCString::lower(), reg::match(), QCString::str(), and reg::Ex::Wildcard.

Referenced by getEncoding(), and patternMatch().

◆ getCanonicalTemplateSpec()

QCString getCanonicalTemplateSpec ( const Definition * d,
const FileDef * fs,
const QCString & spec,
SrcLangExt lang )
static

Definition at line 1639 of file util.cpp.

1640{
1641 AUTO_TRACE("spec={}",spec);
1642 QCString templSpec = spec.stripWhiteSpace();
1643 // this part had been commented out before... but it is needed to match for instance
1644 // std::list<std::string> against list<string> so it is now back again!
1645 if (!templSpec.isEmpty() && templSpec.at(0) == '<')
1646 {
1647 templSpec = "< " + extractCanonicalType(d,fs,templSpec.right(templSpec.length()-1).stripWhiteSpace(),lang,true);
1648 }
1649 QCString resolvedType = lang==SrcLangExt::Java ? templSpec : resolveTypeDef(d,templSpec);
1650 if (!resolvedType.isEmpty()) // not known as a typedef either
1651 {
1652 templSpec = resolvedType;
1653 }
1654 //printf("getCanonicalTemplateSpec(%s)=%s\n",qPrint(spec),qPrint(templSpec));
1655 AUTO_TRACE_EXIT("result={}",templSpec);
1656 return templSpec;
1657}
QCString resolveTypeDef(const Definition *context, const QCString &qualifiedName, const Definition **typedefContext)
Definition util.cpp:373

References QCString::at(), AUTO_TRACE, AUTO_TRACE_EXIT, extractCanonicalType(), QCString::isEmpty(), QCString::length(), resolveTypeDef(), QCString::right(), and QCString::stripWhiteSpace().

Referenced by getCanonicalTypeForIdentifier().

◆ getCanonicalTypeForIdentifier()

QCString getCanonicalTypeForIdentifier ( const Definition * d,
const FileDef * fs,
const QCString & word,
SrcLangExt lang,
QCString * tSpec,
int count = 0 )
static

Definition at line 1660 of file util.cpp.

1663{
1664 if (count>10) return word; // oops recursion
1665
1666 QCString symName,result,templSpec,tmpName;
1667 if (tSpec && !tSpec->isEmpty())
1668 templSpec = stripDeclKeywords(getCanonicalTemplateSpec(d,fs,*tSpec,lang));
1669
1670 AUTO_TRACE("d='{}' fs='{}' word='{}' templSpec='{}'",d?d->name():"",fs?fs->name():"",word,templSpec);
1671
1672 if (word.findRev("::")!=-1 && !(tmpName=stripScope(word)).isEmpty())
1673 {
1674 symName=tmpName; // name without scope
1675 }
1676 else
1677 {
1678 symName=word;
1679 }
1680
1681 // lookup class / class template instance
1682 SymbolResolver resolver(fs);
1683 const ClassDef *cd = resolver.resolveClass(d,word+templSpec,true,true);
1684 const MemberDef *mType = resolver.getTypedef();
1685 QCString ts = resolver.getTemplateSpec();
1686 QCString resolvedType = resolver.getResolvedType();
1687
1688 bool isTemplInst = cd && !templSpec.isEmpty();
1689 if (!cd && !templSpec.isEmpty())
1690 {
1691 // class template specialization not known, look up class template
1692 cd = resolver.resolveClass(d,word,true,true);
1693 mType = resolver.getTypedef();
1694 ts = resolver.getTemplateSpec();
1695 resolvedType = resolver.getResolvedType();
1696 }
1697 if (cd && cd->isUsedOnly()) cd=nullptr; // ignore types introduced by usage relations
1698
1699 AUTO_TRACE_ADD("cd='{}' mType='{}' ts='{}' resolvedType='{}'",
1700 cd?cd->name():"",mType?mType->name():"",ts,resolvedType);
1701 //printf("cd=%p mtype=%p\n",cd,mType);
1702 //printf(" getCanonicalTypeForIdentifier: symbol=%s word=%s cd=%s d=%s fs=%s cd->isTemplate=%d\n",
1703 // qPrint(symName),
1704 // qPrint(word),
1705 // cd ? qPrint(cd->name()) : "<none>",
1706 // d ? qPrint( d->name()) : "<none>",
1707 // fs ? qPrint(fs->name()) : "<none>",
1708 // cd ? cd->isTemplate():-1
1709 // );
1710
1711 //printf(" >>>> word '%s' => '%s' templSpec=%s ts=%s tSpec=%s isTemplate=%d resolvedType=%s\n",
1712 // qPrint((word+templSpec)),
1713 // cd ? qPrint(cd->qualifiedName()) : "<none>",
1714 // qPrint(templSpec), qPrint(ts),
1715 // tSpec ? qPrint(tSpec) : "<null>",
1716 // cd ? cd->isTemplate():FALSE,
1717 // qPrint(resolvedType));
1718
1719 //printf(" mtype=%s\n",mType ? qPrint(mType->name()) : "<none>");
1720
1721 if (cd) // resolves to a known class type
1722 {
1723 if (cd==d && tSpec) *tSpec="";
1724
1725 if (mType && mType->isTypedef()) // but via a typedef
1726 {
1727 result = resolvedType+ts; // the +ts was added for bug 685125
1728 }
1729 else
1730 {
1731 if (isTemplInst)
1732 {
1733 // spec is already part of class type
1734 templSpec="";
1735 if (tSpec) *tSpec="";
1736 }
1737 else if (!ts.isEmpty() && templSpec.isEmpty())
1738 {
1739 // use formal template args for spec
1740 templSpec = stripDeclKeywords(getCanonicalTemplateSpec(d,fs,ts,lang));
1741 }
1742
1743 result = removeRedundantWhiteSpace(cd->qualifiedName() + templSpec);
1744
1745 if (cd->isTemplate() && tSpec) //
1746 {
1747 if (!templSpec.isEmpty()) // specific instance
1748 {
1749 result=cd->name()+templSpec;
1750 }
1751 else // use template type
1752 {
1754 }
1755 // template class, so remove the template part (it is part of the class name)
1756 *tSpec="";
1757 }
1758 else if (ts.isEmpty() && !templSpec.isEmpty() && cd && !cd->isTemplate() && tSpec)
1759 {
1760 // obscure case, where a class is used as a template, but doxygen think it is
1761 // not (could happen when loading the class from a tag file).
1762 *tSpec="";
1763 }
1764 }
1765 }
1766 else if (mType && mType->isEnumerate()) // an enum
1767 {
1768 result = mType->qualifiedName();
1769 }
1770 else if (mType && mType->isTypedef()) // a typedef
1771 {
1772 //result = mType->qualifiedName(); // changed after 1.7.2
1773 //result = mType->typeString();
1774 //printf("word=%s typeString=%s\n",qPrint(word),mType->typeString());
1775 if (word!=mType->typeString())
1776 {
1777 QCString type = mType->typeString();
1778 if (type.startsWith("typename "))
1779 {
1780 type.stripPrefix("typename ");
1782 }
1783 if (!type.isEmpty()) // see issue #11065
1784 {
1785 result = getCanonicalTypeForIdentifier(d,fs,type,mType->getLanguage(),tSpec,count+1);
1786 }
1787 else
1788 {
1789 result = word;
1790 }
1791 }
1792 else
1793 {
1794 result = mType->typeString();
1795 }
1796 }
1797 else // fallback
1798 {
1799 resolvedType = lang==SrcLangExt::Java ? word : resolveTypeDef(d,word);
1800 AUTO_TRACE_ADD("fallback resolvedType='{}'",resolvedType);
1801 if (resolvedType.isEmpty()) // not known as a typedef either
1802 {
1803 result = word;
1804 }
1805 else
1806 {
1807 result = resolvedType;
1808 }
1809 }
1810 AUTO_TRACE_EXIT("result='{}'",result);
1811 return result;
1812}
virtual bool isTemplate() const =0
Returns TRUE if this class is a template.
virtual QCString qualifiedNameWithTemplateParameters(const ArgumentLists *actualParams=nullptr, uint32_t *actualParamIndex=nullptr) const =0
virtual bool isUsedOnly() const =0
virtual SrcLangExt getLanguage() const =0
Returns the programming language this definition was written in.
virtual QCString qualifiedName() const =0
virtual QCString typeString() const =0
virtual bool isEnumerate() const =0
#define AUTO_TRACE_ADD(...)
Definition docnode.cpp:49
static QCString stripDeclKeywords(const QCString &s)
Definition util.cpp:1623
QCString stripScope(const QCString &name)
Definition util.cpp:3790
static QCString getCanonicalTemplateSpec(const Definition *d, const FileDef *fs, const QCString &spec, SrcLangExt lang)
Definition util.cpp:1639
QCString stripTemplateSpecifiersFromScope(const QCString &fullName, bool parentOnly, QCString *pLastScopeStripped, QCString scopeName, bool allowArtificial)
Definition util.cpp:4538

References AUTO_TRACE, AUTO_TRACE_ADD, AUTO_TRACE_EXIT, FALSE, QCString::findRev(), getCanonicalTemplateSpec(), getCanonicalTypeForIdentifier(), Definition::getLanguage(), SymbolResolver::getResolvedType(), SymbolResolver::getTemplateSpec(), SymbolResolver::getTypedef(), QCString::isEmpty(), MemberDef::isEnumerate(), ClassDef::isTemplate(), MemberDef::isTypedef(), ClassDef::isUsedOnly(), Definition::name(), Definition::qualifiedName(), ClassDef::qualifiedNameWithTemplateParameters(), removeRedundantWhiteSpace(), SymbolResolver::resolveClass(), resolveTypeDef(), QCString::startsWith(), stripDeclKeywords(), QCString::stripPrefix(), stripScope(), stripTemplateSpecifiersFromScope(), and MemberDef::typeString().

Referenced by extractCanonicalType(), and getCanonicalTypeForIdentifier().

◆ getCaseSenseNames()

bool getCaseSenseNames ( )

Definition at line 3331 of file util.cpp.

3332{
3333 auto caseSenseNames = Config_getEnum(CASE_SENSE_NAMES);
3334
3335 if (caseSenseNames == CASE_SENSE_NAMES_t::YES) return true;
3336 else if (caseSenseNames == CASE_SENSE_NAMES_t::NO) return false;
3338}
#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 2298 of file util.cpp.

2299{
2300 GetDefResult result;
2301 if (input.memberName.isEmpty()) return result;
2302 AUTO_TRACE("scopeName={},memberName={},forceEmptyScope={}",
2303 input.scopeName,input.memberName,input.forceEmptyScope);
2304
2305 //printf("@@ --- getDefsNew(%s,%s)-----------\n",qPrint(scName),qPrint(mbName));
2306 const Definition *scope = Doxygen::globalScope;
2307 SymbolResolver resolver;
2308 if (input.currentFile) resolver.setFileScope(input.currentFile);
2309 if (!input.scopeName.isEmpty() && !input.forceEmptyScope)
2310 {
2311 scope = resolver.resolveSymbol(scope,input.scopeName);
2312 }
2313 if (scope==Doxygen::globalScope)
2314 {
2315 scope = input.currentFile;
2316 }
2317 //printf("@@ -> found scope scope=%s member=%s out=%s\n",qPrint(input.scopeName),qPrint(input.memberName),qPrint(scope?scope->name():""));
2318 //
2319 const Definition *symbol = resolver.resolveSymbol(scope,input.memberName,input.args,input.checkCV,input.insideCode,true);
2320 //printf("@@ -> found symbol in=%s out=%s\n",qPrint(input.memberName),qPrint(symbol?symbol->qualifiedName():QCString()));
2321 if (symbol && symbol->definitionType()==Definition::TypeMember)
2322 {
2323 result.md = toMemberDef(symbol);
2324 result.cd = result.md->getClassDef();
2325 if (result.cd==nullptr) result.nd = result.md->getNamespaceDef();
2326 if (result.cd==nullptr && result.nd==nullptr) result.fd = result.md->getFileDef();
2327 result.gd = result.md->getGroupDef();
2328 result.found = true;
2329 }
2330 else if (symbol && symbol->definitionType()==Definition::TypeClass)
2331 {
2332 result.cd = toClassDef(symbol);
2333 result.found = true;
2334 }
2335 else if (symbol && symbol->definitionType()==Definition::TypeNamespace)
2336 {
2337 result.nd = toNamespaceDef(symbol);
2338 result.found = true;
2339 }
2340 else if (symbol && symbol->definitionType()==Definition::TypeConcept)
2341 {
2342 result.cnd = toConceptDef(symbol);
2343 result.found = true;
2344 }
2345 else if (symbol && symbol->definitionType()==Definition::TypeModule)
2346 {
2347 result.modd = toModuleDef(symbol);
2348 result.found = true;
2349 }
2350 return result;
2351}
The common base class of all entity definitions found in the sources.
Definition definition.h:77
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.
MemberDef * toMemberDef(Definition *d)
ModuleDef * toModuleDef(Definition *d)
NamespaceDef * toNamespaceDef(Definition *d)
bool forceEmptyScope
Definition util.h:164
const FileDef * currentFile
Definition util.h:165
QCString scopeName
Definition util.h:161
bool insideCode
Definition util.h:167
bool checkCV
Definition util.h:166
QCString args
Definition util.h:163
QCString memberName
Definition util.h:162
const MemberDef * md
Definition util.h:173
const ConceptDef * cnd
Definition util.h:178
const FileDef * fd
Definition util.h:175
const ModuleDef * modd
Definition util.h:179
const GroupDef * gd
Definition util.h:177
bool found
Definition util.h:172
const ClassDef * cd
Definition util.h:174
const NamespaceDef * nd
Definition util.h:176

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

6320{
6321 QCString imgExt = Config_getEnumAsString(DOT_IMAGE_FORMAT);
6322 int i= imgExt.find(':'); // strip renderer part when using e.g. 'png:cairo:gd' as format
6323 return i==-1 ? imgExt : imgExt.left(i);
6324}
#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()(), 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(), HtmlDocVisitor::writeMermaidFile(), HtmlDocVisitor::writeMscFile(), and HtmlDocVisitor::writePlantUMLFile().

◆ getEncoding()

QCString getEncoding ( const FileInfo & fi)

Definition at line 5721 of file util.cpp.

5722{
5723 InputFileEncoding elem;
5724 auto getter = [](const InputFileEncoding &e) -> QCString { return e.pattern; };
5725 if (genericPatternMatch(fi,Doxygen::inputFileEncodingList,elem,getter)) // check for file specific encoding
5726 {
5727 return elem.encoding;
5728 }
5729 else // fall back to default encoding
5730 {
5731 return Config_getString(INPUT_ENCODING);
5732 }
5733}
static InputFileEncodingList inputFileEncodingList
Definition doxygen.h:138
#define Config_getString(name)
Definition config.h:32
QCString encoding
Definition doxygen.h:70
bool genericPatternMatch(const FileInfo &fi, const PatternList &patList, PatternElem &elem, PatternGet getter)
Definition util.cpp:5664

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

1423{
1424 // sanity check
1425 if (name.isEmpty()) return "";
1426
1427 const StringVector& filterSrcList = Config_getList(FILTER_SOURCE_PATTERNS);
1428 const StringVector& filterList = Config_getList(FILTER_PATTERNS);
1429
1430 QCString filterName;
1431 bool found=FALSE;
1432 if (isSourceCode && !filterSrcList.empty())
1433 { // first look for source filter pattern list
1434 filterName = getFilterFromList(name,filterSrcList,found);
1435 }
1436 if (!found && filterName.isEmpty())
1437 { // then look for filter pattern list
1438 filterName = getFilterFromList(name,filterList,found);
1439 }
1440 if (!found)
1441 { // then use the generic input filter
1442 return Config_getString(INPUT_FILTER);
1443 }
1444 else
1445 {
1446 /* remove surrounding double quotes */
1447 if (filterName.length()>=2 && filterName[0]=='"' && filterName[static_cast<int>(filterName.length())-1]=='"')
1448 {
1449 filterName = filterName.mid(1,filterName.length()-2);
1450 }
1451 return filterName;
1452 }
1453}
static QCString getFilterFromList(const QCString &name, const StringVector &filterList, bool &found)
Definition util.cpp:1381

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

◆ getFilterFromList()

QCString getFilterFromList ( const QCString & name,
const StringVector & filterList,
bool & found )
static

Definition at line 1381 of file util.cpp.

1382{
1383 found=FALSE;
1384 // compare the file name to the filter pattern list
1385 for (const auto &filterStr : filterList)
1386 {
1387 QCString fs = filterStr;
1388 int i_equals=fs.find('=');
1389 if (i_equals!=-1)
1390 {
1391 QCString filterPattern = fs.left(i_equals);
1392 QCString input = name;
1394 {
1395 filterPattern = filterPattern.lower();
1396 input = input.lower();
1397 }
1398 reg::Ex re(filterPattern.str(),reg::Ex::Mode::Wildcard);
1399 if (re.isValid() && reg::match(input.str(),re))
1400 {
1401 // found a match!
1402 QCString filterName = fs.mid(i_equals+1);
1403 if (filterName.find(' ')!=-1)
1404 { // add quotes if the name has spaces
1405 filterName="\""+filterName+"\"";
1406 }
1407 found=TRUE;
1408 return filterName;
1409 }
1410 }
1411 }
1412
1413 // no match
1414 return "";
1415}

References FALSE, Portable::fileSystemIsCaseSensitive(), QCString::find(), reg::Ex::isValid(), QCString::left(), QCString::lower(), reg::match(), QCString::mid(), QCString::str(), TRUE, and reg::Ex::Wildcard.

Referenced by getFileFilter().

◆ getLanguageFromCodeLang()

SrcLangExt getLanguageFromCodeLang ( QCString & fileName)

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

Definition at line 5239 of file util.cpp.

5240{
5241 // try the extension
5242 auto lang = getLanguageFromFileName(fileName, SrcLangExt::Unknown);
5243 if (lang == SrcLangExt::Unknown)
5244 {
5245 // try the language names
5246 QCString langName = fileName.lower();
5247 if (langName.at(0)=='.') langName = langName.mid(1);
5248 auto it = std::find_if(g_lang2extMap.begin(),g_lang2extMap.end(),
5249 [&langName](const auto &info) { return info.langName==langName; });
5250 if (it != g_lang2extMap.end())
5251 {
5252 lang = it->parserId;
5253 fileName = it->defExt;
5254 }
5255 else // default to C++
5256 {
5257 return SrcLangExt::Cpp;
5258 }
5259 }
5260 return lang;
5261}
SrcLangExt getLanguageFromFileName(const QCString &fileName, SrcLangExt defLang)
Definition util.cpp:5221
static std::vector< Lang2ExtMap > g_lang2extMap
Definition util.cpp:5092

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 )

Definition at line 5221 of file util.cpp.

5222{
5223 FileInfo fi(fileName.str());
5224 // we need only the part after the last ".", newer implementations of FileInfo have 'suffix()' for this.
5225 QCString extName = QCString(fi.extension(FALSE)).lower();
5226 if (extName.isEmpty()) extName=".no_extension";
5227 if (extName.at(0)!='.') extName.prepend(".");
5228 auto it = g_extLookup.find(extName.str());
5229 if (it!=g_extLookup.end()) // listed extension
5230 {
5231 //printf("getLanguageFromFileName(%s)=%x\n",qPrint(fi.extension()),*pVal);
5232 return it->second;
5233 }
5234 //printf("getLanguageFromFileName(%s) not found!\n",qPrint(fileName));
5235 return defLang; // not listed => assume C-ish language.
5236}
static std::unordered_map< std::string, SrcLangExt > g_extLookup
Definition util.cpp:5082

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 )

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

Definition at line 5927 of file util.cpp.

5928{
5929 if (lang==SrcLangExt::Java || lang==SrcLangExt::CSharp || lang==SrcLangExt::VHDL || lang==SrcLangExt::Python)
5930 {
5931 return ".";
5932 }
5933 else if (lang==SrcLangExt::PHP && !classScope)
5934 {
5935 return "\\";
5936 }
5937 else
5938 {
5939 return "::";
5940 }
5941}

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

◆ getMemberFromSymbol()

MemberDef * getMemberFromSymbol ( const Definition * scope,
const FileDef * fileScope,
const QCString & n )
static

Definition at line 5273 of file util.cpp.

5275{
5276 if (scope==nullptr ||
5279 )
5280 )
5281 {
5283 }
5284
5285 QCString name = n;
5286 if (name.isEmpty())
5287 return nullptr; // no name was given
5288
5289 auto &range = Doxygen::symbolMap->find(name);
5290 if (range.empty())
5291 return nullptr; // could not find any matching symbols
5292
5293 // mostly copied from getResolvedClassRec()
5294 QCString explicitScopePart;
5295 int qualifierIndex = computeQualifiedIndex(name);
5296 if (qualifierIndex!=-1)
5297 {
5298 explicitScopePart = name.left(qualifierIndex);
5299 replaceNamespaceAliases(explicitScopePart);
5300 name = name.mid(qualifierIndex+2);
5301 }
5302 //printf("explicitScopePart=%s\n",qPrint(explicitScopePart));
5303
5304 int minDistance = 10000;
5305 MemberDef *bestMatch = nullptr;
5306
5307 for (Definition *d : range)
5308 {
5309 if (d->definitionType()==Definition::TypeMember)
5310 {
5311 SymbolResolver resolver(fileScope);
5312 int distance = resolver.isAccessibleFromWithExpScope(scope,d,explicitScopePart);
5313 if (distance!=-1 && distance<minDistance)
5314 {
5315 minDistance = distance;
5316 bestMatch = toMemberDef(d);
5317 //printf("new best match %s distance=%d\n",qPrint(bestMatch->qualifiedName()),distance);
5318 }
5319 }
5320 }
5321 return bestMatch;
5322}
static SymbolMap< Definition > * symbolMap
Definition doxygen.h:125
void replaceNamespaceAliases(QCString &name)
int computeQualifiedIndex(const QCString &name)
Return the index of the last :: in the string name that is still before the first <.
Definition util.cpp:6854

References computeQualifiedIndex(), Definition::definitionType(), Doxygen::globalScope, SymbolResolver::isAccessibleFromWithExpScope(), QCString::isEmpty(), QCString::left(), QCString::mid(), replaceNamespaceAliases(), Doxygen::symbolMap, toMemberDef(), Definition::TypeClass, Definition::TypeMember, and Definition::TypeNamespace.

Referenced by checkIfTypedef().

◆ getOverloadDocs()

QCString getOverloadDocs ( )

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

Definition at line 4100 of file util.cpp.

4101{
4102 return theTranslator->trOverloadText();
4103 //"This is an overloaded member function, "
4104 // "provided for convenience. It differs from the above "
4105 // "function only in what argument(s) it accepts.";
4106}
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 3242 of file util.cpp.

3243{
3244 if (name.isEmpty()) return 0;
3245 const StringVector &sl = Config_getList(IGNORE_PREFIX);
3246 for (const auto &s : sl)
3247 {
3248 const char *ps=s.c_str();
3249 const char *pd=name.data();
3250 int i=0;
3251 while (*ps!=0 && *pd!=0 && *ps==*pd)
3252 {
3253 ps++;
3254 pd++;
3255 i++;
3256 }
3257 if (*ps==0 && *pd!=0)
3258 {
3259 return i;
3260 }
3261 }
3262 return 0;
3263}

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

6842{
6843 QCString projectCookie = Config_getString(HTML_PROJECT_COOKIE);
6844 if (projectCookie.isEmpty()) return QCString();
6845 uint8_t md5_sig[16];
6846 char sigStr[34];
6847 MD5Buffer(projectCookie.data(),static_cast<unsigned int>(projectCookie.length()),md5_sig);
6848 MD5SigToString(md5_sig,sigStr);
6849 sigStr[32]='_'; sigStr[33]=0;
6850 return sigStr;
6851}

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

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

◆ getScopeDefs()

bool getScopeDefs ( const QCString & docScope,
const QCString & scope,
ClassDef *& cd,
ConceptDef *& cnd,
NamespaceDef *& nd,
ModuleDef *& modd )
static

Searches for a scope definition given its name as a string via parameter scope.

The parameter docScope is a string representing the name of the scope in which the scope string was found.

The function returns TRUE if the scope is known and documented or FALSE if it is not. If TRUE is returned exactly one of the parameter cd, nd will be non-zero:

  • if cd is non zero, the scope was a class pointed to by cd.
  • if nd is non zero, the scope was a namespace pointed to by nd.

Definition at line 2368 of file util.cpp.

2370{
2371 cd=nullptr;
2372 cnd=nullptr;
2373 nd=nullptr;
2374 modd=nullptr;
2375
2376 QCString scopeName=scope;
2377 //printf("getScopeDefs: docScope='%s' scope='%s'\n",qPrint(docScope),qPrint(scope));
2378 if (scopeName.isEmpty()) return FALSE;
2379
2380 bool explicitGlobalScope=FALSE;
2381 if (scopeName.at(0)==':' && scopeName.at(1)==':')
2382 {
2383 scopeName=scopeName.right(scopeName.length()-2);
2384 explicitGlobalScope=TRUE;
2385 }
2386 if (scopeName.isEmpty())
2387 {
2388 return FALSE;
2389 }
2390
2391 QCString docScopeName=docScope;
2392 int scopeOffset=explicitGlobalScope ? 0 : static_cast<int>(docScopeName.length());
2393
2394 do // for each possible docScope (from largest to and including empty)
2395 {
2396 QCString fullName=scopeName;
2397 if (scopeOffset>0) fullName.prepend(docScopeName.left(scopeOffset)+"::");
2398
2399 if (((cd=getClass(fullName)) || // normal class
2400 (cd=getClass(fullName+"-p")) // ObjC protocol
2401 ) && cd->isLinkable())
2402 {
2403 return TRUE; // class link written => quit
2404 }
2405 else if ((nd=Doxygen::namespaceLinkedMap->find(fullName)) && nd->isLinkable())
2406 {
2407 return TRUE; // namespace link written => quit
2408 }
2409 else if ((cnd=Doxygen::conceptLinkedMap->find(fullName)) && cnd->isLinkable())
2410 {
2411 return TRUE; // concept link written => quit
2412 }
2413 else if ((modd=ModuleManager::instance().modules().find(fullName)) && modd->isLinkable())
2414 {
2415 return TRUE; // module link written => quit
2416 }
2417 if (scopeOffset==0)
2418 {
2419 scopeOffset=-1;
2420 }
2421 else if ((scopeOffset=docScopeName.findRev("::",scopeOffset-1))==-1)
2422 {
2423 scopeOffset=0;
2424 }
2425 } while (scopeOffset>=0);
2426
2427 return FALSE;
2428}
static NamespaceLinkedMap * namespaceLinkedMap
Definition doxygen.h:115
static ConceptLinkedMap * conceptLinkedMap
Definition doxygen.h:97
static ModuleManager & instance()

References QCString::at(), Doxygen::conceptLinkedMap, FALSE, QCString::findRev(), getClass(), ModuleManager::instance(), QCString::isEmpty(), Definition::isLinkable(), QCString::left(), QCString::length(), Doxygen::namespaceLinkedMap, QCString::prepend(), QCString::right(), and TRUE.

Referenced by resolveRef().

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

4651{
4652 int sl=static_cast<int>(s.length());
4653 int sp=p;
4654 int count=0;
4655 bool done=false;
4656 if (sp>=sl) return -1;
4657 while (sp<sl)
4658 {
4659 char c=s.at(sp);
4660 if (c==':')
4661 {
4662 sp++;
4663 p++;
4664 }
4665 else
4666 {
4667 break;
4668 }
4669 }
4670 while (sp<sl)
4671 {
4672 char c=s.at(sp);
4673 switch (c)
4674 {
4675 case ':': // found next part
4676 goto found;
4677 case '<': // skip template specifier
4678 count=1;sp++;
4679 done=false;
4680 while (sp<sl && !done)
4681 {
4682 // TODO: deal with << and >> operators!
4683 c=s.at(sp++);
4684 switch(c)
4685 {
4686 case '<': count++; break;
4687 case '>': count--; if (count==0) done=true; break;
4688 default: break;
4689 }
4690 }
4691 break;
4692 default:
4693 sp++;
4694 break;
4695 }
4696 }
4697found:
4698 *l=sp-p;
4699 //printf("getScopeFragment(%s,%d)=%s\n",qPrint(s),p,qPrint(s.mid(p,*l)));
4700 return p;
4701}

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

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

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

5149{
5150 // NOTE: when adding an extension, also add the extension in config.xml
5151 // extension parser id
5152 updateLanguageMapping(".dox", "c");
5153 updateLanguageMapping(".txt", "c"); // see bug 760836
5154 updateLanguageMapping(".doc", "c");
5155 updateLanguageMapping(".c", "c");
5156 updateLanguageMapping(".C", "c");
5157 updateLanguageMapping(".cc", "c");
5158 updateLanguageMapping(".CC", "c");
5159 updateLanguageMapping(".cxx", "c");
5160 updateLanguageMapping(".cpp", "c");
5161 updateLanguageMapping(".c++", "c");
5162 updateLanguageMapping(".cxxm", "c"); // C++20 modules
5163 updateLanguageMapping(".cppm", "c"); // C++20 modules
5164 updateLanguageMapping(".ccm", "c"); // C++20 modules
5165 updateLanguageMapping(".c++m", "c"); // C++20 modules
5166 updateLanguageMapping(".ii", "c");
5167 updateLanguageMapping(".ixx", "c");
5168 updateLanguageMapping(".ipp", "c");
5169 updateLanguageMapping(".i++", "c");
5170 updateLanguageMapping(".inl", "c");
5171 updateLanguageMapping(".h", "c");
5172 updateLanguageMapping(".H", "c");
5173 updateLanguageMapping(".hh", "c");
5174 updateLanguageMapping(".HH", "c");
5175 updateLanguageMapping(".hxx", "c");
5176 updateLanguageMapping(".hpp", "c");
5177 updateLanguageMapping(".h++", "c");
5178 updateLanguageMapping(".idl", "idl");
5179 updateLanguageMapping(".ddl", "idl");
5180 updateLanguageMapping(".odl", "idl");
5181 updateLanguageMapping(".java", "java");
5182 //updateLanguageMapping(".as", "javascript"); // not officially supported
5183 //updateLanguageMapping(".js", "javascript"); // not officially supported
5184 updateLanguageMapping(".cs", "csharp");
5185 updateLanguageMapping(".d", "d");
5186 updateLanguageMapping(".php", "php");
5187 updateLanguageMapping(".php4", "php");
5188 updateLanguageMapping(".php5", "php");
5189 updateLanguageMapping(".inc", "php");
5190 updateLanguageMapping(".phtml", "php");
5191 updateLanguageMapping(".m", "objective-c");
5192 updateLanguageMapping(".M", "objective-c");
5193 updateLanguageMapping(".mm", "c"); // see bug746361
5194 updateLanguageMapping(".py", "python");
5195 updateLanguageMapping(".pyw", "python");
5196 updateLanguageMapping(".f", "fortran");
5197 updateLanguageMapping(".for", "fortran");
5198 updateLanguageMapping(".f90", "fortran");
5199 updateLanguageMapping(".f95", "fortran");
5200 updateLanguageMapping(".f03", "fortran");
5201 updateLanguageMapping(".f08", "fortran");
5202 updateLanguageMapping(".f18", "fortran");
5203 updateLanguageMapping(".vhd", "vhdl");
5204 updateLanguageMapping(".vhdl", "vhdl");
5205 updateLanguageMapping(".ucf", "vhdl");
5206 updateLanguageMapping(".qsf", "vhdl");
5207 updateLanguageMapping(".md", "md");
5208 updateLanguageMapping(".markdown", "md");
5209 updateLanguageMapping(".ice", "slice");
5210 updateLanguageMapping(".l", "lex");
5211 updateLanguageMapping(".doxygen_lex_c", "c"); // this is a placeholder so we can map initializations
5212 // in the lex scanning to cpp
5213}

References updateLanguageMapping().

Referenced by initDoxygen().

◆ inlineArgListToDoc()

QCString inlineArgListToDoc ( const ArgumentList & al)

Definition at line 1204 of file util.cpp.

1205{
1206 QCString paramDocs;
1207 if (al.hasDocumentation(true))
1208 {
1209 for (const Argument &a : al)
1210 {
1211 if (a.hasDocumentation(true))
1212 {
1213 QCString docsWithoutDir = a.docs;
1214 QCString direction = extractDirection(docsWithoutDir);
1215 QCString name = a.name;
1216 if (name.isEmpty())
1217 {
1218 name = "-";
1219 }
1220 paramDocs+=" \\ilinebr @param"+direction+" "+name+" "+docsWithoutDir;
1221 }
1222 }
1223 }
1224 return paramDocs;
1225}
bool hasDocumentation(bool allowEmptyNames=false) const
Definition arguments.cpp:22
QCString extractDirection(QCString &docs)
Strip the direction part from docs and return it as a string in canonical form The input docs string ...
Definition util.cpp:6208

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

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

◆ inlineTemplateArgListToDoc()

QCString inlineTemplateArgListToDoc ( const ArgumentList & al)

Definition at line 1227 of file util.cpp.

1228{
1229 QCString paramDocs;
1230 if (al.hasTemplateDocumentation())
1231 {
1232 for (const Argument &a : al)
1233 {
1234 if (!a.docs.isEmpty())
1235 {
1236 if (!a.name.isEmpty())
1237 {
1238 paramDocs+=" \\ilinebr @tparam "+a.name+" "+a.docs;
1239 }
1240 else if (!a.type.isEmpty())
1241 {
1242 QCString type = a.type;
1243 type.stripPrefix("class ");
1244 type.stripPrefix("typename ");
1245 type = type.stripWhiteSpace();
1246 paramDocs+=" \\ilinebr @tparam "+type+" "+a.docs;
1247 }
1248 }
1249 }
1250 }
1251 return paramDocs;
1252}
bool hasTemplateDocumentation() const
Definition arguments.cpp:30

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

3758{
3759 QCString result=scope;
3760 if (!templ.isEmpty() && scope.find('<')==-1)
3761 {
3762 int si=0, pi=0;
3763 ClassDef *cd=nullptr;
3764 while (
3765 (si=scope.find("::",pi))!=-1 && !getClass(scope.left(si)+templ) &&
3766 ((cd=getClass(scope.left(si)))==nullptr || cd->templateArguments().empty())
3767 )
3768 {
3769 //printf("Tried '%s'\n",qPrint((scope.left(si)+templ)));
3770 pi=si+2;
3771 }
3772 if (si==-1) // not nested => append template specifier
3773 {
3774 result+=templ;
3775 }
3776 else // nested => insert template specifier before after first class name
3777 {
3778 result=scope.left(si) + templ + scope.right(scope.length()-si);
3779 }
3780 }
3781 //printf("insertTemplateSpecifierInScope('%s','%s')=%s\n",
3782 // qPrint(scope),qPrint(templ),qPrint(result));
3783 return result;
3784}
bool empty() const
Definition arguments.h:99
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 )

Definition at line 6712 of file util.cpp.

6713{
6714 QCString result;
6715 int residual = n;
6716
6717 char modVal[2];
6718 modVal[1] = 0;
6719 while (residual > 0)
6720 {
6721 modVal[0] = (upper ? 'A': 'a') + (residual-1)%26;
6722 result = modVal + result;
6723 residual = (residual-1) / 26;
6724 }
6725 return result;
6726}

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

◆ integerToRoman()

QCString integerToRoman ( int n,
bool upper )

Definition at line 6728 of file util.cpp.

6729{
6730 static const char *str_romans_upper[] = { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" };
6731 static const char *str_romans_lower[] = { "m", "cm", "d", "cd", "c", "xc", "l", "xl", "x", "ix", "v", "iv", "i" };
6732 static const int values[] = { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 };
6733 static const char **str_romans = upper ? str_romans_upper : str_romans_lower;
6734
6735 QCString result;
6736 int residual = n;
6737
6738 for (int i = 0; i < 13; ++i)
6739 {
6740 while (residual - values[i] >= 0)
6741 {
6742 result += str_romans[i];
6743 residual -= values[i];
6744 }
6745 }
6746
6747 return result;
6748}

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

◆ isLowerCase()

bool isLowerCase ( QCString & s)
static

Definition at line 2430 of file util.cpp.

2431{
2432 if (s.isEmpty()) return true;
2433 const char *p=s.data();
2434 int c=0;
2435 while ((c=static_cast<uint8_t>(*p++))) if (!islower(c)) return false;
2436 return true;
2437}

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

Referenced by resolveRef().

◆ isURL()

bool isURL ( const QCString & url)

Checks whether the given url starts with a supported protocol.

Definition at line 5943 of file util.cpp.

5944{
5945 static const std::unordered_set<std::string> schemes = {
5946 "http", "https", "ftp", "ftps", "sftp", "file", "news", "irc", "ircs"
5947 };
5948 QCString loc_url = url.stripWhiteSpace();
5949 int colonPos = loc_url.find(':');
5950 return colonPos!=-1 && schemes.find(loc_url.left(colonPos).str())!=schemes.end();
5951}

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

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

◆ join()

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

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

Definition at line 6699 of file util.cpp.

6700{
6701 std::string result;
6702 bool first=true;
6703 for (const auto &s : sv)
6704 {
6705 if (!first) result+=delimiter;
6706 first=false;
6707 result+=s;
6708 }
6709 return result;
6710}

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

◆ keyWordsFortranC()

bool keyWordsFortranC ( const char * contents)
static

Definition at line 6353 of file util.cpp.

6354{
6355 static const std::unordered_set<std::string> fortran_C_keywords = {
6356 "character", "call", "close", "common", "continue",
6357 "case", "contains", "cycle", "class", "codimension",
6358 "concurrent", "contiguous", "critical"
6359 };
6360
6361 if (*contents != 'c' && *contents != 'C') return false;
6362
6363 const char *c = contents;
6364 QCString keyword;
6365 while (*c && *c != ' ') {keyword += *c; c++;}
6366 keyword = keyword.lower();
6367
6368 return (fortran_C_keywords.find(keyword.str()) != fortran_C_keywords.end());
6369}

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

Referenced by recognizeFixedForm().

◆ langToString()

QCString langToString ( SrcLangExt lang)

Returns a string representation of lang.

Definition at line 5921 of file util.cpp.

5922{
5923 return to_string(lang);
5924}
static constexpr const char * to_string(Protection prot) noexcept
Definition types.h:38

References to_string().

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

◆ leftScopeMatch()

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

Definition at line 881 of file util.cpp.

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

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

5901{
5902 int result = 1;
5903
5904 // find the character positions of the first marker
5905 int m1 = text.find(marker);
5906 if (m1==-1) return result;
5907
5908 // find start line positions for the markers
5909 bool found=false;
5910 int p=0, i=0;
5911 while (!found && (i=text.find('\n',p))!=-1)
5912 {
5913 found = (p<=m1 && m1<i); // found the line with the start marker
5914 p=i+1;
5915 result++;
5916 }
5917 return result;
5918}

References QCString::find().

Referenced by readIncludeFile().

◆ linkifyText()

void linkifyText ( const TextGeneratorIntf & out,
const QCString & text,
const LinkifyTextOptions & options )

Definition at line 893 of file util.cpp.

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

References Definition::anchor(), LinkifyTextOptions::argumentList(), AUTO_TRACE, LinkifyTextOptions::autoBreak(), ArgumentList::begin(), LinkifyTextOptions::breakThreshold(), QCString::data(), Definition::definitionType(), ArgumentList::end(), end(), LinkifyTextOptions::external(), FALSE, LinkifyTextOptions::fileScope(), QCString::findRev(), GetDefResult::found, getClass(), getConcept(), getDefs(), Definition::getLanguage(), Definition::getOuterScope(), Definition::getOutputFileBase(), Definition::getReference(), SymbolResolver::getTypedef(), LinkifyTextOptions::indentLevel(), QCString::isEmpty(), Definition::isLinkable(), Definition::isLinkableInProject(), MemberDef::isVariable(), LinkifyTextOptions::keepSpaces(), QCString::left(), GetDefResult::md, QCString::mid(), Definition::name(), Definition::qualifiedName(), SymbolResolver::resolveClass(), SymbolResolver::resolveSymbol(), LinkifyTextOptions::scope(), LinkifyTextOptions::self(), 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 2698 of file util.cpp.

2699{
2700 //bool optimizeOutputJava = Config_getBool(OPTIMIZE_OUTPUT_JAVA);
2701 QCString result=link;
2702 if (!result.isEmpty())
2703 {
2704 // replace # by ::
2705 result=substitute(result,"#","::");
2706 // replace . by ::
2707 if (!isFileName && result.find('<')==-1) result=substitute(result,".","::",3);
2708 // strip leading :: prefix if present
2709 if (result.at(0)==':' && result.at(1)==':')
2710 {
2711 result=result.right(result.length()-2);
2712 }
2714 if (sep!="::")
2715 {
2716 result=substitute(result,"::",sep);
2717 }
2718 }
2719 //printf("linkToText(%s,lang=%d)=%s\n",qPrint(link),lang,qPrint(result));
2720 return result;
2721}
QCString getLanguageSpecificSeparator(SrcLangExt lang, bool classScope)
Returns the scope separator to use given the programming language lang.
Definition util.cpp:5927

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

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

References Doxygen::mainPage.

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

◆ makeBaseName()

◆ mangleCSharpGenericName()

QCString mangleCSharpGenericName ( const QCString & name)

Definition at line 6943 of file util.cpp.

6944{
6945 int idx = name.find('<');
6946 if (idx!=-1)
6947 {
6948 return name.left(idx)+"-"+QCString().setNum(name.contains(",")+1)+"-g";
6949 }
6950 return name;
6951}
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().

◆ matchArgument2()

bool matchArgument2 ( const Definition * srcScope,
const FileDef * srcFileScope,
Argument & srcA,
const Definition * dstScope,
const FileDef * dstFileScope,
Argument & dstA,
SrcLangExt lang )
static

Definition at line 1955 of file util.cpp.

1960{
1961 AUTO_TRACE("src: scope={} type={} name={} canType={}, dst: scope={} type={} name={} canType={}",
1962 srcScope?srcScope->name():"",srcA.type,srcA.name,srcA.canType,
1963 dstScope?dstScope->name():"",dstA.type,dstA.name,dstA.canType);
1964 //printf(">> match argument: %s::'%s|%s' (%s) <-> %s::'%s|%s' (%s)\n",
1965 // srcScope ? qPrint(srcScope->name()) : "",
1966 // qPrint(srcA.type), qPrint(srcA.name), qPrint(srcA.canType),
1967 // dstScope ? qPrint(dstScope->name()) : "",
1968 // qPrint(dstA.type), qPrint(dstA.name), qPrint(dstA.canType));
1969
1970 QCString sSrcName = " "+srcA.name;
1971 QCString sDstName = " "+dstA.name;
1972 QCString srcType = srcA.type;
1973 QCString dstType = dstA.type;
1974 stripIrrelevantConstVolatile(srcType,false);
1975 stripIrrelevantConstVolatile(dstType,false);
1976 //printf("'%s'<->'%s'\n",qPrint(sSrcName),qPrint(dstType.right(sSrcName.length())));
1977 //printf("'%s'<->'%s'\n",qPrint(sDstName),qPrint(srcType.right(sDstName.length())));
1978 if (sSrcName==dstType.right(sSrcName.length()))
1979 { // case "unsigned int" <-> "unsigned int i"
1980 srcA.type+=sSrcName;
1981 srcA.name="";
1982 srcA.canType=""; // invalidate cached type value
1983 }
1984 else if (sDstName==srcType.right(sDstName.length()))
1985 { // case "unsigned int i" <-> "unsigned int"
1986 dstA.type+=sDstName;
1987 dstA.name="";
1988 dstA.canType=""; // invalidate cached type value
1989 }
1990
1991 {
1992 std::lock_guard lock(g_matchArgsMutex);
1993 if (srcA.canType.isEmpty() || dstA.canType.isEmpty())
1994 {
1995 // need to re-evaluate both see issue #8370
1996 srcA.canType = extractCanonicalArgType(srcScope,srcFileScope,srcA,lang);
1997 dstA.canType = extractCanonicalArgType(dstScope,dstFileScope,dstA,lang);
1998 }
1999 }
2000
2001 if (matchCanonicalTypes(srcScope,srcFileScope,srcA.canType,
2002 dstScope,dstFileScope,dstA.canType,
2003 lang))
2004 {
2005 MATCH
2006 AUTO_TRACE_EXIT("true");
2007 return TRUE;
2008 }
2009 else
2010 {
2011 //printf(" Canonical types do not match [%s]<->[%s]\n",
2012 // qPrint(srcA->canType),qPrint(dstA->canType));
2013 NOMATCH
2014 AUTO_TRACE_EXIT("false");
2015 return FALSE;
2016 }
2017}
static bool matchCanonicalTypes(const Definition *srcScope, const FileDef *srcFileScope, const QCString &srcType, const Definition *dstScope, const FileDef *dstFileScope, const QCString &dstType, SrcLangExt lang)
Definition util.cpp:1923
#define MATCH
Definition util.cpp:1920
static QCString extractCanonicalArgType(const Definition *d, const FileDef *fs, const Argument &arg, SrcLangExt lang)
Definition util.cpp:1890
#define NOMATCH
Definition util.cpp:1921
static std::mutex g_matchArgsMutex
Definition util.cpp:1913

References AUTO_TRACE, AUTO_TRACE_EXIT, Argument::canType, extractCanonicalArgType(), FALSE, g_matchArgsMutex, QCString::isEmpty(), QCString::length(), MATCH, matchCanonicalTypes(), Argument::name, Definition::name(), NOMATCH, QCString::right(), stripIrrelevantConstVolatile(), TRUE, and Argument::type.

Referenced by matchArguments2().

◆ matchArguments2()

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

Definition at line 2021 of file util.cpp.

2024{
2025 ASSERT(srcScope!=nullptr && dstScope!=nullptr);
2026
2027 AUTO_TRACE("srcScope='{}' dstScope='{}' srcArgs='{}' dstArgs='{}' checkCV={} lang={}",
2028 srcScope->name(),dstScope->name(),srcAl?argListToString(*srcAl):"",dstAl?argListToString(*dstAl):"",checkCV,lang);
2029
2030 if (srcAl==nullptr || dstAl==nullptr)
2031 {
2032 bool match = srcAl==dstAl;
2033 if (match)
2034 {
2035 MATCH
2036 return TRUE;
2037 }
2038 else
2039 {
2040 NOMATCH
2041 return FALSE;
2042 }
2043 }
2044
2045 // handle special case with void argument
2046 if ( srcAl->empty() && dstAl->size()==1 && dstAl->front().type=="void" )
2047 { // special case for finding match between func() and func(void)
2048 Argument a;
2049 a.type = "void";
2050 const_cast<ArgumentList*>(srcAl)->push_back(a);
2051 MATCH
2052 return TRUE;
2053 }
2054 if ( dstAl->empty() && srcAl->size()==1 && srcAl->front().type=="void" )
2055 { // special case for finding match between func(void) and func()
2056 Argument a;
2057 a.type = "void";
2058 const_cast<ArgumentList*>(dstAl)->push_back(a);
2059 MATCH
2060 return TRUE;
2061 }
2062
2063 if (srcAl->size() != dstAl->size())
2064 {
2065 NOMATCH
2066 return FALSE; // different number of arguments -> no match
2067 }
2068
2069 if (checkCV)
2070 {
2071 if (srcAl->constSpecifier() != dstAl->constSpecifier())
2072 {
2073 NOMATCH
2074 return FALSE; // one member is const, the other not -> no match
2075 }
2076 if (srcAl->volatileSpecifier() != dstAl->volatileSpecifier())
2077 {
2078 NOMATCH
2079 return FALSE; // one member is volatile, the other not -> no match
2080 }
2081 }
2082
2083 if (srcAl->refQualifier() != dstAl->refQualifier())
2084 {
2085 NOMATCH
2086 return FALSE; // one member is has a different ref-qualifier than the other
2087 }
2088
2089 if (srcReturnType=="auto" && dstReturnType=="auto" && srcAl->trailingReturnType()!=dstAl->trailingReturnType())
2090 {
2091 NOMATCH
2092 return FALSE; // one member is has a different return type than the other
2093 }
2094
2095 // so far the argument list could match, so we need to compare the types of
2096 // all arguments.
2097 auto srcIt = srcAl->begin();
2098 auto dstIt = dstAl->begin();
2099 for (;srcIt!=srcAl->end() && dstIt!=dstAl->end();++srcIt,++dstIt)
2100 {
2101 Argument &srcA = const_cast<Argument&>(*srcIt);
2102 Argument &dstA = const_cast<Argument&>(*dstIt);
2103 if (!matchArgument2(srcScope,srcFileScope,srcA,
2104 dstScope,dstFileScope,dstA,
2105 lang)
2106 )
2107 {
2108 NOMATCH
2109 return FALSE;
2110 }
2111 }
2112 MATCH
2113 return TRUE; // all arguments match
2114}
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
QCString argListToString(const ArgumentList &al, bool useCanonicalType, bool showDefVals)
Definition util.cpp:1254
static bool matchArgument2(const Definition *srcScope, const FileDef *srcFileScope, Argument &srcA, const Definition *dstScope, const FileDef *dstFileScope, Argument &dstA, SrcLangExt lang)
Definition util.cpp:1955

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

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

◆ matchCanonicalTypes()

bool matchCanonicalTypes ( const Definition * srcScope,
const FileDef * srcFileScope,
const QCString & srcType,
const Definition * dstScope,
const FileDef * dstFileScope,
const QCString & dstType,
SrcLangExt lang )
static

Definition at line 1923 of file util.cpp.

1927{
1928 AUTO_TRACE("srcType='{}' dstType='{}'",srcType,dstType);
1929 if (srcType==dstType) return true;
1930
1931 // check if the types are function pointers
1932 int i1=srcType.find(")(");
1933 if (i1==-1) return false;
1934 int i2=dstType.find(")(");
1935 if (i1!=i2) return false;
1936
1937 // check if the result part of the function pointer types matches
1938 int j1=srcType.find("(");
1939 if (j1==-1 || j1>i1) return false;
1940 int j2=dstType.find("(");
1941 if (j2!=j1) return false;
1942 if (srcType.left(j1)!=dstType.left(j2)) return false; // different return types
1943
1944 // if srcType and dstType are both function pointers with the same return type,
1945 // then match against the parameter lists.
1946 // This way srcType='void (*fptr)(int x)' will match against `void (*fptr)(int y)' because
1947 // 'int x' matches 'int y'. A simple literal string match would treat these as different.
1948 auto srcAl = stringToArgumentList(lang,srcType.mid(i1+1));
1949 auto dstAl = stringToArgumentList(lang,dstType.mid(i2+1));
1950 return matchArguments2(srcScope,srcFileScope,srcType.left(j1),srcAl.get(),
1951 dstScope,dstFileScope,dstType.left(j2),dstAl.get(),
1952 true,lang);
1953}
std::unique_ptr< ArgumentList > stringToArgumentList(SrcLangExt lang, const QCString &argsString, QCString *extraTypeChars=nullptr)
Definition defargs.l:822
bool matchArguments2(const Definition *srcScope, const FileDef *srcFileScope, const QCString &srcReturnType, const ArgumentList *srcAl, const Definition *dstScope, const FileDef *dstFileScope, const QCString &dstReturnType, const ArgumentList *dstAl, bool checkCV, SrcLangExt lang)
Definition util.cpp:2021

References AUTO_TRACE, QCString::find(), QCString::left(), matchArguments2(), QCString::mid(), and stringToArgumentList().

Referenced by matchArgument2().

◆ matchTemplateArguments()

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

Definition at line 2265 of file util.cpp.

2266{
2267 AUTO_TRACE("srcAl={} dstAl={}",argListToString(srcAl),argListToString(dstAl));
2268 if (srcAl.size()!=dstAl.size()) // different number of template parameters -> overload
2269 {
2270 AUTO_TRACE_EXIT("different number of parameters");
2271 return false;
2272 }
2273 auto isUnconstraintTemplate = [](const QCString &type)
2274 {
2275 return type=="typename" || type=="class" || type.startsWith("typename ") || type.startsWith("class ");
2276 };
2277 auto srcIt = srcAl.begin();
2278 auto dstIt = dstAl.begin();
2279 while (srcIt!=srcAl.end() && dstIt!=dstAl.end())
2280 {
2281 const Argument &srcA = *srcIt;
2282 const Argument &dstA = *dstIt;
2283 if ((!isUnconstraintTemplate(srcA.type) || !isUnconstraintTemplate(dstA.type)) && srcA.type!=dstA.type) // different constraints -> overload
2284 {
2285 AUTO_TRACE_EXIT("different constraints");
2286 return false;
2287 }
2288 ++srcIt;
2289 ++dstIt;
2290 }
2291 AUTO_TRACE_EXIT("same");
2292 // no overload with respect to the template parameters
2293 return true;
2294}

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 )

Definition at line 2121 of file util.cpp.

2122{
2123 AUTO_TRACE("srcAl='{}',dstAl='{}',forceNameOverwrite={}",
2124 qPrint(argListToString(srcAl)),qPrint(argListToString(dstAl)),forceNameOverwrite);
2125
2126 if (srcAl.size()!=dstAl.size())
2127 {
2128 return; // invalid argument lists -> do not merge
2129 }
2130
2131 auto srcIt=srcAl.begin();
2132 auto dstIt=dstAl.begin();
2133 while (srcIt!=srcAl.end() && dstIt!=dstAl.end())
2134 {
2135 Argument &srcA = *srcIt;
2136 Argument &dstA = *dstIt;
2137
2138 AUTO_TRACE_ADD("before merge: src=[type='{}',name='{}',def='{}'] dst=[type='{}',name='{}',def='{}']",
2139 srcA.type,srcA.name,srcA.defval,
2140 dstA.type,dstA.name,dstA.defval);
2141 if (srcA.defval.isEmpty() && !dstA.defval.isEmpty())
2142 {
2143 //printf("Defval changing '%s'->'%s'\n",qPrint(srcA.defval),qPrint(dstA.defval));
2144 srcA.defval=dstA.defval;
2145 }
2146 else if (!srcA.defval.isEmpty() && dstA.defval.isEmpty())
2147 {
2148 //printf("Defval changing '%s'->'%s'\n",qPrint(dstA.defval),qPrint(srcA.defval));
2149 dstA.defval=srcA.defval;
2150 }
2151
2152 // fix wrongly detected const or volatile specifiers before merging.
2153 // example: "const A *const" is detected as type="const A *" name="const"
2154 if (srcA.name=="const" || srcA.name=="volatile")
2155 {
2156 srcA.type+=" "+srcA.name;
2157 srcA.name.clear();
2158 }
2159 if (dstA.name=="const" || dstA.name=="volatile")
2160 {
2161 dstA.type+=" "+dstA.name;
2162 dstA.name.clear();
2163 }
2164
2165 if (srcA.type==dstA.type)
2166 {
2167 //printf("1. merging %s:%s <-> %s:%s\n",qPrint(srcA.type),qPrint(srcA.name),qPrint(dstA.type),qPrint(dstA.name));
2168 if (srcA.name.isEmpty() && !dstA.name.isEmpty())
2169 {
2170 //printf("type: '%s':='%s'\n",qPrint(srcA.type),qPrint(dstA.type));
2171 //printf("name: '%s':='%s'\n",qPrint(srcA.name),qPrint(dstA.name));
2172 srcA.type = dstA.type;
2173 srcA.name = dstA.name;
2174 }
2175 else if (!srcA.name.isEmpty() && dstA.name.isEmpty())
2176 {
2177 //printf("type: '%s':='%s'\n",qPrint(dstA.type),qPrint(srcA.type));
2178 //printf("name: '%s':='%s'\n",qPrint(dstA.name),qPrint(srcA.name));
2179 dstA.type = srcA.type;
2180 dstA.name = srcA.name;
2181 }
2182 else if (!srcA.name.isEmpty() && !dstA.name.isEmpty())
2183 {
2184 //printf("srcA.name=%s dstA.name=%s\n",qPrint(srcA.name),qPrint(dstA.name));
2185 if (forceNameOverwrite)
2186 {
2187 srcA.name = dstA.name;
2188 }
2189 else
2190 {
2191 if (srcA.docs.isEmpty() && !dstA.docs.isEmpty())
2192 {
2193 srcA.name = dstA.name;
2194 }
2195 else if (!srcA.docs.isEmpty() && dstA.docs.isEmpty())
2196 {
2197 dstA.name = srcA.name;
2198 }
2199 }
2200 }
2201 }
2202 else
2203 {
2204 //printf("2. merging '%s':'%s' <-> '%s':'%s'\n",qPrint(srcA.type),qPrint(srcA.name),qPrint(dstA.type),qPrint(dstA.name));
2205 srcA.type=srcA.type.stripWhiteSpace();
2206 dstA.type=dstA.type.stripWhiteSpace();
2207 if (srcA.type+" "+srcA.name==dstA.type) // "unsigned long:int" <-> "unsigned long int:bla"
2208 {
2209 srcA.type+=" "+srcA.name;
2210 srcA.name=dstA.name;
2211 }
2212 else if (dstA.type+" "+dstA.name==srcA.type) // "unsigned long int bla" <-> "unsigned long int"
2213 {
2214 dstA.type+=" "+dstA.name;
2215 dstA.name=srcA.name;
2216 }
2217 else if (srcA.name.isEmpty() && !dstA.name.isEmpty())
2218 {
2219 srcA.name = dstA.name;
2220 }
2221 else if (dstA.name.isEmpty() && !srcA.name.isEmpty())
2222 {
2223 dstA.name = srcA.name;
2224 }
2225 }
2226 int i1=srcA.type.find("::"),
2227 i2=dstA.type.find("::"),
2228 j1=static_cast<int>(srcA.type.length())-i1-2,
2229 j2=static_cast<int>(dstA.type.length())-i2-2;
2230 if (i1!=-1 && i2==-1 && srcA.type.right(j1)==dstA.type)
2231 {
2232 //printf("type: '%s':='%s'\n",qPrint(dstA.type),qPrint(srcA.type));
2233 //printf("name: '%s':='%s'\n",qPrint(dstA.name),qPrint(srcA.name));
2234 dstA.type = srcA.type.left(i1+2)+dstA.type;
2235 dstA.name = srcA.name;
2236 }
2237 else if (i1==-1 && i2!=-1 && dstA.type.right(j2)==srcA.type)
2238 {
2239 //printf("type: '%s':='%s'\n",qPrint(srcA.type),qPrint(dstA.type));
2240 //printf("name: '%s':='%s'\n",qPrint(dstA.name),qPrint(srcA.name));
2241 srcA.type = dstA.type.left(i2+2)+srcA.type;
2242 srcA.name = dstA.name;
2243 }
2244 if (srcA.docs.isEmpty() && !dstA.docs.isEmpty())
2245 {
2246 srcA.docs = dstA.docs;
2247 }
2248 else if (dstA.docs.isEmpty() && !srcA.docs.isEmpty())
2249 {
2250 dstA.docs = srcA.docs;
2251 }
2252 //printf("Merge argument '%s|%s' '%s|%s'\n",
2253 // qPrint(srcA.type), qPrint(srcA.name),
2254 // qPrint(dstA.type), qPrint(dstA.name));
2255 ++srcIt;
2256 ++dstIt;
2257 AUTO_TRACE_ADD("after merge: src=[type='{}',name='{}',def='{}'] dst=[type='{}',name='{}',def='{}']",
2258 srcA.type,srcA.name,srcA.defval,
2259 dstA.type,dstA.name,dstA.defval);
2260 }
2261}
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 6891 of file util.cpp.

6892{
6893 if (Config_getBool(CALL_GRAPH) !=md1->hasCallGraph()) md2->overrideCallGraph(md1->hasCallGraph());
6894 if (Config_getBool(CALLER_GRAPH)!=md1->hasCallerGraph()) md2->overrideCallerGraph(md1->hasCallerGraph());
6895 if (Config_getBool(CALL_GRAPH) !=md2->hasCallGraph()) md1->overrideCallGraph( md2->hasCallGraph());
6896 if (Config_getBool(CALLER_GRAPH)!=md2->hasCallerGraph()) md1->overrideCallerGraph(md2->hasCallerGraph());
6897
6898 if (Config_getBool(SHOW_ENUM_VALUES) !=md1->hasEnumValues()) md2->overrideEnumValues(md1->hasEnumValues());
6899 if (Config_getBool(SHOW_ENUM_VALUES) !=md2->hasEnumValues()) md1->overrideEnumValues( md2->hasEnumValues());
6900
6901 if (Config_getBool(REFERENCED_BY_RELATION)!=md1->hasReferencedByRelation()) md2->overrideReferencedByRelation(md1->hasReferencedByRelation());
6902 if (Config_getBool(REFERENCES_RELATION) !=md1->hasReferencesRelation()) md2->overrideReferencesRelation(md1->hasReferencesRelation());
6903 if (Config_getBool(REFERENCED_BY_RELATION)!=md2->hasReferencedByRelation()) md1->overrideReferencedByRelation(md2->hasReferencedByRelation());
6904 if (Config_getBool(REFERENCES_RELATION) !=md2->hasReferencesRelation()) md1->overrideReferencesRelation(md2->hasReferencesRelation());
6905
6906 if (Config_getBool(INLINE_SOURCES)!=md1->hasInlineSource()) md2->overrideInlineSource(md1->hasInlineSource());
6907 if (Config_getBool(INLINE_SOURCES)!=md2->hasInlineSource()) md1->overrideInlineSource(md2->hasInlineSource());
6908}
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 4605 of file util.cpp.

4606{
4607 AUTO_TRACE("leftScope='{}' rightScope='{}'",leftScope,rightScope);
4608 // case leftScope=="A" rightScope=="A::B" => result = "A::B"
4609 if (leftScopeMatch(leftScope,rightScope))
4610 {
4611 AUTO_TRACE_EXIT("case1={}",rightScope);
4612 return rightScope;
4613 }
4614 QCString result;
4615 int i=0,p=static_cast<int>(leftScope.length());
4616
4617 // case leftScope=="A::B" rightScope=="B::C" => result = "A::B::C"
4618 // case leftScope=="A::B" rightScope=="B" => result = "A::B"
4619 bool found=FALSE;
4620 while ((i=leftScope.findRev("::",p))>0)
4621 {
4622 if (leftScopeMatch(rightScope,leftScope.right(leftScope.length()-i-2)))
4623 {
4624 result = leftScope.left(i+2)+rightScope;
4625 found=TRUE;
4626 }
4627 p=i-1;
4628 }
4629 if (found)
4630 {
4631 AUTO_TRACE_EXIT("case2={}",result);
4632 return result;
4633 }
4634
4635 // case leftScope=="A" rightScope=="B" => result = "A::B"
4636 result=leftScope;
4637 if (!result.isEmpty() && !rightScope.isEmpty()) result+="::";
4638 result+=rightScope;
4639 AUTO_TRACE_EXIT("case3={}",result);
4640 return result;
4641}
bool leftScopeMatch(const QCString &scope, const QCString &name)
Definition util.cpp:881

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

Definition at line 5335 of file util.cpp.

5336{
5337 if (startPos>=len) return len;
5338 uint8_t c = static_cast<uint8_t>(utf8Str[startPos]);
5339 int bytes=getUTF8CharNumBytes(c);
5340 if (c=='&') // skip over character entities
5341 {
5342 bytes=1;
5343 int (*matcher)(int) = nullptr;
5344 c = static_cast<uint8_t>(utf8Str[startPos+bytes]);
5345 if (c=='#') // numerical entity?
5346 {
5347 bytes++;
5348 c = static_cast<uint8_t>(utf8Str[startPos+bytes]);
5349 if (c=='x') // hexadecimal entity?
5350 {
5351 bytes++;
5352 matcher = std::isxdigit;
5353 }
5354 else // decimal entity
5355 {
5356 matcher = std::isdigit;
5357 }
5358 }
5359 else if (std::isalnum(c)) // named entity?
5360 {
5361 bytes++;
5362 matcher = std::isalnum;
5363 }
5364 if (matcher)
5365 {
5366 while ((c = static_cast<uint8_t>(utf8Str[startPos+bytes]))!=0 && matcher(c))
5367 {
5368 bytes++;
5369 }
5370 }
5371 if (c!=';')
5372 {
5373 bytes=1; // not a valid entity, reset bytes counter
5374 }
5375 }
5376 return startPos+bytes;
5377}

References getUTF8CharNumBytes().

Referenced by parseCommentAsText().

◆ normalizeNonTemplateArgumentsInString()

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

Definition at line 4311 of file util.cpp.

4315{
4316 // skip until <
4317 int p=name.find('<');
4318 if (p==-1) return name;
4319 p++;
4320 QCString result = name.left(p);
4321
4322 std::string s = name.mid(p).str();
4323 static const reg::Ex re(R"([\a:][\w:]*)");
4324 reg::Iterator it(s,re);
4326 size_t pi=0;
4327 // for each identifier in the template part (e.g. B<T> -> T)
4328 for (; it!=end ; ++it)
4329 {
4330 const auto &match = *it;
4331 size_t i = match.position();
4332 size_t l = match.length();
4333 result += s.substr(pi,i-pi);
4334 QCString n(match.str());
4335 bool found=FALSE;
4336 for (const Argument &formArg : formalArgs)
4337 {
4338 if (formArg.name == n)
4339 {
4340 found=TRUE;
4341 break;
4342 }
4343 }
4344 if (!found)
4345 {
4346 // try to resolve the type
4347 SymbolResolver resolver;
4348 const ClassDef *cd = resolver.resolveClass(context,n);
4349 if (cd)
4350 {
4351 result+=cd->name();
4352 }
4353 else
4354 {
4355 result+=n;
4356 }
4357 }
4358 else
4359 {
4360 result+=n;
4361 }
4362 pi=i+l;
4363 }
4364 result+=s.substr(pi);
4365 //printf("normalizeNonTemplateArgumentInString(%s)=%s\n",qPrint(name),qPrint(result));
4366 return removeRedundantWhiteSpace(result);
4367}
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 6326 of file util.cpp.

6327{
6328 assert(!f.is_open());
6329 bool fileOpened=FALSE;
6330 bool writeToStdout=outFile=="-";
6331 if (writeToStdout) // write to stdout
6332 {
6333 f.basic_ios<char>::rdbuf(std::cout.rdbuf());
6334 fileOpened = true;
6335 }
6336 else // write to file
6337 {
6338 FileInfo fi(outFile.str());
6339 if (fi.exists()) // create a backup
6340 {
6341 Dir dir;
6342 FileInfo backup(fi.filePath()+".bak");
6343 if (backup.exists()) // remove existing backup
6344 dir.remove(backup.filePath());
6345 dir.rename(fi.filePath(),fi.filePath()+".bak");
6346 }
6347 f = Portable::openOutputStream(outFile);
6348 fileOpened = f.is_open();
6349 }
6350 return fileOpened;
6351}
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:648

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

5436{
5437 std::lock_guard lock(g_docCacheMutex);
5438 auto it = g_docCache.find(doc.str());
5439 if (it != g_docCache.end())
5440 {
5441 //printf("Cache: [%s]->[%s]\n",qPrint(doc),qPrint(it->second));
5442 return it->second;
5443 }
5444 auto parser { createDocParser() };
5445 auto ast { validatingParseTitle(*parser.get(),fileName,lineNr,doc) };
5446 auto astImpl = dynamic_cast<const DocNodeAST*>(ast.get());
5447 QCString result;
5448 if (astImpl)
5449 {
5450 TextStream t;
5451 OutputCodeList codeList;
5452 codeList.add<HtmlCodeGenerator>(&t);
5453 HtmlDocVisitor visitor(t,codeList,scope,fileName);
5454 std::visit(visitor,astImpl->root);
5455 result = t.str();
5456 }
5457 else // fallback, should not happen
5458 {
5459 result = filterTitle(doc);
5460 }
5461 //printf("Conversion: [%s]->[%s]\n",qPrint(doc),qPrint(result));
5462 g_docCache.insert(std::make_pair(doc.str(),result));
5463 return result;
5464}
Class representing the abstract syntax tree of a documentation block.
Definition docnode.h:1472
Generator for HTML code fragments.
Definition htmlgen.h:26
Concrete visitor implementation for HTML output.
Class representing a list of different code generators.
Definition outputlist.h:165
void add(OutputCodeIntfPtr &&p)
Definition outputlist.h:195
Text streaming class that buffers data.
Definition textstream.h:36
std::string str() const
Return the contents of the buffer as a std::string object.
Definition textstream.h:216
IDocParserPtr createDocParser()
factory function to create a parser
Definition docparser.cpp:55
IDocNodeASTPtr validatingParseTitle(IDocParser &parserIntf, const QCString &fileName, int lineNr, const QCString &input)
static std::unordered_map< std::string, QCString > g_docCache
Definition util.cpp:5433
QCString filterTitle(const QCString &title)
Definition util.cpp:5640
static std::mutex g_docCacheMutex
Definition util.cpp:5432

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

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

◆ parseCommentAsText()

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

Definition at line 5379 of file util.cpp.

5381{
5382 if (doc.isEmpty()) return "";
5383 //printf("parseCommentAsText(%s)\n",qPrint(doc));
5384 TextStream t;
5385 auto parser { createDocParser() };
5386 auto ast { validatingParseDoc(*parser.get(),
5387 fileName,
5388 lineNr,
5389 scope,
5390 md,
5391 doc,
5392 DocOptions()
5393 .setAutolinkSupport(false))
5394 };
5395 auto astImpl = dynamic_cast<const DocNodeAST*>(ast.get());
5396 if (astImpl)
5397 {
5398 TextDocVisitor visitor(t);
5399 std::visit(visitor,astImpl->root);
5400 }
5402 int i=0;
5403 int charCnt=0;
5404 int l=static_cast<int>(result.length());
5405 while ((i=nextUTF8CharPosition(result,l,i))<l)
5406 {
5407 charCnt++;
5408 if (charCnt>=80) break;
5409 }
5410 if (charCnt>=80) // try to truncate the string
5411 {
5412 while ((i=nextUTF8CharPosition(result,l,i))<l && charCnt<100)
5413 {
5414 charCnt++;
5415 if (result.at(i)==',' ||
5416 result.at(i)=='.' ||
5417 result.at(i)=='!' ||
5418 result.at(i)=='?' ||
5419 result.at(i)=='}') // good for UTF-16 characters and } otherwise also a good point to stop the string
5420 {
5421 i++; // we want to be "behind" last inspected character
5422 break;
5423 }
5424 }
5425 }
5426 if ( i < l) result=result.left(i)+"...";
5427 return result.data();
5428}
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:5335

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

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

◆ patternMatch()

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

Definition at line 5714 of file util.cpp.

5715{
5716 std::string elem;
5717 auto getter = [](std::string s) -> QCString { return s; };
5718 return genericPatternMatch(fi,patList,elem,getter);
5719}

References genericPatternMatch().

Referenced by checkAndOpenFile(), and readDir().

◆ projectLogoFile()

QCString projectLogoFile ( )

Definition at line 3151 of file util.cpp.

3152{
3153 QCString projectLogo = Config_getString(PROJECT_LOGO);
3154 if (!projectLogo.isEmpty())
3155 {
3156 // check for optional width= and height= specifier
3157 int wi = projectLogo.find(" width=");
3158 if (wi!=-1) // and strip them
3159 {
3160 projectLogo = projectLogo.left(wi);
3161 }
3162 int hi = projectLogo.find(" height=");
3163 if (hi!=-1)
3164 {
3165 projectLogo = projectLogo.left(hi);
3166 }
3167 }
3168 //printf("projectlogo='%s'\n",qPrint(projectLogo));
3169 return projectLogo;
3170}

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

Referenced by copyLogo(), and substituteKeywords().

◆ projectLogoSize()

QCString projectLogoSize ( )
static

Definition at line 3172 of file util.cpp.

3173{
3174 QCString sizeVal;
3175 QCString projectLogo = Config_getString(PROJECT_LOGO);
3176 if (!projectLogo.isEmpty())
3177 {
3178 auto extractDimension = [&projectLogo](const char *startMarker,size_t startPos,size_t endPos) -> QCString
3179 {
3180 QCString result = projectLogo.mid(startPos,endPos-startPos).stripWhiteSpace().quoted();
3181 if (result.length()>=2 && result.at(0)!='"' && result.at(result.length()-1)!='"')
3182 {
3183 result="\""+result+"\"";
3184 }
3185 result.prepend(startMarker);
3186 return result;
3187 };
3188 // check for optional width= and height= specifier
3189 int wi = projectLogo.find(" width=");
3190 int hi = projectLogo.find(" height=");
3191 if (wi!=-1 && hi!=-1)
3192 {
3193 if (wi<hi) // "... width=x height=y..."
3194 {
3195 sizeVal = extractDimension(" width=", wi+7, hi) + " "
3196 + extractDimension(" height=", hi+8, projectLogo.length());
3197 }
3198 else // "... height=y width=x..."
3199 {
3200 sizeVal = extractDimension(" height=", hi+8, wi) + " "
3201 + extractDimension(" width=", wi+7, projectLogo.length());
3202 }
3203 }
3204 else if (wi!=-1) // ... width=x..."
3205 {
3206 sizeVal = extractDimension(" width=", wi+7, projectLogo.length());
3207 }
3208 else if (hi!=-1) // ... height=x..."
3209 {
3210 sizeVal = extractDimension(" height=", hi+8, projectLogo.length());
3211 }
3212 }
3213 //printf("projectsize='%s'\n",qPrint(sizeVal));
3214 return sizeVal;
3215}
QCString quoted() const
Definition qcstring.h:275

References QCString::at(), Config_getString, QCString::find(), QCString::isEmpty(), QCString::length(), QCString::mid(), QCString::prepend(), QCString::quoted(), and QCString::stripWhiteSpace().

Referenced by substituteKeywords().

◆ protectionLevelVisible()

bool protectionLevelVisible ( Protection prot)

Definition at line 5967 of file util.cpp.

5968{
5969 bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
5970 bool extractPackage = Config_getBool(EXTRACT_PACKAGE);
5971
5972 return (prot!=Protection::Private && prot!=Protection::Package) ||
5973 (prot==Protection::Private && extractPrivate) ||
5974 (prot==Protection::Package && extractPackage);
5975}

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,
bool isSourceCode )

read a file name fileName and optionally filter and transcode it

Definition at line 5560 of file util.cpp.

5561{
5562 // try to open file
5563 FileInfo fi(fileName.str());
5564 if (!fi.exists()) return FALSE;
5565 QCString filterName = getFileFilter(fileName,isSourceCode);
5566 if (filterName.isEmpty() || !filter)
5567 {
5568 std::ifstream f = Portable::openInputStream(fileName,true);
5569 if (!f.is_open())
5570 {
5571 err("could not open file {}\n",fileName);
5572 return FALSE;
5573 }
5574 // read the file
5575 auto fileSize = fi.size();
5576 contents.resize(fileSize);
5577 f.read(contents.data(),fileSize);
5578 if (f.fail())
5579 {
5580 err("problems while reading file {}\n",fileName);
5581 return FALSE;
5582 }
5583 }
5584 else
5585 {
5586 QCString cmd=filterName+" \""+fileName+"\"";
5587 Debug::print(Debug::ExtCmd,0,"Executing popen(`{}`)\n",cmd);
5588 FILE *f=Portable::popen(cmd,"r");
5589 if (!f)
5590 {
5591 err("could not execute filter {}\n",filterName);
5592 return FALSE;
5593 }
5594 const int bufSize=4096;
5595 char buf[bufSize];
5596 int numRead = 0;
5597 while ((numRead=static_cast<int>(fread(buf,1,bufSize,f)))>0)
5598 {
5599 //printf(">>>>>>>>Reading %d bytes\n",numRead);
5600 contents.append(buf,numRead);
5601 }
5603 Debug::print(Debug::FilterOutput, 0, "Filter output\n");
5604 Debug::print(Debug::FilterOutput,0,"-------------\n{}\n-------------\n",contents);
5605 }
5606
5607 if (contents.size()>=2 &&
5608 static_cast<uint8_t>(contents[0])==0xFF &&
5609 static_cast<uint8_t>(contents[1])==0xFE // Little endian BOM
5610 ) // UCS-2LE encoded file
5611 {
5612 transcodeCharacterBuffer(fileName,contents,"UCS-2LE","UTF-8");
5613 }
5614 else if (contents.size()>=2 &&
5615 static_cast<uint8_t>(contents[0])==0xFE &&
5616 static_cast<uint8_t>(contents[1])==0xFF // big endian BOM
5617 ) // UCS-2BE encoded file
5618 {
5619 transcodeCharacterBuffer(fileName,contents,"UCS-2BE","UTF-8");
5620 }
5621 else if (contents.size()>=3 &&
5622 static_cast<uint8_t>(contents[0])==0xEF &&
5623 static_cast<uint8_t>(contents[1])==0xBB &&
5624 static_cast<uint8_t>(contents[2])==0xBF
5625 ) // UTF-8 encoded file
5626 {
5627 contents.erase(0,3); // remove UTF-8 BOM: no translation needed
5628 }
5629 else // transcode according to the INPUT_ENCODING setting
5630 {
5631 // do character transcoding if needed.
5632 transcodeCharacterBuffer(fileName,contents,getEncoding(fi),"UTF-8");
5633 }
5634
5635 filterCRLF(contents);
5636 return true;
5637}
@ FilterOutput
Definition debug.h:38
@ ExtCmd
Definition debug.h:36
static void print(DebugMask mask, int prio, fmt::format_string< Args... > fmt, Args &&... args)
Definition debug.h:77
std::ifstream openInputStream(const QCString &name, bool binary=false, bool openAtEnd=false)
Definition portable.cpp:659
FILE * popen(const QCString &name, const QCString &type)
Definition portable.cpp:479
int pclose(FILE *stream)
Definition portable.cpp:488
static void filterCRLF(std::string &contents)
Definition util.cpp:1355
static void transcodeCharacterBuffer(const QCString &fileName, std::string &contents, const QCString &inputEncoding, const QCString &outputEncoding)
Definition util.cpp:5524
QCString getEncoding(const FileInfo &fi)
Definition util.cpp:5721
QCString getFileFilter(const QCString &name, bool isSourceCode)
Definition util.cpp:1422

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(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), parseFile(), parseInput(), readIncludeFile(), DocbookDocVisitor::startMermaidFile(), LatexDocVisitor::startMermaidFile(), DocbookDocVisitor::startPlantUmlFile(), and LatexDocVisitor::startPlantUmlFile().

◆ recognizeFixedForm()

bool recognizeFixedForm ( const QCString & contents,
FortranFormat format )

Definition at line 6373 of file util.cpp.

6374{
6375 int column=0;
6376 bool skipLine=FALSE;
6377
6378 if (format == FortranFormat::Fixed) return TRUE;
6379 if (format == FortranFormat::Free) return FALSE;
6380
6381 int tabSize=Config_getInt(TAB_SIZE);
6382 size_t sizCont = contents.length();
6383 for (size_t i=0;i<sizCont;i++)
6384 {
6385 column++;
6386
6387 switch(contents.at(i))
6388 {
6389 case '\n':
6390 column=0;
6391 skipLine=FALSE;
6392 break;
6393 case '\t':
6394 column += tabSize-1;
6395 break;
6396 case ' ':
6397 break;
6398 case '\000':
6399 return FALSE;
6400 case '#':
6401 skipLine=TRUE;
6402 break;
6403 case 'C':
6404 case 'c':
6405 if (column==1)
6406 {
6407 return !keyWordsFortranC(contents.data()+i);
6408 }
6409 // fallthrough
6410 case '*':
6411 if (column==1) return TRUE;
6412 if (skipLine) break;
6413 return FALSE;
6414 case '!':
6415 if (column!=6) skipLine=TRUE;
6416 break;
6417 default:
6418 if (skipLine) break;
6419 if (column>=7) return TRUE;
6420 return FALSE;
6421 }
6422 }
6423 return FALSE;
6424}
static bool keyWordsFortranC(const char *contents)
Definition util.cpp:6353

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

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

◆ recursivelyAddGroupListToTitle()

bool recursivelyAddGroupListToTitle ( OutputList & ol,
const Definition * d,
bool root )
static

Definition at line 4883 of file util.cpp.

4884{
4885 ModuleDef *mod = root ? findModuleDef(d) : nullptr;
4886 if (!d->partOfGroups().empty() || mod!=nullptr) // write list of group to which this definition belongs
4887 {
4888 if (root)
4889 {
4890 ol.pushGeneratorState();
4892 ol.writeString("<div class=\"ingroups\">");
4893 }
4894 bool first=true;
4895 for (const auto &gd : d->partOfGroups())
4896 {
4897 if (!first) { ol.writeString(" &#124; "); } else first=false;
4899 {
4900 ol.writeString(" &raquo; ");
4901 }
4902 ol.writeObjectLink(gd->getReference(),gd->getOutputFileBase(),QCString(),gd->groupTitle());
4903 }
4904 if (root)
4905 {
4906 // add module as a group to the file as well
4907 if (mod)
4908 {
4909 if (!first) { ol.writeString(" &#124; "); } else first=false;
4910 ol.writeString(theTranslator->trModule(false,true)+" ");
4912 mod->displayName());
4913 }
4914 ol.writeString("</div>");
4915 ol.popGeneratorState();
4916 }
4917 return true;
4918 }
4919 return false;
4920}
virtual const GroupList & partOfGroups() const =0
virtual QCString displayName(bool includeScope=TRUE) const =0
void writeString(const QCString &text)
Definition outputlist.h:411
void pushGeneratorState()
void disableAllBut(OutputType o)
void popGeneratorState()
static ModuleDef * findModuleDef(const Definition *d)
Definition util.cpp:4854

References OutputList::disableAllBut(), Definition::displayName(), FALSE, findModuleDef(), Definition::getOutputFileBase(), Definition::getReference(), Html, Definition::partOfGroups(), OutputList::popGeneratorState(), OutputList::pushGeneratorState(), recursivelyAddGroupListToTitle(), theTranslator, OutputList::writeObjectLink(), and OutputList::writeString().

Referenced by addGroupListToTitle(), and recursivelyAddGroupListToTitle().

◆ relativePathToRoot()

QCString relativePathToRoot ( const QCString & name)

Definition at line 3590 of file util.cpp.

3591{
3592 QCString result;
3593 if (Config_getBool(CREATE_SUBDIRS))
3594 {
3595 if (name.isEmpty())
3596 {
3597 return REL_PATH_TO_ROOT;
3598 }
3599 else
3600 {
3601 int i = name.findRev('/');
3602 if (i!=-1)
3603 {
3604 result=REL_PATH_TO_ROOT;
3605 }
3606 }
3607 }
3608 return result;
3609}
#define REL_PATH_TO_ROOT
Definition util.cpp:94

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

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

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

6617{
6618 std::string out;
6619 out.reserve(s.length());
6620 const char *p=s.data();
6621 if (p)
6622 {
6623 char c = 0;
6624 while ((c=*p++))
6625 {
6626 if (c=='\n')
6627 {
6628 const char *e = p;
6629 while (*e==' ' || *e=='\t') e++;
6630 if (*e=='\n')
6631 {
6632 p=e;
6633 }
6634 else out+=c;
6635 }
6636 else
6637 {
6638 out+=c;
6639 }
6640 }
6641 }
6642 //printf("removeEmptyLines(%s)=%s\n",qPrint(s),qPrint(out));
6643 return out;
6644}

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

Referenced by substituteHtmlKeywords(), and substituteLatexKeywords().

◆ removeLongPathMarker()

QCString removeLongPathMarker ( QCString path)

Definition at line 287 of file util.cpp.

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

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

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

◆ removeRedundantWhiteSpace()

QCString removeRedundantWhiteSpace ( const QCString & s)

Definition at line 567 of file util.cpp.

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

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

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

◆ replaceAnonymousScopes()

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

Definition at line 218 of file util.cpp.

219{
220 if (s.isEmpty()) return s;
221 static const reg::Ex marker(R"(@\d+)");
222 std::string result = reg::replace(s.str(),marker,
223 !replacement.isEmpty() ? replacement.data() : "__anonymous__");
224 //printf("replaceAnonymousScopes('%s')='%s'\n",qPrint(s),qPrint(result));
225 return result;
226}
std::string replace(std::string_view str, const Ex &re, std::string_view replacement)
Searching in a given input string for parts that match regular expression re and replaces those parts...
Definition regex.cpp:866

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

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

◆ replaceColorMarkers()

QCString replaceColorMarkers ( const QCString & str)

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

Definition at line 5836 of file util.cpp.

5837{
5838 if (str.isEmpty()) return QCString();
5839 std::string result;
5840 std::string s=str.str();
5841 static const reg::Ex re(R"(##[0-9A-Fa-f][0-9A-Fa-f])");
5842 reg::Iterator it(s,re);
5844 int hue = Config_getInt(HTML_COLORSTYLE_HUE);
5845 int sat = Config_getInt(HTML_COLORSTYLE_SAT);
5846 int gamma = Config_getInt(HTML_COLORSTYLE_GAMMA);
5847 size_t sl=s.length();
5848 size_t p=0;
5849 for (; it!=end ; ++it)
5850 {
5851 const auto &match = *it;
5852 size_t i = match.position();
5853 size_t l = match.length();
5854 if (i>p) result+=s.substr(p,i-p);
5855 std::string lumStr = match.str().substr(2);
5856#define HEXTONUM(x) (((x)>='0' && (x)<='9') ? ((x)-'0') : \
5857 ((x)>='a' && (x)<='f') ? ((x)-'a'+10) : \
5858 ((x)>='A' && (x)<='F') ? ((x)-'A'+10) : 0)
5859
5860 double r = 0,g = 0,b = 0;
5861 int level = HEXTONUM(lumStr[0])*16+HEXTONUM(lumStr[1]);
5862 ColoredImage::hsl2rgb(hue/360.0,sat/255.0,
5863 pow(level/255.0,gamma/100.0),&r,&g,&b);
5864 int red = static_cast<int>(r*255.0);
5865 int green = static_cast<int>(g*255.0);
5866 int blue = static_cast<int>(b*255.0);
5867 char colStr[8];
5868 colStr[0]='#';
5869 colStr[1]=hex[red>>4];
5870 colStr[2]=hex[red&0xf];
5871 colStr[3]=hex[green>>4];
5872 colStr[4]=hex[green&0xf];
5873 colStr[5]=hex[blue>>4];
5874 colStr[6]=hex[blue&0xf];
5875 colStr[7]=0;
5876 //printf("replacing %s->%s (level=%d)\n",qPrint(lumStr),colStr,level);
5877 result+=colStr;
5878 p=i+l;
5879 }
5880 if (p<sl) result+=s.substr(p);
5881 return result;
5882}
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 )

Definition at line 2724 of file util.cpp.

2732{
2733 *resContext=nullptr;
2734
2735 QCString linkRef=lr;
2736 if (lang==SrcLangExt::CSharp)
2737 {
2738 linkRef = mangleCSharpGenericName(linkRef);
2739 }
2740 QCString linkRefWithoutTemplates = stripTemplateSpecifiersFromScope(linkRef,FALSE);
2741 AUTO_TRACE("scName='{}',ref='{}'",scName,lr);
2742 const FileDef *fd = nullptr;
2743 const GroupDef *gd = nullptr;
2744 const PageDef *pd = nullptr;
2745 const ClassDef *cd = nullptr;
2746 const DirDef *dir = nullptr;
2747 const ConceptDef *cnd = nullptr;
2748 const ModuleDef *modd = nullptr;
2749 const NamespaceDef *nd = nullptr;
2750 const SectionInfo *si = nullptr;
2751 bool ambig = false;
2752 if (linkRef.isEmpty()) // no reference name!
2753 {
2754 AUTO_TRACE_EXIT("no_ref");
2755 return FALSE;
2756 }
2757 else if ((pd=Doxygen::pageLinkedMap->find(linkRef))) // link to a page
2758 {
2759 gd = pd->getGroupDef();
2760 if (gd)
2761 {
2762 if (!pd->name().isEmpty()) si=SectionManager::instance().find(pd->name());
2763 *resContext=gd;
2764 if (si) resAnchor = si->label();
2765 }
2766 else
2767 {
2768 *resContext=pd;
2769 }
2770 AUTO_TRACE_EXIT("page");
2771 return TRUE;
2772 }
2773 else if ((si=SectionManager::instance().find(prefix+linkRef)))
2774 {
2775 *resContext=si->definition();
2776 resAnchor = si->label();
2777 AUTO_TRACE_EXIT("section anchor={} def={}",resAnchor,si->definition()?si->definition()->name():"<none>");
2778 return TRUE;
2779 }
2780 else if (!prefix.isEmpty() && (si=SectionManager::instance().find(linkRef)))
2781 {
2782 *resContext=si->definition();
2783 resAnchor = si->label();
2784 AUTO_TRACE_EXIT("section anchor={} def={}",resAnchor,si->definition()?si->definition()->name():"<none>");
2785 return TRUE;
2786 }
2787 else if ((pd=Doxygen::exampleLinkedMap->find(linkRef))) // link to an example
2788 {
2789 *resContext=pd;
2790 AUTO_TRACE_EXIT("example");
2791 return TRUE;
2792 }
2793 else if ((gd=Doxygen::groupLinkedMap->find(linkRef))) // link to a group
2794 {
2795 *resContext=gd;
2796 AUTO_TRACE_EXIT("group");
2797 return TRUE;
2798 }
2799 else if ((fd=findFileDef(Doxygen::inputNameLinkedMap,linkRef,ambig)) // file link
2800 && fd->isLinkable())
2801 {
2802 *resContext=fd;
2803 AUTO_TRACE_EXIT("file");
2804 return TRUE;
2805 }
2806 else if ((cd=getClass(linkRef))) // class link
2807 {
2808 *resContext=cd;
2809 resAnchor=cd->anchor();
2810 AUTO_TRACE_EXIT("class");
2811 return TRUE;
2812 }
2813 else if (lang==SrcLangExt::Java &&
2814 (cd=getClass(linkRefWithoutTemplates))) // Java generic class link
2815 {
2816 *resContext=cd;
2817 resAnchor=cd->anchor();
2818 AUTO_TRACE_EXIT("generic");
2819 return TRUE;
2820 }
2821 else if ((cd=getClass(linkRef+"-p"))) // Obj-C protocol link
2822 {
2823 *resContext=cd;
2824 resAnchor=cd->anchor();
2825 AUTO_TRACE_EXIT("protocol");
2826 return TRUE;
2827 }
2828 else if ((cnd=getConcept(linkRef))) // C++20 concept definition
2829 {
2830 *resContext=cnd;
2831 resAnchor=cnd->anchor();
2832 AUTO_TRACE_EXIT("concept");
2833 return TRUE;
2834 }
2835 else if ((modd=ModuleManager::instance().modules().find(linkRef)))
2836 {
2837 *resContext=modd;
2838 resAnchor=modd->anchor();
2839 AUTO_TRACE_EXIT("module");
2840 return TRUE;
2841 }
2842 else if ((nd=Doxygen::namespaceLinkedMap->find(linkRef)))
2843 {
2844 *resContext=nd;
2845 AUTO_TRACE_EXIT("namespace");
2846 return TRUE;
2847 }
2848 else if ((dir=Doxygen::dirLinkedMap->find(FileInfo(linkRef.str()).absFilePath()+"/"))
2849 && dir->isLinkable()) // TODO: make this location independent like filedefs
2850 {
2851 *resContext=dir;
2852 AUTO_TRACE_EXIT("directory");
2853 return TRUE;
2854 }
2855 else // probably a member reference
2856 {
2857 const MemberDef *md = nullptr;
2858 bool res = resolveRef(scName,lr,TRUE,resContext,&md,lang);
2859 if (md) resAnchor=md->anchor();
2860 AUTO_TRACE_EXIT("member? res={}",res);
2861 return res;
2862 }
2863}
A model of a directory symbol.
Definition dirdef.h:110
static PageLinkedMap * exampleLinkedMap
Definition doxygen.h:98
static DirLinkedMap * dirLinkedMap
Definition doxygen.h:127
static GroupLinkedMap * groupLinkedMap
Definition doxygen.h:114
A model of a group of symbols.
Definition groupdef.h:52
virtual const GroupDef * getGroupDef() const =0
QCString label() const
Definition section.h:69
Definition * definition() const
Definition section.h:77
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:2442
QCString mangleCSharpGenericName(const QCString &name)
Definition util.cpp:6943

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

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

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 * context,
const QCString & qualifiedName,
const Definition ** typedefContext )

Definition at line 373 of file util.cpp.

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

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

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

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

6440{
6441 if (s.isEmpty()) return s;
6442
6443 // helper to find the end of a block
6444 auto skipBlock = [&markerInfo](const char *p,const SelectionBlock &blk)
6445 {
6446 char c = 0;
6447 while ((c=*p))
6448 {
6449 if (c==markerInfo.markerChar && qstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // end marker
6450 {
6451 size_t len = markerInfo.endLen;
6452 bool negate = *(p+markerInfo.endLen)=='!';
6453 if (negate) len++;
6454 size_t blkNameLen = qstrlen(blk.name);
6455 if (qstrncmp(p+len,blk.name,blkNameLen)==0 && // matching marker name
6456 qstrncmp(p+len+blkNameLen,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6457 {
6458 //printf("Found end marker %s enabled=%d negate=%d\n",blk.name,blk.enabled,negate);
6459 return p+len+blkNameLen+markerInfo.closeLen;
6460 }
6461 else // not the right marker id
6462 {
6463 p++;
6464 }
6465 }
6466 else // not and end marker
6467 {
6468 p++;
6469 }
6470 }
6471 return p;
6472 };
6473
6474 QCString result;
6475 result.reserve(s.length());
6476 const char *p = s.data();
6477 char c = 0;
6478 while ((c=*p))
6479 {
6480 if (c==markerInfo.markerChar) // potential start of marker
6481 {
6482 if (qstrncmp(p,markerInfo.beginStr,markerInfo.beginLen)==0) // start of begin marker
6483 {
6484 bool found = false;
6485 size_t len = markerInfo.beginLen;
6486 bool negate = *(p+len)=='!';
6487 if (negate) len++;
6488 for (const auto &blk : blockList)
6489 {
6490 size_t blkNameLen = qstrlen(blk.name);
6491 if (qstrncmp(p+len,blk.name,blkNameLen)==0 && // matching marker name
6492 qstrncmp(p+len+blkNameLen,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6493 {
6494 bool blockEnabled = blk.enabled!=negate;
6495 //printf("Found start marker %s enabled=%d negate=%d\n",blk.name,blk.enabled,negate);
6496 p+=len+blkNameLen+markerInfo.closeLen;
6497 if (!blockEnabled) // skip until the end of the block
6498 {
6499 //printf("skipping block\n");
6500 p=skipBlock(p,blk);
6501 }
6502 found=true;
6503 break;
6504 }
6505 }
6506 if (!found) // unknown marker id
6507 {
6508 result+=c;
6509 p++;
6510 }
6511 }
6512 else if (qstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // start of end marker
6513 {
6514 bool found = false;
6515 size_t len = markerInfo.endLen;
6516 bool negate = *(p+len)=='!';
6517 if (negate) len++;
6518 for (const auto &blk : blockList)
6519 {
6520 size_t blkNameLen = qstrlen(blk.name);
6521 if (qstrncmp(p+len,blk.name,blkNameLen)==0 && // matching marker name
6522 qstrncmp(p+len+blkNameLen,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6523 {
6524 //printf("Found end marker %s enabled=%d negate=%d\n",blk.name,blk.enabled,negate);
6525 p+=len+blkNameLen+markerInfo.closeLen;
6526 found=true;
6527 break;
6528 }
6529 }
6530 if (!found) // unknown marker id
6531 {
6532 result+=c;
6533 p++;
6534 }
6535 }
6536 else // not a start or end marker
6537 {
6538 result+=c;
6539 p++;
6540 }
6541 }
6542 else // not a marker character
6543 {
6544 result+=c;
6545 p++;
6546 }
6547 }
6548 //printf("====\n%s\n-----\n%s\n~~~~\n",qPrint(s),qPrint(result));
6549 return result;
6550}
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().

◆ showDate()

QCString showDate ( const QCString & fmt)
static

Definition at line 3138 of file util.cpp.

3139{
3140 // get the current date and time
3141 std::tm dat{};
3142 int specFormat=0;
3143 QCString specDate = "";
3144 QCString err = dateTimeFromString(specDate,dat,specFormat);
3145
3146 // do the conversion
3147 int usedFormat=0;
3148 return formatDateTime(fmt,dat,usedFormat);
3149}
QCString formatDateTime(const QCString &format, const std::tm &dt, int &formatUsed)
Return a string representation for a given std::tm value that is formatted according to the pattern g...
Definition datetime.cpp:174
QCString dateTimeFromString(const QCString &spec, std::tm &dt, int &format)
Returns the filled in std::tm for a given string representing a date and/or time.
Definition datetime.cpp:133
Definition message.h:144

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

Referenced by substituteKeywords().

◆ showFileDefMatches()

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

Definition at line 3029 of file util.cpp.

3030{
3031 QCString result;
3032 QCString name=Dir::cleanDirPath(n.str());
3033 QCString path;
3034 int slashPos=std::max(name.findRev('/'),name.findRev('\\'));
3035 if (slashPos!=-1)
3036 {
3037 path=removeLongPathMarker(name.left(slashPos+1));
3038 name=name.right(name.length()-slashPos-1);
3039 }
3040 const FileName *fn=fnMap->find(name);
3041 if (fn)
3042 {
3043 bool first = true;
3044 QCString pathStripped = stripFromIncludePath(path);
3045 for (const auto &fd_p : *fn)
3046 {
3047 FileDef *fd = fd_p.get();
3048 QCString fdStripPath = stripFromIncludePath(fd->getPath());
3049 if (path.isEmpty() ||
3050 (!pathStripped.isEmpty() && fdStripPath.endsWith(pathStripped)) ||
3051 (pathStripped.isEmpty() && fdStripPath.isEmpty()))
3052 {
3053 if (!first) result += "\n";
3054 else first = false;
3055 result+=" "+fd->absFilePath();
3056 }
3057 }
3058
3059 }
3060 return result;
3061}

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

Referenced by addIncludeFile(), buildFileList(), DocParser::findAndCopyImage(), DocDiaFile::parse(), DocDotFile::parse(), DocMermaidFile::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 6665 of file util.cpp.

6666{
6667 StringVector result;
6668 reg::Iterator iter(s, delimiter);
6670 size_t p=0;
6671 for ( ; iter != end; ++iter)
6672 {
6673 const auto &match = *iter;
6674 size_t i=match.position();
6675 size_t l=match.length();
6676 if (i>p) result.push_back(s.substr(p,i-p));
6677 p=i+l;
6678 }
6679 if (p<s.length()) result.push_back(s.substr(p));
6680 return result;
6681}

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

6649{
6650 StringVector result;
6651 size_t prev = 0, pos = 0, len = s.length();
6652 do
6653 {
6654 pos = s.find(delimiter, prev);
6655 if (pos == std::string::npos) pos = len;
6656 if (pos>prev) result.push_back(s.substr(prev,pos-prev));
6657 prev = pos + delimiter.length();
6658 }
6659 while (pos<len && prev<len);
6660 return result;
6661}

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

5497{
5498#ifdef TRACINGSUPPORT
5499 void *backtraceFrames[128];
5500 int frameCount = backtrace(backtraceFrames, 128);
5501 const size_t cmdLen = 40960;
5502 static char cmd[cmdLen];
5503 char *p = cmd;
5504 p += qsnprintf(p,cmdLen,"/usr/bin/atos -p %d ", (int)getpid());
5505 for (int x = 0; x < frameCount; x++)
5506 {
5507 p += qsnprintf(p,cmdLen,"%p ", backtraceFrames[x]);
5508 }
5509 fprintf(stderr,"========== STACKTRACE START ==============\n");
5510 if (FILE *fp = Portable::popen(cmd, "r"))
5511 {
5512 char resBuf[512];
5513 while (size_t len = fread(resBuf, 1, sizeof(resBuf), fp))
5514 {
5515 fwrite(resBuf, 1, len, stderr);
5516 }
5517 Portable::pclose(fp);
5518 }
5519 fprintf(stderr,"============ STACKTRACE END ==============\n");
5520 //fprintf(stderr,"%s\n", frameStrings[x]);
5521#endif
5522}

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

◆ stripAnonymousNamespaceScope()

QCString stripAnonymousNamespaceScope ( const QCString & s)

Definition at line 230 of file util.cpp.

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

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

◆ stripDeclKeywords()

QCString stripDeclKeywords ( const QCString & s)
static

Definition at line 1623 of file util.cpp.

1624{
1625 int i=s.find(" class ");
1626 if (i!=-1) return s.left(i)+s.mid(i+6);
1627 i=s.find(" typename ");
1628 if (i!=-1) return s.left(i)+s.mid(i+9);
1629 i=s.find(" union ");
1630 if (i!=-1) return s.left(i)+s.mid(i+6);
1631 i=s.find(" struct ");
1632 if (i!=-1) return s.left(i)+s.mid(i+7);
1633 return s;
1634}

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

Referenced by getCanonicalTypeForIdentifier().

◆ stripExtension()

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

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

References Config_getList, and stripFromPath().

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

◆ stripFromPath() [1/2]

QCString stripFromPath ( const QCString & p,
const StringVector & l )
static

Definition at line 298 of file util.cpp.

299{
300 // look at all the strings in the list and strip the longest match
301 QCString potential;
303 size_t length = 0;
304 for (const auto &s : l)
305 {
306 QCString prefix = s;
307 if (prefix.length() > length &&
308 qstricmp(path.left(prefix.length()),prefix)==0) // case insensitive compare
309 {
310 length = prefix.length();
311 potential = path.right(path.length()-prefix.length());
312 }
313 }
314 if (length>0) return potential;
315 return path;
316}
int qstricmp(const char *s1, const char *s2)
Definition qcstring.cpp:530

References QCString::left(), QCString::length(), prefix, qstricmp(), removeLongPathMarker(), and QCString::right().

Referenced by Config::checkAndCorrect(), DirDefImpl::DirDefImpl(), FileDefImpl::FileDefImpl(), generateAnonymousAnchor(), generateXMLForClass(), generateXMLForConcept(), generateXMLForDir(), generateXMLForFile(), generateXMLForMember(), generateXMLForModule(), generateXMLForNamespace(), generateXMLForPage(), generateXMLForRequirement(), generateXMLForRequirements(), handleFileInfoResult(), insertPath(), markdownFileNameToId(), MarkdownOutlineParser::parseInput(), ModuleManager::resolveImports(), ClassDefImpl::showUsedFiles(), stripFromIncludePath(), stripFromPath(), ModuleDefImpl::writeFiles(), writeSingleFileIndex(), DirDefImpl::writeTagFile(), FileDefImpl::writeTagFile(), and GroupDefImpl::writeTagFile().

◆ stripFromPath() [2/2]

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

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

References Config_getList, and stripFromPath().

◆ stripIndentation()

QCString stripIndentation ( const QCString & s,
bool skipFirstLine )

Definition at line 5979 of file util.cpp.

5980{
5981 if (s.isEmpty()) return s; // empty string -> we're done
5982
5983 //printf("stripIndentation:\n%s\n------\n",qPrint(s));
5984 // compute minimum indentation over all lines
5985 const char *p=s.data();
5986 char c=0;
5987 int indent=0;
5988 int minIndent=1000000; // "infinite"
5989 bool searchIndent=true;
5990 int tabSize=Config_getInt(TAB_SIZE);
5991 bool skipFirst = skipFirstLine;
5992 while ((c=*p++))
5993 {
5994 if (c=='\t') { indent+=tabSize - (indent%tabSize); }
5995 else if (c=='\n') { indent=0; searchIndent=true; skipFirst=false; }
5996 else if (c==' ') { indent++; }
5997 else if (searchIndent && !skipFirst)
5998 {
5999 searchIndent=false;
6000 if (indent<minIndent) minIndent=indent;
6001 }
6002 }
6003
6004 // no indent to remove -> we're done
6005 if (minIndent==0) return substitute(s,"@ilinebr","\\ilinebr");
6006
6007 // remove minimum indentation for each line
6008 TextStream result;
6009 p=s.data();
6010 indent=0;
6011 skipFirst=skipFirstLine;
6012 while ((c=*p++))
6013 {
6014 if (c=='\n') // start of new line
6015 {
6016 indent=0;
6017 result << c;
6018 skipFirst=false;
6019 }
6020 else if (indent<minIndent && !skipFirst) // skip until we reach minIndent
6021 {
6022 if (c=='\t')
6023 {
6024 int newIndent = indent+tabSize-(indent%tabSize);
6025 int i=newIndent;
6026 while (i>minIndent) // if a tab crosses the minIndent boundary fill the rest with spaces
6027 {
6028 result << ' ';
6029 i--;
6030 }
6031 indent=newIndent;
6032 }
6033 else // space
6034 {
6035 indent++;
6036 }
6037 }
6038 else if (c=='\\' && literal_at(p,"ilinebr "))
6039 // we also need to remove the indentation after a \ilinebr command at the end of a line
6040 {
6041 result << "\\ilinebr ";
6042 p+=8;
6043 int skipAmount=0;
6044 for (int j=0;j<minIndent;j++) if (*(p+j)==' ') skipAmount++; // test to see if we have the indent
6045 if (skipAmount==minIndent)
6046 {
6047 p+=skipAmount; // remove the indent
6048 }
6049 }
6050 else if (c=='@' && literal_at(p,"ilinebr"))
6051 {
6052 result << "\\ilinebr";
6053 p+=7;
6054 }
6055 else // copy anything until the end of the line
6056 {
6057 result << c;
6058 }
6059 }
6060
6061 //printf("stripIndentation: result=\n%s\n------\n",qPrint(result.str()));
6062
6063 return result.str();
6064}

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,
bool skipFirstLine )

Definition at line 6068 of file util.cpp.

6069{
6070 //printf("stripIndentationVerbatim(level=%d):\n%s\n------\n",indentationLevel,qPrint(doc));
6071 if (indentationLevel <= 0 || doc.isEmpty()) return; // nothing to strip
6072
6073 // by stripping content the string will only become shorter so we write the results
6074 // back into the input string and then resize it at the end.
6075 char c = 0;
6076 const char *src = doc.data();
6077 char *dst = doc.rawData();
6078 bool insideIndent = !skipFirstLine; // skip the initial line from stripping
6079 int cnt = 0;
6080 if (!skipFirstLine) cnt = indentationLevel;
6081 while ((c=*src++))
6082 {
6083 // invariant: dst<=src
6084 switch(c)
6085 {
6086 case '\n':
6087 *dst++ = c;
6088 insideIndent = true;
6089 cnt = indentationLevel;
6090 break;
6091 case ' ':
6092 if (insideIndent)
6093 {
6094 if (cnt>0) // count down the spacing until the end of the indent
6095 {
6096 cnt--;
6097 }
6098 else // reached the end of the indent, start of the part of the line to keep
6099 {
6100 insideIndent = false;
6101 *dst++ = c;
6102 }
6103 }
6104 else // part after indent, copy to the output
6105 {
6106 *dst++ = c;
6107 }
6108 break;
6109 default:
6110 insideIndent = false;
6111 *dst++ = c;
6112 break;
6113 }
6114 }
6115 doc.resize(static_cast<uint32_t>(dst-doc.data()));
6116 //printf("stripIndentationVerbatim: result=\n%s\n------\n",qPrint(doc));
6117}
char * rawData()
Returns a writable pointer to the data.
Definition qcstring.h:178
void resize(size_t newlen)
Definition qcstring.h:180

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

Referenced by MemberDefImpl::setInitializer().

◆ stripIrrelevantConstVolatile()

void stripIrrelevantConstVolatile ( QCString & s,
bool insideTemplate )

According to the C++ spec and Ivan Vecerina:

Parameter declarations that differ only in the presence or absence of const and/or volatile are equivalent.

So the following example, show what is stripped by this routine for const. The same is done for volatile.

For Java code we also strip the "final" keyword, see bug 765070.

const T param -> T param // not relevant
const T& param -> const T& param // const needed
T* const param -> T* param // not relevant
const T* param -> const T* param // const needed

Definition at line 1613 of file util.cpp.

1614{
1615 //printf("stripIrrelevantConstVolatile(%s)=",qPrint(s));
1616 stripIrrelevantString(s,"const",insideTemplate);
1617 stripIrrelevantString(s,"volatile",insideTemplate);
1618 stripIrrelevantString(s,"final",insideTemplate);
1619 //printf("%s\n",qPrint(s));
1620}
static void stripIrrelevantString(QCString &target, const QCString &str, bool insideTemplate)
Definition util.cpp:1553

References stripIrrelevantString().

Referenced by extractCanonicalType(), and matchArgument2().

◆ stripIrrelevantString()

void stripIrrelevantString ( QCString & target,
const QCString & str,
bool insideTemplate )
static

Definition at line 1553 of file util.cpp.

1554{
1555 AUTO_TRACE("target='{}' str='{}'",target,str);
1556 if (target==str) { target.clear(); return; }
1557 int i=0,p=0;
1558 int l=static_cast<int>(str.length());
1559 bool changed=false;
1560 int sharpCount=0;
1561 while ((i=target.find(str,p))!=-1)
1562 {
1563 for (int q=p;q<i;q++)
1564 {
1565 if (target[q]=='<') sharpCount++;
1566 else if (target[q]=='>' && sharpCount>0) sharpCount--;
1567 }
1568 bool isMatch = (i==0 || !isId(target.at(i-1))) && // not a character before str
1569 (i+l==static_cast<int>(target.length()) || !isId(target.at(i+l))) && // not a character after str
1570 !insideTemplate && sharpCount==0; // not inside template, because e.g. <const A> is different than <A>, see issue #11663
1571 if (isMatch)
1572 {
1573 int i1=target.find('*',i+l);
1574 int i2=target.find('&',i+l);
1575 if (i1==-1 && i2==-1)
1576 {
1577 // strip str from target at index i
1578 target=target.left(i)+target.right(target.length()-i-l);
1579 changed=true;
1580 i-=l;
1581 }
1582 else if ((i1!=-1 && i<i1) || (i2!=-1 && i<i2)) // str before * or &
1583 {
1584 // move str to front
1585 target=str+" "+target.left(i)+target.right(target.length()-i-l);
1586 changed=true;
1587 i++;
1588 }
1589 }
1590 p = i+l;
1591 }
1592 if (changed) target=target.stripWhiteSpace();
1593 AUTO_TRACE_EXIT("target='{}'",target,str);
1594}

References QCString::at(), AUTO_TRACE, AUTO_TRACE_EXIT, QCString::clear(), QCString::find(), isId(), QCString::left(), QCString::length(), QCString::right(), and QCString::stripWhiteSpace().

Referenced by stripIrrelevantConstVolatile().

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

5041{
5042 if (s.isEmpty()) return QCString();
5043 const char *p = s.data();
5044
5045 // search for leading empty lines
5046 int i=0,li=-1,l=static_cast<int>(s.length());
5047 char c = 0;
5048 while ((c=*p))
5049 {
5050 if (c==' ' || c=='\t' || c=='\r') { i++; p++; }
5051 else if (c=='\\' && literal_at(p,"\\ilinebr")) { i+=8; li=i; p+=8; }
5052 else if (c=='\n') { i++; li=i; docLine++; p++; }
5053 else break;
5054 }
5055
5056 // search for trailing empty lines
5057 int b=l-1,bi=-1;
5058 p=s.data()+b;
5059 while (b>=0)
5060 {
5061 c=*p;
5062 if (c==' ' || c=='\t' || c=='\r') { b--; p--; }
5063 else if (c=='r' && b>=7 && literal_at(p-7,"\\ilinebr")) { bi=b-7; b-=8; p-=8; }
5064 else if (c=='>' && b>=11 && literal_at(p-11,"\\ilinebr<br>")) { bi=b-11; b-=12; p-=12; }
5065 else if (c=='\n') { bi=b; b--; p--; }
5066 else break;
5067 }
5068
5069 // return whole string if no leading or trailing lines where found
5070 if (li==-1 && bi==-1) return s;
5071
5072 // return substring
5073 if (bi==-1) bi=l;
5074 if (li==-1) li=0;
5075 if (bi<=li) return QCString(); // only empty lines
5076 //printf("docLine='%s' len=%d li=%d bi=%d\n",qPrint(s),s.length(),li,bi);
5077 return s.mid(li,bi-li);
5078}

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

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

◆ stripPath()

QCString stripPath ( const QCString & s)

Definition at line 4959 of file util.cpp.

4960{
4961 QCString result=s;
4962 int i=result.findRev('/');
4963 if (i!=-1)
4964 {
4965 result=result.mid(i+1);
4966 }
4967 i=result.findRev('\\');
4968 if (i!=-1)
4969 {
4970 result=result.mid(i+1);
4971 }
4972 return result;
4973}

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

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

◆ stripScope()

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

3791{
3792 QCString result = name;
3793 int l = static_cast<int>(result.length());
3794 int p = 0;
3795 bool done = FALSE;
3796 bool skipBracket=FALSE; // if brackets do not match properly, ignore them altogether
3797 int count=0;
3798 int round=0;
3799
3800 do
3801 {
3802 p=l-1; // start at the end of the string
3803 while (p>=0 && count>=0)
3804 {
3805 char c=result.at(p);
3806 switch (c)
3807 {
3808 case ':':
3809 // only exit in the case of ::
3810 //printf("stripScope(%s)=%s\n",name,qPrint(result.right(l-p-1)));
3811 if (p>0 && result.at(p-1)==':' && (count==0 || skipBracket))
3812 {
3813 return result.right(l-p-1);
3814 }
3815 p--;
3816 break;
3817 case '>':
3818 if (skipBracket) // we don't care about brackets
3819 {
3820 p--;
3821 }
3822 else // count open/close brackets
3823 {
3824 if (p>0 && result.at(p-1)=='>') // skip >> operator
3825 {
3826 p-=2;
3827 break;
3828 }
3829 count=1;
3830 //printf("pos < = %d\n",p);
3831 p--;
3832 bool foundMatch=false;
3833 while (p>=0 && !foundMatch)
3834 {
3835 c=result.at(p--);
3836 switch (c)
3837 {
3838 case ')':
3839 round++;
3840 break;
3841 case '(':
3842 round--;
3843 break;
3844 case '>': // ignore > inside (...) to support e.g. (sizeof(T)>0) inside template parameters
3845 if (round==0) count++;
3846 break;
3847 case '<':
3848 if (round==0)
3849 {
3850 if (p>0)
3851 {
3852 if (result.at(p-1) == '<') // skip << operator
3853 {
3854 p--;
3855 break;
3856 }
3857 }
3858 count--;
3859 foundMatch = count==0;
3860 }
3861 break;
3862 default:
3863 //printf("c=%c count=%d\n",c,count);
3864 break;
3865 }
3866 }
3867 }
3868 //printf("pos > = %d\n",p+1);
3869 break;
3870 default:
3871 p--;
3872 }
3873 }
3874 done = count==0 || skipBracket; // reparse if brackets do not match
3875 skipBracket=TRUE;
3876 }
3877 while (!done); // if < > unbalanced repeat ignoring them
3878 //printf("stripScope(%s)=%s\n",name,name);
3879 return name;
3880}

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

4543{
4544 //printf("stripTemplateSpecifiersFromScope(name=%s,scopeName=%s)\n",qPrint(fullName),qPrint(scopeName));
4545 int i=fullName.find('<');
4546 if (i==-1) return fullName;
4547 QCString result;
4548 int p=0;
4549 int l=static_cast<int>(fullName.length());
4550 while (i!=-1)
4551 {
4552 //printf("1:result+=%s\n",qPrint(fullName.mid(p,i-p)));
4553 int e=i+1;
4554 int count=1;
4555 int round=0;
4556 while (e<l && count>0)
4557 {
4558 char c=fullName.at(e++);
4559 switch (c)
4560 {
4561 case '(': round++; break;
4562 case ')': if (round>0) round--; break;
4563 case '<': if (round==0) count++; break;
4564 case '>': if (round==0) count--; break;
4565 default:
4566 break;
4567 }
4568 }
4569 int si= fullName.find("::",e);
4570
4571 if (parentOnly && si==-1) break;
4572 // we only do the parent scope, so we stop here if needed
4573
4574 result+=fullName.mid(p,i-p);
4575 //printf(" trying %s\n",qPrint(mergeScopes(scopeName,result+fullName.mid(i,e-i))));
4576 ClassDef *cd = getClass(mergeScopes(scopeName,result+fullName.mid(i,e-i)));
4577 if (cd!=nullptr && (allowArtificial || !cd->isArtificial()))
4578 {
4579 result+=fullName.mid(i,e-i);
4580 //printf(" 2:result+=%s\n",qPrint(fullName.mid(i,e-i-1)));
4581 }
4582 else if (pLastScopeStripped)
4583 {
4584 //printf(" last stripped scope '%s'\n",qPrint(fullName.mid(i,e-i)));
4585 *pLastScopeStripped=fullName.mid(i,e-i);
4586 }
4587 p=e;
4588 i=fullName.find('<',p);
4589 }
4590 result+=fullName.right(l-p);
4591 //printf("3:result+=%s\n",qPrint(fullName.right(l-p)));
4592 //printf("end result=%s\n",qPrint(result));
4593 return result;
4594}
virtual bool isArtificial() const =0
QCString mergeScopes(const QCString &leftScope, const QCString &rightScope)
Definition util.cpp:4605

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

◆ substituteKeywords() [1/2]

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

Definition at line 3065 of file util.cpp.

3066{
3067 std::string substRes;
3068 int line = 1;
3069 const char *p = s.data();
3070 if (p)
3071 {
3072 // reserve some room for expansion
3073 substRes.reserve(s.length()+1024);
3074 char c = 0;
3075 while ((c=*p))
3076 {
3077 bool found = false;
3078 if (c=='$')
3079 {
3080 for (const auto &kw : keywords)
3081 {
3082 size_t keyLen = qstrlen(kw.keyword);
3083 if (qstrncmp(p,kw.keyword,keyLen)==0)
3084 {
3085 const char *startArg = p+keyLen;
3086 bool expectParam = std::holds_alternative<KeywordSubstitution::GetValueWithParam>(kw.getValueVariant);
3087 //printf("%s: expectParam=%d *startArg=%c\n",kw.keyword,expectParam,*startArg);
3088 if (expectParam && *startArg=='(') // $key(value)
3089 {
3090 size_t j=1;
3091 const char *endArg = nullptr;
3092 while ((c=*(startArg+j)) && c!=')' && c!='\n' && c!=0) j++;
3093 if (c==')') endArg=startArg+j;
3094 if (endArg)
3095 {
3096 QCString value = QCString(startArg+1).left(endArg-startArg-1);
3097 auto &&getValue = std::get<KeywordSubstitution::GetValueWithParam>(kw.getValueVariant);
3098 substRes+=getValue(value).str();
3099 p=endArg+1;
3100 //printf("found '%s'->'%s'\n",kw.keyword,qPrint(getValue(value)));
3101 }
3102 else
3103 {
3104 //printf("missing argument\n");
3105 warn(file,line,"Missing argument for '{}'",kw.keyword);
3106 p+=keyLen;
3107 }
3108 }
3109 else if (!expectParam) // $key
3110 {
3111 auto &&getValue = std::get<KeywordSubstitution::GetValue>(kw.getValueVariant);
3112 substRes+=getValue().str();
3113 //printf("found '%s'->'%s'\n",kw.keyword,qPrint(getValue()));
3114 p+=keyLen;
3115 }
3116 else
3117 {
3118 //printf("%s %d Expected arguments, none specified '%s'\n",qPrint(file), line, qPrint(kw.keyword));
3119 warn(file,line,"Expected arguments for '{}' but none were specified",kw.keyword);
3120 p+=keyLen;
3121 }
3122 found = true;
3123 break;
3124 }
3125 }
3126 }
3127 if (!found) // copy
3128 {
3129 if (c=='\n') line++;
3130 substRes+=c;
3131 p++;
3132 }
3133 }
3134 }
3135 return substRes;
3136}

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

3219{
3220 return substituteKeywords(file,s,
3221 {
3222 // keyword value getter
3223 { "$title", [&]() { return !title.isEmpty() ? title : projName; } },
3224 { "$doxygenversion", [&]() { return getDoxygenVersion(); } },
3225 { "$projectname", [&]() { return projName; } },
3226 { "$projectnumber", [&]() { return projNum; } },
3227 { "$projectbrief", [&]() { return projBrief; } },
3228 { "$projectlogo", [&]() { return stripPath(projectLogoFile()); } },
3229 { "$logosize", [&]() { return projectLogoSize(); } },
3230 { "$projecticon", [&]() { return stripPath(Config_getString(PROJECT_ICON)); } },
3231 { "$langISO", [&]() { return theTranslator->trISOLang(); } },
3232 { "$showdate", [&](const QCString &fmt) { return showDate(fmt); } }
3233 });
3234}
QCString substituteKeywords(const QCString &file, const QCString &s, const KeywordSubstitutionList &keywords)
Definition util.cpp:3065
QCString projectLogoFile()
Definition util.cpp:3151
static QCString projectLogoSize()
Definition util.cpp:3172
static QCString showDate(const QCString &fmt)
Definition util.cpp:3138

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

4380{
4381 AUTO_TRACE("name={} formalArgs={} actualArgs={}",nm,argListToString(formalArgs),actualArgs ? argListToString(*actualArgs) : QCString());
4382 if (formalArgs.empty()) return nm;
4383 QCString result;
4384
4385 static const reg::Ex re(R"(\a\w*)");
4386 std::string name = nm.str();
4387 reg::Iterator it(name,re);
4389 size_t p=0;
4390
4391 for (; it!=end ; ++it)
4392 {
4393 const auto &match = *it;
4394 size_t i = match.position();
4395 size_t l = match.length();
4396 if (i>p) result += name.substr(p,i-p);
4397 QCString n(match.str());
4399 if (actualArgs)
4400 {
4401 actIt = actualArgs->begin();
4402 }
4403 //printf(": name=%s\n",qPrint(name));
4404
4405 // if n is a template argument, then we substitute it
4406 // for its template instance argument.
4407 bool found=FALSE;
4408 for (auto formIt = formalArgs.begin();
4409 formIt!=formalArgs.end() && !found;
4410 ++formIt
4411 )
4412 {
4413 Argument formArg = *formIt;
4414 Argument actArg;
4415 if (actualArgs && actIt!=actualArgs->end())
4416 {
4417 actArg = *actIt;
4418 }
4419 if (formArg.type.startsWith("class ") && formArg.name.isEmpty())
4420 {
4421 formArg.name = formArg.type.mid(6);
4422 formArg.type = "class";
4423 }
4424 else if (formArg.type.startsWith("typename ") && formArg.name.isEmpty())
4425 {
4426 formArg.name = formArg.type.mid(9);
4427 formArg.type = "typename";
4428 }
4429 else if (formArg.type.startsWith("class...")) // match 'class... name' to 'name...'
4430 {
4431 formArg.name += "...";
4432 formArg.type = formArg.type.left(5)+formArg.type.mid(8);
4433 }
4434 else if (formArg.type.startsWith("typename...")) // match 'typename... name' to 'name...'
4435 {
4436 formArg.name += "...";
4437 formArg.type = formArg.type.left(8)+formArg.type.mid(11);
4438 }
4439 //printf(": n=%s formArg->type='%s' formArg->name='%s' formArg->defval='%s' actArg->type='%s' actArg->name='%s' \n",
4440 // qPrint(n),qPrint(formArg.type),qPrint(formArg.name),qPrint(formArg.defval),qPrint(actArg.type),qPrint(actArg.name));
4441 if (formArg.type=="class" || formArg.type=="typename" || formArg.type.startsWith("template"))
4442 {
4443 if (formArg.name==n && actualArgs && actIt!=actualArgs->end() && !actArg.type.isEmpty()) // base class is a template argument
4444 {
4445 static constexpr auto hasRecursion = [](const QCString &prefix,const QCString &nameArg,const QCString &subst) -> bool
4446 {
4447 int ii=0;
4448 int pp=0;
4449
4450 ii = subst.find('<');
4451 //printf("prefix='%s' subst='%s'\n",qPrint(prefix.mid(prefix.length()-ii-2,ii+1)),qPrint(subst.left(ii+1)));
4452 if (ii!=-1 && static_cast<int>(prefix.length())>=ii+2 && prefix.mid(prefix.length()-ii-2,ii+1)==subst.left(ii+1))
4453 {
4454 return true; // don't replace 'A< ' with 'A< A<...', see issue #10951
4455 }
4456
4457 while ((ii=subst.find(nameArg,pp))!=-1)
4458 {
4459 bool beforeNonWord = ii==0 || !isId(subst.at(ii-1));
4460 bool afterNonWord = subst.length()==ii+nameArg.length() || !isId(subst.at(ii+nameArg.length()));
4461 if (beforeNonWord && afterNonWord)
4462 {
4463 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
4464 }
4465 pp=ii+static_cast<int>(nameArg.length());
4466 }
4467 return false;
4468 };
4469 // replace formal argument with the actual argument of the instance
4470 AUTO_TRACE_ADD("result={} n={} type={} hasRecursion={}",result,n,actArg.type,hasRecursion(result,n,actArg.type));
4471 if (!hasRecursion(result,n,actArg.type))
4472 // the scope guard is to prevent recursive lockup for
4473 // template<class A> class C : public<A::T>,
4474 // where A::T would become A::T::T here,
4475 // since n==A and actArg->type==A::T
4476 // see bug595833 for an example
4477 //
4478 // Also prevent recursive substitution if n is part of actArg.type, i.e.
4479 // n='A' in argType='S< A >' would produce 'S< S< A > >'
4480 {
4481 if (actArg.name.isEmpty())
4482 {
4483 result += actArg.type;
4484 }
4485 else
4486 // for case where the actual arg is something like "unsigned int"
4487 // the "int" part is in actArg->name.
4488 {
4489 result += actArg.type+" "+actArg.name;
4490 }
4491 found=TRUE;
4492 }
4493 }
4494 else if (formArg.name==n &&
4495 (actualArgs==nullptr || actIt==actualArgs->end()) &&
4496 !formArg.defval.isEmpty() &&
4497 formArg.defval!=nm /* to prevent recursion */
4498 )
4499 {
4500 result += substituteTemplateArgumentsInString(formArg.defval,formalArgs,actualArgs);
4501 found=TRUE;
4502 }
4503 }
4504 else if (formArg.name==n &&
4505 (actualArgs==nullptr || actIt==actualArgs->end()) &&
4506 !formArg.defval.isEmpty() &&
4507 formArg.defval!=nm /* to prevent recursion */
4508 )
4509 {
4510 result += substituteTemplateArgumentsInString(formArg.defval,formalArgs,actualArgs);
4511 found=TRUE;
4512 }
4513 if (actualArgs && actIt!=actualArgs->end())
4514 {
4515 actIt++;
4516 }
4517 }
4518 if (!found)
4519 {
4520 result += n;
4521 }
4522 p=i+l;
4523 }
4524 result+=name.substr(p);
4525 result=result.simplifyWhiteSpace();
4526 AUTO_TRACE_EXIT("result={}",result);
4527 return result.stripWhiteSpace();
4528}
typename Vec::const_iterator const_iterator
Definition arguments.h:69
QCString substituteTemplateArgumentsInString(const QCString &nm, const ArgumentList &formalArgs, const ArgumentList *actualArgs)
Definition util.cpp:4376

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

Definition at line 1299 of file util.cpp.

1300{
1301 QCString result;
1302 if (al.empty()) return result;
1303 result="<";
1304 bool first=true;
1305 for (const auto &a : al)
1306 {
1307 if (a.defval.isEmpty() || includeDefault)
1308 {
1309 if (!first) result+=", ";
1310 if (!a.name.isEmpty()) // add template argument name
1311 {
1312 if (lang==SrcLangExt::Java || lang==SrcLangExt::CSharp)
1313 {
1314 result+=a.type+" ";
1315 }
1316 result+=a.name;
1317 }
1318 else // extract name from type
1319 {
1320 int i = static_cast<int>(a.type.length())-1;
1321 while (i>=0 && isId(a.type.at(i))) i--;
1322 if (i>0)
1323 {
1324 result+=a.type.right(a.type.length()-i-1);
1325 if (a.type.find("...")!=-1)
1326 {
1327 result+="...";
1328 }
1329 }
1330 else // nothing found -> take whole name
1331 {
1332 result+=a.type;
1333 }
1334 }
1335 if (!a.typeConstraint.isEmpty() && lang==SrcLangExt::Java)
1336 {
1337 result+=" extends "; // TODO: now Java specific, C# has where...
1338 result+=a.typeConstraint;
1339 }
1340 first=false;
1341 }
1342 }
1343 result+=">";
1344 return removeRedundantWhiteSpace(result);
1345}

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

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

◆ transcodeCharacterBuffer()

void transcodeCharacterBuffer ( const QCString & fileName,
std::string & contents,
const QCString & inputEncoding,
const QCString & outputEncoding )
static

Definition at line 5524 of file util.cpp.

5526{
5527 if (inputEncoding.isEmpty() || outputEncoding.isEmpty()) return; // no encoding specified
5528 if (qstricmp(inputEncoding,outputEncoding)==0) return; // input encoding same as output encoding
5529 void *cd = portable_iconv_open(outputEncoding.data(),inputEncoding.data());
5530 if (cd==reinterpret_cast<void *>(-1))
5531 {
5532 term("unsupported character conversion: '{}'->'{}': {}\n"
5533 "Check the INPUT_ENCODING setting in the config file!\n",
5534 inputEncoding,outputEncoding,strerror(errno));
5535 }
5536 size_t iLeft = contents.size();
5537 const char *srcPtr = contents.data();
5538 size_t tmpBufSize = contents.size()*4+1;
5539 size_t oLeft = tmpBufSize;
5540 std::string tmpBuf;
5541 tmpBuf.resize(tmpBufSize);
5542 char *dstPtr = tmpBuf.data();
5543 size_t newSize=0;
5544 if (!portable_iconv(cd, &srcPtr, &iLeft, &dstPtr, &oLeft))
5545 {
5546 newSize = tmpBufSize-oLeft;
5547 tmpBuf.resize(newSize);
5548 std::swap(contents,tmpBuf);
5549 //printf("iconv: input size=%d output size=%d\n[%s]\n",size,newSize,qPrint(srcBuf));
5550 }
5551 else
5552 {
5553 term("{}: failed to translate characters from {} to {}: check INPUT_ENCODING\n",
5554 fileName,inputEncoding,outputEncoding);
5555 }
5557}
int portable_iconv_close(void *cd)
size_t portable_iconv(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)
void * portable_iconv_open(const char *tocode, const char *fromcode)

References QCString::data(), QCString::isEmpty(), portable_iconv(), portable_iconv_close(), portable_iconv_open(), qstricmp(), and term.

Referenced by readInputFile().

◆ transcodeCharacterStringToUTF8()

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

Definition at line 1456 of file util.cpp.

1457{
1458 const char *outputEncoding = "UTF-8";
1459 if (inputEncoding==nullptr || qstricmp(inputEncoding,outputEncoding)==0) return true;
1460 size_t inputSize=input.length();
1461 size_t outputSize=inputSize*4;
1462 QCString output(outputSize, QCString::ExplicitSize);
1463 void *cd = portable_iconv_open(outputEncoding,inputEncoding);
1464 if (cd==reinterpret_cast<void *>(-1))
1465 {
1466 return false;
1467 }
1468 bool ok=true;
1469 size_t iLeft=inputSize;
1470 size_t oLeft=outputSize;
1471 const char *inputPtr = input.data();
1472 char *outputPtr = output.rawData();
1473 if (!portable_iconv(cd, &inputPtr, &iLeft, &outputPtr, &oLeft))
1474 {
1475 outputSize-=static_cast<int>(oLeft);
1476 output.resize(outputSize);
1477 output.at(outputSize)='\0';
1478 // replace input
1479 input=output.str();
1480 //printf("iconv: input size=%d output size=%d\n[%s]\n",size,newSize,qPrint(srcBuf));
1481 }
1482 else
1483 {
1484 ok=false;
1485 }
1487 return ok;
1488}
@ ExplicitSize
Definition qcstring.h:146

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

◆ trimBaseClassScope()

void trimBaseClassScope ( const BaseClassList & bcl,
QCString & s,
int level = 0 )

Definition at line 1531 of file util.cpp.

1532{
1533 //printf("trimBaseClassScope level=%d '%s'\n",level,qPrint(s));
1534 for (const auto &bcd : bcl)
1535 {
1536 ClassDef *cd=bcd.classDef;
1537 //printf("Trying class %s\n",qPrint(cd->name()));
1538 int spos=s.find(cd->name()+"::");
1539 if (spos!=-1)
1540 {
1541 s = s.left(spos)+s.right(
1542 s.length()-spos-cd->name().length()-2
1543 );
1544 }
1545 //printf("base class '%s'\n",qPrint(cd->name()));
1546 if (!cd->baseClasses().empty())
1547 {
1548 trimBaseClassScope(cd->baseClasses(),s,level+1);
1549 }
1550 }
1551}
virtual const BaseClassList & baseClasses() const =0
Returns the list of base classes from which this class directly inherits.
void trimBaseClassScope(const BaseClassList &bcl, QCString &s, int level=0)
Definition util.cpp:1531

References ClassDef::baseClasses(), QCString::find(), QCString::left(), QCString::length(), Definition::name(), QCString::right(), and trimBaseClassScope().

Referenced by trimBaseClassScope().

◆ unescapeCharsInString()

QCString unescapeCharsInString ( const QCString & s)

Definition at line 3427 of file util.cpp.

3428{
3429 if (s.isEmpty()) return s;
3430 bool caseSenseNames = getCaseSenseNames();
3431 QCString result;
3432 result.reserve(s.length());
3433 const char *p = s.data();
3434 if (p)
3435 {
3436 char c = 0;
3437 while ((c=*p++))
3438 {
3439 if (c=='_') // 2 or 3 character escape
3440 {
3441 switch (*p)
3442 {
3443 case '_': result+=c; p++; break; // __ -> '_'
3444 case '1': result+=':'; p++; break; // _1 -> ':'
3445 case '2': result+='/'; p++; break; // _2 -> '/'
3446 case '3': result+='<'; p++; break; // _3 -> '<'
3447 case '4': result+='>'; p++; break; // _4 -> '>'
3448 case '5': result+='*'; p++; break; // _5 -> '*'
3449 case '6': result+='&'; p++; break; // _6 -> '&'
3450 case '7': result+='|'; p++; break; // _7 -> '|'
3451 case '8': result+='.'; p++; break; // _8 -> '.'
3452 case '9': result+='!'; p++; break; // _9 -> '!'
3453 case '0': // 3 character escape
3454 switch (*(p+1))
3455 {
3456 case '0': result+=','; p+=2; break; // _00 -> ','
3457 case '1': result+=' '; p+=2; break; // _01 -> ' '
3458 case '2': result+='{'; p+=2; break; // _02 -> '{'
3459 case '3': result+='}'; p+=2; break; // _03 -> '}'
3460 case '4': result+='?'; p+=2; break; // _04 -> '?'
3461 case '5': result+='^'; p+=2; break; // _05 -> '^'
3462 case '6': result+='%'; p+=2; break; // _06 -> '%'
3463 case '7': result+='('; p+=2; break; // _07 -> '('
3464 case '8': result+=')'; p+=2; break; // _08 -> ')'
3465 case '9': result+='+'; p+=2; break; // _09 -> '+'
3466 case 'a': result+='='; p+=2; break; // _0a -> '='
3467 case 'b': result+='$'; p+=2; break; // _0b -> '$'
3468 case 'c': result+='\\'; p+=2; break;// _0c -> '\'
3469 case 'd': result+='@'; p+=2; break; // _0d -> '@'
3470 case 'e': result+=']'; p+=2; break; // _0e -> ']'
3471 case 'f': result+='['; p+=2; break; // _0f -> '['
3472 case 'g': result+='#'; p+=2; break; // _0g -> '#'
3473 case 'h': result+='"'; p+=2; break; // _0h -> '"'
3474 case 'i': result+='~'; p+=2; break; // _0i -> '~'
3475 case 'j': result+='\''; p+=2; break;// _0j -> '\'
3476 case 'k': result+=';'; p+=2; break; // _0k -> ';'
3477 case 'l': result+='`'; p+=2; break; // _0l -> '`'
3478 default: // unknown escape, just pass underscore character as-is
3479 result+=c;
3480 break;
3481 }
3482 break;
3483 default:
3484 if (!caseSenseNames && c>='a' && c<='z') // lower to upper case escape, _a -> 'A'
3485 {
3486 result+=static_cast<char>(toupper(*p));
3487 p++;
3488 }
3489 else // unknown escape, pass underscore character as-is
3490 {
3491 result+=c;
3492 }
3493 break;
3494 }
3495 }
3496 else // normal character; pass as is
3497 {
3498 result+=c;
3499 }
3500 }
3501 }
3502 return result;
3503}

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

◆ updateColumnCount()

size_t updateColumnCount ( const char * s,
size_t col )

Definition at line 6910 of file util.cpp.

6911{
6912 if (s)
6913 {
6914 const int tabSize = Config_getInt(TAB_SIZE);
6915 char c;
6916 while ((c=*s++))
6917 {
6918 switch(c)
6919 {
6920 case '\t': col+=tabSize - (col%tabSize);
6921 break;
6922 case '\n': col=0;
6923 break;
6924 default:
6925 col++;
6926 if (c<0) // multi-byte character
6927 {
6928 int numBytes = getUTF8CharNumBytes(c);
6929 for (int i=0;i<numBytes-1 && (c=*s++);i++) {} // skip over extra chars
6930 if (c==0) return col; // end of string half way a multibyte char
6931 }
6932 break;
6933 }
6934 }
6935 }
6936 return col;
6937}

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 & language )

Definition at line 5116 of file util.cpp.

5117{
5118 QCString langName = language.lower();
5119 auto it1 = std::find_if(g_lang2extMap.begin(),g_lang2extMap.end(),
5120 [&langName](const auto &info) { return info.langName==langName; });
5121 if (it1 == g_lang2extMap.end()) return false;
5122
5123 // found the language
5124 SrcLangExt parserId = it1->parserId;
5125 QCString extName = extension.lower();
5126 if (extName.isEmpty()) return FALSE;
5127 if (extName.at(0)!='.') extName.prepend(".");
5128 auto it2 = g_extLookup.find(extName.str());
5129 if (it2!=g_extLookup.end())
5130 {
5131 g_extLookup.erase(it2); // language was already register for this ext
5132 }
5133 //printf("registering extension %s\n",qPrint(extName));
5134 g_extLookup.emplace(extName.str(),parserId);
5135 if (!Doxygen::parserManager->registerExtension(extName,it1->parserName))
5136 {
5137 err("Failed to assign extension {} to parser {} for language {}\n",
5138 extName.data(),it1->parserName,language);
5139 }
5140 else
5141 {
5142 //msg("Registered extension {} to language parser {}...\n",
5143 // extName,language);
5144 }
5145 return TRUE;
5146}
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 5812 of file util.cpp.

5813{
5814 int hue = Config_getInt(HTML_COLORSTYLE_HUE);
5815 int sat = Config_getInt(HTML_COLORSTYLE_SAT);
5816 int gamma = Config_getInt(HTML_COLORSTYLE_GAMMA);
5817 while (data->name)
5818 {
5819 QCString fileName = dir+"/"+data->name;
5820 ColoredImage img(data->width,data->height,data->content,data->alpha,
5821 sat,hue,gamma);
5822 if (!img.save(fileName))
5823 {
5824 fprintf(stderr,"Warning: Cannot open file %s for writing\n",data->name);
5825 }
5826 Doxygen::indexList->addImageFile(data->name);
5827 data++;
5828 }
5829}
Class representing a bitmap image colored based on hue/sat/gamma settings.
Definition image.h:56
static IndexList * indexList
Definition doxygen.h:132
const unsigned char * content
Definition util.h:470
unsigned short height
Definition util.h:469
const unsigned char * alpha
Definition util.h:471
unsigned short width
Definition util.h:468
const char * name
Definition util.h:467

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 & list )

Definition at line 1175 of file util.cpp.

1176{
1177 auto replaceFunc = [&list,&ol](size_t entryIndex)
1178 {
1179 const auto &e = list[entryIndex];
1180 ol.pushGeneratorState();
1184 // link for Html / man
1185 //printf("writeObjectLink(file=%s)\n",qPrint(e->file));
1186 ol.writeObjectLink(QCString(),e.file,e.anchor,e.name);
1187 ol.popGeneratorState();
1188
1189 ol.pushGeneratorState();
1192 // link for Latex / pdf with anchor because the sources
1193 // are not hyperlinked (not possible with a verbatim environment).
1194 ol.writeObjectLink(QCString(),e.file,QCString(),e.name);
1195 ol.popGeneratorState();
1196 };
1197
1198 writeMarkerList(ol, theTranslator->trWriteList(static_cast<int>(list.size())).str(), list.size(), replaceFunc);
1199
1200 ol.writeString(".");
1201}
void disable(OutputType o)
void writeMarkerList(OutputList &ol, const std::string &markerText, size_t numMarkers, std::function< void(size_t)> replaceFunc)
Definition util.cpp:1124

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

◆ writeFileContents()

QCString writeFileContents ( const QCString & baseName,
const QCString & extension,
const QCString & content,
bool & exists )

Thread-safe function to write a string to a file.

The contents will be used to create a hash that will be used to make the name unique.

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

Definition at line 6989 of file util.cpp.

6990{
6991 uint8_t md5_sig[16];
6992 char sigStr[33];
6993 MD5Buffer(content.data(),static_cast<unsigned int>(content.length()),md5_sig);
6994 MD5SigToString(md5_sig,sigStr);
6995
6996 QCString fileName = baseName + sigStr + extension;
6997 { // ==== start atomic section
6998 std::lock_guard lock(writeFileContents_lock);
6999 auto it=writeFileContents_set.find(fileName.str());
7000 exists = it!=writeFileContents_set.end();
7001 if (!exists)
7002 {
7003 writeFileContents_set.insert(fileName.str());
7004 if (auto file = Portable::openOutputStream(fileName); file.is_open())
7005 {
7006 file.write( content.data(), content.length() );
7007 file.close();
7008 }
7009 else
7010 {
7011 err("Could not open file {} for writing\n",fileName);
7012 return QCString();
7013 }
7014 }
7015 } // ==== end atomic section
7016 return fileName;
7017}
static std::mutex writeFileContents_lock
Definition util.cpp:6978

References QCString::data(), err, QCString::length(), Portable::openOutputStream(), QCString::str(), writeFileContents_lock, and writeFileContents_set.

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

◆ writeMarkerList() [1/2]

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

Definition at line 1147 of file util.cpp.

1149{
1150 QCString result;
1151 static const reg::Ex marker(R"(@(\d+))");
1152 reg::Iterator it(markerText,marker);
1154 size_t index=0;
1155 for ( ; it!=end ; ++it)
1156 {
1157 const auto &match = *it;
1158 size_t newIndex = match.position();
1159 size_t matchLen = match.length();
1160 result += markerText.substr(index,newIndex-index);
1161 unsigned long entryIndex = std::stoul(match[1].str());
1162 if (entryIndex<static_cast<unsigned long>(numMarkers))
1163 {
1164 result+=replaceFunc(entryIndex);
1165 }
1166 index=newIndex+matchLen;
1167 }
1168 if (index<markerText.size())
1169 {
1170 result += markerText.substr(index);
1171 }
1172 return result;
1173}

References end().

◆ writeMarkerList() [2/2]

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

Definition at line 1124 of file util.cpp.

1126{
1127 static const reg::Ex marker(R"(@(\d+))");
1128 reg::Iterator it(markerText,marker);
1130 size_t index=0;
1131 for ( ; it!=end ; ++it)
1132 {
1133 const auto &match = *it;
1134 size_t newIndex = match.position();
1135 size_t matchLen = match.length();
1136 ol.parseText(markerText.substr(index,newIndex-index));
1137 unsigned long entryIndex = std::stoul(match[1].str());
1138 if (entryIndex<static_cast<unsigned long>(numMarkers))
1139 {
1140 replaceFunc(entryIndex);
1141 }
1142 index=newIndex+matchLen;
1143 }
1144 ol.parseText(markerText.substr(index));
1145}
void parseText(const QCString &textStr)

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

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

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

5470{
5471 if (al.empty()) return;
5472 ol.startConstraintList(theTranslator->trTypeConstraints());
5473 for (const Argument &a : al)
5474 {
5476 ol.parseText(a.name);
5477 ol.endConstraintParam();
5479 linkifyText(TextGeneratorOLImpl(ol),a.type,LinkifyTextOptions().setScope(d));
5480 ol.endConstraintType();
5482 ol.generateDoc(d->docFile(),
5483 d->docLine(),
5484 d,
5485 nullptr,
5486 a.docs,
5487 DocOptions()
5488 .setIndexWords(true));
5489 ol.endConstraintDocs();
5490 }
5491 ol.endConstraintList();
5492}
virtual int docLine() const =0
void endConstraintType()
Definition outputlist.h:714
void endConstraintList()
Definition outputlist.h:720
void startConstraintParam()
Definition outputlist.h:708
void generateDoc(const QCString &fileName, int startLine, const Definition *ctx, const MemberDef *md, const QCString &docStr, const DocOptions &options)
void startConstraintDocs()
Definition outputlist.h:716
void startConstraintType()
Definition outputlist.h:712
void endConstraintDocs()
Definition outputlist.h:718
void endConstraintParam()
Definition outputlist.h:710
void startConstraintList(const QCString &header)
Definition outputlist.h:706
Implements TextGeneratorIntf for an OutputDocInterface stream.
Definition util.h:76
void linkifyText(const TextGeneratorIntf &out, const QCString &text, const LinkifyTextOptions &options)
Definition util.cpp:893

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

Variable Documentation

◆ constScope

const char constScope[] = { 'c', 'o', 'n', 's', 't', ':' }
static

Definition at line 520 of file util.cpp.

520{ 'c', 'o', 'n', 's', 't', ':' };

Referenced by removeRedundantWhiteSpace().

◆ g_charAroundSpace

CharAroundSpace g_charAroundSpace
static

Definition at line 564 of file util.cpp.

Referenced by removeRedundantWhiteSpace().

◆ g_docCache

std::unordered_map<std::string,QCString> g_docCache
static

Definition at line 5433 of file util.cpp.

Referenced by parseCommentAsHtml().

◆ g_docCacheMutex

std::mutex g_docCacheMutex
static

Definition at line 5432 of file util.cpp.

Referenced by parseCommentAsHtml().

◆ g_extLookup

std::unordered_map<std::string,SrcLangExt> g_extLookup
static

Definition at line 5082 of file util.cpp.

Referenced by getLanguageFromFileName(), and updateLanguageMapping().

◆ g_findFileDefCache

Cache< std::string, FindFileCacheElem > g_findFileDefCache(5000) ( 5000 )
static

Referenced by findFileDef().

◆ g_findFileDefMutex

std::mutex g_findFileDefMutex
static

Definition at line 2892 of file util.cpp.

Referenced by findFileDef().

◆ g_lang2extMap

std::vector<Lang2ExtMap> g_lang2extMap
static
Initial value:
=
{
{ "idl", "c", SrcLangExt::IDL, ".idl" },
{ "java", "c", SrcLangExt::Java, ".java"},
{ "javascript", "c", SrcLangExt::JS, ".js" },
{ "csharp", "c", SrcLangExt::CSharp, ".cs" },
{ "d", "c", SrcLangExt::D, ".d" },
{ "php", "c", SrcLangExt::PHP, ".php" },
{ "objective-c", "c", SrcLangExt::ObjC, ".m" },
{ "c", "c", SrcLangExt::Cpp, ".c" },
{ "c++", "c", SrcLangExt::Cpp, ".cpp" },
{ "slice", "c", SrcLangExt::Slice, ".ice" },
{ "python", "python", SrcLangExt::Python, ".py" },
{ "fortran", "fortran", SrcLangExt::Fortran, ".f" },
{ "fortranfree", "fortranfree", SrcLangExt::Fortran, ".f90" },
{ "fortranfixed", "fortranfixed", SrcLangExt::Fortran, ".f" },
{ "vhdl", "vhdl", SrcLangExt::VHDL, ".vhdl"},
{ "xml", "xml", SrcLangExt::XML, ".xml" },
{ "sql", "sql", SrcLangExt::SQL, ".sql" },
{ "md", "md", SrcLangExt::Markdown, ".md" },
{ "lex", "lex", SrcLangExt::Lex, ".l" },
}

Definition at line 5092 of file util.cpp.

5092 {
5093// language parser parser option
5094 { "idl", "c", SrcLangExt::IDL, ".idl" },
5095 { "java", "c", SrcLangExt::Java, ".java"},
5096 { "javascript", "c", SrcLangExt::JS, ".js" },
5097 { "csharp", "c", SrcLangExt::CSharp, ".cs" },
5098 { "d", "c", SrcLangExt::D, ".d" },
5099 { "php", "c", SrcLangExt::PHP, ".php" },
5100 { "objective-c", "c", SrcLangExt::ObjC, ".m" },
5101 { "c", "c", SrcLangExt::Cpp, ".c" },
5102 { "c++", "c", SrcLangExt::Cpp, ".cpp" },
5103 { "slice", "c", SrcLangExt::Slice, ".ice" },
5104 { "python", "python", SrcLangExt::Python, ".py" },
5105 { "fortran", "fortran", SrcLangExt::Fortran, ".f" },
5106 { "fortranfree", "fortranfree", SrcLangExt::Fortran, ".f90" },
5107 { "fortranfixed", "fortranfixed", SrcLangExt::Fortran, ".f" },
5108 { "vhdl", "vhdl", SrcLangExt::VHDL, ".vhdl"},
5109 { "xml", "xml", SrcLangExt::XML, ".xml" },
5110 { "sql", "sql", SrcLangExt::SQL, ".sql" },
5111 { "md", "md", SrcLangExt::Markdown, ".md" },
5112 { "lex", "lex", SrcLangExt::Lex, ".l" },
5113};

Referenced by getLanguageFromCodeLang(), and updateLanguageMapping().

◆ g_matchArgsMutex

std::mutex g_matchArgsMutex
static

Definition at line 1913 of file util.cpp.

Referenced by matchArgument2().

◆ g_usedNames

std::unordered_map<std::string,int> g_usedNames
static

Definition at line 3505 of file util.cpp.

Referenced by convertNameToFile().

◆ g_usedNamesCount

int g_usedNamesCount =1
static

Definition at line 3507 of file util.cpp.

Referenced by convertNameToFile().

◆ g_usedNamesMutex

std::mutex g_usedNamesMutex
static

Definition at line 3506 of file util.cpp.

Referenced by convertNameToFile().

◆ hex

const char* hex = "0123456789ABCDEF"
static

Definition at line 96 of file util.cpp.

◆ operatorScope

const char operatorScope[] = { 'o', 'p', 'e', 'r', 'a', 't', 'o', 'r', '?', '?', '?' }
static

Definition at line 523 of file util.cpp.

523{ 'o', 'p', 'e', 'r', 'a', 't', 'o', 'r', '?', '?', '?' };

Referenced by removeRedundantWhiteSpace().

◆ virtualScope

const char virtualScope[] = { 'v', 'i', 'r', 't', 'u', 'a', 'l', ':' }
static

Definition at line 522 of file util.cpp.

522{ 'v', 'i', 'r', 't', 'u', 'a', 'l', ':' };

Referenced by removeRedundantWhiteSpace().

◆ volatileScope

const char volatileScope[] = { 'v', 'o', 'l', 'a', 't', 'i', 'l', 'e', ':' }
static

Definition at line 521 of file util.cpp.

521{ 'v', 'o', 'l', 'a', 't', 'i', 'l', 'e', ':' };

Referenced by removeRedundantWhiteSpace().

◆ writeFileContents_lock

std::mutex writeFileContents_lock
static

Definition at line 6978 of file util.cpp.

Referenced by writeFileContents().

◆ writeFileContents_set

StringUnorderedSet writeFileContents_set
static

Definition at line 6979 of file util.cpp.

Referenced by cleanupInlineGraph(), and writeFileContents().