Doxygen
Loading...
Searching...
No Matches
util.cpp File Reference
#include "util.h"
#include <algorithm>
#include <cctype>
#include <cinttypes>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <mutex>
#include <unordered_set>
#include "arguments.h"
#include "classdef.h"
#include "classlist.h"
#include "conceptdef.h"
#include "config.h"
#include "datetime.h"
#include "debug.h"
#include "defargs.h"
#include "dir.h"
#include "dirdef.h"
#include "doxygen.h"
#include "example.h"
#include "filedef.h"
#include "fileinfo.h"
#include "filename.h"
#include "groupdef.h"
#include "htmlentity.h"
#include "image.h"
#include "language.h"
#include "md5hash.h"
#include "membername.h"
#include "message.h"
#include "moduledef.h"
#include "namespacedef.h"
#include "outputlist.h"
#include "pagedef.h"
#include "parserintf.h"
#include "portable.h"
#include "regex.h"
#include "stringutil.h"
#include "symbolresolver.h"
#include "textstream.h"
#include "trace.h"
#include "utf8.h"
Include dependency graph for util.cpp:

Go to the source code of this file.

Classes

struct  CharAroundSpace
struct  CharAroundSpace::CharElem
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

DString removeAnonymousScopes (const DString &str)
DString replaceAnonymousScopes (const DString &s, const DString &replacement)
DString stripAnonymousNamespaceScope (const DString &s)
static DString stripFromPath (const DString &p, StringVector l)
DString stripFromPath (const DString &path)
DString stripFromIncludePath (const DString &path)
DString resolveTypeDef (const Definition *context, const DString &qualifiedName, const Definition **typedefContext)
DString removeRedundantWhiteSpace (const DString &s)
static size_t findParameterList (const DString &name)
 Returns the position in the string where a function parameter list begins, or DString::npos if one is not found.
bool rightScopeMatch (const DString &scope, const DString &name)
bool leftScopeMatch (const DString &scope, const DString &name)
void writeMarkerList (OutputList &ol, const std::string &markerText, size_t numMarkers, std::function< void(size_t)> replaceFunc)
DString writeMarkerList (const std::string &markerText, size_t numMarkers, std::function< DString(size_t)> replaceFunc)
void writeExamples (OutputList &ol, const ExampleList &list)
DString inlineTemplateArgListToDoc (const ArgumentList &al)
DString argListToString (const ArgumentList &al, bool useCanonicalType, bool showDefVals)
DString tempArgListToString (const ArgumentList &al, SrcLangExt lang, bool includeDefault)
static void filterCRLF (std::string &contents)
static DString getFilterFromList (const DString &name, const StringVector &filterList, bool &found)
DString getFileFilter (const DString &name, bool isSourceCode)
DString fileToString (const DString &name, bool filter, bool isSourceCode)
void trimBaseClassScope (const BaseClassList &bcl, DString &s, int level=0)
static void stripIrrelevantString (DString &target, const DString &str, bool insideTemplate)
void stripIrrelevantConstVolatile (DString &s, bool insideTemplate)
static DString stripDeclKeywords (const DString &s)
static DString extractCanonicalType (const Definition *d, const FileDef *fs, DString type, SrcLangExt lang, bool insideTemplate)
static DString getCanonicalTemplateSpec (const Definition *d, const FileDef *fs, const DString &spec, SrcLangExt lang)
static DString getCanonicalTypeForIdentifier (const Definition *d, const FileDef *fs, const DString &word, SrcLangExt lang, DString *tSpec, int count=0)
static DString extractCanonicalArgType (const Definition *d, const FileDef *fs, const Argument &arg, SrcLangExt lang)
static bool matchCanonicalTypes (const Definition *srcScope, const FileDef *srcFileScope, const DString &srcType, const Definition *dstScope, const FileDef *dstFileScope, const DString &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 DString &srcReturnType, const ArgumentList *srcAl, const Definition *dstScope, const FileDef *dstFileScope, const DString &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 DString &docScope, const DString &scope, ClassDef *&cd, ConceptDef *&cnd, NamespaceDef *&nd, ModuleDef *&modd)
static bool isLowerCase (DString &s)
bool resolveRef (const DString &scName, const DString &name, bool inSeeBlock, const Definition **resContext, const MemberDef **resMember, SrcLangExt lang, bool lookForSpecialization, const FileDef *currentFile, bool checkScope)
DString linkToText (SrcLangExt lang, const DString &link, bool ignoreDots)
static const DirDefresolveDirLink (const DString &linkRef)
bool resolveLink (const DString &scName, const DString &lr, bool, const Definition **resContext, DString &resAnchor, SrcLangExt lang, const DString &prefix)
DString findExampleFilePath (const DString &file, bool &ambig)
DString substituteKeywords (const DString &file, const DString &s, const KeywordSubstitutionList &keywords)
DString showDate (const DString &fmt)
DString projectLogoFile ()
DString projectLogoSize ()
int getPrefixIndex (const DString &name)
bool useCaseSenseNames ()
 Returns true if the names of the symbols can be case sensitive.
DString escapeCharsInString (const DString &name, bool allowDots, bool allowUnderscore)
DString unescapeCharsInString (const DString &s)
DString convertNameToFile (const DString &name, bool allowDots, bool allowUnderscore)
DString relativePathToRoot (const DString &name)
DString determineAbsoluteIncludeName (const DString &curFile, const DString &incFileName)
void createSubDirs (const Dir &d)
void clearSubDirs (const Dir &d)
void extractNamespaceName (const DString &scopeName, DString &className, DString &namespaceName, bool allowEmptyClass)
DString insertTemplateSpecifierInScope (const DString &scope, const DString &templ)
DString stripScope (const DString &name)
DString convertToId (const DString &s)
DString convertToXML (const DString &s, bool keepEntities, const bool citeEntry)
DString convertToHtml (const DString &s, bool keepEntities)
DString convertToJSString (const DString &s, bool keepEntities, bool singleQuotes)
int extractClassNameFromType (const DString &type, int &pos, DString &name, DString &templSpec, SrcLangExt lang)
DString normalizeNonTemplateArgumentsInString (const DString &name, const Definition *context, const ArgumentList &formalArgs)
DString substituteTemplateArgumentsInString (const DString &nm, const ArgumentList &formalArgs, const ArgumentList *actualArgs)
DString stripTemplateSpecifiersFromScope (const DString &fullName, bool parentOnly, DString *pLastScopeStripped, DString scopeName, bool allowArtificial)
DString mergeScopes (const DString &leftScope, const DString &rightScope)
int getScopeFragment (const DString &s, int p, int *l)
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 DString &fName, const DString &ext)
void addHtmlExtensionIfMissing (DString &fName)
DString stripExtensionGeneral (const DString &fName, const DString &ext)
DString stripExtension (const DString &fName)
DString stripPath (const DString &s)
DString makeBaseName (const DString &name, const DString &ext)
DString stripLeadingAndTrailingEmptyLines (const DString &s, int &docLine)
 Special version of DString::stripWhiteSpace() that only strips completely blank lines.
bool updateLanguageMapping (const DString &extension, const DString &language)
void initDefaultExtensionMapping ()
void addCodeOnlyMappings ()
SrcLangExt getLanguageFromFileName (const DString &fileName, SrcLangExt defLang)
SrcLangExt getLanguageFromCodeLang (DString &fileName)
 Routine to handle the language attribute of the \code command.
DString getFileNameExtension (const DString &fn)
static MemberDefgetMemberFromSymbol (const Definition *scope, const FileDef *fileScope, const DString &n)
bool checkIfTypedef (const Definition *scope, const FileDef *fileScope, const DString &n)
void writeTypeConstraints (OutputList &ol, const Definition *d, const ArgumentList &al)
void stackTrace ()
static void transcodeCharacterBuffer (const DString &fileName, std::string &contents, const DString &inputEncoding, const DString &outputEncoding)
bool readInputFile (const DString &fileName, std::string &contents, bool filter, bool isSourceCode)
 read a file name fileName and optionally filter and transcode it
DString filterTitle (const DString &title)
DString getEncoding (const FileInfo &fi)
DString externalLinkTarget (const bool parent)
DString createHtmlUrl (const DString &relPath, const DString &ref, bool isLocalFile, const DString &targetFileName, const DString &anchor)
DString externalRef (const DString &relPath, const DString &ref)
DString replaceColorMarkers (const DString &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 DString &src, const DString &dest)
 Copies the contents of file with name src to the newly created file with name dest.
DString getLanguageSpecificSeparator (SrcLangExt lang, bool classScope)
bool isURL (const DString &url)
 Checks whether the given url starts with a supported protocol.
DString correctURL (const DString &url, const DString &relPath)
 Corrects URL url according to the relative path relPath.
bool protectionLevelVisible (Protection prot)
DString stripIndentation (const DString &s, bool skipFirstLine)
void stripIndentationVerbatim (DString &doc, size_t indentationLevel, bool skipFirstLine)
static DString extractDirection (DString &docs)
 Strip the direction part from docs and return it as a string in canonical form.
DString inlineArgListToDoc (const ArgumentList &al)
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 ()
DString getDotImageExtension ()
bool openOutputFile (const DString &outFile, std::ofstream &f)
DString selectBlocks (const DString &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 DString &s, const DString fileName, const SelectionMarkerInfo &markerInfo)
DString detab (const DString &s, size_t &refIndent)
DString getProjectId ()
int computeQualifiedIndex (const DString &name)
 Return the index of the last :: in the string name that is still before the first <.
DString mangleCSharpGenericName (const DString &name)
DString demangleCSharpGenericName (const DString &name, const DString &templArgs)
DString extractBeginRawStringDelimiter (const char *rawStart)
DString extractEndRawStringDelimiter (const char *rawEnd)
DString writeInlineGraph (const DString &baseName, const DString &extension, const DString &content, bool &exists)
void cleanupInlineGraphs ()

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 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 writeFileContents_lock
static StringUnorderedSet writeFileContents_set

Macro Definition Documentation

◆ ENABLE_TRACINGSUPPORT

#define ENABLE_TRACINGSUPPORT   0

Definition at line 65 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 1488 of file util.cpp.

Referenced by matchArgument2(), and matchArguments2().

◆ NOMATCH

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

Definition at line 1489 of file util.cpp.

Referenced by matchArgument2(), and matchArguments2().

◆ REL_PATH_TO_ROOT

#define REL_PATH_TO_ROOT   "../../"

Definition at line 78 of file util.cpp.

Referenced by relativePathToRoot().

Function Documentation

◆ addCodeOnlyMappings()

void addCodeOnlyMappings ( )

Definition at line 4162 of file util.cpp.

4163{
4164 updateLanguageMapping(".xml", "xml");
4165 updateLanguageMapping(".sql", "sql");
4166}
bool updateLanguageMapping(const DString &extension, const DString &language)
Definition util.cpp:4063

References updateLanguageMapping().

Referenced by generateOutput().

◆ addGroupListToTitle()

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

◆ addHtmlExtensionIfMissing()

void addHtmlExtensionIfMissing ( DString & fName)

Definition at line 3931 of file util.cpp.

3932{
3933 if (fName.empty()) return;
3934 size_t i_fs = fName.rfind('/');
3935 size_t i_bs = fName.rfind('\\');
3936 size_t p = i_fs!=DString::npos && i_bs!=DString::npos ? std::max(i_fs, i_bs) :
3937 i_fs!=DString::npos ? i_fs : i_bs!=DString::npos ? i_bs : 0;
3938 size_t i = fName.find('.',p); // search for . after path part
3939 if (i==DString::npos)
3940 {
3942 }
3943}
A String class for use with Doxygen wrapping std::string and adding some additional functionality off...
Definition dstring.h:84
size_t rfind(char c, size_t pos=npos) const
Definition dstring.h:244
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:148
static constexpr size_t npos
value used to indicate 'not found' or 'to the end of the string', matching std::string::npos
Definition dstring.h:178
size_t find(char c, size_t pos=0) const
Definition dstring.h:239
static DString htmlFileExtension
Definition doxygen.h:115

References DString::empty(), DString::find(), Doxygen::htmlFileExtension, DString::npos, and DString::rfind().

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

◆ argListToString()

DString argListToString ( const ArgumentList & al,
bool useCanonicalType = false,
bool showDefVals = true )

Returns a string representation of the parameter list al. If useCanonicalType is true then the canonical type is used for each argument. If showDefVals is true then default values are included in the string representation.

Definition at line 859 of file util.cpp.

860{
861 DString result;
862 if (!al.hasParameters()) return result;
863 result+="(";
864 for (auto it = al.begin() ; it!=al.end() ;)
865 {
866 Argument a = *it;
867 DString type1 = useCanonicalType && !a.canType.empty() ? a.canType : a.type;
868 DString type2;
869 if (size_t i=type1.find(")("); i!=DString::npos) // hack to deal with function pointers
870 {
871 type2=type1.mid(i);
872 type1=type1.left(i);
873 }
874 if (!a.attrib.empty())
875 {
876 result+=a.attrib+" ";
877 }
878 if (!a.name.empty() || !a.array.empty())
879 {
880 result+= type1+" "+a.name+type2+a.array;
881 }
882 else
883 {
884 result+= type1+type2;
885 }
886 if (!a.defval.empty() && showDefVals)
887 {
888 result+="="+a.defval;
889 }
890 ++it;
891 if (it!=al.end()) result+=", ";
892 }
893 result+=")";
894 if (al.constSpecifier()) result+=" const";
895 if (al.volatileSpecifier()) result+=" volatile";
896 if (al.refQualifier()==RefQualifierType::LValue) result+=" &";
897 else if (al.refQualifier()==RefQualifierType::RValue) result+=" &&";
898 if (!al.trailingReturnType().empty()) result+=al.trailingReturnType();
899 if (al.pureSpecifier()) result+=" =0";
900 return removeRedundantWhiteSpace(result);
901}
This class contains the information about the argument of a function or template.
Definition arguments.h:27
DString attrib
Definition arguments.h:42
DString defval
Definition arguments.h:47
DString array
Definition arguments.h:46
DString name
Definition arguments.h:45
DString type
Definition arguments.h:43
DString canType
Definition arguments.h:44
RefQualifierType refQualifier() const
Definition arguments.h:117
bool pureSpecifier() const
Definition arguments.h:114
iterator end()
Definition arguments.h:95
bool hasParameters() const
Definition arguments.h:77
DString trailingReturnType() const
Definition arguments.h:115
bool constSpecifier() const
Definition arguments.h:112
iterator begin()
Definition arguments.h:94
bool volatileSpecifier() const
Definition arguments.h:113
DString mid(size_t index, size_t len=npos) const
Definition dstring.h:318
DString left(size_t len) const
Definition dstring.h:306
DString removeRedundantWhiteSpace(const DString &s)
Definition util.cpp:426

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

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

◆ checkBlocks()

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

Definition at line 5114 of file util.cpp.

