Doxygen
Loading...
Searching...
No Matches
util.cpp File Reference
#include "util.h"
#include <algorithm>
#include <cassert>
#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 67 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 1490 of file util.cpp.

Referenced by matchArgument2(), and matchArguments2().

◆ NOMATCH

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

Definition at line 1491 of file util.cpp.

Referenced by matchArgument2(), and matchArguments2().

◆ REL_PATH_TO_ROOT

#define REL_PATH_TO_ROOT   "../../"

Definition at line 80 of file util.cpp.

Referenced by relativePathToRoot().

Function Documentation

◆ addCodeOnlyMappings()

void addCodeOnlyMappings ( )

Definition at line 4164 of file util.cpp.

4165{
4166 updateLanguageMapping(".xml", "xml");
4167 updateLanguageMapping(".sql", "sql");
4168}
bool updateLanguageMapping(const DString &extension, const DString &language)
Definition util.cpp:4065

References addCodeOnlyMappings(), and updateLanguageMapping().

Referenced by addCodeOnlyMappings(), addDirPrefix(), and generateOutput().

◆ addGroupListToTitle()

◆ addHtmlExtensionIfMissing()

void addHtmlExtensionIfMissing ( DString & fName)

Definition at line 3933 of file util.cpp.

3934{
3935 if (fName.empty()) return;
3936 size_t i_fs = fName.rfind('/');
3937 size_t i_bs = fName.rfind('\\');
3938 size_t p = i_fs!=DString::npos && i_bs!=DString::npos ? std::max(i_fs, i_bs) :
3939 i_fs!=DString::npos ? i_fs : i_bs!=DString::npos ? i_bs : 0;
3940 size_t i = fName.find('.',p); // search for . after path part
3941 if (i==DString::npos)
3942 {
3944 }
3945}
A String class for use with Doxygen wrapping std::string and adding some additional functionality off...
Definition dstring.h:88
size_t rfind(char c, size_t pos=npos) const
Definition dstring.h:248
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:152
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:182
size_t find(char c, size_t pos=0) const
Definition dstring.h:243
static DString htmlFileExtension
Definition doxygen.h:115

References addHtmlExtensionIfMissing(), 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(), addDirPrefix(), addHtmlExtensionIfMissing(), 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 861 of file util.cpp.

862{
863 DString result;
864 if (!al.hasParameters()) return result;
865 result+="(";
866 for (auto it = al.begin() ; it!=al.end() ;)
867 {
868 Argument a = *it;
869 DString type1 = useCanonicalType && !a.canType.empty() ? a.canType : a.type;
870 DString type2;
871 if (size_t i=type1.find(")("); i!=DString::npos) // hack to deal with function pointers
872 {
873 type2=type1.mid(i);
874 type1=type1.left(i);
875 }
876 if (!a.attrib.empty())
877 {
878 result+=a.attrib+" ";
879 }
880 if (!a.name.empty() || !a.array.empty())
881 {
882 result+= type1+" "+a.name+type2+a.array;
883 }
884 else
885 {
886 result+= type1+type2;
887 }
888 if (!a.defval.empty() && showDefVals)
889 {
890 result+="="+a.defval;
891 }
892 ++it;
893 if (it!=al.end()) result+=", ";
894 }
895 result+=")";
896 if (al.constSpecifier()) result+=" const";
897 if (al.volatileSpecifier()) result+=" volatile";
898 if (al.refQualifier()==RefQualifierType::LValue) result+=" &";
899 else if (al.refQualifier()==RefQualifierType::RValue) result+=" &&";
900 if (!al.trailingReturnType().empty()) result+=al.trailingReturnType();
901 if (al.pureSpecifier()) result+=" =0";
902 return removeRedundantWhiteSpace(result);
903}
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:322
DString left(size_t len) const
Definition dstring.h:310
DString removeRedundantWhiteSpace(const DString &s)
Definition util.cpp:428

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

