vfs_layered: Add LayeredVfsDirectory
Reads multiple dirs through as if a waterfall.
This commit is contained in:
		
							
								
								
									
										128
									
								
								src/core/file_sys/vfs_layered.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								src/core/file_sys/vfs_layered.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,128 @@
 | 
			
		||||
// Copyright 2018 yuzu emulator team
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <utility>
 | 
			
		||||
#include "core/file_sys/vfs_layered.h"
 | 
			
		||||
 | 
			
		||||
namespace FileSys {
 | 
			
		||||
 | 
			
		||||
VirtualDir LayerDirectories(std::vector<VirtualDir> dirs, std::string name) {
 | 
			
		||||
    if (dirs.empty())
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    if (dirs.size() == 1)
 | 
			
		||||
        return dirs[0];
 | 
			
		||||
 | 
			
		||||
    return std::shared_ptr<VfsDirectory>(new LayeredVfsDirectory(std::move(dirs), std::move(name)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LayeredVfsDirectory::LayeredVfsDirectory(std::vector<VirtualDir> dirs, std::string name)
 | 
			
		||||
    : dirs(std::move(dirs)), name(std::move(name)) {}
 | 
			
		||||
 | 
			
		||||
std::shared_ptr<VfsFile> LayeredVfsDirectory::GetFileRelative(std::string_view path) const {
 | 
			
		||||
    VirtualFile file;
 | 
			
		||||
    for (const auto& layer : dirs) {
 | 
			
		||||
        file = layer->GetFileRelative(path);
 | 
			
		||||
        if (file != nullptr)
 | 
			
		||||
            return file;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::shared_ptr<VfsDirectory> LayeredVfsDirectory::GetDirectoryRelative(
 | 
			
		||||
    std::string_view path) const {
 | 
			
		||||
    std::vector<VirtualDir> out;
 | 
			
		||||
    for (const auto& layer : dirs) {
 | 
			
		||||
        const auto dir = layer->GetDirectoryRelative(path);
 | 
			
		||||
        if (dir != nullptr)
 | 
			
		||||
            out.push_back(dir);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return LayerDirectories(out);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::shared_ptr<VfsFile> LayeredVfsDirectory::GetFile(std::string_view name) const {
 | 
			
		||||
    return GetFileRelative(name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::shared_ptr<VfsDirectory> LayeredVfsDirectory::GetSubdirectory(std::string_view name) const {
 | 
			
		||||
    return GetDirectoryRelative(name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string LayeredVfsDirectory::GetFullPath() const {
 | 
			
		||||
    return dirs[0]->GetFullPath();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::vector<std::shared_ptr<VfsFile>> LayeredVfsDirectory::GetFiles() const {
 | 
			
		||||
    std::vector<VirtualFile> out;
 | 
			
		||||
    for (const auto& layer : dirs) {
 | 
			
		||||
        for (const auto& file : layer->GetFiles()) {
 | 
			
		||||
            if (std::find_if(out.begin(), out.end(), [&file](const VirtualFile& comp) {
 | 
			
		||||
                    return comp->GetName() == file->GetName();
 | 
			
		||||
                }) == out.end())
 | 
			
		||||
                out.push_back(file);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::vector<std::shared_ptr<VfsDirectory>> LayeredVfsDirectory::GetSubdirectories() const {
 | 
			
		||||
    std::vector<std::string> names;
 | 
			
		||||
    for (const auto& layer : dirs) {
 | 
			
		||||
        for (const auto& sd : layer->GetSubdirectories()) {
 | 
			
		||||
            if (std::find(names.begin(), names.end(), sd->GetName()) == names.end())
 | 
			
		||||
                names.push_back(sd->GetName());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::vector<VirtualDir> out;
 | 
			
		||||
    for (const auto& subdir : names)
 | 
			
		||||
        out.push_back(GetSubdirectory(subdir));
 | 
			
		||||
 | 
			
		||||
    return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool LayeredVfsDirectory::IsWritable() const {
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool LayeredVfsDirectory::IsReadable() const {
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string LayeredVfsDirectory::GetName() const {
 | 
			
		||||
    return name.empty() ? dirs[0]->GetName() : name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::shared_ptr<VfsDirectory> LayeredVfsDirectory::GetParentDirectory() const {
 | 
			
		||||
    return dirs[0]->GetParentDirectory();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::shared_ptr<VfsDirectory> LayeredVfsDirectory::CreateSubdirectory(std::string_view name) {
 | 
			
		||||
    return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::shared_ptr<VfsFile> LayeredVfsDirectory::CreateFile(std::string_view name) {
 | 
			
		||||
    return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool LayeredVfsDirectory::DeleteSubdirectory(std::string_view name) {
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool LayeredVfsDirectory::DeleteFile(std::string_view name) {
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool LayeredVfsDirectory::Rename(std::string_view name_) {
 | 
			
		||||
    name = name_;
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool LayeredVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
} // namespace FileSys
 | 
			
		||||
							
								
								
									
										50
									
								
								src/core/file_sys/vfs_layered.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/core/file_sys/vfs_layered.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
// Copyright 2018 yuzu emulator team
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include "core/file_sys/vfs.h"
 | 
			
		||||
 | 
			
		||||
namespace FileSys {
 | 
			
		||||
 | 
			
		||||
// Wrapper function to allow for more efficient handling of dirs.size() == 0, 1 cases.
 | 
			
		||||
VirtualDir LayerDirectories(std::vector<VirtualDir> dirs, std::string name = "");
 | 
			
		||||
 | 
			
		||||
// Class that stacks multiple VfsDirectories on top of each other, attempting to read from the first
 | 
			
		||||
// one and falling back to the one after. The highest priority directory (overwrites all others)
 | 
			
		||||
// should be element 0 in the dirs vector.
 | 
			
		||||
class LayeredVfsDirectory : public VfsDirectory {
 | 
			
		||||
    friend VirtualDir LayerDirectories(std::vector<VirtualDir> dirs, std::string name);
 | 
			
		||||
 | 
			
		||||
    LayeredVfsDirectory(std::vector<VirtualDir> dirs, std::string name);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    std::shared_ptr<VfsFile> GetFileRelative(std::string_view path) const override;
 | 
			
		||||
    std::shared_ptr<VfsDirectory> GetDirectoryRelative(std::string_view path) const override;
 | 
			
		||||
    std::shared_ptr<VfsFile> GetFile(std::string_view name) const override;
 | 
			
		||||
    std::shared_ptr<VfsDirectory> GetSubdirectory(std::string_view name) const override;
 | 
			
		||||
    std::string GetFullPath() const override;
 | 
			
		||||
 | 
			
		||||
    std::vector<std::shared_ptr<VfsFile>> GetFiles() const override;
 | 
			
		||||
    std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const override;
 | 
			
		||||
    bool IsWritable() const override;
 | 
			
		||||
    bool IsReadable() const override;
 | 
			
		||||
    std::string GetName() const override;
 | 
			
		||||
    std::shared_ptr<VfsDirectory> GetParentDirectory() const override;
 | 
			
		||||
    std::shared_ptr<VfsDirectory> CreateSubdirectory(std::string_view name) override;
 | 
			
		||||
    std::shared_ptr<VfsFile> CreateFile(std::string_view name) override;
 | 
			
		||||
    bool DeleteSubdirectory(std::string_view name) override;
 | 
			
		||||
    bool DeleteFile(std::string_view name) override;
 | 
			
		||||
    bool Rename(std::string_view name) override;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::vector<VirtualDir> dirs;
 | 
			
		||||
    std::string name;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace FileSys
 | 
			
		||||
		Reference in New Issue
	
	Block a user