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

Go to the source code of this file.

Classes

struct  CharAroundSpace
struct  CharAroundSpace::CharElem
struct  FindFileCacheElem
 Cache element for the file name to FileDef mapping cache. More...
struct  Lang2ExtMap
struct  has_insertion_op< T, typename >
struct  has_insertion_op< T, std::void_t< decltype(std::declval< T & >()<< std::declval< const QCString & >())> >

Macros

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

Functions

QCString removeAnonymousScopes (const QCString &str)
QCString replaceAnonymousScopes (const QCString &s, const QCString &replacement)
QCString stripAnonymousNamespaceScope (const QCString &s)
void writePageRef (OutputList &ol, const QCString &cn, const QCString &mn)
QCString generateMarker (int id)
QCString removeLongPathMarker (QCString path)
static QCString stripFromPath (const QCString &p, const StringVector &l)
QCString stripFromPath (const QCString &path)
QCString stripFromIncludePath (const QCString &path)
EntryType guessSection (const QCString &name)
QCString resolveTypeDef (const Definition *context, const QCString &qualifiedName, const Definition **typedefContext)
QCString removeRedundantWhiteSpace (const QCString &s)
int findParameterList (const QCString &name)
 Returns the position in the string where a function parameter list begins, or -1 if one is not found.
bool rightScopeMatch (const QCString &scope, const QCString &name)
bool leftScopeMatch (const QCString &scope, const QCString &name)
void linkifyText (const TextGeneratorIntf &out, const QCString &text, const LinkifyTextOptions &options)
void writeMarkerList (OutputList &ol, const std::string &markerText, size_t numMarkers, std::function< void(size_t)> replaceFunc)
QCString writeMarkerList (const std::string &markerText, size_t numMarkers, std::function< QCString(size_t)> replaceFunc)
void writeExamples (OutputList &ol, const ExampleList &list)
QCString inlineArgListToDoc (const ArgumentList &al)
QCString inlineTemplateArgListToDoc (const ArgumentList &al)
QCString argListToString (const ArgumentList &al, bool useCanonicalType, bool showDefVals)
QCString tempArgListToString (const ArgumentList &al, SrcLangExt lang, bool includeDefault)
static void filterCRLF (std::string &contents)
static QCString getFilterFromList (const QCString &name, const StringVector &filterList, bool &found)
QCString getFileFilter (const QCString &name, bool isSourceCode)
bool transcodeCharacterStringToUTF8 (std::string &input, const char *inputEncoding)
QCString fileToString (const QCString &name, bool filter, bool isSourceCode)
void trimBaseClassScope (const BaseClassList &bcl, QCString &s, int level=0)
static void stripIrrelevantString (QCString &target, const QCString &str, bool insideTemplate)
void stripIrrelevantConstVolatile (QCString &s, bool insideTemplate)
static QCString stripDeclKeywords (const QCString &s)
static QCString extractCanonicalType (const Definition *d, const FileDef *fs, QCString type, SrcLangExt lang, bool insideTemplate)
static QCString getCanonicalTemplateSpec (const Definition *d, const FileDef *fs, const QCString &spec, SrcLangExt lang)
static QCString getCanonicalTypeForIdentifier (const Definition *d, const FileDef *fs, const QCString &word, SrcLangExt lang, QCString *tSpec, int count=0)
static QCString extractCanonicalArgType (const Definition *d, const FileDef *fs, const Argument &arg, SrcLangExt lang)
static bool matchCanonicalTypes (const Definition *srcScope, const FileDef *srcFileScope, const QCString &srcType, const Definition *dstScope, const FileDef *dstFileScope, const QCString &dstType, SrcLangExt lang)
static bool matchArgument2 (const Definition *srcScope, const FileDef *srcFileScope, Argument &srcA, const Definition *dstScope, const FileDef *dstFileScope, Argument &dstA, SrcLangExt lang)
bool matchArguments2 (const Definition *srcScope, const FileDef *srcFileScope, const QCString &srcReturnType, const ArgumentList *srcAl, const Definition *dstScope, const FileDef *dstFileScope, const QCString &dstReturnType, const ArgumentList *dstAl, bool checkCV, SrcLangExt lang)
void mergeArguments (ArgumentList &srcAl, ArgumentList &dstAl, bool forceNameOverwrite)
bool matchTemplateArguments (const ArgumentList &srcAl, const ArgumentList &dstAl)
GetDefResult getDefs (const GetDefInput &input)
static bool getScopeDefs (const QCString &docScope, const QCString &scope, ClassDef *&cd, ConceptDef *&cnd, NamespaceDef *&nd, ModuleDef *&modd)
static bool isLowerCase (QCString &s)
bool resolveRef (const QCString &scName, const QCString &name, bool inSeeBlock, const Definition **resContext, const MemberDef **resMember, SrcLangExt lang, bool lookForSpecialization, const FileDef *currentFile, bool checkScope)
QCString linkToText (SrcLangExt lang, const QCString &link, bool isFileName)
bool resolveLink (const QCString &scName, const QCString &lr, bool, const Definition **resContext, QCString &resAnchor, SrcLangExt lang, const QCString &prefix)
void generateFileRef (OutputList &ol, const QCString &name, const QCString &text)
FileDeffindFileDef (const FileNameLinkedMap *fnMap, const QCString &n, bool &ambig)
QCString findFilePath (const QCString &file, bool &ambig)
QCString showFileDefMatches (const FileNameLinkedMap *fnMap, const QCString &n)
QCString substituteKeywords (const QCString &file, const QCString &s, const KeywordSubstitutionList &keywords)
static QCString showDate (const QCString &fmt)
QCString projectLogoFile ()
static QCString projectLogoSize ()
QCString substituteKeywords (const QCString &file, const QCString &s, const QCString &title, const QCString &projName, const QCString &projNum, const QCString &projBrief)
int getPrefixIndex (const QCString &name)
bool getCaseSenseNames ()
QCString escapeCharsInString (const QCString &name, bool allowDots, bool allowUnderscore)
QCString unescapeCharsInString (const QCString &s)
QCString convertNameToFile (const QCString &name, bool allowDots, bool allowUnderscore)
QCString generateAnonymousAnchor (const QCString &fileName, int count)
QCString relativePathToRoot (const QCString &name)
QCString determineAbsoluteIncludeName (const QCString &curFile, const QCString &incFileName)
void createSubDirs (const Dir &d)
void clearSubDirs (const Dir &d)
void extractNamespaceName (const QCString &scopeName, QCString &className, QCString &namespaceName, bool allowEmptyClass)
QCString insertTemplateSpecifierInScope (const QCString &scope, const QCString &templ)
QCString stripScope (const QCString &name)
QCString convertToId (const QCString &s)
QCString correctId (const QCString &s)
QCString convertToXML (const QCString &s, bool keepEntities, const bool citeEntry)
QCString convertToHtml (const QCString &s, bool keepEntities)
QCString convertToJSString (const QCString &s, bool keepEntities, bool singleQuotes)
QCString convertCharEntitiesToUTF8 (const QCString &str)
QCString getOverloadDocs ()
void addMembersToMemberGroup (MemberList *ml, MemberGroupList *pMemberGroups, const Definition *context)
int extractClassNameFromType (const QCString &type, int &pos, QCString &name, QCString &templSpec, SrcLangExt lang)
QCString normalizeNonTemplateArgumentsInString (const QCString &name, const Definition *context, const ArgumentList &formalArgs)
QCString substituteTemplateArgumentsInString (const QCString &nm, const ArgumentList &formalArgs, const ArgumentList *actualArgs)
QCString stripTemplateSpecifiersFromScope (const QCString &fullName, bool parentOnly, QCString *pLastScopeStripped, QCString scopeName, bool allowArtificial)
QCString mergeScopes (const QCString &leftScope, const QCString &rightScope)
int getScopeFragment (const QCString &s, int p, int *l)
PageDefaddRelatedPage (const QCString &name, const QCString &ptitle, const QCString &doc, const QCString &fileName, int docLine, int startLine, const RefItemVector &sli, GroupDef *gd, const TagInfo *tagInfo, bool xref, SrcLangExt lang)
void addRefItem (const RefItemVector &sli, const QCString &key, const QCString &prefix, const QCString &name, const QCString &title, const QCString &args, const Definition *scope)
static ModuleDeffindModuleDef (const Definition *d)
static bool recursivelyAddGroupListToTitle (OutputList &ol, const Definition *d, bool root)
void addGroupListToTitle (OutputList &ol, const Definition *d)
bool checkExtension (const QCString &fName, const QCString &ext)
void addHtmlExtensionIfMissing (QCString &fName)
QCString stripExtensionGeneral (const QCString &fName, const QCString &ext)
QCString stripExtension (const QCString &fName)
QCString stripPath (const QCString &s)
QCString makeBaseName (const QCString &name, const QCString &ext)
bool containsWord (const QCString &str, const char *word)
 returns TRUE iff string s contains word w
bool findAndRemoveWord (QCString &sentence, const char *word)
 removes occurrences of whole word from sentence, while keeps internal spaces and reducing multiple sequences of spaces.
QCString stripLeadingAndTrailingEmptyLines (const QCString &s, int &docLine)
 Special version of QCString::stripWhiteSpace() that only strips completely blank lines.
bool updateLanguageMapping (const QCString &extension, const QCString &language)
void initDefaultExtensionMapping ()
void addCodeOnlyMappings ()
SrcLangExt getLanguageFromFileName (const QCString &fileName, SrcLangExt defLang)
SrcLangExt getLanguageFromCodeLang (QCString &fileName)
 Routine to handle the language attribute of the \code command.
QCString getFileNameExtension (const QCString &fn)
static MemberDefgetMemberFromSymbol (const Definition *scope, const FileDef *fileScope, const QCString &n)
bool checkIfTypedef (const Definition *scope, const FileDef *fileScope, const QCString &n)
static int nextUTF8CharPosition (const QCString &utf8Str, uint32_t len, uint32_t startPos)
QCString parseCommentAsText (const Definition *scope, const MemberDef *md, const QCString &doc, const QCString &fileName, int lineNr)
QCString parseCommentAsHtml (const Definition *scope, const MemberDef *member, const QCString &doc, const QCString &fileName, int lineNr)
void writeTypeConstraints (OutputList &ol, const Definition *d, const ArgumentList &al)
void stackTrace ()
static void transcodeCharacterBuffer (const QCString &fileName, std::string &contents, const QCString &inputEncoding, const QCString &outputEncoding)
bool readInputFile (const QCString &fileName, std::string &contents, bool filter, bool isSourceCode)
 read a file name fileName and optionally filter and transcode it
QCString filterTitle (const QCString &title)
template<class PatternList, class PatternElem, typename PatternGet = QCString(*)(const PatternElem &)>
bool genericPatternMatch (const FileInfo &fi, const PatternList &patList, PatternElem &elem, PatternGet getter)
bool patternMatch (const FileInfo &fi, const StringVector &patList)
QCString getEncoding (const FileInfo &fi)
QCString externalLinkTarget (const bool parent)
QCString createHtmlUrl (const QCString &relPath, const QCString &ref, bool href, bool isLocalFile, const QCString &targetFileName, const QCString &anchor)
QCString externalRef (const QCString &relPath, const QCString &ref, bool href)
QCString replaceColorMarkers (const QCString &str)
 Replaces any markers of the form ##AA in input string str by new markers of the form #AABBCC, where #AABBCC represents a valid color, based on the intensity represented by hex number AA and the current HTML_COLORSTYLE_* settings.
bool copyFile (const QCString &src, const QCString &dest)
 Copies the contents of file with name src to the newly created file with name dest.
int lineBlock (const QCString &text, const QCString &marker)
 Returns the line number of the line following the line with the marker.
QCString langToString (SrcLangExt lang)
 Returns a string representation of lang.
QCString getLanguageSpecificSeparator (SrcLangExt lang, bool classScope)
 Returns the scope separator to use given the programming language lang.
bool isURL (const QCString &url)
 Checks whether the given url starts with a supported protocol.
QCString correctURL (const QCString &url, const QCString &relPath)
 Corrects URL url according to the relative path relPath.
bool protectionLevelVisible (Protection prot)
QCString stripIndentation (const QCString &s, bool skipFirstLine)
void stripIndentationVerbatim (QCString &doc, const int indentationLevel, bool skipFirstLine)
bool fileVisibleInIndex (const FileDef *fd, bool &genSourceFile)
QCString extractDirection (QCString &docs)
 Strip the direction part from docs and return it as a string in canonical form.
void convertProtectionLevel (MemberListType inListType, Protection inProt, MemberListType *outListType1, MemberListType *outListType2)
 Computes for a given list type inListType, which are the the corresponding list type(s) in the base class that are to be added to this list.
bool mainPageHasTitle ()
QCString getDotImageExtension ()
bool openOutputFile (const QCString &outFile, std::ofstream &f)
static bool keyWordsFortranC (const char *contents)
bool recognizeFixedForm (const QCString &contents, FortranFormat format)
FortranFormat convertFileNameFortranParserCode (QCString fn)
QCString selectBlocks (const QCString &s, const SelectionBlockList &blockList, const SelectionMarkerInfo &markerInfo)
 remove disabled blocks and all block markers from s and return the result as a string
void checkBlocks (const QCString &s, const QCString fileName, const SelectionMarkerInfo &markerInfo)
QCString removeEmptyLines (const QCString &s)
StringVector split (const std::string &s, const std::string &delimiter)
 split input string s by string delimiter delimiter.
StringVector split (const std::string &s, const reg::Ex &delimiter)
 split input string s by regular expression delimiter delimiter.
int findIndex (const StringVector &sv, const std::string &s)
 find the index of a string in a vector of strings, returns -1 if the string could not be found
int findIndex (const std::string &s, const reg::Ex &re)
 find the index of the first occurrence of pattern re in a string s returns -1 if the pattern could not be found
std::string join (const StringVector &sv, const std::string &delimiter)
 create a string where the string in the vector are joined by the given delimiter
QCString integerToAlpha (int n, bool upper)
QCString integerToRoman (int n, bool upper)
QCString detab (const QCString &s, size_t &refIndent)
QCString getProjectId ()
int computeQualifiedIndex (const QCString &name)
 Return the index of the last :: in the string name that is still before the first <.
