1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
// slang-include-system.cpp
#include "slang-include-system.h"
#include "../core/slang-file-system.h"
#include "../core/slang-io.h"
#include "../core/slang-string-util.h"
#include "slang-artifact-impl.h"
#include "slang-artifact-representation-impl.h"
#include "slang-slice-allocator.h"
namespace Slang
{
IncludeSystem::IncludeSystem(
SearchDirectoryList* searchDirectories,
ISlangFileSystemExt* fileSystemExt,
SourceManager* sourceManager)
: m_searchDirectories(searchDirectories)
, m_fileSystemExt(fileSystemExt)
, m_sourceManager(sourceManager)
{
}
SlangResult IncludeSystem::findFile(
SlangPathType fromPathType,
const String& fromPath,
const String& path,
PathInfo& outPathInfo)
{
String combinedPath;
if (fromPath.getLength() == 0 || Path::isAbsolute(path))
{
// If the path is absolute or the fromPath is empty, the combined path is just the path
combinedPath = path;
}
else
{
// Get relative path
ComPtr<ISlangBlob> combinedPathBlob;
SLANG_RETURN_ON_FAIL(m_fileSystemExt->calcCombinedPath(
fromPathType,
fromPath.begin(),
path.begin(),
combinedPathBlob.writeRef()));
combinedPath = StringUtil::getString(combinedPathBlob);
if (combinedPath.getLength() <= 0)
{
return SLANG_FAIL;
}
}
// This checks the path exists
SlangPathType pathType;
SLANG_RETURN_ON_FAIL(m_fileSystemExt->getPathType(combinedPath.begin(), &pathType));
if (pathType != SLANG_PATH_TYPE_FILE)
{
return SLANG_E_NOT_FOUND;
}
// Get the uniqueIdentity
ComPtr<ISlangBlob> uniqueIdentityBlob;
SLANG_RETURN_ON_FAIL(m_fileSystemExt->getFileUniqueIdentity(
combinedPath.begin(),
uniqueIdentityBlob.writeRef()));
// If the rel path exists -> a uniqueIdentity MUST exists too
String uniqueIdentity(StringUtil::getString(uniqueIdentityBlob));
if (uniqueIdentity.getLength() <= 0)
{
// Unique identity can't be empty
return SLANG_FAIL;
}
outPathInfo = PathInfo::makeNormal(combinedPath, uniqueIdentity);
return SLANG_OK;
}
String IncludeSystem::simplifyPath(const String& path)
{
ComPtr<ISlangBlob> simplifiedPath;
if (SLANG_FAILED(m_fileSystemExt->getPath(
PathKind::Simplified,
path.getBuffer(),
simplifiedPath.writeRef())))
{
return path;
}
return StringUtil::getString(simplifiedPath);
}
SlangResult IncludeSystem::findFile(
String const& pathToInclude,
String const& pathIncludedFrom,
PathInfo& outPathInfo)
{
outPathInfo.type = PathInfo::Type::Unknown;
// If it's absolute we only have to try and find if it's there - no need to look at search paths
if (Path::isAbsolute(pathToInclude))
{
// We pass in "" as the from path, so ensure no from path is taken into account
// and to allow easy identification that this is in effect absolute
return findFile(
SLANG_PATH_TYPE_DIRECTORY,
UnownedStringSlice::fromLiteral(""),
pathToInclude,
outPathInfo);
}
// Try just relative to current path
{
SlangResult res =
findFile(SLANG_PATH_TYPE_FILE, pathIncludedFrom, pathToInclude, outPathInfo);
// It either succeeded or wasn't found, anything else is a failure passed back
if (SLANG_SUCCEEDED(res) || res != SLANG_E_NOT_FOUND)
{
return res;
}
}
// Search all the searchDirectories
for (auto sd = m_searchDirectories; sd; sd = sd->parent)
{
for (auto& dir : sd->searchDirectories)
{
SlangResult res =
findFile(SLANG_PATH_TYPE_DIRECTORY, dir.path, pathToInclude, outPathInfo);
if (SLANG_SUCCEEDED(res) || res != SLANG_E_NOT_FOUND)
{
return res;
}
}
}
return SLANG_E_NOT_FOUND;
}
SlangResult IncludeSystem::loadFile(
const PathInfo& pathInfo,
ComPtr<ISlangBlob>& outBlob,
SourceFile*& outSourceFile)
{
if (m_sourceManager)
{
// See if this an already loaded source file
outSourceFile = m_sourceManager->findSourceFileRecursively(pathInfo.uniqueIdentity);
// If not create a new one, and add to the list of known source files
if (!outSourceFile)
{
ComPtr<ISlangBlob> foundSourceBlob;
if (SLANG_FAILED(m_fileSystemExt->loadFile(
pathInfo.foundPath.getBuffer(),
foundSourceBlob.writeRef())))
{
return SLANG_E_CANNOT_OPEN;
}
outSourceFile = m_sourceManager->createSourceFileWithBlob(pathInfo, foundSourceBlob);
m_sourceManager->addSourceFile(pathInfo.uniqueIdentity, outSourceFile);
outBlob = foundSourceBlob;
return SLANG_OK;
}
else
{
if (outSourceFile->getContentBlob())
{
outBlob = outSourceFile->getContentBlob();
return SLANG_OK;
}
ComPtr<ISlangBlob> foundSourceBlob;
if (SLANG_FAILED(m_fileSystemExt->loadFile(
pathInfo.foundPath.getBuffer(),
foundSourceBlob.writeRef())))
{
return SLANG_E_CANNOT_OPEN;
}
outSourceFile->setContents(foundSourceBlob);
outBlob = foundSourceBlob;
return SLANG_OK;
}
}
else
{
// If we don't have the source manager, just load
outSourceFile = nullptr;
return m_fileSystemExt->loadFile(pathInfo.foundPath.getBuffer(), outBlob.writeRef());
}
}
SlangResult IncludeSystem::findAndLoadFile(
const String& pathToInclude,
const String& pathIncludedFrom,
PathInfo& outPathInfo,
ComPtr<ISlangBlob>& outBlob)
{
SLANG_RETURN_ON_FAIL(findFile(pathToInclude, pathIncludedFrom, outPathInfo));
SLANG_RETURN_ON_FAIL(loadFile(outPathInfo, outBlob));
return SLANG_OK;
}
} // namespace Slang
|