From b59451020eee59cd52e4d8231360ebed4fc59adb Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Thu, 19 Nov 2020 04:14:48 -0500 Subject: 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'. --- slang.h | 51 ++++- source/core/slang-blob.h | 88 +++++++-- source/core/slang-io.cpp | 43 ++++ source/core/slang-io.h | 5 + source/slang/slang-file-system.cpp | 393 +++++++++++++++++++++++++++++++------ source/slang/slang-file-system.h | 196 ++++++------------ source/slang/slang-options.cpp | 12 +- source/slang/slang-repro.cpp | 4 +- source/slang/slang-repro.h | 2 +- source/slang/slang.cpp | 4 +- 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 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& 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(this) : nullptr; -} - -/* !!!!!!!!!!!!!!!!!!!!!!!!!! OSFileSystemExt !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ - -/* static */OSFileSystemExt OSFileSystemExt::s_singleton; - -template -static ISlangFileSystemExt* _getInterface(T* ptr, const Guid& guid) -{ - return (guid == IID_ISlangUnknown || guid == IID_ISlangFileSystem || guid == IID_ISlangFileSystemExt) ? static_cast(ptr) : nullptr; -} - -ISlangUnknown* OSFileSystemExt::getInterface(const Guid& guid) -{ - return _getInterface(this, guid); + return _canCast(m_style, guid) ? static_cast(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(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& 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(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& 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 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(m_fileSystem.get()) : nullptr; } + ISlangMutableFileSystem* _getMutable() { return Index(m_style) >= Index(FileSystemStyle::Mutable) ? reinterpret_cast(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 m_fileSystem; + FileSystemStyle m_style; + ComPtr 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); -- cgit v1.2.3