void mergeMemberOverrideOptions (MemberDefMutable *md1, MemberDefMutable *md2)
size_t updateColumnCount (const char *s, size_t col)
QCString mangleCSharpGenericName (const QCString &name)
QCString demangleCSharpGenericName (const QCString &name, const QCString &templArgs)
QCString extractBeginRawStringDelimiter (const char *rawStart)
QCString extractEndRawStringDelimiter (const char *rawEnd)
QCString writeFileContents (const QCString &baseName, const QCString &extension, const QCString &content, bool &exists)
 Thread-safe function to write a string to a file.
void cleanupInlineGraph ()
template<class T>
const char * writeHtmlEntity (T &result, const char *s, HtmlEntityMapperFunc &&mapper, const char *fallback)
template const char * writeHtmlEntity< QCString > (QCString &t, const char *s, HtmlEntityMapperFunc &&mapper, const char *fallback)
template const char * writeHtmlEntity< TextStream > (TextStream &t, const char *s, HtmlEntityMapperFunc &&mapper, const char *fallback)

Variables

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

Macro Definition Documentation

◆ ENABLE_TRACINGSUPPORT

#define ENABLE_TRACINGSUPPORT   0

Definition at line 80 of file util.cpp.

◆ HEXTONUM

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

Referenced by replaceColorMarkers().

◆ MATCH

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

Definition at line 1930 of file util.cpp.

Referenced by matchArgument2(), and matchArguments2().

◆ NOMATCH

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

Definition at line 1931 of file util.cpp.

Referenced by matchArgument2(), and matchArguments2().

◆ REL_PATH_TO_ROOT

#define REL_PATH_TO_ROOT   "../../"

Definition at line 94 of file util.cpp.

Referenced by relativePathToRoot().

Function Documentation

◆ addCodeOnlyMappings()

void addCodeOnlyMappings ( )

Definition at line 5229 of file util.cpp.

5230{
5231 updateLanguageMapping(".xml", "xml");
5232 updateLanguageMapping(".sql", "sql");
5233}
bool updateLanguageMapping(const QCString &extension, const QCString &language)
Definition util.cpp:5130

References updateLanguageMapping().

Referenced by generateOutput().

◆ addGroupListToTitle()

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

◆ addHtmlExtensionIfMissing()

void addHtmlExtensionIfMissing ( QCString & fName)

Definition at line 4946 of file util.cpp.

4947{
4948 if (fName.isEmpty()) return;
4949 int i_fs = fName.findRev('/');
4950 int i_bs = fName.findRev('\\');
4951 int i = fName.find('.',std::max({ i_fs, i_bs ,0})); // search for . after path part
4952 if (i==-1)
4953 {
4955 }
4956}
static QCString htmlFileExtension
Definition doxygen.h:122
int find(char c, int index=0, bool cs=TRUE) const
Definition qcstring.cpp:43
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:167
int findRev(char c, int index=-1, bool cs=TRUE) const
Definition qcstring.cpp:96

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

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

◆ addMembersToMemberGroup()

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

Definition at line 4122 of file util.cpp.

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

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

◆ addRefItem()

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

Definition at line 4849 of file util.cpp.

4852{
4853 //printf("addRefItem(sli=%d,key=%s,prefix=%s,name=%s,title=%s,args=%s)\n",(int)sli.size(),key,prefix,name,title,args);
4854 if (!key.isEmpty() && key[0]!='@') // check for @ to skip anonymous stuff (see bug427012)
4855 {
4856 for (RefItem *item : sli)
4857 {
4858 item->setPrefix(prefix);
4859 item->setScope(scope);
4860 item->setName(name);
4861 item->setTitle(title);
4862 item->setArgs(args);
4863 item->setGroup(key);
4864 }
4865 }
4866}
constexpr auto prefix
Definition anchor.cpp:44
This struct represents an item in the list of references.
Definition reflist.h:32

References QCString::isEmpty(), and prefix.

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

◆ addRelatedPage()

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

Definition at line 4719 of file util.cpp.

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

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

◆ argListToString()

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

Definition at line 1254 of file util.cpp.

1255{
1256 QCString result;
1257 if (!al.hasParameters()) return result;
1258 result+="(";
1259 for (auto it = al.begin() ; it!=al.end() ;)
1260 {
1261 Argument a = *it;
1262 QCString type1 = useCanonicalType && !a.canType.isEmpty() ? a.canType : a.type;
1263 QCString type2;
1264 int i=type1.find(")("); // hack to deal with function pointers
1265 if (i!=-1)
1266 {
1267 type2=type1.mid(i);
1268 type1=type1.left(i);
1269 }
1270 if (!a.attrib.isEmpty())
1271 {
1272 result+=a.attrib+" ";
1273 }
1274 if (!a.name.isEmpty() || !a.array.isEmpty())
1275 {
1276 result+= type1+" "+a.name+type2+a.array;
1277 }
1278 else
1279 {
1280 result+= type1+type2;
1281 }
1282 if (!a.defval.isEmpty() && showDefVals)
1283 {
1284 result+="="+a.defval;
1285 }
1286 ++it;
1287 if (it!=al.end()) result+=", ";
1288 }
1289 result+=")";
1290 if (al.constSpecifier()) result+=" const";
1291 if (al.volatileSpecifier()) result+=" volatile";
1292 if (al.refQualifier()==RefQualifierType::LValue) result+=" &";
1293 else if (al.refQualifier()==RefQualifierType::RValue) result+=" &&";
1294 if (!al.trailingReturnType().isEmpty()) result+=al.trailingReturnType();
1295 if (al.pureSpecifier()) result+=" =0";
1296 return removeRedundantWhiteSpace(result);
1297}
RefQualifierType refQualifier() const
Definition arguments.h:116
bool pureSpecifier() const
Definition arguments.h:113
iterator end()
Definition arguments.h:94
bool hasParameters() const
Definition arguments.h:76
QCString trailingReturnType() const
Definition arguments.h:114
bool constSpecifier() const
Definition arguments.h:111
iterator begin()
Definition arguments.h:93
bool volatileSpecifier() const
Definition arguments.h:112
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:245
This class contains the information about the argument of a function or template.
Definition arguments.h:27
QCString type
Definition arguments.h:42
QCString name
Definition arguments.h:44
QCString defval
Definition arguments.h:46
QCString array
Definition arguments.h:45
QCString canType
Definition arguments.h:43
QCString attrib
Definition arguments.h:41
QCString removeRedundantWhiteSpace(const QCString &s)
Definition util.cpp:567

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

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

◆ checkBlocks()

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

Definition at line 6544 of file util.cpp.

