summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2020-11-19 04:14:48 -0500
committerGitHub <noreply@github.com>2020-11-19 01:14:48 -0800
commitb59451020eee59cd52e4d8231360ebed4fc59adb (patch)
treea5a77794097ee99bbef91b8f28be8788284e7736
parentac41b9956681d54f4487ff06922017f2753d0c45 (diff)
File system refactor (#1611)
* #include an absolute path didn't work - because paths were taken to always be relative. * WIP FileSystem refactor. * Made loadFile load the file in binary mode. * Fixed some comments. Fixed typo in RelativePath - not used 'fixedPath'.
-rw-r--r--slang.h51
-rw-r--r--source/core/slang-blob.h88
-rw-r--r--source/core/slang-io.cpp43
-rw-r--r--source/core/slang-io.h5
-rw-r--r--source/slang/slang-file-system.cpp393
-rw-r--r--source/slang/slang-file-system.h196
-rw-r--r--source/slang/slang-options.cpp12
-rw-r--r--source/slang/slang-repro.cpp4
-rw-r--r--source/slang/slang-repro.h2
-rw-r--r--source/slang/slang.cpp4
10 files changed, 573 insertions, 225 deletions
diff --git a/slang.h b/slang.h
index 10dfb2b18..4304f3e20 100644
--- a/slang.h
+++ b/slang.h
@@ -872,6 +872,9 @@ extern "C"
@param outBlob A destination pointer to receive the blob of the file contents.
@returns A `SlangResult` to indicate success or failure in loading the file.
+ NOTE! This is a *binary* load - the blob should contain the exact same bytes
+ as are found in the backing file.
+
If load is successful, the implementation should create a blob to hold
the file's content, store it to `outBlob`, and return 0.
If the load fails, the implementation should return a failure status
@@ -930,6 +933,10 @@ extern "C"
SLANG_PATH_TYPE_FILE, /**< Path specified is to a file. */
};
+ /* Callback to enumerate the contents of of a directory in a ISlangFileSystemExt.
+ The name is the name of a file system object (directory/file) in the specified path (ie it is without a path) */
+ typedef void (*FileSystemContentsCallBack)(SlangPathType pathType, const char* name, void* userData);
+
/** An extended file system abstraction.
Implementing and using this interface over ISlangFileSystem gives much more control over how paths
@@ -1027,9 +1034,26 @@ extern "C"
/** Clears any cached information */
virtual SLANG_NO_THROW void SLANG_MCALL clearCache() = 0;
- /** Write the data specified with data and size to the specified path.
+ /** Enumerate the contents of the path
+
+ Note that for normal Slang operation it isn't necessary to enumerate contents this can return SLANG_E_NOT_IMPLEMENTED.
+
+ @param The path to enumerate
+ @param callback This callback is called for each entry in the path.
+ @param userData This is passed to the callback
+ @returns SLANG_OK if successful
+ */
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL enumeratePathContents(
+ const char* path,
+ FileSystemContentsCallBack callback,
+ void* userData) = 0;
+ };
+
+ #define SLANG_UUID_ISlangFileSystemExt { 0x5fb632d2, 0x979d, 0x4481, { 0x9f, 0xee, 0x66, 0x3c, 0x3f, 0x14, 0x49, 0xe1 } }
- Note that for normal slang operation it doesn't write files so this can return SLANG_E_NOT_IMPLEMENTED.
+ struct ISlangMutableFileSystem : public ISlangFileSystemExt
+ {
+ /** Write the data specified with data and size to the specified path.
@param path The path for data to be saved to
@param data The data to be saved
@@ -1040,9 +1064,28 @@ extern "C"
const char* path,
const void* data,
size_t size) = 0;
+
+ /** Remove the entry in the path (directory of file). Will only delete an empty directory, if not empty
+ will return an error.
+
+ @param path The path to remove
+ @returns SLANG_OK if successful
+ */
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL remove(
+ const char* path) = 0;
+
+ /** Create a directory.
+
+ The path to the directory must exist
+
+ @param path To the directory to create. The parent path *must* exist otherwise will return an error.
+ @returns SLANG_OK if successful
+ */
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL createDirectory(
+ const char* path) = 0;
};
- #define SLANG_UUID_ISlangFileSystemExt { 0x5fb632d2, 0x979d, 0x4481, { 0x9f, 0xee, 0x66, 0x3c, 0x3f, 0x14, 0x49, 0xe1 } }
+ #define SLANG_UUID_ISlangMutableFileSystem { 0xa058675c, 0x1d65, 0x452a, { 0x84, 0x58, 0xcc, 0xde, 0xd1, 0x42, 0x71, 0x5 } }
/* Identifies different types of writer target*/
typedef unsigned int SlangWriterChannel;
@@ -1773,7 +1816,7 @@ extern "C"
SlangSession* session,
const void* reproData,
size_t reproDataSize,
- ISlangFileSystemExt* fileSystem);
+ ISlangMutableFileSystem* fileSystem);
/* Turns a repro into a file system.
diff --git a/source/core/slang-blob.h b/source/core/slang-blob.h
index aab131a36..8bf02512d 100644
--- a/source/core/slang-blob.h
+++ b/source/core/slang-blob.h
@@ -69,30 +69,96 @@ protected:
void operator=(const ThisType& rhs) = delete;
};
+
+class ScopedAllocation
+{
+public:
+ typedef ScopedAllocation ThisType;
+ // Returns the allocation if successful.
+ void* allocate(size_t size)
+ {
+ deallocate();
+ m_data = ::malloc(size);
+ m_sizeInBytes = size;
+ return m_data;
+ }
+ /// Deallocates if holds an allocation
+ void deallocate()
+ {
+ if (m_data)
+ {
+ ::free(m_data);
+ m_data = nullptr;
+ }
+ m_sizeInBytes = 0;
+ }
+ /// Makes this no longer own the allocation. Returns the allocated data (or nullptr if no allocation)
+ void* detach()
+ {
+ void* data = m_data;
+ m_data = nullptr;
+ m_sizeInBytes = 0;
+ return data;
+ }
+ /// Attach some data.
+ /// NOTE! data must be a pointer that was returned from malloc, otherwise will incorrectly free.
+ void attach(void* data, size_t size)
+ {
+ deallocate();
+ m_data = data;
+ m_sizeInBytes = size;
+ }
+
+ /// Get the allocated data. Returns nullptr if there is no allocated data
+ void* getData() const { return m_data; }
+ /// Get the size of the allocated data.
+ size_t getSizeInBytes() const { return m_sizeInBytes; }
+
+ ScopedAllocation() :
+ m_data(nullptr),
+ m_sizeInBytes(0)
+ {
+ }
+
+private:
+ // disable
+ ScopedAllocation(const ThisType& rhs) = delete;
+ void operator=(const ThisType& rhs) = delete;
+
+ void* m_data;
+ size_t m_sizeInBytes;
+};
+
/** A blob that manages some raw data that it owns.
*/
class RawBlob : public BlobBase
{
public:
// ISlangBlob
- SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_data; }
- SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_size; }
+ SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_data.getData(); }
+ SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_data.getSizeInBytes(); }
- // Ctor
- RawBlob(const void* data, size_t size) :
- m_size(size)
+ // Ctor
+ // NOTE! Takes a copy of the input data
+ RawBlob(const void* data, size_t size)
{
- m_data = malloc(size);
- memcpy(m_data, data, size);
+ memcpy(m_data.allocate(size), data, size);
}
- ~RawBlob()
+
+ /// Moves ownership of data and dataCount to the blob
+ /// data must be a pointer returned by ::malloc.
+ static RefPtr<RawBlob> moveCreate(uint8_t* data, size_t dataCount)
{
- free(m_data);
+ RawBlob* blob = new RawBlob;
+ blob->m_data.attach(data, dataCount);
+ return blob;
}
protected:
- void* m_data;
- size_t m_size;
+ RawBlob() = default;
+
+ ScopedAllocation m_data;
+
};
/// Create a blob that will retain (a copy of) raw data.
diff --git a/source/core/slang-io.cpp b/source/core/slang-io.cpp
index 5cbe021a2..8e7266dc5 100644
--- a/source/core/slang-io.cpp
+++ b/source/core/slang-io.cpp
@@ -557,6 +557,49 @@ namespace Slang
#endif
}
+ SlangResult Path::remove(const String& path)
+ {
+#ifdef _WIN32
+ // Need to determine if its a file or directory
+
+ SlangPathType pathType;
+ SLANG_RETURN_ON_FAIL(getPathType(path, &pathType));
+
+
+ switch (pathType)
+ {
+ case SLANG_PATH_TYPE_FILE:
+ {
+ // https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-deletefilea
+ if (DeleteFileA(path.getBuffer()))
+ {
+ return SLANG_OK;
+ }
+ break;
+ }
+ case SLANG_PATH_TYPE_DIRECTORY:
+ {
+ // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-removedirectorya
+ if (RemoveDirectoryA(path.getBuffer()))
+ {
+ return SLANG_OK;
+ }
+ break;
+ }
+ default: break;
+ }
+
+ return SLANG_FAIL;
+#else
+ // https://linux.die.net/man/3/remove
+ if (::remove(path.getBuffer()) == 0)
+ {
+ return SLANG_OK;
+ }
+ return SLANG_FAIL;
+#endif
+ }
+
#if defined(_WIN32)
/* static */SlangResult Path::find(const String& directoryPath, const char* pattern, Visitor* visitor)
{
diff --git a/source/core/slang-io.h b/source/core/slang-io.h
index 492723602..3a5510566 100644
--- a/source/core/slang-io.h
+++ b/source/core/slang-io.h
@@ -126,6 +126,11 @@ namespace Slang
/// @param path Path to extract first element from
/// @return The first element of the path, or empty
static UnownedStringSlice getFirstElement(const UnownedStringSlice& path);
+
+ /// Remove a file or directory at specified path. The directory must be empty for it to be removed
+ /// @param path
+ /// @return SLANG_OK if file or directory is removed
+ static SlangResult remove(const String& path);
};
// Helper class to clean up temporary files on dtor
diff --git a/source/slang/slang-file-system.cpp b/source/slang/slang-file-system.cpp
index d3d1fd9f5..6dbcc864d 100644
--- a/source/slang/slang-file-system.cpp
+++ b/source/slang/slang-file-system.cpp
@@ -11,8 +11,54 @@ namespace Slang
static const Guid IID_ISlangUnknown = SLANG_UUID_ISlangUnknown;
static const Guid IID_ISlangFileSystem = SLANG_UUID_ISlangFileSystem;
static const Guid IID_ISlangFileSystemExt = SLANG_UUID_ISlangFileSystemExt;
+static const Guid IID_ISlangMutableFileSystem = SLANG_UUID_ISlangMutableFileSystem;
+
static const Guid IID_SlangCacheFileSystem = SLANG_UUID_CacheFileSystem;
+SLANG_FORCE_INLINE static SlangResult _checkExt(FileSystemStyle style) { return Index(style) >= Index(FileSystemStyle::Ext) ? SLANG_OK : SLANG_E_NOT_IMPLEMENTED; }
+SLANG_FORCE_INLINE static SlangResult _checkMutable(FileSystemStyle style) { return Index(style) >= Index(FileSystemStyle::Mutable) ? SLANG_OK : SLANG_E_NOT_IMPLEMENTED; }
+
+SLANG_FORCE_INLINE static bool _canCast(FileSystemStyle style, const Guid& guid)
+{
+ if (guid == IID_ISlangUnknown || guid == IID_ISlangFileSystem)
+ {
+ return true;
+ }
+ else if (guid == IID_ISlangFileSystemExt)
+ {
+ return Index(style) >= Index(FileSystemStyle::Ext);
+ }
+ else if (guid == IID_ISlangMutableFileSystem)
+ {
+ return Index(style) >= Index(FileSystemStyle::Mutable);
+ }
+ return false;
+}
+
+static FileSystemStyle _getFileSystemStyle(ISlangFileSystem* system, ComPtr<ISlangFileSystem>& out)
+{
+ SLANG_ASSERT(system);
+
+ FileSystemStyle style = FileSystemStyle::Load;
+
+ if (SLANG_SUCCEEDED(system->queryInterface(IID_ISlangMutableFileSystem, (void**)out.writeRef())))
+ {
+ style = FileSystemStyle::Mutable;
+ }
+ else if (SLANG_SUCCEEDED(system->queryInterface(IID_ISlangFileSystemExt, (void**)out.writeRef())))
+ {
+ style = FileSystemStyle::Ext;
+ }
+ else
+ {
+ style = FileSystemStyle::Load;
+ out = system;
+ }
+
+ SLANG_ASSERT(out);
+ return style;
+}
+
// Cacluate a combined path, just using Path:: string processing
static SlangResult _calcCombinedPath(SlangPathType fromPathType, const char* fromPath, const char* path, ISlangBlob** pathOut)
{
@@ -37,26 +83,13 @@ static SlangResult _calcCombinedPath(SlangPathType fromPathType, const char* fro
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! OSFileSystem !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
-/* static */OSFileSystem OSFileSystem::s_singleton;
+/* static */OSFileSystem OSFileSystem::g_load(FileSystemStyle::Load);
+/* static */OSFileSystem OSFileSystem::g_ext(FileSystemStyle::Ext);
+/* static */OSFileSystem OSFileSystem::g_mutable(FileSystemStyle::Mutable);
ISlangUnknown* OSFileSystem::getInterface(const Guid& guid)
{
- return (guid == IID_ISlangUnknown || guid == IID_ISlangFileSystem ) ? static_cast<ISlangFileSystem*>(this) : nullptr;
-}
-
-/* !!!!!!!!!!!!!!!!!!!!!!!!!! OSFileSystemExt !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
-
-/* static */OSFileSystemExt OSFileSystemExt::s_singleton;
-
-template <typename T>
-static ISlangFileSystemExt* _getInterface(T* ptr, const Guid& guid)
-{
- return (guid == IID_ISlangUnknown || guid == IID_ISlangFileSystem || guid == IID_ISlangFileSystemExt) ? static_cast<ISlangFileSystemExt*>(ptr) : nullptr;
-}
-
-ISlangUnknown* OSFileSystemExt::getInterface(const Guid& guid)
-{
- return _getInterface(this, guid);
+ return _canCast(m_style, guid) ? static_cast<ISlangFileSystem*>(this) : nullptr;
}
static String _fixPathDelimiters(const char* pathIn)
@@ -70,39 +103,50 @@ static String _fixPathDelimiters(const char* pathIn)
#endif
}
-SlangResult OSFileSystemExt::getFileUniqueIdentity(const char* pathIn, ISlangBlob** outUniqueIdentity)
+SlangResult OSFileSystem::getFileUniqueIdentity(const char* pathIn, ISlangBlob** outUniqueIdentity)
{
+ SLANG_RETURN_ON_FAIL(_checkExt(m_style));
+
// By default we use the canonical path to uniquely identify a file
return getCanonicalPath(pathIn, outUniqueIdentity);
}
-SlangResult OSFileSystemExt::getCanonicalPath(const char* path, ISlangBlob** outCanonicalPath)
+SlangResult OSFileSystem::getCanonicalPath(const char* path, ISlangBlob** outCanonicalPath)
{
+ SLANG_RETURN_ON_FAIL(_checkExt(m_style));
+
String canonicalPath;
SLANG_RETURN_ON_FAIL(Path::getCanonical(_fixPathDelimiters(path), canonicalPath));
*outCanonicalPath = StringUtil::createStringBlob(canonicalPath).detach();
return SLANG_OK;
}
-SlangResult OSFileSystemExt::getSimplifiedPath(const char* pathIn, ISlangBlob** outSimplifiedPath)
+SlangResult OSFileSystem::getSimplifiedPath(const char* pathIn, ISlangBlob** outSimplifiedPath)
{
+ SLANG_RETURN_ON_FAIL(_checkExt(m_style));
+
String simplifiedPath = Path::simplify(_fixPathDelimiters(pathIn));
*outSimplifiedPath = StringUtil::createStringBlob(simplifiedPath).detach();
return SLANG_OK;
}
-SlangResult OSFileSystemExt::calcCombinedPath(SlangPathType fromPathType, const char* fromPath, const char* path, ISlangBlob** pathOut)
+SlangResult OSFileSystem::calcCombinedPath(SlangPathType fromPathType, const char* fromPath, const char* path, ISlangBlob** pathOut)
{
+ SLANG_RETURN_ON_FAIL(_checkExt(m_style));
+
// Don't need to fix delimiters - because combine path handles both path delimiter types
return _calcCombinedPath(fromPathType, fromPath, path, pathOut);
}
-SlangResult SLANG_MCALL OSFileSystemExt::getPathType(const char* pathIn, SlangPathType* pathTypeOut)
+SlangResult SLANG_MCALL OSFileSystem::getPathType(const char* pathIn, SlangPathType* pathTypeOut)
{
+ SLANG_RETURN_ON_FAIL(_checkExt(m_style));
+
return Path::getPathType(_fixPathDelimiters(pathIn), pathTypeOut);
}
-SlangResult OSFileSystemExt::loadFile(char const* pathIn, ISlangBlob** outBlob)
+
+SlangResult OSFileSystem::loadFile(char const* pathIn, ISlangBlob** outBlob)
{
// Default implementation that uses the `core` libraries facilities for talking to the OS filesystem.
//
@@ -118,8 +162,36 @@ SlangResult OSFileSystemExt::loadFile(char const* pathIn, ISlangBlob** outBlob)
try
{
- String sourceString = File::readAllText(path);
- *outBlob = StringUtil::createStringBlob(sourceString).detach();
+ FileStream stream(path, FileMode::Open, FileAccess::Read, FileShare::ReadWrite);
+
+ stream.seek(SeekOrigin::End, 0);
+ const Int64 positionSizeInBytes = stream.getPosition();
+ stream.seek(SeekOrigin::Start, 0);
+
+ if (UInt64(positionSizeInBytes) > UInt64(~size_t(0)))
+ {
+ // It's too large to fit in memory.
+ return SLANG_FAIL;
+ }
+
+ const size_t sizeInBytes = size_t(positionSizeInBytes);
+
+ ScopedAllocation alloc;
+ void* data = alloc.allocate(sizeInBytes);
+ if (!data)
+ {
+ return SLANG_E_OUT_OF_MEMORY;
+ }
+
+ const size_t readSizeInBytes = stream.read(data, sizeInBytes);
+
+ // If not all read just return an error
+ if (sizeInBytes != readSizeInBytes)
+ {
+ return SLANG_FAIL;
+ }
+
+ *outBlob = RawBlob::moveCreate((uint8_t*)alloc.detach(), sizeInBytes).detach();
return SLANG_OK;
}
catch (...)
@@ -128,8 +200,48 @@ SlangResult OSFileSystemExt::loadFile(char const* pathIn, ISlangBlob** outBlob)
return SLANG_E_CANNOT_OPEN;
}
-SLANG_NO_THROW SlangResult SLANG_MCALL OSFileSystemExt::saveFile(const char* pathIn, const void* data, size_t size)
+SlangResult OSFileSystem::enumeratePathContents(const char* path, FileSystemContentsCallBack callback, void* userData)
+{
+ SLANG_RETURN_ON_FAIL(_checkExt(m_style));
+
+ struct Visitor : Path::Visitor
+ {
+ void accept(Path::Type type, const UnownedStringSlice& filename) SLANG_OVERRIDE
+ {
+ m_buffer.Clear();
+ m_buffer.append(filename);
+
+ SlangPathType pathType;
+ switch (type)
+ {
+ case Path::Type::File: pathType = SLANG_PATH_TYPE_FILE; break;
+ case Path::Type::Directory: pathType = SLANG_PATH_TYPE_DIRECTORY; break;
+ default: return;
+ }
+
+ m_callback(pathType, m_buffer.getBuffer(), m_userData);
+ }
+
+ Visitor(FileSystemContentsCallBack callback, void* userData) :
+ m_callback(callback),
+ m_userData(userData)
+ {
+ }
+ StringBuilder m_buffer;
+ FileSystemContentsCallBack m_callback;
+ void* m_userData;
+ };
+
+ Visitor visitor(callback, userData);
+ Path::find(path, nullptr, &visitor);
+
+ return SLANG_OK;
+}
+
+SlangResult OSFileSystem::saveFile(const char* pathIn, const void* data, size_t size)
{
+ SLANG_RETURN_ON_FAIL(_checkMutable(m_style));
+
const String path = _fixPathDelimiters(pathIn);
try
@@ -152,6 +264,18 @@ SLANG_NO_THROW SlangResult SLANG_MCALL OSFileSystemExt::saveFile(const char* pat
return SLANG_OK;
}
+SlangResult OSFileSystem::remove(const char* path)
+{
+ SLANG_RETURN_ON_FAIL(_checkMutable(m_style));
+ return Path::remove(path);
+}
+
+SlangResult OSFileSystem::createDirectory(const char* path)
+{
+ SLANG_RETURN_ON_FAIL(_checkMutable(m_style));
+ return Path::createDirectory(path);
+}
+
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CacheFileSystem !!!!!!!!!!!!!!!!!!!!!!!!!!!
/* static */ const Result CacheFileSystem::s_compressedResultToResult[] =
@@ -177,11 +301,6 @@ SLANG_NO_THROW SlangResult SLANG_MCALL OSFileSystemExt::saveFile(const char* pat
}
}
-ISlangUnknown* CacheFileSystem::getInterface(const Guid& guid)
-{
- return _getInterface(this, guid);
-}
-
SLANG_NO_THROW SlangResult SLANG_MCALL CacheFileSystem::queryInterface(SlangUUID const& uuid, void** outObject)
{
if (uuid == IID_SlangCacheFileSystem)
@@ -190,17 +309,15 @@ SLANG_NO_THROW SlangResult SLANG_MCALL CacheFileSystem::queryInterface(SlangUUID
return SLANG_OK;
}
- ISlangUnknown* intf = getInterface(uuid);
- if (intf)
+ if (_canCast(FileSystemStyle::Ext, uuid))
{
addReference();
- *outObject = intf;
+ *outObject = static_cast<ISlangFileSystemExt*>(this);
return SLANG_OK;
}
return SLANG_E_NO_INTERFACE;
}
-
CacheFileSystem::CacheFileSystem(ISlangFileSystem* fileSystem, UniqueIdentityMode uniqueIdentityMode, PathStyle pathStyle)
{
setInnerFileSystem(fileSystem, uniqueIdentityMode, pathStyle);
@@ -275,6 +392,7 @@ void CacheFileSystem::clearCache()
}
}
+
// Determines if we can simplify a path for a given mode
static bool _canSimplifyPath(CacheFileSystem::UniqueIdentityMode mode)
{
@@ -293,6 +411,76 @@ static bool _canSimplifyPath(CacheFileSystem::UniqueIdentityMode mode)
}
}
+SlangResult CacheFileSystem::enumeratePathContents(const char* path, FileSystemContentsCallBack callback, void* userData)
+{
+ if (m_fileSystemExt)
+ {
+ return m_fileSystemExt->enumeratePathContents(path, callback, userData);
+ }
+
+ // Okay.. the contents of the 'cache' *is* the filesystem. So lets iterate over that
+ // This will win no prizes for efficiency, but that is unlikely to matter for typical usage
+
+ if (!_canSimplifyPath(m_uniqueIdentityMode))
+ {
+ // As it stands if we can't simplify paths, it's kind of hard to make this
+ // all work. As we use the simplified path cache
+ return SLANG_E_NOT_IMPLEMENTED;
+ }
+
+ // Simplify the path
+ String simplifiedPath = Path::simplify(path);
+
+ for (auto& pair : m_pathMap)
+ {
+ // NOTE! The currentPath can be a *non* simplified path (the m_pathMap is the cache of paths simplified and other to a file/directory)
+ // Also note that there will always be the simplified version of the path in cache.
+ const String& currentPath = pair.Key;
+
+ // If it doesn't start with simplified path, then it can't be a hit
+ if (!currentPath.startsWith(simplifiedPath))
+ {
+ continue;
+ }
+
+ UnownedStringSlice remaining(currentPath.getBuffer() + simplifiedPath.getLength(), currentPath.end());
+
+ // If it starts with a / delimiter strip it
+ if (remaining.getLength() > 0 && remaining[0] == '/')
+ {
+ remaining = UnownedStringSlice(remaining.begin() + 1, remaining.end());
+ }
+
+ // If it has a / then it's either not simplified - so we ignore (we only want to invoke on the simplified path version as there is only one
+ // of these for every PathInfo)
+ // or it is a child file/directory, and so we ignore that too.
+ Index index = remaining.indexOf('/');
+ if (index >= 0)
+ {
+ continue;
+ }
+
+ // We *know* that remaining comes from the end of currentPath .We also know currentPath is zero terminated.
+ // So we can just use (normally this would be a problem because UnownedStringSlice is generally *not* followed by zero termination.
+ const char* foundPath = remaining.begin();
+ // Let's check that fact...
+ SLANG_ASSERT(foundPath[remaining.getLength()] == 0);
+
+ PathInfo* pathInfo = pair.Value;
+
+ SlangPathType pathType;
+ if (SLANG_FAILED(_getPathType(pathInfo, currentPath.getBuffer(), &pathType)))
+ {
+ continue;
+ }
+
+ callback(pathType, foundPath, userData);
+ }
+
+ return SLANG_OK;
+}
+
+
SlangResult CacheFileSystem::_calcUniqueIdentity(const String& path, String& outUniqueIdentity, ComPtr<ISlangBlob>& outFileContents)
{
switch (m_uniqueIdentityMode)
@@ -474,40 +662,44 @@ SlangResult CacheFileSystem::calcCombinedPath(SlangPathType fromPathType, const
}
}
-SlangResult CacheFileSystem::getPathType(const char* pathIn, SlangPathType* pathTypeOut)
+SlangResult CacheFileSystem::_getPathType(PathInfo* info, const char* inPath, SlangPathType* outPathType)
{
- String path(pathIn);
- PathInfo* info = _resolvePathCacheInfo(path);
- if (!info)
- {
- return SLANG_E_NOT_FOUND;
- }
-
if (info->m_getPathTypeResult == CompressedResult::Uninitialized)
{
if (m_fileSystemExt)
{
- info->m_getPathTypeResult = toCompressedResult(m_fileSystemExt->getPathType(pathIn, &info->m_pathType));
+ info->m_getPathTypeResult = toCompressedResult(m_fileSystemExt->getPathType(inPath, &info->m_pathType));
}
else
{
// Okay try to load the file
if (info->m_loadFileResult == CompressedResult::Uninitialized)
{
- info->m_loadFileResult = toCompressedResult(m_fileSystem->loadFile(path.getBuffer(), info->m_fileBlob.writeRef()));
+ info->m_loadFileResult = toCompressedResult(m_fileSystem->loadFile(inPath, info->m_fileBlob.writeRef()));
}
// Make the getPathResult the same as the load result
info->m_getPathTypeResult = info->m_loadFileResult;
// Just set to file... the result is what matters in this case
- info->m_pathType = SLANG_PATH_TYPE_FILE;
+ info->m_pathType = SLANG_PATH_TYPE_FILE;
}
}
- *pathTypeOut = info->m_pathType;
+ *outPathType = info->m_pathType;
return toResult(info->m_getPathTypeResult);
}
+SlangResult CacheFileSystem::getPathType(const char* inPath, SlangPathType* outPathType)
+{
+ PathInfo* info = _resolvePathCacheInfo(inPath);
+ if (!info)
+ {
+ return SLANG_E_NOT_FOUND;
+ }
+
+ return _getPathType(info, inPath, outPathType);
+}
+
SlangResult CacheFileSystem::getSimplifiedPath(const char* path, ISlangBlob** outSimplifiedPath)
{
// If we have a ISlangFileSystemExt we can just pass on the request to it
@@ -576,9 +768,29 @@ SlangResult CacheFileSystem::getCanonicalPath(const char* path, ISlangBlob** out
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! RelativeFileSystem !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+RelativeFileSystem::RelativeFileSystem(ISlangFileSystem* fileSystem, const String& relativePath, bool stripPath) :
+ m_relativePath(relativePath),
+ m_stripPath(stripPath)
+{
+ m_style = _getFileSystemStyle(fileSystem, m_fileSystem);
+}
+
ISlangUnknown* RelativeFileSystem::getInterface(const Guid& guid)
{
- return _getInterface(this, guid);
+ return _canCast(m_style, guid) ? static_cast<ISlangMutableFileSystem*>(this) : nullptr;
+}
+
+SlangResult RelativeFileSystem::_calcCombinedPathInner(SlangPathType fromPathType, const char* fromPath, const char* path, ISlangBlob** outPath)
+{
+ ISlangFileSystemExt* fileSystem = _getExt();
+ if (fileSystem)
+ {
+ return fileSystem->calcCombinedPath(fromPathType, fromPath, path, outPath);
+ }
+ else
+ {
+ return _calcCombinedPath(fromPathType, fromPath, path, outPath);
+ }
}
SlangResult RelativeFileSystem::_getFixedPath(const char* path, String& outPath)
@@ -587,68 +799,119 @@ SlangResult RelativeFileSystem::_getFixedPath(const char* path, String& outPath)
if (m_stripPath)
{
String strippedPath = Path::getFileName(path);
- SLANG_RETURN_ON_FAIL(m_fileSystem->calcCombinedPath(SLANG_PATH_TYPE_DIRECTORY, m_relativePath.getBuffer(), strippedPath.getBuffer(), blob.writeRef()));
+ SLANG_RETURN_ON_FAIL(_calcCombinedPathInner(SLANG_PATH_TYPE_DIRECTORY, m_relativePath.getBuffer(), strippedPath.getBuffer(), blob.writeRef()));
}
else
{
- SLANG_RETURN_ON_FAIL(m_fileSystem->calcCombinedPath(SLANG_PATH_TYPE_DIRECTORY, m_relativePath.getBuffer(), path, blob.writeRef()));
+ SLANG_RETURN_ON_FAIL(_calcCombinedPathInner(SLANG_PATH_TYPE_DIRECTORY, m_relativePath.getBuffer(), path, blob.writeRef()));
}
outPath = StringUtil::getString(blob);
return SLANG_OK;
}
-SLANG_NO_THROW SlangResult SLANG_MCALL RelativeFileSystem::loadFile(char const* path, ISlangBlob** outBlob)
+SlangResult RelativeFileSystem::loadFile(char const* path, ISlangBlob** outBlob)
{
String fixedPath;
SLANG_RETURN_ON_FAIL(_getFixedPath(path, fixedPath));
return m_fileSystem->loadFile(fixedPath.getBuffer(), outBlob);
}
-SLANG_NO_THROW SlangResult SLANG_MCALL RelativeFileSystem::getFileUniqueIdentity(const char* path, ISlangBlob** outUniqueIdentity)
+SlangResult RelativeFileSystem::getFileUniqueIdentity(const char* path, ISlangBlob** outUniqueIdentity)
{
+ auto fileSystem = _getExt();
+ if (!fileSystem) return SLANG_E_NOT_IMPLEMENTED;
+
String fixedPath;
SLANG_RETURN_ON_FAIL(_getFixedPath(path, fixedPath));
- return m_fileSystem->getFileUniqueIdentity(fixedPath.getBuffer(), outUniqueIdentity);
+ return fileSystem->getFileUniqueIdentity(fixedPath.getBuffer(), outUniqueIdentity);
}
-SLANG_NO_THROW SlangResult SLANG_MCALL RelativeFileSystem::calcCombinedPath(SlangPathType fromPathType, const char* fromPath, const char* path, ISlangBlob** outPath)
+SlangResult RelativeFileSystem::calcCombinedPath(SlangPathType fromPathType, const char* fromPath, const char* path, ISlangBlob** outPath)
{
+ auto fileSystem = _getExt();
+ if (!fileSystem) return SLANG_E_NOT_IMPLEMENTED;
+
String fixedFromPath;
SLANG_RETURN_ON_FAIL(_getFixedPath(fromPath, fixedFromPath));
- return m_fileSystem->calcCombinedPath(fromPathType, fixedFromPath.getBuffer(), path, outPath);
+ return fileSystem->calcCombinedPath(fromPathType, fixedFromPath.getBuffer(), path, outPath);
+}
+
+SlangResult RelativeFileSystem::getPathType(const char* path, SlangPathType* outPathType)
+{
+ auto fileSystem = _getExt();
+ if (!fileSystem) return SLANG_E_NOT_IMPLEMENTED;
+
+ String fixedPath;
+ SLANG_RETURN_ON_FAIL(_getFixedPath(path, fixedPath));
+ return fileSystem->getPathType(fixedPath.getBuffer(), outPathType);
}
-SLANG_NO_THROW SlangResult SLANG_MCALL RelativeFileSystem::getPathType(const char* path, SlangPathType* outPathType)
+SlangResult RelativeFileSystem::getSimplifiedPath(const char* path, ISlangBlob** outSimplifiedPath)
{
+ auto fileSystem = _getExt();
+ if (!fileSystem) return SLANG_E_NOT_IMPLEMENTED;
+
+ return fileSystem->getSimplifiedPath(path, outSimplifiedPath);
+}
+
+SlangResult RelativeFileSystem::getCanonicalPath(const char* path, ISlangBlob** outCanonicalPath)
+{
+ auto fileSystem = _getExt();
+ if (!fileSystem) return SLANG_E_NOT_IMPLEMENTED;
+
String fixedPath;
SLANG_RETURN_ON_FAIL(_getFixedPath(path, fixedPath));
- return m_fileSystem->getPathType(fixedPath.getBuffer(), outPathType);
+ return fileSystem->getCanonicalPath(fixedPath.getBuffer(), outCanonicalPath);
}
-SLANG_NO_THROW SlangResult SLANG_MCALL RelativeFileSystem::getSimplifiedPath(const char* path, ISlangBlob** outSimplifiedPath)
+void RelativeFileSystem::clearCache()
{
- return m_fileSystem->getSimplifiedPath(path, outSimplifiedPath);
+ auto fileSystem = _getExt();
+ if (!fileSystem) return;
+
+ fileSystem->clearCache();
}
-SLANG_NO_THROW SlangResult SLANG_MCALL RelativeFileSystem::getCanonicalPath(const char* path, ISlangBlob** outCanonicalPath)
+SlangResult RelativeFileSystem::enumeratePathContents(const char* path, FileSystemContentsCallBack callback, void* userData)
{
+ auto fileSystem = _getExt();
+ if (!fileSystem) return SLANG_E_NOT_IMPLEMENTED;
+
String fixedPath;
SLANG_RETURN_ON_FAIL(_getFixedPath(path, fixedPath));
- return m_fileSystem->getCanonicalPath(fixedPath.getBuffer(), outCanonicalPath);
+ return fileSystem->enumeratePathContents(fixedPath.getBuffer(), callback, userData);
}
-SLANG_NO_THROW void SLANG_MCALL RelativeFileSystem::clearCache()
+SlangResult RelativeFileSystem::saveFile(const char* path, const void* data, size_t size)
{
- m_fileSystem->clearCache();
+ auto fileSystem = _getMutable();
+ if (!fileSystem) return SLANG_E_NOT_IMPLEMENTED;
+
+ String fixedPath;
+ SLANG_RETURN_ON_FAIL(_getFixedPath(path, fixedPath));
+ return fileSystem->saveFile(fixedPath.getBuffer(), data, size);
+}
+
+SlangResult RelativeFileSystem::remove(const char* path)
+{
+ auto fileSystem = _getMutable();
+ if (!fileSystem) return SLANG_E_NOT_IMPLEMENTED;
+
+ String fixedPath;
+ SLANG_RETURN_ON_FAIL(_getFixedPath(path, fixedPath));
+ return fileSystem->remove(fixedPath.getBuffer());
}
-SLANG_NO_THROW SlangResult SLANG_MCALL RelativeFileSystem::saveFile(const char* path, const void* data, size_t size)
+SlangResult RelativeFileSystem::createDirectory(const char* path)
{
+ auto fileSystem = _getMutable();
+ if (!fileSystem) return SLANG_E_NOT_IMPLEMENTED;
+
String fixedPath;
SLANG_RETURN_ON_FAIL(_getFixedPath(path, fixedPath));
- return m_fileSystem->saveFile(fixedPath.getBuffer(), data, size);
+ return fileSystem->createDirectory(fixedPath.getBuffer());
}
}
diff --git a/source/slang/slang-file-system.h b/source/slang/slang-file-system.h
index 199cafe24..d5145404d 100644
--- a/source/slang/slang-file-system.h
+++ b/source/slang/slang-file-system.h
@@ -13,8 +13,15 @@
namespace Slang
{
-// Implementation of ISlangFileSystemExt for the OS
-class OSFileSystemExt : public ISlangFileSystemExt
+enum class FileSystemStyle
+{
+ Load, ///< Equivalent to ISlangFileSystem
+ Ext, ///< Equivalent to ISlangFileSystemExt
+ Mutable, ///< Equivalent to ISlangModifyableFileSystem
+};
+
+// Can be used for all styles of file system
+class OSFileSystem : public ISlangMutableFileSystem
{
public:
// ISlangUnknown
@@ -24,83 +31,44 @@ public:
SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; }
// ISlangFileSystem
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadFile(
- char const* path,
- ISlangBlob** outBlob) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadFile(char const* path, ISlangBlob** outBlob) SLANG_OVERRIDE;
// ISlangFileSystemExt
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL getFileUniqueIdentity(
- const char* path,
- ISlangBlob** uniqueIdentityOut) SLANG_OVERRIDE;
-
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcCombinedPath(
- SlangPathType fromPathType,
- const char* fromPath,
- const char* path,
- ISlangBlob** pathOut) SLANG_OVERRIDE;
-
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL getPathType(
- const char* path,
- SlangPathType* pathTypeOut) SLANG_OVERRIDE;
-
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL getSimplifiedPath(
- const char* path,
- ISlangBlob** outSimplifiedPath) SLANG_OVERRIDE;
-
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL getCanonicalPath(
- const char* path,
- ISlangBlob** outCanonicalPath) SLANG_OVERRIDE;
-
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL getFileUniqueIdentity(const char* path, ISlangBlob** uniqueIdentityOut) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcCombinedPath(SlangPathType fromPathType, const char* fromPath, const char* path, ISlangBlob** pathOut) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL getPathType(const char* path, SlangPathType* pathTypeOut) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL getSimplifiedPath(const char* path, ISlangBlob** outSimplifiedPath) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL getCanonicalPath(const char* path, ISlangBlob** outCanonicalPath) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL clearCache() SLANG_OVERRIDE {}
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL enumeratePathContents(const char* path, FileSystemContentsCallBack callback, void* userData) SLANG_OVERRIDE;
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL saveFile(
- const char* path,
- const void* data,
- size_t size) SLANG_OVERRIDE ;
-
+ // ISlangModifyableFileSystem
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL saveFile(const char* path, const void* data, size_t size) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL remove(const char* path) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL createDirectory(const char* path) SLANG_OVERRIDE;
/// Get a default instance
- static ISlangFileSystemExt* getSingleton() { return &s_singleton; }
+ static ISlangFileSystem* getLoadSingleton() { return &g_load; }
+ static ISlangFileSystemExt* getExtSingleton() { return &g_ext; }
+ static ISlangMutableFileSystem* getMutableSingleton() { return &g_mutable; }
private:
- /// Make so not constructible
- OSFileSystemExt() {}
- virtual ~OSFileSystemExt() {}
-
- ISlangUnknown* getInterface(const Guid& guid);
- static OSFileSystemExt s_singleton;
-};
-
-// Implementation of ISlangFileSystem for the OS (ie only has simplified interface of just loadFile)
-class OSFileSystem : public ISlangFileSystem
-{
-public:
- // ISlangUnknown
- SLANG_IUNKNOWN_QUERY_INTERFACE
- SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return 1; }
- SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; }
-
- // ISlangFileSystem
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadFile(
- char const* path,
- ISlangBlob** outBlob) SLANG_OVERRIDE
- {
- // Can just use OsFileSystemExt impl
- return OSFileSystemExt::getSingleton()->loadFile(path, outBlob);
- }
-
- static ISlangFileSystem* getSingleton() { return &s_singleton; }
-
-private:
/// Make so not constructible
- OSFileSystem() {}
+ OSFileSystem(FileSystemStyle style):
+ m_style(style)
+ {}
+
virtual ~OSFileSystem() {}
ISlangUnknown* getInterface(const Guid& guid);
- static OSFileSystem s_singleton;
-};
+ FileSystemStyle m_style;
+
+ static OSFileSystem g_load;
+ static OSFileSystem g_ext;
+ static OSFileSystem g_mutable;
+};
#define SLANG_UUID_CacheFileSystem { 0x2f4d1d03, 0xa0d1, 0x434b, { 0x87, 0x7a, 0x65, 0x5, 0xa4, 0xa0, 0x9a, 0x3b } };
@@ -180,43 +148,16 @@ class CacheFileSystem: public ISlangFileSystemExt, public RefObject
SLANG_REF_OBJECT_IUNKNOWN_RELEASE
// ISlangFileSystem
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadFile(
- char const* path,
- ISlangBlob** outBlob) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadFile(char const* path, ISlangBlob** outBlob) SLANG_OVERRIDE;
// ISlangFileSystemExt
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL getFileUniqueIdentity(
- const char* path,
- ISlangBlob** outUniqueIdentity) SLANG_OVERRIDE;
-
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcCombinedPath(
- SlangPathType fromPathType,
- const char* fromPath,
- const char* path,
- ISlangBlob** pathOut) SLANG_OVERRIDE;
-
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL getPathType(
- const char* path,
- SlangPathType* outPathType) SLANG_OVERRIDE;
-
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL getSimplifiedPath(
- const char* path,
- ISlangBlob** outSimplifiedPath) SLANG_OVERRIDE;
-
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL getCanonicalPath(
- const char* path,
- ISlangBlob** outCanonicalPath) SLANG_OVERRIDE;
-
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL getFileUniqueIdentity(const char* path, ISlangBlob** outUniqueIdentity) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcCombinedPath(SlangPathType fromPathType, const char* fromPath, const char* path, ISlangBlob** pathOut) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL getPathType(const char* path, SlangPathType* outPathType) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL getSimplifiedPath(const char* path, ISlangBlob** outSimplifiedPath) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL getCanonicalPath(const char* path, ISlangBlob** outCanonicalPath) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL clearCache() SLANG_OVERRIDE;
-
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL saveFile(const char* path, const void* data, size_t size) SLANG_OVERRIDE
- {
- SLANG_UNUSED(path);
- SLANG_UNUSED(data);
- SLANG_UNUSED(size);
-
- return SLANG_E_NOT_IMPLEMENTED;
- }
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL enumeratePathContents(const char* path, FileSystemContentsCallBack callback, void* userData) SLANG_OVERRIDE;
/// Get the unique identity mode
UniqueIdentityMode getUniqueIdentityMode() const { return m_uniqueIdentityMode; }
@@ -236,8 +177,6 @@ class CacheFileSystem: public ISlangFileSystemExt, public RefObject
static const Result s_compressedResultToResult[int(CompressedResult::CountOf)];
protected:
- ISlangUnknown* getInterface(const Guid& guid);
-
/// Given a path, works out a uniqueIdentity, based on the uniqueIdentityMode. outFileContents will be set if file had to be read to produce the uniqueIdentity (ie with Hash)
SlangResult _calcUniqueIdentity(const String& path, String& outUniqueIdentity, ComPtr<ISlangBlob>& outFileContents);
@@ -249,6 +188,8 @@ protected:
/// Will simplify the path (if possible) to lookup on the pathCache else will create on uniqueIdentityMap
PathInfo* _resolveSimplifiedPathCacheInfo(const String& path);
+ SlangResult _getPathType(PathInfo* pathInfo, const char* inPath, SlangPathType* pathTypeOut);
+
/* TODO: This may be improved by mapping to a ISlangBlob. This makes output fast and easy, and if constructed
as a StringBlob, we can just static_cast to get as a string to use internally, instead of constantly converting.
It is probably the case we cannot do dynamic_cast on ISlangBlob if we don't know where constructed -> if outside of slang codebase
@@ -264,59 +205,46 @@ protected:
ComPtr<ISlangFileSystemExt> m_fileSystemExt; ///< Optionally set -> if nullptr will fall back on the m_fileSystem and emulate all the other methods of ISlangFileSystemExt
};
-class RelativeFileSystem : public ISlangFileSystemExt, public RefObject
+class RelativeFileSystem : public ISlangMutableFileSystem, public RefObject
{
public:
SLANG_REF_OBJECT_IUNKNOWN_ALL
// ISlangFileSystem
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadFile(
- char const* path,
- ISlangBlob** outBlob) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadFile(char const* path, ISlangBlob** outBlob) SLANG_OVERRIDE;
// ISlangFileSystemExt
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL getFileUniqueIdentity(
- const char* path,
- ISlangBlob** outUniqueIdentity) SLANG_OVERRIDE;
-
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcCombinedPath(
- SlangPathType fromPathType,
- const char* fromPath,
- const char* path,
- ISlangBlob** pathOut) SLANG_OVERRIDE;
-
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL getPathType(
- const char* path,
- SlangPathType* outPathType) SLANG_OVERRIDE;
-
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL getSimplifiedPath(
- const char* path,
- ISlangBlob** outSimplifiedPath) SLANG_OVERRIDE;
-
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL getCanonicalPath(
- const char* path,
- ISlangBlob** outCanonicalPath) SLANG_OVERRIDE;
-
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL getFileUniqueIdentity(const char* path, ISlangBlob** outUniqueIdentity) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcCombinedPath(SlangPathType fromPathType, const char* fromPath, const char* path, ISlangBlob** pathOut) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL getPathType(const char* path, SlangPathType* outPathType) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL getSimplifiedPath(const char* path, ISlangBlob** outSimplifiedPath) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL getCanonicalPath(const char* path, ISlangBlob** outCanonicalPath) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL clearCache() SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL enumeratePathContents(const char* path, FileSystemContentsCallBack callback, void* userData) SLANG_OVERRIDE;
+ // ISlangModifyableFileSystem
virtual SLANG_NO_THROW SlangResult SLANG_MCALL saveFile(const char* path, const void* data, size_t size) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL remove(const char* path) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL createDirectory(const char* path) SLANG_OVERRIDE;
- RelativeFileSystem(ISlangFileSystemExt* fileSystem, const String& relativePath, bool stripPath = false):
- m_fileSystem(fileSystem),
- m_relativePath(relativePath),
- m_stripPath(stripPath)
- {
- }
+ RelativeFileSystem(ISlangFileSystem* fileSystem, const String& relativePath, bool stripPath = false);
protected:
+ ISlangFileSystemExt* _getExt() { return Index(m_style) >= Index(FileSystemStyle::Ext) ? reinterpret_cast<ISlangFileSystemExt*>(m_fileSystem.get()) : nullptr; }
+ ISlangMutableFileSystem* _getMutable() { return Index(m_style) >= Index(FileSystemStyle::Mutable) ? reinterpret_cast<ISlangMutableFileSystem*>(m_fileSystem.get()) : nullptr; }
+
+ SlangResult _calcCombinedPathInner(SlangPathType fromPathType, const char* fromPath, const char* path, ISlangBlob** pathOut);
+
SlangResult _getFixedPath(const char* path, String& outPath);
ISlangUnknown* getInterface(const Guid& guid);
bool m_stripPath;
- ComPtr<ISlangFileSystemExt> m_fileSystem;
+ FileSystemStyle m_style;
+ ComPtr<ISlangFileSystem> m_fileSystem; ///< NOTE! Has to match what's in style, such style can be reached via reinterpret_cast
+
String m_relativePath;
};
diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp
index 6a5b43876..60d41ee5c 100644
--- a/source/slang/slang-options.cpp
+++ b/source/slang/slang-options.cpp
@@ -529,7 +529,7 @@ struct OptionsParser
SlangPathType pathType;
if (SLANG_SUCCEEDED(Path::getPathType(dirPath, &pathType)) && pathType == SLANG_PATH_TYPE_DIRECTORY)
{
- fileSystem = new RelativeFileSystem(OSFileSystemExt::getSingleton(), dirPath);
+ fileSystem = new RelativeFileSystem(OSFileSystem::getExtSingleton(), dirPath);
}
}
@@ -557,7 +557,7 @@ struct OptionsParser
SlangPathType pathType;
if (SLANG_SUCCEEDED(Path::getPathType(dirPath, &pathType)) && pathType == SLANG_PATH_TYPE_DIRECTORY)
{
- dirFileSystem = new RelativeFileSystem(OSFileSystemExt::getSingleton(), dirPath, true);
+ dirFileSystem = new RelativeFileSystem(OSFileSystem::getExtSingleton(), dirPath, true);
}
}
@@ -907,13 +907,13 @@ struct OptionsParser
}
else if (name == "load-file")
{
- // OSFileSystem just implements loadFile interface, so will be wrapped with CacheFileSystem internally
- spSetFileSystem(compileRequest, OSFileSystem::getSingleton());
+ // 'Simple' just implements loadFile interface, so will be wrapped with CacheFileSystem internally
+ spSetFileSystem(compileRequest, OSFileSystem::getLoadSingleton());
}
else if (name == "os")
{
- // OSFileSystemExt implements the ISlangFileSystemExt interface - and will be used directly
- spSetFileSystem(compileRequest, OSFileSystemExt::getSingleton());
+ // 'Immutable' implements the ISlangFileSystemExt interface - and will be used directly
+ spSetFileSystem(compileRequest, OSFileSystem::getExtSingleton());
}
else
{
diff --git a/source/slang/slang-repro.cpp b/source/slang/slang-repro.cpp
index 80ef0322e..f9cc415c0 100644
--- a/source/slang/slang-repro.cpp
+++ b/source/slang/slang-repro.cpp
@@ -1149,7 +1149,7 @@ struct LoadContext
Path::createDirectory(dirPath);
// Set up a file system to write into this directory
- RelativeFileSystem relFileSystem(OSFileSystemExt::getSingleton(), dirPath);
+ RelativeFileSystem relFileSystem(OSFileSystem::getMutableSingleton(), dirPath);
return extractFiles(base, requestState, &relFileSystem);
}
@@ -1382,7 +1382,7 @@ static SlangResult _calcCommandLine(OffsetBase& base, ReproUtil::RequestState* r
return SLANG_OK;
}
-/* static */SlangResult ReproUtil::extractFiles(OffsetBase& base, RequestState* requestState, ISlangFileSystemExt* fileSystem)
+/* static */SlangResult ReproUtil::extractFiles(OffsetBase& base, RequestState* requestState, ISlangMutableFileSystem* fileSystem)
{
StringBuilder builder;
diff --git a/source/slang/slang-repro.h b/source/slang/slang-repro.h
index bd35d3ee9..dd9984395 100644
--- a/source/slang/slang-repro.h
+++ b/source/slang/slang-repro.h
@@ -186,7 +186,7 @@ struct ReproUtil
static SlangResult extractFilesToDirectory(const String& file);
- static SlangResult extractFiles(OffsetBase& base, RequestState* requestState, ISlangFileSystemExt* fileSystem);
+ static SlangResult extractFiles(OffsetBase& base, RequestState* requestState, ISlangMutableFileSystem* fileSystem);
/// Given the repo file work out a suitable path
static SlangResult calcDirectoryPathFromFilename(const String& filename, String& outPath);
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index d61814136..063a84bbe 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -3043,7 +3043,7 @@ void Linkage::setFileSystem(ISlangFileSystem* inFileSystem)
// If nullptr passed in set up default
if (inFileSystem == nullptr)
{
- m_cacheFileSystem = new Slang::CacheFileSystem(Slang::OSFileSystemExt::getSingleton());
+ m_cacheFileSystem = new Slang::CacheFileSystem(Slang::OSFileSystem::getExtSingleton());
m_fileSystemExt = m_cacheFileSystem;
}
else
@@ -4245,7 +4245,7 @@ SLANG_API SlangResult spEnableReproCapture(
return SLANG_OK;
}
-SLANG_API SlangResult spExtractRepro(SlangSession* session, const void* reproData, size_t reproDataSize, ISlangFileSystemExt* fileSystem)
+SLANG_API SlangResult spExtractRepro(SlangSession* session, const void* reproData, size_t reproDataSize, ISlangMutableFileSystem* fileSystem)
{
using namespace Slang;
SLANG_UNUSED(session);