#pragma once #if !defined(MIJIN_VIRTUAL_FILESYSTEM_RELATIVE_HPP_INCLUDED) #define MIJIN_VIRTUAL_FILESYSTEM_RELATIVE_HPP_INCLUDED 1 #include "./filesystem.hpp" #include "../internal/common.hpp" namespace mijin { // // public defines // // // public constants // // // public types // template class RelativeFileSystemAdapter : public FileSystemAdapter { private: TWrapped wrapped_; fs::path root_; public: template explicit RelativeFileSystemAdapter(fs::path root, TArgs&&... args) : wrapped_(std::forward(args)...), root_(std::move(root)) {} RelativeFileSystemAdapter(const RelativeFileSystemAdapter&) = default; RelativeFileSystemAdapter(RelativeFileSystemAdapter&&) MIJIN_NOEXCEPT = default; RelativeFileSystemAdapter& operator=(const RelativeFileSystemAdapter&) = default; RelativeFileSystemAdapter& operator=(RelativeFileSystemAdapter&&) MIJIN_NOEXCEPT = default; fs::path getHomeFolder() override; std::vector listFiles(const fs::path& folder) override; FileInfo getFileInfo(const fs::path& file) override; Optional getNativePath(const fs::path& file) override; StreamError open(const fs::path& path, FileOpenMode mode, std::unique_ptr& outStream) override; private: fs::path appendPath(const fs::path& other) const MIJIN_NOEXCEPT; }; // // public functions // template fs::path RelativeFileSystemAdapter::getHomeFolder() { return root_; } template std::vector RelativeFileSystemAdapter::listFiles(const fs::path& folder) { std::vector result; result = wrapped_.listFiles(appendPath(folder)); for (FileInfo& fileInfo : result) { fileInfo.path = "/" / fileInfo.path.lexically_relative(root_); } return result; } template FileInfo RelativeFileSystemAdapter::getFileInfo(const fs::path& file) { return wrapped_.getFileInfo(appendPath(file)); } template Optional RelativeFileSystemAdapter::getNativePath(const fs::path& file) { return wrapped_.getNativePath(appendPath(file)); } template StreamError RelativeFileSystemAdapter::open(const fs::path& path, FileOpenMode mode, std::unique_ptr& outStream) { return wrapped_.open(appendPath(path), mode, outStream); } template fs::path RelativeFileSystemAdapter::appendPath(const fs::path& other) const MIJIN_NOEXCEPT { fs::path combinedPath = root_; if (other.is_absolute()) { combinedPath += other; } else { combinedPath /= other; } return combinedPath.lexically_normal(); } namespace vfs_pipe { template struct RelativeBuilder : Builder, RelativeFileSystemAdapter> { fs::path root; TBase base; std::unique_ptr> build() { return std::make_unique>(root, std::move(*base.build())); } }; struct RelativeOptions { fs::path root; }; [[nodiscard]] inline RelativeOptions relative_to(fs::path root) noexcept { return {.root = std::move(root) }; } template [[nodiscard]] RelativeBuilder operator|(TBase other, RelativeOptions options) noexcept { return {.root = std::move(options.root), .base = std::move(other) }; } } } // namespace mijin #endif // !defined(MIJIN_VIRTUAL_FILESYSTEM_RELATIVE_HPP_INCLUDED)