Doxygen
Loading...
Searching...
No Matches
filename.cpp
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * Copyright (C) 1997-2026 by Dimitri van Heesch.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
10 *
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
13 *
14 */
15
16#include <mutex>
17
18#include "cache.h"
19#include "filename.h"
20#include "filedef.h"
21#include "dir.h"
22#include "portable.h"
23
24/** Cache element for the file name to FileDef mapping cache. */
26{
27 FindFileCacheElem(FileDef *fd,bool ambig) : fileDef(fd), isAmbig(ambig) {}
29 bool isAmbig;
30};
31
33
34static std::mutex g_findFileDefMutex;
35
36FileDef *FileNameLinkedMap::findFileDef(const DString &n, bool &ambig) const
37{
38 ambig=false;
39 if (n.empty()) return nullptr;
40
41
42 const int maxAddrSize = 20;
43 char addr[maxAddrSize];
44 snprintf(addr,maxAddrSize,"%p:",reinterpret_cast<const void*>(this));
45 DString key = addr;
46 key+=n;
47
48 std::lock_guard<std::mutex> lock(g_findFileDefMutex);
49 FindFileCacheElem *cachedResult = g_findFileDefCache.find(key.str());
50 //printf("key=%s cachedResult=%p\n",qPrint(key),cachedResult);
51 if (cachedResult)
52 {
53 ambig = cachedResult->isAmbig;
54 //printf("cached: fileDef=%p\n",cachedResult->fileDef);
55 return cachedResult->fileDef;
56 }
57 else
58 {
59 cachedResult = g_findFileDefCache.insert(key.str(),FindFileCacheElem(nullptr,false));
60 }
61
63 DString path;
64 if (name.empty()) return nullptr;
65 size_t sp0 = name.rfind('/');
66 size_t sp1 = name.rfind('\\');
67 size_t slashPos = sp0!=DString::npos && sp1!=DString::npos ? std::max(sp0,sp1) :
68 sp0!=DString::npos ? sp0 : sp1;
69 if (slashPos!=DString::npos)
70 {
71 path=removeLongPathMarker(name.left(slashPos+1));
72 name=name.mid(slashPos+1);
73 }
74 if (name.empty()) return nullptr;
75 const FileName *fn = this->find(name);
76 if (fn)
77 {
78 //printf("fn->size()=%zu\n",fn->size());
79 if (fn->size()==1)
80 {
81 const std::unique_ptr<FileDef> &fd = fn->front();
82 bool isSamePath = Portable::fileSystemIsCaseSensitive() ?
83 fd->getPath().right(path.length())==path :
84 fd->getPath().right(path.length()).lower()==path.lower();
85 if (path.empty() || isSamePath)
86 {
87 cachedResult->fileDef = fd.get();
88 return fd.get();
89 }
90 }
91 else // file name alone is ambiguous
92 {
93 int count=0;
94 FileDef *lastMatch=nullptr;
95 DString pathStripped = stripFromIncludePath(path);
96 for (const auto &fd_p : *fn)
97 {
98 FileDef *fd = fd_p.get();
99 DString fdStripPath = stripFromIncludePath(fd->getPath());
100 if (fdStripPath == pathStripped)
101 {
102 // if the stripped paths are equal, we have a perfect match
103 count = 1;
104 lastMatch=fd;
105 break;
106 }
107 if (path.empty() ||
108 (!pathStripped.empty() && fdStripPath.endsWith(pathStripped)) ||
109 (pathStripped.empty() && fdStripPath.empty()))
110 {
111 count++;
112 lastMatch=fd;
113 }
114 }
115
116 ambig=(count>1);
117 cachedResult->isAmbig = ambig;
118 cachedResult->fileDef = lastMatch;
119 return lastMatch;
120 }
121 }
122 else
123 {
124 //printf("not found!\n");
125 }
126 return nullptr;
127}
128
130{
131 DString result;
132 DString name=Dir::cleanDirPath(n.str());
133 DString path;
134 size_t sp0 = name.rfind('/');
135 size_t sp1 = name.rfind('\\');
136 size_t slashPos = sp0!=DString::npos && sp1!=DString::npos ? std::max(sp0,sp1) :
137 sp0!=DString::npos ? sp0 : sp1;
138 if (slashPos!=DString::npos)
139 {
140 path=removeLongPathMarker(name.left(slashPos+1));
141 name=name.mid(slashPos+1);
142 }
143 const FileName *fn=this->find(name);
144 if (fn)
145 {
146 bool first = true;
147 DString pathStripped = stripFromIncludePath(path);
148 for (const auto &fd_p : *fn)
149 {
150 FileDef *fd = fd_p.get();
151 DString fdStripPath = stripFromIncludePath(fd->getPath());
152 if (path.empty() ||
153 (!pathStripped.empty() && fdStripPath.endsWith(pathStripped)) ||
154 (pathStripped.empty() && fdStripPath.empty()))
155 {
156 if (!first) result += "\n";
157 else first = false;
158 result+=" "+fd->absFilePath();
159 }
160 }
161
162 }
163 return result;
164}
165
166
Definition cache.h:32
A String class for use with Doxygen wrapping std::string and adding some additional functionality off...
Definition dstring.h:89
size_t rfind(char c, size_t pos=npos) const
Definition dstring.h:249
DString mid(size_t index, size_t len=npos) const
Definition dstring.h:323
DString lower() const
Definition dstring.h:331
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:153
static constexpr size_t npos
value used to indicate 'not found' or 'to the end of the string', matching std::string::npos
Definition dstring.h:183
DString right(size_t len) const
Definition dstring.h:316
DString left(size_t len) const
Definition dstring.h:311
const std::string & str() const
Definition dstring.h:634
bool endsWith(const char *s) const
Definition dstring.h:606
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition dstring.h:156
static std::string cleanDirPath(const std::string &path)
Definition dir.cpp:357
A model of a file symbol.
Definition filedef.h:99
virtual DString getPath() const =0
virtual DString absFilePath() const =0
Class representing all files with a certain base name.
Definition filename.h:30
DString showFileDefMatches(const DString &n) const
Returns a list of file definitions in fnMap that match the file name n.
Definition filename.cpp:129
FileDef * findFileDef(const DString &n, bool &ambig) const
Returns the file definition in fnMap that matches the file name n.
Definition filename.cpp:36
static Cache< std::string, FindFileCacheElem > g_findFileDefCache(5000)
static std::mutex g_findFileDefMutex
Definition filename.cpp:34
bool fileSystemIsCaseSensitive()
Definition portable.cpp:470
Portable versions of functions that are platform dependent.
Cache element for the file name to FileDef mapping cache.
Definition filename.cpp:26
FileDef * fileDef
Definition filename.cpp:28
FindFileCacheElem(FileDef *fd, bool ambig)
Definition filename.cpp:27
DString stripFromIncludePath(const DString &path)
Definition util.cpp:259
DString removeLongPathMarker(const DString &path)
Definition util.cpp:212