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

Go to the source code of this file.

Classes

struct  CharAroundSpace
struct  CharAroundSpace::CharElem
struct  Lang2ExtMap

Macros

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

Functions

DString removeAnonymousScopes (const DString &str)
DString replaceAnonymousScopes (const DString &s, const DString &replacement)
DString stripAnonymousNamespaceScope (const DString &s)
static DString stripFromPath (const DString &p, StringVector l)
DString stripFromPath (const DString &path)
DString stripFromIncludePath (const DString &path)
DString resolveTypeDef (const Definition *context, const DString &qualifiedName, const Definition **typedefContext)
DString removeRedundantWhiteSpace (const DString &s)
static size_t findParameterList (const DString &name)
 Returns the position in the string where a function parameter list begins, or DString::npos if one is not found.
bool rightScopeMatch (const DString &scope, const DString &name)
bool leftScopeMatch (const DString &scope, const DString &name)
void writeMarkerList (OutputList &ol, const std::string &markerText, size_t numMarkers, std::function< void(size_t)> replaceFunc)
DString writeMarkerList (const std::string &markerText, size_t numMarkers, std::function< DString(size_t)> replaceFunc)
void writeExamples (OutputList &ol, const ExampleList &list)
DString inlineTemplateArgListToDoc (const ArgumentList &al)
DString argListToString (const ArgumentList &al, bool useCanonicalType, bool showDefVals)
DString tempArgListToString (const ArgumentList &al, SrcLangExt lang, bool includeDefault)
static void filterCRLF (std::string &contents)
static DString getFilterFromList (const DString &name, const StringVector &filterList, bool &found)
DString getFileFilter (const DString &name, bool isSourceCode)
DString fileToString (const DString &name, bool filter, bool isSourceCode)
void trimBaseClassScope (const BaseClassList &bcl, DString &s, int level=0)
static void stripIrrelevantString (DString &target, const DString &str, bool insideTemplate)
void stripIrrelevantConstVolatile (DString &s, bool insideTemplate)
static DString stripDeclKeywords (const DString &s)
static DString extractCanonicalType (const Definition *d, const FileDef *fs, DString type, SrcLangExt lang, bool insideTemplate)
static DString getCanonicalTemplateSpec (const Definition *d, const FileDef *fs, const DString &spec, SrcLangExt lang)
static DString getCanonicalTypeForIdentifier (const Definition *d, const FileDef *fs, const DString &word, SrcLangExt lang, DString *tSpec, int count=0)
static DString extractCanonicalArgType (const Definition *d, const FileDef *fs, const Argument &arg, SrcLangExt lang)
static bool matchCanonicalTypes (const Definition *srcScope, const FileDef *srcFileScope, const DString &srcType, const Definition *dstScope, const FileDef *dstFileScope, const DString &dstType, SrcLangExt lang)
static bool matchArgument2 (const Definition *srcScope, const FileDef *srcFileScope, Argument &srcA, const Definition *dstScope, const FileDef *dstFileScope, Argument &dstA, SrcLangExt lang)
bool matchArguments2 (const Definition *srcScope, const FileDef *srcFileScope, const DString &srcReturnType, const ArgumentList *srcAl, const Definition *dstScope, const FileDef *dstFileScope, const DString &dstReturnType, const ArgumentList *dstAl, bool checkCV, SrcLangExt lang)
void mergeArguments (ArgumentList &srcAl, ArgumentList &dstAl, bool forceNameOverwrite)
bool matchTemplateArguments (const ArgumentList &srcAl, const ArgumentList &dstAl)
GetDefResult getDefs (const GetDefInput &input)
static bool getScopeDefs (const DString &docScope, const DString &scope, ClassDef *&cd, ConceptDef *&cnd, NamespaceDef *&nd, ModuleDef *&modd)
static bool isLowerCase (DString &s)
bool resolveRef (const DString &scName, const DString &name, bool inSeeBlock, const Definition **resContext, const MemberDef **resMember, SrcLangExt lang, bool lookForSpecialization, const FileDef *currentFile, bool checkScope)
DString linkToText (SrcLangExt lang, const DString &link, bool ignoreDots)
static const DirDef * resolveDirLink (const DString &linkRef)
bool resolveLink (const DString &scName, const DString &lr, bool, const Definition **resContext, DString &resAnchor, SrcLangExt lang, const DString &prefix, const FileDef *currentFile)
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 ModuleDef * findModuleDef (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 MemberDef * getMemberFromSymbol (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, const ReadInputFileOptions &options)
 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 ()
DString getDotImageExtension (const DString &format)
DString getDotImageExtensionGenerated (const DString &format)
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 const char staticScope [] = { 's', 't', 'a', 't', 'i', 'c', ' ' }
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, SrcLangExt > g_extLookup
static std::vector< Lang2ExtMap > g_lang2extMap
static std::mutex writeFileContents_lock
static StringUnorderedSet writeFileContents_set

Macro Definition Documentation

◆ ENABLE_TRACINGSUPPORT

#define ENABLE_TRACINGSUPPORT   0

Definition at line 65 of file util.cpp.

◆ HEXTONUM

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

Referenced by replaceColorMarkers().

◆ MATCH

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

Definition at line 1493 of file util.cpp.

Referenced by matchArgument2(), and matchArguments2().

◆ NOMATCH

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

Definition at line 1494 of file util.cpp.

Referenced by matchArgument2(), and matchArguments2().

◆ REL_PATH_TO_ROOT

#define REL_PATH_TO_ROOT   "../../"

Definition at line 78 of file util.cpp.

Referenced by relativePathToRoot().

Function Documentation

◆ addCodeOnlyMappings()

void addCodeOnlyMappings ( )

Definition at line 4168 of file util.cpp.

4169{
4170 updateLanguageMapping(".xml", "xml");
4171 updateLanguageMapping(".sql", "sql");
4172}
bool updateLanguageMapping(const DString &extension, const DString &language)
Definition util.cpp:4069

References updateLanguageMapping().

Referenced by generateOutput().

◆ addGroupListToTitle()

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

◆ addHtmlExtensionIfMissing()

void addHtmlExtensionIfMissing ( DString & fName)

Definition at line 3937 of file util.cpp.

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

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

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

◆ argListToString()

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

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

Definition at line 864 of file util.cpp.

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

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

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

◆ checkBlocks()

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

Definition at line 5139 of file util.cpp.

5140{
5141 if (s.empty()) return;
5142
5143 const char *p = s.data();
5144 char c = 0;
5145 while ((c=*p))
5146 {
5147 if (c==markerInfo.markerChar) // potential start of marker
5148 {
5149 if (dstrncmp(p,markerInfo.beginStr,markerInfo.beginLen)==0) // start of begin marker
5150 {
5151 size_t len = markerInfo.beginLen;
5152 bool negate = *(p+len)=='!';
5153 if (negate) len++;
5154 p += len;
5155 DString marker;
5156 while (*p)
5157 {
5158 if (markerInfo.closeLen==0 && *p=='\n') // matching end of line
5159 {
5160 warn(fileName,-1,"Remaining begin replacement with marker '{}'",marker);
5161 break;
5162 }
5163 else if (markerInfo.closeLen!= 0 && dstrncmp(p,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
5164 {
5165 p += markerInfo.closeLen;
5166 warn(fileName,-1,"Remaining begin replacement with marker '{}'",marker);
5167 break;
5168 }
5169 marker += *p;
5170 p++;
5171 }
5172 }
5173 else if (dstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // start of end marker
5174 {
5175 size_t len = markerInfo.endLen;
5176 bool negate = *(p+len)=='!';
5177 if (negate) len++;
5178 p += len;
5179 DString marker;
5180 while (*p)
5181 {
5182 if (markerInfo.closeLen==0 && *p=='\n') // matching end of line
5183 {
5184 warn(fileName,-1,"Remaining end replacement with marker '{}'",marker);
5185 break;
5186 }
5187 else if (markerInfo.closeLen!= 0 && dstrncmp(p,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
5188 {
5189 p += markerInfo.closeLen;
5190 warn(fileName,-1,"Remaining end replacement with marker '{}'",marker);
5191 break;
5192 }
5193 marker += *p;
5194 p++;
5195 }
5196 }
5197 }
5198 p++;
5199 }
5200}
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition dstring.h:157
int dstrncmp(const char *str1, const char *str2, size_t len)
Definition dstring.h:56
#define warn(file, line, fmt,...)
Definition message.h:97
size_t beginLen
Definition util.h:236
const char * closeStr
Definition util.h:239
const char * beginStr
Definition util.h:235
size_t closeLen
Definition util.h:240
const char * endStr
Definition util.h:237

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

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

◆ checkExtension()

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

Definition at line 3932 of file util.cpp.

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

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

Referenced by copyLatexStyleSheet(), and extraLatexStyleSheet().

◆ checkIfTypedef()

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

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

Definition at line 4277 of file util.cpp.

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

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

Referenced by isVarWithConstructor().

◆ cleanupInlineGraphs()

void cleanupInlineGraphs ( )

Deletes all graph files written with writeInlineGraph()

Definition at line 5432 of file util.cpp.

5433{
5434 if (Config_getBool(DOT_CLEANUP))
5435 {
5436 for (const auto& fileName: writeFileContents_set)
5437 {
5438 Dir().remove(qPrint(fileName));
5439 }
5440 }
5441}
Class representing a directory in the file system.
Definition dir.h:73
bool remove(const std::string &path, bool acceptsAbsPath=true) const
Definition dir.cpp:320
#define Config_getBool(name)
Definition config.h:33
const char * qPrint(const char *s)
Definition dstring.h:783
static StringUnorderedSet writeFileContents_set
Definition util.cpp:5405

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

Referenced by generateOutput().

◆ clearSubDirs()

void clearSubDirs ( const Dir & d)

Definition at line 3002 of file util.cpp.

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

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

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

◆ computeQualifiedIndex()

int computeQualifiedIndex ( const DString & name)

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

Definition at line 5309 of file util.cpp.

5310{
5311 int l = static_cast<int>(name.length());
5312 int lastSepPos = -1;
5313 const char *p = name.data();
5314 int i=l-2;
5315 int sharpCount=0;
5316 // --- begin optimized version of ts=name.findRev(">::");
5317 int ts = -1;
5318 while (i>=0)
5319 {
5320 if (p[i]=='>')
5321 {
5322 if (sharpCount==0 && p[i+1]==':' && p[i+2]==':')
5323 {
5324 ts=i;
5325 break;
5326 }
5327 sharpCount++;
5328 }
5329 else if (p[i]=='<')
5330 {
5331 sharpCount--;
5332 }
5333 i--;
5334 }
5335 // --- end optimized version
5336 if (ts==-1) ts=0; else p+=++ts;
5337 for (i=ts;i<l-1;i++)
5338 {
5339 char c=*p++;
5340 if (c==':' && *p==':') lastSepPos=i;
5341 if (c=='<') break;
5342 }
5343 return lastSepPos;
5344}
const char * name(int level)
Definition latexgen.h:368

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

◆ convertNameToFile()

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

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

Definition at line 2869 of file util.cpp.

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

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

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

◆ convertProtectionLevel()

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

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

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

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

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

Definition at line 4914 of file util.cpp.

4920{
4921 bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
4922
4923 // default representing 1-1 mapping
4924 *outListType1=inListType;
4925 *outListType2=MemberListType::Invalid();
4926
4927 if (inProt==Protection::Public)
4928 {
4929 if (inListType.isPrivate())
4930 {
4931 *outListType1=MemberListType::Invalid();
4932 }
4933 }
4934 else if (inProt==Protection::Protected)
4935 {
4936 if (inListType.isPrivate() || inListType.isPublic())
4937 {
4938 *outListType1=MemberListType::Invalid();
4939 }
4940 else if (inListType.isProtected())
4941 {
4942 *outListType2=inListType.toPublic();
4943 }
4944 }
4945 else if (inProt==Protection::Private)
4946 {
4947 if (inListType.isPublic() || inListType.isProtected())
4948 {
4949 *outListType1=MemberListType::Invalid();
4950 }
4951 else if (inListType.isPrivate())
4952 {
4953 if (extractPrivate)
4954 {
4955 *outListType1=inListType.toPublic();
4956 *outListType2=inListType.toProtected();
4957 }
4958 else
4959 {
4960 *outListType1=MemberListType::Invalid();
4961 }
4962 }
4963 }
4964
4965 //printf("convertProtectionLevel(type=%s prot=%d): %s,%s\n",
4966 // qPrint(inListType.to_string()),inProt,qPrint(outListType1->to_string()),qPrint(outListType2->to_string()));
4967}
constexpr bool isPrivate() const noexcept
Definition types.h:382
constexpr MemberListType toPublic() const noexcept
Definition types.h:426
static constexpr MemberListType Invalid() noexcept
Definition types.h:371
constexpr MemberListType toProtected() const noexcept
Definition types.h:438
constexpr bool isProtected() const noexcept
Definition types.h:380
ML_TYPES constexpr bool isPublic() const noexcept
Definition types.h:378

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

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

◆ convertToHtml()

DString convertToHtml ( const DString & s,
bool keepEntities )

Converts a string to a HTML-encoded string

Definition at line 3297 of file util.cpp.

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

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

Referenced by HtmlCodeGenerator::_writeCodeLink(), HtmlHelp::addContentsItem(), addMembersToIndex(), convertToHtmlAndTruncate(), FTVHelp::Private::generateLink(), RequirementManager::generatePage(), 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 3208 of file util.cpp.

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

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

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

◆ convertToJSString()

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

Definition at line 3357 of file util.cpp.

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

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

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

◆ convertToXML()

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

Converts a string to an XML-encoded string

Definition at line 3238 of file util.cpp.

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

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

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

◆ copyFile()

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

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

Returns true if successful.

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

Definition at line 4629 of file util.cpp.

4630{
4631 if (!Dir().copy(src.str(),dest.str()))
4632 {
4633 err("could not copy file {} to {}\n",src,dest);
4634 return false;
4635 }
4636 return true;
4637}
#define err(fmt,...)
Definition message.h:127

References err, and DString::str().

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

◆ correctURL()

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

Corrects URL url according to the relative path relPath.

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

Definition at line 4669 of file util.cpp.

4670{
4671 DString result = url;
4672 if (!relPath.empty() && !isURL(url))
4673 {
4674 result.prepend(relPath);
4675 }
4676 return result;
4677}
bool isURL(const DString &url)
Checks whether the given url starts with a supported protocol.
Definition util.cpp:4656

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

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

◆ createHtmlUrl()

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

Definition at line 4512 of file util.cpp.

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

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

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

◆ createSubDirs()

void createSubDirs ( const Dir & d)

Definition at line 2975 of file util.cpp.

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

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

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

◆ demangleCSharpGenericName()

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

Definition at line 5377 of file util.cpp.

5378{
5379 DString result=name;
5380 if (result.endsWith("-g"))
5381 {
5382 size_t idx = result.find('-');
5383 result = result.left(idx)+templArgs;
5384 }
5385 return result;
5386}

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

Referenced by ClassDefImpl::className().

◆ detab()

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

Definition at line 5204 of file util.cpp.

5205{
5206 int tabSize = Config_getInt(TAB_SIZE);
5207 size_t size = s.length();
5208 DString result;
5209 result.reserve(size+256);
5210 const char *data = s.data();
5211 size_t i=0;
5212 int col=0;
5213 constexpr auto doxy_nbsp = "&_doxy_nbsp;"; // doxygen escape command for UTF-8 nbsp
5214 const int maxIndent=1000000; // value representing infinity
5215 int minIndent=maxIndent;
5216 bool skip = false;
5217 while (i<size)
5218 {
5219 char c = data[i++];
5220 switch(c)
5221 {
5222 case '\t': // expand tab
5223 {
5224 int stop = tabSize - (col%tabSize);
5225 //printf("expand at %d stop=%d\n",col,stop);
5226 col+=stop;
5227 while (stop--) result+=' ';
5228 }
5229 break;
5230 case '\\':
5231 if (skip && data[i] == '\\' && i+8<size && literal_at(data+i+1,"endiskip"))
5232 {
5233 // literal backslash directly followed by , e.g. `\` in a code span
5234 result+=c;
5235 col++;
5236 }
5237 else if (data[i] == '\\') // escaped command -> ignore
5238 {
5239 result+=c;
5240 result+=data[i++];
5241 col+=2;
5242 }
5243 else if (i+5<size && literal_at(data+i,"iskip")) // command
5244 {
5245 i+=5;
5246 skip = true;
5247 }
5248 else if (i+8<size && literal_at(data+i,"endiskip")) // command
5249 {
5250 i+=8;
5251 skip = false;
5252 }
5253 else // some other command
5254 {
5255 result+=c;
5256 col++;
5257 }
5258 break;
5259 case '\n': // reset column counter
5260 result+=c;
5261 col=0;
5262 break;
5263 case ' ': // increment column counter
5264 result+=c;
5265 col++;
5266 break;
5267 default: // non-whitespace => update minIndent
5268 if (static_cast<signed char>(c)<0 && i<size) // multibyte sequence
5269 {
5270 // special handling of the UTF-8 nbsp character 0xC2 0xA0
5271 int nb = isUTF8NonBreakableSpace(data);
5272 if (nb>0)
5273 {
5274 result+=doxy_nbsp;
5275 i+=nb-1;
5276 }
5277 else
5278 {
5279 int bytes = getUTF8CharNumBytes(c);
5280 for (int j=0;j<bytes-1 && c;j++)
5281 {
5282 result+=c;
5283 c = data[i++];
5284 }
5285 result+=c;
5286 }
5287 }
5288 else
5289 {
5290 result+=c;
5291 }
5292 if (!skip && col<minIndent) minIndent=col;
5293 col++;
5294 }
5295 }
5296 if (minIndent!=maxIndent) refIndent=minIndent; else refIndent=0;
5297 //printf("detab(\n%s\n)=[\n%s\n]\n",qPrint(s),qPrint(out.get()));
5298 return result;
5299}
bool literal_at(const char *data, const char(&str)[N])
returns true iff data points to a substring that matches string literal str
Definition stringutil.h:101
int isUTF8NonBreakableSpace(const char *input)
Check if the first character pointed at by input is a non-breakable whitespace character.
Definition utf8.cpp:232
uint8_t getUTF8CharNumBytes(char c)
Returns the number of bytes making up a single UTF8 character given the first byte in the sequence.
Definition utf8.cpp:27

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

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

◆ determineAbsoluteIncludeName()

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

Definition at line 2935 of file util.cpp.

2936{
2937 bool searchIncludes = Config_getBool(SEARCH_INCLUDES);
2938 DString absIncFileName = incFileName;
2939 FileInfo fi(curFile.str());
2940 if (fi.exists())
2941 {
2942 DString absName = fi.dirPath(true)+"/"+incFileName;
2943 FileInfo fi2(absName.str());
2944 if (fi2.exists())
2945 {
2946 absIncFileName=fi2.absFilePath();
2947 }
2948 else if (searchIncludes) // search in INCLUDE_PATH as well
2949 {
2950 StringVector includePath = Config_getList(INCLUDE_PATH);
2951 for (const auto &incPath : includePath)
2952 {
2953 FileInfo fi3(incPath);
2954 if (fi3.exists() && fi3.isDir())
2955 {
2956 absName = fi3.absFilePath()+"/"+incFileName;
2957 //printf("trying absName=%s\n",qPrint(absName));
2958 FileInfo fi4(absName.str());
2959 if (fi4.exists())
2960 {
2961 absIncFileName=fi4.absFilePath();
2962 break;
2963 }
2964 //printf( "absIncFileName = %s\n", qPrint(absIncFileName) );
2965 }
2966 }
2967 }
2968 //printf( "absIncFileName = %s\n", qPrint(absIncFileName) );
2969 }
2970 return absIncFileName;
2971}
Minimal replacement for QFileInfo.
Definition fileinfo.h:26
#define Config_getList(name)
Definition config.h:38
std::vector< std::string > StringVector
Definition containers.h:33

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

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

◆ escapeCharsInString()

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

Definition at line 2694 of file util.cpp.

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

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

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

◆ externalLinkTarget()

DString externalLinkTarget ( const bool parent)

Definition at line 4501 of file util.cpp.

4502{
4503 bool extLinksInWindow = Config_getBool(EXT_LINKS_IN_WINDOW);
4504 if (extLinksInWindow)
4505 return "target=\"_blank\" ";
4506 else if (parent)
4507 return "target=\"_parent\" ";
4508 else
4509 return "";
4510}
constexpr DocNodeVariant * parent(DocNodeVariant *n)
returns the parent node of a given node n or nullptr if the node has no parent.
Definition docnode.h:1335

References Config_getBool, and parent().

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

◆ externalRef()

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

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

Definition at line 4548 of file util.cpp.

4549{
4550 DString result;
4551 if (!ref.empty())
4552 {
4553 auto it = Doxygen::tagDestinationMap.find(ref.str());
4555 {
4556 result = it->second;
4557 size_t l = result.length();
4558 if (!relPath.empty() && l>0 && result.at(0)=='.')
4559 { // relative path -> prepend relPath.
4560 result.prepend(relPath);
4561 l+=relPath.length();
4562 }
4563 if (l>0 && result.at(l-1)!='/') result+='/';
4564 }
4565 }
4566 else
4567 {
4568 result = relPath;
4569 }
4570 return result;
4571}
char & at(size_t i)
Returns a reference to the character at index i.
Definition dstring.h:686
static StringMap tagDestinationMap
Definition doxygen.h:109
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:181

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

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

◆ extractBeginRawStringDelimiter()

DString extractBeginRawStringDelimiter ( const char * rawStart)

Definition at line 5388 of file util.cpp.

5389{
5390 DString text=rawStart;
5391 size_t i = text.find('"');
5393 return text.mid(i+1,text.length()-i-2); // text=...R"xyz( -> delimiter=xyz
5394}
#define ASSERT(x)
Definition message.h:142

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

◆ extractCanonicalArgType()

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

Definition at line 1463 of file util.cpp.

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

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

Referenced by matchArgument2().

◆ extractCanonicalType()

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

Definition at line 1377 of file util.cpp.

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

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

Referenced by extractCanonicalArgType(), and getCanonicalTemplateSpec().

◆ extractClassNameFromType()

int extractClassNameFromType ( const DString & type,
int & pos,
DString & name,
DString & templSpec,
SrcLangExt lang )

Extracts a (sub-)string from type starting at pos that could form a class. The index of the match is returned and the found class name and a template argument list templSpec. If -1 is returned there are no more matches.

Definition at line 3386 of file util.cpp.

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

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

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

◆ extractDirection()

DString extractDirection ( DString & docs)
static

Strip the direction part from docs and return it as a string in canonical form.

The input docs string can start with e.g. "[in]", "[in, out]", "[inout]", "[out,in]"...

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

Definition at line 4839 of file util.cpp.

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

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

Referenced by inlineArgListToDoc().

◆ extractEndRawStringDelimiter()

DString extractEndRawStringDelimiter ( const char * rawEnd)

Definition at line 5396 of file util.cpp.

5397{
5398 DString text=rawEnd;
5399 return text.mid(1,text.length()-2); // text=)xyz" -> delimiter=xyz
5400}

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

◆ extractNamespaceName()

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

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

Definition at line 3032 of file util.cpp.

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

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

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

◆ fileToString()

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

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

Definition at line 1058 of file util.cpp.

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

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

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

◆ filterCRLF()

void filterCRLF ( std::string & contents)
static

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

Definition at line 964 of file util.cpp.

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

Referenced by readInputFile().

◆ filterTitle()

DString filterTitle ( const DString & title)

Definition at line 4464 of file util.cpp.

4465{
4466 std::string tf;
4467 std::string t = title.str();
4468 static const reg::Ex re(R"(%[a-z_A-Z]+)");
4469 reg::Iterator it(t,re);
4471 size_t p = 0;
4472 for (; it!=end ; ++it)
4473 {
4474 const auto &match = *it;
4475 size_t i = match.position();
4476 size_t l = match.length();
4477 if (i>p) tf+=t.substr(p,i-p);
4478 tf+=match.str().substr(1); // skip %
4479 p=i+l;
4480 }
4481 tf+=t.substr(p);
4482 return tf;
4483}

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

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

◆ findExampleFilePath()

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

Definition at line 2457 of file util.cpp.

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

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

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

◆ findModuleDef()

ModuleDef * findModuleDef ( const Definition * d)
static

Definition at line 3859 of file util.cpp.

3860{
3861 ModuleDef *mod = nullptr;
3863 {
3864 const FileDef *fd = toFileDef(d);
3865 if (fd) mod = fd->getModuleDef();
3866 }
3868 {
3869 const ClassDef *cd = toClassDef(d);
3870 if (cd)
3871 {
3872 const FileDef *fd = cd->getFileDef();
3873 if (fd) mod = fd->getModuleDef();
3874 }
3875 }
3877 {
3878 const ConceptDef *cd = toConceptDef(d);
3879 if (cd)
3880 {
3881 const FileDef *fd = cd->getFileDef();
3882 if (fd) mod = fd->getModuleDef();
3883 }
3884 }
3885 return mod;
3886}
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:2033

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

Referenced by recursivelyAddGroupListToTitle().

◆ findParameterList()

size_t findParameterList ( const DString & name)
static

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

Definition at line 689 of file util.cpp.

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

References DString::npos.

Referenced by resolveRef().

◆ getCanonicalTemplateSpec()

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

Definition at line 1202 of file util.cpp.

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

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

Referenced by getCanonicalTypeForIdentifier().

◆ getCanonicalTypeForIdentifier()

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

Definition at line 1223 of file util.cpp.

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

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

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

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

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

◆ getDotImageExtension() [1/2]

DString getDotImageExtension ( )

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

Definition at line 4974 of file util.cpp.

4975{
4976 return getDotImageExtension(Config_getEnumAsString(DOT_IMAGE_FORMAT));
4977}
#define Config_getEnumAsString(name)
Definition config.h:36
DString getDotImageExtension()
Definition util.cpp:4974

References Config_getEnumAsString, and getDotImageExtension().

Referenced by MermaidManager::convertToImageFormat(), RTFGenerator::endCallGraph(), RTFGenerator::endDirDepGraph(), RTFGenerator::endDotGraph(), RTFGenerator::endInclDepGraph(), DotGraph::generateCode(), getDotImageExtension(), DotGraph::imgName(), HtmlDocVisitor::operator()(), HtmlDocVisitor::operator()(), DotRunner::run(), 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().

◆ getDotImageExtension() [2/2]

DString getDotImageExtension ( const DString & format)

Returns the file extension to use for dot files as specified via the argument format.

Definition at line 4978 of file util.cpp.

4979{
4980 size_t i= format.find(':'); // strip renderer part when using e.g. 'png:cairo:gd' as format
4981 return i==DString::npos ? format : format.left(i);
4982}

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

◆ getDotImageExtensionGenerated()

DString getDotImageExtensionGenerated ( const DString & format)

Definition at line 4984 of file util.cpp.

4985{
4986 StringVector splitExt = split(format.str(),":");
4987 DString extGen;
4988 for (size_t i = splitExt.size(); i > 0; )
4989 {
4990 --i;
4991 extGen += splitExt[i] + (i!=0 ? "." : "");
4992 }
4993 return extGen;
4994}
StringVector split(const std::string &s, const std::string &delimiter, bool retainEmpty=false)
split input string s by string delimiter delimiter.
Definition stringutil.h:119

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

Referenced by DotRunner::run().

◆ getEncoding()

DString getEncoding ( const FileInfo & fi)

Definition at line 4487 of file util.cpp.

4488{
4489 InputFileEncoding elem;
4490 auto getter = [](const InputFileEncoding &e) { return e.pattern.str(); };
4491 if (fi.match(Doxygen::inputFileEncodingList,useCaseSenseNames(),&elem,getter)) // check for file specific encoding
4492 {
4493 return elem.encoding;
4494 }
4495 else // fall back to default encoding
4496 {
4497 return Config_getString(INPUT_ENCODING);
4498 }
4499}
static InputFileEncodingList inputFileEncodingList
Definition doxygen.h:131
bool match(const PatternList &patList, bool caseSenseNames, PatternElem *elem=nullptr, PatternGet getter=[](const std::string &s){ return s;}) const
Match the file name against a list of patterns.
Definition fileinfo.h:60
#define Config_getString(name)
Definition config.h:32
DString encoding
Definition doxygen.h:63

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

Referenced by readCodeFragment(), and readInputFile().

◆ getFileFilter()

DString getFileFilter ( const DString & name,
bool isSourceCode )

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

Definition at line 1025 of file util.cpp.

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

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

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

◆ getFileNameExtension()

◆ getFilterFromList()

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

Definition at line 990 of file util.cpp.

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

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

Referenced by getFileFilter().

◆ getLanguageFromCodeLang()

SrcLangExt getLanguageFromCodeLang ( DString & fileName)

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

Definition at line 4192 of file util.cpp.

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

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

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

◆ getLanguageFromFileName()

SrcLangExt getLanguageFromFileName ( const DString & fileName,
SrcLangExt defLang )

Definition at line 4174 of file util.cpp.

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

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

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

◆ getLanguageSpecificSeparator()

DString getLanguageSpecificSeparator ( SrcLangExt lang,
bool classScope = false )

Returns the scope separator to use given the programming language lang

Definition at line 4639 of file util.cpp.

4640{
4641 if (lang==SrcLangExt::Java || lang==SrcLangExt::CSharp || lang==SrcLangExt::VHDL || lang==SrcLangExt::Python)
4642 {
4643 return ".";
4644 }
4645 else if (lang==SrcLangExt::PHP && !classScope)
4646 {
4647 return "\\";
4648 }
4649 else
4650 {
4651 return "::";
4652 }
4653}

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

◆ getMemberFromSymbol()

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

Definition at line 4225 of file util.cpp.

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

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

Referenced by checkIfTypedef().

◆ getPrefixIndex()

int getPrefixIndex ( const DString & name)

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

Definition at line 2657 of file util.cpp.

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

References Config_getList.

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

◆ getProjectId()

DString getProjectId ( )

Definition at line 5301 of file util.cpp.

5302{
5303 DString projectCookie = Config_getString(HTML_PROJECT_COOKIE);
5304 if (projectCookie.empty()) return DString();
5305 return md5str(projectCookie.view())+"_";
5306}

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

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

◆ getScopeDefs()

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

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

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

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

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

Definition at line 1941 of file util.cpp.

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

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

Referenced by resolveRef().

◆ getScopeFragment()

int getScopeFragment ( const DString & s,
int p,
int * l )

Returns a fragment from scope s, starting at position p.

Parameters
sthe scope name as a string.
pthe start position (0 is the first).
lthe resulting length of the fragment.
Returns
the location of the fragment, or -1 if non is found.

Definition at line 3804 of file util.cpp.

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

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

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

◆ initDefaultExtensionMapping()

void initDefaultExtensionMapping ( )

Definition at line 4101 of file util.cpp.

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

References updateLanguageMapping().

Referenced by initDoxygen().

◆ inlineArgListToDoc()

DString inlineArgListToDoc ( const ArgumentList & al)

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

Definition at line 4875 of file util.cpp.

4876{
4877 DString paramDocs;
4878 if (al.hasDocumentation(true))
4879 {
4880 for (const Argument &a : al)
4881 {
4882 if (a.hasDocumentation(true))
4883 {
4884 DString docsWithoutDir = a.docs;
4885 DString direction = extractDirection(docsWithoutDir);
4886 DString name = a.name;
4887 if (name.empty())
4888 {
4889 name = "-";
4890 }
4891 paramDocs+=" \\ilinebr @param"+direction+" "+name+" "+docsWithoutDir;
4892 }
4893 }
4894 }
4895 return paramDocs;
4896}
bool hasDocumentation(bool allowEmptyNames=false) const
Definition arguments.cpp:26
static DString extractDirection(DString &docs)
Strip the direction part from docs and return it as a string in canonical form.
Definition util.cpp:4839

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

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

◆ inlineTemplateArgListToDoc()

DString inlineTemplateArgListToDoc ( const ArgumentList & al)

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

Definition at line 837 of file util.cpp.

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

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

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

◆ insertTemplateSpecifierInScope()

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

Definition at line 3082 of file util.cpp.

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

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

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

◆ isLowerCase()

bool isLowerCase ( DString & s)
static

Definition at line 2004 of file util.cpp.

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

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

Referenced by resolveRef().

◆ isURL()

bool isURL ( const DString & url)

Checks whether the given url starts with a supported protocol.

Definition at line 4656 of file util.cpp.

4657{
4658 static const std::unordered_set<std::string> schemes = {
4659 "http", "https", "ftp", "ftps", "sftp", "file", "news", "irc", "ircs"
4660 };
4661 DString loc_url = url.stripWhiteSpace();
4662 size_t colonPos = loc_url.find(':');
4663 return colonPos!=DString::npos && schemes.find(loc_url.left(colonPos).str())!=schemes.end();
4664}

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

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

◆ leftScopeMatch()

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

Definition at line 745 of file util.cpp.

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

References DString::length().

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

◆ linkToText()

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

Definition at line 2270 of file util.cpp.

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

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

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

◆ mainPageHasTitle()

bool mainPageHasTitle ( )

Definition at line 4969 of file util.cpp.

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

References Doxygen::mainPage.

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

◆ makeBaseName()

◆ mangleCSharpGenericName()

DString mangleCSharpGenericName ( const DString & name)

Definition at line 5351 of file util.cpp.

5352{
5353 DString result;
5354 size_t p=0;
5355 size_t idx;
5356 while ((idx=name.find('<',p))!=DString::npos)
5357 {
5358 result+=name.mid(p,idx-p);
5359 // count the top level arguments of the balanced <...> group
5360 int depth=0;
5361 int count=1;
5362 size_t i=idx;
5363 for (; i<name.length(); i++)
5364 {
5365 char c=name[i];
5366 if (c=='<') depth++;
5367 else if (c=='>' && --depth==0) break;
5368 else if (c==',' && depth==1) count++;
5369 }
5370 result+="-"+DString().setNum(count)+"-g";
5371 p=i+1;
5372 }
5373 if (p<name.length()) result+=name.mid(p);
5374 return result;
5375}
DString & setNum(short n)
Definition dstring.h:552

References DString::npos, and DString::setNum().

Referenced by addClassToContext(), addEnumValuesToEnums(), addVariable(), buildFunctionList(), extractClassName(), findClassRelation(), findEnums(), SymbolResolver::resolveClass(), resolveLink(), and resolveRef().

◆ matchArgument2()

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

Definition at line 1528 of file util.cpp.

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

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

Referenced by matchArguments2().

◆ matchArguments2()

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

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

Definition at line 1594 of file util.cpp.

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

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

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

◆ matchCanonicalTypes()

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

Definition at line 1496 of file util.cpp.

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

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

Referenced by matchArgument2().

◆ matchTemplateArguments()

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

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

Definition at line 1838 of file util.cpp.

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

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

Referenced by buildFunctionList().

◆ mergeArguments()

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

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

Definition at line 1694 of file util.cpp.

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

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

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

◆ mergeScopes()

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

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

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

Definition at line 3759 of file util.cpp.

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

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

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

◆ normalizeNonTemplateArgumentsInString()

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

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

Definition at line 3471 of file util.cpp.

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

Referenced by findUsedClassesForClass().

◆ openOutputFile()

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

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

Definition at line 4996 of file util.cpp.

4997{
4998 ASSERT(!f.is_open());
4999 bool fileOpened=false;
5000 bool writeToStdout=outFile=="-";
5001 if (writeToStdout) // write to stdout
5002 {
5003 f.basic_ios<char>::rdbuf(std::cout.rdbuf());
5004 fileOpened = true;
5005 }
5006 else // write to file
5007 {
5008 FileInfo fi(outFile.str());
5009 if (fi.exists()) // create a backup
5010 {
5011 Dir dir;
5012 FileInfo backup(fi.filePath()+".bak");
5013 if (backup.exists()) // remove existing backup
5014 dir.remove(backup.filePath());
5015 dir.rename(fi.filePath(),fi.filePath()+".bak");
5016 }
5017 f = Portable::openOutputStream(outFile);
5018 fileOpened = f.is_open();
5019 }
5020 return fileOpened;
5021}
bool rename(const std::string &orgName, const std::string &newName, bool acceptsAbsPath=true) const
Definition dir.cpp:327
std::ofstream openOutputStream(const DString &name, bool append=false)
Definition portable.cpp:681

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

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

◆ projectLogoFile()

DString projectLogoFile ( )

Definition at line 2586 of file util.cpp.

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

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

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

◆ projectLogoSize()

DString projectLogoSize ( )

Definition at line 2605 of file util.cpp.

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

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

Referenced by substituteHtmlKeywords(), and substituteLatexKeywords().

◆ protectionLevelVisible()

bool protectionLevelVisible ( Protection prot)

Definition at line 4681 of file util.cpp.

4682{
4683 bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
4684 bool extractPackage = Config_getBool(EXTRACT_PACKAGE);
4685
4686 return (prot!=Protection::Private && prot!=Protection::Package) ||
4687 (prot==Protection::Private && extractPrivate) ||
4688 (prot==Protection::Package && extractPackage);
4689}

References Config_getBool.

Referenced by MemberDefImpl::_computeLinkableInProject(), addClassAndNestedClasses(), computeClassRelations(), MemberDefImpl::hasDetailedDescription(), ClassDefImpl::internalInsertMember(), MemberDefImpl::isBriefSectionVisible(), ClassDefImpl::isLinkableInProject(), ClassDefImpl::isVisibleInHierarchy(), MemberDefImpl::warnIfUndocumented(), MemberDefImpl::writeDeclaration(), ClassDefImpl::writeDocumentationForInnerClasses(), ClassDefImpl::writeMemberList(), and ClassDefImpl::writeTagFile().

◆ readInputFile()

bool readInputFile ( const DString & fileName,
std::string & contents,
const ReadInputFileOptions & options )

read a file name fileName and optionally filter and transcode it

Definition at line 4380 of file util.cpp.

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

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

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

◆ recursivelyAddGroupListToTitle()

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

Definition at line 3888 of file util.cpp.

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

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

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

References Config_getBool, DString::npos, and REL_PATH_TO_ROOT.

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

◆ removeAnonymousScopes()

DString removeAnonymousScopes ( const DString & str)

Removes all anonymous scopes from string s Possible examples:

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

Definition at line 98 of file util.cpp.

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

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

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

◆ removeRedundantWhiteSpace()

DString removeRedundantWhiteSpace ( const DString & s)

Definition at line 427 of file util.cpp.

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

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

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

◆ replaceAnonymousScopes()

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

Definition at line 155 of file util.cpp.

156{
157 if (s.empty()) return s;
158 static const reg::Ex marker(R"(@\d+)");
159 std::string result = reg::replace(s.str(),marker,
160 !replacement.empty() ? replacement.data() : "__anonymous__");
161 //printf("replaceAnonymousScopes('%s')='%s'\n",qPrint(s),qPrint(result));
162 return result;
163}
std::string replace(std::string_view str, const Ex &re, std::string_view replacement)
Searching in a given input string for parts that match regular expression re and replaces those parts...
Definition regex.cpp:872

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

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

◆ replaceColorMarkers()

DString replaceColorMarkers ( const DString & str)

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

Definition at line 4578 of file util.cpp.

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

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

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

◆ resolveDirLink()

const DirDef * resolveDirLink ( const DString & linkRef)
static

Definition at line 2295 of file util.cpp.

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

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

Referenced by resolveLink().

◆ resolveLink()

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

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

Postcondition
return value true implies *resContext!=0

Definition at line 2313 of file util.cpp.

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

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

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

◆ resolveRef()

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

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

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

Definition at line 2013 of file util.cpp.

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

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

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

◆ resolveTypeDef()

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

Definition at line 232 of file util.cpp.

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

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

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

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

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

◆ selectBlocks()

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

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

Definition at line 5026 of file util.cpp.

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

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

Referenced by substituteHtmlKeywords(), and substituteLatexKeywords().

◆ showDate()

DString showDate ( const DString & fmt)

Definition at line 2573 of file util.cpp.

2574{
2575 // get the current date and time
2576 std::tm dat{};
2577 int specFormat=0;
2578 DString specDate = "";
2579 DString err = dateTimeFromString(specDate,dat,specFormat);
2580
2581 // do the conversion
2582 int usedFormat=0;
2583 return formatDateTime(fmt,dat,usedFormat);
2584}
DString formatDateTime(const DString &format, const std::tm &dt, int &formatUsed)
Return a string representation for a given std::tm value that is formatted according to the pattern g...
Definition datetime.cpp:176
DString dateTimeFromString(const DString &spec, std::tm &dt, int &format)
Returns the filled in std::tm for a given string representing a date and/or time.
Definition datetime.cpp:135
Definition message.h:146

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

Referenced by substituteHtmlKeywords(), and substituteLatexKeywords().

◆ stackTrace()

void stackTrace ( )

Definition at line 4316 of file util.cpp.

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

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

◆ stripAnonymousNamespaceScope()

DString stripAnonymousNamespaceScope ( const DString & s)

Definition at line 167 of file util.cpp.

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

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

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

◆ stripDeclKeywords()

DString stripDeclKeywords ( const DString & s)
static

Definition at line 1186 of file util.cpp.

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

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

Referenced by getCanonicalTypeForIdentifier().

◆ stripExtension()

◆ stripExtensionGeneral()

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

◆ stripFromIncludePath()

DString stripFromIncludePath ( const DString & path)

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

Definition at line 227 of file util.cpp.

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

References Config_getList, and stripFromPath().

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

◆ stripFromPath() [1/2]

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

Definition at line 196 of file util.cpp.

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

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

Referenced by stripFromIncludePath(), and stripFromPath().

◆ stripFromPath() [2/2]

◆ stripIndentation()

DString stripIndentation ( const DString & s,
bool skipFirstLine )

Definition at line 4693 of file util.cpp.

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

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

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

◆ stripIndentationVerbatim()

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

Definition at line 4782 of file util.cpp.

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

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

Referenced by MemberDefImpl::setInitializer().

◆ stripIrrelevantConstVolatile()

void stripIrrelevantConstVolatile ( DString & s,
bool insideTemplate )

According to the C++ spec and Ivan Vecerina:

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

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

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

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

Definition at line 1176 of file util.cpp.

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

References stripIrrelevantString().

Referenced by extractCanonicalType(), and matchArgument2().

◆ stripIrrelevantString()

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

Definition at line 1116 of file util.cpp.

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

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

Referenced by stripIrrelevantConstVolatile().

◆ stripLeadingAndTrailingEmptyLines()

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

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

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

Definition at line 3993 of file util.cpp.

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

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

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

◆ stripPath()

DString stripPath ( const DString & s)

Definition at line 3966 of file util.cpp.

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

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

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

◆ stripScope()

DString stripScope ( const DString & name)

Strips the scope from a name. Examples: A::B will return A and A<T>::B<N::C<D> > will return A<T>.

Definition at line 3115 of file util.cpp.

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

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

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

◆ stripTemplateSpecifiersFromScope()

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

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

Definition at line 3692 of file util.cpp.

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

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

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

◆ substituteKeywords()

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

Definition at line 2500 of file util.cpp.

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

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

Referenced by substituteHtmlKeywords(), and substituteLatexKeywords().

◆ substituteTemplateArgumentsInString()

DString substituteTemplateArgumentsInString ( const DString & name,
const ArgumentList & formalArgs,
const ArgumentList * actualArgs )

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

Definition at line 3530 of file util.cpp.

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

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

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

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

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

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

◆ transcodeCharacterBuffer()

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

Definition at line 4344 of file util.cpp.

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

References DString::data(), dstricmp(), DString::empty(), portable_iconv(), portable_iconv_close(), portable_iconv_open(), and term.

Referenced by readInputFile().

◆ trimBaseClassScope()

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

Definition at line 1095 of file util.cpp.

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

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

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

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

◆ updateLanguageMapping()

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

Definition at line 4069 of file util.cpp.

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

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

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

◆ useCaseSenseNames()

bool useCaseSenseNames ( )

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

Definition at line 2685 of file util.cpp.

2686{
2687 auto caseSenseNames = Config_getEnum(CASE_SENSE_NAMES);
2688
2689 if (caseSenseNames == CASE_SENSE_NAMES_t::YES) return true;
2690 else if (caseSenseNames == CASE_SENSE_NAMES_t::NO) return false;
2692}
#define Config_getEnum(name)
Definition config.h:35

References Config_getEnum, and Portable::fileSystemIsCaseSensitive().

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

◆ writeExamples()

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

Definition at line 809 of file util.cpp.

810{
811 auto replaceFunc = [&list,&ol](size_t entryIndex)
812 {
813 const auto &e = list[entryIndex];
818 // link for Html / man
819 //printf("writeObjectLink(file=%s)\n",qPrint(e->file));
820 ol.writeObjectLink(DString(),e.file,e.anchor,e.name);
822
826 // link for Latex / pdf with anchor because the sources
827 // are not hyperlinked (not possible with a verbatim environment).
828 ol.writeObjectLink(DString(),e.file,DString(),e.name);
830 };
831
832 writeMarkerList(ol, theTranslator->trWriteList(static_cast<int>(list.size())).str(), list.size(), replaceFunc);
833
834 ol.writeString(".");
835}
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:758

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

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

◆ writeInlineGraph()

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

Thread-safe function to write a string representing an inline graph to a file. The contents will be used to create a hash that will be used to make the name unique.

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

Definition at line 5407 of file util.cpp.

5408{
5409 DString fileName = baseName + md5str(content.view()) + extension;
5410 { // ==== start atomic section
5411 std::lock_guard lock(writeFileContents_lock);
5412 auto it=writeFileContents_set.find(fileName.str());
5413 exists = it!=writeFileContents_set.end();
5414 if (!exists)
5415 {
5416 writeFileContents_set.insert(fileName.str());
5417 if (auto file = Portable::openOutputStream(fileName); file.is_open())
5418 {
5419 file.write( content.data(), content.length() );
5420 file.close();
5421 }
5422 else
5423 {
5424 err("Could not open file {} for writing\n",fileName);
5425 return DString();
5426 }
5427 }
5428 } // ==== end atomic section
5429 return fileName;
5430}
static std::mutex writeFileContents_lock
Definition util.cpp:5404

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

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

◆ writeMarkerList() [1/2]

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

Definition at line 781 of file util.cpp.

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

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

◆ writeMarkerList() [2/2]

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

Definition at line 758 of file util.cpp.

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

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

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

◆ writeTypeConstraints()

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

Definition at line 4289 of file util.cpp.

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

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

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

Variable Documentation

◆ constScope

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

Definition at line 379 of file util.cpp.

Referenced by removeRedundantWhiteSpace().

◆ g_charAroundSpace

CharAroundSpace g_charAroundSpace
static

Definition at line 424 of file util.cpp.

Referenced by removeRedundantWhiteSpace().

◆ g_extLookup

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

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

Referenced by getLanguageFromCodeLang(), and updateLanguageMapping().

◆ g_matchArgsMutex

std::mutex g_matchArgsMutex
static

Definition at line 1486 of file util.cpp.

Referenced by matchArgument2().

◆ g_usedNames

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

Definition at line 2859 of file util.cpp.

Referenced by convertNameToFile().

◆ g_usedNamesCount

int g_usedNamesCount =1
static

Definition at line 2861 of file util.cpp.

Referenced by convertNameToFile().

◆ g_usedNamesMutex

std::mutex g_usedNamesMutex
static

Definition at line 2860 of file util.cpp.

Referenced by convertNameToFile().

◆ hex

const char* hex = "0123456789ABCDEF"
static

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

Referenced by removeRedundantWhiteSpace().

◆ staticScope

const char staticScope[] = { 's', 't', 'a', 't', 'i', 'c', ' ' }
static

Definition at line 383 of file util.cpp.

Referenced by removeRedundantWhiteSpace().

◆ virtualScope

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

Definition at line 381 of file util.cpp.

Referenced by removeRedundantWhiteSpace().

◆ volatileScope

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

Definition at line 380 of file util.cpp.

Referenced by removeRedundantWhiteSpace().

◆ writeFileContents_lock

std::mutex writeFileContents_lock
static

Definition at line 5404 of file util.cpp.

Referenced by writeInlineGraph().

◆ writeFileContents_set

StringUnorderedSet writeFileContents_set
static

Definition at line 5405 of file util.cpp.

Referenced by cleanupInlineGraphs(), and writeInlineGraph().