6545{
6546 if (s.isEmpty()) return;
6547
6548 const char *p = s.data();
6549 char c = 0;
6550 while ((c=*p))
6551 {
6552 if (c==markerInfo.markerChar) // potential start of marker
6553 {
6554 if (qstrncmp(p,markerInfo.beginStr,markerInfo.beginLen)==0) // start of begin marker
6555 {
6556 size_t len = markerInfo.beginLen;
6557 bool negate = *(p+len)=='!';
6558 if (negate) len++;
6559 p += len;
6560 QCString marker;
6561 while (*p)
6562 {
6563 if (markerInfo.closeLen==0 && *p=='\n') // matching end of line
6564 {
6565 warn(fileName,-1,"Remaining begin replacement with marker '{}'",marker);
6566 break;
6567 }
6568 else if (markerInfo.closeLen!= 0 && qstrncmp(p,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6569 {
6570 p += markerInfo.closeLen;
6571 warn(fileName,-1,"Remaining begin replacement with marker '{}'",marker);
6572 break;
6573 }
6574 marker += *p;
6575 p++;
6576 }
6577 }
6578 else if (qstrncmp(p,markerInfo.endStr,markerInfo.endLen)==0) // start of end marker
6579 {
6580 size_t len = markerInfo.endLen;
6581 bool negate = *(p+len)=='!';
6582 if (negate) len++;
6583 p += len;
6584 QCString marker;
6585 while (*p)
6586 {
6587 if (markerInfo.closeLen==0 && *p=='\n') // matching end of line
6588 {
6589 warn(fileName,-1,"Remaining end replacement with marker '{}'",marker);
6590 break;
6591 }
6592 else if (markerInfo.closeLen!= 0 && qstrncmp(p,markerInfo.closeStr,markerInfo.closeLen)==0) // matching marker closing
6593 {
6594 p += markerInfo.closeLen;
6595 warn(fileName,-1,"Remaining end replacement with marker '{}'",marker);
6596 break;
6597 }
6598 marker += *p;
6599 p++;
6600 }
6601 }
6602 }
6603 p++;
6604 }
6605}
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition qcstring.h:176
int qstrncmp(const char *str1, const char *str2, size_t len)
Definition qcstring.h:75
size_t beginLen
Definition util.h:237
const char * closeStr
Definition util.h:240
const char * beginStr
Definition util.h:236
size_t closeLen
Definition util.h:241
const char * endStr
Definition util.h:238

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

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

◆ checkExtension()

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

Definition at line 4941 of file util.cpp.

4942{
4943 return fName.right(ext.length())==ext;
4944}

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

Referenced by copyLatexStyleSheet(), and extraLatexStyleSheet().

◆ checkIfTypedef()

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

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

Definition at line 5339 of file util.cpp.

5340{
5341 MemberDef *bestMatch = getMemberFromSymbol(scope,fileScope,n);
5342
5343 if (bestMatch && bestMatch->isTypedef())
5344 return TRUE; // closest matching symbol is a typedef
5345 else
5346 return FALSE;
5347}
A model of a class/file/namespace member symbol.
Definition memberdef.h:48
virtual bool isTypedef() const =0
static MemberDef * getMemberFromSymbol(const Definition *scope, const FileDef *fileScope, const QCString &n)
Definition util.cpp:5287

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

Referenced by isVarWithConstructor().

◆ cleanupInlineGraph()

void cleanupInlineGraph ( )

Definition at line 7012 of file util.cpp.

7013{
7014 if (Config_getBool(DOT_CLEANUP))
7015 {
7016 for (const auto& fileName: writeFileContents_set)
7017 {
7018 Dir().remove(qPrint(fileName));
7019 }
7020 }
7021}
Class representing a directory in the file system.
Definition dir.h:75
bool remove(const std::string &path, bool acceptsAbsPath=true) const
Definition dir.cpp:314
#define Config_getBool(name)
Definition config.h:33
const char * qPrint(const char *s)
Definition qcstring.h:691
static StringUnorderedSet writeFileContents_set
Definition util.cpp:6971

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

Referenced by generateOutput().

◆ clearSubDirs()

void clearSubDirs ( const Dir & d)

Definition at line 3688 of file util.cpp.

3689{
3690 if (Config_getBool(CREATE_SUBDIRS))
3691 {
3692 // remove empty subdirectories
3693 int createSubdirsLevelPow2 = 1 << Config_getInt(CREATE_SUBDIRS_LEVEL);
3694 for (int l1=0;l1<16;l1++)
3695 {
3696 QCString subdir;
3697 subdir.sprintf("d%x",l1);
3698 for (int l2=0; l2 < createSubdirsLevelPow2; l2++)
3699 {
3700 QCString subsubdir;
3701 subsubdir.sprintf("d%x/d%02x",l1,l2);
3702 if (d.exists(subsubdir.str()) && d.isEmpty(subsubdir.str()))
3703 {
3704 d.rmdir(subsubdir.str());
3705 }
3706 }
3707 if (d.exists(subdir.str()) && d.isEmpty(subdir.str()))
3708 {
3709 d.rmdir(subdir.str());
3710 }
3711 }
3712 }
3713}
bool isEmpty(const std::string &subdir) const
Definition dir.cpp:263
bool rmdir(const std::string &path, bool acceptsAbsPath=true) const
Definition dir.cpp:309
bool exists() const
Definition dir.cpp:257
const std::string & str() const
Definition qcstring.h:556
QCString & sprintf(const char *format,...)
Definition qcstring.cpp:29
#define Config_getInt(name)
Definition config.h:34

References Config_getBool, Config_getInt, Dir::exists(), Dir::isEmpty(), Dir::rmdir(), QCString::sprintf(), and QCString::str().

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

◆ computeQualifiedIndex()

int computeQualifiedIndex ( const QCString & name)

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

Definition at line 6846 of file util.cpp.

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

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

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

◆ containsWord()

bool containsWord ( const QCString & str,
const char * word )

returns TRUE iff string s contains word w

Definition at line 4995 of file util.cpp.

4996{
4997 if (str.isEmpty() || word==nullptr) return false;
4998 static const reg::Ex re(R"(\a+)");
4999 std::string s = str.str();
5000 for (reg::Iterator it(s,re) ; it!=reg::Iterator() ; ++it)
5001 {
5002 if (it->str()==word) return true;
5003 }
5004 return false;
5005}
Class representing a regular expression.
Definition regex.h:39
Class to iterate through matches.
Definition regex.h:230

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

◆ convertCharEntitiesToUTF8()

QCString convertCharEntitiesToUTF8 ( const QCString & str)

Definition at line 4072 of file util.cpp.

4073{
4074 if (str.isEmpty()) return QCString();
4075
4076 std::string s = str.data();
4077 static const reg::Ex re(R"(&\a\w*;)");
4078 reg::Iterator it(s,re);
4080
4081 QCString result;
4082 result.reserve(str.length()+32);
4083 size_t p=0, i=0, l=0;
4084 for (; it!=end ; ++it)
4085 {
4086 const auto &match = *it;
4087 p = match.position();
4088 l = match.length();
4089 if (p>i)
4090 {
4091 result+=s.substr(i,p-i);
4092 }
4093 QCString entity(match.str());
4095 const char *code=nullptr;
4096 if (symType!=HtmlEntityMapper::Sym_Unknown && (code=HtmlEntityMapper::instance().utf8(symType)))
4097 {
4098 result+=code;
4099 }
4100 else
4101 {
4102 result+=entity;
4103 }
4104 i=p+l;
4105 }
4106 result+=s.substr(i);
4107 //printf("convertCharEntitiesToUTF8(%s)->%s\n",qPrint(s),qPrint(result));
4108 return result;
4109}
static HtmlEntityMapper & instance()
Returns the one and only instance of the HTML entity mapper.
SymType name2sym(const QCString &symName) const
Give code of the requested HTML entity name.
void reserve(size_t size)
Reserve space for size bytes without changing the string contents.
Definition qcstring.h:189
bool match(std::string_view str, Match &match, const Ex &re)
Matches a given string str for a match against regular expression re.
Definition regex.cpp:855

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

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

◆ convertFileNameFortranParserCode()

FortranFormat convertFileNameFortranParserCode ( QCString fn)

Definition at line 6418 of file util.cpp.

6419{
6421 QCString parserName = Doxygen::parserManager->getParserName(ext);
6422
6423 if (parserName == "fortranfixed") return FortranFormat::Fixed;
6424 else if (parserName == "fortranfree") return FortranFormat::Free;
6425
6427}
static ParserManager * parserManager
Definition doxygen.h:129
QCString getFileNameExtension(const QCString &fn)
Definition util.cpp:5277

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

Referenced by convertCppComments().

◆ convertNameToFile()

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

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

Definition at line 3525 of file util.cpp.

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

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

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

◆ convertProtectionLevel()

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

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

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

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

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

Definition at line 6251 of file util.cpp.

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

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

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

◆ convertToHtml()

QCString convertToHtml ( const QCString & s,
bool keepEntities )

Converts a string to a HTML-encoded string

Definition at line 3988 of file util.cpp.

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

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

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

◆ convertToId()

QCString convertToId ( const QCString & s)

Converts a string to a HTML id string

Definition at line 3893 of file util.cpp.

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

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

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

◆ convertToJSString()

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

Definition at line 4048 of file util.cpp.

4049{
4050 if (s.isEmpty()) return s;
4051 QCString result;
4052 result.reserve(s.length()+32);
4053 const char *p=s.data();
4054 char c = 0;
4055 while ((c=*p++))
4056 {
4057 switch (c)
4058 {
4059 case '"': if (!singleQuotes) result+="\\\""; else result+=c;
4060 break;
4061 case '\'': if (singleQuotes) result+="\\\'"; else result+=c;
4062 break;
4063 case '\\': if (*p=='u' && *(p+1)=='{') result+="\\"; // keep \u{..} unicode escapes
4064 else result+="\\\\";
4065 break;
4066 default: result+=c; break;
4067 }
4068 }
4069 return keepEntities ? result : convertCharEntitiesToUTF8(result);
4070}
QCString convertCharEntitiesToUTF8(const QCString &str)
Definition util.cpp:4072

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

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

◆ convertToXML()

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

Converts a string to an XML-encoded string

Definition at line 3933 of file util.cpp.

3934{
3935 if (s.isEmpty()) return s;
3936 QCString result;
3937 result.reserve(s.length()+32);
3938 const char *p = s.data();
3939 char c = 0;
3940 while ((c=*p++))
3941 {
3942 switch (c)
3943 {
3944 case '<': result+="&lt;"; break;
3945 case '>': result+="&gt;"; break;
3946 case '&': if (keepEntities)
3947 {
3948 const char *e=p;
3949 char ce = 0;
3950 while ((ce=*e++))
3951 {
3952 if (ce==';' || (!(isId(ce) || ce=='#'))) break;
3953 }
3954 if (ce==';') // found end of an entity
3955 {
3956 // copy entry verbatim
3957 result+=c;
3958 while (p<e) result+=*p++;
3959 }
3960 else
3961 {
3962 result+="&amp;";
3963 }
3964 }
3965 else if (citeEntry)
3966 {
3967 p = writeHtmlEntity(result, p-1, [](HtmlEntityMapper::SymType symType) { return HtmlEntityMapper::instance().xml(symType); }, "&amp;");
3968 }
3969 else
3970 {
3971 result+="&amp;";
3972 }
3973 break;
3974 case '\'': result+="&apos;"; break;
3975 case '"': result+="&quot;"; break;
3976 case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
3977 case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18:
3978 case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26:
3979 case 27: case 28: case 29: case 30: case 31:
3980 break; // skip invalid XML characters (see http://www.w3.org/TR/2000/REC-xml-20001006#NT-Char)
3981 default: result+=c; break;
3982 }
3983 }
3984 return result;
3985}
const char * xml(SymType symb) const
Access routine to the XML code of the HTML entity.
const char * writeHtmlEntity(T &result, const char *s, HtmlEntityMapperFunc &&mapper, const char *fallback)
Definition util.cpp:7034

References QCString::data(), HtmlEntityMapper::instance(), QCString::isEmpty(), isId(), QCString::length(), QCString::reserve(), 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()

◆ correctId()

QCString correctId ( const QCString & s)

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

Definition at line 3926 of file util.cpp.

3927{
3928 if (s.isEmpty()) return s;
3929 return "a" + s;
3930}

References QCString::isEmpty().

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

◆ correctURL()

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

Corrects URL url according to the relative path relPath.

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

Definition at line 5947 of file util.cpp.

5948{
5949 QCString result = url;
5950 if (!relPath.isEmpty() && !isURL(url))
5951 {
5952 result.prepend(relPath);
5953 }
5954 return result;
5955}
bool isURL(const QCString &url)
Checks whether the given url starts with a supported protocol.
Definition util.cpp:5935

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

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

◆ createHtmlUrl()

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

Definition at line 5760 of file util.cpp.

5766{
5767 QCString url;
5768 if (!ref.isEmpty())
5769 {
5770 url = externalRef(relPath,ref,href);
5771 }
5772 if (!targetFileName.isEmpty())
5773 {
5774 QCString fn = targetFileName;
5775 if (ref.isEmpty())
5776 {
5777 if (!anchor.isEmpty() && isLocalFile)
5778 {
5779 fn=""; // omit file name for local links
5780 }
5781 else
5782 {
5783 url = relPath;
5784 }
5785 }
5786 url+=fn;
5787 }
5788 if (!anchor.isEmpty())
5789 {
5790 if (!url.endsWith("=")) url+="#";
5791 url+=anchor;
5792 }
5793 //printf("createHtmlUrl(relPath=%s,local=%d,target=%s,anchor=%s)=%s\n",qPrint(relPath),isLocalFile,qPrint(targetFileName),qPrint(anchor),qPrint(url));
5794 return url;
5795}
QCString externalRef(const QCString &relPath, const QCString &ref, bool href)
Definition util.cpp:5797

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

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

◆ createSubDirs()

void createSubDirs ( const Dir & d)

Definition at line 3661 of file util.cpp.

3662{
3663 if (Config_getBool(CREATE_SUBDIRS))
3664 {
3665 // create up to 4096 subdirectories
3666 int createSubdirsLevelPow2 = 1 << Config_getInt(CREATE_SUBDIRS_LEVEL);
3667 for (int l1=0; l1<16; l1++)
3668 {
3669 QCString subdir;
3670 subdir.sprintf("d%x",l1);
3671 if (!d.exists(subdir.str()) && !d.mkdir(subdir.str()))
3672 {
3673 term("Failed to create output directory '{}'\n",subdir);
3674 }
3675 for (int l2=0; l2<createSubdirsLevelPow2; l2++)
3676 {
3677 QCString subsubdir;
3678 subsubdir.sprintf("d%x/d%02x",l1,l2);
3679 if (!d.exists(subsubdir.str()) && !d.mkdir(subsubdir.str()))
3680 {
3681 term("Failed to create output directory '{}'\n",subsubdir);
3682 }
3683 }
3684 }
3685 }
3686}
bool mkdir(const std::string &path, bool acceptsAbsPath=true) const
Definition dir.cpp:295
#define term(fmt,...)
Definition message.h:137

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

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

◆ demangleCSharpGenericName()

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

Definition at line 6945 of file util.cpp.

6946{
6947 QCString result=name;
6948 if (result.endsWith("-g"))
6949 {
6950 int idx = result.find('-');
6951 result = result.left(idx)+templArgs;
6952 }
6953 return result;
6954}

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

Referenced by ClassDefImpl::className().

◆ detab()

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

Definition at line 6742 of file util.cpp.

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

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

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

◆ determineAbsoluteIncludeName()

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

Definition at line 3621 of file util.cpp.

3622{
3623 bool searchIncludes = Config_getBool(SEARCH_INCLUDES);
3624 QCString absIncFileName = incFileName;
3625 FileInfo fi(curFile.str());
3626 if (fi.exists())
3627 {
3628 QCString absName = fi.dirPath(TRUE)+"/"+incFileName;
3629 FileInfo fi2(absName.str());
3630 if (fi2.exists())
3631 {
3632 absIncFileName=fi2.absFilePath();
3633 }
3634 else if (searchIncludes) // search in INCLUDE_PATH as well
3635 {
3636 const StringVector &includePath = Config_getList(INCLUDE_PATH);
3637 for (const auto &incPath : includePath)
3638 {
3639 FileInfo fi3(incPath);
3640 if (fi3.exists() && fi3.isDir())
3641 {
3642 absName = fi3.absFilePath()+"/"+incFileName;
3643 //printf("trying absName=%s\n",qPrint(absName));
3644 FileInfo fi4(absName.str());
3645 if (fi4.exists())
3646 {
3647 absIncFileName=fi4.absFilePath();
3648 break;
3649 }
3650 //printf( "absIncFileName = %s\n", qPrint(absIncFileName) );
3651 }
3652 }
3653 }
3654 //printf( "absIncFileName = %s\n", qPrint(absIncFileName) );
3655 }
3656 return absIncFileName;
3657}
Minimal replacement for QFileInfo.
Definition fileinfo.h:23
#define Config_getList(name)
Definition config.h:38
std::vector< std::string > StringVector
Definition containers.h:33

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

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

◆ escapeCharsInString()

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

Definition at line 3350 of file util.cpp.

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

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

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

◆ externalLinkTarget()

QCString externalLinkTarget ( const bool parent)

Definition at line 5749 of file util.cpp.

5750{
5751 bool extLinksInWindow = Config_getBool(EXT_LINKS_IN_WINDOW);
5752 if (extLinksInWindow)
5753 return "target=\"_blank\" ";
5754 else if (parent)
5755 return "target=\"_parent\" ";
5756 else
5757 return "";
5758}
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()

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

Definition at line 5797 of file util.cpp.

5798{
5799 QCString result;
5800 if (!ref.isEmpty())
5801 {
5802 auto it = Doxygen::tagDestinationMap.find(ref.str());
5804 {
5805 result = it->second;
5806 size_t l = result.length();
5807 if (!relPath.isEmpty() && l>0 && result.at(0)=='.')
5808 { // relative path -> prepend relPath.
5809 result.prepend(relPath);
5810 l+=relPath.length();
5811 }
5812 if (l>0 && result.at(l-1)!='/') result+='/';
5813 if (!href) result.append("\" ");
5814 }
5815 }
5816 else
5817 {
5818 result = relPath;
5819 }
5820 return result;
5821}
static StringMap tagDestinationMap
Definition doxygen.h:116
char & at(size_t i)
Returns a reference to the character at index i.
Definition qcstring.h:597
QCString & append(char c)
Definition qcstring.h:400

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

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

◆ extractBeginRawStringDelimiter()

QCString extractBeginRawStringDelimiter ( const char * rawStart)

Definition at line 6956 of file util.cpp.

6957{
6958 QCString text=rawStart;
6959 int i = text.find('"');
6960 assert(i!=-1);
6961 return text.mid(i+1,text.length()-i-2); // text=...R"xyz( -> delimiter=xyz
6962}

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

◆ extractCanonicalArgType()

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

Definition at line 1900 of file util.cpp.

1901{
1902 QCString type = arg.type.stripWhiteSpace();
1903 QCString name = arg.name;
1904 //printf("----- extractCanonicalArgType(type=%s,name=%s)\n",qPrint(type),qPrint(name));
1905 if ((type=="const" || type=="volatile") && !name.isEmpty())
1906 { // name is part of type => correct
1907 type+=" ";
1908 type+=name;
1909 }
1910 if (name=="const" || name=="volatile")
1911 { // name is part of type => correct
1912 if (!type.isEmpty()) type+=" ";
1913 type+=name;
1914 }
1915 if (!arg.array.isEmpty())
1916 {
1917 type+=arg.array;
1918 }
1919
1920 return extractCanonicalType(d,fs,type,lang,false);
1921}
static QCString extractCanonicalType(const Definition *d, const FileDef *fs, QCString type, SrcLangExt lang, bool insideTemplate)
Definition util.cpp:1814

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

Referenced by matchArgument2().

◆ extractCanonicalType()

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

Definition at line 1814 of file util.cpp.

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

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

Referenced by extractCanonicalArgType(), and getCanonicalTemplateSpec().

◆ extractClassNameFromType()

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

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

Definition at line 4240 of file util.cpp.

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

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

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

◆ extractDirection()

QCString extractDirection ( QCString & docs)

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

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

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

Definition at line 6200 of file util.cpp.

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

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

Referenced by inlineArgListToDoc().

◆ extractEndRawStringDelimiter()

QCString extractEndRawStringDelimiter ( const char * rawEnd)

Definition at line 6964 of file util.cpp.

6965{
6966 QCString text=rawEnd;
6967 return text.mid(1,text.length()-2); // text=)xyz" -> delimiter=xyz
6968}

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

◆ extractNamespaceName()

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

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

Definition at line 3718 of file util.cpp.

3721{
3722 int i=0, p=0;
3723 QCString clName=scopeName;
3724 NamespaceDef *nd = nullptr;
3725 if (!clName.isEmpty() && (nd=getResolvedNamespace(clName)) && getClass(clName)==nullptr)
3726 { // the whole name is a namespace (and not a class)
3727 namespaceName=nd->name();
3728 className.clear();
3729 goto done;
3730 }
3731 p=static_cast<int>(clName.length())-2;
3732 while (p>=0 && (i=clName.findRev("::",p))!=-1)
3733 // see if the first part is a namespace (and not a class)
3734 {
3735 //printf("Trying %s\n",qPrint(clName.left(i)));
3736 if (i>0 && (nd=getResolvedNamespace(clName.left(i))) && getClass(clName.left(i))==nullptr)
3737 {
3738 //printf("found!\n");
3739 namespaceName=nd->name();
3740 className=clName.right(clName.length()-i-2);
3741 goto done;
3742 }
3743 p=i-2; // try a smaller piece of the scope
3744 }
3745 //printf("not found!\n");
3746
3747 // not found, so we just have to guess.
3748 className=scopeName;
3749 namespaceName.clear();
3750
3751done:
3752 if (className.isEmpty() && !namespaceName.isEmpty() && !allowEmptyClass)
3753 {
3754 // class and namespace with the same name, correct to return the class.
3755 className=namespaceName;
3756 namespaceName.clear();
3757 }
3758 //printf("extractNamespace '%s' => '%s|%s'\n",qPrint(scopeName),
3759 // qPrint(className),qPrint(namespaceName));
3760 if (className.endsWith("-p"))
3761 {
3762 className = className.left(className.length()-2);
3763 }
3764 return;
3765}
An abstract interface of a namespace symbol.
ClassDef * getClass(const QCString &n)
NamespaceDef * getResolvedNamespace(const QCString &name)

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

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

◆ fileToString()

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

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

Definition at line 1494 of file util.cpp.

1495{
1496 if (name.isEmpty()) return QCString();
1497 bool fileOpened=false;
1498 if (name[0]=='-' && name[1]==0) // read from stdin
1499 {
1500 std::string contents;
1501 std::string line;
1502 while (getline(std::cin,line))
1503 {
1504 contents+=line+'\n';
1505 }
1506 return contents;
1507 }
1508 else // read from file
1509 {
1510 FileInfo fi(name.str());
1511 if (!fi.exists() || !fi.isFile())
1512 {
1513 err("file '{}' not found\n",name);
1514 return "";
1515 }
1516 std::string buf;
1517 fileOpened=readInputFile(name,buf,filter,isSourceCode);
1518 if (fileOpened)
1519 {
1520 addTerminalCharIfMissing(buf,'\n');
1521 return buf;
1522 }
1523 }
1524 if (!fileOpened)
1525 {
1526 err("cannot open file '{}' for reading\n",name);
1527 }
1528 return "";
1529}
void addTerminalCharIfMissing(std::string &s, char c)
Definition stringutil.h:84
bool readInputFile(const QCString &fileName, std::string &contents, bool filter, bool isSourceCode)
read a file name fileName and optionally filter and transcode it
Definition util.cpp:5574

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

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

◆ fileVisibleInIndex()

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

Definition at line 6111 of file util.cpp.

6112{
6113 bool allExternals = Config_getBool(ALLEXTERNALS);
6114 bool isDocFile = fd->isDocumentationFile();
6115 genSourceFile = !isDocFile && fd->generateSourceFile();
6116 return ( ((allExternals && fd->isLinkable()) ||
6118 ) &&
6119 !isDocFile
6120 );
6121}
virtual bool isLinkable() const =0
virtual bool isLinkableInProject() const =0
virtual bool generateSourceFile() const =0
virtual bool isDocumentationFile() const =0

References Config_getBool, FileDef::generateSourceFile(), FileDef::isDocumentationFile(), Definition::isLinkable(), and Definition::isLinkableInProject().

Referenced by countFiles(), dirHasVisibleChildren(), generateJSTree(), writeDirHierarchy(), writeDirTreeNode(), and DirDefImpl::writeFileList().

◆ filterCRLF()

void filterCRLF ( std::string & contents)
static

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

Definition at line 1355 of file util.cpp.

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

Referenced by readInputFile().

◆ filterTitle()

QCString filterTitle ( const QCString & title)

Definition at line 5654 of file util.cpp.

5655{
5656 std::string tf;
5657 std::string t = title.str();
5658 static const reg::Ex re(R"(%[a-z_A-Z]+)");
5659 reg::Iterator it(t,re);
5661 size_t p = 0;
5662 for (; it!=end ; ++it)
5663 {
5664 const auto &match = *it;
5665 size_t i = match.position();
5666 size_t l = match.length();
5667 if (i>p) tf+=t.substr(p,i-p);
5668 tf+=match.str().substr(1); // skip %
5669 p=i+l;
5670 }
5671 tf+=t.substr(p);
5672 return tf;
5673}

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

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

◆ findAndRemoveWord()

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

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

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

Definition at line 5011 of file util.cpp.

5012{
5013 static reg::Ex re(R"(\s*(<\a+>)\s*)");
5014 std::string s = sentence.str();
5015 reg::Iterator it(s,re);
5017 std::string result;
5018 bool found=false;
5019 size_t p=0;
5020 for ( ; it!=end ; ++it)
5021 {
5022 const auto match = *it;
5023 std::string part = match[1].str();
5024 if (part!=word)
5025 {
5026 size_t i = match.position();
5027 size_t l = match.length();
5028 result+=s.substr(p,i-p);
5029 result+=match.str();
5030 p=i+l;
5031 }
5032 else
5033 {
5034 found=true;
5035 size_t i = match[1].position();
5036 size_t l = match[1].length();
5037 result+=s.substr(p,i-p);
5038 p=i+l;
5039 }
5040 }
5041 result+=s.substr(p);
5042 sentence = QCString(result).simplifyWhiteSpace();
5043 return found;
5044}
QCString simplifyWhiteSpace() const
return a copy of this string with leading and trailing whitespace removed and multiple whitespace cha...
Definition qcstring.cpp:190

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

Referenced by isVarWithConstructor().

◆ findFileDef()

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

Definition at line 2904 of file util.cpp.

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

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

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

◆ findFilePath()

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

Definition at line 2996 of file util.cpp.

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

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

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

◆ findIndex() [1/2]

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

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

Definition at line 6684 of file util.cpp.

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

References reg::search().

◆ findIndex() [2/2]

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

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

Definition at line 6676 of file util.cpp.

6677{
6678 auto it = std::find(sv.begin(),sv.end(),s);
6679 return it!=sv.end() ? static_cast<int>(it-sv.begin()) : -1;
6680}

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

◆ findModuleDef()

ModuleDef * findModuleDef ( const Definition * d)
static

Definition at line 4868 of file util.cpp.

4869{
4870 ModuleDef *mod = nullptr;
4872 {
4873 const FileDef *fd = toFileDef(d);
4874 if (fd) mod = fd->getModuleDef();
4875 }
4877 {
4878 const ClassDef *cd = toClassDef(d);
4879 if (cd)
4880 {
4881 const FileDef *fd = cd->getFileDef();
4882 if (fd) mod = fd->getModuleDef();
4883 }
4884 }
4886 {
4887 const ConceptDef *cd = toConceptDef(d);
4888 if (cd)
4889 {
4890 const FileDef *fd = cd->getFileDef();
4891 if (fd) mod = fd->getModuleDef();
4892 }
4893 }
4894 return mod;
4895}
A abstract class representing of a compound symbol.
Definition classdef.h:104
virtual FileDef * getFileDef() const =0
Returns the namespace this compound is in, or 0 if it has a global scope.
virtual const FileDef * getFileDef() const =0
virtual DefType definitionType() const =0
virtual ModuleDef * getModuleDef() const =0
ClassDef * toClassDef(Definition *d)
ConceptDef * toConceptDef(Definition *d)
FileDef * toFileDef(Definition *d)
Definition filedef.cpp:1966

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

Referenced by recursivelyAddGroupListToTitle().

◆ findParameterList()

int findParameterList ( const QCString & name)

Returns the position in the string where a function parameter list begins, or -1 if one is not found.

Definition at line 825 of file util.cpp.

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

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

Referenced by resolveRef().

◆ generateAnonymousAnchor()

QCString generateAnonymousAnchor ( const QCString & fileName,
int count )

Definition at line 3579 of file util.cpp.

3580{
3581 QCString fn = stripFromPath(fileName)+":"+QCString().setNum(count);
3582 const int sig_size=16;
3583 uint8_t md5_sig[sig_size];
3584 MD5Buffer(fn.data(),static_cast<unsigned int>(fn.length()),md5_sig);
3585 char result[sig_size*3+2];
3586 char *p = result;
3587 *p++='@';
3588 for (int i=0;i<sig_size;i++)
3589 {
3590 static const char oct[]="01234567";
3591 uint8_t byte = md5_sig[i];
3592 *p++=oct[(byte>>6)&7];
3593 *p++=oct[(byte>>3)&7];
3594 *p++=oct[(byte>>0)&7];
3595 }
3596 *p='\0';
3597 return result;
3598}
QCString & setNum(short n)
Definition qcstring.h:463
static QCString stripFromPath(const QCString &p, const StringVector &l)
Definition util.cpp:298

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

◆ generateFileRef()

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

Definition at line 2876 of file util.cpp.

2877{
2878 //printf("generateFileRef(%s,%s)\n",name,text);
2879 QCString linkText = text.isEmpty() ? text : name;
2880 //FileInfo *fi;
2881 bool ambig = false;
2883 if (fd && fd->isLinkable())
2884 // link to documented input file
2885 ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),QCString(),linkText);
2886 else
2887 ol.docify(linkText);
2888}
static FileNameLinkedMap * inputNameLinkedMap
Definition doxygen.h:104
void writeObjectLink(const QCString &ref, const QCString &file, const QCString &anchor, const QCString &name)
Definition outputlist.h:439
void docify(const QCString &s)
Definition outputlist.h:437

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

