130 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
 | |
| #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<typename TWrapped>
 | |
| class RelativeFileSystemAdapter : public FileSystemAdapter
 | |
| {
 | |
| private:
 | |
|     TWrapped wrapped_;
 | |
|     Path root_;
 | |
| public:
 | |
|     template<typename... TArgs>
 | |
|     explicit RelativeFileSystemAdapter(Path root, TArgs&&... args)
 | |
|         : wrapped_(std::forward<TArgs>(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<FolderEntry> listFiles(PathView folder) override;
 | |
|     FileInfo getFileInfo(PathView file) override;
 | |
|     Optional<NativePath> getNativePath(PathView file) override;
 | |
|     StreamError open(PathView path, FileOpenMode mode, std::unique_ptr<Stream>& outStream) override;
 | |
| private:
 | |
|     Path appendPath(PathView other) const MIJIN_NOEXCEPT;
 | |
| };
 | |
| 
 | |
| //
 | |
| // public functions
 | |
| //
 | |
| 
 | |
| template<typename TWrapped>
 | |
| std::vector<FolderEntry> RelativeFileSystemAdapter<TWrapped>::listFiles(PathView folder)
 | |
| {
 | |
|     std::vector<FolderEntry> result;
 | |
| 
 | |
|     result = wrapped_.listFiles(appendPath(folder));
 | |
|     for (FolderEntry& fileInfo : result) {
 | |
|         fileInfo.path = Path("/") / fileInfo.path.stringView().substr(root_.size());
 | |
|     }
 | |
|     return result;
 | |
| }
 | |
| 
 | |
| template<typename TWrapped>
 | |
| FileInfo RelativeFileSystemAdapter<TWrapped>::getFileInfo(PathView file)
 | |
| {
 | |
|     return wrapped_.getFileInfo(appendPath(file));
 | |
| }
 | |
| 
 | |
| template<typename TWrapped>
 | |
| Optional<NativePath> RelativeFileSystemAdapter<TWrapped>::getNativePath(PathView file)
 | |
| {
 | |
|     return wrapped_.getNativePath(appendPath(file));
 | |
| }
 | |
| 
 | |
| template<typename TWrapped>
 | |
| StreamError RelativeFileSystemAdapter<TWrapped>::open(PathView path, FileOpenMode mode, std::unique_ptr<Stream>& outStream)
 | |
| {
 | |
|     return wrapped_.open(appendPath(path), mode, outStream);
 | |
| }
 | |
| 
 | |
| template<typename TWrapped>
 | |
| Path RelativeFileSystemAdapter<TWrapped>::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<typename TBase>
 | |
| struct RelativeBuilder : Builder<RelativeBuilder<TBase>, RelativeFileSystemAdapter<typename TBase::adapter_t>>
 | |
| {
 | |
|     Path root;
 | |
|     TBase base;
 | |
| 
 | |
|     std::unique_ptr<RelativeFileSystemAdapter<typename TBase::adapter_t>> build()
 | |
|     {
 | |
|         return std::make_unique<RelativeFileSystemAdapter<typename TBase::adapter_t>>(root, std::move(*base.build()));
 | |
|     }
 | |
| };
 | |
| 
 | |
| struct RelativeOptions
 | |
| {
 | |
|     Path root;
 | |
| };
 | |
| 
 | |
| [[nodiscard]]
 | |
| inline RelativeOptions relative_to(Path root) noexcept
 | |
| {
 | |
|     return {.root = std::move(root) };
 | |
| }
 | |
| 
 | |
| template<typename TBase>
 | |
| [[nodiscard]]
 | |
| RelativeBuilder<TBase> 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)
 |