diff options
| author | 2018-07-18 21:07:11 -0400 | |
|---|---|---|
| committer | 2018-07-18 18:07:11 -0700 | |
| commit | 29aff8d5ab46c8d0199aa4bfa7eeff5d4fa2d7ef (patch) | |
| tree | 3202e2ce55ab6387a4ca366a509eccdd963434c3 /src/core/file_sys/vfs.h | |
| parent | Merge pull request #683 from DarkLordZach/touch (diff) | |
| download | yuzu-29aff8d5ab46c8d0199aa4bfa7eeff5d4fa2d7ef.tar.gz yuzu-29aff8d5ab46c8d0199aa4bfa7eeff5d4fa2d7ef.tar.xz yuzu-29aff8d5ab46c8d0199aa4bfa7eeff5d4fa2d7ef.zip | |
Virtual Filesystem 2: Electric Boogaloo (#676)
* Virtual Filesystem
* Fix delete bug and documentate
* Review fixes + other stuff
* Fix puyo regression
Diffstat (limited to 'src/core/file_sys/vfs.h')
| -rw-r--r-- | src/core/file_sys/vfs.h | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h new file mode 100644 index 000000000..a5213e0cc --- /dev/null +++ b/src/core/file_sys/vfs.h | |||
| @@ -0,0 +1,237 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <string> | ||
| 9 | #include <type_traits> | ||
| 10 | #include <vector> | ||
| 11 | #include "boost/optional.hpp" | ||
| 12 | #include "common/common_types.h" | ||
| 13 | #include "common/file_util.h" | ||
| 14 | |||
| 15 | namespace FileSys { | ||
| 16 | struct VfsFile; | ||
| 17 | struct VfsDirectory; | ||
| 18 | |||
| 19 | // Convenience typedefs to use VfsDirectory and VfsFile | ||
| 20 | using VirtualDir = std::shared_ptr<FileSys::VfsDirectory>; | ||
| 21 | using VirtualFile = std::shared_ptr<FileSys::VfsFile>; | ||
| 22 | |||
| 23 | // A class representing a file in an abstract filesystem. | ||
| 24 | struct VfsFile : NonCopyable { | ||
| 25 | virtual ~VfsFile(); | ||
| 26 | |||
| 27 | // Retrieves the file name. | ||
| 28 | virtual std::string GetName() const = 0; | ||
| 29 | // Retrieves the extension of the file name. | ||
| 30 | virtual std::string GetExtension() const; | ||
| 31 | // Retrieves the size of the file. | ||
| 32 | virtual size_t GetSize() const = 0; | ||
| 33 | // Resizes the file to new_size. Returns whether or not the operation was successful. | ||
| 34 | virtual bool Resize(size_t new_size) = 0; | ||
| 35 | // Gets a pointer to the directory containing this file, returning nullptr if there is none. | ||
| 36 | virtual std::shared_ptr<VfsDirectory> GetContainingDirectory() const = 0; | ||
| 37 | |||
| 38 | // Returns whether or not the file can be written to. | ||
| 39 | virtual bool IsWritable() const = 0; | ||
| 40 | // Returns whether or not the file can be read from. | ||
| 41 | virtual bool IsReadable() const = 0; | ||
| 42 | |||
| 43 | // The primary method of reading from the file. Reads length bytes into data starting at offset | ||
| 44 | // into file. Returns number of bytes successfully read. | ||
| 45 | virtual size_t Read(u8* data, size_t length, size_t offset = 0) const = 0; | ||
| 46 | // The primary method of writing to the file. Writes length bytes from data starting at offset | ||
| 47 | // into file. Returns number of bytes successfully written. | ||
| 48 | virtual size_t Write(const u8* data, size_t length, size_t offset = 0) = 0; | ||
| 49 | |||
| 50 | // Reads exactly one byte at the offset provided, returning boost::none on error. | ||
| 51 | virtual boost::optional<u8> ReadByte(size_t offset = 0) const; | ||
| 52 | // Reads size bytes starting at offset in file into a vector. | ||
| 53 | virtual std::vector<u8> ReadBytes(size_t size, size_t offset = 0) const; | ||
| 54 | // Reads all the bytes from the file into a vector. Equivalent to 'file->Read(file->GetSize(), | ||
| 55 | // 0)' | ||
| 56 | virtual std::vector<u8> ReadAllBytes() const; | ||
| 57 | |||
| 58 | // Reads an array of type T, size number_elements starting at offset. | ||
| 59 | // Returns the number of bytes (sizeof(T)*number_elements) read successfully. | ||
| 60 | template <typename T> | ||
| 61 | size_t ReadArray(T* data, size_t number_elements, size_t offset = 0) const { | ||
| 62 | static_assert(std::is_trivially_copyable<T>::value, | ||
| 63 | "Data type must be trivially copyable."); | ||
| 64 | |||
| 65 | return Read(reinterpret_cast<u8*>(data), number_elements * sizeof(T), offset); | ||
| 66 | } | ||
| 67 | |||
| 68 | // Reads size bytes into the memory starting at data starting at offset into the file. | ||
| 69 | // Returns the number of bytes read successfully. | ||
| 70 | template <typename T> | ||
| 71 | size_t ReadBytes(T* data, size_t size, size_t offset = 0) const { | ||
| 72 | static_assert(std::is_trivially_copyable<T>::value, | ||
| 73 | "Data type must be trivially copyable."); | ||
| 74 | return Read(reinterpret_cast<u8*>(data), size, offset); | ||
| 75 | } | ||
| 76 | |||
| 77 | // Reads one object of type T starting at offset in file. | ||
| 78 | // Returns the number of bytes read successfully (sizeof(T)). | ||
| 79 | template <typename T> | ||
| 80 | size_t ReadObject(T* data, size_t offset = 0) const { | ||
| 81 | static_assert(std::is_trivially_copyable<T>::value, | ||
| 82 | "Data type must be trivially copyable."); | ||
| 83 | return Read(reinterpret_cast<u8*>(data), sizeof(T), offset); | ||
| 84 | } | ||
| 85 | |||
| 86 | // Writes exactly one byte to offset in file and retuns whether or not the byte was written | ||
| 87 | // successfully. | ||
| 88 | virtual bool WriteByte(u8 data, size_t offset = 0); | ||
| 89 | // Writes a vector of bytes to offset in file and returns the number of bytes successfully | ||
| 90 | // written. | ||
| 91 | virtual size_t WriteBytes(std::vector<u8> data, size_t offset = 0); | ||
| 92 | |||
| 93 | // Writes an array of type T, size number_elements to offset in file. | ||
| 94 | // Returns the number of bytes (sizeof(T)*number_elements) written successfully. | ||
| 95 | template <typename T> | ||
| 96 | size_t WriteArray(T* data, size_t number_elements, size_t offset = 0) { | ||
| 97 | static_assert(std::is_trivially_copyable<T>::value, | ||
| 98 | "Data type must be trivially copyable."); | ||
| 99 | |||
| 100 | return Write(data, number_elements * sizeof(T), offset); | ||
| 101 | } | ||
| 102 | |||
| 103 | // Writes size bytes starting at memory location data to offset in file. | ||
| 104 | // Returns the number of bytes written successfully. | ||
| 105 | template <typename T> | ||
| 106 | size_t WriteBytes(T* data, size_t size, size_t offset = 0) { | ||
| 107 | static_assert(std::is_trivially_copyable<T>::value, | ||
| 108 | "Data type must be trivially copyable."); | ||
| 109 | return Write(reinterpret_cast<u8*>(data), size, offset); | ||
| 110 | } | ||
| 111 | |||
| 112 | // Writes one object of type T to offset in file. | ||
| 113 | // Returns the number of bytes written successfully (sizeof(T)). | ||
| 114 | template <typename T> | ||
| 115 | size_t WriteObject(const T& data, size_t offset = 0) { | ||
| 116 | static_assert(std::is_trivially_copyable<T>::value, | ||
| 117 | "Data type must be trivially copyable."); | ||
| 118 | return Write(&data, sizeof(T), offset); | ||
| 119 | } | ||
| 120 | |||
| 121 | // Renames the file to name. Returns whether or not the operation was successsful. | ||
| 122 | virtual bool Rename(const std::string& name) = 0; | ||
| 123 | }; | ||
| 124 | |||
| 125 | // A class representing a directory in an abstract filesystem. | ||
| 126 | struct VfsDirectory : NonCopyable { | ||
| 127 | virtual ~VfsDirectory(); | ||
| 128 | |||
| 129 | // Retrives the file located at path as if the current directory was root. Returns nullptr if | ||
| 130 | // not found. | ||
| 131 | virtual std::shared_ptr<VfsFile> GetFileRelative(const std::string& path) const; | ||
| 132 | // Calls GetFileRelative(path) on the root of the current directory. | ||
| 133 | virtual std::shared_ptr<VfsFile> GetFileAbsolute(const std::string& path) const; | ||
| 134 | |||
| 135 | // Retrives the directory located at path as if the current directory was root. Returns nullptr | ||
| 136 | // if not found. | ||
| 137 | virtual std::shared_ptr<VfsDirectory> GetDirectoryRelative(const std::string& path) const; | ||
| 138 | // Calls GetDirectoryRelative(path) on the root of the current directory. | ||
| 139 | virtual std::shared_ptr<VfsDirectory> GetDirectoryAbsolute(const std::string& path) const; | ||
| 140 | |||
| 141 | // Returns a vector containing all of the files in this directory. | ||
| 142 | virtual std::vector<std::shared_ptr<VfsFile>> GetFiles() const = 0; | ||
| 143 | // Returns the file with filename matching name. Returns nullptr if directory dosen't have a | ||
| 144 | // file with name. | ||
| 145 | virtual std::shared_ptr<VfsFile> GetFile(const std::string& name) const; | ||
| 146 | |||
| 147 | // Returns a vector containing all of the subdirectories in this directory. | ||
| 148 | virtual std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const = 0; | ||
| 149 | // Returns the directory with name matching name. Returns nullptr if directory dosen't have a | ||
| 150 | // directory with name. | ||
| 151 | virtual std::shared_ptr<VfsDirectory> GetSubdirectory(const std::string& name) const; | ||
| 152 | |||
| 153 | // Returns whether or not the directory can be written to. | ||
| 154 | virtual bool IsWritable() const = 0; | ||
| 155 | // Returns whether of not the directory can be read from. | ||
| 156 | virtual bool IsReadable() const = 0; | ||
| 157 | |||
| 158 | // Returns whether or not the directory is the root of the current file tree. | ||
| 159 | virtual bool IsRoot() const; | ||
| 160 | |||
| 161 | // Returns the name of the directory. | ||
| 162 | virtual std::string GetName() const = 0; | ||
| 163 | // Returns the total size of all files and subdirectories in this directory. | ||
| 164 | virtual size_t GetSize() const; | ||
| 165 | // Returns the parent directory of this directory. Returns nullptr if this directory is root or | ||
| 166 | // has no parent. | ||
| 167 | virtual std::shared_ptr<VfsDirectory> GetParentDirectory() const = 0; | ||
| 168 | |||
| 169 | // Creates a new subdirectory with name name. Returns a pointer to the new directory or nullptr | ||
| 170 | // if the operation failed. | ||
| 171 | virtual std::shared_ptr<VfsDirectory> CreateSubdirectory(const std::string& name) = 0; | ||
| 172 | // Creates a new file with name name. Returns a pointer to the new file or nullptr if the | ||
| 173 | // operation failed. | ||
| 174 | virtual std::shared_ptr<VfsFile> CreateFile(const std::string& name) = 0; | ||
| 175 | |||
| 176 | // Creates a new file at the path relative to this directory. Also creates directories if | ||
| 177 | // they do not exist and is supported by this implementation. Returns nullptr on any failure. | ||
| 178 | virtual std::shared_ptr<VfsFile> CreateFileRelative(const std::string& path); | ||
| 179 | |||
| 180 | // Creates a new file at the path relative to root of this directory. Also creates directories | ||
| 181 | // if they do not exist and is supported by this implementation. Returns nullptr on any failure. | ||
| 182 | virtual std::shared_ptr<VfsFile> CreateFileAbsolute(const std::string& path); | ||
| 183 | |||
| 184 | // Creates a new directory at the path relative to this directory. Also creates directories if | ||
| 185 | // they do not exist and is supported by this implementation. Returns nullptr on any failure. | ||
| 186 | virtual std::shared_ptr<VfsDirectory> CreateDirectoryRelative(const std::string& path); | ||
| 187 | |||
| 188 | // Creates a new directory at the path relative to root of this directory. Also creates | ||
| 189 | // directories if they do not exist and is supported by this implementation. Returns nullptr on | ||
| 190 | // any failure. | ||
| 191 | virtual std::shared_ptr<VfsDirectory> CreateDirectoryAbsolute(const std::string& path); | ||
| 192 | |||
| 193 | // Deletes the subdirectory with name and returns true on success. | ||
| 194 | virtual bool DeleteSubdirectory(const std::string& name) = 0; | ||
| 195 | // Deletes all subdirectories and files of subdirectory with name recirsively and then deletes | ||
| 196 | // the subdirectory. Returns true on success. | ||
| 197 | virtual bool DeleteSubdirectoryRecursive(const std::string& name); | ||
| 198 | // Returnes whether or not the file with name name was deleted successfully. | ||
| 199 | virtual bool DeleteFile(const std::string& name) = 0; | ||
| 200 | |||
| 201 | // Returns whether or not this directory was renamed to name. | ||
| 202 | virtual bool Rename(const std::string& name) = 0; | ||
| 203 | |||
| 204 | // Returns whether or not the file with name src was successfully copied to a new file with name | ||
| 205 | // dest. | ||
| 206 | virtual bool Copy(const std::string& src, const std::string& dest); | ||
| 207 | |||
| 208 | // Interprets the file with name file instead as a directory of type directory. | ||
| 209 | // The directory must have a constructor that takes a single argument of type | ||
| 210 | // std::shared_ptr<VfsFile>. Allows to reinterpret container files (i.e NCA, zip, XCI, etc) as a | ||
| 211 | // subdirectory in one call. | ||
| 212 | template <typename Directory> | ||
| 213 | bool InterpretAsDirectory(const std::string& file) { | ||
| 214 | auto file_p = GetFile(file); | ||
| 215 | if (file_p == nullptr) | ||
| 216 | return false; | ||
| 217 | return ReplaceFileWithSubdirectory(file, std::make_shared<Directory>(file_p)); | ||
| 218 | } | ||
| 219 | |||
| 220 | protected: | ||
| 221 | // Backend for InterpretAsDirectory. | ||
| 222 | // Removes all references to file and adds a reference to dir in the directory's implementation. | ||
| 223 | virtual bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) = 0; | ||
| 224 | }; | ||
| 225 | |||
| 226 | // A convenience partial-implementation of VfsDirectory that stubs out methods that should only work | ||
| 227 | // if writable. This is to avoid redundant empty methods everywhere. | ||
| 228 | struct ReadOnlyVfsDirectory : public VfsDirectory { | ||
| 229 | bool IsWritable() const override; | ||
| 230 | bool IsReadable() const override; | ||
| 231 | std::shared_ptr<VfsDirectory> CreateSubdirectory(const std::string& name) override; | ||
| 232 | std::shared_ptr<VfsFile> CreateFile(const std::string& name) override; | ||
| 233 | bool DeleteSubdirectory(const std::string& name) override; | ||
| 234 | bool DeleteFile(const std::string& name) override; | ||
| 235 | bool Rename(const std::string& name) override; | ||
| 236 | }; | ||
| 237 | } // namespace FileSys | ||