From 25717ef768b8d6267d4ffb7dbc4bda93ed132ba8 Mon Sep 17 00:00:00 2001 From: janwas Date: Fri, 6 Nov 2009 01:30:16 +0000 Subject: [PATCH] add VirtualPath API to VFS in preparation for moving hotload logic out of library code and into the game. also rename GetRealPath -> RealPath + some cleanup/documentation This was SVN commit r7169. --- source/graphics/ColladaManager.cpp | 2 +- source/lib/file/vfs/vfs.cpp | 55 +++++++++++++++++++++++------- source/lib/file/vfs/vfs.h | 32 ++++++++++++----- source/ps/XML/Xeromyces.cpp | 2 +- 4 files changed, 68 insertions(+), 23 deletions(-) diff --git a/source/graphics/ColladaManager.cpp b/source/graphics/ColladaManager.cpp index 06e203ae29..3d9587550b 100644 --- a/source/graphics/ColladaManager.cpp +++ b/source/graphics/ColladaManager.cpp @@ -239,7 +239,7 @@ VfsPath CColladaManager::GetLoadableFilename(const VfsPath& pathnameNoExtension, // realDaePath_ is "[..]/mods/whatever/art/meshes/whatever.dae" fs::wpath realDaePath_; - LibError ret = g_VFS->GetRealPath(dae, realDaePath_); + LibError ret = g_VFS->RealPath(dae, realDaePath_); debug_assert(ret == INFO::OK); wchar_t realDaeBuf[PATH_MAX]; wcscpy_s(realDaeBuf, ARRAY_SIZE(realDaeBuf), realDaePath_.string().c_str()); diff --git a/source/lib/file/vfs/vfs.cpp b/source/lib/file/vfs/vfs.cpp index 6b8dfc25a3..6253c5f755 100644 --- a/source/lib/file/vfs/vfs.cpp +++ b/source/lib/file/vfs/vfs.cpp @@ -45,7 +45,7 @@ public: virtual LibError Mount(const VfsPath& mountPoint, const fs::wpath& path, size_t flags /* = 0 */, size_t priority /* = 0 */) { - CreateDirectories(path, 0700); + RETURN_ERR(CreateDirectories(path, 0700)); VfsDirectory* directory; CHECK_ERR(vfs_Lookup(mountPoint, &m_rootDirectory, directory, 0, VFS_LOOKUP_ADD|VFS_LOOKUP_CREATE)); @@ -103,13 +103,13 @@ public: const std::wstring& name = pathname.leaf(); RETURN_ERR(realDirectory->Store(name, fileContents, size)); - const VfsFile file(name, size, time(0), realDirectory->Priority(), realDirectory); - directory->AddFile(file); - // wipe out any cached blocks. this is necessary to cover the (rare) case // of file cache contents predating the file write. m_fileCache.Remove(pathname); + const VfsFile file(name, size, time(0), realDirectory->Priority(), realDirectory); + directory->AddFile(file); + m_trace->NotifyStore(pathname.string().c_str(), size); return INFO::OK; } @@ -146,11 +146,6 @@ public: return INFO::OK; } - virtual void Clear() - { - m_rootDirectory.Clear(); - } - virtual std::wstring TextRepresentation() const { std::wstring textRepresentation; @@ -159,12 +154,20 @@ public: return textRepresentation; } - virtual LibError GetRealPath(const VfsPath& pathname, fs::wpath& realPathname) + virtual LibError RealPath(const VfsPath& pathname, fs::wpath& realPathname) { VfsDirectory* directory; CHECK_ERR(vfs_Lookup(pathname, &m_rootDirectory, directory, 0)); - const PRealDirectory& realDirectory = directory->AssociatedDirectory(); - realPathname = realDirectory->Path() / pathname.leaf(); + realPathname = directory->AssociatedDirectory()->Path() / pathname.leaf(); + return INFO::OK; + } + + virtual LibError VirtualPath(const fs::wpath& realPathname, VfsPath& pathname) + { + const fs::wpath realPath = AddSlash(realPathname.branch_path()); + VfsPath path; + RETURN_ERR(FindRealPathR(realPathname, m_rootDirectory, L"", path)); + pathname = path / realPathname.leaf(); return INFO::OK; } @@ -181,6 +184,11 @@ public: return INFO::OK; } + virtual void Clear() + { + m_rootDirectory.Clear(); + } + private: // try to skip unnecessary work by ignoring uninteresting notifications. static bool CanIgnore(const DirWatchNotification& notification) @@ -203,6 +211,29 @@ private: return false; } + LibError FindRealPathR(const fs::wpath& realPath, const VfsDirectory& directory, const VfsPath& curPath, VfsPath& path) + { + PRealDirectory realDirectory = directory.AssociatedDirectory(); + if(realDirectory && realDirectory->Path() == realPath) + { + path = curPath; + return INFO::OK; + } + + const VfsDirectory::VfsSubdirectories& subdirectories = directory.Subdirectories(); + for(VfsDirectory::VfsSubdirectories::const_iterator it = subdirectories.begin(); it != subdirectories.end(); ++it) + { + const std::wstring& subdirectoryName = it->first; + const VfsDirectory& subdirectory = it->second; + LibError ret = FindRealPathR(realPath, subdirectory, AddSlash(path/subdirectoryName), path); + if(ret == INFO::OK) + return INFO::OK; + } + + return ERR::PATH_NOT_FOUND; // NOWARN + } + + LibError NotifyChangedR(VfsDirectory& directory, const VfsPath& path, const fs::wpath& realPathname) { const fs::wpath realPath = AddSlash(realPathname.branch_path()); diff --git a/source/lib/file/vfs/vfs.h b/source/lib/file/vfs/vfs.h index ad4de43275..68a2c5ac9e 100644 --- a/source/lib/file/vfs/vfs.h +++ b/source/lib/file/vfs/vfs.h @@ -70,6 +70,9 @@ struct IVFS /** * retrieve information about a file (similar to POSIX stat) + * + * @param pfileInfo receives information about the file. passing NULL + * suppresses warnings if the file doesn't exist. * * @return LibError. **/ @@ -113,24 +116,27 @@ struct IVFS virtual LibError LoadFile(const VfsPath& pathname, shared_ptr& fileContents, size_t& size) = 0; /** - * @return a text representation of all files and directories. + * @return a string representation of all files and directories. **/ virtual std::wstring TextRepresentation() const = 0; /** - * empty the contents of the filesystem. - * this is typically only necessary when changing the set of - * mounted directories, e.g. when switching mods. - * NB: open files are not affected. + * retrieve the real (POSIX) pathname underlying a VFS file. + * + * this is useful for passing paths to external libraries. **/ - virtual void Clear() = 0; + virtual LibError RealPath(const VfsPath& pathname, fs::wpath& realPathname) = 0; /** - * retrieve the real (POSIX) path underlying a VFS file. + * retrieve the VFS pathname that corresponds to a real file. * - * this is useful when passing paths to external libraries. + * this is useful for reacting to file change notifications. + * + * the current implementation requires time proportional to the + * number of directories; this could be accelerated by only checking + * directories below a mount point with a matching real path. **/ - virtual LibError GetRealPath(const VfsPath& pathname, fs::wpath& path) = 0; + virtual LibError VirtualPath(const fs::wpath& realPathname, VfsPath& pathname) = 0; /** * poll for directory change notifications and reload all affected files. @@ -139,6 +145,14 @@ struct IVFS * note: polling is much simpler than asynchronous notifications. **/ virtual LibError ReloadChangedFiles() = 0; + + /** + * empty the contents of the filesystem. + * this is typically only necessary when changing the set of + * mounted directories, e.g. when switching mods. + * NB: open files are not affected. + **/ + virtual void Clear() = 0; }; typedef shared_ptr PIVFS; diff --git a/source/ps/XML/Xeromyces.cpp b/source/ps/XML/Xeromyces.cpp index ac84bbd201..8bcbd3641b 100644 --- a/source/ps/XML/Xeromyces.cpp +++ b/source/ps/XML/Xeromyces.cpp @@ -75,7 +75,7 @@ void CXeromyces::GetXMBPath(const PIVFS& vfs, const VfsPath& xmlFilename, const // get real path of XML file (e.g. mods/official/entities/...) fs::wpath XMBRealPath_; - vfs->GetRealPath(xmlFilename, XMBRealPath_); + vfs->RealPath(xmlFilename, XMBRealPath_); wchar_t XMBRealPath[PATH_MAX]; wcscpy_s(XMBRealPath, ARRAY_SIZE(XMBRealPath), XMBRealPath_.string().c_str());