diff --git a/hecl/include/HECL/HECL.hpp b/hecl/include/HECL/HECL.hpp index c394e23b2..6a7fd4794 100644 --- a/hecl/include/HECL/HECL.hpp +++ b/hecl/include/HECL/HECL.hpp @@ -416,6 +416,28 @@ public: bool operator>=(const Time& other) const {return ts >= other.ts;} }; +/** + * @brief Special ProjectRootPath class for opening HECLDatabase::IProject instances + * + * Constructing a ProjectPath requires supplying a ProjectRootPath to consistently + * resolve canonicalized relative paths. + */ +class ProjectRootPath +{ + SystemString m_projRoot; +public: + ProjectRootPath(const SystemString& path) : m_projRoot(path) {SanitizePath(m_projRoot);} + const SystemString& getAbsolutePath() const {return m_projRoot;} + + /** + * @brief Create directory at path + * + * Fatal log report is issued if directory is not able to be created or doesn't already exist. + * If directory already exists, no action taken. + */ + void makeDir() const {MakeDir(m_projRoot.c_str());} +}; + /** * @brief Canonicalized project path representation using POSIX conventions * @@ -431,8 +453,7 @@ public: */ class ProjectPath { -protected: - SystemString m_projRoot; + const ProjectRootPath* m_projRoot = nullptr; SystemString m_absPath; SystemString m_relPath; Hash m_hash = 0; @@ -440,31 +461,32 @@ protected: std::string m_utf8AbsPath; std::string m_utf8RelPath; #endif - ProjectPath(const SystemString& projRoot) - : m_projRoot(projRoot), m_absPath(projRoot), m_relPath(_S(".")) - { - SanitizePath(m_projRoot); - SanitizePath(m_relPath); - SanitizePath(m_absPath); - m_hash = Hash(m_relPath); -#if HECL_UCS2 - m_utf8AbsPath = WideToUTF8(m_absPath); - m_utf8RelPath = "."; -#endif - } public: /** * @brief Empty constructor * * Used to preallocate ProjectPath for later population using assign() */ - ProjectPath() {} + ProjectPath() = default; /** * @brief Tests for non-empty project path */ operator bool() const {return m_absPath.size() != 0;} + /** + * @brief Construct a project subpath representation within a root path + * @param parentPath previously constructed ProjectRootPath + * @param path valid filesystem-path (relative or absolute) to subpath + */ + ProjectPath(const ProjectRootPath& parentPath, const SystemString& path) {assign(parentPath, path);} + void assign(const ProjectRootPath& parentPath, const SystemString& path); + +#if HECL_UCS2 + ProjectPath(const ProjectRootPath& parentPath, const std::string& path) {assign(parentPath, path);} + void assign(const ProjectRootPath& parentPath, const std::string& path); +#endif + /** * @brief Construct a project subpath representation within another subpath * @param parentPath previously constructed ProjectPath which ultimately connects to a ProjectRootPath @@ -614,19 +636,6 @@ public: }; -/** - * @brief Special ProjectRootPath subclass for opening HECLDatabase::IProject instances - * - * Constructing a ProjectPath requires supplying a ProjectRootPath to consistently - * resolve canonicalized relative paths. - */ -class ProjectRootPath : public ProjectPath -{ -public: - ProjectRootPath(const SystemString& path) - : ProjectPath(path) {} -}; - /** * @brief Search from within provided directory for the project root * @param path absolute or relative file path to search from diff --git a/hecl/lib/ProjectPath.cpp b/hecl/lib/ProjectPath.cpp index 5c4d823e1..a6a2233ce 100644 --- a/hecl/lib/ProjectPath.cpp +++ b/hecl/lib/ProjectPath.cpp @@ -55,13 +55,41 @@ static SystemString canonRelPath(const SystemString& path) return _S("."); } +void ProjectPath::assign(const ProjectRootPath& parentPath, const SystemString& path) +{ + m_projRoot = &parentPath; + m_relPath = canonRelPath(path); + m_absPath = parentPath.getAbsolutePath() + _S('/') + m_relPath; + SanitizePath(m_relPath); + SanitizePath(m_absPath); + m_hash = Hash(m_relPath); + +#if HECL_UCS2 + m_utf8AbsPath = WideToUTF8(m_absPath); + m_utf8RelPath = WideToUTF8(m_relPath); +#endif +} + +#if HECL_UCS2 +void ProjectPath::assign(const ProjectRootPath& parentPath, const std::string& path) +{ + m_projRoot = &parentPath; + std::wstring wpath = UTF8ToWide(path); + m_relPath = canonRelPath(wpath); + m_absPath = parentPath.getAbsolutePath() + _S('/') + m_relPath; + SanitizePath(m_relPath); + SanitizePath(m_absPath); + m_hash = Hash(m_relPath); + m_utf8AbsPath = WideToUTF8(m_absPath); + m_utf8RelPath = WideToUTF8(m_relPath); +} +#endif + void ProjectPath::assign(const ProjectPath& parentPath, const SystemString& path) { - SystemString in = path; m_projRoot = parentPath.m_projRoot; - m_relPath = canonRelPath(parentPath.m_relPath + _S('/') + in); - m_absPath = parentPath.m_projRoot + _S('/') + m_relPath; - SanitizePath(m_projRoot); + m_relPath = canonRelPath(parentPath.m_relPath + _S('/') + path); + m_absPath = parentPath.m_projRoot->getAbsolutePath() + _S('/') + m_relPath; SanitizePath(m_relPath); SanitizePath(m_absPath); m_hash = Hash(m_relPath); @@ -75,12 +103,10 @@ void ProjectPath::assign(const ProjectPath& parentPath, const SystemString& path #if HECL_UCS2 void ProjectPath::assign(const ProjectPath& parentPath, const std::string& path) { - std::string in = path; m_projRoot = parentPath.m_projRoot; - std::wstring wpath = UTF8ToWide(in); + std::wstring wpath = UTF8ToWide(path); m_relPath = canonRelPath(parentPath.m_relPath + _S('/') + wpath); - m_absPath = parentPath.m_projRoot + _S('/') + m_relPath; - SanitizePath(m_projRoot); + m_absPath = parentPath.m_projRoot->getAbsolutePath() + _S('/') + m_relPath; SanitizePath(m_relPath); SanitizePath(m_absPath); m_hash = Hash(m_relPath);