5115{
5116 if (s.empty()) return;
5117
5118 const char *p = s.data();
5119 char c = 0;
5120 while ((c=*p))
5121 {
5122 if (c==markerInfo.markerChar) // potential start of marker
5123 {
5124 if (dstrncmp(p,markerInfo.beginStr,markerInfo.beginLen)==0) // start of begin marker
5125 {
5126 size_t len = markerInfo.beginLen;
5127 bool negate = *(p+len)=='!';
5128 if (negate) len++;
5129 p += len;
5130 DString marker;
5131 while (*p)
5132 {
5133 if (markerInfo.closeLen==0 && *p=='\n') // matching end of line
5134 {
5135 warn(fileName,-1,"Remaining begin replacement with marker '{}'",marker);
5136 break;
5137 }
5138 else if (markerInfo.closeLen!= 0 && dstrncmp(p,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
5139 {
5140 p += markerInfo.closeLen;
5141 warn(fileName,-1,"Remaining begin replacement with marker '{}'",marker);
5142 break;
5143 }
5144 marker += *p;
5145 p++;
5146 }
5147 }
5148 else if (dstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // start of end marker
5149 {
5150 size_t len = markerInfo.endLen;
5151 bool negate = *(p+len)=='!';
5152 if (negate) len++;
5153 p += len;
5154 DString marker;
5155 while (*p)
5156 {
5157 if (markerInfo.closeLen==0 && *p=='\n') // matching end of line
5158 {
5159 warn(fileName,-1,"Remaining end replacement with marker '{}'",marker);
5160 break;
5161 }
5162 else if (markerInfo.closeLen!= 0 && dstrncmp(p,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
5163 {
5164 p += markerInfo.closeLen;
5165 warn(fileName,-1,"Remaining end replacement with marker '{}'",marker);
5166 break;
5167 }
5168 marker += *p;
5169 p++;
5170 }
5171 }
5172 }
5173 p++;
5174 }
5175}
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition dstring.h:157
int dstrncmp(const char *str1, const char *str2, size_t len)
Definition dstring.h:56
#define warn(file, line, fmt,...)
Definition message.h:97
size_t beginLen
Definition util.h:219
const char * closeStr
Definition util.h:222
const char * beginStr
Definition util.h:218
size_t closeLen
Definition util.h:223
const char * endStr
Definition util.h:220

References SelectionMarkerInfo::beginLen, SelectionMarkerInfo::beginStr, SelectionMarkerInfo::closeLen, SelectionMarkerInfo::closeStr, DString::data(), dstrncmp(), DString::empty(), SelectionMarkerInfo::endLen, SelectionMarkerInfo::endStr, SelectionMarkerInfo::markerChar, and warn.

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

◆ checkExtension()

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

Definition at line 3926 of file util.cpp.

3927{
3928 return fName.right(ext.length())==ext;
3929}
DString right(size_t len) const
Definition dstring.h:311
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition dstring.h:151

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

Referenced by copyLatexStyleSheet(), and extraLatexStyleSheet().

◆ checkIfTypedef()

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

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

Definition at line 4271 of file util.cpp.

4272{
4273 MemberDef *bestMatch = getMemberFromSymbol(scope,fileScope,n);
4274
4275 if (bestMatch && bestMatch->isTypedef())
4276 return true; // closest matching symbol is a typedef
4277 else
4278 return false;
4279}
A model of a class/file/namespace member symbol.
Definition memberdef.h:45
virtual bool isTypedef() const =0
static MemberDef * getMemberFromSymbol(const Definition *scope, const FileDef *fileScope, const DString &n)
Definition util.cpp:4219

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

Referenced by isVarWithConstructor().

◆ cleanupInlineGraphs()

void cleanupInlineGraphs ( )

Deletes all graph files written with writeInlineGraph()

Definition at line 5383 of file util.cpp.

5384{
5385 if (Config_getBool(DOT_CLEANUP))
5386 {
5387 for (const auto& fileName: writeFileContents_set)
5388 {
5389 Dir().remove(qPrint(fileName));
5390 }
5391 }
5392}
Class representing a directory in the file system.
Definition dir.h:73
bool remove(const std::string &path, bool acceptsAbsPath=true) const
Definition dir.cpp:320
#define Config_getBool(name)
Definition config.h:33
const char * qPrint(const char *s)
Definition dstring.h:783
static StringUnorderedSet writeFileContents_set
Definition util.cpp:5356

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

Referenced by generateOutput().

◆ clearSubDirs()

void clearSubDirs ( const Dir & d)

Definition at line 2996 of file util.cpp.

2997{
2998 if (Config_getBool(CREATE_SUBDIRS))
2999 {
3000 // remove empty subdirectories
3001 int createSubdirsLevelPow2 = 1 << Config_getInt(CREATE_SUBDIRS_LEVEL);
3002 for (int l1=0;l1<16;l1++)
3003 {
3004 DString subdir;
3005 subdir.sprintf("d%x",l1);
3006 for (int l2=0; l2 < createSubdirsLevelPow2; l2++)
3007 {
3008 DString subsubdir;
3009 subsubdir.sprintf("d%x/d%02x",l1,l2);
3010 if (d.exists(subsubdir.str()) && d.empty(subsubdir.str()))
3011 {
3012 d.rmdir(subsubdir.str());
3013 }
3014 }
3015 if (d.exists(subdir.str()) && d.empty(subdir.str()))
3016 {
3017 d.rmdir(subdir.str());
3018 }
3019 }
3020 }
3021}
DString & sprintf(const char *format,...)
Definition dstring.cpp:34
const std::string & str() const
Definition dstring.h:645
bool empty(const std::string &subdir) const
Definition dir.cpp:269
bool rmdir(const std::string &path, bool acceptsAbsPath=true) const
Definition dir.cpp:315
bool exists() const
Definition dir.cpp:263
#define Config_getInt(name)
Definition config.h:34

References Config_getBool, Config_getInt, Dir::empty(), Dir::exists(), Dir::rmdir(), DString::sprintf(), and DString::str().

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

◆ computeQualifiedIndex()

int computeQualifiedIndex ( const DString & name)

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

Definition at line 5278 of file util.cpp.

5279{
5280 int l = static_cast<int>(name.length());
5281 int lastSepPos = -1;
5282 const char *p = name.data();
5283 int i=l-2;
5284 int sharpCount=0;
5285 // --- begin optimized version of ts=name.findRev(">::");
5286 int ts = -1;
5287 while (i>=0)
5288 {
5289 if (p[i]=='>')
5290 {
5291 if (sharpCount==0 && p[i+1]==':' && p[i+2]==':')
5292 {
5293 ts=i;
5294 break;
5295 }
5296 sharpCount++;
5297 }
5298 else if (p[i]=='<')
5299 {
5300 sharpCount--;
5301 }
5302 i--;
5303 }
5304 // --- end optimized version
5305 if (ts==-1) ts=0; else p+=++ts;
5306 for (i=ts;i<l-1;i++)
5307 {
5308 char c=*p++;
5309 if (c==':' && *p==':') lastSepPos=i;
5310 if (c=='<') break;
5311 }
5312 return lastSepPos;
5313}

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

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

◆ convertNameToFile()

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

2864{
2865 if (name.empty()) return name;
2866 bool shortNames = Config_getBool(SHORT_NAMES);
2867 bool createSubdirs = Config_getBool(CREATE_SUBDIRS);
2868 DString result;
2869 if (shortNames) // use short names only
2870 {
2871 std::lock_guard<std::mutex> lock(g_usedNamesMutex);
2872 auto kv = g_usedNames.find(name.str());
2873 uint32_t num=0;
2874 if (kv!=g_usedNames.end())
2875 {
2876 num = kv->second;
2877 }
2878 else
2879 {
2880 num = g_usedNamesCount;
2881 g_usedNames.emplace(name.str(),g_usedNamesCount++);
2882 }
2883 result.sprintf("a%05d",num);
2884 }
2885 else // long names
2886 {
2887 result=escapeCharsInString(name,allowDots,allowUnderscore);
2888 size_t resultLen = result.length();
2889 if (resultLen>=128) // prevent names that cannot be created!
2890 {
2891 // third algorithm based on MD5 hash
2892 result=result.left(128-32)+md5str(result.view());
2893 }
2894 }
2895 if (createSubdirs)
2896 {
2897 int l1Dir=0,l2Dir=0;
2898 int createSubdirsLevel = Config_getInt(CREATE_SUBDIRS_LEVEL);
2899 int createSubdirsBitmaskL2 = (1<<createSubdirsLevel)-1;
2900
2901 // compute md5 hash to determine sub directory to use
2902 auto md5_sig = md5hash(result.view());
2903 l1Dir = md5_sig[14] & 0xf;
2904 l2Dir = md5_sig[15] & createSubdirsBitmaskL2;
2905
2906 result.prepend(DString().sprintf("d%x/d%02x/",l1Dir,l2Dir));
2907 }
2908 //printf("*** convertNameToFile(%s)->%s\n",qPrint(name),qPrint(result));
2909 return result;
2910}
std::string_view view() const
Definition dstring.h:162
DString & prepend(const char *s)
Definition dstring.h:515
DString md5str(const std::string_view &str)
Definition md5hash.h:33
std::array< uint8_t, 16 > md5hash(const std::string_view &str)
Definition md5hash.h:26
static int g_usedNamesCount
Definition util.cpp:2855
DString escapeCharsInString(const DString &name, bool allowDots, bool allowUnderscore)
Definition util.cpp:2688
static std::mutex g_usedNamesMutex
Definition util.cpp:2854
static std::unordered_map< std::string, int > g_usedNames
Definition util.cpp:2853

References Config_getBool, Config_getInt, DString::empty(), escapeCharsInString(), g_usedNames, g_usedNamesCount, g_usedNamesMutex, DString::left(), DString::length(), md5hash(), md5str(), DString::prepend(), DString::sprintf(), DString::str(), and DString::view().

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

◆ convertProtectionLevel()

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

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

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

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

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

Definition at line 4904 of file util.cpp.

4910{
4911 bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
4912
4913 // default representing 1-1 mapping
4914 *outListType1=inListType;
4915 *outListType2=MemberListType::Invalid();
4916
4917 if (inProt==Protection::Public)
4918 {
4919 if (inListType.isPrivate())
4920 {
4921 *outListType1=MemberListType::Invalid();
4922 }
4923 }
4924 else if (inProt==Protection::Protected)
4925 {
4926 if (inListType.isPrivate() || inListType.isPublic())
4927 {
4928 *outListType1=MemberListType::Invalid();
4929 }
4930 else if (inListType.isProtected())
4931 {
4932 *outListType2=inListType.toPublic();
4933 }
4934 }
4935 else if (inProt==Protection::Private)
4936 {
4937 if (inListType.isPublic() || inListType.isProtected())
4938 {
4939 *outListType1=MemberListType::Invalid();
4940 }
4941 else if (inListType.isPrivate())
4942 {
4943 if (extractPrivate)
4944 {
4945 *outListType1=inListType.toPublic();
4946 *outListType2=inListType.toProtected();
4947 }
4948 else
4949 {
4950 *outListType1=MemberListType::Invalid();
4951 }
4952 }
4953 }
4954
4955 //printf("convertProtectionLevel(type=%s prot=%d): %s,%s\n",
4956 // qPrint(inListType.to_string()),inProt,qPrint(outListType1->to_string()),qPrint(outListType2->to_string()));
4957}
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()

DString convertToHtml ( const DString & s,
bool keepEntities )

Converts a string to a HTML-encoded string

Definition at line 3291 of file util.cpp.

3292{
3293 if (s.empty()) return s;
3294 DString result;
3295 result.reserve(s.length()+32);
3296 const char *p=s.data();
3297 char c = 0;
3298 while ((c=*p++))
3299 {
3300 switch (c)
3301 {
3302 case '<': result+="&lt;"; break;
3303 case '>': result+="&gt;"; break;
3304 case '&': if (keepEntities)
3305 {
3306 const char *e=p;
3307 char ce = 0;
3308 while ((ce=*e++))
3309 {
3310 if (ce==';' || (!(isId(ce) || ce=='#'))) break;
3311 }
3312 if (ce==';') // found end of an entity
3313 {
3314 // copy entry verbatim
3315 result+=c;
3316 while (p<e) result+=*p++;
3317 }
3318 else
3319 {
3320 result+="&amp;";
3321 }
3322 }
3323 else
3324 {
3325 result+="&amp;";
3326 }
3327 break;
3328 case '\'': result+="&#39;"; break;
3329 case '"': result+="&quot;"; break;
3330 default:
3331 {
3332 uint8_t uc = static_cast<uint8_t>(c);
3333 if (uc<32 && !isspace(c))
3334 {
3335 result+="&#x24";
3336 result+=hex[uc>>4];
3337 result+=hex[uc&0xF];
3338 result+=';';
3339 }
3340 else
3341 {
3342 result+=c;
3343 }
3344 }
3345 break;
3346 }
3347 }
3348 return result;
3349}
void reserve(size_t size)
Reserve space for size bytes without changing the string contents.
Definition dstring.h:217
static constexpr auto hex
bool isId(char c)
Returns true if c is a valid character for an identifier.
Definition dstring.h:895

References DString::data(), DString::empty(), hex, isId(), DString::length(), and DString::reserve().

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

DString convertToId ( const DString & s)

Converts a string to a HTML id string

Definition at line 3202 of file util.cpp.

3203{
3204 if (s.empty()) return s;
3205 DString result;
3206 result.reserve(s.length()+8);
3207 const char *p = s.data();
3208 char c = 0;
3209 bool first = true;
3210 while ((c=*p++))
3211 {
3212 char encChar[4];
3213 if ((c>='0' && c<='9') || (c>='a' && c<='z') || (c>='A' && c<='Z') || c=='-')
3214 { // any permissive character except _
3215 if (first && c>='0' && c<='9') result+='a'; // don't start with a digit
3216 result+=c;
3217 }
3218 else
3219 {
3220 encChar[0]='_';
3221 encChar[1]=hex[static_cast<unsigned char>(c)>>4];
3222 encChar[2]=hex[static_cast<unsigned char>(c)&0xF];
3223 encChar[3]=0;
3224 result+=encChar;
3225 }
3226 first=false;
3227 }
3228 return result;
3229}

References DString::data(), DString::empty(), hex, DString::length(), and DString::reserve().

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

◆ convertToJSString()

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

Definition at line 3351 of file util.cpp.

3352{
3353 if (s.empty()) return s;
3354 DString result;
3355 result.reserve(s.length()+32);
3356 const char *p=s.data();
3357 char c = 0;
3358 while ((c=*p++))
3359 {
3360 switch (c)
3361 {
3362 case '"': if (!singleQuotes) result+="\\\""; else result+=c;
3363 break;
3364 case '\'': if (singleQuotes) result+="\\\'"; else result+=c;
3365 break;
3366 case '\\': if (*p=='u' && *(p+1)=='{') result+="\\"; // keep \u{..} unicode escapes
3367 else result+="\\\\";
3368 break;
3369 default: result+=c; break;
3370 }
3371 }
3372 return keepEntities ? result : HtmlEntityMapper::instance().convertCharEntitiesToUTF8(result);
3373}
static HtmlEntityMapper & instance()
Returns the one and only instance of the HTML entity mapper.
DString convertCharEntitiesToUTF8(const DString &s) const

References HtmlEntityMapper::convertCharEntitiesToUTF8(), DString::data(), DString::empty(), HtmlEntityMapper::instance(), DString::length(), and DString::reserve().

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

◆ convertToXML()

DString convertToXML ( const DString & s,
bool keepEntities,
const bool citeEntry )

Converts a string to an XML-encoded string

Definition at line 3232 of file util.cpp.

3233{
3234 if (s.empty()) return s;
3235 DString result;
3236 result.reserve(s.length()+32);
3237 const char *p = s.data();
3238 char c = 0;
3239 while ((c=*p++))
3240 {
3241 switch (c)
3242 {
3243 case '<': result+="&lt;"; break;
3244 case '>': result+="&gt;"; break;
3245 case '&': if (keepEntities)
3246 {
3247 const char *e=p;
3248 char ce = 0;
3249 while ((ce=*e++))
3250 {
3251 if (ce==';' || (!(isId(ce) || ce=='#'))) break;
3252 }
3253 if (ce==';') // found end of an entity
3254 {
3255 // copy entry verbatim
3256 result+=c;
3257 while (p<e) result+=*p++;
3258 }
3259 else
3260 {
3261 result+="&amp;";
3262 }
3263 }
3264 else if (citeEntry)
3265 {
3267 result,
3268 p-1,
3269 [](HtmlEntityMapper::SymType symType) { return HtmlEntityMapper::instance().xml(symType); },
3270 "&amp;");
3271 }
3272 else
3273 {
3274 result+="&amp;";
3275 }
3276 break;
3277 case '\'': result+="&apos;"; break;
3278 case '"': result+="&quot;"; break;
3279 case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
3280 case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18:
3281 case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26:
3282 case 27: case 28: case 29: case 30: case 31:
3283 break; // skip invalid XML characters (see http://www.w3.org/TR/2000/REC-xml-20001006#NT-Char)
3284 default: result+=c; break;
3285 }
3286 }
3287 return result;
3288}
const char * writeHtmlEntity(T &result, const char *s, HtmlEntityMapperFunc &&mapper, const char *fallback)
Definition htmlentity.h:127
const char * xml(SymType symb) const
Access routine to the XML code of the HTML entity.

References DString::data(), DString::empty(), HtmlEntityMapper::instance(), isId(), DString::length(), DString::reserve(), HtmlEntityMapper::writeHtmlEntity(), and HtmlEntityMapper::xml().

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

◆ copyFile()

bool copyFile ( const DString & src,
const DString & dest )

Copies the contents of file with name src to the newly created file with name dest.

Returns true if successful.

Copies the file src to dest. Returns true if the copy was successful, false otherwise. When a relative path is used, is is based on the current working directory.

Definition at line 4619 of file util.cpp.

4620{
4621 if (!Dir().copy(src.str(),dest.str()))
4622 {
4623 err("could not copy file {} to {}\n",src,dest);
4624 return false;
4625 }
4626 return true;
4627}
#define err(fmt,...)
Definition message.h:127

References err, and DString::str().

Referenced by copyExtraFiles(), copyIcon(), copyLatexStyleSheet(), copyLogo(), copyStyleSheet(), DocParser::findAndCopyImage(), FormulaManager::generateImages(), CitationManager::generatePage(), RTFGenerator::init(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), DocbookDocVisitor::operator()(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), LatexDocVisitor::operator()(), LatexDocVisitor::operator()(), RTFDocVisitor::operator()(), RTFDocVisitor::operator()(), XmlDocVisitor::operator()(), XmlDocVisitor::operator()(), XmlDocVisitor::operator()(), XmlDocVisitor::operator()(), XmlDocVisitor::operator()(), XmlDocVisitor::operator()(), and substituteLatexKeywords().

◆ correctURL()

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

4660{
4661 DString result = url;
4662 if (!relPath.empty() && !isURL(url))
4663 {
4664 result.prepend(relPath);
4665 }
4666 return result;
4667}
bool isURL(const DString &url)
Checks whether the given url starts with a supported protocol.
Definition util.cpp:4646

References DString::empty(), isURL(), and DString::prepend().

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

◆ createHtmlUrl()

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

Definition at line 4502 of file util.cpp.

4507{
4508 DString url;
4509 if (!ref.empty())
4510 {
4511 url = externalRef(relPath,ref);
4512 }
4513 if (!targetFileName.empty())
4514 {
4515 DString fn = targetFileName;
4516 if (ref.empty())
4517 {
4518 if (!anchor.empty() && isLocalFile)
4519 {
4520 fn=""; // omit file name for local links
4521 }
4522 else
4523 {
4524 url = relPath;
4525 }
4526 }
4527 url+=fn;
4528 }
4529 if (!anchor.empty())
4530 {
4531 if (!url.endsWith("=")) url+="#";
4532 url+=anchor;
4533 }
4534 //printf("createHtmlUrl(relPath=%s,local=%d,target=%s,anchor=%s)=%s\n",qPrint(relPath),isLocalFile,qPrint(targetFileName),qPrint(anchor),qPrint(url));
4535 return url;
4536}
bool endsWith(const char *s) const
Definition dstring.h:617
DString externalRef(const DString &relPath, const DString &ref)
Definition util.cpp:4538

References DString::empty(), DString::endsWith(), and externalRef().

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

◆ createSubDirs()

void createSubDirs ( const Dir & d)

Definition at line 2969 of file util.cpp.

2970{
2971 if (Config_getBool(CREATE_SUBDIRS))
2972 {
2973 // create up to 4096 subdirectories
2974 int createSubdirsLevelPow2 = 1 << Config_getInt(CREATE_SUBDIRS_LEVEL);
2975 for (int l1=0; l1<16; l1++)
2976 {
2977 DString subdir;
2978 subdir.sprintf("d%x",l1);
2979 if (!d.exists(subdir.str()) && !d.mkdir(subdir.str()))
2980 {
2981 term("Failed to create output directory '{}'\n",subdir);
2982 }
2983 for (int l2=0; l2<createSubdirsLevelPow2; l2++)
2984 {
2985 DString subsubdir;
2986 subsubdir.sprintf("d%x/d%02x",l1,l2);
2987 if (!d.exists(subsubdir.str()) && !d.mkdir(subsubdir.str()))
2988 {
2989 term("Failed to create output directory '{}'\n",subsubdir);
2990 }
2991 }
2992 }
2993 }
2994}
bool mkdir(const std::string &path, bool acceptsAbsPath=true) const
Definition dir.cpp:301
#define term(fmt,...)
Definition message.h:137

References Config_getBool, Config_getInt, Dir::exists(), Dir::mkdir(), DString::sprintf(), DString::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()

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

Definition at line 5328 of file util.cpp.

5329{
5330 DString result=name;
5331 if (result.endsWith("-g"))
5332 {
5333 size_t idx = result.find('-');
5334 result = result.left(idx)+templArgs;
5335 }
5336 return result;
5337}

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

Referenced by ClassDefImpl::className().

◆ detab()

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

Definition at line 5179 of file util.cpp.

5180{
5181 int tabSize = Config_getInt(TAB_SIZE);
5182 size_t size = s.length();
5183 DString result;
5184 result.reserve(size+256);
5185 const char *data = s.data();
5186 size_t i=0;
5187 int col=0;
5188 constexpr auto doxy_nbsp = "&_doxy_nbsp;"; // doxygen escape command for UTF-8 nbsp
5189 const int maxIndent=1000000; // value representing infinity
5190 int minIndent=maxIndent;
5191 bool skip = false;
5192 while (i<size)
5193 {
5194 char c = data[i++];
5195 switch(c)
5196 {
5197 case '\t': // expand tab
5198 {
5199 int stop = tabSize - (col%tabSize);
5200 //printf("expand at %d stop=%d\n",col,stop);
5201 col+=stop;
5202 while (stop--) result+=' ';
5203 }
5204 break;
5205 case '\\':
5206 if (data[i] == '\\') // escaped command -> ignore
5207 {
5208 result+=c;
5209 result+=data[i++];
5210 col+=2;
5211 }
5212 else if (i+5<size && literal_at(data+i,"iskip")) // command
5213 {
5214 i+=5;
5215 skip = true;
5216 }
5217 else if (i+8<size && literal_at(data+i,"endiskip")) // command
5218 {
5219 i+=8;
5220 skip = false;
5221 }
5222 else // some other command
5223 {
5224 result+=c;
5225 col++;
5226 }
5227 break;
5228 case '\n': // reset column counter
5229 result+=c;
5230 col=0;
5231 break;
5232 case ' ': // increment column counter
5233 result+=c;
5234 col++;
5235 break;
5236 default: // non-whitespace => update minIndent
5237 if (static_cast<signed char>(c)<0 && i<size) // multibyte sequence
5238 {
5239 // special handling of the UTF-8 nbsp character 0xC2 0xA0
5240 int nb = isUTF8NonBreakableSpace(data);
5241 if (nb>0)
5242 {
5243 result+=doxy_nbsp;
5244 i+=nb-1;
5245 }
5246 else
5247 {
5248 int bytes = getUTF8CharNumBytes(c);
5249 for (int j=0;j<bytes-1 && c;j++)
5250 {
5251 result+=c;
5252 c = data[i++];
5253 }
5254 result+=c;
5255 }
5256 }
5257 else
5258 {
5259 result+=c;
5260 }
5261 if (!skip && col<minIndent) minIndent=col;
5262 col++;
5263 }
5264 }
5265 if (minIndent!=maxIndent) refIndent=minIndent; else refIndent=0;
5266 //printf("detab(\n%s\n)=[\n%s\n]\n",qPrint(s),qPrint(out.get()));
5267 return result;
5268}
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:101
int isUTF8NonBreakableSpace(const char *input)
Check if the first character pointed at by input is a non-breakable whitespace character.
Definition utf8.cpp:232
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:27

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

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

◆ determineAbsoluteIncludeName()

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

Definition at line 2929 of file util.cpp.

2930{
2931 bool searchIncludes = Config_getBool(SEARCH_INCLUDES);
2932 DString absIncFileName = incFileName;
2933 FileInfo fi(curFile.str());
2934 if (fi.exists())
2935 {
2936 DString absName = fi.dirPath(true)+"/"+incFileName;
2937 FileInfo fi2(absName.str());
2938 if (fi2.exists())
2939 {
2940 absIncFileName=fi2.absFilePath();
2941 }
2942 else if (searchIncludes) // search in INCLUDE_PATH as well
2943 {
2944 StringVector includePath = Config_getList(INCLUDE_PATH);
2945 for (const auto &incPath : includePath)
2946 {
2947 FileInfo fi3(incPath);
2948 if (fi3.exists() && fi3.isDir())
2949 {
2950 absName = fi3.absFilePath()+"/"+incFileName;
2951 //printf("trying absName=%s\n",qPrint(absName));
2952 FileInfo fi4(absName.str());
2953 if (fi4.exists())
2954 {
2955 absIncFileName=fi4.absFilePath();
2956 break;
2957 }
2958 //printf( "absIncFileName = %s\n", qPrint(absIncFileName) );
2959 }
2960 }
2961 }
2962 //printf( "absIncFileName = %s\n", qPrint(absIncFileName) );
2963 }
2964 return absIncFileName;
2965}
Minimal replacement for QFileInfo.
Definition fileinfo.h:26
#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(), and DString::str().

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

◆ escapeCharsInString()

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

Definition at line 2688 of file util.cpp.

2689{
2690 if (name.empty()) return name;
2691 bool caseSenseNames = useCaseSenseNames();
2692 bool allowUnicodeNames = Config_getBool(ALLOW_UNICODE_NAMES);
2693 DString result;
2694 result.reserve(name.length()+8);
2695 signed char c = 0;
2696 const char *p=name.data();
2697 while ((c=*p++)!=0)
2698 {
2699 switch(c)
2700 {
2701 case '_': if (allowUnderscore) result+='_'; else result+="__"; break;
2702 case '-': result+='-'; break;
2703 case ':': result+="_1"; break;
2704 case '/': result+="_2"; break;
2705 case '<': result+="_3"; break;
2706 case '>': result+="_4"; break;
2707 case '*': result+="_5"; break;
2708 case '&': result+="_6"; break;
2709 case '|': result+="_7"; break;
2710 case '.': if (allowDots) result+='.'; else result+="_8"; break;
2711 case '!': result+="_9"; break;
2712 case ',': result+="_00"; break;
2713 case ' ': result+="_01"; break;
2714 case '{': result+="_02"; break;
2715 case '}': result+="_03"; break;
2716 case '?': result+="_04"; break;
2717 case '^': result+="_05"; break;
2718 case '%': result+="_06"; break;
2719 case '(': result+="_07"; break;
2720 case ')': result+="_08"; break;
2721 case '+': result+="_09"; break;
2722 case '=': result+="_0a"; break;
2723 case '$': result+="_0b"; break;
2724 case '\\': result+="_0c"; break;
2725 case '@': result+="_0d"; break;
2726 case ']': result+="_0e"; break;
2727 case '[': result+="_0f"; break;
2728 case '#': result+="_0g"; break;
2729 case '"': result+="_0h"; break;
2730 case '~': result+="_0i"; break;
2731 case '\'': result+="_0j"; break;
2732 case ';': result+="_0k"; break;
2733 case '`': result+="_0l"; break;
2734 default:
2735 if (c<0)
2736 {
2737 bool doEscape = true;
2738 if (allowUnicodeNames)
2739 {
2740 int charLen = getUTF8CharNumBytes(c);
2741 if (charLen>0)
2742 {
2743 result+=DString(p-1,charLen);
2744 p+=charLen;
2745 doEscape = false;
2746 }
2747 }
2748 if (doEscape) // not a valid unicode char or escaping needed
2749 {
2750 char ids[5];
2751 unsigned char id = static_cast<unsigned char>(c);
2752 ids[0]='_';
2753 ids[1]='x';
2754 ids[2]=hex[id>>4];
2755 ids[3]=hex[id&0xF];
2756 ids[4]=0;
2757 result+=ids;
2758 }
2759 }
2760 else if (caseSenseNames || !isupper(c))
2761 {
2762 result+=c;
2763 }
2764 else
2765 {
2766 result+='_';
2767 result+=static_cast<char>(tolower(c));
2768 }
2769 break;
2770 }
2771 }
2772 return result;
2773}
bool useCaseSenseNames()
Returns true if the names of the symbols can be case sensitive.
Definition util.cpp:2679

References Config_getBool, DString::data(), DString::empty(), getUTF8CharNumBytes(), hex, DString::length(), DString::reserve(), and useCaseSenseNames().

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

◆ externalLinkTarget()

DString externalLinkTarget ( const bool parent)

Definition at line 4491 of file util.cpp.

4492{
4493 bool extLinksInWindow = Config_getBool(EXT_LINKS_IN_WINDOW);
4494 if (extLinksInWindow)
4495 return "target=\"_blank\" ";
4496 else if (parent)
4497 return "target=\"_parent\" ";
4498 else
4499 return "";
4500}
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:1335

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

DString externalRef ( const DString & relPath,
const DString & ref )

Resolve a reference via a tagfile reference ref. If after resolving the reference the result points to a relative path then relPath is prepended to create the correct link.

Definition at line 4538 of file util.cpp.

4539{
4540 DString result;
4541 if (!ref.empty())
4542 {
4543 auto it = Doxygen::tagDestinationMap.find(ref.str());
4545 {
4546 result = it->second;
4547 size_t l = result.length();
4548 if (!relPath.empty() && l>0 && result.at(0)=='.')
4549 { // relative path -> prepend relPath.
4550 result.prepend(relPath);
4551 l+=relPath.length();
4552 }
4553 if (l>0 && result.at(l-1)!='/') result+='/';
4554 }
4555 }
4556 else
4557 {
4558 result = relPath;
4559 }
4560 return result;
4561}
char & at(size_t i)
Returns a reference to the character at index i.
Definition dstring.h:686
static StringMap tagDestinationMap
Definition doxygen.h:109
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:181

References DString::at(), DString::empty(), end(), DString::length(), DString::prepend(), DString::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()

DString extractBeginRawStringDelimiter ( const char * rawStart)

Definition at line 5339 of file util.cpp.

5340{
5341 DString text=rawStart;
5342 size_t i = text.find('"');
5344 return text.mid(i+1,text.length()-i-2); // text=...R"xyz( -> delimiter=xyz
5345}
#define ASSERT(x)
Definition message.h:142

References ASSERT, DString::find(), DString::length(), DString::mid(), and DString::npos.

◆ extractCanonicalArgType()

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

Definition at line 1458 of file util.cpp.

1459{
1460 DString type = arg.type.stripWhiteSpace();
1461 DString name = arg.name;
1462 //printf("----- extractCanonicalArgType(type=%s,name=%s)\n",qPrint(type),qPrint(name));
1463 if ((type=="const" || type=="volatile") && !name.empty())
1464 { // name is part of type => correct
1465 type+=" ";
1466 type+=name;
1467 }
1468 if (name=="const" || name=="volatile")
1469 { // name is part of type => correct
1470 if (!type.empty()) type+=" ";
1471 type+=name;
1472 }
1473 if (!arg.array.empty())
1474 {
1475 type+=arg.array;
1476 }
1477
1478 return extractCanonicalType(d,fs,type,lang,false);
1479}
DString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition dstring.h:337
static DString extractCanonicalType(const Definition *d, const FileDef *fs, DString type, SrcLangExt lang, bool insideTemplate)
Definition util.cpp:1372

References Argument::array, DString::empty(), extractCanonicalType(), Argument::name, DString::stripWhiteSpace(), and Argument::type.

Referenced by matchArgument2().

◆ extractCanonicalType()

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

Definition at line 1372 of file util.cpp.

1373{
1374 AUTO_TRACE("d={} fs={} type='{}'",d?d->name():"",fs?fs->name():"",type);
1375 type = type.stripWhiteSpace();
1376
1377 // strip const and volatile keywords that are not relevant for the type
1378 stripIrrelevantConstVolatile(type,insideTemplate);
1379
1380 // strip leading keywords
1381 type.stripPrefix("class ");
1382 type.stripPrefix("struct ");
1383 type.stripPrefix("union ");
1384 type.stripPrefix("enum ");
1385 type.stripPrefix("typename ");
1386
1387 type = removeRedundantWhiteSpace(type);
1388 //printf("extractCanonicalType(type=%s) start: def=%s file=%s\n",qPrint(type),
1389 // d ? qPrint(d->name()) : "<null>", fs ? qPrint(fs->name()) : "<null>");
1390
1391 DString canType;
1392 DString templSpec,word;
1393 int i=0,p=0,pp=0;
1394 while ((i=extractClassNameFromType(type,p,word,templSpec))!=-1)
1395 // foreach identifier in the type
1396 {
1397 //printf(" i=%d p=%d\n",i,p);
1398 if (i>pp)
1399 {
1400 if (i-pp>=2 && type[i-2]==':' && type[i-1]==':') // skip over leading ::, see issue #12021
1401 {
1402 canType += type.mid(pp,i-pp-2);
1403 }
1404 else
1405 {
1406 canType += type.mid(pp,i-pp);
1407 }
1408 }
1409
1410 DString ct = getCanonicalTypeForIdentifier(d,fs,word,lang,&templSpec);
1411
1412 // in case the ct is empty it means that "word" represents scope "d"
1413 // and this does not need to be added to the canonical
1414 // type (it is redundant), so/ we skip it. This solves problem 589616.
1415 if (ct.empty() && type.mid(p,2)=="::")
1416 {
1417 p+=2;
1418 }
1419 else
1420 {
1421 canType += ct;
1422 }
1423 //printf(" word=%s templSpec=%s canType=%s ct=%s\n",
1424 // qPrint(word), qPrint(templSpec), qPrint(canType), qPrint(ct));
1425 if (!templSpec.empty()) // if we didn't use up the templSpec already
1426 // (i.e. type is not a template specialization)
1427 // then resolve any identifiers inside.
1428 {
1429 std::string ts = templSpec.str();
1430 static const reg::Ex re(R"(\a\w*)");
1431 reg::Iterator it(ts,re);
1433
1434 size_t tp=0;
1435 // for each identifier template specifier
1436 //printf("adding resolved %s to %s\n",qPrint(templSpec),qPrint(canType));
1437 for (; it!=end ; ++it)
1438 {
1439 const auto &match = *it;
1440 size_t ti = match.position();
1441 size_t tl = match.length();
1442 std::string matchStr = match.str();
1443 canType += ts.substr(tp,ti-tp);
1444 canType += getCanonicalTypeForIdentifier(d,fs,matchStr,lang,nullptr);
1445 tp=ti+tl;
1446 }
1447 canType+=ts.substr(tp);
1448 }
1449
1450 pp=p;
1451 }
1452 canType += type.mid(pp);
1453 AUTO_TRACE_EXIT("canType='{}'",canType);
1454
1455 return removeRedundantWhiteSpace(canType);
1456}
DString substr(size_t pos=0, size_t count=npos) const
Returns a substring of length count starting at pos.
Definition dstring.h:223
bool stripPrefix(const DString &prefix)
Definition dstring.h:290
virtual const DString & name() const =0
Class representing a regular expression.
Definition regex.h:39
Class to iterate through matches.
Definition regex.h:239
#define AUTO_TRACE(...)
Definition docnode.cpp:53
#define AUTO_TRACE_EXIT(...)
Definition docnode.cpp:55
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:861
void stripIrrelevantConstVolatile(DString &s, bool insideTemplate)
Definition util.cpp:1171
static DString getCanonicalTypeForIdentifier(const Definition *d, const FileDef *fs, const DString &word, SrcLangExt lang, DString *tSpec, int count=0)
Definition util.cpp:1218
int extractClassNameFromType(const DString &type, int &pos, DString &name, DString &templSpec, SrcLangExt lang)
Definition util.cpp:3380

References AUTO_TRACE, AUTO_TRACE_EXIT, DString::empty(), end(), extractClassNameFromType(), getCanonicalTypeForIdentifier(), DString::mid(), Definition::name(), removeRedundantWhiteSpace(), DString::str(), stripIrrelevantConstVolatile(), DString::stripPrefix(), DString::stripWhiteSpace(), and DString::substr().

Referenced by extractCanonicalArgType(), and getCanonicalTemplateSpec().

◆ extractClassNameFromType()

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

3381{
3382 AUTO_TRACE("type='{}' pos={} name='{}' lang={}",type,pos,name,lang);
3383 static const reg::Ex re_norm(R"(\a[\w:]*)");
3384 static const reg::Ex re_fortran(R"(\a[\w:()=]*)");
3385 const reg::Ex *re = &re_norm;
3386
3387 name.clear();
3388 templSpec.clear();
3389 if (type.empty())
3390 {
3391 AUTO_TRACE_EXIT("empty type");
3392 return -1;
3393 }
3394 size_t typeLen=type.length();
3395 if (typeLen>0)
3396 {
3397 if (lang == SrcLangExt::Fortran)
3398 {
3399 if (type[pos]==',')
3400 {
3401 AUTO_TRACE_EXIT("comma");
3402 return -1;
3403 }
3404 if (!type.lower().startsWith("type"))
3405 {
3406 re = &re_fortran;
3407 }
3408 }
3409 std::string s = type.str();
3410 reg::Iterator it(s,*re,static_cast<int>(pos));
3412
3413 if (it!=end)
3414 {
3415 const auto &match = *it;
3416 size_t i = match.position();
3417 size_t l = match.length();
3418 size_t ts = i+l;
3419 size_t te = ts;
3420 size_t tl = 0;
3421
3422 while (ts<typeLen && type[static_cast<uint32_t>(ts)]==' ') { ts++; tl++; } // skip any whitespace
3423 if (ts<typeLen && type[static_cast<uint32_t>(ts)]=='<') // assume template instance
3424 {
3425 // locate end of template
3426 te=ts+1;
3427 int brCount=1;
3428 while (te<typeLen && brCount!=0)
3429 {
3430 if (type[static_cast<uint32_t>(te)]=='<')
3431 {
3432 if (te<typeLen-1 && type[static_cast<uint32_t>(te)+1]=='<') te++; else brCount++;
3433 }
3434 if (type[static_cast<uint32_t>(te)]=='>')
3435 {
3436 if (te<typeLen-1 && type[static_cast<uint32_t>(te)+1]=='>') te++; else brCount--;
3437 }
3438 te++;
3439 }
3440 }
3441 name = match.str();
3442 if (te>ts)
3443 {
3444 templSpec = DString(type).mid(ts,te-ts);
3445 tl+=te-ts;
3446 pos=static_cast<int>(i+l+tl);
3447 }
3448 else // no template part
3449 {
3450 pos=static_cast<int>(i+l);
3451 }
3452 //printf("extractClassNameFromType([in] type=%s,[out] pos=%d,[out] name=%s,[out] templ=%s)=true i=%d\n",
3453 // qPrint(type),pos,qPrint(name),qPrint(templSpec),i);
3454 AUTO_TRACE_EXIT("pos={} templSpec='{}' return={}",pos,templSpec,i);
3455 return static_cast<int>(i);
3456 }
3457 }
3458 pos = static_cast<int>(typeLen);
3459 //printf("extractClassNameFromType([in] type=%s,[out] pos=%d,[out] name=%s,[out] templ=%s)=false\n",
3460 // qPrint(type),pos,qPrint(name),qPrint(templSpec));
3461 AUTO_TRACE_EXIT("not found");
3462 return -1;
3463}
void clear()
Definition dstring.h:214
DString lower() const
Definition dstring.h:326
bool startsWith(const char *s) const
Definition dstring.h:600

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

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

◆ extractDirection()

DString extractDirection ( DString & docs)
static

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

4830{
4831 std::string s = docs.str();
4832 static const reg::Ex re(R"(\‍[([ inout,]+)\‍])");
4833 reg::Iterator it(s,re);
4835 if (it!=end)
4836 {
4837 const auto &match = *it;
4838 size_t p = match.position();
4839 size_t l = match.length();
4840 if (p==0 && l>2)
4841 {
4842 // make dir the part inside [...] without separators
4843 std::string dir = match[1].str();
4844 // strip , and ' ' from dir
4845 dir.erase(std::remove_if(dir.begin(),dir.end(),
4846 [](const char c) { return c==' ' || c==','; }
4847 ),dir.end());
4848 unsigned char ioMask=0;
4849 size_t inIndex = dir.find( "in");
4850 if ( inIndex!=std::string::npos) { dir.erase( inIndex,2); ioMask|=(1<<0); }
4851 size_t outIndex = dir.find("out");
4852 if (outIndex!=std::string::npos) { dir.erase(outIndex,3); ioMask|=(1<<1); }
4853 if (dir.empty() && ioMask!=0) // only in and/or out attributes found
4854 {
4855 docs = s.substr(l); // strip attributes
4856 if (ioMask==((1<<0)|(1<<1))) return "[in,out]";
4857 else if (ioMask==(1<<0)) return "[in]";
4858 else if (ioMask==(1<<1)) return "[out]";
4859 }
4860 }
4861 }
4862 return "";
4863}

References end(), DString::str(), and DString::substr().

Referenced by inlineArgListToDoc().

◆ extractEndRawStringDelimiter()

DString extractEndRawStringDelimiter ( const char * rawEnd)

Definition at line 5347 of file util.cpp.

5348{
5349 DString text=rawEnd;
5350 return text.mid(1,text.length()-2); // text=)xyz" -> delimiter=xyz
5351}

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

◆ extractNamespaceName()

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

3029{
3030 DString clName=scopeName;
3031 NamespaceDef *nd = nullptr;
3032 size_t i=0;
3033 int p=0;
3034 if (!clName.empty() && (nd=getResolvedNamespace(clName)) && getClass(clName)==nullptr)
3035 { // the whole name is a namespace (and not a class)
3036 namespaceName=nd->name();
3037 className.clear();
3038 goto done;
3039 }
3040 p=static_cast<int>(clName.length())-2;
3041 while (p>=0 && (i=clName.rfind("::",p))!=DString::npos)
3042 // see if the first part is a namespace (and not a class)
3043 {
3044 //printf("Trying %s\n",qPrint(clName.left(i)));
3045 if (i>0 && (nd=getResolvedNamespace(clName.left(i))) && getClass(clName.left(i))==nullptr)
3046 {
3047 //printf("found!\n");
3048 namespaceName=nd->name();
3049 className=clName.mid(i+2);
3050 goto done;
3051 }
3052 p=static_cast<int>(i)-2; // try a smaller piece of the scope
3053 }
3054 //printf("not found!\n");
3055
3056 // not found, so we just have to guess.
3057 className=scopeName;
3058 namespaceName.clear();
3059
3060done:
3061 if (className.empty() && !namespaceName.empty() && !allowEmptyClass)
3062 {
3063 // class and namespace with the same name, correct to return the class.
3064 className=namespaceName;
3065 namespaceName.clear();
3066 }
3067 //printf("extractNamespace '%s' => '%s|%s'\n",qPrint(scopeName),
3068 // qPrint(className),qPrint(namespaceName));
3069 if (className.endsWith("-p"))
3070 {
3071 className = className.left(className.length()-2);
3072 }
3073 return;
3074}
An abstract interface of a namespace symbol.
ClassDef * getClass(const DString &n)
NamespaceDef * getResolvedNamespace(const DString &name)

References DString::clear(), DString::empty(), DString::endsWith(), getClass(), getResolvedNamespace(), DString::left(), DString::length(), DString::mid(), Definition::name(), DString::npos, and DString::rfind().

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

◆ fileToString()

DString fileToString ( const DString & name,
bool filter = false,
bool isSourceCode = false )

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

1054{
1055 if (name.empty()) return DString();
1056 bool fileOpened=false;
1057 if (name[0]=='-' && name[1]==0) // read from stdin
1058 {
1059 std::string contents;
1060 std::string line;
1061 while (getline(std::cin,line))
1062 {
1063 contents+=line+'\n';
1064 }
1065 return contents;
1066 }
1067 else // read from file
1068 {
1069 FileInfo fi(name.str());
1070 if (!fi.exists() || !fi.isFile())
1071 {
1072 err("file '{}' not found\n",name);
1073 return "";
1074 }
1075 std::string buf;
1076 fileOpened=readInputFile(name,buf,filter,isSourceCode);
1077 if (fileOpened)
1078 {
1079 addTerminalCharIfMissing(buf,'\n');
1080 return buf;
1081 }
1082 }
1083 if (!fileOpened)
1084 {
1085 err("cannot open file '{}' for reading\n",name);
1086 }
1087 return "";
1088}
void addTerminalCharIfMissing(std::string &s, char c)
Definition stringutil.h:87
bool readInputFile(const DString &fileName, std::string &contents, bool filter, bool isSourceCode)
read a file name fileName and optionally filter and transcode it
Definition util.cpp:4374

References addTerminalCharIfMissing(), DString::empty(), err, FileInfo::exists(), FileInfo::isFile(), readInputFile(), and DString::str().

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

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

960{
961 size_t src = 0; // source index
962 size_t dest = 0; // destination index
963 size_t len = contents.length();
964
965 while (src<len)
966 {
967 char c = contents[src++]; // Remember the processed character.
968 if (c == '\r') // CR to be solved (MAC, DOS)
969 {
970 c = '\n'; // each CR to LF
971 if (src<len && contents[src] == '\n')
972 {
973 ++src; // skip LF just after CR (DOS)
974 }
975 }
976 else if ( c == '\0' && src<len-1) // filter out internal \0 characters, as it will confuse the parser
977 {
978 c = ' '; // turn into a space
979 }
980 contents[dest++] = c; // copy the (modified) character to dest
981 }
982 contents.resize(dest);
983}

Referenced by readInputFile().

◆ filterTitle()

DString filterTitle ( const DString & title)

Definition at line 4454 of file util.cpp.

4455{
4456 std::string tf;
4457 std::string t = title.str();
4458 static const reg::Ex re(R"(%[a-z_A-Z]+)");
4459 reg::Iterator it(t,re);
4461 size_t p = 0;
4462 for (; it!=end ; ++it)
4463 {
4464 const auto &match = *it;
4465 size_t i = match.position();
4466 size_t l = match.length();
4467 if (i>p) tf+=t.substr(p,i-p);
4468 tf+=match.str().substr(1); // skip %
4469 p=i+l;
4470 }
4471 tf+=t.substr(p);
4472 return tf;
4473}

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

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

◆ findExampleFilePath()

DString findExampleFilePath ( const DString & file,
bool & ambig )

Definition at line 2451 of file util.cpp.

2452{
2453 ambig=false;
2454 DString result;
2455 bool found=false;
2456 if (!found)
2457 {
2458 FileInfo fi(file.str());
2459 if (fi.exists())
2460 {
2461 result=fi.absFilePath();
2462 found=true;
2463 }
2464 }
2465 if (!found)
2466 {
2467 StringVector examplePathList = Config_getList(EXAMPLE_PATH);
2468 for (const auto &s : examplePathList)
2469 {
2470 std::string absFileName = s+(Portable::pathSeparator()+file).str();
2471 FileInfo fi(absFileName);
2472 if (fi.exists())
2473 {
2474 result=fi.absFilePath();
2475 found=true;
2476 }
2477 }
2478 }
2479
2480 if (!found)
2481 {
2482 // as a fallback we also look in the exampleNameDict
2484 if (fd && !ambig)
2485 {
2486 result=fd->absFilePath();
2487 }
2488 }
2489 return result;
2490}
static FileNameLinkedMap * exampleNameLinkedMap
Definition doxygen.h:95
A model of a file symbol.
Definition filedef.h:97
virtual DString absFilePath() const =0
FileDef * findFileDef(const DString &n, bool &ambig) const
Returns the file definition in fnMap that matches the file name n.
Definition filename.cpp:38
DString pathSeparator()
Definition portable.cpp:390

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

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

◆ findModuleDef()

ModuleDef * findModuleDef ( const Definition * d)
static

Definition at line 3853 of file util.cpp.

3854{
3855 ModuleDef *mod = nullptr;
3857 {
3858 const FileDef *fd = toFileDef(d);
3859 if (fd) mod = fd->getModuleDef();
3860 }
3862 {
3863 const ClassDef *cd = toClassDef(d);
3864 if (cd)
3865 {
3866 const FileDef *fd = cd->getFileDef();
3867 if (fd) mod = fd->getModuleDef();
3868 }
3869 }
3871 {
3872 const ConceptDef *cd = toConceptDef(d);
3873 if (cd)
3874 {
3875 const FileDef *fd = cd->getFileDef();
3876 if (fd) mod = fd->getModuleDef();
3877 }
3878 }
3879 return mod;
3880}
A abstract class representing of a compound symbol.
Definition classdef.h:100
virtual FileDef * getFileDef() const =0
Returns the file in which this compound's definition can be found.
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:1973

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

Referenced by recursivelyAddGroupListToTitle().

◆ findParameterList()

size_t findParameterList ( const DString & name)
static

Returns the position in the string where a function parameter list begins, or DString::npos if one is not found.

Definition at line 684 of file util.cpp.

685{
686 size_t pos=DString::npos;
687 int templateDepth=0;
688 do
689 {
690 if (templateDepth > 0)
691 {
692 size_t nextOpenPos = name.rfind('>', pos);
693 size_t nextClosePos = name.rfind('<', pos);
694 if (nextOpenPos!=DString::npos && nextClosePos!=DString::npos && nextOpenPos>nextClosePos)
695 {
696 ++templateDepth;
697 pos=nextOpenPos-1;
698 }
699 else if (nextClosePos!=DString::npos)
700 {
701 --templateDepth;
702 pos=nextClosePos-1;
703 }
704 else // more >'s than <'s, see bug701295
705 {
706 return -1;
707 }
708 }
709 else
710 {
711 size_t lastAnglePos = name.rfind('>', pos);
712 size_t bracePos = name.rfind('(', pos);
713 if (lastAnglePos!=DString::npos && bracePos!=DString::npos && lastAnglePos>bracePos)
714 {
715 ++templateDepth;
716 pos=lastAnglePos-1;
717 }
718 else
719 {
720 size_t bp = bracePos>0 ? name.rfind('(',bracePos-1) : DString::npos;
721 // bp test is to allow foo(int(&)[10]), but we need to make an exception for operator()
722 return bp==DString::npos || (bp>=8 && name.mid(bp-8,10)=="operator()") ? bracePos : bp;
723 }
724 }
725 } while (pos!=DString::npos);
726 return DString::npos;
727}

References DString::mid(), DString::npos, and DString::rfind().

Referenced by resolveRef().

◆ getCanonicalTemplateSpec()

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

Definition at line 1197 of file util.cpp.

1198{
1199 AUTO_TRACE("spec={}",spec);
1200 DString templSpec = spec.stripWhiteSpace();
1201 // this part had been commented out before... but it is needed to match for instance
1202 // std::list<std::string> against list<string> so it is now back again!
1203 if (!templSpec.empty() && templSpec.at(0) == '<')
1204 {
1205 templSpec = "< " + extractCanonicalType(d,fs,templSpec.mid(1).stripWhiteSpace(),lang,true);
1206 }
1207 DString resolvedType = lang==SrcLangExt::Java ? templSpec : resolveTypeDef(d,templSpec);
1208 if (!resolvedType.empty()) // not known as a typedef either
1209 {
1210 templSpec = resolvedType;
1211 }
1212 //printf("getCanonicalTemplateSpec(%s)=%s\n",qPrint(spec),qPrint(templSpec));
1213 AUTO_TRACE_EXIT("result={}",templSpec);
1214 return templSpec;
1215}
DString resolveTypeDef(const Definition *context, const DString &qualifiedName, const Definition **typedefContext)
Definition util.cpp:232

References DString::at(), AUTO_TRACE, AUTO_TRACE_EXIT, DString::empty(), extractCanonicalType(), DString::mid(), resolveTypeDef(), and DString::stripWhiteSpace().

Referenced by getCanonicalTypeForIdentifier().

◆ getCanonicalTypeForIdentifier()

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

Definition at line 1218 of file util.cpp.

1221{
1222 if (count>10) return word; // oops recursion
1223
1224 DString symName,result,templSpec,tmpName;
1225 if (tSpec && !tSpec->empty())
1226 templSpec = stripDeclKeywords(getCanonicalTemplateSpec(d,fs,*tSpec,lang));
1227
1228 AUTO_TRACE("d='{}' fs='{}' word='{}' templSpec='{}'",d?d->name():"",fs?fs->name():"",word,templSpec);
1229
1230 if (word.rfind("::")!=DString::npos && !(tmpName=stripScope(word)).empty())
1231 {
1232 symName=tmpName; // name without scope
1233 }
1234 else
1235 {
1236 symName=word;
1237 }
1238
1239 // lookup class / class template instance
1240 SymbolResolver resolver(fs);
1241 const ClassDef *cd = resolver.resolveClass(d,word+templSpec,true,true);
1242 const MemberDef *mType = resolver.getTypedef();
1243 DString ts = resolver.getTemplateSpec();
1244 DString resolvedType = resolver.getResolvedType();
1245
1246 bool isTemplInst = cd && !templSpec.empty();
1247 if (!cd && !templSpec.empty())
1248 {
1249 // class template specialization not known, look up class template
1250 cd = resolver.resolveClass(d,word,true,true);
1251 mType = resolver.getTypedef();
1252 ts = resolver.getTemplateSpec();
1253 resolvedType = resolver.getResolvedType();
1254 }
1255 if (cd && cd->isUsedOnly()) cd=nullptr; // ignore types introduced by usage relations
1256
1257 AUTO_TRACE_ADD("cd='{}' mType='{}' ts='{}' resolvedType='{}'",
1258 cd?cd->name():"",mType?mType->name():"",ts,resolvedType);
1259 //printf("cd=%p mtype=%p\n",cd,mType);
1260 //printf(" getCanonicalTypeForIdentifier: symbol=%s word=%s cd=%s d=%s fs=%s cd->isTemplate=%d\n",
1261 // qPrint(symName),
1262 // qPrint(word),
1263 // cd ? qPrint(cd->name()) : "<none>",
1264 // d ? qPrint( d->name()) : "<none>",
1265 // fs ? qPrint(fs->name()) : "<none>",
1266 // cd ? cd->isTemplate():-1
1267 // );
1268
1269 //printf(" >>>> word '%s' => '%s' templSpec=%s ts=%s tSpec=%s isTemplate=%d resolvedType=%s\n",
1270 // qPrint((word+templSpec)),
1271 // cd ? qPrint(cd->qualifiedName()) : "<none>",
1272 // qPrint(templSpec), qPrint(ts),
1273 // tSpec ? qPrint(tSpec) : "<null>",
1274 // cd ? cd->isTemplate():false,
1275 // qPrint(resolvedType));
1276
1277 //printf(" mtype=%s\n",mType ? qPrint(mType->name()) : "<none>");
1278
1279 if (cd) // resolves to a known class type
1280 {
1281 if (cd==d && tSpec) *tSpec="";
1282
1283 if (mType && mType->isTypedef()) // but via a typedef
1284 {
1285 result = resolvedType+ts; // the +ts was added for bug 685125
1286 }
1287 else
1288 {
1289 if (isTemplInst)
1290 {
1291 // spec is already part of class type
1292 templSpec="";
1293 if (tSpec) *tSpec="";
1294 }
1295 else if (!ts.empty() && templSpec.empty())
1296 {
1297 // use formal template args for spec
1298 templSpec = stripDeclKeywords(getCanonicalTemplateSpec(d,fs,ts,lang));
1299 }
1300
1301 result = removeRedundantWhiteSpace(cd->qualifiedName() + templSpec);
1302
1303 if (cd->isTemplate() && tSpec) //
1304 {
1305 if (!templSpec.empty()) // specific instance
1306 {
1307 result=cd->name()+templSpec;
1308 }
1309 else // use template type
1310 {
1312 }
1313 // template class, so remove the template part (it is part of the class name)
1314 *tSpec="";
1315 }
1316 else if (ts.empty() && !templSpec.empty() && cd && !cd->isTemplate() && tSpec)
1317 {
1318 // obscure case, where a class is used as a template, but doxygen think it is
1319 // not (could happen when loading the class from a tag file).
1320 *tSpec="";
1321 }
1322 }
1323 }
1324 else if (mType && mType->isEnumerate()) // an enum
1325 {
1326 result = mType->qualifiedName();
1327 }
1328 else if (mType && mType->isTypedef()) // a typedef
1329 {
1330 //result = mType->qualifiedName(); // changed after 1.7.2
1331 //result = mType->typeString();
1332 //printf("word=%s typeString=%s\n",qPrint(word),mType->typeString());
1333 if (word!=mType->typeString())
1334 {
1335 DString type = mType->typeString();
1336 if (type.startsWith("typename "))
1337 {
1338 type.stripPrefix("typename ");
1339 type = stripTemplateSpecifiersFromScope(type,false);
1340 }
1341 if (!type.empty()) // see issue #11065
1342 {
1343 result = getCanonicalTypeForIdentifier(d,fs,type,mType->getLanguage(),tSpec,count+1);
1344 }
1345 else
1346 {
1347 result = word;
1348 }
1349 }
1350 else
1351 {
1352 result = mType->typeString();
1353 }
1354 }
1355 else // fallback
1356 {
1357 resolvedType = lang==SrcLangExt::Java ? word : resolveTypeDef(d,word);
1358 AUTO_TRACE_ADD("fallback resolvedType='{}'",resolvedType);
1359 if (resolvedType.empty()) // not known as a typedef either
1360 {
1361 result = word;
1362 }
1363 else
1364 {
1365 result = resolvedType;
1366 }
1367 }
1368 AUTO_TRACE_EXIT("result='{}'",result);
1369 return result;
1370}
virtual bool isTemplate() const =0
Returns true if this class is a template.
virtual DString 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 DString qualifiedName() const =0
virtual bool isEnumerate() const =0
virtual DString typeString() const =0
#define AUTO_TRACE_ADD(...)
Definition docnode.cpp:54
static DString stripDeclKeywords(const DString &s)
Definition util.cpp:1181
static DString getCanonicalTemplateSpec(const Definition *d, const FileDef *fs, const DString &spec, SrcLangExt lang)
Definition util.cpp:1197
DString stripScope(const DString &name)
Definition util.cpp:3109
DString stripTemplateSpecifiersFromScope(const DString &fullName, bool parentOnly, DString *pLastScopeStripped, DString scopeName, bool allowArtificial)
Definition util.cpp:3686

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

Referenced by extractCanonicalType(), and getCanonicalTypeForIdentifier().

◆ getDefs()

GetDefResult getDefs ( const GetDefInput & input)

Definition at line 1866 of file util.cpp.

1867{
1868 GetDefResult result;
1869 if (input.memberName.empty()) return result;
1870 AUTO_TRACE("scopeName={},memberName={},forceEmptyScope={}",
1871 input.scopeName,input.memberName,input.forceEmptyScope);
1872
1873 //printf("@@ --- getDefsNew(%s,%s)-----------\n",qPrint(scName),qPrint(mbName));
1874 const Definition *scope = Doxygen::globalScope;
1875 SymbolResolver resolver;
1876 if (input.currentFile) resolver.setFileScope(input.currentFile);
1877 if (!input.scopeName.empty() && !input.forceEmptyScope)
1878 {
1879 scope = resolver.resolveSymbol(scope,input.scopeName);
1880 }
1881 if (scope==Doxygen::globalScope)
1882 {
1883 scope = input.currentFile;
1884 }
1885 //printf("@@ -> found scope scope=%s member=%s out=%s\n",qPrint(input.scopeName),qPrint(input.memberName),qPrint(scope?scope->name():""));
1886 //
1887 const Definition *symbol = resolver.resolveSymbol(scope,input.memberName,input.args,input.checkCV,input.insideCode,true);
1888 //printf("@@ -> found symbol in=%s out=%s\n",qPrint(input.memberName),qPrint(symbol?symbol->qualifiedName():DString()));
1889 if (symbol && symbol->definitionType()==Definition::TypeMember)
1890 {
1891 result.md = toMemberDef(symbol);
1892 result.cd = result.md->getClassDef();
1893 if (result.cd==nullptr) result.nd = result.md->getNamespaceDef();
1894 if (result.cd==nullptr && result.nd==nullptr) result.fd = result.md->getFileDef();
1895 result.gd = result.md->getGroupDef();
1896 result.found = true;
1897 }
1898 else if (symbol && symbol->definitionType()==Definition::TypeClass)
1899 {
1900 result.cd = toClassDef(symbol);
1901 result.found = true;
1902 }
1903 else if (symbol && symbol->definitionType()==Definition::TypeNamespace)
1904 {
1905 result.nd = toNamespaceDef(symbol);
1906 result.found = true;
1907 }
1908 else if (symbol && symbol->definitionType()==Definition::TypeConcept)
1909 {
1910 result.cnd = toConceptDef(symbol);
1911 result.found = true;
1912 }
1913 else if (symbol && symbol->definitionType()==Definition::TypeModule)
1914 {
1915 result.modd = toModuleDef(symbol);
1916 result.found = true;
1917 }
1918 return result;
1919}
The common base class of all entity definitions found in the sources.
Definition definition.h:77
static NamespaceDefMutable * globalScope
Definition doxygen.h:114
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 DString &name, const DString &args=DString(), 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:85
const FileDef * currentFile
Definition util.h:86
bool insideCode
Definition util.h:88
DString args
Definition util.h:84
DString memberName
Definition util.h:83
bool checkCV
Definition util.h:87
DString scopeName
Definition util.h:82
const MemberDef * md
Definition util.h:95
const ConceptDef * cnd
Definition util.h:100
const FileDef * fd
Definition util.h:97
const ModuleDef * modd
Definition util.h:101
const GroupDef * gd
Definition util.h:99
bool found
Definition util.h:94
const ClassDef * cd
Definition util.h:96
const NamespaceDef * nd
Definition util.h:98

References GetDefInput::args, AUTO_TRACE, GetDefResult::cd, GetDefInput::checkCV, GetDefResult::cnd, GetDefInput::currentFile, Definition::definitionType(), DString::empty(), GetDefResult::fd, GetDefInput::forceEmptyScope, GetDefResult::found, GetDefResult::gd, MemberDef::getClassDef(), MemberDef::getFileDef(), MemberDef::getGroupDef(), MemberDef::getNamespaceDef(), Doxygen::globalScope, GetDefInput::insideCode, 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()

DString getDotImageExtension ( )

Returns the file extension to use for dot files as specified via the DOT_IMAGE_FORMAT configuration option.

Definition at line 4964 of file util.cpp.

4965{
4966 DString imgExt = Config_getEnumAsString(DOT_IMAGE_FORMAT);
4967 size_t i= imgExt.find(':'); // strip renderer part when using e.g. 'png:cairo:gd' as format
4968 return i==DString::npos ? imgExt : imgExt.left(i);
4969}
#define Config_getEnumAsString(name)
Definition config.h:36

References Config_getEnumAsString, DString::find(), DString::left(), and DString::npos.

Referenced by MermaidManager::convertToImageFormat(), 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(), HtmlDocVisitor::writeMscFile(), and HtmlDocVisitor::writePlantUMLFile().

◆ getEncoding()

DString getEncoding ( const FileInfo & fi)

Definition at line 4477 of file util.cpp.

4478{
4479 InputFileEncoding elem;
4480 auto getter = [](const InputFileEncoding &e) { return e.pattern.str(); };
4481 if (fi.match(Doxygen::inputFileEncodingList,useCaseSenseNames(),&elem,getter)) // check for file specific encoding
4482 {
4483 return elem.encoding;
4484 }
4485 else // fall back to default encoding
4486 {
4487 return Config_getString(INPUT_ENCODING);
4488 }
4489}
static InputFileEncodingList inputFileEncodingList
Definition doxygen.h:131
bool match(const PatternList &patList, bool caseSenseNames, PatternElem *elem=nullptr, PatternGet getter=[](const std::string &s){ return s;}) const
Match the file name against a list of patterns.
Definition fileinfo.h:60
#define Config_getString(name)
Definition config.h:32
DString encoding
Definition doxygen.h:63

References Config_getString, InputFileEncoding::encoding, Doxygen::inputFileEncodingList, FileInfo::match(), and useCaseSenseNames().

Referenced by readCodeFragment(), and readInputFile().

◆ getFileFilter()

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

1021{
1022 // sanity check
1023 if (name.empty()) return "";
1024
1025 StringVector filterSrcList = Config_getList(FILTER_SOURCE_PATTERNS);
1026 StringVector filterList = Config_getList(FILTER_PATTERNS);
1027
1028 DString filterName;
1029 bool found=false;
1030 if (isSourceCode && !filterSrcList.empty())
1031 { // first look for source filter pattern list
1032 filterName = getFilterFromList(name,filterSrcList,found);
1033 }
1034 if (!found && filterName.empty())
1035 { // then look for filter pattern list
1036 filterName = getFilterFromList(name,filterList,found);
1037 }
1038 if (!found)
1039 { // then use the generic input filter
1040 return Config_getString(INPUT_FILTER);
1041 }
1042 else
1043 {
1044 /* remove surrounding double quotes */
1045 if (filterName.length()>=2 && filterName[0]=='"' && filterName[static_cast<int>(filterName.length())-1]=='"')
1046 {
1047 filterName = filterName.mid(1,filterName.length()-2);
1048 }
1049 return filterName;
1050 }
1051}
static DString getFilterFromList(const DString &name, const StringVector &filterList, bool &found)
Definition util.cpp:985

References Config_getList, Config_getString, DString::empty(), getFilterFromList(), DString::length(), and DString::mid().

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

◆ getFileNameExtension()

◆ getFilterFromList()

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

Definition at line 985 of file util.cpp.

986{
987 found=false;
988 // compare the file name to the filter pattern list
989 for (const auto &filterStr : filterList)
990 {
991 DString fs = filterStr;
992 if (size_t i_equals=fs.find('='); i_equals!=DString::npos)
993 {
994 DString filterPattern = fs.left(i_equals);
995 DString input = name;
997 {
998 filterPattern = filterPattern.lower();
999 input = input.lower();
1000 }
1001 reg::Ex re(filterPattern.str(),reg::Ex::Mode::Wildcard);
1002 if (re.isValid() && reg::match(input.str(),re))
1003 {
1004 // found a match!
1005 DString filterName = fs.mid(i_equals+1);
1006 if (filterName.find(' ')!=DString::npos)
1007 { // add quotes if the name has spaces
1008 filterName="\""+filterName+"\"";
1009 }
1010 found=true;
1011 return filterName;
1012 }
1013 }
1014 }
1015
1016 // no match
1017 return "";
1018}
@ Wildcard
simple globbing pattern.
Definition regex.h:45
bool fileSystemIsCaseSensitive()
Definition portable.cpp:486

References Portable::fileSystemIsCaseSensitive(), DString::find(), reg::Ex::isValid(), DString::left(), DString::lower(), reg::match(), DString::mid(), DString::npos, DString::str(), and reg::Ex::Wildcard.

Referenced by getFileFilter().

◆ getLanguageFromCodeLang()

SrcLangExt getLanguageFromCodeLang ( DString & fileName)

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

Definition at line 4186 of file util.cpp.

4187{
4188 // try the extension
4189 auto lang = getLanguageFromFileName(fileName, SrcLangExt::Unknown);
4190 if (lang == SrcLangExt::Unknown)
4191 {
4192 // try the language names
4193 DString langName = fileName.lower();
4194 if (langName.at(0)=='.') langName = langName.mid(1);
4195 auto it = std::find_if(g_lang2extMap.begin(),g_lang2extMap.end(),
4196 [&langName](const auto &info) { return info.langName==langName; });
4197 if (it != g_lang2extMap.end())
4198 {
4199 lang = it->parserId;
4200 fileName = it->defExt;
4201 }
4202 else // default to C++
4203 {
4204 return SrcLangExt::Cpp;
4205 }
4206 }
4207 return lang;
4208}
SrcLangExt getLanguageFromFileName(const DString &fileName, SrcLangExt defLang)
Definition util.cpp:4168
static std::vector< Lang2ExtMap > g_lang2extMap
Definition util.cpp:4039

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

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

◆ getLanguageFromFileName()

SrcLangExt getLanguageFromFileName ( const DString & fileName,
SrcLangExt defLang )

Definition at line 4168 of file util.cpp.

4169{
4170 FileInfo fi(fileName.str());
4171 // we need only the part after the last ".", newer implementations of FileInfo have 'suffix()' for this.
4172 DString extName = DString(fi.extension(false)).lower();
4173 if (extName.empty()) extName=".no_extension";
4174 if (extName.at(0)!='.') extName.prepend(".");
4175 auto it = g_extLookup.find(extName.str());
4176 if (it!=g_extLookup.end()) // listed extension
4177 {
4178 //printf("getLanguageFromFileName(%s)=%x\n",qPrint(fi.extension()),*pVal);
4179 return it->second;
4180 }
4181 //printf("getLanguageFromFileName(%s) not found!\n",qPrint(fileName));
4182 return defLang; // not listed => assume C-ish language.
4183}
static std::unordered_map< std::string, SrcLangExt > g_extLookup
Definition util.cpp:4029

References DString::at(), DString::empty(), FileInfo::extension(), g_extLookup, DString::lower(), DString::prepend(), and DString::str().

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

◆ getLanguageSpecificSeparator()

DString getLanguageSpecificSeparator ( SrcLangExt lang,
bool classScope = false )

Returns the scope separator to use given the programming language lang

Definition at line 4629 of file util.cpp.

4630{
4631 if (lang==SrcLangExt::Java || lang==SrcLangExt::CSharp || lang==SrcLangExt::VHDL || lang==SrcLangExt::Python)
4632 {
4633 return ".";
4634 }
4635 else if (lang==SrcLangExt::PHP && !classScope)
4636 {
4637 return "\\";
4638 }
4639 else
4640 {
4641 return "::";
4642 }
4643}

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

◆ getMemberFromSymbol()

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

Definition at line 4219 of file util.cpp.

4221{
4222 if (scope==nullptr ||
4225 )
4226 )
4227 {
4229 }
4230
4231 DString name = n;
4232 if (name.empty())
4233 return nullptr; // no name was given
4234
4235 auto &range = Doxygen::symbolMap->find(name);
4236 if (range.empty())
4237 return nullptr; // could not find any matching symbols
4238
4239 // mostly copied from getResolvedClassRec()
4240 DString explicitScopePart;
4241 int qualifierIndex = computeQualifiedIndex(name);
4242 if (qualifierIndex!=-1)
4243 {
4244 explicitScopePart = name.left(qualifierIndex);
4245 replaceNamespaceAliases(explicitScopePart);
4246 name = name.mid(qualifierIndex+2);
4247 }
4248 //printf("explicitScopePart=%s\n",qPrint(explicitScopePart));
4249
4250 int minDistance = 10000;
4251 MemberDef *bestMatch = nullptr;
4252
4253 for (Definition *d : range)
4254 {
4255 if (d->definitionType()==Definition::TypeMember)
4256 {
4257 SymbolResolver resolver(fileScope);
4258 int distance = resolver.isAccessibleFromWithExpScope(scope,d,explicitScopePart);
4259 if (distance!=-1 && distance<minDistance)
4260 {
4261 minDistance = distance;
4262 bestMatch = toMemberDef(d);
4263 //printf("new best match %s distance=%d\n",qPrint(bestMatch->qualifiedName()),distance);
4264 }
4265 }
4266 }
4267 return bestMatch;
4268}
static SymbolMap< Definition > * symbolMap
Definition doxygen.h:118
const VectorPtr & find(const DString &name)
Definition symbolmap.h:74
void replaceNamespaceAliases(DString &name)
int computeQualifiedIndex(const DString &name)
Return the index of the last :: in the string name that is still before the first <.
Definition util.cpp:5278

References computeQualifiedIndex(), Definition::definitionType(), DString::empty(), SymbolMap< T >::find(), Doxygen::globalScope, SymbolResolver::isAccessibleFromWithExpScope(), DString::left(), DString::mid(), replaceNamespaceAliases(), Doxygen::symbolMap, toMemberDef(), Definition::TypeClass, Definition::TypeMember, and Definition::TypeNamespace.

Referenced by checkIfTypedef().

◆ getPrefixIndex()

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

2652{
2653 if (name.empty()) return 0;
2654 int result=0;
2655 StringVector sl = Config_getList(IGNORE_PREFIX);
2656 for (const auto &s : sl)
2657 {
2658 const char *ps=s.c_str();
2659 const char *pd=name.data();
2660 int i=0;
2661 while (*ps!=0 && *pd!=0 && *ps==*pd)
2662 {
2663 ps++;
2664 pd++;
2665 i++;
2666 }
2667 if (*ps==0 && *pd!=0)
2668 {
2669 result=i;
2670 break;
2671 }
2672 }
2673 if (result<static_cast<int>(name.length())-1 && name.at(result)=='[') result++; // for e.g. [union] return u
2674 return result;
2675}

References DString::at(), Config_getList, DString::data(), DString::empty(), and DString::length().

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

◆ getProjectId()

DString getProjectId ( )

Definition at line 5270 of file util.cpp.

5271{
5272 DString projectCookie = Config_getString(HTML_PROJECT_COOKIE);
5273 if (projectCookie.empty()) return DString();
5274 return md5str(projectCookie.view())+"_";
5275}

References Config_getString, DString::empty(), md5str(), and DString::view().

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

◆ getScopeDefs()

bool getScopeDefs ( const DString & docScope,
const DString & 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 1936 of file util.cpp.

1938{
1939 cd=nullptr;
1940 cnd=nullptr;
1941 nd=nullptr;
1942 modd=nullptr;
1943
1944 DString scopeName=scope;
1945 //printf("getScopeDefs: docScope='%s' scope='%s'\n",qPrint(docScope),qPrint(scope));
1946 if (scopeName.empty()) return false;
1947
1948 bool explicitGlobalScope=false;
1949 if (scopeName.at(0)==':' && scopeName.at(1)==':')
1950 {
1951 scopeName=scopeName.mid(2);
1952 explicitGlobalScope=true;
1953 }
1954 if (scopeName.empty())
1955 {
1956 return false;
1957 }
1958
1959 DString docScopeName=docScope;
1960 int scopeOffset=explicitGlobalScope ? 0 : static_cast<int>(docScopeName.length());
1961
1962 do // for each possible docScope (from largest to and including empty)
1963 {
1964 DString fullName=scopeName;
1965 if (scopeOffset>0) fullName.prepend(docScopeName.left(scopeOffset)+"::");
1966
1967 if (((cd=getClass(fullName)) || // normal class
1968 (cd=getClass(fullName+"-p")) // ObjC protocol
1969 ) && cd->isLinkable())
1970 {
1971 return true; // class link written => quit
1972 }
1973 else if ((nd=Doxygen::namespaceLinkedMap->find(fullName)) && nd->isLinkable())
1974 {
1975 return true; // namespace link written => quit
1976 }
1977 else if ((cnd=Doxygen::conceptLinkedMap->find(fullName)) && cnd->isLinkable())
1978 {
1979 return true; // concept link written => quit
1980 }
1981 else if ((modd=ModuleManager::instance().modules().find(fullName)) && modd->isLinkable())
1982 {
1983 return true; // module link written => quit
1984 }
1985 if (scopeOffset==0)
1986 {
1987 scopeOffset=-1;
1988 }
1989 else
1990 {
1991 size_t o = docScopeName.rfind("::",scopeOffset-1);
1992 scopeOffset = o!=DString::npos ? static_cast<int>(o) : 0;
1993 }
1994 } while (scopeOffset>=0);
1995
1996 return false;
1997}
virtual bool isLinkable() const =0
static NamespaceLinkedMap * namespaceLinkedMap
Definition doxygen.h:108
static ConceptLinkedMap * conceptLinkedMap
Definition doxygen.h:90
static ModuleManager & instance()

References DString::at(), Doxygen::conceptLinkedMap, DString::empty(), getClass(), ModuleManager::instance(), Definition::isLinkable(), DString::left(), DString::length(), DString::mid(), Doxygen::namespaceLinkedMap, DString::npos, DString::prepend(), and DString::rfind().

Referenced by resolveRef().

◆ getScopeFragment()

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

3799{
3800 int sl=static_cast<int>(s.length());
3801 int sp=p;
3802 int count=0;
3803 bool done=false;
3804 if (sp>=sl) return -1;
3805 while (sp<sl)
3806 {
3807 char c=s.at(sp);
3808 if (c==':')
3809 {
3810 sp++;
3811 p++;
3812 }
3813 else
3814 {
3815 break;
3816 }
3817 }
3818 while (sp<sl)
3819 {
3820 char c=s.at(sp);
3821 switch (c)
3822 {
3823 case ':': // found next part
3824 goto found;
3825 case '<': // skip template specifier
3826 count=1;sp++;
3827 done=false;
3828 while (sp<sl && !done)
3829 {
3830 // TODO: deal with << and >> operators!
3831 c=s.at(sp++);
3832 switch(c)
3833 {
3834 case '<': count++; break;
3835 case '>': count--; if (count==0) done=true; break;
3836 default: break;
3837 }
3838 }
3839 break;
3840 default:
3841 sp++;
3842 break;
3843 }
3844 }
3845found:
3846 *l=sp-p;
3847 //printf("getScopeFragment(%s,%d)=%s\n",qPrint(s),p,qPrint(s.mid(p,*l)));
3848 return p;
3849}

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

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

◆ initDefaultExtensionMapping()

void initDefaultExtensionMapping ( )

Definition at line 4095 of file util.cpp.

4096{
4097 // NOTE: when adding an extension, also add the extension in config.xml
4098 // extension parser id
4099 updateLanguageMapping(".dox", "c");
4100 updateLanguageMapping(".txt", "c"); // see bug 760836
4101 updateLanguageMapping(".doc", "c");
4102 updateLanguageMapping(".c", "c");
4103 updateLanguageMapping(".C", "c");
4104 updateLanguageMapping(".cc", "c");
4105 updateLanguageMapping(".CC", "c");
4106 updateLanguageMapping(".cxx", "c");
4107 updateLanguageMapping(".cpp", "c");
4108 updateLanguageMapping(".c++", "c");
4109 updateLanguageMapping(".cxxm", "c"); // C++20 modules
4110 updateLanguageMapping(".cppm", "c"); // C++20 modules
4111 updateLanguageMapping(".ccm", "c"); // C++20 modules
4112 updateLanguageMapping(".c++m", "c"); // C++20 modules
4113 updateLanguageMapping(".ii", "c");
4114 updateLanguageMapping(".ixx", "c");
4115 updateLanguageMapping(".ipp", "c");
4116 updateLanguageMapping(".i++", "c");
4117 updateLanguageMapping(".inl", "c");
4118 updateLanguageMapping(".h", "c");
4119 updateLanguageMapping(".H", "c");
4120 updateLanguageMapping(".hh", "c");
4121 updateLanguageMapping(".HH", "c");
4122 updateLanguageMapping(".hxx", "c");
4123 updateLanguageMapping(".hpp", "c");
4124 updateLanguageMapping(".h++", "c");
4125 updateLanguageMapping(".idl", "idl");
4126 updateLanguageMapping(".ddl", "idl");
4127 updateLanguageMapping(".odl", "idl");
4128 updateLanguageMapping(".java", "java");
4129 //updateLanguageMapping(".as", "javascript"); // not officially supported
4130 //updateLanguageMapping(".js", "javascript"); // not officially supported
4131 updateLanguageMapping(".cs", "csharp");
4132 updateLanguageMapping(".d", "d");
4133 updateLanguageMapping(".php", "php");
4134 updateLanguageMapping(".php4", "php");
4135 updateLanguageMapping(".php5", "php");
4136 updateLanguageMapping(".inc", "php");
4137 updateLanguageMapping(".phtml", "php");
4138 updateLanguageMapping(".m", "objective-c");
4139 updateLanguageMapping(".M", "objective-c");
4140 updateLanguageMapping(".mm", "c"); // see bug746361
4141 updateLanguageMapping(".py", "python");
4142 updateLanguageMapping(".pyw", "python");
4143 updateLanguageMapping(".f", "fortran");
4144 updateLanguageMapping(".for", "fortran");
4145 updateLanguageMapping(".f90", "fortran");
4146 updateLanguageMapping(".f95", "fortran");
4147 updateLanguageMapping(".f03", "fortran");
4148 updateLanguageMapping(".f08", "fortran");
4149 updateLanguageMapping(".f18", "fortran");
4150 updateLanguageMapping(".vhd", "vhdl");
4151 updateLanguageMapping(".vhdl", "vhdl");
4152 updateLanguageMapping(".ucf", "vhdl");
4153 updateLanguageMapping(".qsf", "vhdl");
4154 updateLanguageMapping(".md", "md");
4155 updateLanguageMapping(".markdown", "md");
4156 updateLanguageMapping(".ice", "slice");
4157 updateLanguageMapping(".l", "lex");
4158 updateLanguageMapping(".doxygen_lex_c", "c"); // this is a placeholder so we can map initializations
4159 // in the lex scanning to cpp
4160}

References updateLanguageMapping().

Referenced by initDoxygen().

◆ inlineArgListToDoc()

DString inlineArgListToDoc ( const ArgumentList & al)

Returns a documentation string combining the inline documentation for each parameter in the list al.

Definition at line 4865 of file util.cpp.

4866{
4867 DString paramDocs;
4868 if (al.hasDocumentation(true))
4869 {
4870 for (const Argument &a : al)
4871 {
4872 if (a.hasDocumentation(true))
4873 {
4874 DString docsWithoutDir = a.docs;
4875 DString direction = extractDirection(docsWithoutDir);
4876 DString name = a.name;
4877 if (name.empty())
4878 {
4879 name = "-";
4880 }
4881 paramDocs+=" \\ilinebr @param"+direction+" "+name+" "+docsWithoutDir;
4882 }
4883 }
4884 }
4885 return paramDocs;
4886}
bool hasDocumentation(bool allowEmptyNames=false) const
Definition arguments.cpp:26
static DString extractDirection(DString &docs)
Strip the direction part from docs and return it as a string in canonical form.
Definition util.cpp:4829

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

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

◆ inlineTemplateArgListToDoc()

DString inlineTemplateArgListToDoc ( const ArgumentList & al)

Returns a documentation string combining the inline documentation for each template parameter in the list al.

Definition at line 832 of file util.cpp.

833{
834 DString paramDocs;
836 {
837 for (const Argument &a : al)
838 {
839 if (!a.docs.empty())
840 {
841 if (!a.name.empty())
842 {
843 paramDocs+=" \\ilinebr @tparam "+a.name+" "+a.docs;
844 }
845 else if (!a.type.empty())
846 {
847 DString type = a.type;
848 type.stripPrefix("class ");
849 type.stripPrefix("typename ");
850 type = type.stripWhiteSpace();
851 paramDocs+=" \\ilinebr @tparam "+type+" "+a.docs;
852 }
853 }
854 }
855 }
856 return paramDocs;
857}
bool hasTemplateDocumentation() const
Definition arguments.cpp:34

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

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

◆ insertTemplateSpecifierInScope()

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

Definition at line 3076 of file util.cpp.

3077{
3078 DString result=scope;
3079 if (!templ.empty() && scope.find('<')==DString::npos)
3080 {
3081 size_t si=0, pi=0;
3082 ClassDef *cd=nullptr;
3083 while (
3084 (si=scope.find("::",pi))!=DString::npos && !getClass(scope.left(si)+templ) &&
3085 ((cd=getClass(scope.left(si)))==nullptr || cd->templateArguments().empty())
3086 )
3087 {
3088 //printf("Tried '%s'\n",qPrint((scope.left(si)+templ)));
3089 pi=si+2;
3090 }
3091 if (si==DString::npos) // not nested => append template specifier
3092 {
3093 result+=templ;
3094 }
3095 else // nested => insert template specifier before after first class name
3096 {
3097 result=scope.left(si) + templ + scope.mid(si);
3098 }
3099 }
3100 //printf("insertTemplateSpecifierInScope('%s','%s')=%s\n",
3101 // qPrint(scope),qPrint(templ),qPrint(result));
3102 return result;
3103}
bool empty() const
Definition arguments.h:100
virtual const ArgumentList & templateArguments() const =0
Returns the template arguments of this class.

References ArgumentList::empty(), DString::empty(), DString::find(), getClass(), DString::left(), DString::mid(), DString::npos, and ClassDef::templateArguments().

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

◆ isLowerCase()

bool isLowerCase ( DString & s)
static

Definition at line 1999 of file util.cpp.

2000{
2001 if (s.empty()) return true;
2002 const char *p=s.data();
2003 int c=0;
2004 while ((c=static_cast<uint8_t>(*p++))) if (!islower(c)) return false;
2005 return true;
2006}

References DString::data(), and DString::empty().

Referenced by resolveRef().

◆ isURL()

bool isURL ( const DString & url)

Checks whether the given url starts with a supported protocol.

Definition at line 4646 of file util.cpp.

4647{
4648 static const std::unordered_set<std::string> schemes = {
4649 "http", "https", "ftp", "ftps", "sftp", "file", "news", "irc", "ircs"
4650 };
4651 DString loc_url = url.stripWhiteSpace();
4652 size_t colonPos = loc_url.find(':');
4653 return colonPos!=DString::npos && schemes.find(loc_url.left(colonPos).str())!=schemes.end();
4654}

References DString::find(), DString::left(), DString::npos, DString::str(), and DString::stripWhiteSpace().

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

◆ leftScopeMatch()

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

Definition at line 740 of file util.cpp.

741{
742 size_t sl=scope.length();
743 size_t nl=name.length();
744 return (name==scope || // equal
745 (name.left(sl)==scope && // substring
746 nl>sl+1 && name.at(sl)==':' && name.at(sl+1)==':' // scope
747 )
748 );
749}

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

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

◆ linkToText()

DString linkToText ( SrcLangExt lang,
const DString & link,
bool ignoreDots )

Definition at line 2265 of file util.cpp.

2266{
2267 //bool optimizeOutputJava = Config_getBool(OPTIMIZE_OUTPUT_JAVA);
2268 DString result=link;
2269 if (!result.empty())
2270 {
2271 // replace # by ::
2272 result=substitute(result,"#","::");
2273 // replace . by ::
2274 if (!ignoreDots && result.find('<')==DString::npos) result=substitute(result,".","::",3);
2275 // strip leading :: prefix if present
2276 if (result.at(0)==':' && result.at(1)==':')
2277 {
2278 result=result.mid(2);
2279 }
2281 if (sep!="::")
2282 {
2283 result=substitute(result,"::",sep);
2284 }
2285 }
2286 //printf("linkToText(%s,lang=%d)=%s\n",qPrint(link),lang,qPrint(result));
2287 return result;
2288}
DString substitute(const DString &s, const DString &src, const DString &dst)
substitute all occurrences of src in s by dst
Definition dstring.cpp:485
DString getLanguageSpecificSeparator(SrcLangExt lang, bool classScope)
Definition util.cpp:4629

References DString::at(), DString::empty(), DString::find(), getLanguageSpecificSeparator(), DString::mid(), DString::npos, and substitute().

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

◆ mainPageHasTitle()

bool mainPageHasTitle ( )

Definition at line 4959 of file util.cpp.

4960{
4961 return Doxygen::mainPage!=nullptr && Doxygen::mainPage->hasTitle();
4962}
static std::unique_ptr< PageDef > mainPage
Definition doxygen.h:93

References Doxygen::mainPage.

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

◆ makeBaseName()

◆ mangleCSharpGenericName()

DString mangleCSharpGenericName ( const DString & name)

Definition at line 5319 of file util.cpp.

5320{
5321 if (size_t idx = name.find('<'); idx!=DString::npos)
5322 {
5323 return name.left(idx)+"-"+DString().setNum(name.contains(",")+1)+"-g";
5324 }
5325 return name;
5326}
DString & setNum(short n)
Definition dstring.h:552
int contains(char c, bool cs=true) const
Definition dstring.cpp:85

References DString::contains(), DString::find(), DString::left(), DString::npos, and DString::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 1523 of file util.cpp.

1528{
1529 AUTO_TRACE("src: scope={} type={} name={} canType={}, dst: scope={} type={} name={} canType={}",
1530 srcScope?srcScope->name():"",srcA.type,srcA.name,srcA.canType,
1531 dstScope?dstScope->name():"",dstA.type,dstA.name,dstA.canType);
1532 //printf(">> match argument: %s::'%s|%s' (%s) <-> %s::'%s|%s' (%s)\n",
1533 // srcScope ? qPrint(srcScope->name()) : "",
1534 // qPrint(srcA.type), qPrint(srcA.name), qPrint(srcA.canType),
1535 // dstScope ? qPrint(dstScope->name()) : "",
1536 // qPrint(dstA.type), qPrint(dstA.name), qPrint(dstA.canType));
1537
1538 DString sSrcName = " "+srcA.name;
1539 DString sDstName = " "+dstA.name;
1540 DString srcType = srcA.type;
1541 DString dstType = dstA.type;
1542 stripIrrelevantConstVolatile(srcType,false);
1543 stripIrrelevantConstVolatile(dstType,false);
1544 //printf("'%s'<->'%s'\n",qPrint(sSrcName),qPrint(dstType.right(sSrcName.length())));
1545 //printf("'%s'<->'%s'\n",qPrint(sDstName),qPrint(srcType.right(sDstName.length())));
1546 if (sSrcName==dstType.right(sSrcName.length()))
1547 { // case "unsigned int" <-> "unsigned int i"
1548 srcA.type+=sSrcName;
1549 srcA.name="";
1550 srcA.canType=""; // invalidate cached type value
1551 }
1552 else if (sDstName==srcType.right(sDstName.length()))
1553 { // case "unsigned int i" <-> "unsigned int"
1554 dstA.type+=sDstName;
1555 dstA.name="";
1556 dstA.canType=""; // invalidate cached type value
1557 }
1558
1559 {
1560 std::lock_guard lock(g_matchArgsMutex);
1561 if (srcA.canType.empty() || dstA.canType.empty())
1562 {
1563 // need to re-evaluate both see issue #8370
1564 srcA.canType = extractCanonicalArgType(srcScope,srcFileScope,srcA,lang);
1565 dstA.canType = extractCanonicalArgType(dstScope,dstFileScope,dstA,lang);
1566 }
1567 }
1568
1569 if (matchCanonicalTypes(srcScope,srcFileScope,srcA.canType,
1570 dstScope,dstFileScope,dstA.canType,
1571 lang))
1572 {
1573 MATCH
1574 AUTO_TRACE_EXIT("true");
1575 return true;
1576 }
1577 else
1578 {
1579 //printf(" Canonical types do not match [%s]<->[%s]\n",
1580 // qPrint(srcA->canType),qPrint(dstA->canType));
1581 NOMATCH
1582 AUTO_TRACE_EXIT("false");
1583 return false;
1584 }
1585}
static DString extractCanonicalArgType(const Definition *d, const FileDef *fs, const Argument &arg, SrcLangExt lang)
Definition util.cpp:1458
#define MATCH
Definition util.cpp:1488
#define NOMATCH
Definition util.cpp:1489
static bool matchCanonicalTypes(const Definition *srcScope, const FileDef *srcFileScope, const DString &srcType, const Definition *dstScope, const FileDef *dstFileScope, const DString &dstType, SrcLangExt lang)
Definition util.cpp:1491
static std::mutex g_matchArgsMutex
Definition util.cpp:1481

References AUTO_TRACE, AUTO_TRACE_EXIT, Argument::canType, DString::empty(), extractCanonicalArgType(), g_matchArgsMutex, DString::length(), MATCH, matchCanonicalTypes(), Argument::name, Definition::name(), NOMATCH, DString::right(), stripIrrelevantConstVolatile(), and Argument::type.

Referenced by matchArguments2().

◆ matchArguments2()

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

Compares two parameter lists srcAl and dstAl and returns true if they match.

Definition at line 1589 of file util.cpp.

1592{
1593 ASSERT(srcScope!=nullptr && dstScope!=nullptr);
1594
1595 AUTO_TRACE("srcScope='{}' dstScope='{}' srcArgs='{}' dstArgs='{}' checkCV={} lang={}",
1596 srcScope->name(),dstScope->name(),srcAl?argListToString(*srcAl):"",dstAl?argListToString(*dstAl):"",checkCV,lang);
1597
1598 if (srcAl==nullptr || dstAl==nullptr)
1599 {
1600 bool match = srcAl==dstAl;
1601 if (match)
1602 {
1603 MATCH
1604 return true;
1605 }
1606 else
1607 {
1608 NOMATCH
1609 return false;
1610 }
1611 }
1612
1613 // handle special case with void argument
1614 if ( srcAl->empty() && dstAl->size()==1 && dstAl->front().type=="void" )
1615 { // special case for finding match between func() and func(void)
1616 Argument a;
1617 a.type = "void";
1618 const_cast<ArgumentList*>(srcAl)->push_back(a);
1619 MATCH
1620 return true;
1621 }
1622 if ( dstAl->empty() && srcAl->size()==1 && srcAl->front().type=="void" )
1623 { // special case for finding match between func(void) and func()
1624 Argument a;
1625 a.type = "void";
1626 const_cast<ArgumentList*>(dstAl)->push_back(a);
1627 MATCH
1628 return true;
1629 }
1630
1631 if (srcAl->size() != dstAl->size())
1632 {
1633 NOMATCH
1634 return false; // different number of arguments -> no match
1635 }
1636
1637 if (checkCV)
1638 {
1639 if (srcAl->constSpecifier() != dstAl->constSpecifier())
1640 {
1641 NOMATCH
1642 return false; // one member is const, the other not -> no match
1643 }
1644 if (srcAl->volatileSpecifier() != dstAl->volatileSpecifier())
1645 {
1646 NOMATCH
1647 return false; // one member is volatile, the other not -> no match
1648 }
1649 }
1650
1651 if (srcAl->refQualifier() != dstAl->refQualifier())
1652 {
1653 NOMATCH
1654 return false; // one member is has a different ref-qualifier than the other
1655 }
1656
1657 if (srcReturnType=="auto" && dstReturnType=="auto" && srcAl->trailingReturnType()!=dstAl->trailingReturnType())
1658 {
1659 NOMATCH
1660 return false; // one member is has a different return type than the other
1661 }
1662
1663 // so far the argument list could match, so we need to compare the types of
1664 // all arguments.
1665 auto srcIt = srcAl->begin();
1666 auto dstIt = dstAl->begin();
1667 for (;srcIt!=srcAl->end() && dstIt!=dstAl->end();++srcIt,++dstIt)
1668 {
1669 Argument &srcA = const_cast<Argument&>(*srcIt);
1670 Argument &dstA = const_cast<Argument&>(*dstIt);
1671 if (!matchArgument2(srcScope,srcFileScope,srcA,
1672 dstScope,dstFileScope,dstA,
1673 lang)
1674 )
1675 {
1676 NOMATCH
1677 return false;
1678 }
1679 }
1680 MATCH
1681 return true; // all arguments match
1682}
This class represents an function or template argument list.
Definition arguments.h:66
Argument & front()
Definition arguments.h:106
size_t size() const
Definition arguments.h:101
DString argListToString(const ArgumentList &al, bool useCanonicalType, bool showDefVals)
Definition util.cpp:859
static bool matchArgument2(const Definition *srcScope, const FileDef *srcFileScope, Argument &srcA, const Definition *dstScope, const FileDef *dstFileScope, Argument &dstA, SrcLangExt lang)
Definition util.cpp:1523

References argListToString(), ASSERT, AUTO_TRACE, ArgumentList::begin(), ArgumentList::constSpecifier(), ArgumentList::empty(), ArgumentList::end(), ArgumentList::front(), MATCH, matchArgument2(), Definition::name(), NOMATCH, ArgumentList::refQualifier(), ArgumentList::size(), ArgumentList::trailingReturnType(), 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 DString & srcType,
const Definition * dstScope,
const FileDef * dstFileScope,
const DString & dstType,
SrcLangExt lang )
static

Definition at line 1491 of file util.cpp.

1495{
1496 AUTO_TRACE("srcType='{}' dstType='{}'",srcType,dstType);
1497 if (srcType==dstType) return true;
1498
1499 // check if the types are function pointers
1500 size_t i1=srcType.find(")(");
1501 if (i1==DString::npos) return false;
1502 size_t i2=dstType.find(")(");
1503 if (i1!=i2) return false;
1504
1505 // check if the result part of the function pointer types matches
1506 size_t j1=srcType.find("(");
1507 if (j1==DString::npos || j1>i1) return false;
1508 size_t j2=dstType.find("(");
1509 if (j2!=j1) return false;
1510 if (srcType.left(j1)!=dstType.left(j2)) return false; // different return types
1511
1512 // if srcType and dstType are both function pointers with the same return type,
1513 // then match against the parameter lists.
1514 // This way srcType='void (*fptr)(int x)' will match against `void (*fptr)(int y)' because
1515 // 'int x' matches 'int y'. A simple literal string match would treat these as different.
1516 auto srcAl = stringToArgumentList(lang,srcType.mid(i1+1));
1517 auto dstAl = stringToArgumentList(lang,dstType.mid(i2+1));
1518 return matchArguments2(srcScope,srcFileScope,srcType.left(j1),srcAl.get(),
1519 dstScope,dstFileScope,dstType.left(j2),dstAl.get(),
1520 true,lang);
1521}
std::unique_ptr< ArgumentList > stringToArgumentList(SrcLangExt lang, const DString &argsString, DString *extraTypeChars=nullptr)
Definition defargs.l:821
bool matchArguments2(const Definition *srcScope, const FileDef *srcFileScope, const DString &srcReturnType, const ArgumentList *srcAl, const Definition *dstScope, const FileDef *dstFileScope, const DString &dstReturnType, const ArgumentList *dstAl, bool checkCV, SrcLangExt lang)
Definition util.cpp:1589

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

Referenced by matchArgument2().

◆ matchTemplateArguments()

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

Returns true if the template parameter lists srcAl and dstAl match. The lists are considered to match if they have the same number of parameters and each matching parameter in srcAl and dstAl has the same constraints (or at least one parameter has no constraints).

Definition at line 1833 of file util.cpp.

1834{
1835 AUTO_TRACE("srcAl={} dstAl={}",argListToString(srcAl),argListToString(dstAl));
1836 if (srcAl.size()!=dstAl.size()) // different number of template parameters -> overload
1837 {
1838 AUTO_TRACE_EXIT("different number of parameters");
1839 return false;
1840 }
1841 auto isUnconstraintTemplate = [](const DString &type)
1842 {
1843 return type=="typename" || type=="class" || type.startsWith("typename ") || type.startsWith("class ");
1844 };
1845 auto srcIt = srcAl.begin();
1846 auto dstIt = dstAl.begin();
1847 while (srcIt!=srcAl.end() && dstIt!=dstAl.end())
1848 {
1849 const Argument &srcA = *srcIt;
1850 const Argument &dstA = *dstIt;
1851 if ((!isUnconstraintTemplate(srcA.type) || !isUnconstraintTemplate(dstA.type)) && srcA.type!=dstA.type) // different constraints -> overload
1852 {
1853 AUTO_TRACE_EXIT("different constraints");
1854 return false;
1855 }
1856 ++srcIt;
1857 ++dstIt;
1858 }
1859 AUTO_TRACE_EXIT("same");
1860 // no overload with respect to the template parameters
1861 return true;
1862}

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

Referenced by buildFunctionList().

◆ mergeArguments()

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

Merges the information of two parameter lists (typically a declaration and a definition). Missing information is added to either list. The name of parameter of srcAl is only overwritten if forceNameOverwrite is true.

Definition at line 1689 of file util.cpp.

1690{
1691 AUTO_TRACE("srcAl='{}',dstAl='{}',forceNameOverwrite={}",
1692 qPrint(argListToString(srcAl)),qPrint(argListToString(dstAl)),forceNameOverwrite);
1693
1694 if (srcAl.size()!=dstAl.size())
1695 {
1696 return; // invalid argument lists -> do not merge
1697 }
1698
1699 auto srcIt=srcAl.begin();
1700 auto dstIt=dstAl.begin();
1701 while (srcIt!=srcAl.end() && dstIt!=dstAl.end())
1702 {
1703 Argument &srcA = *srcIt;
1704 Argument &dstA = *dstIt;
1705
1706 AUTO_TRACE_ADD("before merge: src=[type='{}',name='{}',def='{}'] dst=[type='{}',name='{}',def='{}']",
1707 srcA.type,srcA.name,srcA.defval,
1708 dstA.type,dstA.name,dstA.defval);
1709 if (srcA.defval.empty() && !dstA.defval.empty())
1710 {
1711 //printf("Defval changing '%s'->'%s'\n",qPrint(srcA.defval),qPrint(dstA.defval));
1712 srcA.defval=dstA.defval;
1713 }
1714 else if (!srcA.defval.empty() && dstA.defval.empty())
1715 {
1716 //printf("Defval changing '%s'->'%s'\n",qPrint(dstA.defval),qPrint(srcA.defval));
1717 dstA.defval=srcA.defval;
1718 }
1719
1720 // fix wrongly detected const or volatile specifiers before merging.
1721 // example: "const A *const" is detected as type="const A *" name="const"
1722 if (srcA.name=="const" || srcA.name=="volatile")
1723 {
1724 srcA.type+=" "+srcA.name;
1725 srcA.name.clear();
1726 }
1727 if (dstA.name=="const" || dstA.name=="volatile")
1728 {
1729 dstA.type+=" "+dstA.name;
1730 dstA.name.clear();
1731 }
1732
1733 if (srcA.type==dstA.type)
1734 {
1735 //printf("1. merging %s:%s <-> %s:%s\n",qPrint(srcA.type),qPrint(srcA.name),qPrint(dstA.type),qPrint(dstA.name));
1736 if (srcA.name.empty() && !dstA.name.empty())
1737 {
1738 //printf("type: '%s':='%s'\n",qPrint(srcA.type),qPrint(dstA.type));
1739 //printf("name: '%s':='%s'\n",qPrint(srcA.name),qPrint(dstA.name));
1740 srcA.type = dstA.type;
1741 srcA.name = dstA.name;
1742 }
1743 else if (!srcA.name.empty() && dstA.name.empty())
1744 {
1745 //printf("type: '%s':='%s'\n",qPrint(dstA.type),qPrint(srcA.type));
1746 //printf("name: '%s':='%s'\n",qPrint(dstA.name),qPrint(srcA.name));
1747 dstA.type = srcA.type;
1748 dstA.name = srcA.name;
1749 }
1750 else if (!srcA.name.empty() && !dstA.name.empty())
1751 {
1752 //printf("srcA.name=%s dstA.name=%s\n",qPrint(srcA.name),qPrint(dstA.name));
1753 if (forceNameOverwrite)
1754 {
1755 srcA.name = dstA.name;
1756 }
1757 else
1758 {
1759 if (srcA.docs.empty() && !dstA.docs.empty())
1760 {
1761 srcA.name = dstA.name;
1762 }
1763 else if (!srcA.docs.empty() && dstA.docs.empty())
1764 {
1765 dstA.name = srcA.name;
1766 }
1767 }
1768 }
1769 }
1770 else
1771 {
1772 //printf("2. merging '%s':'%s' <-> '%s':'%s'\n",qPrint(srcA.type),qPrint(srcA.name),qPrint(dstA.type),qPrint(dstA.name));
1773 srcA.type=srcA.type.stripWhiteSpace();
1774 dstA.type=dstA.type.stripWhiteSpace();
1775 if (srcA.type+" "+srcA.name==dstA.type) // "unsigned long:int" <-> "unsigned long int:bla"
1776 {
1777 srcA.type+=" "+srcA.name;
1778 srcA.name=dstA.name;
1779 }
1780 else if (dstA.type+" "+dstA.name==srcA.type) // "unsigned long int bla" <-> "unsigned long int"
1781 {
1782 dstA.type+=" "+dstA.name;
1783 dstA.name=srcA.name;
1784 }
1785 else if (srcA.name.empty() && !dstA.name.empty())
1786 {
1787 srcA.name = dstA.name;
1788 }
1789 else if (dstA.name.empty() && !srcA.name.empty())
1790 {
1791 dstA.name = srcA.name;
1792 }
1793 }
1794 size_t i1=srcA.type.find("::"),
1795 i2=dstA.type.find("::"),
1796 j1=srcA.type.length()-i1-2,
1797 j2=dstA.type.length()-i2-2;
1798 if (i1!=DString::npos && i2==DString::npos && srcA.type.right(j1)==dstA.type)
1799 {
1800 //printf("type: '%s':='%s'\n",qPrint(dstA.type),qPrint(srcA.type));
1801 //printf("name: '%s':='%s'\n",qPrint(dstA.name),qPrint(srcA.name));
1802 dstA.type = srcA.type.left(i1+2)+dstA.type;
1803 dstA.name = srcA.name;
1804 }
1805 else if (i1==DString::npos && i2!=DString::npos && dstA.type.right(j2)==srcA.type)
1806 {
1807 //printf("type: '%s':='%s'\n",qPrint(srcA.type),qPrint(dstA.type));
1808 //printf("name: '%s':='%s'\n",qPrint(dstA.name),qPrint(srcA.name));
1809 srcA.type = dstA.type.left(i2+2)+srcA.type;
1810 srcA.name = dstA.name;
1811 }
1812 if (srcA.docs.empty() && !dstA.docs.empty())
1813 {
1814 srcA.docs = dstA.docs;
1815 }
1816 else if (dstA.docs.empty() && !srcA.docs.empty())
1817 {
1818 dstA.docs = srcA.docs;
1819 }
1820 //printf("Merge argument '%s|%s' '%s|%s'\n",
1821 // qPrint(srcA.type), qPrint(srcA.name),
1822 // qPrint(dstA.type), qPrint(dstA.name));
1823 ++srcIt;
1824 ++dstIt;
1825 AUTO_TRACE_ADD("after merge: src=[type='{}',name='{}',def='{}'] dst=[type='{}',name='{}',def='{}']",
1826 srcA.type,srcA.name,srcA.defval,
1827 dstA.type,dstA.name,dstA.defval);
1828 }
1829}
DString docs
Definition arguments.h:48

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

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

◆ mergeScopes()

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

3754{
3755 AUTO_TRACE("leftScope='{}' rightScope='{}'",leftScope,rightScope);
3756 // case leftScope=="A" rightScope=="A::B" => result = "A::B"
3757 if (leftScopeMatch(leftScope,rightScope))
3758 {
3759 AUTO_TRACE_EXIT("case1={}",rightScope);
3760 return rightScope;
3761 }
3762 DString result;
3763 size_t i=0,p=leftScope.length();
3764
3765 // case leftScope=="A::B" rightScope=="B::C" => result = "A::B::C"
3766 // case leftScope=="A::B" rightScope=="B" => result = "A::B"
3767 bool found=false;
3768 while ((i=leftScope.rfind("::",p))!=DString::npos && i>0)
3769 {
3770 if (leftScopeMatch(rightScope,leftScope.mid(i+2)))
3771 {
3772 result = leftScope.left(i+2)+rightScope;
3773 found=true;
3774 }
3775 p=i-1;
3776 }
3777 if (found)
3778 {
3779 AUTO_TRACE_EXIT("case2={}",result);
3780 return result;
3781 }
3782
3783 // case leftScope=="A" rightScope=="B" => result = "A::B"
3784 result=leftScope;
3785 if (!result.empty() && !rightScope.empty()) result+="::";
3786 result+=rightScope;
3787 AUTO_TRACE_EXIT("case3={}",result);
3788 return result;
3789}
bool leftScopeMatch(const DString &scope, const DString &name)
Definition util.cpp:740

References AUTO_TRACE, AUTO_TRACE_EXIT, DString::empty(), DString::left(), leftScopeMatch(), DString::length(), DString::mid(), DString::npos, and DString::rfind().

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

◆ normalizeNonTemplateArgumentsInString()

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

Returns a representation of name where all known types have been normalized to their canonical form. The normalization is done in the context of context and using the formal arguments in formalArgs.

Definition at line 3465 of file util.cpp.

3469{
3470 // skip until <
3471 size_t p=name.find('<');
3472 if (p==DString::npos) return name;
3473 p++;
3474 DString result = name.left(p);
3475
3476 std::string s = name.mid(p).str();
3477 static const reg::Ex re(R"([\a:][\w:]*)");
3478 reg::Iterator it(s,re);
3480 size_t pi=0;
3481 // for each identifier in the template part (e.g. B<T> -> T)
3482 for (; it!=end ; ++it)
3483 {
3484 const auto &match = *it;
3485 size_t i = match.position();
3486 size_t l = match.length();
3487 result += s.substr(pi,i-pi);
3488 DString n(match.str());
3489 bool found=false;
3490 for (const Argument &formArg : formalArgs)
3491 {
3492 if (formArg.name == n)
3493 {
3494 found=true;
3495 break;
3496 }
3497 }
3498 if (!found)
3499 {
3500 // try to resolve the type
3501 SymbolResolver resolver;
3502 const ClassDef *cd = resolver.resolveClass(context,n);
3503 if (cd)
3504 {
3505 result+=cd->name();
3506 }
3507 else
3508 {
3509 result+=n;
3510 }
3511 }
3512 else
3513 {
3514 result+=n;
3515 }
3516 pi=i+l;
3517 }
3518 result+=s.substr(pi);
3519 //printf("normalizeNonTemplateArgumentInString(%s)=%s\n",qPrint(name),qPrint(result));
3520 return removeRedundantWhiteSpace(result);
3521}
const ClassDef * resolveClass(const Definition *scope, const DString &name, bool maybeUnlinkable=false, bool mayBeHidden=false)
Find the class definition matching name within the scope set.

References end(), DString::find(), DString::left(), DString::mid(), Definition::name(), DString::npos, removeRedundantWhiteSpace(), SymbolResolver::resolveClass(), DString::str(), and DString::substr().

Referenced by findUsedClassesForClass().

◆ openOutputFile()

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

Helper to open an output search f for writing. If the file already exists it will be renamed to .bak first. If outFile is "-" then the output will be written to standard output.

Definition at line 4971 of file util.cpp.

4972{
4973 ASSERT(!f.is_open());
4974 bool fileOpened=false;
4975 bool writeToStdout=outFile=="-";
4976 if (writeToStdout) // write to stdout
4977 {
4978 f.basic_ios<char>::rdbuf(std::cout.rdbuf());
4979 fileOpened = true;
4980 }
4981 else // write to file
4982 {
4983 FileInfo fi(outFile.str());
4984 if (fi.exists()) // create a backup
4985 {
4986 Dir dir;
4987 FileInfo backup(fi.filePath()+".bak");
4988 if (backup.exists()) // remove existing backup
4989 dir.remove(backup.filePath());
4990 dir.rename(fi.filePath(),fi.filePath()+".bak");
4991 }
4992 f = Portable::openOutputStream(outFile);
4993 fileOpened = f.is_open();
4994 }
4995 return fileOpened;
4996}
bool rename(const std::string &orgName, const std::string &newName, bool acceptsAbsPath=true) const
Definition dir.cpp:327
std::ofstream openOutputStream(const DString &name, bool append=false)
Definition portable.cpp:681

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

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

◆ projectLogoFile()

DString projectLogoFile ( )

Definition at line 2580 of file util.cpp.

2581{
2582 DString projectLogo = Config_getString(PROJECT_LOGO);
2583 if (!projectLogo.empty())
2584 {
2585 // check for optional width= and height= specifier
2586 if (size_t wi = projectLogo.find(" width="); wi!=DString::npos) // and strip them
2587 {
2588 projectLogo = projectLogo.left(wi);
2589 }
2590 if (size_t hi = projectLogo.find(" height="); hi!=DString::npos)
2591 {
2592 projectLogo = projectLogo.left(hi);
2593 }
2594 }
2595 //printf("projectlogo='%s'\n",qPrint(projectLogo));
2596 return projectLogo;
2597}

References Config_getString, DString::empty(), DString::find(), DString::left(), and DString::npos.

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

◆ projectLogoSize()

DString projectLogoSize ( )

Definition at line 2599 of file util.cpp.

2600{
2601 DString sizeVal;
2602 DString projectLogo = Config_getString(PROJECT_LOGO);
2603 if (!projectLogo.empty())
2604 {
2605 auto extractDimension = [&projectLogo](const char *startMarker,size_t startPos,size_t endPos) -> DString
2606 {
2607 DString result = projectLogo.mid(startPos,endPos-startPos).stripWhiteSpace().quoted();
2608 if (result.length()>=2 && result.at(0)!='"' && result.at(result.length()-1)!='"')
2609 {
2610 result="\""+result+"\"";
2611 }
2612 result.prepend(startMarker);
2613 return result;
2614 };
2615 // check for optional width= and height= specifier
2616 size_t wi = projectLogo.find(" width=");
2617 size_t hi = projectLogo.find(" height=");
2618 if (wi!=DString::npos && hi!=DString::npos)
2619 {
2620 if (wi<hi) // "... width=x height=y..."
2621 {
2622 sizeVal = extractDimension(" width=", wi+7, hi) + " "
2623 + extractDimension(" height=", hi+8, projectLogo.length());
2624 }
2625 else // "... height=y width=x..."
2626 {
2627 sizeVal = extractDimension(" height=", hi+8, wi) + " "
2628 + extractDimension(" width=", wi+7, projectLogo.length());
2629 }
2630 }
2631 else if (wi!=DString::npos) // ... width=x..."
2632 {
2633 sizeVal = extractDimension(" width=", wi+7, projectLogo.length());
2634 }
2635 else if (hi!=DString::npos) // ... height=x..."
2636 {
2637 sizeVal = extractDimension(" height=", hi+8, projectLogo.length());
2638 }
2639 }
2640 //printf("projectsize='%s'\n",qPrint(sizeVal));
2641 return sizeVal;
2642}
DString quoted() const
Definition dstring.h:352

References DString::at(), Config_getString, DString::empty(), DString::find(), DString::length(), DString::mid(), DString::npos, DString::prepend(), DString::quoted(), and DString::stripWhiteSpace().

Referenced by substituteHtmlKeywords(), and substituteLatexKeywords().

◆ protectionLevelVisible()

bool protectionLevelVisible ( Protection prot)

Definition at line 4671 of file util.cpp.

4672{
4673 bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
4674 bool extractPackage = Config_getBool(EXTRACT_PACKAGE);
4675
4676 return (prot!=Protection::Private && prot!=Protection::Package) ||
4677 (prot==Protection::Private && extractPrivate) ||
4678 (prot==Protection::Package && extractPackage);
4679}

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 DString & fileName,
std::string & contents,
bool filter,
bool isSourceCode )

read a file name fileName and optionally filter and transcode it

Definition at line 4374 of file util.cpp.

4375{
4376 // try to open file
4377 FileInfo fi(fileName.str());
4378 if (!fi.exists()) return false;
4379 DString filterName = getFileFilter(fileName,isSourceCode);
4380 if (filterName.empty() || !filter)
4381 {
4382 std::ifstream f = Portable::openInputStream(fileName,true);
4383 if (!f.is_open())
4384 {
4385 err("could not open file {}\n",fileName);
4386 return false;
4387 }
4388 // read the file
4389 auto fileSize = fi.size();
4390 contents.resize(fileSize);
4391 f.read(contents.data(),fileSize);
4392 if (f.fail())
4393 {
4394 err("problems while reading file {}\n",fileName);
4395 return false;
4396 }
4397 }
4398 else
4399 {
4400 DString cmd=filterName+" \""+fileName+"\"";
4401 Debug::print(Debug::ExtCmd,0,"Executing popen(`{}`)\n",cmd);
4402 FILE *f=Portable::popen(cmd,"r");
4403 if (!f)
4404 {
4405 err("could not execute filter {}\n",filterName);
4406 return false;
4407 }
4408 const int bufSize=4096;
4409 char buf[bufSize];
4410 int numRead = 0;
4411 while ((numRead=static_cast<int>(fread(buf,1,bufSize,f)))>0)
4412 {
4413 //printf(">>>>>>>>Reading %d bytes\n",numRead);
4414 contents.append(buf,numRead);
4415 }
4417 Debug::print(Debug::FilterOutput, 0, "Filter output\n");
4418 Debug::print(Debug::FilterOutput,0,"-------------\n{}\n-------------\n",contents);
4419 }
4420
4421 if (contents.size()>=2 &&
4422 static_cast<uint8_t>(contents[0])==0xFF &&
4423 static_cast<uint8_t>(contents[1])==0xFE // Little endian BOM
4424 ) // UCS-2LE encoded file
4425 {
4426 transcodeCharacterBuffer(fileName,contents,"UCS-2LE","UTF-8");
4427 }
4428 else if (contents.size()>=2 &&
4429 static_cast<uint8_t>(contents[0])==0xFE &&
4430 static_cast<uint8_t>(contents[1])==0xFF // big endian BOM
4431 ) // UCS-2BE encoded file
4432 {
4433 transcodeCharacterBuffer(fileName,contents,"UCS-2BE","UTF-8");
4434 }
4435 else if (contents.size()>=3 &&
4436 static_cast<uint8_t>(contents[0])==0xEF &&
4437 static_cast<uint8_t>(contents[1])==0xBB &&
4438 static_cast<uint8_t>(contents[2])==0xBF
4439 ) // UTF-8 encoded file
4440 {
4441 contents.erase(0,3); // remove UTF-8 BOM: no translation needed
4442 }
4443 else // transcode according to the INPUT_ENCODING setting
4444 {
4445 // do character transcoding if needed.
4446 transcodeCharacterBuffer(fileName,contents,getEncoding(fi),"UTF-8");
4447 }
4448
4449 filterCRLF(contents);
4450 return true;
4451}
@ FilterOutput
Definition debug.h:39
@ ExtCmd
Definition debug.h:37
static void print(DebugMask mask, int prio, fmt::format_string< Args... > fmt, Args &&... args)
Definition debug.h:78
FILE * popen(const DString &name, const DString &type)
Definition portable.cpp:495
std::ifstream openInputStream(const DString &name, bool binary=false, bool openAtEnd=false)
Definition portable.cpp:692
int pclose(FILE *stream)
Definition portable.cpp:504
static void filterCRLF(std::string &contents)
Definition util.cpp:959
DString getFileFilter(const DString &name, bool isSourceCode)
Definition util.cpp:1020
static void transcodeCharacterBuffer(const DString &fileName, std::string &contents, const DString &inputEncoding, const DString &outputEncoding)
Definition util.cpp:4338
DString getEncoding(const FileInfo &fi)
Definition util.cpp:4477

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

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

◆ recursivelyAddGroupListToTitle()

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

Definition at line 3882 of file util.cpp.

3883{
3884 ModuleDef *mod = root ? findModuleDef(d) : nullptr;
3885 if (!d->partOfGroups().empty() || mod!=nullptr) // write list of group to which this definition belongs
3886 {
3887 if (root)
3888 {
3889 ol.pushGeneratorState();
3891 ol.writeString("<div class=\"ingroups\">");
3892 }
3893 bool first=true;
3894 for (const auto &gd : d->partOfGroups())
3895 {
3896 if (!first) { ol.writeString(" &#124; "); } else first=false;
3897 if (recursivelyAddGroupListToTitle(ol, gd, false))
3898 {
3899 ol.writeString(" &raquo; ");
3900 }
3901 ol.writeObjectLink(gd->getReference(),gd->getOutputFileBase(),DString(),gd->groupTitle());
3902 }
3903 if (root)
3904 {
3905 // add module as a group to the file as well
3906 if (mod)
3907 {
3908 if (!first) { ol.writeString(" &#124; "); } else first=false;
3909 ol.writeString(theTranslator->trModule(false,true)+" ");
3911 mod->displayName());
3912 }
3913 ol.writeString("</div>");
3914 ol.popGeneratorState();
3915 }
3916 return true;
3917 }
3918 return false;
3919}
virtual DString displayName(bool includeScope=true) const =0
virtual DString getReference() const =0
virtual const GroupList & partOfGroups() const =0
virtual DString getOutputFileBase() const =0
void writeObjectLink(const DString &ref, const DString &file, const DString &anchor, const DString &name)
Definition outputlist.h:435
void writeString(const DString &text)
Definition outputlist.h:407
void pushGeneratorState()
void disableAllBut(OutputType o)
void popGeneratorState()
virtual DString trModule(bool first_capital, bool singular)=0
Translator * theTranslator
Definition language.cpp:76
static ModuleDef * findModuleDef(const Definition *d)
Definition util.cpp:3853

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

Referenced by addGroupListToTitle(), and recursivelyAddGroupListToTitle().

◆ relativePathToRoot()

DString relativePathToRoot ( const DString & name)

Definition at line 2912 of file util.cpp.

2913{
2914 DString result;
2915 if (Config_getBool(CREATE_SUBDIRS))
2916 {
2917 if (name.empty())
2918 {
2919 return REL_PATH_TO_ROOT;
2920 }
2921 else if (size_t i = name.rfind('/'); i!=DString::npos)
2922 {
2923 result=REL_PATH_TO_ROOT;
2924 }
2925 }
2926 return result;
2927}
#define REL_PATH_TO_ROOT
Definition util.cpp:78

References Config_getBool, DString::empty(), DString::npos, REL_PATH_TO_ROOT, and DString::rfind().

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

◆ removeAnonymousScopes()

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

99{
100 std::string result;
101 if (str.empty()) return result;
102
103 // helper to check if the found delimiter starts with a colon
104 auto startsWithColon = [](const std::string &del)
105 {
106 for (size_t i=0;i<del.size();i++)
107 {
108 if (del[i]=='@') return false;
109 else if (del[i]==':') return true;
110 }
111 return false;
112 };
113
114 // helper to check if the found delimiter ends with a colon
115 auto endsWithColon = [](const std::string &del)
116 {
117 for (int i=static_cast<int>(del.size())-1;i>=0;i--)
118 {
119 if (del[i]=='@') return false;
120 else if (del[i]==':') return true;
121 }
122 return false;
123 };
124
125 static const reg::Ex re(R"([\s:]*@\d+[\s:]*)");
126 std::string s = str.str();
127 reg::Iterator iter(s,re);
129 size_t p=0;
130 size_t sl=s.length();
131 bool needsSeparator=false;
132 for ( ; iter!=end ; ++iter)
133 {
134 const auto &match = *iter;
135 size_t i = match.position();
136 if (i>p) // add non-matching prefix
137 {
138 if (needsSeparator) result+="::";
139 needsSeparator=false;
140 result+=s.substr(p,i-p);
141 }
142 std::string delim = match.str();
143 needsSeparator = needsSeparator || (startsWithColon(delim) && endsWithColon(delim));
144 p = match.position()+match.length();
145 }
146 if (p<sl) // add trailing remainder
147 {
148 if (needsSeparator) result+="::";
149 result+=s.substr(p);
150 }
151 return result;
152}

References DString::empty(), end(), and DString::str().

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

◆ removeRedundantWhiteSpace()

DString removeRedundantWhiteSpace ( const DString & s)

Definition at line 426 of file util.cpp.

427{
428 bool cliSupport = Config_getBool(CPP_CLI_SUPPORT);
429 bool vhdl = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
430
431 if (s.empty() || vhdl) return s;
432
433 // We use a static character array to
434 // improve the performance of this function
435 // and thread_local is needed to make it multi-thread safe
436 static THREAD_LOCAL char *growBuf = nullptr;
437 static THREAD_LOCAL size_t growBufLen = 0;
438 if (s.length()*3>growBufLen) // For input character we produce at most 3 output characters,
439 {
440 growBufLen = s.length()*3;
441 growBuf = static_cast<char *>(realloc(growBuf,growBufLen+1)); // add 1 for 0-terminator
442 }
443 if (growBuf==nullptr) return s; // should not happen, only we run out of memory
444
445 const char *src=s.data();
446 char *dst=growBuf;
447
448 size_t i=0;
449 size_t l=s.length();
450 size_t csp=0;
451 size_t vosp=0;
452 size_t vsp=0;
453 size_t osp=0;
454 char pc=0;
455 // skip leading whitespace
456 while (i<l && isspace(static_cast<uint8_t>(src[i])))
457 {
458 i++;
459 }
460 for (;i<l;i++)
461 {
462 char c=src[i];
463 char nc=i+1<l ? src[i+1] : ' ';
464
465 auto searchForKeyword = [&](const char *kw,size_t &matchLen,size_t totalLen)
466 {
467 if (matchLen<=totalLen && c==kw[matchLen] && // character matches substring kw
468 (matchLen>0 || // inside search string
469 i==0 || // if it is the first character
470 !isId(pc) // the previous may not be a digit
471 )
472 )
473 matchLen++;
474 else // reset counter
475 matchLen=0;
476 };
477 searchForKeyword(constScope, csp, 5); // keyword: const
478 searchForKeyword(volatileScope, vosp, 8); // keyword: volatile
479 searchForKeyword(virtualScope, vsp, 7); // keyword: virtual
480
481 // search for "operator"
482 if (osp<11 && (osp>=8 || c==operatorScope[osp]) && // character matches substring "operator" followed by 3 arbitrary characters
483 (osp>0 || // inside search string
484 i==0 || // if it is the first character
485 !isId(pc) // the previous may not be a digit
486 )
487 )
488 osp++;
489 else // reset counter
490 osp=0;
491
492 switch(c)
493 {
494 case '"': // quoted string
495 {
496 *dst++=c;
497 i++;
498 for (;i<l;i++) // find end of string
499 {
500 c = src[i];
501 *dst++=c;
502 if (c=='\\' && i+1<l)
503 {
504 i++;
505 c = src[i];
506 *dst++=c;
507 }
508 else if (c=='"')
509 {
510 break;
511 }
512 }
513 }
514 break;
515 case '<': // current char is a <
516 *dst++=c;
517 if (i+1<l &&
518 (isId(nc)) && // next char is an id char
519 (osp<8) // string in front is not "operator"
520 )
521 {
522 *dst++=' '; // add extra space
523 }
524 break;
525 case '>': // current char is a >
526 if (i>0 && !isspace(static_cast<uint8_t>(pc)) &&
527 (isId(pc) || pc=='*' || pc=='&' || pc=='.' || pc=='>') && // prev char is an id char or space or *&.
528 (osp<8 || (osp==8 && pc!='-')) // string in front is not "operator>" or "operator->"
529 )
530 {
531 *dst++=' '; // add extra space in front
532 }
533 *dst++=c;
534 if (i+1<l && (nc=='-' || nc=='&')) // '>-' -> '> -'
535 {
536 *dst++=' '; // add extra space after
537 }
538 break;
539 case ',': // current char is a ,
540 *dst++=c;
541 if (i>0 && !isspace(static_cast<uint8_t>(pc)) &&
542 ((i+1<l && (isId(nc) || nc=='[')) || // the [ is for attributes (see bug702170)
543 (i+2<l && nc=='$' && isId(src[i+2])) || // for PHP: ',$name' -> ', $name'
544 (i+3<l && nc=='&' && src[i+2]=='$' && isId(src[i+3])) // for PHP: ',&$name' -> ', &$name'
545 )
546 )
547 {
548 *dst++=' '; // add extra space after
549 }
550 break;
551 case '^': // CLI 'Type^name' -> 'Type^ name'
552 case '%': // CLI 'Type%name' -> 'Type% name'
553 *dst++=c;
554 if (cliSupport && i+1<l && (isId(nc) || nc=='-'))
555 {
556 *dst++=' '; // add extra space after
557 }
558 break;
559 case ')': // current char is a ) -> ')name' -> ') name'
560 *dst++=c;
561 if (i+1<l && (isId(nc) || nc=='-'))
562 {
563 *dst++=' '; // add extra space after
564 }
565 break;
566 case '*':
567 if (i>0 && pc!=' ' && pc!='\t' && pc!=':' &&
568 pc!='*' && pc!='&' && pc!='(' && pc!='/' && pc!='[' &&
569 pc!='.' && osp<9
570 )
571 // avoid splitting &&, **, .*, operator*, operator->*
572 {
573 *dst++=' ';
574 }
575 *dst++=c;
576 break;
577 case '&':
578 if (i>0 && isId(pc) && osp<9)
579 {
580 if (nc != '=')
581 // avoid splitting operator&=
582 {
583 *dst++=' ';
584 }
585 }
586 *dst++=c;
587 break;
588 case '$': // '$name' -> ' $name'
589 // 'name$name' -> 'name$name'
590 if (isId(pc))
591 {
592 *dst++=c;
593 break;
594 }
595 // else fallthrough
596 case '@': // '@name' -> ' @name'
597 case '\'': // ''name' -> '' name'
598 if (i>0 && i+1<l && pc!='=' && pc!=':' && !isspace(static_cast<uint8_t>(pc)) &&
599 isId(nc) && osp<8) // ")id" -> ") id"
600 {
601 *dst++=' ';
602 }
603 *dst++=c;
604 break;
605 case ':': // current char is a :
606 if (csp==6) // replace const::A by const ::A
607 {
608 *dst++=' ';
609 csp=0;
610 }
611 else if (vosp==9) // replace volatile::A by volatile ::A
612 {
613 *dst++=' ';
614 vosp=0;
615 }
616 else if (vsp==8) // replace virtual::A by virtual ::A
617 {
618 *dst++=' ';
619 vsp=0;
620 }
621 *dst++=c;
622 break;
623 case ' ': // fallthrough
624 case '\n': // fallthrough
625 case '\t':
626 {
627 if (g_charAroundSpace.charMap[static_cast<uint8_t>(pc)].before &&
628 g_charAroundSpace.charMap[static_cast<uint8_t>(nc)].after &&
629 !(pc==',' && nc=='.') &&
630 (osp<8 || (osp>=8 && isId(pc) && isId(nc)))
631 // e.g. 'operator >>' -> 'operator>>',
632 // 'operator "" _x' -> 'operator""_x',
633 // but not 'operator int' -> 'operatorint'
634 )
635 { // keep space
636 *dst++=' ';
637 }
638 else if ((pc=='*' || pc=='&' || pc=='.') && nc=='>')
639 {
640 *dst++=' ';
641 }
642 }
643 break;
644 default:
645 *dst++=c;
646 auto correctKeywordAllowedInsideScope = [&](char cc,size_t &matchLen,size_t totalLen) {
647 if (c==cc && matchLen==totalLen)
648 {
649 if ((i+2<l && src[i+1] == ':' && src[i+2] == ':') || // keyword::
650 ((i>matchLen && src[i-matchLen] == ':' && src[i-matchLen-1] == ':')) // ::keyword
651 ) matchLen = 0;
652 };
653 };
654 correctKeywordAllowedInsideScope('t',csp, 5); // keyword: const
655 correctKeywordAllowedInsideScope('e',vosp,8); // keyword: volatile
656 correctKeywordAllowedInsideScope('l',vsp, 7); // keyword: virtual
657
658 auto correctKeywordNotPartOfScope = [&](char cc,size_t &matchLen,size_t totalLen)
659 {
660 if (c==cc && matchLen==totalLen && i+1<l && // found matching keyword
661 !(isId(nc) || nc==')' || nc==',' || disspace(nc))
662 ) // prevent keyword ::A from being converted to keyword::A
663 {
664 *dst++=' ';
665 matchLen=0;
666 }
667 };
668 correctKeywordNotPartOfScope('t',csp, 5); // keyword: const
669 correctKeywordNotPartOfScope('e',vosp,8); // keyword: volatile
670 correctKeywordNotPartOfScope('l',vsp, 7); // keyword: virtual
671 break;
672 }
673 pc=c;
674 }
675 *dst++='\0';
676 //printf("removeRedundantWhitespace(%s)->%s\n",qPrint(s),growBuf);
677 return growBuf;
678}
#define THREAD_LOCAL
Definition doxygen.h:29
bool disspace(char c)
Definition dstring.h:62
Token literal values and constants.
Definition CharStream.h:12
CharElem charMap[256]
Definition util.cpp:420
static const char constScope[]
Definition util.cpp:379
static const char virtualScope[]
Definition util.cpp:381
static const char volatileScope[]
Definition util.cpp:380
static CharAroundSpace g_charAroundSpace
Definition util.cpp:423
static const char operatorScope[]
Definition util.cpp:382

References CharAroundSpace::CharElem::after, CharAroundSpace::CharElem::before, CharAroundSpace::charMap, Config_getBool, constScope, DString::data(), disspace(), DString::empty(), g_charAroundSpace, isId(), DString::length(), operatorScope, THREAD_LOCAL, virtualScope, and volatileScope.

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

◆ replaceAnonymousScopes()

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

Definition at line 155 of file util.cpp.

156{
157 if (s.empty()) return s;
158 static const reg::Ex marker(R"(@\d+)");
159 std::string result = reg::replace(s.str(),marker,
160 !replacement.empty() ? replacement.data() : "__anonymous__");
161 //printf("replaceAnonymousScopes('%s')='%s'\n",qPrint(s),qPrint(result));
162 return result;
163}
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:872

References DString::data(), DString::empty(), reg::replace(), and DString::str().

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

◆ replaceColorMarkers()

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

4569{
4570 if (str.empty()) return DString();
4571 std::string result;
4572 std::string s=str.str();
4573 static const reg::Ex re(R"(##[0-9A-Fa-f][0-9A-Fa-f])");
4574 reg::Iterator it(s,re);
4576 int hue = Config_getInt(HTML_COLORSTYLE_HUE);
4577 int sat = Config_getInt(HTML_COLORSTYLE_SAT);
4578 int gamma = Config_getInt(HTML_COLORSTYLE_GAMMA);
4579 size_t sl=s.length();
4580 size_t p=0;
4581 for (; it!=end ; ++it)
4582 {
4583 const auto &match = *it;
4584 size_t i = match.position();
4585 size_t l = match.length();
4586 if (i>p) result+=s.substr(p,i-p);
4587 std::string lumStr = match.str().substr(2);
4588#define HEXTONUM(x) (((x)>='0' && (x)<='9') ? ((x)-'0') : \
4589 ((x)>='a' && (x)<='f') ? ((x)-'a'+10) : \
4590 ((x)>='A' && (x)<='F') ? ((x)-'A'+10) : 0)
4591
4592 double r = 0,g = 0,b = 0;
4593 int level = HEXTONUM(lumStr[0])*16+HEXTONUM(lumStr[1]);
4594 ColoredImage::hsl2rgb(hue/360.0,sat/255.0,
4595 pow(level/255.0,gamma/100.0),&r,&g,&b);
4596 int red = static_cast<int>(r*255.0);
4597 int green = static_cast<int>(g*255.0);
4598 int blue = static_cast<int>(b*255.0);
4599 char colStr[8];
4600 colStr[0]='#';
4601 colStr[1]=hex[red>>4];
4602 colStr[2]=hex[red&0xf];
4603 colStr[3]=hex[green>>4];
4604 colStr[4]=hex[green&0xf];
4605 colStr[5]=hex[blue>>4];
4606 colStr[6]=hex[blue&0xf];
4607 colStr[7]=0;
4608 //printf("replacing %s->%s (level=%d)\n",qPrint(lumStr),colStr,level);
4609 result+=colStr;
4610 p=i+l;
4611 }
4612 if (p<sl) result+=s.substr(p);
4613 return result;
4614}
static void hsl2rgb(double h, double s, double l, double *pRed, double *pGreen, double *pBlue)
Definition image.cpp:373
#define HEXTONUM(x)