◆ generateMarker()

QCString generateMarker ( int id)

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

Definition at line 279 of file util.cpp.

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

References qsnprintf.

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

◆ genericPatternMatch()

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

Definition at line 5678 of file util.cpp.

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

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

Referenced by getEncoding(), and patternMatch().

◆ getCanonicalTemplateSpec()

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

Definition at line 1639 of file util.cpp.

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

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

Referenced by getCanonicalTypeForIdentifier().

◆ getCanonicalTypeForIdentifier()

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

Definition at line 1660 of file util.cpp.

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

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

Referenced by extractCanonicalType(), and getCanonicalTypeForIdentifier().

◆ getCaseSenseNames()

bool getCaseSenseNames ( )

Definition at line 3341 of file util.cpp.

3342{
3343 auto caseSenseNames = Config_getEnum(CASE_SENSE_NAMES);
3344
3345 if (caseSenseNames == CASE_SENSE_NAMES_t::YES) return true;
3346 else if (caseSenseNames == CASE_SENSE_NAMES_t::NO) return false;
3348}
#define Config_getEnum(name)
Definition config.h:35

References Config_getEnum, and Portable::fileSystemIsCaseSensitive().

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

◆ getDefs()

GetDefResult getDefs ( const GetDefInput & input)

Definition at line 2308 of file util.cpp.

2309{
2310 GetDefResult result;
2311 if (input.memberName.isEmpty()) return result;
2312 AUTO_TRACE("scopeName={},memberName={},forceEmptyScope={}",
2313 input.scopeName,input.memberName,input.forceEmptyScope);
2314
2315 //printf("@@ --- getDefsNew(%s,%s)-----------\n",qPrint(scName),qPrint(mbName));
2316 const Definition *scope = Doxygen::globalScope;
2317 SymbolResolver resolver;
2318 if (input.currentFile) resolver.setFileScope(input.currentFile);
2319 if (!input.scopeName.isEmpty() && !input.forceEmptyScope)
2320 {
2321 scope = resolver.resolveSymbol(scope,input.scopeName);
2322 }
2323 if (scope==Doxygen::globalScope)
2324 {
2325 scope = input.currentFile;
2326 }
2327 //printf("@@ -> found scope scope=%s member=%s out=%s\n",qPrint(input.scopeName),qPrint(input.memberName),qPrint(scope?scope->name():""));
2328 //
2329 const Definition *symbol = resolver.resolveSymbol(scope,input.memberName,input.args,input.checkCV,input.insideCode,true);
2330 //printf("@@ -> found symbol in=%s out=%s\n",qPrint(input.memberName),qPrint(symbol?symbol->qualifiedName():QCString()));
2331 if (symbol && symbol->definitionType()==Definition::TypeMember)
2332 {
2333 result.md = toMemberDef(symbol);
2334 result.cd = result.md->getClassDef();
2335 if (result.cd==nullptr) result.nd = result.md->getNamespaceDef();
2336 if (result.cd==nullptr && result.nd==nullptr) result.fd = result.md->getFileDef();
2337 result.gd = result.md->getGroupDef();
2338 result.found = true;
2339 }
2340 else if (symbol && symbol->definitionType()==Definition::TypeClass)
2341 {
2342 result.cd = toClassDef(symbol);
2343 result.found = true;
2344 }
2345 else if (symbol && symbol->definitionType()==Definition::TypeNamespace)
2346 {
2347 result.nd = toNamespaceDef(symbol);
2348 result.found = true;
2349 }
2350 else if (symbol && symbol->definitionType()==Definition::TypeConcept)
2351 {
2352 result.cnd = toConceptDef(symbol);
2353 result.found = true;
2354 }
2355 else if (symbol && symbol->definitionType()==Definition::TypeModule)
2356 {
2357 result.modd = toModuleDef(symbol);
2358 result.found = true;
2359 }
2360 return result;
2361}
The common base class of all entity definitions found in the sources.
Definition definition.h:77
static NamespaceDefMutable * globalScope
Definition doxygen.h:121
virtual const ClassDef * getClassDef() const =0
virtual GroupDef * getGroupDef()=0
virtual const FileDef * getFileDef() const =0
virtual const NamespaceDef * getNamespaceDef() const =0
const Definition * resolveSymbol(const Definition *scope, const QCString &name, const QCString &args=QCString(), bool checkCV=false, bool insideCode=false, bool onlyLinkable=false)
Find the symbool definition matching name within the scope set.
void setFileScope(const FileDef *fd)
Sets or updates the file scope using when resolving symbols.
MemberDef * toMemberDef(Definition *d)
ModuleDef * toModuleDef(Definition *d)
NamespaceDef * toNamespaceDef(Definition *d)
bool forceEmptyScope
Definition util.h:165
const FileDef * currentFile
Definition util.h:166
QCString scopeName
Definition util.h:162
bool insideCode
Definition util.h:168
bool checkCV
Definition util.h:167
QCString args
Definition util.h:164
QCString memberName
Definition util.h:163
const MemberDef * md
Definition util.h:174
const ConceptDef * cnd
Definition util.h:179
const FileDef * fd
Definition util.h:176
const ModuleDef * modd
Definition util.h:180
const GroupDef * gd
Definition util.h:178
bool found
Definition util.h:173
const ClassDef * cd
Definition util.h:175
const NamespaceDef * nd
Definition util.h:177

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

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

