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 Definition *scope, const FileDef *fileScope, const Definition *self, const QCString &text, bool autoBreak, bool external, bool keepSpaces, int indentLevel)
void writeMarkerList (OutputList &ol, const std::string &markerText, size_t numMarkers, std::function< void(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 81 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 1870 of file util.cpp.

Referenced by matchArgument2(), and matchArguments2().

◆ NOMATCH

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

Definition at line 1871 of file util.cpp.

Referenced by matchArgument2(), and matchArguments2().

◆ REL_PATH_TO_ROOT

#define REL_PATH_TO_ROOT   "../../"

Definition at line 95 of file util.cpp.

Referenced by relativePathToRoot().

Function Documentation

◆ addCodeOnlyMappings()

void addCodeOnlyMappings ( )

Definition at line 5158 of file util.cpp.

5159{
5160 updateLanguageMapping(".xml", "xml");
5161 updateLanguageMapping(".sql", "sql");
5162}
bool updateLanguageMapping(const QCString &extension, const QCString &language)
Definition util.cpp:5059

References updateLanguageMapping().

Referenced by generateOutput().

◆ addGroupListToTitle()

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

◆ addHtmlExtensionIfMissing()

void addHtmlExtensionIfMissing ( QCString & fName)

Definition at line 4875 of file util.cpp.

4876{
4877 if (fName.isEmpty()) return;
4878 int i_fs = fName.findRev('/');
4879 int i_bs = fName.findRev('\\');
4880 int i = fName.find('.',std::max({ i_fs, i_bs ,0})); // search for . after path part
4881 if (i==-1)
4882 {
4884 }
4885}
static QCString htmlFileExtension
Definition doxygen.h:121
int find(char c, int index=0, bool cs=TRUE) const
Definition qcstring.cpp:43
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:163
int findRev(char c, int index=-1, bool cs=TRUE) const
Definition qcstring.cpp:96

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

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

◆ addMembersToMemberGroup()

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

Definition at line 4051 of file util.cpp.

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

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

◆ addRefItem()

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

Definition at line 4778 of file util.cpp.

4781{
4782 //printf("addRefItem(sli=%d,key=%s,prefix=%s,name=%s,title=%s,args=%s)\n",(int)sli.size(),key,prefix,name,title,args);
4783 if (!key.isEmpty() && key[0]!='@') // check for @ to skip anonymous stuff (see bug427012)
4784 {
4785 for (RefItem *item : sli)
4786 {
4787 item->setPrefix(prefix);
4788 item->setScope(scope);
4789 item->setName(name);
4790 item->setTitle(title);
4791 item->setArgs(args);
4792 item->setGroup(key);
4793 }
4794 }
4795}
constexpr auto prefix
Definition anchor.cpp:44
This struct represents an item in the list of references.
Definition reflist.h:32

References QCString::isEmpty(), and prefix.

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

◆ addRelatedPage()

PageDef * addRelatedPage ( const QCString & name,
const QCString & ptitle,
const QCString & doc,
const QCString & fileName,
int docLine,
int startLine,
const RefItemVector & sli,
GroupDef * gd,
const TagInfo * tagInfo,
bool xref,
SrcLangExt lang )

Definition at line 4648 of file util.cpp.

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

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

◆ argListToString()

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

Definition at line 1204 of file util.cpp.

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

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

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

◆ checkBlocks()

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

Definition at line 6491 of file util.cpp.

6492{
6493 if (s.isEmpty()) return;
6494
6495 const char *p = s.data();
6496 char c = 0;
6497 while ((c=*p))
6498 {
6499 if (c==markerInfo.markerChar) // potential start of marker
6500 {
6501 if (qstrncmp(p,markerInfo.beginStr,markerInfo.beginLen)==0) // start of begin marker
6502 {
6503 size_t len = markerInfo.beginLen;
6504 bool negate = *(p+len)=='!';
6505 if (negate) len++;
6506 p += len;
6507 QCString marker;
6508 while (*p)
6509 {
6510 if (markerInfo.closeLen==0 && *p=='\n') // matching end of line
6511 {
6512 warn(fileName,-1,"Remaining begin replacement with marker '{}'",marker);
6513 break;
6514 }
6515 else if (markerInfo.closeLen!= 0 && qstrncmp(p,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6516 {
6517 p += markerInfo.closeLen;
6518 warn(fileName,-1,"Remaining begin replacement with marker '{}'",marker);
6519 break;
6520 }
6521 marker += *p;
6522 p++;
6523 }
6524 }
6525 else if (qstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // start of end marker
6526 {
6527 size_t len = markerInfo.endLen;
6528 bool negate = *(p+len)=='!';
6529 if (negate) len++;
6530 p += len;
6531 QCString marker;
6532 while (*p)
6533 {
6534 if (markerInfo.closeLen==0 && *p=='\n') // matching end of line
6535 {
6536 warn(fileName,-1,"Remaining end replacement with marker '{}'",marker);
6537 break;
6538 }
6539 else if (markerInfo.closeLen!= 0 && qstrncmp(p,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6540 {
6541 p += markerInfo.closeLen;
6542 warn(fileName,-1,"Remaining end replacement with marker '{}'",marker);
6543 break;
6544 }
6545 marker += *p;
6546 p++;
6547 }
6548 }
6549 }
6550 p++;
6551 }
6552}
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition qcstring.h:172
int qstrncmp(const char *str1, const char *str2, size_t len)
Definition qcstring.h:75
size_t beginLen
Definition util.h:187
const char * closeStr
Definition util.h:190
const char * beginStr
Definition util.h:186
size_t closeLen
Definition util.h:191
const char * endStr
Definition util.h:188

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

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

◆ checkExtension()

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

Definition at line 4870 of file util.cpp.

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

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

Referenced by copyLatexStyleSheet(), and extraLatexStyleSheet().

◆ checkIfTypedef()

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

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

Definition at line 5268 of file util.cpp.

5269{
5270 MemberDef *bestMatch = getMemberFromSymbol(scope,fileScope,n);
5271
5272 if (bestMatch && bestMatch->isTypedef())
5273 return TRUE; // closest matching symbol is a typedef
5274 else
5275 return FALSE;
5276}
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:5216

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

Referenced by isVarWithConstructor().

◆ cleanupInlineGraph()

void cleanupInlineGraph ( )

Definition at line 6959 of file util.cpp.

6960{
6961 if (Config_getBool(DOT_CLEANUP))
6962 {
6963 for (const auto& fileName: writeFileContents_set)
6964 {
6965 Dir().remove(qPrint(fileName));
6966 }
6967 }
6968}
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:6918

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

Referenced by generateOutput().

◆ clearSubDirs()

void clearSubDirs ( const Dir & d)

Definition at line 3621 of file util.cpp.

3622{
3623 if (Config_getBool(CREATE_SUBDIRS))
3624 {
3625 // remove empty subdirectories
3626 int createSubdirsLevelPow2 = 1 << Config_getInt(CREATE_SUBDIRS_LEVEL);
3627 for (int l1=0;l1<16;l1++)
3628 {
3629 QCString subdir;
3630 subdir.sprintf("d%x",l1);
3631 for (int l2=0; l2 < createSubdirsLevelPow2; l2++)
3632 {
3633 QCString subsubdir;
3634 subsubdir.sprintf("d%x/d%02x",l1,l2);
3635 if (d.exists(subsubdir.str()) && d.isEmpty(subsubdir.str()))
3636 {
3637 d.rmdir(subsubdir.str());
3638 }
3639 }
3640 if (d.exists(subdir.str()) && d.isEmpty(subdir.str()))
3641 {
3642 d.rmdir(subdir.str());
3643 }
3644 }
3645 }
3646}
bool isEmpty(const std::string &subdir) const
Definition dir.cpp:263
bool rmdir(const std::string &path, bool acceptsAbsPath=true) const
Definition dir.cpp:309
bool exists() const
Definition dir.cpp:257
const std::string & str() const
Definition qcstring.h:552
QCString & sprintf(const char *format,...)
Definition qcstring.cpp:29
#define Config_getInt(name)
Definition config.h:34

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

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

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

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

4002{
4003 if (str.isEmpty()) return QCString();
4004
4005 std::string s = str.data();
4006 static const reg::Ex re(R"(&\a\w*;)");
4007 reg::Iterator it(s,re);
4009
4010 QCString result;
4011 result.reserve(str.length()+32);
4012 size_t p=0, i=0, l=0;
4013 for (; it!=end ; ++it)
4014 {
4015 const auto &match = *it;
4016 p = match.position();
4017 l = match.length();
4018 if (p>i)
4019 {
4020 result+=s.substr(i,p-i);
4021 }
4022 QCString entity(match.str());
4024 const char *code=nullptr;
4025 if (symType!=HtmlEntityMapper::Sym_Unknown && (code=HtmlEntityMapper::instance().utf8(symType)))
4026 {
4027 result+=code;
4028 }
4029 else
4030 {
4031 result+=entity;
4032 }
4033 i=p+l;
4034 }
4035 result+=s.substr(i);
4036 //printf("convertCharEntitiesToUTF8(%s)->%s\n",qPrint(s),qPrint(result));
4037 return result;
4038}
static HtmlEntityMapper & instance()
Returns the one and only instance of the HTML entity mapper.
SymType name2sym(const QCString &symName) const
Give code of the requested HTML entity name.
void reserve(size_t size)
Reserve space for size bytes without changing the string contents.
Definition qcstring.h:185
bool match(std::string_view str, Match &match, const Ex &re)
Matches a given string str for a match against regular expression re.
Definition regex.cpp:855

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

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

◆ convertFileNameFortranParserCode()

FortranFormat convertFileNameFortranParserCode ( QCString fn)

Definition at line 6365 of file util.cpp.

6366{
6368 QCString parserName = Doxygen::parserManager->getParserName(ext);
6369
6370 if (parserName == "fortranfixed") return FortranFormat::Fixed;
6371 else if (parserName == "fortranfree") return FortranFormat::Free;
6372
6374}
static ParserManager * parserManager
Definition doxygen.h:130
QCString getFileNameExtension(const QCString &fn)
Definition util.cpp:5206

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

◆ convertNameToFile()

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

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

Definition at line 3458 of file util.cpp.

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

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

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

◆ convertProtectionLevel()

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

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

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

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

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

Definition at line 6198 of file util.cpp.

6204{
6205 bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
6206
6207 // default representing 1-1 mapping
6208 *outListType1=inListType;
6209 *outListType2=MemberListType::Invalid();
6210
6211 if (inProt==Protection::Public)
6212 {
6213 if (inListType.isPrivate())
6214 {
6215 *outListType1=MemberListType::Invalid();
6216 }
6217 }
6218 else if (inProt==Protection::Protected)
6219 {
6220 if (inListType.isPrivate() || inListType.isPublic())
6221 {
6222 *outListType1=MemberListType::Invalid();
6223 }
6224 else if (inListType.isProtected())
6225 {
6226 *outListType2=inListType.toPublic();
6227 }
6228 }
6229 else if (inProt==Protection::Private)
6230 {
6231 if (inListType.isPublic() || inListType.isProtected())
6232 {
6233 *outListType1=MemberListType::Invalid();
6234 }
6235 else if (inListType.isPrivate())
6236 {
6237 if (extractPrivate)
6238 {
6239 *outListType1=inListType.toPublic();
6240 *outListType2=inListType.toProtected();
6241 }
6242 else
6243 {
6244 *outListType1=MemberListType::Invalid();
6245 }
6246 }
6247 }
6248
6249 //printf("convertProtectionLevel(type=%s prot=%d): %s,%s\n",
6250 // qPrint(inListType.to_string()),inProt,qPrint(outListType1->to_string()),qPrint(outListType2->to_string()));
6251}
constexpr bool isPrivate() const noexcept
Definition types.h:382
constexpr MemberListType toPublic() const noexcept
Definition types.h:426
static constexpr MemberListType Invalid() noexcept
Definition types.h:371
constexpr MemberListType toProtected() const noexcept
Definition types.h:438
constexpr bool isProtected() const noexcept
Definition types.h:380
ML_TYPES constexpr bool isPublic() const noexcept
Definition types.h:378

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

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

◆ convertToHtml()

QCString convertToHtml ( const QCString & s,
bool keepEntities )

Converts a string to a HTML-encoded string

Definition at line 3917 of file util.cpp.

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

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

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

◆ convertToId()

QCString convertToId ( const QCString & s)

Converts a string to a HTML id string

Definition at line 3826 of file util.cpp.

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

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

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

◆ convertToJSString()

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

Definition at line 3977 of file util.cpp.

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

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

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

◆ convertToXML()

QCString convertToXML ( const QCString & s,
bool keepEntities )

Converts a string to an XML-encoded string

Definition at line 3866 of file util.cpp.

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

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

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

◆ copyFile()

◆ correctId()

QCString correctId ( const QCString & s)

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

Definition at line 3859 of file util.cpp.

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

References QCString::isEmpty().

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

◆ correctURL()

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

Corrects URL url according to the relative path relPath.

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

Definition at line 5894 of file util.cpp.

5895{
5896 QCString result = url;
5897 if (!relPath.isEmpty() && !isURL(url))
5898 {
5899 result.prepend(relPath);
5900 }
5901 return result;
5902}
bool isURL(const QCString &url)
Checks whether the given url starts with a supported protocol.
Definition util.cpp:5882

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

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

◆ createHtmlUrl()

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

Definition at line 5689 of file util.cpp.

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

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

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

◆ createSubDirs()

void createSubDirs ( const Dir & d)

Definition at line 3594 of file util.cpp.

3595{
3596 if (Config_getBool(CREATE_SUBDIRS))
3597 {
3598 // create up to 4096 subdirectories
3599 int createSubdirsLevelPow2 = 1 << Config_getInt(CREATE_SUBDIRS_LEVEL);
3600 for (int l1=0; l1<16; l1++)
3601 {
3602 QCString subdir;
3603 subdir.sprintf("d%x",l1);
3604 if (!d.exists(subdir.str()) && !d.mkdir(subdir.str()))
3605 {
3606 term("Failed to create output directory '{}'\n",subdir);
3607 }
3608 for (int l2=0; l2<createSubdirsLevelPow2; l2++)
3609 {
3610 QCString subsubdir;
3611 subsubdir.sprintf("d%x/d%02x",l1,l2);
3612 if (!d.exists(subsubdir.str()) && !d.mkdir(subsubdir.str()))
3613 {
3614 term("Failed to create output directory '{}'\n",subsubdir);
3615 }
3616 }
3617 }
3618 }
3619}
bool mkdir(const std::string &path, bool acceptsAbsPath=true) const
Definition dir.cpp:295
#define term(fmt,...)
Definition message.h:137

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

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

◆ demangleCSharpGenericName()

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

Definition at line 6892 of file util.cpp.

6893{
6894 QCString result=name;
6895 if (result.endsWith("-g"))
6896 {
6897 int idx = result.find('-');
6898 result = result.left(idx)+templArgs;
6899 }
6900 return result;
6901}

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

Referenced by ClassDefImpl::className().

◆ detab()

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

Definition at line 6689 of file util.cpp.

6690{
6691 int tabSize = Config_getInt(TAB_SIZE);
6692 size_t size = s.length();
6693 QCString result;
6694 result.reserve(size+256);
6695 const char *data = s.data();
6696 size_t i=0;
6697 int col=0;
6698 constexpr auto doxy_nbsp = "&_doxy_nbsp;"; // doxygen escape command for UTF-8 nbsp
6699 const int maxIndent=1000000; // value representing infinity
6700 int minIndent=maxIndent;
6701 bool skip = false;
6702 while (i<size)
6703 {
6704 char c = data[i++];
6705 switch(c)
6706 {
6707 case '\t': // expand tab
6708 {
6709 int stop = tabSize - (col%tabSize);
6710 //printf("expand at %d stop=%d\n",col,stop);
6711 col+=stop;
6712 while (stop--) result+=' ';
6713 }
6714 break;
6715 case '\\':
6716 if (data[i] == '\\') // escaped command -> ignore
6717 {
6718 result+=c;
6719 result+=data[i++];
6720 col+=2;
6721 }
6722 else if (i+5<size && literal_at(data+i,"iskip")) // command
6723 {
6724 i+=5;
6725 skip = true;
6726 }
6727 else if (i+8<size && literal_at(data+i,"endiskip")) // command
6728 {
6729 i+=8;
6730 skip = false;
6731 }
6732 else // some other command
6733 {
6734 result+=c;
6735 col++;
6736 }
6737 break;
6738 case '\n': // reset column counter
6739 result+=c;
6740 col=0;
6741 break;
6742 case ' ': // increment column counter
6743 result+=c;
6744 col++;
6745 break;
6746 default: // non-whitespace => update minIndent
6747 if (c<0 && i<size) // multibyte sequence
6748 {
6749 // special handling of the UTF-8 nbsp character 0xC2 0xA0
6750 int nb = isUTF8NonBreakableSpace(data);
6751 if (nb>0)
6752 {
6753 result+=doxy_nbsp;
6754 i+=nb-1;
6755 }
6756 else
6757 {
6758 int bytes = getUTF8CharNumBytes(c);
6759 for (int j=0;j<bytes-1 && c;j++)
6760 {
6761 result+=c;
6762 c = data[i++];
6763 }
6764 result+=c;
6765 }
6766 }
6767 else
6768 {
6769 result+=c;
6770 }
6771 if (!skip && col<minIndent) minIndent=col;
6772 col++;
6773 }
6774 }
6775 if (minIndent!=maxIndent) refIndent=minIndent; else refIndent=0;
6776 //printf("detab(\n%s\n)=[\n%s\n]\n",qPrint(s),qPrint(out.get()));
6777 return result;
6778}
bool literal_at(const char *data, const char(&str)[N])
returns TRUE iff data points to a substring that matches string literal str
Definition stringutil.h:98
int isUTF8NonBreakableSpace(const char *input)
Check if the first character pointed at by input is a non-breakable whitespace character.
Definition utf8.cpp:228
uint8_t getUTF8CharNumBytes(char c)
Returns the number of bytes making up a single UTF8 character given the first byte in the sequence.
Definition utf8.cpp:23

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

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

◆ determineAbsoluteIncludeName()

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

Definition at line 3554 of file util.cpp.

3555{
3556 bool searchIncludes = Config_getBool(SEARCH_INCLUDES);
3557 QCString absIncFileName = incFileName;
3558 FileInfo fi(curFile.str());
3559 if (fi.exists())
3560 {
3561 QCString absName = fi.dirPath(TRUE)+"/"+incFileName;
3562 FileInfo fi2(absName.str());
3563 if (fi2.exists())
3564 {
3565 absIncFileName=fi2.absFilePath();
3566 }
3567 else if (searchIncludes) // search in INCLUDE_PATH as well
3568 {
3569 const StringVector &includePath = Config_getList(INCLUDE_PATH);
3570 for (const auto &incPath : includePath)
3571 {
3572 FileInfo fi3(incPath);
3573 if (fi3.exists() && fi3.isDir())
3574 {
3575 absName = fi3.absFilePath()+"/"+incFileName;
3576 //printf("trying absName=%s\n",qPrint(absName));
3577 FileInfo fi4(absName.str());
3578 if (fi4.exists())
3579 {
3580 absIncFileName=fi4.absFilePath();
3581 break;
3582 }
3583 //printf( "absIncFileName = %s\n", qPrint(absIncFileName) );
3584 }
3585 }
3586 }
3587 //printf( "absIncFileName = %s\n", qPrint(absIncFileName) );
3588 }
3589 return absIncFileName;
3590}
Minimal replacement for QFileInfo.
Definition fileinfo.h:23
#define Config_getList(name)
Definition config.h:38
std::vector< std::string > StringVector
Definition containers.h:33

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

Referenced by ModuleManager::resolveImports().

◆ escapeCharsInString()

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

Definition at line 3283 of file util.cpp.

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

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

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

◆ externalLinkTarget()

QCString externalLinkTarget ( const bool parent)

Definition at line 5678 of file util.cpp.

5679{
5680 bool extLinksInWindow = Config_getBool(EXT_LINKS_IN_WINDOW);
5681 if (extLinksInWindow)
5682 return "target=\"_blank\" ";
5683 else if (parent)
5684 return "target=\"_parent\" ";
5685 else
5686 return "";
5687}
constexpr DocNodeVariant * parent(DocNodeVariant *n)
returns the parent node of a given node n or nullptr if the node has no parent.
Definition docnode.h:1330

References Config_getBool, and parent().

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

◆ externalRef()

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

Definition at line 5722 of file util.cpp.

5723{
5724 QCString result;
5725 if (!ref.isEmpty())
5726 {
5727 auto it = Doxygen::tagDestinationMap.find(ref.str());
5729 {
5730 result = it->second;
5731 size_t l = result.length();
5732 if (!relPath.isEmpty() && l>0 && result.at(0)=='.')
5733 { // relative path -> prepend relPath.
5734 result.prepend(relPath);
5735 l+=relPath.length();
5736 }
5737 if (l>0 && result.at(l-1)!='/') result+='/';
5738 if (!href) result.append("\" ");
5739 }
5740 }
5741 else
5742 {
5743 result = relPath;
5744 }
5745 return result;
5746}
static StringMap tagDestinationMap
Definition doxygen.h:115
char & at(size_t i)
Returns a reference to the character at index i.
Definition qcstring.h:593
QCString & append(char c)
Definition qcstring.h:396

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

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

◆ extractBeginRawStringDelimiter()

QCString extractBeginRawStringDelimiter ( const char * rawStart)

Definition at line 6903 of file util.cpp.

6904{
6905 QCString text=rawStart;
6906 int i = text.find('"');
6907 assert(i!=-1);
6908 return text.mid(i+1,text.length()-i-2); // text=...R"xyz( -> delimiter=xyz
6909}

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

1841{
1842 QCString type = arg.type.stripWhiteSpace();
1843 QCString name = arg.name;
1844 //printf("----- extractCanonicalArgType(type=%s,name=%s)\n",qPrint(type),qPrint(name));
1845 if ((type=="const" || type=="volatile") && !name.isEmpty())
1846 { // name is part of type => correct
1847 type+=" ";
1848 type+=name;
1849 }
1850 if (name=="const" || name=="volatile")
1851 { // name is part of type => correct
1852 if (!type.isEmpty()) type+=" ";
1853 type+=name;
1854 }
1855 if (!arg.array.isEmpty())
1856 {
1857 type+=arg.array;
1858 }
1859
1860 return extractCanonicalType(d,fs,type,lang,false);
1861}
static QCString extractCanonicalType(const Definition *d, const FileDef *fs, QCString type, SrcLangExt lang, bool insideTemplate)
Definition util.cpp:1764

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

1765{
1766 AUTO_TRACE("d={} fs={} type='{}'",d?d->name():"",fs?fs->name():"",type);
1767 type = type.stripWhiteSpace();
1768
1769 // strip const and volatile keywords that are not relevant for the type
1770 stripIrrelevantConstVolatile(type,insideTemplate);
1771
1772 // strip leading keywords
1773 type.stripPrefix("class ");
1774 type.stripPrefix("struct ");
1775 type.stripPrefix("union ");
1776 type.stripPrefix("enum ");
1777 type.stripPrefix("typename ");
1778
1779 type = removeRedundantWhiteSpace(type);
1780 //printf("extractCanonicalType(type=%s) start: def=%s file=%s\n",qPrint(type),
1781 // d ? qPrint(d->name()) : "<null>", fs ? qPrint(fs->name()) : "<null>");
1782
1783 QCString canType;
1784 QCString templSpec,word;
1785 int i=0,p=0,pp=0;
1786 while ((i=extractClassNameFromType(type,p,word,templSpec))!=-1)
1787 // foreach identifier in the type
1788 {
1789 //printf(" i=%d p=%d\n",i,p);
1790 if (i>pp) canType += type.mid(pp,i-pp);
1791
1792 QCString ct = getCanonicalTypeForIdentifier(d,fs,word,lang,&templSpec);
1793
1794 // in case the ct is empty it means that "word" represents scope "d"
1795 // and this does not need to be added to the canonical
1796 // type (it is redundant), so/ we skip it. This solves problem 589616.
1797 if (ct.isEmpty() && type.mid(p,2)=="::")
1798 {
1799 p+=2;
1800 }
1801 else
1802 {
1803 canType += ct;
1804 }
1805 //printf(" word=%s templSpec=%s canType=%s ct=%s\n",
1806 // qPrint(word), qPrint(templSpec), qPrint(canType), qPrint(ct));
1807 if (!templSpec.isEmpty()) // if we didn't use up the templSpec already
1808 // (i.e. type is not a template specialization)
1809 // then resolve any identifiers inside.
1810 {
1811 std::string ts = templSpec.str();
1812 static const reg::Ex re(R"(\a\w*)");
1813 reg::Iterator it(ts,re);
1815
1816 size_t tp=0;
1817 // for each identifier template specifier
1818 //printf("adding resolved %s to %s\n",qPrint(templSpec),qPrint(canType));
1819 for (; it!=end ; ++it)
1820 {
1821 const auto &match = *it;
1822 size_t ti = match.position();
1823 size_t tl = match.length();
1824 std::string matchStr = match.str();
1825 canType += ts.substr(tp,ti-tp);
1826 canType += getCanonicalTypeForIdentifier(d,fs,matchStr,lang,nullptr);
1827 tp=ti+tl;
1828 }
1829 canType+=ts.substr(tp);
1830 }
1831
1832 pp=p;
1833 }
1834 canType += type.right(type.length()-pp);
1835 AUTO_TRACE_EXIT("canType='{}'",canType);
1836
1837 return removeRedundantWhiteSpace(canType);
1838}
bool stripPrefix(const QCString &prefix)
Definition qcstring.h:213
#define AUTO_TRACE(...)
Definition docnode.cpp:46
#define AUTO_TRACE_EXIT(...)
Definition docnode.cpp:48
int extractClassNameFromType(const QCString &type, int &pos, QCString &name, QCString &templSpec, SrcLangExt lang)
Definition util.cpp:4169
static QCString getCanonicalTypeForIdentifier(const Definition *d, const FileDef *fs, const QCString &word, SrcLangExt lang, QCString *tSpec, int count=0)
Definition util.cpp:1610
void stripIrrelevantConstVolatile(QCString &s, bool insideTemplate)
Definition util.cpp:1563

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

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

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

Referenced by extractCanonicalType(), and findUsedClassesForClass().

◆ extractDirection()

QCString extractDirection ( QCString & docs)

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

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

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

Definition at line 6147 of file util.cpp.

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

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

Referenced by inlineArgListToDoc().

◆ extractEndRawStringDelimiter()

QCString extractEndRawStringDelimiter ( const char * rawEnd)

Definition at line 6911 of file util.cpp.

6912{
6913 QCString text=rawEnd;
6914 return text.mid(1,text.length()-2); // text=)xyz" -> delimiter=xyz
6915}

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

◆ extractNamespaceName()

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

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

Definition at line 3651 of file util.cpp.

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

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

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

◆ fileToString()

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

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

Definition at line 1444 of file util.cpp.

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

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

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

◆ fileVisibleInIndex()

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

Definition at line 6058 of file util.cpp.

6059{
6060 bool allExternals = Config_getBool(ALLEXTERNALS);
6061 bool isDocFile = fd->isDocumentationFile();
6062 genSourceFile = !isDocFile && fd->generateSourceFile();
6063 return ( ((allExternals && fd->isLinkable()) ||
6065 ) &&
6066 !isDocFile
6067 );
6068}
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 1305 of file util.cpp.

1306{
1307 size_t src = 0; // source index
1308 size_t dest = 0; // destination index
1309 size_t len = contents.length();
1310
1311 while (src<len)
1312 {
1313 char c = contents[src++]; // Remember the processed character.
1314 if (c == '\r') // CR to be solved (MAC, DOS)
1315 {
1316 c = '\n'; // each CR to LF
1317 if (src<len && contents[src] == '\n')
1318 {
1319 ++src; // skip LF just after CR (DOS)
1320 }
1321 }
1322 else if ( c == '\0' && src<len-1) // filter out internal \0 characters, as it will confuse the parser
1323 {
1324 c = ' '; // turn into a space
1325 }
1326 contents[dest++] = c; // copy the (modified) character to dest
1327 }
1328 contents.resize(dest);
1329}

Referenced by readInputFile().

◆ filterTitle()

QCString filterTitle ( const QCString & title)

Definition at line 5583 of file util.cpp.

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

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

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

◆ findAndRemoveWord()

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

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

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

Definition at line 4940 of file util.cpp.

4941{
4942 static reg::Ex re(R"(\s*(<\a+>)\s*)");
4943 std::string s = sentence.str();
4944 reg::Iterator it(s,re);
4946 std::string result;
4947 bool found=false;
4948 size_t p=0;
4949 for ( ; it!=end ; ++it)
4950 {
4951 const auto match = *it;
4952 std::string part = match[1].str();
4953 if (part!=word)
4954 {
4955 size_t i = match.position();
4956 size_t l = match.length();
4957 result+=s.substr(p,i-p);
4958 result+=match.str();
4959 p=i+l;
4960 }
4961 else
4962 {
4963 found=true;
4964 size_t i = match[1].position();
4965 size_t l = match[1].length();
4966 result+=s.substr(p,i-p);
4967 p=i+l;
4968 }
4969 }
4970 result+=s.substr(p);
4971 sentence = QCString(result).simplifyWhiteSpace();
4972 return found;
4973}
QCString simplifyWhiteSpace() const
return a copy of this string with leading and trailing whitespace removed and multiple whitespace cha...
Definition qcstring.cpp:190

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

Referenced by isVarWithConstructor().

◆ findFileDef()

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

Definition at line 2844 of file util.cpp.

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

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

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

◆ findFilePath()

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

Definition at line 2929 of file util.cpp.

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

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

Referenced by DocParser::readTextFileByName().

◆ findIndex() [1/2]

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

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

Definition at line 6631 of file util.cpp.

6632{
6634 return reg::search(s,match,re) ? static_cast<int>(match.position()) : -1;
6635}
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 6623 of file util.cpp.

6624{
6625 auto it = std::find(sv.begin(),sv.end(),s);
6626 return it!=sv.end() ? static_cast<int>(it-sv.begin()) : -1;
6627}

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

◆ findModuleDef()

ModuleDef * findModuleDef ( const Definition * d)
static

Definition at line 4797 of file util.cpp.

4798{
4799 ModuleDef *mod = nullptr;
4801 {
4802 const FileDef *fd = toFileDef(d);
4803 if (fd) mod = fd->getModuleDef();
4804 }
4806 {
4807 const ClassDef *cd = toClassDef(d);
4808 if (cd)
4809 {
4810 const FileDef *fd = cd->getFileDef();
4811 if (fd) mod = fd->getModuleDef();
4812 }
4813 }
4815 {
4816 const ConceptDef *cd = toConceptDef(d);
4817 if (cd)
4818 {
4819 const FileDef *fd = cd->getFileDef();
4820 if (fd) mod = fd->getModuleDef();
4821 }
4822 }
4823 return mod;
4824}
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:1951

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

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

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

Referenced by resolveRef().

◆ generateAnonymousAnchor()

QCString generateAnonymousAnchor ( const QCString & fileName,
int count )

Definition at line 3512 of file util.cpp.

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

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

◆ generateFileRef()

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

Definition at line 2816 of file util.cpp.

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

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

◆ generateMarker()

QCString generateMarker ( int id)

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

Definition at line 280 of file util.cpp.

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

References qsnprintf.

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

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

5611{
5612 bool caseSenseNames = getCaseSenseNames();
5613 bool found = FALSE;
5614
5615 if (!patList.empty())
5616 {
5617 std::string fn = fi.fileName();
5618 std::string fp = fi.filePath();
5619 std::string afp= fi.absFilePath();
5620
5621 for (const auto &li : patList)
5622 {
5623 std::string pattern = getter(li).str();
5624 if (!pattern.empty())
5625 {
5626 size_t i=pattern.find('=');
5627 if (i!=std::string::npos) pattern=pattern.substr(0,i); // strip of the extension specific filter name
5628
5629 if (!caseSenseNames)
5630 {
5631 pattern = QCString(pattern).lower().str();
5632 fn = QCString(fn).lower().str();
5633 fp = QCString(fp).lower().str();
5634 afp = QCString(afp).lower().str();
5635 }
5636 reg::Ex re(pattern,reg::Ex::Mode::Wildcard);
5637 found = re.isValid() && (reg::match(fn,re) ||
5638 (fn!=fp && reg::match(fp,re)) ||
5639 (fn!=afp && fp!=afp && reg::match(afp,re)));
5640 if (found)
5641 {
5642 elem = li;
5643 break;
5644 }
5645 //printf("Matching '%s' against pattern '%s' found=%d\n",
5646 // qPrint(fi->fileName()),qPrint(pattern),found);
5647 }
5648 }
5649 }
5650 return found;
5651}
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 1589 of file util.cpp.

1590{
1591 AUTO_TRACE("spec={}",spec);
1592 QCString templSpec = spec.stripWhiteSpace();
1593 // this part had been commented out before... but it is needed to match for instance
1594 // std::list<std::string> against list<string> so it is now back again!
1595 if (!templSpec.isEmpty() && templSpec.at(0) == '<')
1596 {
1597 templSpec = "< " + extractCanonicalType(d,fs,templSpec.right(templSpec.length()-1).stripWhiteSpace(),lang,true);
1598 }
1599 QCString resolvedType = lang==SrcLangExt::Java ? templSpec : resolveTypeDef(d,templSpec);
1600 if (!resolvedType.isEmpty()) // not known as a typedef either
1601 {
1602 templSpec = resolvedType;
1603 }
1604 //printf("getCanonicalTemplateSpec(%s)=%s\n",qPrint(spec),qPrint(templSpec));
1605 AUTO_TRACE_EXIT("result={}",templSpec);
1606 return templSpec;
1607}
QCString resolveTypeDef(const Definition *context, const QCString &qualifiedName, const Definition **typedefContext)
Definition util.cpp:374

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

1613{
1614 if (count>10) return word; // oops recursion
1615
1616 QCString symName,result,templSpec,tmpName;
1617 if (tSpec && !tSpec->isEmpty())
1618 templSpec = stripDeclKeywords(getCanonicalTemplateSpec(d,fs,*tSpec,lang));
1619
1620 AUTO_TRACE("d='{}' fs='{}' word='{}' templSpec='{}'",d?d->name():"",fs?fs->name():"",word,templSpec);
1621
1622 if (word.findRev("::")!=-1 && !(tmpName=stripScope(word)).isEmpty())
1623 {
1624 symName=tmpName; // name without scope
1625 }
1626 else
1627 {
1628 symName=word;
1629 }
1630
1631 // lookup class / class template instance
1632 SymbolResolver resolver(fs);
1633 const ClassDef *cd = resolver.resolveClass(d,word+templSpec,true,true);
1634 const MemberDef *mType = resolver.getTypedef();
1635 QCString ts = resolver.getTemplateSpec();
1636 QCString resolvedType = resolver.getResolvedType();
1637
1638 bool isTemplInst = cd && !templSpec.isEmpty();
1639 if (!cd && !templSpec.isEmpty())
1640 {
1641 // class template specialization not known, look up class template
1642 cd = resolver.resolveClass(d,word,true,true);
1643 mType = resolver.getTypedef();
1644 ts = resolver.getTemplateSpec();
1645 resolvedType = resolver.getResolvedType();
1646 }
1647 if (cd && cd->isUsedOnly()) cd=nullptr; // ignore types introduced by usage relations
1648
1649 AUTO_TRACE_ADD("cd='{}' mType='{}' ts='{}' resolvedType='{}'",
1650 cd?cd->name():"",mType?mType->name():"",ts,resolvedType);
1651 //printf("cd=%p mtype=%p\n",cd,mType);
1652 //printf(" getCanonicalTypeForIdentifier: symbol=%s word=%s cd=%s d=%s fs=%s cd->isTemplate=%d\n",
1653 // qPrint(symName),
1654 // qPrint(word),
1655 // cd ? qPrint(cd->name()) : "<none>",
1656 // d ? qPrint( d->name()) : "<none>",
1657 // fs ? qPrint(fs->name()) : "<none>",
1658 // cd ? cd->isTemplate():-1
1659 // );
1660
1661 //printf(" >>>> word '%s' => '%s' templSpec=%s ts=%s tSpec=%s isTemplate=%d resolvedType=%s\n",
1662 // qPrint((word+templSpec)),
1663 // cd ? qPrint(cd->qualifiedName()) : "<none>",
1664 // qPrint(templSpec), qPrint(ts),
1665 // tSpec ? qPrint(tSpec) : "<null>",
1666 // cd ? cd->isTemplate():FALSE,
1667 // qPrint(resolvedType));
1668
1669 //printf(" mtype=%s\n",mType ? qPrint(mType->name()) : "<none>");
1670
1671 if (cd) // resolves to a known class type
1672 {
1673 if (cd==d && tSpec) *tSpec="";
1674
1675 if (mType && mType->isTypedef()) // but via a typedef
1676 {
1677 result = resolvedType+ts; // the +ts was added for bug 685125
1678 }
1679 else
1680 {
1681 if (isTemplInst)
1682 {
1683 // spec is already part of class type
1684 templSpec="";
1685 if (tSpec) *tSpec="";
1686 }
1687 else if (!ts.isEmpty() && templSpec.isEmpty())
1688 {
1689 // use formal template args for spec
1690 templSpec = stripDeclKeywords(getCanonicalTemplateSpec(d,fs,ts,lang));
1691 }
1692
1693 result = removeRedundantWhiteSpace(cd->qualifiedName() + templSpec);
1694
1695 if (cd->isTemplate() && tSpec) //
1696 {
1697 if (!templSpec.isEmpty()) // specific instance
1698 {
1699 result=cd->name()+templSpec;
1700 }
1701 else // use template type
1702 {
1704 }
1705 // template class, so remove the template part (it is part of the class name)
1706 *tSpec="";
1707 }
1708 else if (ts.isEmpty() && !templSpec.isEmpty() && cd && !cd->isTemplate() && tSpec)
1709 {
1710 // obscure case, where a class is used as a template, but doxygen think it is
1711 // not (could happen when loading the class from a tag file).
1712 *tSpec="";
1713 }
1714 }
1715 }
1716 else if (mType && mType->isEnumerate()) // an enum
1717 {
1718 result = mType->qualifiedName();
1719 }
1720 else if (mType && mType->isTypedef()) // a typedef
1721 {
1722 //result = mType->qualifiedName(); // changed after 1.7.2
1723 //result = mType->typeString();
1724 //printf("word=%s typeString=%s\n",qPrint(word),mType->typeString());
1725 if (word!=mType->typeString())
1726 {
1727 QCString type = mType->typeString();
1728 if (type.startsWith("typename "))
1729 {
1730 type.stripPrefix("typename ");
1732 }
1733 if (!type.isEmpty()) // see issue #11065
1734 {
1735 result = getCanonicalTypeForIdentifier(d,fs,type,mType->getLanguage(),tSpec,count+1);
1736 }
1737 else
1738 {
1739 result = word;
1740 }
1741 }
1742 else
1743 {
1744 result = mType->typeString();
1745 }
1746 }
1747 else // fallback
1748 {
1749 resolvedType = lang==SrcLangExt::Java ? word : resolveTypeDef(d,word);
1750 AUTO_TRACE_ADD("fallback resolvedType='{}'",resolvedType);
1751 if (resolvedType.isEmpty()) // not known as a typedef either
1752 {
1753 result = word;
1754 }
1755 else
1756 {
1757 result = resolvedType;
1758 }
1759 }
1760 AUTO_TRACE_EXIT("result='{}'",result);
1761 return result;
1762}
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:47
static QCString stripDeclKeywords(const QCString &s)
Definition util.cpp:1573
QCString stripScope(const QCString &name)
Definition util.cpp:3733
static QCString getCanonicalTemplateSpec(const Definition *d, const FileDef *fs, const QCString &spec, SrcLangExt lang)
Definition util.cpp:1589
QCString stripTemplateSpecifiersFromScope(const QCString &fullName, bool parentOnly, QCString *pLastScopeStripped, QCString scopeName, bool allowArtificial)
Definition util.cpp:4481

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

3275{
3276 auto caseSenseNames = Config_getEnum(CASE_SENSE_NAMES);
3277
3278 if (caseSenseNames == CASE_SENSE_NAMES_t::YES) return true;
3279 else if (caseSenseNames == CASE_SENSE_NAMES_t::NO) return false;
3281}
#define Config_getEnum(name)
Definition config.h:35

References Config_getEnum, and Portable::fileSystemIsCaseSensitive().

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

◆ getDefs()

GetDefResult getDefs ( const GetDefInput & input)

Definition at line 2248 of file util.cpp.

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

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

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

◆ getDotImageExtension()

QCString getDotImageExtension ( )

Definition at line 6258 of file util.cpp.

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

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

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

◆ getEncoding()

QCString getEncoding ( const FileInfo & fi)

Definition at line 5664 of file util.cpp.

5665{
5666 InputFileEncoding elem;
5667 auto getter = [](const InputFileEncoding &e) -> QCString { return e.pattern; };
5668 if (genericPatternMatch(fi,Doxygen::inputFileEncodingList,elem,getter)) // check for file specific encoding
5669 {
5670 return elem.encoding;
5671 }
5672 else // fall back to default encoding
5673 {
5674 return Config_getString(INPUT_ENCODING);
5675 }
5676}
static InputFileEncodingList inputFileEncodingList
Definition doxygen.h:139
#define Config_getString(name)
Definition config.h:32
QCString encoding
Definition doxygen.h:70
bool genericPatternMatch(const FileInfo &fi, const PatternList &patList, PatternElem &elem, PatternGet getter)
Definition util.cpp:5607

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

Referenced by readCodeFragment(), and readInputFile().

◆ getFileFilter()

QCString getFileFilter ( const QCString & name,
bool isSourceCode )

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

Definition at line 1372 of file util.cpp.

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

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

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

◆ getFileNameExtension()

◆ getFilterFromList()

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

Definition at line 1331 of file util.cpp.

1332{
1333 found=FALSE;
1334 // compare the file name to the filter pattern list
1335 for (const auto &filterStr : filterList)
1336 {
1337 QCString fs = filterStr;
1338 int i_equals=fs.find('=');
1339 if (i_equals!=-1)
1340 {
1341 QCString filterPattern = fs.left(i_equals);
1342 QCString input = name;
1344 {
1345 filterPattern = filterPattern.lower();
1346 input = input.lower();
1347 }
1348 reg::Ex re(filterPattern.str(),reg::Ex::Mode::Wildcard);
1349 if (re.isValid() && reg::match(input.str(),re))
1350 {
1351 // found a match!
1352 QCString filterName = fs.mid(i_equals+1);
1353 if (filterName.find(' ')!=-1)
1354 { // add quotes if the name has spaces
1355 filterName="\""+filterName+"\"";
1356 }
1357 found=TRUE;
1358 return filterName;
1359 }
1360 }
1361 }
1362
1363 // no match
1364 return "";
1365}

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

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

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

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

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

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

◆ getLanguageSpecificSeparator()

QCString getLanguageSpecificSeparator ( SrcLangExt lang,
bool classScope )

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

Definition at line 5866 of file util.cpp.

5867{
5868 if (lang==SrcLangExt::Java || lang==SrcLangExt::CSharp || lang==SrcLangExt::VHDL || lang==SrcLangExt::Python)
5869 {
5870 return ".";
5871 }
5872 else if (lang==SrcLangExt::PHP && !classScope)
5873 {
5874 return "\\";
5875 }
5876 else
5877 {
5878 return "::";
5879 }
5880}

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

◆ getMemberFromSymbol()

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

Definition at line 5216 of file util.cpp.

5218{
5219 if (scope==nullptr ||
5222 )
5223 )
5224 {
5226 }
5227
5228 QCString name = n;
5229 if (name.isEmpty())
5230 return nullptr; // no name was given
5231
5232 auto &range = Doxygen::symbolMap->find(name);
5233 if (range.empty())
5234 return nullptr; // could not find any matching symbols
5235
5236 // mostly copied from getResolvedClassRec()
5237 QCString explicitScopePart;
5238 int qualifierIndex = computeQualifiedIndex(name);
5239 if (qualifierIndex!=-1)
5240 {
5241 explicitScopePart = name.left(qualifierIndex);
5242 replaceNamespaceAliases(explicitScopePart);
5243 name = name.mid(qualifierIndex+2);
5244 }
5245 //printf("explicitScopePart=%s\n",qPrint(explicitScopePart));
5246
5247 int minDistance = 10000;
5248 MemberDef *bestMatch = nullptr;
5249
5250 for (Definition *d : range)
5251 {
5252 if (d->definitionType()==Definition::TypeMember)
5253 {
5254 SymbolResolver resolver(fileScope);
5255 int distance = resolver.isAccessibleFromWithExpScope(scope,d,explicitScopePart);
5256 if (distance!=-1 && distance<minDistance)
5257 {
5258 minDistance = distance;
5259 bestMatch = toMemberDef(d);
5260 //printf("new best match %s distance=%d\n",qPrint(bestMatch->qualifiedName()),distance);
5261 }
5262 }
5263 }
5264 return bestMatch;
5265}
static SymbolMap< Definition > * symbolMap
Definition doxygen.h:124
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:6793

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

4044{
4045 return theTranslator->trOverloadText();
4046 //"This is an overloaded member function, "
4047 // "provided for convenience. It differs from the above "
4048 // "function only in what argument(s) it accepts.";
4049}
Translator * theTranslator
Definition language.cpp:71

References theTranslator.

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

◆ getPrefixIndex()

int getPrefixIndex ( const QCString & name)

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

Definition at line 3185 of file util.cpp.

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

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

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

◆ getProjectId()

QCString getProjectId ( )

Definition at line 6780 of file util.cpp.

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

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

2320{
2321 cd=nullptr;
2322 cnd=nullptr;
2323 nd=nullptr;
2324 modd=nullptr;
2325
2326 QCString scopeName=scope;
2327 //printf("getScopeDefs: docScope='%s' scope='%s'\n",qPrint(docScope),qPrint(scope));
2328 if (scopeName.isEmpty()) return FALSE;
2329
2330 bool explicitGlobalScope=FALSE;
2331 if (scopeName.at(0)==':' && scopeName.at(1)==':')
2332 {
2333 scopeName=scopeName.right(scopeName.length()-2);
2334 explicitGlobalScope=TRUE;
2335 }
2336 if (scopeName.isEmpty())
2337 {
2338 return FALSE;
2339 }
2340
2341 QCString docScopeName=docScope;
2342 int scopeOffset=explicitGlobalScope ? 0 : static_cast<int>(docScopeName.length());
2343
2344 do // for each possible docScope (from largest to and including empty)
2345 {
2346 QCString fullName=scopeName;
2347 if (scopeOffset>0) fullName.prepend(docScopeName.left(scopeOffset)+"::");
2348
2349 if (((cd=getClass(fullName)) || // normal class
2350 (cd=getClass(fullName+"-p")) // ObjC protocol
2351 ) && cd->isLinkable())
2352 {
2353 return TRUE; // class link written => quit
2354 }
2355 else if ((nd=Doxygen::namespaceLinkedMap->find(fullName)) && nd->isLinkable())
2356 {
2357 return TRUE; // namespace link written => quit
2358 }
2359 else if ((cnd=Doxygen::conceptLinkedMap->find(fullName)) && cnd->isLinkable())
2360 {
2361 return TRUE; // concept link written => quit
2362 }
2363 else if ((modd=ModuleManager::instance().modules().find(fullName)) && modd->isLinkable())
2364 {
2365 return TRUE; // module link written => quit
2366 }
2367 if (scopeOffset==0)
2368 {
2369 scopeOffset=-1;
2370 }
2371 else if ((scopeOffset=docScopeName.findRev("::",scopeOffset-1))==-1)
2372 {
2373 scopeOffset=0;
2374 }
2375 } while (scopeOffset>=0);
2376
2377 return FALSE;
2378}
static NamespaceLinkedMap * namespaceLinkedMap
Definition doxygen.h:114
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 4593 of file util.cpp.

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

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

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

◆ guessSection()

EntryType guessSection ( const QCString & name)

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

Definition at line 339 of file util.cpp.

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

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

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

◆ initDefaultExtensionMapping()

void initDefaultExtensionMapping ( )

Definition at line 5091 of file util.cpp.

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

References updateLanguageMapping().

Referenced by initDoxygen().

◆ inlineArgListToDoc()

QCString inlineArgListToDoc ( const ArgumentList & al)

Definition at line 1159 of file util.cpp.

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

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

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

◆ inlineTemplateArgListToDoc()

QCString inlineTemplateArgListToDoc ( const ArgumentList & al)

Definition at line 1177 of file util.cpp.

1178{
1179 QCString paramDocs;
1180 if (al.hasTemplateDocumentation())
1181 {
1182 for (const Argument &a : al)
1183 {
1184 if (!a.docs.isEmpty())
1185 {
1186 if (!a.name.isEmpty())
1187 {
1188 paramDocs+=" \\ilinebr @tparam "+a.name+" "+a.docs;
1189 }
1190 else if (!a.type.isEmpty())
1191 {
1192 QCString type = a.type;
1193 type.stripPrefix("class ");
1194 type.stripPrefix("typename ");
1195 type = type.stripWhiteSpace();
1196 paramDocs+=" \\ilinebr @tparam "+type+" "+a.docs;
1197 }
1198 }
1199 }
1200 }
1201 return paramDocs;
1202}
bool hasTemplateDocumentation() const
Definition arguments.cpp:30

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

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

◆ insertTemplateSpecifierInScope()

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

Definition at line 3700 of file util.cpp.

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

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

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

◆ integerToRoman()

QCString integerToRoman ( int n,
bool upper )

Definition at line 6667 of file util.cpp.

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

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

◆ isLowerCase()

bool isLowerCase ( QCString & s)
static

Definition at line 2380 of file util.cpp.

2381{
2382 if (s.isEmpty()) return true;
2383 const char *p=s.data();
2384 int c=0;
2385 while ((c=static_cast<uint8_t>(*p++))) if (!islower(c)) return false;
2386 return true;
2387}

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

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

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

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

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

6639{
6640 std::string result;
6641 bool first=true;
6642 for (const auto &s : sv)
6643 {
6644 if (!first) result+=delimiter;
6645 first=false;
6646 result+=s;
6647 }
6648 return result;
6649}

◆ keyWordsFortranC()

bool keyWordsFortranC ( const char * contents)
static

Definition at line 6292 of file util.cpp.

6293{
6294 static const std::unordered_set<std::string> fortran_C_keywords = {
6295 "character", "call", "close", "common", "continue",
6296 "case", "contains", "cycle", "class", "codimension",
6297 "concurrent", "contiguous", "critical"
6298 };
6299
6300 if (*contents != 'c' && *contents != 'C') return false;
6301
6302 const char *c = contents;
6303 QCString keyword;
6304 while (*c && *c != ' ') {keyword += *c; c++;}
6305 keyword = keyword.lower();
6306
6307 return (fortran_C_keywords.find(keyword.str()) != fortran_C_keywords.end());
6308}

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

Referenced by recognizeFixedForm().

◆ langToString()

QCString langToString ( SrcLangExt lang)

Returns a string representation of lang.

Definition at line 5860 of file util.cpp.

5861{
5862 return to_string(lang);
5863}
static constexpr const char * to_string(Protection prot) noexcept
Definition types.h:38

References to_string().

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

◆ leftScopeMatch()

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

Definition at line 882 of file util.cpp.

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

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

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

◆ lineBlock()

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

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

See also
routine extractBlock

Definition at line 5839 of file util.cpp.

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

References QCString::find().

◆ linkifyText()

void linkifyText ( const TextGeneratorIntf & out,
const Definition * scope,
const FileDef * fileScope,
const Definition * self,
const QCString & text,
bool autoBreak,
bool external,
bool keepSpaces,
int indentLevel )

Definition at line 894 of file util.cpp.

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

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

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

◆ linkToText()

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

Definition at line 2648 of file util.cpp.

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

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

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

References Doxygen::mainPage.

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

◆ makeBaseName()

◆ mangleCSharpGenericName()

QCString mangleCSharpGenericName ( const QCString & name)

Definition at line 6882 of file util.cpp.

6883{
6884 int idx = name.find('<');
6885 if (idx!=-1)
6886 {
6887 return name.left(idx)+"-"+QCString().setNum(name.contains(",")+1)+"-g";
6888 }
6889 return name;
6890}
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 1905 of file util.cpp.

1910{
1911 AUTO_TRACE("src: scope={} type={} name={} canType={}, dst: scope={} type={} name={} canType={}",
1912 srcScope?srcScope->name():"",srcA.type,srcA.name,srcA.canType,
1913 dstScope?dstScope->name():"",dstA.type,dstA.name,dstA.canType);
1914 //printf(">> match argument: %s::'%s|%s' (%s) <-> %s::'%s|%s' (%s)\n",
1915 // srcScope ? qPrint(srcScope->name()) : "",
1916 // qPrint(srcA.type), qPrint(srcA.name), qPrint(srcA.canType),
1917 // dstScope ? qPrint(dstScope->name()) : "",
1918 // qPrint(dstA.type), qPrint(dstA.name), qPrint(dstA.canType));
1919
1920 QCString sSrcName = " "+srcA.name;
1921 QCString sDstName = " "+dstA.name;
1922 QCString srcType = srcA.type;
1923 QCString dstType = dstA.type;
1924 stripIrrelevantConstVolatile(srcType,false);
1925 stripIrrelevantConstVolatile(dstType,false);
1926 //printf("'%s'<->'%s'\n",qPrint(sSrcName),qPrint(dstType.right(sSrcName.length())));
1927 //printf("'%s'<->'%s'\n",qPrint(sDstName),qPrint(srcType.right(sDstName.length())));
1928 if (sSrcName==dstType.right(sSrcName.length()))
1929 { // case "unsigned int" <-> "unsigned int i"
1930 srcA.type+=sSrcName;
1931 srcA.name="";
1932 srcA.canType=""; // invalidate cached type value
1933 }
1934 else if (sDstName==srcType.right(sDstName.length()))
1935 { // case "unsigned int i" <-> "unsigned int"
1936 dstA.type+=sDstName;
1937 dstA.name="";
1938 dstA.canType=""; // invalidate cached type value
1939 }
1940
1941 {
1942 std::lock_guard lock(g_matchArgsMutex);
1943 if (srcA.canType.isEmpty() || dstA.canType.isEmpty())
1944 {
1945 // need to re-evaluate both see issue #8370
1946 srcA.canType = extractCanonicalArgType(srcScope,srcFileScope,srcA,lang);
1947 dstA.canType = extractCanonicalArgType(dstScope,dstFileScope,dstA,lang);
1948 }
1949 }
1950
1951 if (matchCanonicalTypes(srcScope,srcFileScope,srcA.canType,
1952 dstScope,dstFileScope,dstA.canType,
1953 lang))
1954 {
1955 MATCH
1956 AUTO_TRACE_EXIT("true");
1957 return TRUE;
1958 }
1959 else
1960 {
1961 //printf(" Canonical types do not match [%s]<->[%s]\n",
1962 // qPrint(srcA->canType),qPrint(dstA->canType));
1963 NOMATCH
1964 AUTO_TRACE_EXIT("false");
1965 return FALSE;
1966 }
1967}
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:1873
#define MATCH
Definition util.cpp:1870
static QCString extractCanonicalArgType(const Definition *d, const FileDef *fs, const Argument &arg, SrcLangExt lang)
Definition util.cpp:1840
#define NOMATCH
Definition util.cpp:1871
static std::mutex g_matchArgsMutex
Definition util.cpp:1863

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

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

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

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

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

1877{
1878 AUTO_TRACE("srcType='{}' dstType='{}'",srcType,dstType);
1879 if (srcType==dstType) return true;
1880
1881 // check if the types are function pointers
1882 int i1=srcType.find(")(");
1883 if (i1==-1) return false;
1884 int i2=dstType.find(")(");
1885 if (i1!=i2) return false;
1886
1887 // check if the result part of the function pointer types matches
1888 int j1=srcType.find("(");
1889 if (j1==-1 || j1>i1) return false;
1890 int j2=dstType.find("(");
1891 if (j2!=j1) return false;
1892 if (srcType.left(j1)!=dstType.left(j2)) return false; // different return types
1893
1894 // if srcType and dstType are both function pointers with the same return type,
1895 // then match against the parameter lists.
1896 // This way srcType='void (*fptr)(int x)' will match against `void (*fptr)(int y)' because
1897 // 'int x' matches 'int y'. A simple literal string match would treat these as different.
1898 auto srcAl = stringToArgumentList(lang,srcType.mid(i1+1));
1899 auto dstAl = stringToArgumentList(lang,dstType.mid(i2+1));
1900 return matchArguments2(srcScope,srcFileScope,srcType.left(j1),srcAl.get(),
1901 dstScope,dstFileScope,dstType.left(j2),dstAl.get(),
1902 true,lang);
1903}
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:1971

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

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

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

Referenced by buildFunctionList().

◆ mergeArguments()

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

Definition at line 2071 of file util.cpp.

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

6831{
6832 if (Config_getBool(CALL_GRAPH) !=md1->hasCallGraph()) md2->overrideCallGraph(md1->hasCallGraph());
6833 if (Config_getBool(CALLER_GRAPH)!=md1->hasCallerGraph()) md2->overrideCallerGraph(md1->hasCallerGraph());
6834 if (Config_getBool(CALL_GRAPH) !=md2->hasCallGraph()) md1->overrideCallGraph( md2->hasCallGraph());
6835 if (Config_getBool(CALLER_GRAPH)!=md2->hasCallerGraph()) md1->overrideCallerGraph(md2->hasCallerGraph());
6836
6837 if (Config_getBool(SHOW_ENUM_VALUES) !=md1->hasEnumValues()) md2->overrideEnumValues(md1->hasEnumValues());
6838 if (Config_getBool(SHOW_ENUM_VALUES) !=md2->hasEnumValues()) md1->overrideEnumValues( md2->hasEnumValues());
6839
6840 if (Config_getBool(REFERENCED_BY_RELATION)!=md1->hasReferencedByRelation()) md2->overrideReferencedByRelation(md1->hasReferencedByRelation());
6841 if (Config_getBool(REFERENCES_RELATION) !=md1->hasReferencesRelation()) md2->overrideReferencesRelation(md1->hasReferencesRelation());
6842 if (Config_getBool(REFERENCED_BY_RELATION)!=md2->hasReferencedByRelation()) md1->overrideReferencedByRelation(md2->hasReferencedByRelation());
6843 if (Config_getBool(REFERENCES_RELATION) !=md2->hasReferencesRelation()) md1->overrideReferencesRelation(md2->hasReferencesRelation());
6844
6845 if (Config_getBool(INLINE_SOURCES)!=md1->hasInlineSource()) md2->overrideInlineSource(md1->hasInlineSource());
6846 if (Config_getBool(INLINE_SOURCES)!=md2->hasInlineSource()) md1->overrideInlineSource(md2->hasInlineSource());
6847}
virtual bool hasReferencesRelation() const =0
virtual bool hasCallGraph() const =0
virtual bool hasInlineSource() const =0
virtual bool hasEnumValues() const =0
virtual bool hasCallerGraph() const =0
virtual bool hasReferencedByRelation() const =0
virtual void overrideReferencesRelation(bool e)=0
virtual void overrideReferencedByRelation(bool e)=0
virtual void overrideCallGraph(bool e)=0
virtual void overrideInlineSource(bool e)=0
virtual void overrideEnumValues(bool e)=0
virtual void overrideCallerGraph(bool e)=0

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

Referenced by combineDeclarationAndDefinition(), and findFriends().

◆ mergeScopes()

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

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

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

Definition at line 4548 of file util.cpp.

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

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

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

◆ nextUTF8CharPosition()

int nextUTF8CharPosition ( const QCString & utf8Str,
uint32_t len,
uint32_t startPos )
static

Definition at line 5278 of file util.cpp.

5279{
5280 if (startPos>=len) return len;
5281 uint8_t c = static_cast<uint8_t>(utf8Str[startPos]);
5282 int bytes=getUTF8CharNumBytes(c);
5283 if (c=='&') // skip over character entities
5284 {
5285 bytes=1;
5286 int (*matcher)(int) = nullptr;
5287 c = static_cast<uint8_t>(utf8Str[startPos+bytes]);
5288 if (c=='#') // numerical entity?
5289 {
5290 bytes++;
5291 c = static_cast<uint8_t>(utf8Str[startPos+bytes]);
5292 if (c=='x') // hexadecimal entity?
5293 {
5294 bytes++;
5295 matcher = std::isxdigit;
5296 }
5297 else // decimal entity
5298 {
5299 matcher = std::isdigit;
5300 }
5301 }
5302 else if (std::isalnum(c)) // named entity?
5303 {
5304 bytes++;
5305 matcher = std::isalnum;
5306 }
5307 if (matcher)
5308 {
5309 while ((c = static_cast<uint8_t>(utf8Str[startPos+bytes]))!=0 && matcher(c))
5310 {
5311 bytes++;
5312 }
5313 }
5314 if (c!=';')
5315 {
5316 bytes=1; // not a valid entity, reset bytes counter
5317 }
5318 }
5319 return startPos+bytes;
5320}

References getUTF8CharNumBytes().

Referenced by parseCommentAsText().

◆ normalizeNonTemplateArgumentsInString()

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

Definition at line 4254 of file util.cpp.

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

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

Referenced by findUsedClassesForClass().

◆ openOutputFile()

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

Definition at line 6265 of file util.cpp.

6266{
6267 assert(!f.is_open());
6268 bool fileOpened=FALSE;
6269 bool writeToStdout=outFile=="-";
6270 if (writeToStdout) // write to stdout
6271 {
6272 f.basic_ios<char>::rdbuf(std::cout.rdbuf());
6273 fileOpened = true;
6274 }
6275 else // write to file
6276 {
6277 FileInfo fi(outFile.str());
6278 if (fi.exists()) // create a backup
6279 {
6280 Dir dir;
6281 FileInfo backup(fi.filePath()+".bak");
6282 if (backup.exists()) // remove existing backup
6283 dir.remove(backup.filePath());
6284 dir.rename(fi.filePath(),fi.filePath()+".bak");
6285 }
6286 f = Portable::openOutputStream(outFile);
6287 fileOpened = f.is_open();
6288 }
6289 return fileOpened;
6290}
bool rename(const std::string &orgName, const std::string &newName, bool acceptsAbsPath=true) const
Definition dir.cpp:321
std::ofstream openOutputStream(const QCString &name, bool append=false)
Definition portable.cpp:649

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

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

◆ parseCommentAsHtml()

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

Definition at line 5378 of file util.cpp.

5379{
5380 std::lock_guard lock(g_docCacheMutex);
5381 auto it = g_docCache.find(doc.str());
5382 if (it != g_docCache.end())
5383 {
5384 //printf("Cache: [%s]->[%s]\n",qPrint(doc),qPrint(it->second));
5385 return it->second;
5386 }
5387 auto parser { createDocParser() };
5388 auto ast { validatingParseTitle(*parser.get(),fileName,lineNr,doc) };
5389 auto astImpl = dynamic_cast<const DocNodeAST*>(ast.get());
5390 QCString result;
5391 if (astImpl)
5392 {
5393 TextStream t;
5394 OutputCodeList codeList;
5395 codeList.add<HtmlCodeGenerator>(&t);
5396 HtmlDocVisitor visitor(t,codeList,scope,fileName);
5397 std::visit(visitor,astImpl->root);
5398 result = t.str();
5399 }
5400 else // fallback, should not happen
5401 {
5402 result = filterTitle(doc);
5403 }
5404 //printf("Conversion: [%s]->[%s]\n",qPrint(doc),qPrint(result));
5405 g_docCache.insert(std::make_pair(doc.str(),result));
5406 return result;
5407}
Class representing the abstract syntax tree of a documentation block.
Definition docnode.h:1466
Generator for HTML code fragments.
Definition htmlgen.h:26
Concrete visitor implementation for HTML output.
Class representing a list of different code generators.
Definition outputlist.h:165
void add(OutputCodeIntfPtr &&p)
Definition outputlist.h:195
Text streaming class that buffers data.
Definition textstream.h:36
std::string str() const
Return the contents of the buffer as a std::string object.
Definition textstream.h:216
IDocParserPtr createDocParser()
factory function to create a parser
Definition docparser.cpp:55
IDocNodeASTPtr validatingParseTitle(IDocParser &parserIntf, const QCString &fileName, int lineNr, const QCString &input)
static std::unordered_map< std::string, QCString > g_docCache
Definition util.cpp:5376
QCString filterTitle(const QCString &title)
Definition util.cpp:5583
static std::mutex g_docCacheMutex
Definition util.cpp:5375

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

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

◆ parseCommentAsText()

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

Definition at line 5322 of file util.cpp.

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

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

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

◆ patternMatch()

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

Definition at line 5657 of file util.cpp.

5658{
5659 std::string elem;
5660 auto getter = [](std::string s) -> QCString { return s; };
5661 return genericPatternMatch(fi,patList,elem,getter);
5662}

References genericPatternMatch().

Referenced by readDir().

◆ projectLogoFile()

QCString projectLogoFile ( )

Definition at line 3094 of file util.cpp.

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

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

Referenced by copyLogo(), and substituteKeywords().

◆ projectLogoSize()

QCString projectLogoSize ( )
static

Definition at line 3115 of file util.cpp.

3116{
3117 QCString sizeVal;
3118 QCString projectLogo = Config_getString(PROJECT_LOGO);
3119 if (!projectLogo.isEmpty())
3120 {
3121 auto extractDimension = [&projectLogo](const char *startMarker,size_t startPos,size_t endPos) -> QCString
3122 {
3123 QCString result = projectLogo.mid(startPos,endPos-startPos).stripWhiteSpace().quoted();
3124 if (result.length()>=2 && result.at(0)!='"' && result.at(result.length()-1)!='"')
3125 {
3126 result="\""+result+"\"";
3127 }
3128 result.prepend(startMarker);
3129 return result;
3130 };
3131 // check for optional width= and height= specifier
3132 int wi = projectLogo.find(" width=");
3133 int hi = projectLogo.find(" height=");
3134 if (wi!=-1 && hi!=-1)
3135 {
3136 if (wi<hi) // "... width=x height=y..."
3137 {
3138 sizeVal = extractDimension(" width=", wi+7, hi) + " "
3139 + extractDimension(" height=", hi+8, projectLogo.length());
3140 }
3141 else // "... height=y width=x..."
3142 {
3143 sizeVal = extractDimension(" height=", hi+8, wi) + " "
3144 + extractDimension(" width=", wi+7, projectLogo.length());
3145 }
3146 }
3147 else if (wi!=-1) // ... width=x..."
3148 {
3149 sizeVal = extractDimension(" width=", wi+7, projectLogo.length());
3150 }
3151 else if (hi!=-1) // ... height=x..."
3152 {
3153 sizeVal = extractDimension(" height=", hi+8, projectLogo.length());
3154 }
3155 }
3156 //printf("projectsize='%s'\n",qPrint(sizeVal));
3157 return sizeVal;
3158}
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 5906 of file util.cpp.

5907{
5908 bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
5909 bool extractPackage = Config_getBool(EXTRACT_PACKAGE);
5910
5911 return (prot!=Protection::Private && prot!=Protection::Package) ||
5912 (prot==Protection::Private && extractPrivate) ||
5913 (prot==Protection::Package && extractPackage);
5914}

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

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

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

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

◆ recognizeFixedForm()

bool recognizeFixedForm ( const QCString & contents,
FortranFormat format )

Definition at line 6312 of file util.cpp.

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

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

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

◆ recursivelyAddGroupListToTitle()

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

Definition at line 4826 of file util.cpp.

4827{
4828 ModuleDef *mod = root ? findModuleDef(d) : nullptr;
4829 if (!d->partOfGroups().empty() || mod!=nullptr) // write list of group to which this definition belongs
4830 {
4831 if (root)
4832 {
4833 ol.pushGeneratorState();
4835 ol.writeString("<div class=\"ingroups\">");
4836 }
4837 bool first=true;
4838 for (const auto &gd : d->partOfGroups())
4839 {
4840 if (!first) { ol.writeString(" &#124; "); } else first=false;
4842 {
4843 ol.writeString(" &raquo; ");
4844 }
4845 ol.writeObjectLink(gd->getReference(),gd->getOutputFileBase(),QCString(),gd->groupTitle());
4846 }
4847 if (root)
4848 {
4849 // add module as a group to the file as well
4850 if (mod)
4851 {
4852 if (!first) { ol.writeString(" &#124; "); } else first=false;
4853 ol.writeString(theTranslator->trModule(false,true)+" ");
4855 mod->displayName());
4856 }
4857 ol.writeString("</div>");
4858 ol.popGeneratorState();
4859 }
4860 return true;
4861 }
4862 return false;
4863}
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:4797

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

3534{
3535 QCString result;
3536 if (Config_getBool(CREATE_SUBDIRS))
3537 {
3538 if (name.isEmpty())
3539 {
3540 return REL_PATH_TO_ROOT;
3541 }
3542 else
3543 {
3544 int i = name.findRev('/');
3545 if (i!=-1)
3546 {
3547 result=REL_PATH_TO_ROOT;
3548 }
3549 }
3550 }
3551 return result;
3552}
#define REL_PATH_TO_ROOT
Definition util.cpp:95

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

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

◆ removeAnonymousScopes()

QCString removeAnonymousScopes ( const QCString & str)

Removes all anonymous scopes from string s Possible examples:

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

Definition at line 162 of file util.cpp.

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

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

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

◆ removeEmptyLines()

QCString removeEmptyLines ( const QCString & s)

Definition at line 6555 of file util.cpp.

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

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

Referenced by substituteHtmlKeywords(), and substituteLatexKeywords().

◆ removeLongPathMarker()

QCString removeLongPathMarker ( QCString path)

Definition at line 288 of file util.cpp.

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

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

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

◆ removeRedundantWhiteSpace()

QCString removeRedundantWhiteSpace ( const QCString & s)

Definition at line 568 of file util.cpp.

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

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

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

◆ replaceAnonymousScopes()

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

Definition at line 219 of file util.cpp.

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

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

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

◆ replaceColorMarkers()

QCString replaceColorMarkers ( const QCString & str)

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

Definition at line 5775 of file util.cpp.

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

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

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

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

◆ resolveRef()

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

Returns an object to reference to given its name and context

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

Definition at line 2392 of file util.cpp.

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

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

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

◆ resolveTypeDef()

QCString resolveTypeDef ( const Definition * context,
const QCString & qualifiedName,
const Definition ** typedefContext )

Definition at line 374 of file util.cpp.

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

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

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

◆ rightScopeMatch()

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

Definition at line 871 of file util.cpp.

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

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

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

◆ selectBlocks()

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

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

Definition at line 6378 of file util.cpp.

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

3082{
3083 // get the current date and time
3084 std::tm dat{};
3085 int specFormat=0;
3086 QCString specDate = "";
3087 QCString err = dateTimeFromString(specDate,dat,specFormat);
3088
3089 // do the conversion
3090 int usedFormat=0;
3091 return formatDateTime(fmt,dat,usedFormat);
3092}
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 2972 of file util.cpp.

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

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

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

◆ split() [1/2]

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

split input string s by regular expression delimiter delimiter.

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

Definition at line 6604 of file util.cpp.

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

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

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

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

◆ stackTrace()

void stackTrace ( )

Definition at line 5439 of file util.cpp.

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

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

◆ stripAnonymousNamespaceScope()

QCString stripAnonymousNamespaceScope ( const QCString & s)

Definition at line 231 of file util.cpp.

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

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

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

◆ stripDeclKeywords()

QCString stripDeclKeywords ( const QCString & s)
static

Definition at line 1573 of file util.cpp.

1574{
1575 int i=s.find(" class ");
1576 if (i!=-1) return s.left(i)+s.mid(i+6);
1577 i=s.find(" typename ");
1578 if (i!=-1) return s.left(i)+s.mid(i+9);
1579 i=s.find(" union ");
1580 if (i!=-1) return s.left(i)+s.mid(i+6);
1581 i=s.find(" struct ");
1582 if (i!=-1) return s.left(i)+s.mid(i+7);
1583 return s;
1584}

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

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

References Config_getList, and stripFromPath().

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

◆ stripFromPath() [1/2]

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

Definition at line 299 of file util.cpp.

300{
301 // look at all the strings in the list and strip the longest match
302 QCString potential;
304 size_t length = 0;
305 for (const auto &s : l)
306 {
307 QCString prefix = s;
308 if (prefix.length() > length &&
309 qstricmp(path.left(prefix.length()),prefix)==0) // case insensitive compare
310 {
311 length = prefix.length();
312 potential = path.right(path.length()-prefix.length());
313 }
314 }
315 if (length>0) return potential;
316 return path;
317}
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 DirDefImpl::DirDefImpl(), FileDefImpl::FileDefImpl(), generateAnonymousAnchor(), generateXMLForClass(), generateXMLForConcept(), generateXMLForDir(), generateXMLForFile(), generateXMLForMember(), generateXMLForModule(), generateXMLForNamespace(), generateXMLForPage(), insertPath(), markdownFileNameToId(), MarkdownOutlineParser::parseInput(), ModuleManager::resolveImports(), ClassDefImpl::showUsedFiles(), stripFromIncludePath(), stripFromPath(), ModuleDefImpl::writeFiles(), writeSingleFileIndex(), DirDefImpl::writeTagFile(), and FileDefImpl::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 322 of file util.cpp.

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

References Config_getList, and stripFromPath().

◆ stripIndentation()

QCString stripIndentation ( const QCString & s,
bool skipFirstLine )

Definition at line 5918 of file util.cpp.

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

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

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

◆ stripIndentationVerbatim()

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

Definition at line 6007 of file util.cpp.

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

1564{
1565 //printf("stripIrrelevantConstVolatile(%s)=",qPrint(s));
1566 stripIrrelevantString(s,"const",insideTemplate);
1567 stripIrrelevantString(s,"volatile",insideTemplate);
1568 stripIrrelevantString(s,"final",insideTemplate);
1569 //printf("%s\n",qPrint(s));
1570}
static void stripIrrelevantString(QCString &target, const QCString &str, bool insideTemplate)
Definition util.cpp:1503

References stripIrrelevantString().

Referenced by extractCanonicalType(), and matchArgument2().

◆ stripIrrelevantString()

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

Definition at line 1503 of file util.cpp.

1504{
1505 AUTO_TRACE("target='{}' str='{}'",target,str);
1506 if (target==str) { target.clear(); return; }
1507 int i=0,p=0;
1508 int l=static_cast<int>(str.length());
1509 bool changed=false;
1510 int sharpCount=0;
1511 while ((i=target.find(str,p))!=-1)
1512 {
1513 for (int q=p;q<i;q++)
1514 {
1515 if (target[q]=='<') sharpCount++;
1516 else if (target[q]=='>' && sharpCount>0) sharpCount--;
1517 }
1518 bool isMatch = (i==0 || !isId(target.at(i-1))) && // not a character before str
1519 (i+l==static_cast<int>(target.length()) || !isId(target.at(i+l))) && // not a character after str
1520 !insideTemplate && sharpCount==0; // not inside template, because e.g. <const A> is different than <A>, see issue #11663
1521 if (isMatch)
1522 {
1523 int i1=target.find('*',i+l);
1524 int i2=target.find('&',i+l);
1525 if (i1==-1 && i2==-1)
1526 {
1527 // strip str from target at index i
1528 target=target.left(i)+target.right(target.length()-i-l);
1529 changed=true;
1530 i-=l;
1531 }
1532 else if ((i1!=-1 && i<i1) || (i2!=-1 && i<i2)) // str before * or &
1533 {
1534 // move str to front
1535 target=str+" "+target.left(i)+target.right(target.length()-i-l);
1536 changed=true;
1537 i++;
1538 }
1539 }
1540 p = i+l;
1541 }
1542 if (changed) target=target.stripWhiteSpace();
1543 AUTO_TRACE_EXIT("target='{}'",target,str);
1544}

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

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

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

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

◆ stripPath()

QCString stripPath ( const QCString & s)

Definition at line 4902 of file util.cpp.

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

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

Referenced by LatexGenerator::addLabel(), anonymous_namespace{tagreader.cpp}::TagFileParser::buildLists(), RTFGenerator::endDoxyAnchor(), LatexGenerator::endIndexItem(), LatexGenerator::endIndexValue(), LatexGenerator::endTitleHead(), makeBaseName(), objectLinkToString(), objectLinkToString(), objectLinkToString(), 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()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), XmlDocVisitor::operator()(), XmlDocVisitor::operator()(), XmlDocVisitor::operator()(), XmlDocVisitor::operator()(), XmlDocVisitor::operator()(), DotFilePatcher::run(), SearchIndexExternal::setCurrentDoc(), DocbookGenerator::startDoxyAnchor(), LatexGenerator::startDoxyAnchor(), DocbookGenerator::startFile(), LatexGenerator::startFile(), RTFGenerator::startFile(), DocbookDocVisitor::startLink(), LatexDocVisitor::startLink(), RTFDocVisitor::startLink(), 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::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 3733 of file util.cpp.

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

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

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

◆ stripTemplateSpecifiersFromScope()

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

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

Definition at line 4481 of file util.cpp.

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

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

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

◆ substituteKeywords() [1/2]

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

Definition at line 3008 of file util.cpp.

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

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

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

◆ substituteKeywords() [2/2]

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

Definition at line 3160 of file util.cpp.

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

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

◆ substituteTemplateArgumentsInString()

QCString substituteTemplateArgumentsInString ( const QCString & nm,
const ArgumentList & formalArgs,
const ArgumentList * actualArgs )

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

Definition at line 4319 of file util.cpp.

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

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

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

◆ tempArgListToString()

QCString tempArgListToString ( const ArgumentList & al,
SrcLangExt lang,
bool includeDefault )

Definition at line 1249 of file util.cpp.

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

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

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

◆ transcodeCharacterBuffer()

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

Definition at line 5467 of file util.cpp.

5469{
5470 if (inputEncoding.isEmpty() || outputEncoding.isEmpty()) return; // no encoding specified
5471 if (qstricmp(inputEncoding,outputEncoding)==0) return; // input encoding same as output encoding
5472 void *cd = portable_iconv_open(outputEncoding.data(),inputEncoding.data());
5473 if (cd==reinterpret_cast<void *>(-1))
5474 {
5475 term("unsupported character conversion: '{}'->'{}': {}\n"
5476 "Check the INPUT_ENCODING setting in the config file!\n",
5477 inputEncoding,outputEncoding,strerror(errno));
5478 }
5479 size_t iLeft = contents.size();
5480 const char *srcPtr = contents.data();
5481 size_t tmpBufSize = contents.size()*4+1;
5482 size_t oLeft = tmpBufSize;
5483 std::string tmpBuf;
5484 tmpBuf.resize(tmpBufSize);
5485 char *dstPtr = tmpBuf.data();
5486 size_t newSize=0;
5487 if (!portable_iconv(cd, &srcPtr, &iLeft, &dstPtr, &oLeft))
5488 {
5489 newSize = tmpBufSize-oLeft;
5490 tmpBuf.resize(newSize);
5491 std::swap(contents,tmpBuf);
5492 //printf("iconv: input size=%d output size=%d\n[%s]\n",size,newSize,qPrint(srcBuf));
5493 }
5494 else
5495 {
5496 term("{}: failed to translate characters from {} to {}: check INPUT_ENCODING\n",
5497 fileName,inputEncoding,outputEncoding);
5498 }
5500}
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 1406 of file util.cpp.

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

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

1482{
1483 //printf("trimBaseClassScope level=%d '%s'\n",level,qPrint(s));
1484 for (const auto &bcd : bcl)
1485 {
1486 ClassDef *cd=bcd.classDef;
1487 //printf("Trying class %s\n",qPrint(cd->name()));
1488 int spos=s.find(cd->name()+"::");
1489 if (spos!=-1)
1490 {
1491 s = s.left(spos)+s.right(
1492 s.length()-spos-cd->name().length()-2
1493 );
1494 }
1495 //printf("base class '%s'\n",qPrint(cd->name()));
1496 if (!cd->baseClasses().empty())
1497 {
1498 trimBaseClassScope(cd->baseClasses(),s,level+1);
1499 }
1500 }
1501}
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:1481

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

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

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

◆ updateColumnCount()

size_t updateColumnCount ( const char * s,
size_t col )

Definition at line 6849 of file util.cpp.

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

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

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

5752{
5753 int hue = Config_getInt(HTML_COLORSTYLE_HUE);
5754 int sat = Config_getInt(HTML_COLORSTYLE_SAT);
5755 int gamma = Config_getInt(HTML_COLORSTYLE_GAMMA);
5756 while (data->name)
5757 {
5758 QCString fileName = dir+"/"+data->name;
5759 ColoredImage img(data->width,data->height,data->content,data->alpha,
5760 sat,hue,gamma);
5761 if (!img.save(fileName))
5762 {
5763 fprintf(stderr,"Warning: Cannot open file %s for writing\n",data->name);
5764 }
5765 Doxygen::indexList->addImageFile(data->name);
5766 data++;
5767 }
5768}
Class representing a bitmap image colored based on hue/sat/gamma settings.
Definition image.h:56
static IndexList * indexList
Definition doxygen.h:133
const unsigned char * content
Definition util.h:419
unsigned short height
Definition util.h:418
const unsigned char * alpha
Definition util.h:420
unsigned short width
Definition util.h:417
const char * name
Definition util.h:416

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

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

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

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

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

6929{
6930 uint8_t md5_sig[16];
6931 char sigStr[33];
6932 MD5Buffer(content.data(),static_cast<unsigned int>(content.length()),md5_sig);
6933 MD5SigToString(md5_sig,sigStr);
6934
6935 QCString fileName = baseName + sigStr + extension;
6936 { // ==== start atomic section
6937 std::lock_guard lock(writeFileContents_lock);
6938 auto it=writeFileContents_set.find(fileName.str());
6939 exists = it!=writeFileContents_set.end();
6940 if (!exists)
6941 {
6942 writeFileContents_set.insert(fileName.str());
6943 if (auto file = Portable::openOutputStream(fileName); file.is_open())
6944 {
6945 file.write( content.data(), content.length() );
6946 file.close();
6947 }
6948 else
6949 {
6950 err("Could not open file {} for writing\n",fileName);
6951 return QCString();
6952 }
6953 }
6954 } // ==== end atomic section
6955 return fileName;
6956}
static std::mutex writeFileContents_lock
Definition util.cpp:6917

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

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

◆ writeMarkerList()

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

Definition at line 1106 of file util.cpp.

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

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

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

◆ writePageRef()

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

◆ writeTypeConstraints()

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

Definition at line 5412 of file util.cpp.

5413{
5414 if (al.empty()) return;
5415 ol.startConstraintList(theTranslator->trTypeConstraints());
5416 for (const Argument &a : al)
5417 {
5419 ol.parseText(a.name);
5420 ol.endConstraintParam();
5422 linkifyText(TextGeneratorOLImpl(ol),d,nullptr,nullptr,a.type);
5423 ol.endConstraintType();
5425 ol.generateDoc(d->docFile(),
5426 d->docLine(),
5427 d,
5428 nullptr,
5429 a.docs,
5430 DocOptions()
5431 .setIndexWords(true));
5432 ol.endConstraintDocs();
5433 }
5434 ol.endConstraintList();
5435}
virtual int docLine() const =0
void endConstraintType()
Definition outputlist.h:714
void endConstraintList()
Definition outputlist.h:720
void startConstraintParam()
Definition outputlist.h:708
void generateDoc(const QCString &fileName, int startLine, const Definition *ctx, const MemberDef *md, const QCString &docStr, const DocOptions &options)
void startConstraintDocs()
Definition outputlist.h:716
void startConstraintType()
Definition outputlist.h:712
void endConstraintDocs()
Definition outputlist.h:718
void endConstraintParam()
Definition outputlist.h:710
void startConstraintList(const QCString &header)
Definition outputlist.h:706
Implements TextGeneratorIntf for an OutputDocInterface stream.
Definition util.h:76
void linkifyText(const TextGeneratorIntf &out, const Definition *scope, const FileDef *fileScope, const Definition *self, const QCString &text, bool autoBreak, bool external, bool keepSpaces, int indentLevel)
Definition util.cpp:894

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

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

Variable Documentation

◆ constScope

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

Definition at line 521 of file util.cpp.

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

Referenced by removeRedundantWhiteSpace().

◆ g_charAroundSpace

CharAroundSpace g_charAroundSpace
static

Definition at line 565 of file util.cpp.

Referenced by removeRedundantWhiteSpace().

◆ g_docCache

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

Definition at line 5376 of file util.cpp.

Referenced by parseCommentAsHtml().

◆ g_docCacheMutex

std::mutex g_docCacheMutex
static

Definition at line 5375 of file util.cpp.

Referenced by parseCommentAsHtml().

◆ g_extLookup

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

Definition at line 5025 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 2842 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 5035 of file util.cpp.

5036{
5037// language parser parser option
5038 { "idl", "c", SrcLangExt::IDL, ".idl" },
5039 { "java", "c", SrcLangExt::Java, ".java"},
5040 { "javascript", "c", SrcLangExt::JS, ".js" },
5041 { "csharp", "c", SrcLangExt::CSharp, ".cs" },
5042 { "d", "c", SrcLangExt::D, ".d" },
5043 { "php", "c", SrcLangExt::PHP, ".php" },
5044 { "objective-c", "c", SrcLangExt::ObjC, ".m" },
5045 { "c", "c", SrcLangExt::Cpp, ".c" },
5046 { "c++", "c", SrcLangExt::Cpp, ".cpp" },
5047 { "slice", "c", SrcLangExt::Slice, ".ice" },
5048 { "python", "python", SrcLangExt::Python, ".py" },
5049 { "fortran", "fortran", SrcLangExt::Fortran, ".f" },
5050 { "fortranfree", "fortranfree", SrcLangExt::Fortran, ".f90" },
5051 { "fortranfixed", "fortranfixed", SrcLangExt::Fortran, ".f" },
5052 { "vhdl", "vhdl", SrcLangExt::VHDL, ".vhdl"},
5053 { "xml", "xml", SrcLangExt::XML, ".xml" },
5054 { "sql", "sql", SrcLangExt::SQL, ".sql" },
5055 { "md", "md", SrcLangExt::Markdown, ".md" },
5056 { "lex", "lex", SrcLangExt::Lex, ".l" },
5057};

Referenced by getLanguageFromCodeLang(), and updateLanguageMapping().

◆ g_matchArgsMutex

std::mutex g_matchArgsMutex
static

Definition at line 1863 of file util.cpp.

Referenced by matchArgument2().

◆ g_usedNames

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

Definition at line 3448 of file util.cpp.

Referenced by convertNameToFile().

◆ g_usedNamesCount

int g_usedNamesCount =1
static

Definition at line 3450 of file util.cpp.

Referenced by convertNameToFile().

◆ g_usedNamesMutex

std::mutex g_usedNamesMutex
static

Definition at line 3449 of file util.cpp.

Referenced by convertNameToFile().

◆ hex

const char* hex = "0123456789ABCDEF"
static

Definition at line 97 of file util.cpp.

◆ operatorScope

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

Definition at line 524 of file util.cpp.

524{ '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 523 of file util.cpp.

523{ '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 522 of file util.cpp.

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

Referenced by removeRedundantWhiteSpace().

◆ writeFileContents_lock

std::mutex writeFileContents_lock
static

Definition at line 6917 of file util.cpp.

Referenced by writeFileContents().

◆ writeFileContents_set

StringUnorderedSet writeFileContents_set
static

Definition at line 6918 of file util.cpp.

Referenced by cleanupInlineGraph(), and writeFileContents().