References Config_getInt, DString::empty(), end(), hex, HEXTONUM, ColoredImage::hsl2rgb(), and DString::str().

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

◆ resolveDirLink()

const DirDef * resolveDirLink ( const DString & linkRef)
static

Definition at line 2290 of file util.cpp.

2291{
2292 const DirDef *dd = Doxygen::dirLinkedMap->find(FileInfo(linkRef.str()).absFilePath()+"/");
2293 //printf("resolveDirLink(%s) -> %s\n",qPrint(linkRef),dd?qPrint(dd->name()):"<none>");
2294 if (dd==nullptr)
2295 {
2296 StringVector stripPaths = Config_getList(STRIP_FROM_PATH);
2297 for (const auto &path : stripPaths)
2298 {
2299 FileInfo fi(path+linkRef.str());
2300 //printf(" trying to strip path '%s' from linkRef '%s' fi='%s'\n",qPrint(path),qPrint(linkRef),qPrint(fi.absFilePath()));
2301 dd = Doxygen::dirLinkedMap->find(fi.absFilePath()+"/");
2302 if (dd) break;
2303 }
2304 }
2305 return dd;
2306}
A model of a directory symbol.
Definition dirdef.h:108
static DirLinkedMap * dirLinkedMap
Definition doxygen.h:120
std::string absFilePath() const
Definition fileinfo.cpp:105
const T * find(const std::string &key) const
Definition linkedmap.h:47