◆ getDotImageExtension()

QCString getDotImageExtension ( )

Definition at line 6311 of file util.cpp.

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

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

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

◆ getEncoding()

QCString getEncoding ( const FileInfo & fi)

Definition at line 5735 of file util.cpp.

5736{
5737 InputFileEncoding elem;
5738 auto getter = [](const InputFileEncoding &e) -> QCString { return e.pattern; };
5739 if (genericPatternMatch(fi,Doxygen::inputFileEncodingList,elem,getter)) // check for file specific encoding
5740 {
5741 return elem.encoding;
5742 }
5743 else // fall back to default encoding
5744 {
5745 return Config_getString(INPUT_ENCODING);
5746 }
5747}
static InputFileEncodingList inputFileEncodingList
Definition doxygen.h:138
#define Config_getString(name)
Definition config.h:32
QCString encoding
Definition doxygen.h:70
bool genericPatternMatch(const FileInfo &fi, const PatternList &patList, PatternElem &elem, PatternGet getter)
Definition util.cpp:5678

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

Referenced by readCodeFragment(), and readInputFile().

◆ getFileFilter()

QCString getFileFilter ( const QCString & name,
bool isSourceCode )

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

Definition at line 1422 of file util.cpp.

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

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

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

◆ getFileNameExtension()

◆ getFilterFromList()

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

Definition at line 1381 of file util.cpp.

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

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

Referenced by getFileFilter().

◆ getLanguageFromCodeLang()

SrcLangExt getLanguageFromCodeLang ( QCString & fileName)

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

Definition at line 5253 of file util.cpp.

5254{
5255 // try the extension
5256 auto lang = getLanguageFromFileName(fileName, SrcLangExt::Unknown);
5257 if (lang == SrcLangExt::Unknown)
5258 {
5259 // try the language names
5260 QCString langName = fileName.lower();
5261 if (langName.at(0)=='.') langName = langName.mid(1);
5262 auto it = std::find_if(g_lang2extMap.begin(),g_lang2extMap.end(),
5263 [&langName](const auto &info) { return info.langName==langName; });
5264 if (it != g_lang2extMap.end())
5265 {
5266 lang = it->parserId;
5267 fileName = it->defExt;
5268 }
5269 else // default to C++
5270 {
5271 return SrcLangExt::Cpp;
5272 }
5273 }
5274 return lang;
5275}
SrcLangExt getLanguageFromFileName(const QCString &fileName, SrcLangExt defLang)
Definition util.cpp:5235
static std::vector< Lang2ExtMap > g_lang2extMap
Definition util.cpp:5106

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

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

◆ getLanguageFromFileName()

SrcLangExt getLanguageFromFileName ( const QCString & fileName,
SrcLangExt defLang )

Definition at line 5235 of file util.cpp.

5236{
5237 FileInfo fi(fileName.str());
5238 // we need only the part after the last ".", newer implementations of FileInfo have 'suffix()' for this.
5239 QCString extName = QCString(fi.extension(FALSE)).lower();
5240 if (extName.isEmpty()) extName=".no_extension";
5241 if (extName.at(0)!='.') extName.prepend(".");
5242 auto it = g_extLookup.find(extName.str());
5243 if (it!=g_extLookup.end()) // listed extension
5244 {
5245 //printf("getLanguageFromFileName(%s)=%x\n",qPrint(fi.extension()),*pVal);
5246 return it->second;
5247 }
5248 //printf("getLanguageFromFileName(%s) not found!\n",qPrint(fileName));
5249 return defLang; // not listed => assume C-ish language.
5250}
static std::unordered_map< std::string, SrcLangExt > g_extLookup
Definition util.cpp:5096

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

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

◆ getLanguageSpecificSeparator()

QCString getLanguageSpecificSeparator ( SrcLangExt lang,
bool classScope )

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

Definition at line 5919 of file util.cpp.

5920{
5921 if (lang==SrcLangExt::Java || lang==SrcLangExt::CSharp || lang==SrcLangExt::VHDL || lang==SrcLangExt::Python)
5922 {
5923 return ".";
5924 }
5925 else if (lang==SrcLangExt::PHP && !classScope)
5926 {
5927 return "\\";
5928 }
5929 else
5930 {
5931 return "::";
5932 }
5933}

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

◆ getMemberFromSymbol()

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

Definition at line 5287 of file util.cpp.

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

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

Referenced by checkIfTypedef().

◆ getOverloadDocs()

QCString getOverloadDocs ( )

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

Definition at line 4114 of file util.cpp.

4115{
4116 return theTranslator->trOverloadText();
4117 //"This is an overloaded member function, "
4118 // "provided for convenience. It differs from the above "
4119 // "function only in what argument(s) it accepts.";
4120}
Translator * theTranslator
Definition language.cpp:71

References theTranslator.

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

◆ getPrefixIndex()

int getPrefixIndex ( const QCString & name)

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

Definition at line 3252 of file util.cpp.

3253{
3254 if (name.isEmpty()) return 0;
3255 const StringVector &sl = Config_getList(IGNORE_PREFIX);
3256 for (const auto &s : sl)
3257 {
3258 const char *ps=s.c_str();
3259 const char *pd=name.data();
3260 int i=0;
3261 while (*ps!=0 && *pd!=0 && *ps==*pd)
3262 {
3263 ps++;
3264 pd++;
3265 i++;
3266 }
3267 if (*ps==0 && *pd!=0)
3268 {
3269 return i;
3270 }
3271 }
3272 return 0;
3273}

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

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

◆ getProjectId()

QCString getProjectId ( )

Definition at line 6833 of file util.cpp.

6834{
6835 QCString projectCookie = Config_getString(HTML_PROJECT_COOKIE);
6836 if (projectCookie.isEmpty()) return QCString();
6837 uint8_t md5_sig[16];
6838 char sigStr[34];
6839 MD5Buffer(projectCookie.data(),static_cast<unsigned int>(projectCookie.length()),md5_sig);
6840 MD5SigToString(md5_sig,sigStr);
6841 sigStr[32]='_'; sigStr[33]=0;
6842 return sigStr;
6843}

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

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

◆ getScopeDefs()

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

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

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

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

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

Definition at line 2378 of file util.cpp.

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

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

Referenced by resolveRef().

◆ getScopeFragment()

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

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

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

Definition at line 4664 of file util.cpp.

4665{
4666 int sl=static_cast<int>(s.length());
4667 int sp=p;
4668 int count=0;
4669 bool done=false;
4670 if (sp>=sl) return -1;
4671 while (sp<sl)
4672 {
4673 char c=s.at(sp);
4674 if (c==':')
4675 {
4676 sp++;
4677 p++;
4678 }
4679 else
4680 {
4681 break;
4682 }
4683 }
4684 while (sp<sl)
4685 {
4686 char c=s.at(sp);
4687 switch (c)
4688 {
4689 case ':': // found next part
4690 goto found;
4691 case '<': // skip template specifier
4692 count=1;sp++;
4693 done=false;
4694 while (sp<sl && !done)
4695 {
4696 // TODO: deal with << and >> operators!
4697 c=s.at(sp++);
4698 switch(c)
4699 {
4700 case '<': count++; break;
4701 case '>': count--; if (count==0) done=true; break;
4702 default: break;
4703 }
4704 }
4705 break;
4706 default:
4707 sp++;
4708 break;
4709 }
4710 }
4711found:
4712 *l=sp-p;
4713 //printf("getScopeFragment(%s,%d)=%s\n",qPrint(s),p,qPrint(s.mid(p,*l)));
4714 return p;
4715}

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

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

◆ guessSection()

EntryType guessSection ( const QCString & name)

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

Definition at line 338 of file util.cpp.

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

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

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

◆ initDefaultExtensionMapping()

void initDefaultExtensionMapping ( )

Definition at line 5162 of file util.cpp.

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

References updateLanguageMapping().

Referenced by initDoxygen().

◆ inlineArgListToDoc()

QCString inlineArgListToDoc ( const ArgumentList & al)

Definition at line 1204 of file util.cpp.

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

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

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

◆ inlineTemplateArgListToDoc()

QCString inlineTemplateArgListToDoc ( const ArgumentList & al)

Definition at line 1227 of file util.cpp.

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

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

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

◆ insertTemplateSpecifierInScope()

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

Definition at line 3767 of file util.cpp.

3768{
3769 QCString result=scope;
3770 if (!templ.isEmpty() && scope.find('<')==-1)
3771 {
3772 int si=0, pi=0;
3773 ClassDef *cd=nullptr;
3774 while (
3775 (si=scope.find("::",pi))!=-1 && !getClass(scope.left(si)+templ) &&
3776 ((cd=getClass(scope.left(si)))==nullptr || cd->templateArguments().empty())
3777 )
3778 {
3779 //printf("Tried '%s'\n",qPrint((scope.left(si)+templ)));
3780 pi=si+2;
3781 }
3782 if (si==-1) // not nested => append template specifier
3783 {
3784 result+=templ;
3785 }
3786 else // nested => insert template specifier before after first class name
3787 {
3788 result=scope.left(si) + templ + scope.right(scope.length()-si);
3789 }
3790 }
3791 //printf("insertTemplateSpecifierInScope('%s','%s')=%s\n",
3792 // qPrint(scope),qPrint(templ),qPrint(result));
3793 return result;
3794}
bool empty() const
Definition arguments.h:99
virtual const ArgumentList & templateArguments() const =0
Returns the template arguments of this class.

References ArgumentList::empty(), QCString::find(), getClass(), QCString::isEmpty(), QCString::left(), QCString::length(), QCString::right(), and ClassDef::templateArguments().

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

◆ integerToAlpha()

QCString integerToAlpha ( int n,
bool upper )

Definition at line 6704 of file util.cpp.

6705{
6706 QCString result;
6707 int residual = n;
6708
6709 char modVal[2];
6710 modVal[1] = 0;
6711 while (residual > 0)
6712 {
6713 modVal[0] = (upper ? 'A': 'a') + (residual-1)%26;
6714 result = modVal + result;
6715 residual = (residual-1) / 26;
6716 }
6717 return result;
6718}

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

◆ integerToRoman()

QCString integerToRoman ( int n,
bool upper )

Definition at line 6720 of file util.cpp.

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

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

◆ isLowerCase()

bool isLowerCase ( QCString & s)
static

Definition at line 2440 of file util.cpp.

2441{
2442 if (s.isEmpty()) return true;
2443 const char *p=s.data();
2444 int c=0;
2445 while ((c=static_cast<uint8_t>(*p++))) if (!islower(c)) return false;
2446 return true;
2447}

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

Referenced by resolveRef().

◆ isURL()

bool isURL ( const QCString & url)

Checks whether the given url starts with a supported protocol.

Definition at line 5935 of file util.cpp.

5936{
5937 static const std::unordered_set<std::string> schemes = {
5938 "http", "https", "ftp", "ftps", "sftp", "file", "news", "irc", "ircs"
5939 };
5940 QCString loc_url = url.stripWhiteSpace();
5941 int colonPos = loc_url.find(':');
5942 return colonPos!=-1 && schemes.find(loc_url.left(colonPos).str())!=schemes.end();
5943}

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

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

◆ join()

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

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

Definition at line 6691 of file util.cpp.

6692{
6693 std::string result;
6694 bool first=true;
6695 for (const auto &s : sv)
6696 {
6697 if (!first) result+=delimiter;
6698 first=false;
6699 result+=s;
6700 }
6701 return result;
6702}

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

◆ keyWordsFortranC()

bool keyWordsFortranC ( const char * contents)
static

Definition at line 6345 of file util.cpp.

6346{
6347 static const std::unordered_set<std::string> fortran_C_keywords = {
6348 "character", "call", "close", "common", "continue",
6349 "case", "contains", "cycle", "class", "codimension",
6350 "concurrent", "contiguous", "critical"
6351 };
6352
6353 if (*contents != 'c' && *contents != 'C') return false;
6354
6355 const char *c = contents;
6356 QCString keyword;
6357 while (*c && *c != ' ') {keyword += *c; c++;}
6358 keyword = keyword.lower();
6359
6360 return (fortran_C_keywords.find(keyword.str()) != fortran_C_keywords.end());
6361}

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

Referenced by recognizeFixedForm().

◆ langToString()

QCString langToString ( SrcLangExt lang)

Returns a string representation of lang.

Definition at line 5913 of file util.cpp.

5914{
5915 return to_string(lang);
5916}
static constexpr const char * to_string(Protection prot) noexcept
Definition types.h:38

References to_string().

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

◆ leftScopeMatch()

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

Definition at line 881 of file util.cpp.

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

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

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

◆ lineBlock()

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

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

See also
routine extractBlock

Definition at line 5892 of file util.cpp.

5893{
5894 int result = 1;
5895
5896 // find the character positions of the first marker
5897 int m1 = text.find(marker);
5898 if (m1==-1) return result;
5899
5900 // find start line positions for the markers
5901 bool found=false;
5902 int p=0, i=0;
5903 while (!found && (i=text.find('\n',p))!=-1)
5904 {
5905 found = (p<=m1 && m1<i); // found the line with the start marker
5906 p=i+1;
5907 result++;
5908 }
5909 return result;
5910}

References QCString::find().

Referenced by readIncludeFile().

◆ linkifyText()

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

Definition at line 893 of file util.cpp.

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

