#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_; Path root_; public: template explicit RelativeFileSystemAdapter(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; std::vector listFiles(PathView folder) override; FileInfo getFileInfo(PathView file) override; Optional getNativePath(PathView file) override; StreamError open(PathView path, FileOpenMode mode, std::unique_ptr& outStream) override; private: Path appendPath(PathView other) const MIJIN_NOEXCEPT; }; // // public functions // template std::vector RelativeFileSystemAdapter::listFiles(PathView folder) { std::vector result; result = wrapped_.listFiles(appendPath(folder)); for (FolderEntry& fileInfo : result) { fileInfo.path = Path("/") / fileInfo.path.stringView().substr(root_.size()); } return result; } template FileInfo RelativeFileSystemAdapter::getFileInfo(PathView file) { return wrapped_.getFileInfo(appendPath(file)); } template Optional RelativeFileSystemAdapter::getNativePath(PathView file) { return wrapped_.getNativePath(appendPath(file)); } template StreamError RelativeFileSystemAdapter::open(PathView path, FileOpenMode mode, std::unique_ptr& outStream) { return wrapped_.open(appendPath(path), mode, outStream); } template Path RelativeFileSystemAdapter::appendPath(PathView other) const MIJIN_NOEXCEPT { Path combinedPath = root_; std::string_view otherSv(other.stringView()); if (!otherSv.empty() && otherSv[0] == Path::SEPARATOR) { otherSv = otherSv.substr(1); } combinedPath /= otherSv; return combinedPath; } namespace vfs_pipe { template struct RelativeBuilder : Builder, RelativeFileSystemAdapter> { Path root; TBase base; std::unique_ptr> build() { return std::make_unique>(root, std::move(*base.build())); } }; struct RelativeOptions { Path root; }; [[nodiscard]] inline RelativeOptions relative_to(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)