References FileInfo::absFilePath(), Config_getList, Doxygen::dirLinkedMap, LinkedMap< T, Hash, KeyEqual, Map >::find(), and DString::str().

Referenced by resolveLink().

◆ resolveLink()

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

Returns an symbol definition given its name and context for an explicitly linked symbol.

Postcondition
return value true implies *resContext!=0

Definition at line 2308 of file util.cpp.

2316{
2317 *resContext=nullptr;
2318
2319 DString linkRef=lr;
2320 if (lang==SrcLangExt::CSharp)
2321 {
2322 linkRef = mangleCSharpGenericName(linkRef);
2323 }
2324 DString linkRefWithoutTemplates = stripTemplateSpecifiersFromScope(linkRef,false);
2325 AUTO_TRACE("scName='{}',ref='{}'",scName,lr);
2326 const FileDef *fd = nullptr;
2327 const GroupDef *gd = nullptr;
2328 const PageDef *pd = nullptr;
2329 const ClassDef *cd = nullptr;
2330 const DirDef *dir = nullptr;
2331 const ConceptDef *cnd = nullptr;
2332 const ModuleDef *modd = nullptr;
2333 const NamespaceDef *nd = nullptr;
2334 const SectionInfo *si = nullptr;
2335 bool ambig = false;
2336 if (linkRef.empty()) // no reference name!
2337 {
2338 AUTO_TRACE_EXIT("no_ref");
2339 return false;
2340 }
2341 else if ((pd=Doxygen::pageLinkedMap->find(linkRef))) // link to a page
2342 {
2343 gd = pd->getGroupDef();
2344 if (gd)
2345 {
2346 if (!pd->name().empty()) si=SectionManager::instance().find(pd->name());
2347 *resContext=gd;
2348 if (si) resAnchor = si->label();
2349 }
2350 else
2351 {
2352 *resContext=pd;
2353 }
2354 AUTO_TRACE_EXIT("page");
2355 return true;
2356 }
2357 else if ((si=SectionManager::instance().find(prefix+linkRef)))
2358 {
2359 *resContext=si->definition();
2360 resAnchor = si->label();
2361 AUTO_TRACE_EXIT("section anchor={} def={}",resAnchor,si->definition()?si->definition()->name():"<none>");
2362 return true;
2363 }
2364 else if (!prefix.empty() && (si=SectionManager::instance().find(linkRef)))
2365 {
2366 *resContext=si->definition();
2367 resAnchor = si->label();
2368 AUTO_TRACE_EXIT("section anchor={} def={}",resAnchor,si->definition()?si->definition()->name():"<none>");
2369 return true;
2370 }
2371 else if ((pd=Doxygen::exampleLinkedMap->find(linkRef))) // link to an example
2372 {
2373 *resContext=pd;
2374 AUTO_TRACE_EXIT("example");
2375 return true;
2376 }
2377 else if ((gd=Doxygen::groupLinkedMap->find(linkRef))) // link to a group
2378 {
2379 *resContext=gd;
2380 AUTO_TRACE_EXIT("group");
2381 return true;
2382 }
2383 else if ((fd=Doxygen::inputNameLinkedMap->findFileDef(linkRef,ambig)) // file link
2384 && fd->isLinkable())
2385 {
2386 *resContext=fd;
2387 AUTO_TRACE_EXIT("file");
2388 return true;
2389 }
2390 else if ((cd=getClass(linkRef))) // class link
2391 {
2392 *resContext=cd;
2393 resAnchor=cd->anchor();
2394 AUTO_TRACE_EXIT("class");
2395 return true;
2396 }
2397 else if (lang==SrcLangExt::Java &&
2398 (cd=getClass(linkRefWithoutTemplates))) // Java generic class link
2399 {
2400 *resContext=cd;
2401 resAnchor=cd->anchor();
2402 AUTO_TRACE_EXIT("generic");
2403 return true;
2404 }
2405 else if ((cd=getClass(linkRef+"-p"))) // Obj-C protocol link
2406 {
2407 *resContext=cd;
2408 resAnchor=cd->anchor();
2409 AUTO_TRACE_EXIT("protocol");
2410 return true;
2411 }
2412 else if ((cnd=getConcept(linkRef))) // C++20 concept definition
2413 {
2414 *resContext=cnd;
2415 resAnchor=cnd->anchor();
2416 AUTO_TRACE_EXIT("concept");
2417 return true;
2418 }
2419 else if ((modd=ModuleManager::instance().modules().find(linkRef)))
2420 {
2421 *resContext=modd;
2422 resAnchor=modd->anchor();
2423 AUTO_TRACE_EXIT("module");
2424 return true;
2425 }
2426 else if ((nd=Doxygen::namespaceLinkedMap->find(linkRef)))
2427 {
2428 *resContext=nd;
2429 AUTO_TRACE_EXIT("namespace");
2430 return true;
2431 }
2432 else if ((dir=resolveDirLink(linkRef)) && dir->isLinkable())
2433 {
2434 *resContext=dir;
2435 AUTO_TRACE_EXIT("directory");
2436 return true;
2437 }
2438 else // probably a member reference
2439 {
2440 const MemberDef *md = nullptr;
2441 bool res = resolveRef(scName,lr,true,resContext,&md,lang);
2442 if (md) resAnchor=md->anchor();
2443 AUTO_TRACE_EXIT("member? res={}",res);
2444 return res;
2445 }
2446}
constexpr auto prefix
Definition anchor.cpp:47
virtual DString anchor() const =0
static FileNameLinkedMap * inputNameLinkedMap
Definition doxygen.h:97
static PageLinkedMap * exampleLinkedMap
Definition doxygen.h:91
static PageLinkedMap * pageLinkedMap
Definition doxygen.h:92
static GroupLinkedMap * groupLinkedMap
Definition doxygen.h:107
A model of a group of symbols.
Definition groupdef.h:48
A model of a page symbol.
Definition pagedef.h:27
virtual const GroupDef * getGroupDef() const =0
class that provide information about a section.
Definition section.h:58
Definition * definition() const
Definition section.h:77
DString label() const
Definition section.h:69
static SectionManager & instance()
returns a reference to the singleton
Definition section.h:179
ConceptDef * getConcept(const DString &n)
bool resolveRef(const DString &scName, const DString &name, bool inSeeBlock, const Definition **resContext, const MemberDef **resMember, SrcLangExt lang, bool lookForSpecialization, const FileDef *currentFile, bool checkScope)
Definition util.cpp:2008
static const DirDef * resolveDirLink(const DString &linkRef)
Definition util.cpp:2290
DString mangleCSharpGenericName(const DString &name)
Definition util.cpp:5319