References Definition::anchor(), LinkifyTextOptions::argumentList(), AUTO_TRACE, LinkifyTextOptions::autoBreak(), ArgumentList::begin(), LinkifyTextOptions::breakThreshold(), QCString::data(), Definition::definitionType(), ArgumentList::end(), end(), LinkifyTextOptions::external(), FALSE, LinkifyTextOptions::fileScope(), QCString::findRev(), GetDefResult::found, getClass(), getConcept(), getDefs(), Definition::getLanguage(), Definition::getOuterScope(), Definition::getOutputFileBase(), Definition::getReference(), SymbolResolver::getTypedef(), LinkifyTextOptions::indentLevel(), QCString::isEmpty(), Definition::isLinkable(), Definition::isLinkableInProject(), MemberDef::isVariable(), LinkifyTextOptions::keepSpaces(), QCString::left(), GetDefResult::md, QCString::mid(), Definition::name(), Definition::qualifiedName(), SymbolResolver::resolveClass(), SymbolResolver::resolveSymbol(), LinkifyTextOptions::scope(), LinkifyTextOptions::self(), substitute(), TRUE, Definition::TypeClass, Definition::TypeNamespace, QCString::view(), TextGeneratorIntf::writeBreak(), TextGeneratorIntf::writeLink(), and TextGeneratorIntf::writeString().

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

◆ linkToText()

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

Definition at line 2708 of file util.cpp.

2709{
2710 //bool optimizeOutputJava = Config_getBool(OPTIMIZE_OUTPUT_JAVA);
2711 QCString result=link;
2712 if (!result.isEmpty())
2713 {
2714 // replace # by ::
2715 result=substitute(result,"#","::");
2716 // replace . by ::
2717 if (!isFileName && result.find('<')==-1) result=substitute(result,".","::",3);
2718 // strip leading :: prefix if present
2719 if (result.at(0)==':' && result.at(1)==':')
2720 {
2721 result=result.right(result.length()-2);
2722 }
2724 if (sep!="::")
2725 {
2726 result=substitute(result,"::",sep);
2727 }
2728 }
2729 //printf("linkToText(%s,lang=%d)=%s\n",qPrint(link),lang,qPrint(result));
2730 return result;
2731}
QCString getLanguageSpecificSeparator(SrcLangExt lang, bool classScope)
Returns the scope separator to use given the programming language lang.
Definition util.cpp:5919

References QCString::at(), QCString::find(), getLanguageSpecificSeparator(), QCString::isEmpty(), QCString::length(), QCString::right(), and substitute().

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

◆ mainPageHasTitle()

bool mainPageHasTitle ( )

Definition at line 6306 of file util.cpp.

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

References Doxygen::mainPage.

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

◆ makeBaseName()

◆ mangleCSharpGenericName()

QCString mangleCSharpGenericName ( const QCString & name)

Definition at line 6935 of file util.cpp.

6936{
6937 int idx = name.find('<');
6938 if (idx!=-1)
6939 {
6940 return name.left(idx)+"-"+QCString().setNum(name.contains(",")+1)+"-g";
6941 }
6942 return name;
6943}
int contains(char c, bool cs=TRUE) const
Definition qcstring.cpp:148

References QCString::contains(), QCString::find(), QCString::left(), and QCString::setNum().

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

◆ matchArgument2()

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

Definition at line 1965 of file util.cpp.

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

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

Referenced by matchArguments2().

◆ matchArguments2()

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

Definition at line 2031 of file util.cpp.

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

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

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

◆ matchCanonicalTypes()

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

Definition at line 1933 of file util.cpp.

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

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

Referenced by matchArgument2().

◆ matchTemplateArguments()

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

Definition at line 2275 of file util.cpp.

2276{
2277 AUTO_TRACE("srcAl={} dstAl={}",argListToString(srcAl),argListToString(dstAl));
2278 if (srcAl.size()!=dstAl.size()) // different number of template parameters -> overload
2279 {
2280 AUTO_TRACE_EXIT("different number of parameters");
2281 return false;
2282 }
2283 auto isUnconstraintTemplate = [](const QCString &type)
2284 {
2285 return type=="typename" || type=="class" || type.startsWith("typename ") || type.startsWith("class ");
2286 };
2287 auto srcIt = srcAl.begin();
2288 auto dstIt = dstAl.begin();
2289 while (srcIt!=srcAl.end() && dstIt!=dstAl.end())
2290 {
2291 const Argument &srcA = *srcIt;
2292 const Argument &dstA = *dstIt;
2293 if ((!isUnconstraintTemplate(srcA.type) || !isUnconstraintTemplate(dstA.type)) && srcA.type!=dstA.type) // different constraints -> overload
2294 {
2295 AUTO_TRACE_EXIT("different constraints");
2296 return false;
2297 }
2298 ++srcIt;
2299 ++dstIt;
2300 }
2301 AUTO_TRACE_EXIT("same");
2302 // no overload with respect to the template parameters
2303 return true;
2304}

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

Referenced by buildFunctionList().

◆ mergeArguments()

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

Definition at line 2131 of file util.cpp.

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

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

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

◆ mergeMemberOverrideOptions()

void mergeMemberOverrideOptions ( MemberDefMutable * md1,
MemberDefMutable * md2 )

Definition at line 6883 of file util.cpp.

6884{
6885 if (Config_getBool(CALL_GRAPH) !=md1->hasCallGraph()) md2->overrideCallGraph(md1->hasCallGraph());
6886 if (Config_getBool(CALLER_GRAPH)!=md1->hasCallerGraph()) md2->overrideCallerGraph(md1->hasCallerGraph());
6887 if (Config_getBool(CALL_GRAPH) !=md2->hasCallGraph()) md1->overrideCallGraph( md2->hasCallGraph());
6888 if (Config_getBool(CALLER_GRAPH)!=md2->hasCallerGraph()) md1->overrideCallerGraph(md2->hasCallerGraph());
6889
6890 if (Config_getBool(SHOW_ENUM_VALUES) !=md1->hasEnumValues()) md2->overrideEnumValues(md1->hasEnumValues());
6891 if (Config_getBool(SHOW_ENUM_VALUES) !=md2->hasEnumValues()) md1->overrideEnumValues( md2->hasEnumValues());
6892
6893 if (Config_getBool(REFERENCED_BY_RELATION)!=md1->hasReferencedByRelation()) md2->overrideReferencedByRelation(md1->hasReferencedByRelation());
6894 if (Config_getBool(REFERENCES_RELATION) !=md1->hasReferencesRelation()) md2->overrideReferencesRelation(md1->hasReferencesRelation());
6895 if (Config_getBool(REFERENCED_BY_RELATION)!=md2->hasReferencedByRelation()) md1->overrideReferencedByRelation(md2->hasReferencedByRelation());
6896 if (Config_getBool(REFERENCES_RELATION) !=md2->hasReferencesRelation()) md1->overrideReferencesRelation(md2->hasReferencesRelation());
6897
6898 if (Config_getBool(INLINE_SOURCES)!=md1->hasInlineSource()) md2->overrideInlineSource(md1->hasInlineSource());
6899 if (Config_getBool(INLINE_SOURCES)!=md2->hasInlineSource()) md1->overrideInlineSource(md2->hasInlineSource());
6900}
virtual bool hasReferencesRelation() const =0
virtual bool hasCallGraph() const =0
virtual bool hasInlineSource() const =0
virtual bool hasEnumValues() const =0
virtual bool hasCallerGraph() const =0
virtual bool hasReferencedByRelation() const =0
virtual void overrideReferencesRelation(bool e)=0
virtual void overrideReferencedByRelation(bool e)=0
virtual void overrideCallGraph(bool e)=0
virtual void overrideInlineSource(bool e)=0
virtual void overrideEnumValues(bool e)=0
virtual void overrideCallerGraph(bool e)=0

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

Referenced by combineDeclarationAndDefinition(), and findFriends().

◆ mergeScopes()

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

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

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

Definition at line 4619 of file util.cpp.

4620{
4621 AUTO_TRACE("leftScope='{}' rightScope='{}'",leftScope,rightScope);
4622 // case leftScope=="A" rightScope=="A::B" => result = "A::B"
4623 if (leftScopeMatch(leftScope,rightScope))
4624 {
4625 AUTO_TRACE_EXIT("case1={}",rightScope);
4626 return rightScope;
4627 }
4628 QCString result;
4629 int i=0,p=static_cast<int>(leftScope.length());
4630
4631 // case leftScope=="A::B" rightScope=="B::C" => result = "A::B::C"
4632 // case leftScope=="A::B" rightScope=="B" => result = "A::B"
4633 bool found=FALSE;
4634 while ((i=leftScope.findRev("::",p))>0)
4635 {
4636 if (leftScopeMatch(rightScope,leftScope.right(leftScope.length()-i-2)))
4637 {
4638 result = leftScope.left(i+2)+rightScope;
4639 found=TRUE;
4640 }
4641 p=i-1;
4642 }
4643 if (found)
4644 {
4645 AUTO_TRACE_EXIT("case2={}",result);
4646 return result;
4647 }
4648
4649 // case leftScope=="A" rightScope=="B" => result = "A::B"
4650 result=leftScope;
4651 if (!result.isEmpty() && !rightScope.isEmpty()) result+="::";
4652 result+=rightScope;
4653 AUTO_TRACE_EXIT("case3={}",result);
4654 return result;
4655}
bool leftScopeMatch(const QCString &scope, const QCString &name)
Definition util.cpp:881

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

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

◆ nextUTF8CharPosition()

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

Definition at line 5349 of file util.cpp.

5350{
5351 if (startPos>=len) return len;
5352 uint8_t c = static_cast<uint8_t>(utf8Str[startPos]);
5353 int bytes=getUTF8CharNumBytes(c);
5354 if (c=='&') // skip over character entities
5355 {
5356 bytes=1;
5357 int (*matcher)(int) = nullptr;
5358 c = static_cast<uint8_t>(utf8Str[startPos+bytes]);
5359 if (c=='#') // numerical entity?
5360 {
5361 bytes++;
5362 c = static_cast<uint8_t>(utf8Str[startPos+bytes]);
5363 if (c=='x') // hexadecimal entity?
5364 {
5365 bytes++;
5366 matcher = std::isxdigit;
5367 }
5368 else // decimal entity
5369 {
5370 matcher = std::isdigit;
5371 }
5372 }
5373 else if (std::isalnum(c)) // named entity?
5374 {
5375 bytes++;
5376 matcher = std::isalnum;
5377 }
5378 if (matcher)
5379 {
5380 while ((c = static_cast<uint8_t>(utf8Str[startPos+bytes]))!=0 && matcher(c))
5381 {
5382 bytes++;
5383 }
5384 }
5385 if (c!=';')
5386 {
5387 bytes=1; // not a valid entity, reset bytes counter
5388 }
5389 }
5390 return startPos+bytes;
5391}

References getUTF8CharNumBytes().

Referenced by parseCommentAsText().

◆ normalizeNonTemplateArgumentsInString()

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

Definition at line 4325 of file util.cpp.

4329{
4330 // skip until <
4331 int p=name.find('<');
4332 if (p==-1) return name;
4333 p++;
4334 QCString result = name.left(p);
4335
4336 std::string s = name.mid(p).str();
4337 static const reg::Ex re(R"([\a:][\w:]*)");
4338 reg::Iterator it(s,re);
4340 size_t pi=0;
4341 // for each identifier in the template part (e.g. B<T> -> T)
4342 for (; it!=end ; ++it)
4343 {
4344 const auto &match = *it;
4345 size_t i = match.position();
4346 size_t l = match.length();
4347 result += s.substr(pi,i-pi);
4348 QCString n(match.str());
4349 bool found=FALSE;
4350 for (const Argument &formArg : formalArgs)
4351 {
4352 if (formArg.name == n)
4353 {
4354 found=TRUE;
4355 break;
4356 }
4357 }
4358 if (!found)
4359 {
4360 // try to resolve the type
4361 SymbolResolver resolver;
4362 const ClassDef *cd = resolver.resolveClass(context,n);
4363 if (cd)
4364 {
4365 result+=cd->name();
4366 }
4367 else
4368 {
4369 result+=n;
4370 }
4371 }
4372 else
4373 {
4374 result+=n;
4375 }
4376 pi=i+l;
4377 }
4378 result+=s.substr(pi);
4379 //printf("normalizeNonTemplateArgumentInString(%s)=%s\n",qPrint(name),qPrint(result));
4380 return removeRedundantWhiteSpace(result);
4381}
const ClassDef * resolveClass(const Definition *scope, const QCString &name, bool maybeUnlinkable=false, bool mayBeHidden=false)
Find the class definition matching name within the scope set.

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

Referenced by findUsedClassesForClass().

◆ openOutputFile()

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

Definition at line 6318 of file util.cpp.

6319{
6320 assert(!f.is_open());
6321 bool fileOpened=FALSE;
6322 bool writeToStdout=outFile=="-";
6323 if (writeToStdout) // write to stdout
6324 {
6325 f.basic_ios<char>::rdbuf(std::cout.rdbuf());
6326 fileOpened = true;
6327 }
6328 else // write to file
6329 {
6330 FileInfo fi(outFile.str());
6331 if (fi.exists()) // create a backup
6332 {
6333 Dir dir;
6334 FileInfo backup(fi.filePath()+".bak");
6335 if (backup.exists()) // remove existing backup
6336 dir.remove(backup.filePath());
6337 dir.rename(fi.filePath(),fi.filePath()+".bak");
6338 }
6339 f = Portable::openOutputStream(outFile);
6340 fileOpened = f.is_open();
6341 }
6342 return fileOpened;
6343}
bool rename(const std::string &orgName, const std::string &newName, bool acceptsAbsPath=true) const
Definition dir.cpp:321
std::ofstream openOutputStream(const QCString &name, bool append=false)
Definition portable.cpp:648

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

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

◆ parseCommentAsHtml()

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

Definition at line 5449 of file util.cpp.

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

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

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

◆ parseCommentAsText()

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

Definition at line 5393 of file util.cpp.

