diff options
Diffstat (limited to 'source')
| -rw-r--r-- | source/core/hash.h | 15 | ||||
| -rw-r--r-- | source/slang/slang-file-system.cpp | 135 | ||||
| -rw-r--r-- | source/slang/slang-file-system.h | 23 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 14 |
4 files changed, 137 insertions, 50 deletions
diff --git a/source/core/hash.h b/source/core/hash.h index ca6172fc7..fc0bca737 100644 --- a/source/core/hash.h +++ b/source/core/hash.h @@ -43,7 +43,18 @@ namespace Slang } return hash; } - + + inline uint64_t GetHashCode64(const char * buffer, size_t numChars) + { + // Use uints because hash requires wrap around behavior and int is undefined on over/underflows + uint64_t hash = 0; + for (size_t i = 0; i < numChars; ++i) + { + hash = uint64_t(int64_t(buffer[i])) + (hash << 6) + (hash << 16) - hash; + } + return hash; + } + template<int IsInt> class Hash { @@ -111,4 +122,4 @@ namespace Slang } } -#endif
\ No newline at end of file +#endif diff --git a/source/slang/slang-file-system.cpp b/source/slang/slang-file-system.cpp index ef77dbf33..caaa9f56d 100644 --- a/source/slang/slang-file-system.cpp +++ b/source/slang/slang-file-system.cpp @@ -14,8 +14,8 @@ static const Guid IID_ISlangUnknown = SLANG_UUID_ISlangUnknown; static const Guid IID_ISlangFileSystem = SLANG_UUID_ISlangFileSystem; static const Guid IID_ISlangFileSystemExt = SLANG_UUID_ISlangFileSystemExt; -// Cacluate a relative path, just using Path:: string processing -static SlangResult _calcRelativePath(SlangPathType fromPathType, const char* fromPath, const char* path, ISlangBlob** pathOut) +// Cacluate a combined path, just using Path:: string processing +static SlangResult _calcCombinedPath(SlangPathType fromPathType, const char* fromPath, const char* path, ISlangBlob** pathOut) { String relPath; switch (fromPathType) @@ -60,9 +60,9 @@ SlangResult DefaultFileSystem::getCanoncialPath(const char* path, ISlangBlob** c return SLANG_OK; } -SlangResult DefaultFileSystem::calcRelativePath(SlangPathType fromPathType, const char* fromPath, const char* path, ISlangBlob** pathOut) +SlangResult DefaultFileSystem::calcCombinedPath(SlangPathType fromPathType, const char* fromPath, const char* path, ISlangBlob** pathOut) { - return _calcRelativePath(fromPathType, fromPath, path, pathOut); + return _calcCombinedPath(fromPathType, fromPath, path, pathOut); } SlangResult SLANG_MCALL DefaultFileSystem::getPathType( @@ -127,12 +127,25 @@ ISlangUnknown* CacheFileSystem::getInterface(const Guid& guid) return _getInterface(this, guid); } -CacheFileSystem::CacheFileSystem(ISlangFileSystem* fileSystem, bool useSimplifyForCanonicalPath) : +CacheFileSystem::CacheFileSystem(ISlangFileSystem* fileSystem, CanonicalMode canonicalMode) : m_fileSystem(fileSystem), - m_useSimplifyForCanonicalPath(useSimplifyForCanonicalPath) + m_canonicalMode(canonicalMode) { // Try to get the more sophisticated interface fileSystem->queryInterface(IID_ISlangFileSystemExt, (void**)m_fileSystemExt.writeRef()); + + switch (canonicalMode) + { + case CanonicalMode::Default: + case CanonicalMode::FileSystemExt: + { + m_canonicalMode = m_fileSystemExt ? CanonicalMode::FileSystemExt : CanonicalMode::Hash; + break; + } + default: break; + } + // It can't be default + SLANG_ASSERT(m_canonicalMode != CanonicalMode::Default); } CacheFileSystem::~CacheFileSystem() @@ -143,45 +156,95 @@ CacheFileSystem::~CacheFileSystem() } } -CacheFileSystem::PathInfo* CacheFileSystem::_getPathInfo(const String& relPath) +CacheFileSystem::PathInfo* CacheFileSystem::_getPathInfoFromCanonical(const String& canonicalPath) { - PathInfo** infoPtr = m_pathMap.TryGetValue(relPath); + // First see if we have it.. if not add it + PathInfo** infoPtr = m_canonicalMap.TryGetValue(canonicalPath); if (infoPtr) { return *infoPtr; } - - String canonicalPath; - if (m_fileSystemExt) - { - // Try getting the canonical path - // Okay request from the underlying file system the canonical path - ComPtr<ISlangBlob> canonicalBlob; - if (SLANG_FAILED(m_fileSystemExt->getCanoncialPath(relPath.Buffer(), canonicalBlob.writeRef()))) - { - // Write in result as being null ptr so not tried again - m_pathMap.Add(relPath, nullptr); - return nullptr; - } - // Get the path as a string - canonicalPath = StringUtil::getString(canonicalBlob); - } else { - canonicalPath = m_useSimplifyForCanonicalPath ? Path::Simplify(relPath.getUnownedSlice()) : relPath; + // Create and add to canonical path + PathInfo* pathInfo = new PathInfo(canonicalPath); + m_canonicalMap.Add(canonicalPath, pathInfo); + return pathInfo; } +} - PathInfo* pathInfo; - infoPtr = m_canonicalMap.TryGetValue(canonicalPath); +CacheFileSystem::PathInfo* CacheFileSystem::_getPathInfo(const String& relPath) +{ + PathInfo** infoPtr = m_pathMap.TryGetValue(relPath); if (infoPtr) { - pathInfo = *infoPtr; + return *infoPtr; } - else + + PathInfo* pathInfo = nullptr; + switch (m_canonicalMode) { - // Create and add to canonical path - pathInfo = new PathInfo(canonicalPath); - m_canonicalMap.Add(canonicalPath, pathInfo); + case CanonicalMode::FileSystemExt: + { + // Try getting the canonical path + // Okay request from the underlying file system the canonical path + ComPtr<ISlangBlob> canonicalBlob; + if (SLANG_FAILED(m_fileSystemExt->getCanoncialPath(relPath.Buffer(), canonicalBlob.writeRef()))) + { + // Write in result as being null ptr so not tried again + m_pathMap.Add(relPath, nullptr); + return nullptr; + } + // Get the path as a string + String canonicalPath = StringUtil::getString(canonicalBlob); + pathInfo = _getPathInfoFromCanonical(canonicalPath); + break; + } + case CanonicalMode::Path: + { + pathInfo = _getPathInfoFromCanonical(relPath); + break; + } + case CanonicalMode::SimplifiedPath: + { + pathInfo = _getPathInfoFromCanonical(Path::Simplify(relPath.getUnownedSlice())); + break; + } + case CanonicalMode::Hash: + { + // I can only see if this is the same file as already loaded by loading the file and doing a hash + ComPtr<ISlangBlob> fileBlob; + Result res = m_fileSystem->loadFile(relPath.Buffer(), fileBlob.writeRef()); + if (SLANG_FAILED(res) || fileBlob == nullptr) + { + // Write in result as being null ptr so not tried again + m_pathMap.Add(relPath, nullptr); + return nullptr; + } + + // Calculate the hash on the contents + const uint64_t hash = GetHashCode64((const char*)fileBlob->getBufferPointer(), fileBlob->getBufferSize()); + + String hashString = Path::GetFileName(relPath); + hashString = hashString.ToLower(); + + hashString.append(':'); + + // The canonical name is.. combination of name and hash + hashString.append(hash, 16); + // We'll use the 'hashString' as the canonical path + pathInfo = _getPathInfoFromCanonical(hashString); + + // We have the contents, so store it on the PathInfo, along with the result + if (pathInfo->m_loadFileResult == CompressedResult::Uninitialized) + { + // Save the contents of the saved file + pathInfo->m_loadFileResult = toCompressedResult(res); + pathInfo->m_fileBlob = fileBlob; + } + + break; + } } // Add the relPath @@ -224,17 +287,17 @@ SlangResult CacheFileSystem::getCanoncialPath(const char* path, ISlangBlob** can return SLANG_OK; } -SlangResult CacheFileSystem::calcRelativePath(SlangPathType fromPathType, const char* fromPath, const char* path, ISlangBlob** pathOut) +SlangResult CacheFileSystem::calcCombinedPath(SlangPathType fromPathType, const char* fromPath, const char* path, ISlangBlob** pathOut) { // Just defer to contained implementation if (m_fileSystemExt) { - return m_fileSystemExt->calcRelativePath(fromPathType, fromPath, path, pathOut); + return m_fileSystemExt->calcCombinedPath(fromPathType, fromPath, path, pathOut); } else { // Just use the default implementation - return _calcRelativePath(fromPathType, fromPath, path, pathOut); + return _calcCombinedPath(fromPathType, fromPath, path, pathOut); } } @@ -272,4 +335,4 @@ SlangResult CacheFileSystem::getPathType(const char* pathIn, SlangPathType* path return toResult(info->m_getPathTypeResult); } -}
\ No newline at end of file +} diff --git a/source/slang/slang-file-system.h b/source/slang/slang-file-system.h index b22dc4cb9..c949c66ff 100644 --- a/source/slang/slang-file-system.h +++ b/source/slang/slang-file-system.h @@ -30,7 +30,7 @@ public: const char* path, ISlangBlob** canonicalPathOut) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcRelativePath( + virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcCombinedPath( SlangPathType fromPathType, const char* fromPath, const char* path, @@ -68,6 +68,15 @@ class CacheFileSystem: public ISlangFileSystemExt, public RefObject { public: + enum CanonicalMode + { + Default, ///< If passed, will default to the others depending on what kind of ISlangFileSystem is passed in + Path, ///< Just use the path as is + SimplifiedPath, ///< Use the input path 'simplified' (ie removing . and .. aspects) + Hash, ///< Use hashing + FileSystemExt, ///< Use the file system extended interface. + }; + /* Cannot change order/add members without changing s_compressedResultToResult */ enum class CompressedResult: uint8_t { @@ -92,7 +101,7 @@ class CacheFileSystem: public ISlangFileSystemExt, public RefObject const char* path, ISlangBlob** canonicalPathOut) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcRelativePath( + virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcCombinedPath( SlangPathType fromPathType, const char* fromPath, const char* path, @@ -103,7 +112,7 @@ class CacheFileSystem: public ISlangFileSystemExt, public RefObject SlangPathType* pathTypeOut) SLANG_OVERRIDE; /// Ctor - CacheFileSystem(ISlangFileSystem* fileSystem, bool useSimplifyForCanonicalPath = false); + CacheFileSystem(ISlangFileSystem* fileSystem, CanonicalMode canonicalMode = CanonicalMode::Default); /// Dtor virtual ~CacheFileSystem(); @@ -123,6 +132,8 @@ protected: m_loadFileResult = CompressedResult::Uninitialized; m_getPathTypeResult = CompressedResult::Uninitialized; + + m_pathType = SLANG_PATH_TYPE_FILE; } ~PathInfo() { @@ -140,6 +151,8 @@ protected: /// For a given relPath gets a PathInfo PathInfo* _getPathInfo(const String& relPath); + /// Get path from a canonical path + PathInfo* _getPathInfoFromCanonical(const String& canonicalPath); /* 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. @@ -149,7 +162,7 @@ protected: Dictionary<String, PathInfo*> m_pathMap; ///< Maps a path to a canonical path Dictionary<String, PathInfo*> m_canonicalMap; ///< Maps a canonical path to a files contents. This OWNs the PathInfo. - bool m_useSimplifyForCanonicalPath; ///< If set will use Path::Simplify to create 'canonical' paths + CanonicalMode m_canonicalMode; ///< Determines how 'canonicalPath' is produced. Cannot be Default in usage. ComPtr<ISlangFileSystem> m_fileSystem; ///< Must always be set ComPtr<ISlangFileSystemExt> m_fileSystemExt; ///< Optionally set -> if not will fall back on the m_fileSystem @@ -157,4 +170,4 @@ protected: } -#endif // SLANG_FILE_SYSTEM_H_INCLUDED
\ No newline at end of file +#endif // SLANG_FILE_SYSTEM_H_INCLUDED diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 38b417960..23f7a4e47 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -102,16 +102,16 @@ struct IncludeHandlerImpl : IncludeHandler ISlangFileSystemExt* fileSystemExt = _getFileSystemExt(); // Get relative path - ComPtr<ISlangBlob> relPathBlob; - SLANG_RETURN_ON_FAIL(fileSystemExt->calcRelativePath(fromPathType, fromPath.begin(), path.begin(), relPathBlob.writeRef())); - String relPath(StringUtil::getString(relPathBlob)); - if (relPath.Length() <= 0) + ComPtr<ISlangBlob> combinedPathBlob; + SLANG_RETURN_ON_FAIL(fileSystemExt->calcCombinedPath(fromPathType, fromPath.begin(), path.begin(), combinedPathBlob.writeRef())); + String combinedPath(StringUtil::getString(combinedPathBlob)); + if (combinedPath.Length() <= 0) { return SLANG_FAIL; } SlangPathType pathType; - SLANG_RETURN_ON_FAIL(fileSystemExt->getPathType(relPath.begin(), &pathType)); + SLANG_RETURN_ON_FAIL(fileSystemExt->getPathType(combinedPath.begin(), &pathType)); if (pathType != SLANG_PATH_TYPE_FILE) { return SLANG_E_NOT_FOUND; @@ -119,7 +119,7 @@ struct IncludeHandlerImpl : IncludeHandler // Get the canonical path ComPtr<ISlangBlob> canonicalPathBlob; - SLANG_RETURN_ON_FAIL(fileSystemExt->getCanoncialPath(relPath.begin(), canonicalPathBlob.writeRef())); + SLANG_RETURN_ON_FAIL(fileSystemExt->getCanoncialPath(combinedPath.begin(), canonicalPathBlob.writeRef())); // If the rel path exists -> the canonical path MUST exists too String canonicalPath(StringUtil::getString(canonicalPathBlob)); @@ -130,7 +130,7 @@ struct IncludeHandlerImpl : IncludeHandler } pathInfoOut.type = PathInfo::Type::Normal; - pathInfoOut.foundPath = relPath; + pathInfoOut.foundPath = combinedPath; pathInfoOut.canonicalPath = canonicalPath; return SLANG_OK; } |