References Definition::anchor(), AUTO_TRACE, AUTO_TRACE_EXIT, SectionInfo::definition(), DString::empty(), Doxygen::exampleLinkedMap, LinkedMap< T, Hash, KeyEqual, Map >::find(), getClass(), getConcept(), PageDef::getGroupDef(), Doxygen::groupLinkedMap, Doxygen::inputNameLinkedMap, ModuleManager::instance(), SectionManager::instance(), Definition::isLinkable(), SectionInfo::label(), mangleCSharpGenericName(), Definition::name(), Doxygen::namespaceLinkedMap, Doxygen::pageLinkedMap, prefix, resolveDirLink(), resolveRef(), and stripTemplateSpecifiersFromScope().

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

◆ resolveRef()

bool resolveRef ( const DString & scName,
const DString & name,
bool inSeeBlock,
const Definition ** resContext,
const MemberDef ** resMember,
SrcLangExt lang,
bool lookForSpecializations = true,
const FileDef * currentFile = nullptr,
bool checkScope = false )

Returns a symbol definition (compound and/or member) given its name and context.

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

Definition at line 2008 of file util.cpp.

2018{
2019 AUTO_TRACE("scope={} name={} inSeeBlock={} lang={} lookForSpecialization={} currentFile={} checkScope={}",
2020 scName,name,inSeeBlock,lang,lookForSpecialization,currentFile ? currentFile->name() : "", checkScope);
2021 //printf("resolveRef(scope=%s,name=%s,inSeeBlock=%d)\n",qPrint(scName),qPrint(name),inSeeBlock);
2022 DString tsName = name;
2023 //bool memberScopeFirst = tsName.find('#')!=-1;
2024 DString fullName = substitute(tsName,"#","::");
2025 if (fullName.find("anonymous_namespace{")==DString::npos)
2026 {
2027 fullName = removeRedundantWhiteSpace(substitute(fullName,".","::",3));
2028 }
2029 else
2030 {
2031 fullName = removeRedundantWhiteSpace(fullName);
2032 }
2033
2034 size_t templStartPos;
2035 if (lang==SrcLangExt::CSharp && (templStartPos=fullName.find('<'))!=DString::npos)
2036 {
2037 size_t templEndPos = fullName.rfind('>');
2038 if (templEndPos!=DString::npos)
2039 {
2040 fullName = mangleCSharpGenericName(fullName.left(templEndPos+1))+fullName.mid(templEndPos+1);
2041 AUTO_TRACE_ADD("C# mangled name='{}'",fullName);
2042 }
2043 }
2044
2045 size_t bracePos = findParameterList(fullName);
2046 size_t endNamePos = bracePos!=DString::npos ? bracePos : fullName.length();
2047 size_t scopePos = fullName.rfind("::",endNamePos);
2048 bool explicitScope = fullName.startsWith("::") && // ::scope or #scope
2049 ((scopePos!=DString::npos && scopePos>2) || // ::N::A
2050 tsName.startsWith("::") || // ::foo in local scope
2051 scName==nullptr // #foo in global scope
2052 );
2053 bool allowTypeOnly=false;
2054
2055 // default result values
2056 *resContext=nullptr;
2057 *resMember=nullptr;
2058
2059 if (bracePos==DString::npos) // simple name
2060 {
2061 // the following if() was commented out for releases in the range
2062 // 1.5.2 to 1.6.1, but has been restored as a result of bug report 594787.
2063 if (!inSeeBlock && scopePos==DString::npos && isLowerCase(tsName))
2064 { // link to lower case only name => do not try to autolink
2065 AUTO_TRACE_ADD("false");
2066 return false;
2067 }
2068
2069 ClassDef *cd=nullptr;
2070 NamespaceDef *nd=nullptr;
2071 ConceptDef *cnd=nullptr;
2072 ModuleDef *modd=nullptr;
2073
2074 //printf("scName=%s fullName=%s\n",qPrint(scName),qPrint(fullName));
2075
2076 // check if this is a class or namespace reference
2077 if (scName!=fullName && getScopeDefs(scName,fullName,cd,cnd,nd,modd))
2078 {
2079 //printf("found scopeDef\n");
2080 if (cd) // scope matches that of a class
2081 {
2082 *resContext = cd;
2083 }
2084 else if (cnd)
2085 {
2086 *resContext = cnd;
2087 }
2088 else if (modd)
2089 {
2090 *resContext = modd;
2091 }
2092 else // scope matches that of a namespace
2093 {
2094 ASSERT(nd!=nullptr);
2095 *resContext = nd;
2096 }
2097 AUTO_TRACE_ADD("true");
2098 return true;
2099 }
2100 else if (scName==fullName || (!inSeeBlock && scopePos==DString::npos))
2101 // nothing to link => output plain text
2102 {
2103 //printf("found scName=%s fullName=%s scName==fullName=%d "
2104 // "inSeeBlock=%d scopePos=%d!\n",
2105 // qPrint(scName),qPrint(fullName),scName==fullName,inSeeBlock,scopePos);
2106
2107 // at this point we have a bare word that is not a class or namespace
2108 // we should also allow typedefs or enums to be linked, but not for instance member
2109 // functions, otherwise 'Foo' would always link to the 'Foo()' constructor instead of the
2110 // 'Foo' class. So we use this flag as a filter.
2111 allowTypeOnly=true;
2112 }
2113
2114 // continue search...
2115 }
2116
2117 // extract userscope+name
2118 DString nameStr=fullName.left(endNamePos);
2119 if (explicitScope) nameStr=nameStr.mid(2);
2120
2121
2122 // extract arguments
2123 DString argsStr;
2124 if (bracePos!=DString::npos) argsStr=fullName.mid(bracePos);
2125
2126 // strip template specifier
2127 // TODO: match against the correct partial template instantiation
2128 size_t templPos = nameStr.find('<');
2129 bool tryUnspecializedVersion = false;
2130 if (templPos!=DString::npos && nameStr.find("operator")==DString::npos)
2131 {
2132 size_t endTemplPos=nameStr.rfind('>');
2133 if (endTemplPos!=DString::npos)
2134 {
2135 if (!lookForSpecialization)
2136 {
2137 nameStr=nameStr.left(templPos)+nameStr.mid(endTemplPos+1);
2138 }
2139 else
2140 {
2141 tryUnspecializedVersion = true;
2142 }
2143 }
2144 }
2145
2146 DString scopeStr=scName;
2147 if (!explicitScope && nameStr.length()>scopeStr.length() && leftScopeMatch(scopeStr,nameStr))
2148 {
2149 nameStr=nameStr.mid(scopeStr.length()+2);
2150 }
2151
2152 const GroupDef *gd = nullptr;
2153 const ConceptDef *cnd = nullptr;
2154 const ModuleDef *modd = nullptr;
2155
2156 // check if nameStr is a member or global.
2157 //printf("getDefs(scope=%s,name=%s,args=%s checkScope=%d)\n",
2158 // qPrint(scopeStr), qPrint(nameStr), qPrint(argsStr),checkScope);
2159 GetDefInput input(scopeStr,nameStr,argsStr);
2160 input.forceEmptyScope = explicitScope;
2161 input.currentFile = currentFile;
2162 input.checkCV = true;
2163 GetDefResult result = getDefs(input);
2164 if (result.found)
2165 {
2166 //printf("after getDefs checkScope=%d nameStr=%s\n",checkScope,qPrint(nameStr));
2167 size_t np = nameStr.find("::");
2168 if (checkScope && result.md && result.md->getOuterScope()==Doxygen::globalScope &&
2169 !result.md->isStrongEnumValue() &&
2170 (!scopeStr.empty() || (np!=DString::npos && np>0)))
2171 {
2172 // we did find a member, but it is a global one while we were explicitly
2173 // looking for a scoped variable. See bug 616387 for an example why this check is needed.
2174 // note we do need to support autolinking to "::symbol" hence the >0
2175 //printf("not global member!\n");
2176 *resContext=nullptr;
2177 *resMember=nullptr;
2178 AUTO_TRACE_ADD("false");
2179 return false;
2180 }
2181 //printf("after getDefs md=%p cd=%p fd=%p nd=%p gd=%p\n",md,cd,fd,nd,gd);
2182 if (result.md)
2183 {
2184 if (!allowTypeOnly || result.md->isTypedef() || result.md->isEnumerate())
2185 {
2186 *resMember=result.md;
2187 *resContext=result.md;
2188 }
2189 else // md is not a type, but we explicitly expect one
2190 {
2191 *resContext=nullptr;
2192 *resMember=nullptr;
2193 AUTO_TRACE_ADD("false");
2194 return false;
2195 }
2196 }
2197 else if (result.cd) *resContext=result.cd;
2198 else if (result.nd) *resContext=result.nd;
2199 else if (result.fd) *resContext=result.fd;
2200 else if (result.gd) *resContext=result.gd;
2201 else if (result.cnd) *resContext=result.cnd;
2202 else if (result.modd) *resContext=result.modd;
2203 else
2204 {
2205 *resContext=nullptr; *resMember=nullptr;
2206 AUTO_TRACE_ADD("false");
2207 return false;
2208 }
2209 //printf("member=%s (md=%p) anchor=%s linkable()=%d context=%s\n",
2210 // qPrint(md->name()), md, qPrint(md->anchor()), md->isLinkable(), qPrint((*resContext)->name()));
2211 AUTO_TRACE_ADD("true");
2212 return true;
2213 }
2214 else if (inSeeBlock && !nameStr.empty() && (gd=Doxygen::groupLinkedMap->find(nameStr)))
2215 { // group link
2216 *resContext=gd;
2217 AUTO_TRACE_ADD("true");
2218 return true;
2219 }
2220 else if ((cnd=Doxygen::conceptLinkedMap->find(nameStr)))
2221 {
2222 *resContext=cnd;
2223 AUTO_TRACE_ADD("true");
2224 return true;
2225 }
2226 else if ((modd=ModuleManager::instance().modules().find(nameStr)))
2227 {
2228 *resContext=modd;
2229 AUTO_TRACE_ADD("true");
2230 return true;
2231 }
2232 else if (tsName.find('.')!=DString::npos) // maybe a link to a file
2233 {
2234 bool ambig = false;
2235 const FileDef *fd=Doxygen::inputNameLinkedMap->findFileDef(tsName,ambig);
2236 if (fd && !ambig)
2237 {
2238 *resContext=fd;
2239 AUTO_TRACE_ADD("true");
2240 return true;
2241 }
2242 }
2243
2244 if (tryUnspecializedVersion)
2245 {
2246 bool b = resolveRef(scName,name,inSeeBlock,resContext,resMember,lang,false,nullptr,checkScope);
2247 AUTO_TRACE_ADD("{}",b);
2248 return b;
2249 }
2250 if (bracePos!=DString::npos) // Try without parameters as well, could be a constructor invocation
2251 {
2252 *resContext=getClass(fullName.left(bracePos));
2253 if (*resContext)
2254 {
2255 AUTO_TRACE_ADD("true");
2256 return true;
2257 }
2258 }
2259 //printf("resolveRef: %s not found!\n",qPrint(name));
2260
2261 AUTO_TRACE_ADD("false");
2262 return false;
2263}
virtual Definition * getOuterScope() const =0
virtual bool isStrongEnumValue() const =0
static size_t findParameterList(const DString &name)
Returns the position in the string where a function parameter list begins, or DString::npos if one is...
Definition util.cpp:684
GetDefResult getDefs(const GetDefInput &input)
Definition util.cpp:1866
static bool getScopeDefs(const DString &docScope, const DString &scope, ClassDef *&cd, ConceptDef *&cnd, NamespaceDef *&nd, ModuleDef *&modd)
Definition util.cpp:1936
static bool isLowerCase(DString &s)
Definition util.cpp:1999