5395{
5396 if (doc.isEmpty()) return "";
5397 //printf("parseCommentAsText(%s)\n",qPrint(doc));
5398 TextStream t;
5399 auto parser { createDocParser() };
5400 auto ast { validatingParseDoc(*parser.get(),
5401 fileName,
5402 lineNr,
5403 scope,
5404 md,
5405 doc,
5406 DocOptions()
5407 .setAutolinkSupport(false))
5408 };
5409 auto astImpl = dynamic_cast<const DocNodeAST*>(ast.get());
5410 if (astImpl)
5411 {
5412 TextDocVisitor visitor(t);
5413 std::visit(visitor,astImpl->root);
5414 }
5416 int i=0;
5417 int charCnt=0;
5418 int l=static_cast<int>(result.length());
5419 while ((i=nextUTF8CharPosition(result,l,i))<l)
5420 {
5421 charCnt++;
5422 if (charCnt>=80) break;
5423 }
5424 if (charCnt>=80) // try to truncate the string
5425 {
5426 while ((i=nextUTF8CharPosition(result,l,i))<l && charCnt<100)
5427 {
5428 charCnt++;
5429 if (result.at(i)==',' ||
5430 result.at(i)=='.' ||
5431 result.at(i)=='!' ||
5432 result.at(i)=='?' ||
5433 result.at(i)=='}') // good for UTF-16 characters and } otherwise also a good point to stop the string
5434 {
5435 i++; // we want to be "behind" last inspected character
5436 break;
5437 }
5438 }
5439 }
5440 if ( i < l) result=result.left(i)+"...";
5441 return result.data();
5442}
Concrete visitor implementation for TEXT output.
IDocNodeASTPtr validatingParseDoc(IDocParser &parserIntf, const QCString &fileName, int startLine, const Definition *ctx, const MemberDef *md, const QCString &input, const DocOptions &options)
static int nextUTF8CharPosition(const QCString &utf8Str, uint32_t len, uint32_t startPos)
Definition util.cpp:5349

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

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

◆ patternMatch()

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

Definition at line 5728 of file util.cpp.

5729{
5730 std::string elem;
5731 auto getter = [](std::string s) -> QCString { return s; };
5732 return genericPatternMatch(fi,patList,elem,getter);
5733}

References genericPatternMatch().

Referenced by checkAndOpenFile(), and readDir().

◆ projectLogoFile()

QCString projectLogoFile ( )

Definition at line 3161 of file util.cpp.

3162{
3163 QCString projectLogo = Config_getString(PROJECT_LOGO);
3164 if (!projectLogo.isEmpty())
3165 {
3166 // check for optional width= and height= specifier
3167 int wi = projectLogo.find(" width=");
3168 if (wi!=-1) // and strip them
3169 {
3170 projectLogo = projectLogo.left(wi);
3171 }
3172 int hi = projectLogo.find(" height=");
3173 if (hi!=-1)
3174 {
3175 projectLogo = projectLogo.left(hi);
3176 }
3177 }
3178 //printf("projectlogo='%s'\n",qPrint(projectLogo));
3179 return projectLogo;
3180}

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

Referenced by copyLogo(), and substituteKeywords().

◆ projectLogoSize()

QCString projectLogoSize ( )
static

Definition at line 3182 of file util.cpp.

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

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

Referenced by substituteKeywords().

◆ protectionLevelVisible()

bool protectionLevelVisible ( Protection prot)

Definition at line 5959 of file util.cpp.

5960{
5961 bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
5962 bool extractPackage = Config_getBool(EXTRACT_PACKAGE);
5963
5964 return (prot!=Protection::Private && prot!=Protection::Package) ||
5965 (prot==Protection::Private && extractPrivate) ||
5966 (prot==Protection::Package && extractPackage);
5967}

References Config_getBool.

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

◆ readInputFile()

bool readInputFile ( const QCString & fileName,
std::string & contents,
bool filter,
bool isSourceCode )

read a file name fileName and optionally filter and transcode it

Definition at line 5574 of file util.cpp.

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

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

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

◆ recognizeFixedForm()

bool recognizeFixedForm ( const QCString & contents,
FortranFormat format )

Definition at line 6365 of file util.cpp.

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

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

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

◆ recursivelyAddGroupListToTitle()

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

Definition at line 4897 of file util.cpp.

4898{
4899 ModuleDef *mod = root ? findModuleDef(d) : nullptr;
4900 if (!d->partOfGroups().empty() || mod!=nullptr) // write list of group to which this definition belongs
4901 {
4902 if (root)
4903 {
4904 ol.pushGeneratorState();
4906 ol.writeString("<div class=\"ingroups\">");
4907 }
4908 bool first=true;
4909 for (const auto &gd : d->partOfGroups())
4910 {
4911 if (!first) { ol.writeString(" &#124; "); } else first=false;
4913 {
4914 ol.writeString(" &raquo; ");
4915 }
4916 ol.writeObjectLink(gd->getReference(),gd->getOutputFileBase(),QCString(),gd->groupTitle());
4917 }
4918 if (root)
4919 {
4920 // add module as a group to the file as well
4921 if (mod)
4922 {
4923 if (!first) { ol.writeString(" &#124; "); } else first=false;
4924 ol.writeString(theTranslator->trModule(false,true)+" ");
4926 mod->displayName());
4927 }
4928 ol.writeString("</div>");
4929 ol.popGeneratorState();
4930 }
4931 return true;
4932 }
4933 return false;
4934}
virtual const GroupList & partOfGroups() const =0
virtual QCString displayName(bool includeScope=TRUE) const =0
void writeString(const QCString &text)
Definition outputlist.h:411
void pushGeneratorState()
void disableAllBut(OutputType o)
void popGeneratorState()
static ModuleDef * findModuleDef(const Definition *d)
Definition util.cpp:4868

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

Referenced by addGroupListToTitle(), and recursivelyAddGroupListToTitle().

◆ relativePathToRoot()

QCString relativePathToRoot ( const QCString & name)

Definition at line 3600 of file util.cpp.

3601{
3602 QCString result;
3603 if (Config_getBool(CREATE_SUBDIRS))
3604 {
3605 if (name.isEmpty())
3606 {
3607 return REL_PATH_TO_ROOT;
3608 }
3609 else
3610 {
3611 int i = name.findRev('/');
3612 if (i!=-1)
3613 {
3614 result=REL_PATH_TO_ROOT;
3615 }
3616 }
3617 }
3618 return result;
3619}
#define REL_PATH_TO_ROOT
Definition util.cpp:94

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

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

◆ removeAnonymousScopes()

QCString removeAnonymousScopes ( const QCString & str)

Removes all anonymous scopes from string s Possible examples:

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

Definition at line 161 of file util.cpp.

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

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

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

◆ removeEmptyLines()

QCString removeEmptyLines ( const QCString & s)

Definition at line 6608 of file util.cpp.

6609{
6610 std::string out;
6611 out.reserve(s.length());
6612 const char *p=s.data();
6613 if (p)
6614 {
6615 char c = 0;
6616 while ((c=*p++))
6617 {
6618 if (c=='\n')
6619 {
6620 const char *e = p;
6621 while (*e==' ' || *e=='\t') e++;
6622 if (*e=='\n')
6623 {
6624 p=e;
6625 }
6626 else out+=c;
6627 }
6628 else
6629 {
6630 out+=c;
6631 }
6632 }
6633 }
6634 //printf("removeEmptyLines(%s)=%s\n",qPrint(s),qPrint(out));
6635 return out;
6636}

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

Referenced by substituteHtmlKeywords(), and substituteLatexKeywords().

◆ removeLongPathMarker()

QCString removeLongPathMarker ( QCString path)

Definition at line 287 of file util.cpp.

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

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

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

◆ removeRedundantWhiteSpace()

QCString removeRedundantWhiteSpace ( const QCString & s)

Definition at line 567 of file util.cpp.

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

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

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

◆ replaceAnonymousScopes()

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

Definition at line 218 of file util.cpp.

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

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

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

◆ replaceColorMarkers()

QCString replaceColorMarkers ( const QCString & str)

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

Definition at line 5828 of file util.cpp.

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

References Config_getInt, end(), hex, HEXTONUM, ColoredImage::hsl2rgb(), QCString::isEmpty(), and QCString::str().

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

◆ resolveLink()

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

Definition at line 2734 of file util.cpp.

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

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

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

◆ resolveRef()

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

Returns an object to reference to given its name and context

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

Definition at line 2452 of file util.cpp.

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

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

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

◆ resolveTypeDef()

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

Definition at line 373 of file util.cpp.

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

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

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

◆ rightScopeMatch()

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

Definition at line 870 of file util.cpp.

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

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

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

◆ selectBlocks()

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

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

Definition at line 6431 of file util.cpp.

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

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

Referenced by substituteHtmlKeywords(), and substituteLatexKeywords().

◆ showDate()

QCString showDate ( const QCString & fmt)
static

Definition at line 3148 of file util.cpp.

3149{
3150 // get the current date and time
3151 std::tm dat{};
3152 int specFormat=0;
3153 QCString specDate = "";
3154 QCString err = dateTimeFromString(specDate,dat,specFormat);
3155
3156 // do the conversion
3157 int usedFormat=0;
3158 return formatDateTime(fmt,dat,usedFormat);
3159}
QCString formatDateTime(const QCString &format, const std::tm &dt, int &formatUsed)
Return a string representation for a given std::tm value that is formatted according to the pattern g...
Definition datetime.cpp:174
QCString dateTimeFromString(const QCString &spec, std::tm &dt, int &format)
Returns the filled in std::tm for a given string representing a date and/or time.
Definition datetime.cpp:133
Definition message.h:144

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

Referenced by substituteKeywords().

◆ showFileDefMatches()

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

Definition at line 3039 of file util.cpp.

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

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

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

◆ split() [1/2]

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

split input string s by regular expression delimiter delimiter.

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

Definition at line 6657 of file util.cpp.

6658{
6659 StringVector result;
6660 reg::Iterator iter(s, delimiter);
6662 size_t p=0;
6663 for ( ; iter != end; ++iter)
6664 {
6665 const auto &match = *iter;
6666 size_t i=match.position();
6667 size_t l=match.length();
6668 if (i>p) result.push_back(s.substr(p,i-p));
6669 p=i+l;
6670 }
6671 if (p<s.length()) result.push_back(s.substr(p));
6672 return result;
6673}

References end().

◆ split() [2/2]

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

split input string s by string delimiter delimiter.

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

Definition at line 6640 of file util.cpp.

6641{
6642 StringVector result;
6643 size_t prev = 0, pos = 0, len = s.length();
6644 do
6645 {
6646 pos = s.find(delimiter, prev);
6647 if (pos == std::string::npos) pos = len;
6648 if (pos>prev) result.push_back(s.substr(prev,pos-prev));
6649 prev = pos + delimiter.length();
6650 }
6651 while (pos<len && prev<len);
6652 return result;
6653}

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

◆ stackTrace()

void stackTrace ( )

Definition at line 5510 of file util.cpp.

5511{
5512#ifdef TRACINGSUPPORT
5513 void *backtraceFrames[128];
5514 int frameCount = backtrace(backtraceFrames, 128);
5515 const size_t cmdLen = 40960;
5516 static char cmd[cmdLen];
5517 char *p = cmd;
5518 p += qsnprintf(p,cmdLen,"/usr/bin/atos -p %d ", (int)getpid());
5519 for (int x = 0; x < frameCount; x++)
5520 {
5521 p += qsnprintf(p,cmdLen,"%p ", backtraceFrames[x]);
5522 }
5523 fprintf(stderr,"========== STACKTRACE START ==============\n");
5524 if (FILE *fp = Portable::popen(cmd, "r"))
5525 {
5526 char resBuf[512];
5527 while (size_t len = fread(resBuf, 1, sizeof(resBuf), fp))
5528 {
5529 fwrite(resBuf, 1, len, stderr);
5530 }
5531 Portable::pclose(fp);
5532 }
5533 fprintf(stderr,"============ STACKTRACE END ==============\n");
5534 //fprintf(stderr,"%s\n", frameStrings[x]);
5535#endif
5536}

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

◆ stripAnonymousNamespaceScope()

QCString stripAnonymousNamespaceScope ( const QCString & s)

Definition at line 230 of file util.cpp.

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

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

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

◆ stripDeclKeywords()

QCString stripDeclKeywords ( const QCString & s)
static

Definition at line 1623 of file util.cpp.

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

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

Referenced by getCanonicalTypeForIdentifier().

◆ stripExtension()

◆ stripExtensionGeneral()

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

◆ stripFromIncludePath()

QCString stripFromIncludePath ( const QCString & path)

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

Definition at line 329 of file util.cpp.

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

References Config_getList, and stripFromPath().

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

◆ stripFromPath() [1/2]

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

Definition at line 298 of file util.cpp.

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

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

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

◆ stripFromPath() [2/2]

QCString stripFromPath ( const QCString & path)

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

Definition at line 321 of file util.cpp.

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

References Config_getList, and stripFromPath().

◆ stripIndentation()

QCString stripIndentation ( const QCString & s,
bool skipFirstLine )

Definition at line 5971 of file util.cpp.

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

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

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

◆ stripIndentationVerbatim()

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

Definition at line 6060 of file util.cpp.

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

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

Referenced by MemberDefImpl::setInitializer().

◆ stripIrrelevantConstVolatile()

void stripIrrelevantConstVolatile ( QCString & s,
bool insideTemplate )

According to the C++ spec and Ivan Vecerina:

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

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

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

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

Definition at line 1613 of file util.cpp.

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

References stripIrrelevantString().

Referenced by extractCanonicalType(), and matchArgument2().

◆ stripIrrelevantString()

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

Definition at line 1553 of file util.cpp.

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

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

Referenced by stripIrrelevantConstVolatile().

◆ stripLeadingAndTrailingEmptyLines()

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

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

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

Definition at line 5054 of file util.cpp.

5055{
5056 if (s.isEmpty()) return QCString();
5057 const char *p = s.data();
5058
5059 // search for leading empty lines
5060 int i=0,li=-1,l=static_cast<int>(s.length());
5061 char c = 0;
5062 while ((c=*p))
5063 {
5064 if (c==' ' || c=='\t' || c=='\r') { i++; p++; }
5065 else if (c=='\\' && literal_at(p,"\\ilinebr")) { i+=8; li=i; p+=8; }
5066 else if (c=='\n') { i++; li=i; docLine++; p++; }
5067 else break;
5068 }
5069
5070 // search for trailing empty lines
5071 int b=l-1,bi=-1;
5072 p=s.data()+b;
5073 while (b>=0)
5074 {
5075 c=*p;
5076 if (c==' ' || c=='\t' || c=='\r') { b--; p--; }
5077 else if (c=='r' && b>=7 && literal_at(p-7,"\\ilinebr")) { bi=b-7; b-=8; p-=8; }
5078 else if (c=='>' && b>=11 && literal_at(p-11,"\\ilinebr<br>")) { bi=b-11; b-=12; p-=12; }
5079 else if (c=='\n') { bi=b; b--; p--; }
5080 else break;
5081 }
5082
5083 // return whole string if no leading or trailing lines where found
5084 if (li==-1 && bi==-1) return s;
5085
5086 // return substring
5087 if (bi==-1) bi=l;
5088 if (li==-1) li=0;
5089 if (bi<=li) return QCString(); // only empty lines
5090 //printf("docLine='%s' len=%d li=%d bi=%d\n",qPrint(s),s.length(),li,bi);
5091 return s.mid(li,bi-li);
5092}

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

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