5117{
5118 if (s.empty()) return;
5119
5120 const char *p = s.data();
5121 char c = 0;
5122 while ((c=*p))
5123 {
5124 if (c==markerInfo.markerChar) // potential start of marker
5125 {
5126 if (dstrncmp(p,markerInfo.beginStr,markerInfo.beginLen)==0) // start of begin marker
5127 {
5128 size_t len = markerInfo.beginLen;
5129 bool negate = *(p+len)=='!';
5130 if (negate) len++;
5131 p += len;
5132 DString marker;
5133 while (*p)
5134 {
5135 if (markerInfo.closeLen==0 && *p=='\n') // matching end of line
5136 {
5137 warn(fileName,-1,"Remaining begin replacement with marker '{}'",marker);
5138 break;
5139 }
5140 else if (markerInfo.closeLen!= 0 && dstrncmp(p,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
5141 {
5142 p += markerInfo.closeLen;
5143 warn(fileName,-1,"Remaining begin replacement with marker '{}'",marker);
5144 break;
5145 }
5146 marker += *p;
5147 p++;
5148 }
5149 }
5150 else if (dstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // start of end marker
5151 {
5152 size_t len = markerInfo.endLen;
5153 bool negate = *(p+len)=='!';
5154 if (negate) len++;
5155 p += len;
5156 DString marker;
5157 while (*p)
5158 {
5159 if (markerInfo.closeLen==0 && *p=='\n') // matching end of line
5160 {
5161 warn(fileName,-1,"Remaining end replacement with marker '{}'",marker);
5162 break;
5163 }
5164 else if (markerInfo.closeLen!= 0 && dstrncmp(p,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
5165 {
5166 p += markerInfo.closeLen;
5167 warn(fileName,-1,"Remaining end replacement with marker '{}'",marker);
5168 break;
5169 }
5170 marker += *p;
5171 p++;
5172 }
5173 }
5174 }
5175 p++;
5176 }
5177}
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:161
int dstrncmp(const char *str1, const char *str2, size_t len)
Definition dstring.h:60
#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, checkBlocks(), SelectionMarkerInfo::closeLen, SelectionMarkerInfo::closeStr, DString::data(), dstrncmp(), DString::empty(), SelectionMarkerInfo::endLen, SelectionMarkerInfo::endStr, SelectionMarkerInfo::markerChar, and warn.

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

◆ checkExtension()

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

Definition at line 3928 of file util.cpp.

3929{
3930 return fName.right(ext.length())==ext;
3931}
DString right(size_t len) const
Definition dstring.h:315
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition dstring.h:155

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

Referenced by addDirPrefix(), checkExtension(), 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 4273 of file util.cpp.

4274{
4275 MemberDef *bestMatch = getMemberFromSymbol(scope,fileScope,n);
4276
4277 if (bestMatch && bestMatch->isTypedef())
4278 return true; // closest matching symbol is a typedef
4279 else
4280 return false;
4281}
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:4221

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

Referenced by addDirPrefix(), checkIfTypedef(), and isVarWithConstructor().

◆ cleanupInlineGraphs()

void cleanupInlineGraphs ( )

Deletes all graph files written with writeInlineGraph()

Definition at line 5385 of file util.cpp.

5386{
5387 if (Config_getBool(DOT_CLEANUP))
5388 {
5389 for (const auto& fileName: writeFileContents_set)
5390 {
5391 Dir().remove(qPrint(fileName));
5392 }
5393 }
5394}
Dir()
Definition dir.cpp:190
#define Config_getBool(name)
Definition config.h:33
const char * qPrint(const char *s)
Definition dstring.h:787
static StringUnorderedSet writeFileContents_set
Definition util.cpp:5358

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

Referenced by cleanupInlineGraphs(), and generateOutput().

◆ clearSubDirs()

void clearSubDirs ( const Dir & d)

Definition at line 2998 of file util.cpp.

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

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

Referenced by addDirPrefix(), DocbookGenerator::cleanup(), HtmlGenerator::cleanup(), LatexGenerator::cleanup(), ManGenerator::cleanup(), RTFGenerator::cleanup(), clearSubDirs(), 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 5280 of file util.cpp.

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

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

Referenced by addDirPrefix(), addToMap(), addVariable(), buildFunctionList(), buildTypedefList(), computeQualifiedIndex(), 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 2865 of file util.cpp.

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

References Config_getBool, Config_getInt, convertNameToFile(), DString::DString(), 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 addDirPrefix(), addRelatedPage(), buildExampleList(), ClassDefImpl::ClassDefImpl(), convertNameToFile(), 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 4906 of file util.cpp.

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

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

◆ convertToHtml()

DString convertToHtml ( const DString & s,
bool keepEntities )

Converts a string to a HTML-encoded string

Definition at line 3293 of file util.cpp.

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

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

Referenced by HtmlCodeGenerator::_writeCodeLink(), HtmlHelp::addContentsItem(), addDirPrefix(), addMembersToIndex(), convertToHtml(), 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 3204 of file util.cpp.

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

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

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

◆ convertToJSString()

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

Definition at line 3353 of file util.cpp.

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

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

Referenced by addDirPrefix(), convertToJSString(), generateJSLink(), generateJSNavTree(), renderQuickLinksAsJs(), 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 3234 of file util.cpp.

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

Referenced by DocSets::addContentsItem(), EclipseHelp::addContentsItem(), addDirPrefix(), Qhp::addFile(), Sitemap::addIndexFile(), Qhp::addIndexItem(), convertToXML(), 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 4621 of file util.cpp.

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

References copyFile(), Dir::Dir(), err, and DString::str().

Referenced by addDirPrefix(), copyExtraFiles(), copyFile(), 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 4661 of file util.cpp.

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

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

Referenced by addDirPrefix(), correctURL(), 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 4504 of file util.cpp.

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

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

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

◆ createSubDirs()

void createSubDirs ( const Dir & d)

Definition at line 2971 of file util.cpp.

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

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

Referenced by addDirPrefix(), createSubDirs(), 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 5330 of file util.cpp.

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

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

Referenced by addDirPrefix(), ClassDefImpl::className(), and demangleCSharpGenericName().

◆ detab()

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

Definition at line 5181 of file util.cpp.

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

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

Referenced by detab(), 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 2931 of file util.cpp.

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

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

◆ escapeCharsInString()

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

Definition at line 2690 of file util.cpp.

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

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

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

◆ externalLinkTarget()

DString externalLinkTarget ( const bool parent)

Definition at line 4493 of file util.cpp.

4494{
4495 bool extLinksInWindow = Config_getBool(EXT_LINKS_IN_WINDOW);
4496 if (extLinksInWindow)
4497 return "target=\"_blank\" ";
4498 else if (parent)
4499 return "target=\"_parent\" ";
4500 else
4501 return "";
4502}
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, externalLinkTarget(), and parent().

Referenced by HtmlCodeGenerator::_writeCodeLink(), addDirPrefix(), externalLinkTarget(), 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 4540 of file util.cpp.

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

References DString::at(), DString::empty(), end(), externalRef(), DString::length(), DString::prepend(), DString::str(), and Doxygen::tagDestinationMap.

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

◆ extractBeginRawStringDelimiter()

DString extractBeginRawStringDelimiter ( const char * rawStart)

Definition at line 5341 of file util.cpp.

5342{
5343 DString text=rawStart;
5344 size_t i = text.find('"');
5345 assert(i!=DString::npos);
5346 return text.mid(i+1,text.length()-i-2); // text=...R"xyz( -> delimiter=xyz
5347}

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

Referenced by addDirPrefix(), and extractBeginRawStringDelimiter().

◆ extractCanonicalArgType()

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

Definition at line 1460 of file util.cpp.

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

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

Referenced by extractCanonicalArgType(), and matchArgument2().

◆ extractCanonicalType()

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

Definition at line 1374 of file util.cpp.

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

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

Referenced by extractCanonicalArgType(), extractCanonicalType(), 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 3382 of file util.cpp.

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

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

Referenced by addDirPrefix(), extractCanonicalType(), extractClassNameFromType(), 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 4831 of file util.cpp.

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

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

Referenced by extractDirection(), and inlineArgListToDoc().

◆ extractEndRawStringDelimiter()

DString extractEndRawStringDelimiter ( const char * rawEnd)

Definition at line 5349 of file util.cpp.

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

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

Referenced by addDirPrefix(), and extractEndRawStringDelimiter().

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

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

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

Referenced by addClassToContext(), addConceptToContext(), addDirPrefix(), extractNamespaceName(), 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 1055 of file util.cpp.

1056{
1057 if (name.empty()) return DString();
1058 bool fileOpened=false;
1059 if (name[0]=='-' && name[1]==0) // read from stdin
1060 {
1061 std::string contents;
1062 std::string line;
1063 while (getline(std::cin,line))
1064 {
1065 contents+=line+'\n';
1066 }
1067 return contents;
1068 }
1069 else // read from file
1070 {
1071 FileInfo fi(name.str());
1072 if (!fi.exists() || !fi.isFile())
1073 {
1074 err("file '{}' not found\n",name);
1075 return "";
1076 }
1077 std::string buf;
1078 fileOpened=readInputFile(name,buf,filter,isSourceCode);
1079 if (fileOpened)
1080 {
1081 addTerminalCharIfMissing(buf,'\n');
1082 return buf;
1083 }
1084 }
1085 if (!fileOpened)
1086 {
1087 err("cannot open file '{}' for reading\n",name);
1088 }
1089 return "";
1090}
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:4376

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

Referenced by createDVIFile(), extractBoundingBox(), fileToString(), 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 961 of file util.cpp.

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

References filterCRLF().

Referenced by filterCRLF(), and readInputFile().

◆ filterTitle()

DString filterTitle ( const DString & title)

Definition at line 4456 of file util.cpp.

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

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

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

◆ findExampleFilePath()

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

Definition at line 2453 of file util.cpp.

2454{
2455 ambig=false;
2456 DString result;
2457 bool found=false;
2458 if (!found)
2459 {
2460 FileInfo fi(file.str());
2461 if (fi.exists())
2462 {
2463 result=fi.absFilePath();
2464 found=true;
2465 }
2466 }
2467 if (!found)
2468 {
2469 StringVector examplePathList = Config_getList(EXAMPLE_PATH);
2470 for (const auto &s : examplePathList)
2471 {
2472 std::string absFileName = s+(Portable::pathSeparator()+file).str();
2473 FileInfo fi(absFileName);
2474 if (fi.exists())
2475 {
2476 result=fi.absFilePath();
2477 found=true;
2478 }
2479 }
2480 }
2481
2482 if (!found)
2483 {
2484 // as a fallback we also look in the exampleNameDict
2486 if (fd && !ambig)
2487 {
2488 result=fd->absFilePath();
2489 }
2490 }
2491 return result;
2492}
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:36
DString pathSeparator()
Definition portable.cpp:374

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

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

◆ findModuleDef()

ModuleDef * findModuleDef ( const Definition * d)
static

Definition at line 3855 of file util.cpp.

3856{
3857 ModuleDef *mod = nullptr;
3859 {
3860 const FileDef *fd = toFileDef(d);
3861 if (fd) mod = fd->getModuleDef();
3862 }
3864 {
3865 const ClassDef *cd = toClassDef(d);
3866 if (cd)
3867 {
3868 const FileDef *fd = cd->getFileDef();
3869 if (fd) mod = fd->getModuleDef();
3870 }
3871 }
3873 {
3874 const ConceptDef *cd = toConceptDef(d);
3875 if (cd)
3876 {
3877 const FileDef *fd = cd->getFileDef();
3878 if (fd) mod = fd->getModuleDef();
3879 }
3880 }
3881 return mod;
3882}
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:1976

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

Referenced by findModuleDef(), and 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 686 of file util.cpp.

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

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

Referenced by findParameterList(), and resolveRef().

◆ getCanonicalTemplateSpec()

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

Definition at line 1199 of file util.cpp.

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

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

Referenced by getCanonicalTemplateSpec(), and getCanonicalTypeForIdentifier().

◆ getCanonicalTypeForIdentifier()

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

Definition at line 1220 of file util.cpp.

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

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

1869{
1870 GetDefResult result;
1871 if (input.memberName.empty()) return result;
1872 AUTO_TRACE("scopeName={},memberName={},forceEmptyScope={}",
1873 input.scopeName,input.memberName,input.forceEmptyScope);
1874
1875 //printf("@@ --- getDefsNew(%s,%s)-----------\n",qPrint(scName),qPrint(mbName));
1876 const Definition *scope = Doxygen::globalScope;
1877 SymbolResolver resolver;
1878 if (input.currentFile) resolver.setFileScope(input.currentFile);
1879 if (!input.scopeName.empty() && !input.forceEmptyScope)
1880 {
1881 scope = resolver.resolveSymbol(scope,input.scopeName);
1882 }
1883 if (scope==Doxygen::globalScope)
1884 {
1885 scope = input.currentFile;
1886 }
1887 //printf("@@ -> found scope scope=%s member=%s out=%s\n",qPrint(input.scopeName),qPrint(input.memberName),qPrint(scope?scope->name():""));
1888 //
1889 const Definition *symbol = resolver.resolveSymbol(scope,input.memberName,input.args,input.checkCV,input.insideCode,true);
1890 //printf("@@ -> found symbol in=%s out=%s\n",qPrint(input.memberName),qPrint(symbol?symbol->qualifiedName():DString()));
1891 if (symbol && symbol->definitionType()==Definition::TypeMember)
1892 {
1893 result.md = toMemberDef(symbol);
1894 result.cd = result.md->getClassDef();
1895 if (result.cd==nullptr) result.nd = result.md->getNamespaceDef();
1896 if (result.cd==nullptr && result.nd==nullptr) result.fd = result.md->getFileDef();
1897 result.gd = result.md->getGroupDef();
1898 result.found = true;
1899 }
1900 else if (symbol && symbol->definitionType()==Definition::TypeClass)
1901 {
1902 result.cd = toClassDef(symbol);
1903 result.found = true;
1904 }
1905 else if (symbol && symbol->definitionType()==Definition::TypeNamespace)
1906 {
1907 result.nd = toNamespaceDef(symbol);
1908 result.found = true;
1909 }
1910 else if (symbol && symbol->definitionType()==Definition::TypeConcept)
1911 {
1912 result.cnd = toConceptDef(symbol);
1913 result.found = true;
1914 }
1915 else if (symbol && symbol->definitionType()==Definition::TypeModule)
1916 {
1917 result.modd = toModuleDef(symbol);
1918 result.found = true;
1919 }
1920 return result;
1921}
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(), getDefs(), 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(), getDefs(), 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 4966 of file util.cpp.

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

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

Referenced by addDirPrefix(), MermaidManager::convertToImageFormat(), RTFGenerator::endCallGraph(), RTFGenerator::endDirDepGraph(), RTFGenerator::endDotGraph(), RTFGenerator::endInclDepGraph(), DotGraph::generateCode(), getDotImageExtension(), 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 4479 of file util.cpp.

4480{
4481 InputFileEncoding elem;
4482 auto getter = [](const InputFileEncoding &e) { return e.pattern.str(); };
4483 if (fi.match(Doxygen::inputFileEncodingList,useCaseSenseNames(),&elem,getter)) // check for file specific encoding
4484 {
4485 return elem.encoding;
4486 }
4487 else // fall back to default encoding
4488 {
4489 return Config_getString(INPUT_ENCODING);
4490 }
4491}
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, getEncoding(), Doxygen::inputFileEncodingList, FileInfo::match(), and useCaseSenseNames().

Referenced by addDirPrefix(), getEncoding(), 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 1022 of file util.cpp.

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

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

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

◆ getFileNameExtension()

◆ getFilterFromList()

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

Definition at line 987 of file util.cpp.

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

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

Referenced by getFileFilter(), and getFilterFromList().

◆ getLanguageFromCodeLang()

SrcLangExt getLanguageFromCodeLang ( DString & fileName)

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

Definition at line 4188 of file util.cpp.

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

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

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

◆ getLanguageFromFileName()

SrcLangExt getLanguageFromFileName ( const DString & fileName,
SrcLangExt defLang )

Definition at line 4170 of file util.cpp.

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

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

Referenced by MemberDefImpl::_writeMultiLineInitializer(), addDirPrefix(), ClassDefImpl::ClassDefImpl(), convertCppComments(), DocRef::DocRef(), FileDefImpl::FileDefImpl(), generateExampleDocs(), getLanguageFromCodeLang(), getLanguageFromFileName(), 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 )

◆ getMemberFromSymbol()

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

Definition at line 4221 of file util.cpp.

4223{
4224 if (scope==nullptr ||
4227 )
4228 )
4229 {
4231 }
4232
4233 DString name = n;
4234 if (name.empty())
4235 return nullptr; // no name was given
4236
4237 auto &range = Doxygen::symbolMap->find(name);
4238 if (range.empty())
4239 return nullptr; // could not find any matching symbols
4240
4241 // mostly copied from getResolvedClassRec()
4242 DString explicitScopePart;
4243 int qualifierIndex = computeQualifiedIndex(name);
4244 if (qualifierIndex!=-1)
4245 {
4246 explicitScopePart = name.left(qualifierIndex);
4247 replaceNamespaceAliases(explicitScopePart);
4248 name = name.mid(qualifierIndex+2);
4249 }
4250 //printf("explicitScopePart=%s\n",qPrint(explicitScopePart));
4251
4252 int minDistance = 10000;
4253 MemberDef *bestMatch = nullptr;
4254
4255 for (Definition *d : range)
4256 {
4257 if (d->definitionType()==Definition::TypeMember)
4258 {
4259 SymbolResolver resolver(fileScope);
4260 int distance = resolver.isAccessibleFromWithExpScope(scope,d,explicitScopePart);
4261 if (distance!=-1 && distance<minDistance)
4262 {
4263 minDistance = distance;
4264 bestMatch = toMemberDef(d);
4265 //printf("new best match %s distance=%d\n",qPrint(bestMatch->qualifiedName()),distance);
4266 }
4267 }
4268 }
4269 return bestMatch;
4270}
static SymbolMap< Definition > * symbolMap
Definition doxygen.h:118
const VectorPtr & find(const DString &name)
Definition symbolmap.h:75
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:5280

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

Referenced by checkIfTypedef(), and getMemberFromSymbol().

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

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

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

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

◆ getProjectId()

DString getProjectId ( )

Definition at line 5272 of file util.cpp.

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

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

Referenced by addDirPrefix(), generateJSNavTree(), getProjectId(), 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 1938 of file util.cpp.

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

Referenced by getScopeDefs(), and 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 3800 of file util.cpp.

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

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

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

◆ initDefaultExtensionMapping()

void initDefaultExtensionMapping ( )

Definition at line 4097 of file util.cpp.

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

References initDefaultExtensionMapping(), and updateLanguageMapping().

Referenced by addDirPrefix(), initDefaultExtensionMapping(), and 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 4867 of file util.cpp.

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

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

Referenced by inlineArgListToDoc(), 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 834 of file util.cpp.

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

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

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

◆ insertTemplateSpecifierInScope()

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

Definition at line 3078 of file util.cpp.

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

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

◆ isLowerCase()

bool isLowerCase ( DString & s)
static

Definition at line 2001 of file util.cpp.

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

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

Referenced by isLowerCase(), and resolveRef().

◆ isURL()

bool isURL ( const DString & url)

Checks whether the given url starts with a supported protocol.

Definition at line 4648 of file util.cpp.

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

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

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

◆ leftScopeMatch()

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

Definition at line 742 of file util.cpp.

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

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

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

◆ linkToText()

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

Definition at line 2267 of file util.cpp.

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

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

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

◆ mainPageHasTitle()

bool mainPageHasTitle ( )

Definition at line 4961 of file util.cpp.

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

References Doxygen::mainPage, and mainPageHasTitle().

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

◆ makeBaseName()

◆ mangleCSharpGenericName()

DString mangleCSharpGenericName ( const DString & name)

Definition at line 5321 of file util.cpp.

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

References DString::contains(), DString::DString(), DString::find(), DString::left(), mangleCSharpGenericName(), DString::npos, and DString::setNum().

Referenced by addClassToContext(), addDirPrefix(), addEnumValuesToEnums(), addVariable(), buildFunctionList(), extractClassName(), findClassRelation(), findEnums(), mangleCSharpGenericName(), 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 1525 of file util.cpp.

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

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

Referenced by matchArgument2(), and 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 1591 of file util.cpp.

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

References argListToString(), ASSERT, AUTO_TRACE, ArgumentList::begin(), ArgumentList::constSpecifier(), ArgumentList::empty(), ArgumentList::end(), ArgumentList::front(), MATCH, matchArgument2(), matchArguments2(), 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(), matchArguments2(), 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 1493 of file util.cpp.

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

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

Referenced by matchArgument2(), and matchCanonicalTypes().

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

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

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

Referenced by buildFunctionList(), and matchTemplateArguments().

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

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

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

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

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

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

Referenced by addDirPrefix(), addEnumValuesToEnums(), addVariable(), findEnums(), findMember(), mergeScopes(), 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 3467 of file util.cpp.

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

Referenced by findUsedClassesForClass(), and normalizeNonTemplateArgumentsInString().

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

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

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

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

◆ projectLogoFile()

DString projectLogoFile ( )

Definition at line 2582 of file util.cpp.

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

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

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

◆ projectLogoSize()

DString projectLogoSize ( )

Definition at line 2601 of file util.cpp.

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

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

Referenced by addDirPrefix(), projectLogoSize(), substituteHtmlKeywords(), and substituteLatexKeywords().

◆ protectionLevelVisible()

bool protectionLevelVisible ( Protection prot)

Definition at line 4673 of file util.cpp.

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

References Config_getBool, and protectionLevelVisible().

Referenced by MemberDefImpl::_computeLinkableInProject(), addClassAndNestedClasses(), addDirPrefix(), computeClassRelations(), MemberDefImpl::hasDetailedDescription(), ClassDefImpl::internalInsertMember(), MemberDefImpl::isBriefSectionVisible(), ClassDefImpl::isLinkableInProject(), ClassDefImpl::isVisibleInHierarchy(), protectionLevelVisible(), 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 4376 of file util.cpp.

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

References DString::empty(), err, FileInfo::exists(), Debug::ExtCmd, filterCRLF(), Debug::FilterOutput, getEncoding(), getFileFilter(), Portable::openInputStream(), Portable::pclose(), Portable::popen(), Debug::print(), readInputFile(), 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(), readInputFile(), DocbookDocVisitor::startMermaidFile(), LatexDocVisitor::startMermaidFile(), DocbookDocVisitor::startPlantUmlFile(), and LatexDocVisitor::startPlantUmlFile().

◆ recursivelyAddGroupListToTitle()

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

Definition at line 3884 of file util.cpp.

3885{
3886 ModuleDef *mod = root ? findModuleDef(d) : nullptr;
3887 if (!d->partOfGroups().empty() || mod!=nullptr) // write list of group to which this definition belongs
3888 {
3889 if (root)
3890 {
3891 ol.pushGeneratorState();
3893 ol.writeString("<div class=\"ingroups\">");
3894 }
3895 bool first=true;
3896 for (const auto &gd : d->partOfGroups())
3897 {
3898 if (!first) { ol.writeString(" &#124; "); } else first=false;
3899 if (recursivelyAddGroupListToTitle(ol, gd, false))
3900 {
3901 ol.writeString(" &raquo; ");
3902 }
3903 ol.writeObjectLink(gd->getReference(),gd->getOutputFileBase(),DString(),gd->groupTitle());
3904 }
3905 if (root)
3906 {
3907 // add module as a group to the file as well
3908 if (mod)
3909 {
3910 if (!first) { ol.writeString(" &#124; "); } else first=false;
3911 ol.writeString(theTranslator->trModule(false,true)+" ");
3913 mod->displayName());
3914 }
3915 ol.writeString("</div>");
3916 ol.popGeneratorState();
3917 }
3918 return true;
3919 }
3920 return false;
3921}
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:71
static ModuleDef * findModuleDef(const Definition *d)
Definition util.cpp:3855

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

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

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

Referenced by addDirPrefix(), generateBriefDoc(), relativePathToRoot(), 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 100 of file util.cpp.

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

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

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

◆ removeRedundantWhiteSpace()

DString removeRedundantWhiteSpace ( const DString & s)

Definition at line 428 of file util.cpp.

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

References CharAroundSpace::CharElem::after, CharAroundSpace::CharElem::before, CharAroundSpace::charMap, Config_getBool, constScope, DString::data(), disspace(), DString::empty(), g_charAroundSpace, isId(), DString::length(), operatorScope, removeRedundantWhiteSpace(), 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(), removeRedundantWhiteSpace(), resolveRef(), tempArgListToString(), and writeExceptionListImpl().

◆ replaceAnonymousScopes()

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

Definition at line 157 of file util.cpp.

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

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

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

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

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

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

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

◆ resolveDirLink()

const DirDef * resolveDirLink ( const DString & linkRef)
static

Definition at line 2292 of file util.cpp.

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

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

Referenced by resolveDirLink(), and 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 2310 of file util.cpp.

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

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(), resolveLink(), resolveRef(), and stripTemplateSpecifiersFromScope().

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

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

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

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

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

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

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

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

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

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

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

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

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

◆ showDate()

DString showDate ( const DString & fmt)

Definition at line 2569 of file util.cpp.

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

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

Referenced by addDirPrefix(), showDate(), substituteHtmlKeywords(), and substituteLatexKeywords().

◆ stackTrace()

void stackTrace ( )

Definition at line 4312 of file util.cpp.

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

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

Referenced by addDirPrefix(), and stackTrace().

◆ stripAnonymousNamespaceScope()

DString stripAnonymousNamespaceScope ( const DString & s)

Definition at line 169 of file util.cpp.

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

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

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

◆ stripDeclKeywords()

DString stripDeclKeywords ( const DString & s)
static

Definition at line 1183 of file util.cpp.

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

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

Referenced by getCanonicalTypeForIdentifier(), and stripDeclKeywords().

◆ stripExtension()

◆ stripExtensionGeneral()

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

230{
231 return stripFromPath(path,Config_getList(STRIP_FROM_INC_PATH));
232}
DString stripFromPath(const DString &path)
Definition util.cpp:221

References Config_getList, stripFromIncludePath(), and stripFromPath().

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

◆ stripFromPath() [1/2]

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

Definition at line 198 of file util.cpp.

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

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

◆ stripFromPath() [2/2]

◆ stripIndentation()

DString stripIndentation ( const DString & s,
bool skipFirstLine )

Definition at line 4685 of file util.cpp.

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

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

◆ stripIndentationVerbatim()

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

Definition at line 4774 of file util.cpp.

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

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

Referenced by MemberDefImpl::setInitializer(), and stripIndentationVerbatim().

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

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

References stripIrrelevantConstVolatile(), and stripIrrelevantString().

Referenced by extractCanonicalType(), matchArgument2(), and stripIrrelevantConstVolatile().

◆ stripIrrelevantString()

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

Definition at line 1113 of file util.cpp.

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

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

Referenced by stripIrrelevantConstVolatile(), and stripIrrelevantString().

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

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

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

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

◆ stripPath()

DString stripPath ( const DString & s)

Definition at line 3962 of file util.cpp.

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

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

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

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

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

Referenced by DotClassGraph::addClass(), DocRef::DocRef(), getCanonicalTypeForIdentifier(), DefinitionImpl::Private::init(), DiagramItem::label(), stripScope(), 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 3688 of file util.cpp.

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

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

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

◆ substituteKeywords()

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

Definition at line 2496 of file util.cpp.

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

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

Referenced by substituteHtmlKeywords(), substituteKeywords(), 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 3526 of file util.cpp.

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

References argListToString(), AUTO_TRACE, AUTO_TRACE_ADD, AUTO_TRACE_EXIT, ArgumentList::begin(), Argument::defval, DString::DString(), 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 905 of file util.cpp.

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

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

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

◆ transcodeCharacterBuffer()

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

Definition at line 4340 of file util.cpp.

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

Referenced by readInputFile(), and transcodeCharacterBuffer().

◆ trimBaseClassScope()

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

Definition at line 1092 of file util.cpp.

1093{
1094 //printf("trimBaseClassScope level=%d '%s'\n",level,qPrint(s));
1095 for (const auto &bcd : bcl)
1096 {
1097 ClassDef *cd=bcd.classDef;
1098 //printf("Trying class %s\n",qPrint(cd->name()));
1099 if (size_t spos=s.find(cd->name()+"::"); spos!=DString::npos)
1100 {
1101 s = s.left(spos)+s.right(
1102 s.length()-spos-cd->name().length()-2
1103 );
1104 }
1105 //printf("base class '%s'\n",qPrint(cd->name()));
1106 if (!cd->baseClasses().empty())
1107 {
1108 trimBaseClassScope(cd->baseClasses(),s,level+1);
1109 }
1110 }
1111}
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:1092

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

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

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

Referenced by addDirPrefix(), and unescapeCharsInString().

◆ updateLanguageMapping()

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

Definition at line 4065 of file util.cpp.

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

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

◆ useCaseSenseNames()

bool useCaseSenseNames ( )

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

Definition at line 2681 of file util.cpp.

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

References Config_getEnum, Portable::fileSystemIsCaseSensitive(), and useCaseSenseNames().

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

◆ writeExamples()

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

Definition at line 806 of file util.cpp.

807{
808 auto replaceFunc = [&list,&ol](size_t entryIndex)
809 {
810 const auto &e = list[entryIndex];
815 // link for Html / man
816 //printf("writeObjectLink(file=%s)\n",qPrint(e->file));
817 ol.writeObjectLink(DString(),e.file,e.anchor,e.name);
819
823 // link for Latex / pdf with anchor because the sources
824 // are not hyperlinked (not possible with a verbatim environment).
825 ol.writeObjectLink(DString(),e.file,DString(),e.name);
827 };
828
829 writeMarkerList(ol, theTranslator->trWriteList(static_cast<int>(list.size())).str(), list.size(), replaceFunc);
830
831 ol.writeString(".");
832}
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:755

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

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

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

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

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

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()(), RTFDocVisitor::operator()(), and writeInlineGraph().

◆ writeMarkerList() [1/2]

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

Definition at line 778 of file util.cpp.

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

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

◆ writeMarkerList() [2/2]

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

Definition at line 755 of file util.cpp.

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

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

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

◆ writeTypeConstraints()

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

Definition at line 4285 of file util.cpp.

4286{
4287 if (al.empty()) return;
4289 for (const Argument &a : al)
4290 {
4292 ol.parseText(a.name);
4293 ol.endConstraintParam();
4295 linkifyText(TextGeneratorOLImpl(ol),a.type,LinkifyTextOptions().setScope(d));
4296 ol.endConstraintType();
4298 ol.generateDoc(d->docFile(),
4299 d->docLine(),
4300 d,
4301 nullptr,
4302 a.docs,
4303 DocOptions()
4304 .setIndexWords(true));
4305 ol.endConstraintDocs();
4306 }
4307 ol.endConstraintList();
4308}
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)
TextGeneratorOLImpl(OutputList &ol)
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(), TextGeneratorOLImpl::TextGeneratorOLImpl(), theTranslator, Translator::trTypeConstraints(), and writeTypeConstraints().

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

Variable Documentation

◆ constScope

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

Definition at line 381 of file util.cpp.

Referenced by removeRedundantWhiteSpace().

◆ g_charAroundSpace

CharAroundSpace g_charAroundSpace
static

Definition at line 425 of file util.cpp.

Referenced by removeRedundantWhiteSpace().

◆ g_extLookup

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

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

Referenced by getLanguageFromCodeLang(), and updateLanguageMapping().

◆ g_matchArgsMutex

std::mutex g_matchArgsMutex
static

Definition at line 1483 of file util.cpp.

Referenced by matchArgument2().

◆ g_usedNames

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

Definition at line 2855 of file util.cpp.

Referenced by convertNameToFile().

◆ g_usedNamesCount

int g_usedNamesCount =1
static

Definition at line 2857 of file util.cpp.

Referenced by convertNameToFile().

◆ g_usedNamesMutex

std::mutex g_usedNamesMutex
static

Definition at line 2856 of file util.cpp.

Referenced by convertNameToFile().

◆ hex

const char* hex = "0123456789ABCDEF"
static

Definition at line 82 of file util.cpp.

Referenced by convertToHtml(), convertToId(), escapeCharsInString(), and replaceColorMarkers().

◆ operatorScope

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

Definition at line 384 of file util.cpp.

Referenced by removeRedundantWhiteSpace().

◆ virtualScope

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

Definition at line 383 of file util.cpp.

Referenced by removeRedundantWhiteSpace().

◆ volatileScope

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

Definition at line 382 of file util.cpp.

Referenced by removeRedundantWhiteSpace().

◆ writeFileContents_lock

std::mutex writeFileContents_lock
static

Definition at line 5357 of file util.cpp.

Referenced by writeInlineGraph().

◆ writeFileContents_set

StringUnorderedSet writeFileContents_set
static

Definition at line 5358 of file util.cpp.

Referenced by cleanupInlineGraphs(), and writeInlineGraph().