References ASSERT, AUTO_TRACE, AUTO_TRACE_ADD, GetDefResult::cd, GetDefInput::checkCV, GetDefResult::cnd, Doxygen::conceptLinkedMap, GetDefInput::currentFile, DString::empty(), GetDefResult::fd, DString::find(), LinkedMap< T, Hash, KeyEqual, Map >::find(), FileNameLinkedMap::findFileDef(), findParameterList(), GetDefInput::forceEmptyScope, GetDefResult::found, GetDefResult::gd, getClass(), getDefs(), Definition::getOuterScope(), getScopeDefs(), Doxygen::globalScope, Doxygen::groupLinkedMap, Doxygen::inputNameLinkedMap, ModuleManager::instance(), MemberDef::isEnumerate(), isLowerCase(), MemberDef::isStrongEnumValue(), MemberDef::isTypedef(), DString::left(), leftScopeMatch(), DString::length(), mangleCSharpGenericName(), GetDefResult::md, DString::mid(), GetDefResult::modd, Definition::name(), GetDefResult::nd, DString::npos, removeRedundantWhiteSpace(), resolveRef(), DString::rfind(), DString::startsWith(), and substitute().

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

◆ resolveTypeDef()

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

Definition at line 232 of file util.cpp.

234{
235 AUTO_TRACE("context='{}' qualifiedName='{}'",context?context->name():"",qualifiedName);
236 DString result;
237 if (qualifiedName.empty())
238 {
239 AUTO_TRACE_EXIT("empty name");
240 return result;
241 }
242
243 const Definition *mContext=context;
244 if (typedefContext) *typedefContext=context;
245
246 // see if the qualified name has a scope part
247 if (qualifiedName.find('<')!=DString::npos)
248 {
249 AUTO_TRACE_EXIT("template");
250 return result;
251 }
252 size_t scopeIndex = qualifiedName.rfind("::");
253 DString resName=qualifiedName;
254 if (scopeIndex!=DString::npos) // strip scope part for the name
255 {
256 resName=qualifiedName.mid(scopeIndex+2);
257 if (resName.empty())
258 {
259 AUTO_TRACE_EXIT("invalid format");
260 return result;
261 }
262 }
263 const MemberDef *md=nullptr;
264 while (mContext && md==nullptr)
265 {
266 // step 1: get the right scope
267 const Definition *resScope=mContext;
268 if (scopeIndex!=DString::npos)
269 {
270 // split-off scope part
271 DString resScopeName = qualifiedName.left(scopeIndex);
272 //printf("resScopeName='%s'\n",qPrint(resScopeName));
273
274 // look-up scope in context
275 int is=0,ps=0,l=0;
276 while ((is=getScopeFragment(resScopeName,ps,&l))!=-1)
277 {
278 DString qualScopePart = resScopeName.mid(is,l);
279 DString tmp = resolveTypeDef(mContext,qualScopePart);
280 if (!tmp.empty()) qualScopePart=tmp;
281 resScope = resScope->findInnerCompound(qualScopePart);
282 //printf("qualScopePart='%s' resScope=%p\n",qPrint(qualScopePart),resScope);
283 if (resScope==nullptr) break;
284 ps=is+l;
285 }
286 }
287 AUTO_TRACE_ADD("resScope='{}' resName='{}'",resScope?resScope->name():"",resName);
288
289 // step 2: get the member
290 if (resScope) // no scope or scope found in the current context
291 {
292 //printf("scope found: %s, look for typedef %s\n",
293 // qPrint(resScope->qualifiedName()),qPrint(resName));
294 MemberNameLinkedMap *mnd=nullptr;
295 bool searchRelated=false;
296 bool mustBeRelated=false;
297 if (resScope->definitionType()==Definition::TypeClass)
298 {
300 }
301 else
302 {
304 searchRelated=true;
305 }
306 MemberName *mn=mnd->find(resName);
307 if (mn==0 && searchRelated)
308 {
310 mustBeRelated=true;
311 }
312 if (mn)
313 {
314 int minDist=-1;
315 for (const auto &tmd_p : *mn)
316 {
317 const MemberDef *tmd = tmd_p.get();
318 AUTO_TRACE_ADD("found candidate member '{}' isTypeDef={}' isRelated={} mustBeRelated={}",
319 tmd->name(),tmd->isTypedef(),tmd->isRelated(),mustBeRelated);
320 //printf("Found member %s resScope=%s outerScope=%s mContext=%p\n",
321 // qPrint(tmd->name()),qPrint( resScope->name()),
322 // qPrint(tmd->getOuterScope()->name()), mContext);
323 if (tmd->isTypedef())
324 {
325 if (resScope==Doxygen::globalScope && tmd->isRelated() && mustBeRelated)
326 {
327 md = tmd;
328 }
329 else
330 {
331 SymbolResolver resolver;
332 int dist=resolver.isAccessibleFrom(resScope,tmd);
333 if (dist!=-1 && (md==nullptr || dist<minDist))
334 {
335 md = tmd;
336 minDist = dist;
337 }
338 }
339 }
340 }
341 }
342 }
343 mContext=mContext->getOuterScope();
344 }
345
346 AUTO_TRACE_ADD("md='{}'",md?md->name():"");
347 // step 3: get the member's type
348 if (md)
349 {
350 //printf(">>resolveTypeDef: Found typedef name '%s' in scope '%s' value='%s' args='%s'\n",
351 // qPrint(qualifiedName),qPrint(context->name()),qPrint(md->typeString()),qPrint(md->argsString())
352 // );
353 result=md->typeString();
354 DString args = md->argsString();
355 if (args.find(")(")!=DString::npos) // typedef of a function/member pointer
356 {
357 result+=args;
358 }
359 else if (args.find('[')!=DString::npos) // typedef of an array
360 {
361 result+=args;
362 }
363 if (typedefContext) *typedefContext=md->getOuterScope();
364 }
365 else
366 {
367 //printf(">>resolveTypeDef: Typedef '%s' not found in scope '%s'!\n",
368 // qPrint(qualifiedName),context ? qPrint(context->name()) : "<global>");
369 }
370 AUTO_TRACE_EXIT("result='{}'",result);
371 return result;
372}
virtual const Definition * findInnerCompound(const DString &name) const =0
static MemberNameLinkedMap * functionNameLinkedMap
Definition doxygen.h:105
static MemberNameLinkedMap * memberNameLinkedMap
Definition doxygen.h:104
virtual DString argsString() const =0
virtual bool isRelated() const =0
Ordered dictionary of MemberName objects.
Definition membername.h:61
int isAccessibleFrom(const Definition *scope, const Definition *item)
Checks if symbol item is accessible from within scope.
int getScopeFragment(const DString &s, int p, int *l)
Definition util.cpp:3798

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

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