◆ stripPath()

QCString stripPath ( const QCString & s)

Definition at line 4973 of file util.cpp.

4974{
4975 QCString result=s;
4976 int i=result.findRev('/');
4977 if (i!=-1)
4978 {
4979 result=result.mid(i+1);
4980 }
4981 i=result.findRev('\\');
4982 if (i!=-1)
4983 {
4984 result=result.mid(i+1);
4985 }
4986 return result;
4987}

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

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

◆ stripScope()

QCString stripScope ( const QCString & name)

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

Definition at line 3800 of file util.cpp.

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

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

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

◆ stripTemplateSpecifiersFromScope()

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

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

Definition at line 4552 of file util.cpp.

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

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

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

◆ substituteKeywords() [1/2]

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

Definition at line 3075 of file util.cpp.

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

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

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

◆ substituteKeywords() [2/2]

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

Definition at line 3227 of file util.cpp.

3229{
3230 return substituteKeywords(file,s,
3231 {
3232 // keyword value getter
3233 { "$title", [&]() { return !title.isEmpty() ? title : projName; } },
3234 { "$doxygenversion", [&]() { return getDoxygenVersion(); } },
3235 { "$projectname", [&]() { return projName; } },
3236 { "$projectnumber", [&]() { return projNum; } },
3237 { "$projectbrief", [&]() { return projBrief; } },
3238 { "$projectlogo", [&]() { return stripPath(projectLogoFile()); } },
3239 { "$logosize", [&]() { return projectLogoSize(); } },
3240 { "$projecticon", [&]() { return stripPath(Config_getString(PROJECT_ICON)); } },
3241 { "$langISO", [&]() { return theTranslator->trISOLang(); } },
3242 { "$showdate", [&](const QCString &fmt) { return showDate(fmt); } }
3243 });
3244}
QCString substituteKeywords(const QCString &file, const QCString &s, const KeywordSubstitutionList &keywords)
Definition util.cpp:3075
QCString projectLogoFile()
Definition util.cpp:3161
static QCString projectLogoSize()
Definition util.cpp:3182
static QCString showDate(const QCString &fmt)
Definition util.cpp:3148

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

◆ substituteTemplateArgumentsInString()

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

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

Definition at line 4390 of file util.cpp.

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

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

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

◆ tempArgListToString()

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

Definition at line 1299 of file util.cpp.

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

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

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

◆ transcodeCharacterBuffer()

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

Definition at line 5538 of file util.cpp.

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

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

Referenced by readInputFile().

◆ transcodeCharacterStringToUTF8()

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

Definition at line 1456 of file util.cpp.

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

References QCString::at(), QCString::ExplicitSize, portable_iconv(), portable_iconv_close(), portable_iconv_open(), qstricmp(), QCString::rawData(), QCString::resize(), and QCString::str().

Referenced by LayoutDocManager::parse(), and readCodeFragment().

◆ trimBaseClassScope()

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

Definition at line 1531 of file util.cpp.

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

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

Referenced by trimBaseClassScope().

◆ unescapeCharsInString()

QCString unescapeCharsInString ( const QCString & s)

Definition at line 3437 of file util.cpp.

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

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

◆ updateColumnCount()

size_t updateColumnCount ( const char * s,
size_t col )

Definition at line 6902 of file util.cpp.

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

References Config_getInt, and getUTF8CharNumBytes().

Referenced by HtmlCodeGenerator::codify(), LatexCodeGenerator::codify(), ManCodeGenerator::codify(), RTFCodeGenerator::codify(), writeDocbookCodeString(), and writeXMLCodeString().

◆ updateLanguageMapping()

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

Definition at line 5130 of file util.cpp.

5131{
5132 QCString langName = language.lower();
5133 auto it1 = std::find_if(g_lang2extMap.begin(),g_lang2extMap.end(),
5134 [&langName](const auto &info) { return info.langName==langName; });
5135 if (it1 == g_lang2extMap.end()) return false;
5136
5137 // found the language
5138 SrcLangExt parserId = it1->parserId;
5139 QCString extName = extension.lower();
5140 if (extName.isEmpty()) return FALSE;
5141 if (extName.at(0)!='.') extName.prepend(".");
5142 auto it2 = g_extLookup.find(extName.str());
5143 if (it2!=g_extLookup.end())
5144 {
5145 g_extLookup.erase(it2); // language was already register for this ext
5146 }
5147 //printf("registering extension %s\n",qPrint(extName));
5148 g_extLookup.emplace(extName.str(),parserId);
5149 if (!Doxygen::parserManager->registerExtension(extName,it1->parserName))
5150 {
5151 err("Failed to assign extension {} to parser {} for language {}\n",
5152 extName.data(),it1->parserName,language);
5153 }
5154 else
5155 {
5156 //msg("Registered extension {} to language parser {}...\n",
5157 // extName,language);
5158 }
5159 return TRUE;
5160}
SrcLangExt
Definition types.h:207

References QCString::at(), QCString::data(), err, FALSE, g_extLookup, g_lang2extMap, QCString::isEmpty(), QCString::lower(), Doxygen::parserManager, QCString::prepend(), QCString::str(), and TRUE.

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

◆ writeExamples()

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

Definition at line 1175 of file util.cpp.

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

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

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

◆ writeFileContents()

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

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

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

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

Definition at line 6981 of file util.cpp.

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

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

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

◆ writeHtmlEntity()

template<class T>
const char * writeHtmlEntity ( T & t,
const char * s,
HtmlEntityMapperFunc && mapper,
const char * fallback )

Writes an HTML entity for the current symbol and advances the input pointer.

Template Parameters
TType of the output sink used to write encoded output.
Parameters
tOutput target receiving the encoded entity or fallback text.
sPointer to the start of a potential HTML entity in the input text.
mapperCallback that maps a entity symbol type to its HTML entity string.
fallbackFallback string written when no entity mapping is available.
Returns
Pointer to the position after the processed HTML entity in the input text.

Definition at line 7034 of file util.cpp.

7035{
7036 assert(s!=nullptr);
7037 assert(s[0]=='&');
7038 const char *q = s+1;
7039 size_t cnt = 2; // we have to count & and ; as well
7040 while ((*q >= 'a' && *q <= 'z') || (*q >= 'A' && *q <= 'Z') || (*q >= '0' && *q <= '9'))
7041 {
7042 cnt++;
7043 q++;
7044 }
7045 if (*q == ';') // valid entity name
7046 {
7049 {
7050 if constexpr (has_insertion_op_v<T>)
7051 {
7052 result << mapper(res);
7053 }
7054 else
7055 {
7056 result += mapper(res);
7057 }
7058 return q+1;
7059 }
7060 }
7061 if constexpr (has_insertion_op_v<T>)
7062 {
7063 result << fallback;
7064 }
7065 else
7066 {
7067 result += fallback;
7068 }
7069 return s+1;
7070}
constexpr bool has_insertion_op_v
Definition util.cpp:7031

Referenced by DocbookGenerator::convertToDocbook(), convertToXML(), HtmlDocVisitor::filter(), ManDocVisitor::filter(), RTFDocVisitor::filter(), and filterLatexString().

◆ writeHtmlEntity< QCString >()

template const char * writeHtmlEntity< QCString > ( QCString & t,
const char * s,
HtmlEntityMapperFunc && mapper,
const char * fallback )

◆ writeHtmlEntity< TextStream >()

template const char * writeHtmlEntity< TextStream > ( TextStream & t,
const char * s,
HtmlEntityMapperFunc && mapper,
const char * fallback )

◆ writeMarkerList() [1/2]

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

Definition at line 1147 of file util.cpp.

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

References end().

◆ writeMarkerList() [2/2]

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

Definition at line 1124 of file util.cpp.

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

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

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

◆ writePageRef()

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

◆ writeTypeConstraints()

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

Definition at line 5483 of file util.cpp.

5484{
5485 if (al.empty()) return;
5486 ol.startConstraintList(theTranslator->trTypeConstraints());
5487 for (const Argument &a : al)
5488 {
5490 ol.parseText(a.name);
5491 ol.endConstraintParam();
5493 linkifyText(TextGeneratorOLImpl(ol),a.type,LinkifyTextOptions().setScope(d));
5494 ol.endConstraintType();
5496 ol.generateDoc(d->docFile(),
5497 d->docLine(),
5498 d,
5499 nullptr,
5500 a.docs,
5501 DocOptions()
5502 .setIndexWords(true));
5503 ol.endConstraintDocs();
5504 }
5505 ol.endConstraintList();
5506}
virtual int docLine() const =0
void endConstraintType()
Definition outputlist.h:714
void endConstraintList()
Definition outputlist.h:720
void startConstraintParam()
Definition outputlist.h:708
void generateDoc(const QCString &fileName, int startLine, const Definition *ctx, const MemberDef *md, const QCString &docStr, const DocOptions &options)
void startConstraintDocs()
Definition outputlist.h:716
void startConstraintType()
Definition outputlist.h:712
void endConstraintDocs()
Definition outputlist.h:718
void endConstraintParam()
Definition outputlist.h:710
void startConstraintList(const QCString &header)
Definition outputlist.h:706
Implements TextGeneratorIntf for an OutputDocInterface stream.
Definition util.h:77
void linkifyText(const TextGeneratorIntf &out, const QCString &text, const LinkifyTextOptions &options)
Definition util.cpp:893

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

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

Variable Documentation

◆ constScope

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

Definition at line 520 of file util.cpp.

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

Referenced by removeRedundantWhiteSpace().

◆ g_charAroundSpace

CharAroundSpace g_charAroundSpace
static

Definition at line 564 of file util.cpp.

Referenced by removeRedundantWhiteSpace().

◆ g_docCache

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

Definition at line 5447 of file util.cpp.

Referenced by parseCommentAsHtml().

◆ g_docCacheMutex

std::mutex g_docCacheMutex
static

Definition at line 5446 of file util.cpp.

Referenced by parseCommentAsHtml().

◆ g_extLookup

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

Definition at line 5096 of file util.cpp.

Referenced by getLanguageFromFileName(), and updateLanguageMapping().

◆ g_findFileDefCache

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

Referenced by findFileDef().

◆ g_findFileDefMutex

std::mutex g_findFileDefMutex
static

Definition at line 2902 of file util.cpp.

Referenced by findFileDef().

◆ g_lang2extMap

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

Definition at line 5106 of file util.cpp.

5106 {
5107// language parser parser option
5108 { "idl", "c", SrcLangExt::IDL, ".idl" },
5109 { "java", "c", SrcLangExt::Java, ".java"},
5110 { "javascript", "c", SrcLangExt::JS, ".js" },
5111 { "csharp", "c", SrcLangExt::CSharp, ".cs" },
5112 { "d", "c", SrcLangExt::D, ".d" },
5113 { "php", "c", SrcLangExt::PHP, ".php" },
5114 { "objective-c", "c", SrcLangExt::ObjC, ".m" },
5115 { "c", "c", SrcLangExt::Cpp, ".c" },
5116 { "c++", "c", SrcLangExt::Cpp, ".cpp" },
5117 { "slice", "c", SrcLangExt::Slice, ".ice" },
5118 { "python", "python", SrcLangExt::Python, ".py" },
5119 { "fortran", "fortran", SrcLangExt::Fortran, ".f" },
5120 { "fortranfree", "fortranfree", SrcLangExt::Fortran, ".f90" },
5121 { "fortranfixed", "fortranfixed", SrcLangExt::Fortran, ".f" },
5122 { "vhdl", "vhdl", SrcLangExt::VHDL, ".vhdl"},
5123 { "xml", "xml", SrcLangExt::XML, ".xml" },
5124 { "sql", "sql", SrcLangExt::SQL, ".sql" },
5125 { "md", "md", SrcLangExt::Markdown, ".md" },
5126 { "lex", "lex", SrcLangExt::Lex, ".l" },
5127};

Referenced by getLanguageFromCodeLang(), and updateLanguageMapping().

◆ g_matchArgsMutex

std::mutex g_matchArgsMutex
static

Definition at line 1923 of file util.cpp.

Referenced by matchArgument2().

◆ g_usedNames

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

Definition at line 3515 of file util.cpp.

Referenced by convertNameToFile().

◆ g_usedNamesCount

int g_usedNamesCount =1
static

Definition at line 3517 of file util.cpp.

Referenced by convertNameToFile().

◆ g_usedNamesMutex

std::mutex g_usedNamesMutex
static

Definition at line 3516 of file util.cpp.

Referenced by convertNameToFile().

◆ has_insertion_op_v

template<typename T>
bool has_insertion_op_v = has_insertion_op<T>::value
inlineconstexpr

Definition at line 7031 of file util.cpp.

◆ hex

const char* hex = "0123456789ABCDEF"
static

Definition at line 96 of file util.cpp.

◆ operatorScope

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

Definition at line 523 of file util.cpp.

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

Referenced by removeRedundantWhiteSpace().

◆ virtualScope

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

Definition at line 522 of file util.cpp.

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

Referenced by removeRedundantWhiteSpace().

◆ volatileScope

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

Definition at line 521 of file util.cpp.

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

Referenced by removeRedundantWhiteSpace().

◆ writeFileContents_lock

std::mutex writeFileContents_lock
static

Definition at line 6970 of file util.cpp.

Referenced by writeFileContents().

◆ writeFileContents_set

StringUnorderedSet writeFileContents_set
static

Definition at line 6971 of file util.cpp.

Referenced by cleanupInlineGraph(), and writeFileContents().