◆ rightScopeMatch()

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

Definition at line 729 of file util.cpp.

730{
731 size_t sl=scope.length();
732 size_t nl=name.length();
733 return (name==scope || // equal
734 (scope.right(nl)==name && // substring
735 sl>1+nl && scope.at(sl-nl-1)==':' && scope.at(sl-nl-2)==':' // scope
736 )
737 );
738}

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

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

◆ selectBlocks()

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

5002{
5003 if (s.empty()) return s;
5004
5005 // helper to find the end of a block
5006 auto skipBlock = [&markerInfo](const char *p,const SelectionBlock &blk)
5007 {
5008 char c = 0;
5009 while ((c=*p))
5010 {
5011 if (c==markerInfo.markerChar && dstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // end marker
5012 {
5013 size_t len = markerInfo.endLen;
5014 bool negate = *(p+markerInfo.endLen)=='!';
5015 if (negate) len++;
5016 size_t blkNameLen = dstrlen(blk.name);
5017 if (dstrncmp(p+len,blk.name,blkNameLen)==0 && // matching marker name
5018 dstrncmp(p+len+blkNameLen,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
5019 {
5020 //printf("Found end marker %s enabled=%d negate=%d\n",blk.name,blk.enabled,negate);
5021 return p+len+blkNameLen+markerInfo.closeLen;
5022 }
5023 else // not the right marker id
5024 {
5025 p++;
5026 }
5027 }
5028 else // not and end marker
5029 {
5030 p++;
5031 }
5032 }
5033 return p;
5034 };
5035
5036 DString result;
5037 result.reserve(s.length());
5038 const char *p = s.data();
5039 char c = 0;
5040 while ((c=*p))
5041 {
5042 if (c==markerInfo.markerChar) // potential start of marker
5043 {
5044 if (dstrncmp(p,markerInfo.beginStr,markerInfo.beginLen)==0) // start of begin marker
5045 {
5046 bool found = false;
5047 size_t len = markerInfo.beginLen;
5048 bool negate = *(p+len)=='!';
5049 if (negate) len++;
5050 for (const auto &blk : blockList)
5051 {
5052 size_t blkNameLen = dstrlen(blk.name);
5053 if (dstrncmp(p+len,blk.name,blkNameLen)==0 && // matching marker name
5054 dstrncmp(p+len+blkNameLen,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
5055 {
5056 bool blockEnabled = blk.enabled!=negate;
5057 //printf("Found start marker %s enabled=%d negate=%d\n",blk.name,blk.enabled,negate);
5058 p+=len+blkNameLen+markerInfo.closeLen;
5059 if (!blockEnabled) // skip until the end of the block
5060 {
5061 //printf("skipping block\n");
5062 p=skipBlock(p,blk);
5063 }
5064 found=true;
5065 break;
5066 }
5067 }
5068 if (!found) // unknown marker id
5069 {
5070 result+=c;
5071 p++;
5072 }
5073 }
5074 else if (dstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // start of end marker
5075 {
5076 bool found = false;
5077 size_t len = markerInfo.endLen;
5078 bool negate = *(p+len)=='!';
5079 if (negate) len++;
5080 for (const auto &blk : blockList)
5081 {
5082 size_t blkNameLen = dstrlen(blk.name);
5083 if (dstrncmp(p+len,blk.name,blkNameLen)==0 && // matching marker name
5084 dstrncmp(p+len+blkNameLen,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
5085 {
5086 //printf("Found end marker %s enabled=%d negate=%d\n",blk.name,blk.enabled,negate);
5087 p+=len+blkNameLen+markerInfo.closeLen;
5088 found=true;
5089 break;
5090 }
5091 }
5092 if (!found) // unknown marker id
5093 {
5094 result+=c;
5095 p++;
5096 }
5097 }
5098 else // not a start or end marker
5099 {
5100 result+=c;
5101 p++;
5102 }
5103 }
5104 else // not a marker character
5105 {
5106 result+=c;
5107 p++;
5108 }
5109 }
5110 //printf("====\n%s\n-----\n%s\n~~~~\n",qPrint(s),qPrint(result));
5111 return result;
5112}
uint32_t dstrlen(const char *str)
Returns the length of string str, or 0 if a null pointer is passed.
Definition dstring.h:39

References SelectionMarkerInfo::beginLen, SelectionMarkerInfo::beginStr, SelectionMarkerInfo::closeLen, SelectionMarkerInfo::closeStr, DString::data(), dstrlen(), dstrncmp(), DString::empty(), SelectionMarkerInfo::endLen, SelectionMarkerInfo::endStr, DString::length(), SelectionMarkerInfo::markerChar, and DString::reserve().

Referenced by substituteHtmlKeywords(), and substituteLatexKeywords().

◆ showDate()

DString showDate ( const DString & fmt)

Definition at line 2567 of file util.cpp.

2568{
2569 // get the current date and time
2570 std::tm dat{};
2571 int specFormat=0;
2572 DString specDate = "";
2573 DString err = dateTimeFromString(specDate,dat,specFormat);
2574
2575 // do the conversion
2576 int usedFormat=0;
2577 return formatDateTime(fmt,dat,usedFormat);
2578}
DString formatDateTime(const DString &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:176
DString dateTimeFromString(const DString &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:135
Definition message.h:146

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

Referenced by substituteHtmlKeywords(), and substituteLatexKeywords().

◆ stackTrace()

void stackTrace ( )

Definition at line 4310 of file util.cpp.

4311{
4312#ifdef TRACINGSUPPORT
4313 void *backtraceFrames[128];
4314 int frameCount = backtrace(backtraceFrames, 128);
4315 const size_t cmdLen = 40960;
4316 static char cmd[cmdLen];
4317 char *p = cmd;
4318 p += snprintf(p,cmdLen,"/usr/bin/atos -p %d ", (int)getpid());
4319 for (int x = 0; x < frameCount; x++)
4320 {
4321 p += snprintf(p,cmdLen,"%p ", backtraceFrames[x]);
4322 }
4323 fprintf(stderr,"========== STACKTRACE START ==============\n");
4324 if (FILE *fp = Portable::popen(cmd, "r"))
4325 {
4326 char resBuf[512];
4327 while (size_t len = fread(resBuf, 1, sizeof(resBuf), fp))
4328 {
4329 fwrite(resBuf, 1, len, stderr);
4330 }
4331 Portable::pclose(fp);
4332 }
4333 fprintf(stderr,"============ STACKTRACE END ==============\n");
4334 //fprintf(stderr,"%s\n", frameStrings[x]);
4335#endif
4336}

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

◆ stripAnonymousNamespaceScope()

DString stripAnonymousNamespaceScope ( const DString & s)

Definition at line 167 of file util.cpp.

168{
169 int i=0,p=0,l=0;
170 DString newScope;
171 int sl = static_cast<int>(s.length());
172 while ((i=getScopeFragment(s,p,&l))!=-1)
173 {
174 //printf("Scope fragment %s\n",qPrint(s.mid(i,l)));
175 if (Doxygen::namespaceLinkedMap->find(s.left(i+l))!=nullptr)
176 {
177 if (s.at(i)!='@')
178 {
179 if (!newScope.empty()) newScope+="::";
180 newScope+=s.mid(i,l);
181 }
182 }
183 else if (i<sl)
184 {
185 if (!newScope.empty()) newScope+="::";
186 newScope+=s.right(sl-i);
187 goto done;
188 }
189 p=i+l;
190 }
191done:
192 //printf("stripAnonymousNamespaceScope('%s')='%s'\n",qPrint(s),qPrint(newScope));
193 return newScope;
194}

References DString::at(), DString::empty(), getScopeFragment(), DString::left(), DString::length(), DString::mid(), Doxygen::namespaceLinkedMap, and DString::right().

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

◆ stripDeclKeywords()

DString stripDeclKeywords ( const DString & s)
static

Definition at line 1181 of file util.cpp.

1182{
1183 size_t i=s.find(" class ");
1184 if (i!=DString::npos) return s.left(i)+s.mid(i+6);
1185 i=s.find(" typename ");
1186 if (i!=DString::npos) return s.left(i)+s.mid(i+9);
1187 i=s.find(" union ");
1188 if (i!=DString::npos) return s.left(i)+s.mid(i+6);
1189 i=s.find(" struct ");
1190 if (i!=DString::npos) return s.left(i)+s.mid(i+7);
1191 return s;
1192}

References DString::find(), DString::left(), DString::mid(), and DString::npos.

Referenced by getCanonicalTypeForIdentifier().

◆ stripExtension()

◆ stripExtensionGeneral()

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

◆ stripFromIncludePath()

DString stripFromIncludePath ( const DString & path)

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

Definition at line 227 of file util.cpp.

228{
229 return stripFromPath(path,Config_getList(STRIP_FROM_INC_PATH));
230}
static DString stripFromPath(const DString &p, StringVector l)
Definition util.cpp:196

References Config_getList, and stripFromPath().

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

◆ stripFromPath() [1/2]

DString stripFromPath ( const DString & p,
StringVector l )
inlinestatic

Definition at line 196 of file util.cpp.

197{
198 // look at all the strings in the list and strip the longest match
199 DString potential;
201 size_t length = 0;
202 for (const auto &s : l)
203 {
204 DString prefix = s;
205 if (prefix.length() > length &&
206 dstricmp(path.left(prefix.length()),prefix)==0) // case insensitive compare
207 {
208 length = prefix.length();
209 potential = path.mid(prefix.length());
210 }
211 }
212 if (length>0) return potential;
213 return path;
214}
int dstricmp(const char *s1, const char *s2)
Definition dstring.cpp:444
DString removeLongPathMarker(const DString &path)
Definition portable.cpp:656

References dstricmp(), DString::left(), DString::mid(), prefix, and Portable::removeLongPathMarker().

Referenced by stripFromIncludePath(), and stripFromPath().

◆ stripFromPath() [2/2]

◆ stripIndentation()

DString stripIndentation ( const DString & s,
bool skipFirstLine )

Definition at line 4683 of file util.cpp.

4684{
4685 if (s.empty()) return s; // empty string -> we're done
4686
4687 //printf("stripIndentation:\n%s\n------\n",qPrint(s));
4688 // compute minimum indentation over all lines
4689 const char *p=s.data();
4690 char c=0;
4691 int indent=0;
4692 int minIndent=1000000; // "infinite"
4693 bool searchIndent=true;
4694 int tabSize=Config_getInt(TAB_SIZE);
4695 bool skipFirst = skipFirstLine;
4696 while ((c=*p++))
4697 {
4698 if (c=='\t') { indent+=tabSize - (indent%tabSize); }
4699 else if (c=='\n') { indent=0; searchIndent=true; skipFirst=false; }
4700 else if (c==' ') { indent++; }
4701 else if (searchIndent && !skipFirst)
4702 {
4703 searchIndent=false;
4704 if (indent<minIndent) minIndent=indent;
4705 }
4706 }
4707
4708 // no indent to remove -> we're done
4709 if (minIndent==0) return substitute(s,"@ilinebr","\\ilinebr");
4710
4711 // remove minimum indentation for each line
4712 TextStream result;
4713 p=s.data();
4714 indent=0;
4715 skipFirst=skipFirstLine;
4716 while ((c=*p++))
4717 {
4718 if (c=='\n') // start of new line
4719 {
4720 indent=0;
4721 result << c;
4722 skipFirst=false;
4723 }
4724 else if (indent<minIndent && !skipFirst) // skip until we reach minIndent
4725 {
4726 if (c=='\t')
4727 {
4728 int newIndent = indent+tabSize-(indent%tabSize);
4729 int i=newIndent;
4730 while (i>minIndent) // if a tab crosses the minIndent boundary fill the rest with spaces
4731 {
4732 result << ' ';
4733 i--;
4734 }
4735 indent=newIndent;
4736 }
4737 else // space
4738 {
4739 indent++;
4740 }
4741 }
4742 else if (c=='\\' && literal_at(p,"ilinebr "))
4743 // we also need to remove the indentation after a \ilinebr command at the end of a line
4744 {
4745 result << "\\ilinebr ";
4746 p+=8;
4747 int skipAmount=0;
4748 for (int j=0;j<minIndent;j++) if (*(p+j)==' ') skipAmount++; // test to see if we have the indent
4749 if (skipAmount==minIndent)
4750 {
4751 p+=skipAmount; // remove the indent
4752 }
4753 }
4754 else if (c=='@' && literal_at(p,"ilinebr"))
4755 {
4756 result << "\\ilinebr";
4757 p+=7;
4758 }
4759 else // copy anything until the end of the line
4760 {
4761 result << c;
4762 }
4763 }
4764
4765 //printf("stripIndentation: result=\n%s\n------\n",qPrint(result.str()));
4766
4767 return result.str();
4768}
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:232

References Config_getInt, DString::data(), DString::empty(), literal_at(), TextStream::str(), and substitute().

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

◆ stripIndentationVerbatim()

void stripIndentationVerbatim ( DString & doc,
size_t indentationLevel,
bool skipFirstLine )

Definition at line 4772 of file util.cpp.

4773{
4774 //printf("stripIndentationVerbatim(level=%d):\n%s\n------\n",indentationLevel,qPrint(doc));
4775 if (indentationLevel <= 0 || doc.empty()) return; // nothing to strip
4776
4777 // by stripping content the string will only become shorter so we write the results
4778 // back into the input string and then resize it at the end.
4779 char c = 0;
4780 const char *src = doc.data();
4781 char *dst = doc.rawData();
4782 bool insideIndent = !skipFirstLine; // skip the initial line from stripping
4783 size_t cnt = 0;
4784 if (!skipFirstLine) cnt = indentationLevel;
4785 while ((c=*src++))
4786 {
4787 // invariant: dst<=src
4788 switch(c)
4789 {
4790 case '\n':
4791 *dst++ = c;
4792 insideIndent = true;
4793 cnt = indentationLevel;
4794 break;
4795 case ' ':
4796 if (insideIndent)
4797 {
4798 if (cnt>0) // count down the spacing until the end of the indent
4799 {
4800 cnt--;
4801 }
4802 else // reached the end of the indent, start of the part of the line to keep
4803 {
4804 insideIndent = false;
4805 *dst++ = c;
4806 }
4807 }
4808 else // part after indent, copy to the output
4809 {
4810 *dst++ = c;
4811 }
4812 break;
4813 default:
4814 insideIndent = false;
4815 *dst++ = c;
4816 break;
4817 }
4818 }
4819 doc.resize(static_cast<uint32_t>(dst-doc.data()));
4820 //printf("stripIndentationVerbatim: result=\n%s\n------\n",qPrint(doc));
4821}
void resize(size_t newlen)
Definition dstring.h:209
char * rawData()
Returns a writable pointer to the data.
Definition dstring.h:166

References DString::data(), DString::empty(), DString::rawData(), and DString::resize().

Referenced by MemberDefImpl::setInitializer().

◆ stripIrrelevantConstVolatile()

void stripIrrelevantConstVolatile ( DString & 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 1171 of file util.cpp.

1172{
1173 //printf("stripIrrelevantConstVolatile(%s)=",qPrint(s));
1174 stripIrrelevantString(s,"const",insideTemplate);
1175 stripIrrelevantString(s,"volatile",insideTemplate);
1176 stripIrrelevantString(s,"final",insideTemplate);
1177 //printf("%s\n",qPrint(s));
1178}
static void stripIrrelevantString(DString &target, const DString &str, bool insideTemplate)
Definition util.cpp:1111

References stripIrrelevantString().

Referenced by extractCanonicalType(), and matchArgument2().

◆ stripIrrelevantString()

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

Definition at line 1111 of file util.cpp.

1112{
1113 AUTO_TRACE("target='{}' str='{}'",target,str);
1114 if (target==str) { target.clear(); return; }
1115 size_t i=0,p=0;
1116 size_t l=str.length();
1117 bool changed=false;
1118 int sharpCount=0;
1119 while ((i=target.find(str,p))!=DString::npos)
1120 {
1121 for (size_t q=p;q<i;q++)
1122 {
1123 if (target[q]=='<') sharpCount++;
1124 else if (target[q]=='>' && sharpCount>0) sharpCount--;
1125 }
1126 bool isMatch = (i==0 || !isId(target.at(i-1))) && // not a character before str
1127 (i+l==target.length() || !isId(target.at(i+l))) && // not a character after str
1128 !insideTemplate && sharpCount==0; // not inside template, because e.g. <const A> is different than <A>, see issue #11663
1129 if (isMatch)
1130 {
1131 size_t i1=target.find('*',i+l);
1132 size_t i2=target.find('&',i+l);
1133 if (i1==DString::npos && i2==DString::npos)
1134 {
1135 // strip str from target at index i
1136 target=target.left(i)+target.mid(i+l);
1137 changed=true;
1138 i-=l;
1139 }
1140 else if ((i1!=DString::npos && i<i1) || (i2!=DString::npos && i<i2)) // str before * or &
1141 {
1142 // move str to front
1143 target=str+" "+target.left(i)+target.mid(i+l);
1144 changed=true;
1145 i++;
1146 }
1147 }
1148 p = i+l;
1149 }
1150 if (changed) target=target.stripWhiteSpace();
1151 AUTO_TRACE_EXIT("target='{}'",target,str);
1152}

References DString::at(), AUTO_TRACE, AUTO_TRACE_EXIT, DString::clear(), DString::find(), isId(), DString::left(), DString::length(), DString::mid(), DString::npos, and DString::stripWhiteSpace().

Referenced by stripIrrelevantConstVolatile().

◆ stripLeadingAndTrailingEmptyLines()

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

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

3988{
3989 if (s.empty()) return DString();
3990 const char *p = s.data();
3991
3992 // search for leading empty lines
3993 int i=0,li=-1,l=static_cast<int>(s.length());
3994 char c = 0;
3995 while ((c=*p))
3996 {
3997 if (c==' ' || c=='\t' || c=='\r') { i++; p++; }
3998 else if (c=='\\' && literal_at(p,"\\ilinebr")) { i+=8; li=i; p+=8; }
3999 else if (c=='\n') { i++; li=i; docLine++; p++; }
4000 else break;
4001 }
4002
4003 // search for trailing empty lines
4004 int b=l-1,bi=-1;
4005 p=s.data()+b;
4006 while (b>=0)
4007 {
4008 c=*p;
4009 if (c==' ' || c=='\t' || c=='\r') { b--; p--; }
4010 else if (c=='r' && b>=7 && literal_at(p-7,"\\ilinebr")) { bi=b-7; b-=8; p-=8; }
4011 else if (c=='>' && b>=11 && literal_at(p-11,"\\ilinebr<br>")) { bi=b-11; b-=12; p-=12; }
4012 else if (c=='\n') { bi=b; b--; p--; }
4013 else break;
4014 }
4015
4016 // return whole string if no leading or trailing lines where found
4017 if (li==-1 && bi==-1) return s;
4018
4019 // return substring
4020 if (bi==-1) bi=l;
4021 if (li==-1) li=0;
4022 if (bi<=li) return DString(); // only empty lines
4023 //printf("docLine='%s' len=%d li=%d bi=%d\n",qPrint(s),s.length(),li,bi);
4024 return s.mid(li,bi-li);
4025}

References DString::data(), DString::empty(), DString::length(), literal_at(), and DString::mid().

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

◆ stripPath()

DString stripPath ( const DString & s)

Definition at line 3960 of file util.cpp.

3961{
3962 DString result=s;
3963 if (size_t i=result.rfind('/'); i!=DString::npos)
3964 {
3965 result=result.mid(i+1);
3966 }
3967 if (size_t i=result.rfind('\\'); i!=DString::npos)
3968 {
3969 result=result.mid(i+1);
3970 }
3971 return result;
3972}

References DString::mid(), DString::npos, and DString::rfind().

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

◆ stripScope()

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

3110{
3111 DString result = name;
3112 int l = static_cast<int>(result.length());
3113 int p = 0;
3114 bool done = false;
3115 bool skipBracket=false; // if brackets do not match properly, ignore them altogether
3116 int count=0;
3117 int round=0;
3118
3119 do
3120 {
3121 p=l-1; // start at the end of the string
3122 while (p>=0 && count>=0)
3123 {
3124 char c=result.at(p);
3125 switch (c)
3126 {
3127 case ':':
3128 // only exit in the case of ::
3129 //printf("stripScope(%s)=%s\n",name,qPrint(result.right(l-p-1)));
3130 if (p>0 && result.at(p-1)==':' && (count==0 || skipBracket))
3131 {
3132 return result.right(l-p-1);
3133 }
3134 p--;
3135 break;
3136 case '>':
3137 if (skipBracket) // we don't care about brackets
3138 {
3139 p--;
3140 }
3141 else // count open/close brackets
3142 {
3143 if (p>0 && result.at(p-1)=='>') // skip >> operator
3144 {
3145 p-=2;
3146 break;
3147 }
3148 count=1;
3149 //printf("pos < = %d\n",p);
3150 p--;
3151 bool foundMatch=false;
3152 while (p>=0 && !foundMatch)
3153 {
3154 c=result.at(p--);
3155 switch (c)
3156 {
3157 case ')':
3158 round++;
3159 break;
3160 case '(':
3161 round--;
3162 break;
3163 case '>': // ignore > inside (...) to support e.g. (sizeof(T)>0) inside template parameters
3164 if (round==0) count++;
3165 break;
3166 case '<':
3167 if (round==0)
3168 {
3169 if (p>0)
3170 {
3171 if (result.at(p-1) == '<') // skip << operator
3172 {
3173 p--;
3174 break;
3175 }
3176 }
3177 count--;
3178 foundMatch = count==0;
3179 }
3180 break;
3181 default:
3182 //printf("c=%c count=%d\n",c,count);
3183 break;
3184 }
3185 }
3186 }
3187 //printf("pos > = %d\n",p+1);
3188 break;
3189 default:
3190 p--;
3191 }
3192 }
3193 done = count==0 || skipBracket; // reparse if brackets do not match
3194 skipBracket=true;
3195 }
3196 while (!done); // if < > unbalanced repeat ignoring them
3197 //printf("stripScope(%s)=%s\n",name,name);
3198 return name;
3199}

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

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

◆ stripTemplateSpecifiersFromScope()

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

3691{
3692 //printf("stripTemplateSpecifiersFromScope(name=%s,scopeName=%s)\n",qPrint(fullName),qPrint(scopeName));
3693 size_t i=fullName.find('<');
3694 if (i==DString::npos) return fullName;
3695 DString result;
3696 size_t p=0;
3697 size_t l=fullName.length();
3698 while (i!=DString::npos)
3699 {
3700 //printf("1:result+=%s\n",qPrint(fullName.mid(p,i-p)));
3701 size_t e=i+1;
3702 int count=1;
3703 int round=0;
3704 while (e<l && count>0)
3705 {
3706 char c=fullName.at(e++);
3707 switch (c)
3708 {
3709 case '(': round++; break;
3710 case ')': if (round>0) round--; break;
3711 case '<': if (round==0) count++; break;
3712 case '>': if (round==0) count--; break;
3713 default:
3714 break;
3715 }
3716 }
3717 size_t si = fullName.find("::",e);
3718
3719 if (parentOnly && si==DString::npos) break;
3720 // we only do the parent scope, so we stop here if needed
3721
3722 result+=fullName.mid(p,i-p);
3723 //printf(" trying %s\n",qPrint(mergeScopes(scopeName,result+fullName.mid(i,e-i))));
3724 ClassDef *cd = getClass(mergeScopes(scopeName,result+fullName.mid(i,e-i)));
3725 if (cd!=nullptr && (allowArtificial || !cd->isArtificial()))
3726 {
3727 result+=fullName.mid(i,e-i);
3728 //printf(" 2:result+=%s\n",qPrint(fullName.mid(i,e-i-1)));
3729 }
3730 else if (pLastScopeStripped)
3731 {
3732 //printf(" last stripped scope '%s'\n",qPrint(fullName.mid(i,e-i)));
3733 *pLastScopeStripped=fullName.mid(i,e-i);
3734 }
3735 p=e;
3736 i=fullName.find('<',p);
3737 }
3738 result+=fullName.right(l-p);
3739 //printf("3:result+=%s\n",qPrint(fullName.right(l-p)));
3740 //printf("end result=%s\n",qPrint(result));
3741 return result;
3742}
virtual bool isArtificial() const =0
DString mergeScopes(const DString &leftScope, const DString &rightScope)
Definition util.cpp:3753

References DString::at(), DString::find(), getClass(), Definition::isArtificial(), DString::length(), mergeScopes(), DString::mid(), DString::npos, and DString::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()

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

Definition at line 2494 of file util.cpp.

2495{
2496 std::string substRes;
2497 int line = 1;
2498 const char *p = s.data();
2499 if (p)
2500 {
2501 // reserve some room for expansion
2502 substRes.reserve(s.length()+1024);
2503 char c = 0;
2504 while ((c=*p))
2505 {
2506 bool found = false;
2507 if (c=='$')
2508 {
2509 for (const auto &kw : keywords)
2510 {
2511 size_t keyLen = dstrlen(kw.keyword);
2512 if (dstrncmp(p,kw.keyword,keyLen)==0)
2513 {
2514 const char *startArg = p+keyLen;
2515 bool expectParam = std::holds_alternative<KeywordSubstitution::GetValueWithParam>(kw.getValueVariant);
2516 //printf("%s: expectParam=%d *startArg=%c\n",kw.keyword,expectParam,*startArg);
2517 if (expectParam && *startArg=='(') // $key(value)
2518 {
2519 size_t j=1;
2520 const char *endArg = nullptr;
2521 while ((c=*(startArg+j)) && c!=')' && c!='\n' && c!=0) j++;
2522 if (c==')') endArg=startArg+j;
2523 if (endArg)
2524 {
2525 DString value = DString(startArg+1).left(endArg-startArg-1);
2526 auto &&getValue = std::get<KeywordSubstitution::GetValueWithParam>(kw.getValueVariant);
2527 substRes+=getValue(value).str();
2528 p=endArg+1;
2529 //printf("found '%s'->'%s'\n",kw.keyword,qPrint(getValue(value)));
2530 }
2531 else
2532 {
2533 //printf("missing argument\n");
2534 warn(file,line,"Missing argument for '{}'",kw.keyword);
2535 p+=keyLen;
2536 }
2537 }
2538 else if (!expectParam) // $key
2539 {
2540 auto &&getValue = std::get<KeywordSubstitution::GetValue>(kw.getValueVariant);
2541 substRes+=getValue().str();
2542 //printf("found '%s'->'%s'\n",kw.keyword,qPrint(getValue()));
2543 p+=keyLen;
2544 }
2545 else
2546 {
2547 //printf("%s %d Expected arguments, none specified '%s'\n",qPrint(file), line, qPrint(kw.keyword));
2548 warn(file,line,"Expected arguments for '{}' but none were specified",kw.keyword);
2549 p+=keyLen;
2550 }
2551 found = true;
2552 break;
2553 }
2554 }
2555 }
2556 if (!found) // copy
2557 {
2558 if (c=='\n') line++;
2559 substRes+=c;
2560 p++;
2561 }
2562 }
2563 }
2564 return substRes;
2565}

References DString::data(), dstrlen(), dstrncmp(), DString::left(), DString::length(), and warn.

Referenced by substituteHtmlKeywords(), and substituteLatexKeywords().

◆ substituteTemplateArgumentsInString()

DString substituteTemplateArgumentsInString ( const DString & name,
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 3524 of file util.cpp.

3528{
3529 AUTO_TRACE("name={} formalArgs={} actualArgs={}",nm,argListToString(formalArgs),actualArgs ? argListToString(*actualArgs) : DString());
3530 if (formalArgs.empty()) return nm;
3531 DString result;
3532
3533 static const reg::Ex re(R"(\a\w*)");
3534 std::string name = nm.str();
3535 reg::Iterator it(name,re);
3537 size_t p=0;
3538
3539 for (; it!=end ; ++it)
3540 {
3541 const auto &match = *it;
3542 size_t i = match.position();
3543 size_t l = match.length();
3544 if (i>p) result += name.substr(p,i-p);
3545 DString n(match.str());
3547 if (actualArgs)
3548 {
3549 actIt = actualArgs->begin();
3550 }
3551 //printf(": name=%s\n",qPrint(name));
3552
3553 // if n is a template argument, then we substitute it
3554 // for its template instance argument.
3555 bool found=false;
3556 for (auto formIt = formalArgs.begin();
3557 formIt!=formalArgs.end() && !found;
3558 ++formIt
3559 )
3560 {
3561 Argument formArg = *formIt;
3562 Argument actArg;
3563 if (actualArgs && actIt!=actualArgs->end())
3564 {
3565 actArg = *actIt;
3566 }
3567 if (formArg.type.startsWith("class ") && formArg.name.empty())
3568 {
3569 formArg.name = formArg.type.mid(6);
3570 formArg.type = "class";
3571 }
3572 else if (formArg.type.startsWith("typename ") && formArg.name.empty())
3573 {
3574 formArg.name = formArg.type.mid(9);
3575 formArg.type = "typename";
3576 }
3577 else if (formArg.type.startsWith("class...")) // match 'class... name' to 'name...'
3578 {
3579 formArg.name += "...";
3580 formArg.type = formArg.type.left(5)+formArg.type.mid(8);
3581 }
3582 else if (formArg.type.startsWith("typename...")) // match 'typename... name' to 'name...'
3583 {
3584 formArg.name += "...";
3585 formArg.type = formArg.type.left(8)+formArg.type.mid(11);
3586 }
3587 //printf(": n=%s formArg->type='%s' formArg->name='%s' formArg->defval='%s' actArg->type='%s' actArg->name='%s' \n",
3588 // qPrint(n),qPrint(formArg.type),qPrint(formArg.name),qPrint(formArg.defval),qPrint(actArg.type),qPrint(actArg.name));
3589 if (formArg.type=="class" || formArg.type=="typename" || formArg.type.startsWith("template"))
3590 {
3591 if (formArg.name==n && actualArgs && actIt!=actualArgs->end() && !actArg.type.empty()) // base class is a template argument
3592 {
3593 static constexpr auto hasRecursion = [](const DString &prefix,const DString &nameArg,const DString &subst) -> bool
3594 {
3595 size_t ii=0;
3596 size_t pp=0;
3597
3598 ii = subst.find('<');
3599 //printf("prefix='%s' subst='%s'\n",qPrint(prefix.mid(prefix.length()-ii-2,ii+1)),qPrint(subst.left(ii+1)));
3600 if (ii!=DString::npos && prefix.length()>=ii+2 && prefix.mid(prefix.length()-ii-2,ii+1)==subst.left(ii+1))
3601 {
3602 return true; // don't replace 'A< ' with 'A< A<...', see issue #10951
3603 }
3604
3605 while ((ii=subst.find(nameArg,pp))!=DString::npos)
3606 {
3607 bool beforeNonWord = ii==0 || !isId(subst.at(ii-1));
3608 bool afterNonWord = subst.length()==ii+nameArg.length() || !isId(subst.at(ii+nameArg.length()));
3609 if (beforeNonWord && afterNonWord)
3610 {
3611 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
3612 }
3613 pp=ii+nameArg.length();
3614 }
3615 return false;
3616 };
3617 // replace formal argument with the actual argument of the instance
3618 AUTO_TRACE_ADD("result={} n={} type={} hasRecursion={}",result,n,actArg.type,hasRecursion(result,n,actArg.type));
3619 if (!hasRecursion(result,n,actArg.type))
3620 // the scope guard is to prevent recursive lockup for
3621 // template<class A> class C : public<A::T>,
3622 // where A::T would become A::T::T here,
3623 // since n==A and actArg->type==A::T
3624 // see bug595833 for an example
3625 //
3626 // Also prevent recursive substitution if n is part of actArg.type, i.e.
3627 // n='A' in argType='S< A >' would produce 'S< S< A > >'
3628 {
3629 if (actArg.name.empty())
3630 {
3631 result += actArg.type;
3632 }
3633 else
3634 // for case where the actual arg is something like "unsigned int"
3635 // the "int" part is in actArg->name.
3636 {
3637 result += actArg.type+" "+actArg.name;
3638 }
3639 found=true;
3640 }
3641 }
3642 else if (formArg.name==n &&
3643 (actualArgs==nullptr || actIt==actualArgs->end()) &&
3644 !formArg.defval.empty() &&
3645 formArg.defval!=nm /* to prevent recursion */
3646 )
3647 {
3648 result += substituteTemplateArgumentsInString(formArg.defval,formalArgs,actualArgs);
3649 found=true;
3650 }
3651 }
3652 else if (formArg.name==n &&
3653 (actualArgs==nullptr || actIt==actualArgs->end()) &&
3654 !formArg.defval.empty() &&
3655 formArg.defval!=nm /* to prevent recursion */
3656 )
3657 {
3658 result += substituteTemplateArgumentsInString(formArg.defval,formalArgs,actualArgs);
3659 found=true;
3660 }
3661 if (actualArgs && actIt!=actualArgs->end())
3662 {
3663 actIt++;
3664 }
3665 }
3666 if (!found)
3667 {
3668 result += n;
3669 }
3670 p=i+l;
3671 }
3672 result+=name.substr(p);
3673 result=result.simplifyWhiteSpace();
3674 AUTO_TRACE_EXIT("result={}",result);
3675 return result.stripWhiteSpace();
3676}
typename Vec::const_iterator const_iterator
Definition arguments.h:70
DString simplifyWhiteSpace() const
return a copy of this string with leading and trailing whitespace removed and multiple internal white...
Definition dstring.cpp:127
DString substituteTemplateArgumentsInString(const DString &nm, const ArgumentList &formalArgs, const ArgumentList *actualArgs)
Definition util.cpp:3524

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

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

◆ tempArgListToString()

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

Returns a string representation of the template parameter list al. The lang parameter is used to determine the correct syntax for the template parameters. If includeDefaults is true then default values are included in the string representation.

Definition at line 903 of file util.cpp.

904{
905 DString result;
906 if (al.empty()) return result;
907 result="<";
908 bool first=true;
909 for (const auto &a : al)
910 {
911 if (a.defval.empty() || includeDefault)
912 {
913 if (!first) result+=", ";
914 if (!a.name.empty()) // add template argument name
915 {
916 if (lang==SrcLangExt::Java || lang==SrcLangExt::CSharp)
917 {
918 result+=a.type+" ";
919 }
920 result+=a.name;
921 }
922 else // extract name from type
923 {
924 int i = static_cast<int>(a.type.length())-1;
925 while (i>=0 && isId(a.type.at(i))) i--;
926 if (i>0)
927 {
928 result+=a.type.right(a.type.length()-i-1);
929 if (a.type.find("...")!=DString::npos)
930 {
931 result+="...";
932 }
933 }
934 else // nothing found -> take whole name
935 {
936 result+=a.type;
937 }
938 }
939 if (!a.typeConstraint.empty() && lang==SrcLangExt::Java)
940 {
941 result+=" extends "; // TODO: now Java specific, C# has where...
942 result+=a.typeConstraint;
943 }
944 first=false;
945 }
946 }
947 result+=">";
948 return removeRedundantWhiteSpace(result);
949}

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

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

◆ transcodeCharacterBuffer()

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

Definition at line 4338 of file util.cpp.

4340{
4341 if (inputEncoding.empty() || outputEncoding.empty()) return; // no encoding specified
4342 if (dstricmp(inputEncoding,outputEncoding)==0) return; // input encoding same as output encoding
4343 void *cd = portable_iconv_open(outputEncoding.data(),inputEncoding.data());
4344 if (cd==reinterpret_cast<void *>(-1))
4345 {
4346 term("unsupported character conversion: '{}'->'{}': {}\n"
4347 "Check the INPUT_ENCODING setting in the config file!\n",
4348 inputEncoding,outputEncoding,strerror(errno));
4349 }
4350 size_t iLeft = contents.size();
4351 const char *srcPtr = contents.data();
4352 size_t tmpBufSize = contents.size()*4+1;
4353 size_t oLeft = tmpBufSize;
4354 std::string tmpBuf;
4355 tmpBuf.resize(tmpBufSize);
4356 char *dstPtr = tmpBuf.data();
4357 size_t newSize=0;
4358 if (!portable_iconv(cd, &srcPtr, &iLeft, &dstPtr, &oLeft))
4359 {
4360 newSize = tmpBufSize-oLeft;
4361 tmpBuf.resize(newSize);
4362 std::swap(contents,tmpBuf);
4363 //printf("iconv: input size=%d output size=%d\n[%s]\n",size,newSize,qPrint(srcBuf));
4364 }
4365 else
4366 {
4367 term("{}: failed to translate characters from {} to {}: check INPUT_ENCODING\n",
4368 fileName,inputEncoding,outputEncoding);
4369 }
4371}
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 DString::data(), dstricmp(), DString::empty(), portable_iconv(), portable_iconv_close(), portable_iconv_open(), and term.

Referenced by readInputFile().

◆ trimBaseClassScope()

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

Definition at line 1090 of file util.cpp.

1091{
1092 //printf("trimBaseClassScope level=%d '%s'\n",level,qPrint(s));
1093 for (const auto &bcd : bcl)
1094 {
1095 ClassDef *cd=bcd.classDef;
1096 //printf("Trying class %s\n",qPrint(cd->name()));
1097 if (size_t spos=s.find(cd->name()+"::"); spos!=DString::npos)
1098 {
1099 s = s.left(spos)+s.right(
1100 s.length()-spos-cd->name().length()-2
1101 );
1102 }
1103 //printf("base class '%s'\n",qPrint(cd->name()));
1104 if (!cd->baseClasses().empty())
1105 {
1106 trimBaseClassScope(cd->baseClasses(),s,level+1);
1107 }
1108 }
1109}
virtual const BaseClassList & baseClasses() const =0
Returns the list of base classes from which this class directly inherits.
void trimBaseClassScope(const BaseClassList &bcl, DString &s, int level=0)
Definition util.cpp:1090

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

Referenced by trimBaseClassScope().

◆ unescapeCharsInString()

DString unescapeCharsInString ( const DString & s)

Definition at line 2775 of file util.cpp.

2776{
2777 if (s.empty()) return s;
2778 bool caseSenseNames = useCaseSenseNames();
2779 DString result;
2780 result.reserve(s.length());
2781 const char *p = s.data();
2782 if (p)
2783 {
2784 char c = 0;
2785 while ((c=*p++))
2786 {
2787 if (c=='_') // 2 or 3 character escape
2788 {
2789 switch (*p)
2790 {
2791 case '_': result+=c; p++; break; // __ -> '_'
2792 case '1': result+=':'; p++; break; // _1 -> ':'
2793 case '2': result+='/'; p++; break; // _2 -> '/'
2794 case '3': result+='<'; p++; break; // _3 -> '<'
2795 case '4': result+='>'; p++; break; // _4 -> '>'
2796 case '5': result+='*'; p++; break; // _5 -> '*'
2797 case '6': result+='&'; p++; break; // _6 -> '&'
2798 case '7': result+='|'; p++; break; // _7 -> '|'
2799 case '8': result+='.'; p++; break; // _8 -> '.'
2800 case '9': result+='!'; p++; break; // _9 -> '!'
2801 case '0': // 3 character escape
2802 switch (*(p+1))
2803 {
2804 case '0': result+=','; p+=2; break; // _00 -> ','
2805 case '1': result+=' '; p+=2; break; // _01 -> ' '
2806 case '2': result+='{'; p+=2; break; // _02 -> '{'
2807 case '3': result+='}'; p+=2; break; // _03 -> '}'
2808 case '4': result+='?'; p+=2; break; // _04 -> '?'
2809 case '5': result+='^'; p+=2; break; // _05 -> '^'
2810 case '6': result+='%'; p+=2; break; // _06 -> '%'
2811 case '7': result+='('; p+=2; break; // _07 -> '('
2812 case '8': result+=')'; p+=2; break; // _08 -> ')'
2813 case '9': result+='+'; p+=2; break; // _09 -> '+'
2814 case 'a': result+='='; p+=2; break; // _0a -> '='
2815 case 'b': result+='$'; p+=2; break; // _0b -> '$'
2816 case 'c': result+='\\'; p+=2; break;// _0c -> '\'
2817 case 'd': result+='@'; p+=2; break; // _0d -> '@'
2818 case 'e': result+=']'; p+=2; break; // _0e -> ']'
2819 case 'f': result+='['; p+=2; break; // _0f -> '['
2820 case 'g': result+='#'; p+=2; break; // _0g -> '#'
2821 case 'h': result+='"'; p+=2; break; // _0h -> '"'
2822 case 'i': result+='~'; p+=2; break; // _0i -> '~'
2823 case 'j': result+='\''; p+=2; break;// _0j -> '\'
2824 case 'k': result+=';'; p+=2; break; // _0k -> ';'
2825 case 'l': result+='`'; p+=2; break; // _0l -> '`'
2826 default: // unknown escape, just pass underscore character as-is
2827 result+=c;
2828 break;
2829 }
2830 break;
2831 default:
2832 if (!caseSenseNames && c>='a' && c<='z') // lower to upper case escape, _a -> 'A'
2833 {
2834 result+=static_cast<char>(toupper(*p));
2835 p++;
2836 }
2837 else // unknown escape, pass underscore character as-is
2838 {
2839 result+=c;
2840 }
2841 break;
2842 }
2843 }
2844 else // normal character; pass as is
2845 {
2846 result+=c;
2847 }
2848 }
2849 }
2850 return result;
2851}

References DString::data(), DString::empty(), DString::length(), DString::reserve(), and useCaseSenseNames().

◆ updateLanguageMapping()

bool updateLanguageMapping ( const DString & extension,
const DString & language )

Definition at line 4063 of file util.cpp.

4064{
4065 DString langName = language.lower();
4066 auto it1 = std::find_if(g_lang2extMap.begin(),g_lang2extMap.end(),
4067 [&langName](const auto &info) { return info.langName==langName; });
4068 if (it1 == g_lang2extMap.end()) return false;
4069
4070 // found the language
4071 SrcLangExt parserId = it1->parserId;
4072 DString extName = extension.lower();
4073 if (extName.empty()) return false;
4074 if (extName.at(0)!='.') extName.prepend(".");
4075 auto it2 = g_extLookup.find(extName.str());
4076 if (it2!=g_extLookup.end())
4077 {
4078 g_extLookup.erase(it2); // language was already register for this ext
4079 }
4080 //printf("registering extension %s\n",qPrint(extName));
4081 g_extLookup.emplace(extName.str(),parserId);
4082 if (!Doxygen::parserManager->registerExtension(extName,it1->parserName))
4083 {
4084 err("Failed to assign extension {} to parser {} for language {}\n",
4085 extName.data(),it1->parserName,language);
4086 }
4087 else
4088 {
4089 //msg("Registered extension {} to language parser {}...\n",
4090 // extName,language);
4091 }
4092 return true;
4093}
static ParserManager * parserManager
Definition doxygen.h:122
SrcLangExt
Definition types.h:207

References DString::at(), DString::data(), DString::empty(), err, g_extLookup, g_lang2extMap, DString::lower(), Doxygen::parserManager, DString::prepend(), and DString::str().

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

◆ useCaseSenseNames()

bool useCaseSenseNames ( )

Returns true if the names of the symbols can be case sensitive.

Definition at line 2679 of file util.cpp.

2680{
2681 auto caseSenseNames = Config_getEnum(CASE_SENSE_NAMES);
2682
2683 if (caseSenseNames == CASE_SENSE_NAMES_t::YES) return true;
2684 else if (caseSenseNames == CASE_SENSE_NAMES_t::NO) return false;
2686}
#define Config_getEnum(name)
Definition config.h:35

References Config_getEnum, and Portable::fileSystemIsCaseSensitive().

Referenced by checkAndOpenFile(), escapeCharsInString(), getEncoding(), readDir(), FileNameFn::searchKey(), and unescapeCharsInString().

◆ writeExamples()

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

Definition at line 804 of file util.cpp.

805{
806 auto replaceFunc = [&list,&ol](size_t entryIndex)
807 {
808 const auto &e = list[entryIndex];
813 // link for Html / man
814 //printf("writeObjectLink(file=%s)\n",qPrint(e->file));
815 ol.writeObjectLink(DString(),e.file,e.anchor,e.name);
817
821 // link for Latex / pdf with anchor because the sources
822 // are not hyperlinked (not possible with a verbatim environment).
823 ol.writeObjectLink(DString(),e.file,DString(),e.name);
825 };
826
827 writeMarkerList(ol, theTranslator->trWriteList(static_cast<int>(list.size())).str(), list.size(), replaceFunc);
828
829 ol.writeString(".");
830}
void disable(OutputType o)
virtual DString trWriteList(int numEntries)=0
void writeMarkerList(OutputList &ol, const std::string &markerText, size_t numMarkers, std::function< void(size_t)> replaceFunc)
Definition util.cpp:753

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

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

◆ writeInlineGraph()

DString writeInlineGraph ( const DString & baseName,
const DString & extension,
const DString & content,
bool & exists )

Thread-safe function to write a string representing an inline graph 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 5358 of file util.cpp.

5359{
5360 DString fileName = baseName + md5str(content.view()) + extension;
5361 { // ==== start atomic section
5362 std::lock_guard lock(writeFileContents_lock);
5363 auto it=writeFileContents_set.find(fileName.str());
5364 exists = it!=writeFileContents_set.end();
5365 if (!exists)
5366 {
5367 writeFileContents_set.insert(fileName.str());
5368 if (auto file = Portable::openOutputStream(fileName); file.is_open())
5369 {
5370 file.write( content.data(), content.length() );
5371 file.close();
5372 }
5373 else
5374 {
5375 err("Could not open file {} for writing\n",fileName);
5376 return DString();
5377 }
5378 }
5379 } // ==== end atomic section
5380 return fileName;
5381}
static std::mutex writeFileContents_lock
Definition util.cpp:5355

References DString::data(), err, DString::length(), md5str(), Portable::openOutputStream(), DString::str(), DString::view(), writeFileContents_lock, and writeFileContents_set.

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

◆ writeMarkerList() [1/2]

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

Definition at line 776 of file util.cpp.

778{
779 DString result;
780 static const reg::Ex marker(R"(@(\d+))");
781 reg::Iterator it(markerText,marker);
783 size_t index=0;
784 for ( ; it!=end ; ++it)
785 {
786 const auto &match = *it;
787 size_t newIndex = match.position();
788 size_t matchLen = match.length();
789 result += markerText.substr(index,newIndex-index);
790 unsigned long entryIndex = std::stoul(match[1].str());
791 if (entryIndex<static_cast<unsigned long>(numMarkers))
792 {
793 result+=replaceFunc(entryIndex);
794 }
795 index=newIndex+matchLen;
796 }
797 if (index<markerText.size())
798 {
799 result += markerText.substr(index);
800 }
801 return result;
802}

References end(), and DString::substr().

◆ writeMarkerList() [2/2]

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

Definition at line 753 of file util.cpp.

755{
756 static const reg::Ex marker(R"(@(\d+))");
757 reg::Iterator it(markerText,marker);
759 size_t index=0;
760 for ( ; it!=end ; ++it)
761 {
762 const auto &match = *it;
763 size_t newIndex = match.position();
764 size_t matchLen = match.length();
765 ol.parseText(markerText.substr(index,newIndex-index));
766 unsigned long entryIndex = std::stoul(match[1].str());
767 if (entryIndex<static_cast<unsigned long>(numMarkers))
768 {
769 replaceFunc(entryIndex);
770 }
771 index=newIndex+matchLen;
772 }
773 ol.parseText(markerText.substr(index));
774}
void parseText(const DString &textStr)

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

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

◆ writeTypeConstraints()

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

Definition at line 4283 of file util.cpp.

4284{
4285 if (al.empty()) return;
4287 for (const Argument &a : al)
4288 {
4290 ol.parseText(a.name);
4291 ol.endConstraintParam();
4293 linkifyText(TextGeneratorOLImpl(ol),a.type,LinkifyTextOptions().setScope(d));
4294 ol.endConstraintType();
4296 ol.generateDoc(d->docFile(),
4297 d->docLine(),
4298 d,
4299 nullptr,
4300 a.docs,
4301 DocOptions()
4302 .setIndexWords(true));
4303 ol.endConstraintDocs();
4304 }
4305 ol.endConstraintList();
4306}
virtual int docLine() const =0
virtual DString docFile() const =0
void endConstraintType()
Definition outputlist.h:710
void endConstraintList()
Definition outputlist.h:716
void startConstraintList(const DString &header)
Definition outputlist.h:702
void startConstraintParam()
Definition outputlist.h:704
void startConstraintDocs()
Definition outputlist.h:712
void startConstraintType()
Definition outputlist.h:708
void endConstraintDocs()
Definition outputlist.h:714
void endConstraintParam()
Definition outputlist.h:706
void generateDoc(const DString &fileName, int startLine, const Definition *ctx, const MemberDef *md, const DString &docStr, const DocOptions &options)
Implements TextGeneratorIntf for an OutputDocInterface stream.
Definition outputlist.h:786
virtual DString trTypeConstraints()=0
void linkifyText(const TextGeneratorIntf &out, const DString &text, const LinkifyTextOptions &options)
Helper class to pass options when calling OutputList::generateDoc().
Definition docoptions.h:24

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

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

Variable Documentation

◆ constScope

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

Definition at line 379 of file util.cpp.

Referenced by removeRedundantWhiteSpace().

◆ g_charAroundSpace

CharAroundSpace g_charAroundSpace
static

Definition at line 423 of file util.cpp.

Referenced by removeRedundantWhiteSpace().

◆ g_extLookup

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

Definition at line 4029 of file util.cpp.

Referenced by getLanguageFromFileName(), and updateLanguageMapping().

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

Referenced by getLanguageFromCodeLang(), and updateLanguageMapping().

◆ g_matchArgsMutex

std::mutex g_matchArgsMutex
static

Definition at line 1481 of file util.cpp.

Referenced by matchArgument2().

◆ g_usedNames

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

Definition at line 2853 of file util.cpp.

Referenced by convertNameToFile().

◆ g_usedNamesCount

int g_usedNamesCount =1
static

Definition at line 2855 of file util.cpp.

Referenced by convertNameToFile().

◆ g_usedNamesMutex

std::mutex g_usedNamesMutex
static

Definition at line 2854 of file util.cpp.

Referenced by convertNameToFile().

◆ hex

const char* hex = "0123456789ABCDEF"
static

Definition at line 80 of file util.cpp.

◆ operatorScope

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

Definition at line 382 of file util.cpp.

Referenced by removeRedundantWhiteSpace().

◆ virtualScope

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

Definition at line 381 of file util.cpp.

Referenced by removeRedundantWhiteSpace().

◆ volatileScope

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

Definition at line 380 of file util.cpp.

Referenced by removeRedundantWhiteSpace().

◆ writeFileContents_lock

std::mutex writeFileContents_lock
static

Definition at line 5355 of file util.cpp.

Referenced by writeInlineGraph().

◆ writeFileContents_set

StringUnorderedSet writeFileContents_set
static

Definition at line 5356 of file util.cpp.

Referenced by cleanupInlineGraphs(), and writeInlineGraph().