diff options
| author | 2018-08-03 11:50:00 -0400 | |
|---|---|---|
| committer | 2018-08-08 21:18:45 -0400 | |
| commit | 2de2ec25d6e8971809f98ebe36996c00e0f89f2d (patch) | |
| tree | 7b8ec6b50b8c5de91eef426c3ad3cb4d0d7c2e05 /src | |
| parent | file_util: Add platform-specific slash option to SanitizePath (diff) | |
| download | yuzu-2de2ec25d6e8971809f98ebe36996c00e0f89f2d.tar.gz yuzu-2de2ec25d6e8971809f98ebe36996c00e0f89f2d.tar.xz yuzu-2de2ec25d6e8971809f98ebe36996c00e0f89f2d.zip | |
vfs: Add RealVfsFilesystem implementation
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/file_sys/vfs_real.cpp | 327 | ||||
| -rw-r--r-- | src/core/file_sys/vfs_real.h | 44 |
2 files changed, 290 insertions, 81 deletions
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp index 82d54da4a..2923a8e6a 100644 --- a/src/core/file_sys/vfs_real.cpp +++ b/src/core/file_sys/vfs_real.cpp | |||
| @@ -36,8 +36,164 @@ static std::string ModeFlagsToString(Mode mode) { | |||
| 36 | return mode_str; | 36 | return mode_str; |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | RealVfsFile::RealVfsFile(const std::string& path_, Mode perms_) | 39 | RealVfsFilesystem::RealVfsFilesystem() : VfsFilesystem(nullptr) {} |
| 40 | : backing(path_, ModeFlagsToString(perms_).c_str()), path(path_), | 40 | |
| 41 | std::string RealVfsFilesystem::GetName() const { | ||
| 42 | return "Real"; | ||
| 43 | } | ||
| 44 | |||
| 45 | bool RealVfsFilesystem::IsReadable() const { | ||
| 46 | return true; | ||
| 47 | } | ||
| 48 | |||
| 49 | bool RealVfsFilesystem::IsWritable() const { | ||
| 50 | return true; | ||
| 51 | } | ||
| 52 | |||
| 53 | VfsEntryType RealVfsFilesystem::GetEntryType(std::string_view path_) const { | ||
| 54 | const auto path = FileUtil::SanitizePath(path_, true); | ||
| 55 | if (!FileUtil::Exists(path)) | ||
| 56 | return VfsEntryType::None; | ||
| 57 | if (FileUtil::IsDirectory(path)) | ||
| 58 | return VfsEntryType::Directory; | ||
| 59 | |||
| 60 | return VfsEntryType::File; | ||
| 61 | } | ||
| 62 | |||
| 63 | VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) { | ||
| 64 | const auto path = FileUtil::SanitizePath(path_, true); | ||
| 65 | if (cache.find(path) != cache.end()) { | ||
| 66 | auto weak = cache[path]; | ||
| 67 | if (!weak.expired()) { | ||
| 68 | return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, weak.lock(), path, perms)); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | if (!FileUtil::Exists(path) && (perms & Mode::WriteAppend) != 0) | ||
| 73 | FileUtil::CreateEmptyFile(path); | ||
| 74 | |||
| 75 | auto backing = std::make_shared<FileUtil::IOFile>(path, ModeFlagsToString(perms).c_str()); | ||
| 76 | cache[path] = backing; | ||
| 77 | |||
| 78 | // Cannot use make_shared as RealVfsFile constructor is private | ||
| 79 | return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, backing, path, perms)); | ||
| 80 | } | ||
| 81 | |||
| 82 | VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, Mode perms) { | ||
| 83 | const auto path = FileUtil::SanitizePath(path_, true); | ||
| 84 | if (!FileUtil::Exists(path) && !FileUtil::CreateEmptyFile(path)) | ||
| 85 | return nullptr; | ||
| 86 | return OpenFile(path, perms); | ||
| 87 | } | ||
| 88 | |||
| 89 | VirtualFile RealVfsFilesystem::CopyFile(std::string_view old_path_, std::string_view new_path_) { | ||
| 90 | const auto old_path = FileUtil::SanitizePath(old_path_, true); | ||
| 91 | const auto new_path = FileUtil::SanitizePath(new_path_, true); | ||
| 92 | |||
| 93 | if (!FileUtil::Exists(old_path) || FileUtil::Exists(new_path) || | ||
| 94 | FileUtil::IsDirectory(old_path) || !FileUtil::Copy(old_path, new_path)) | ||
| 95 | return nullptr; | ||
| 96 | return OpenFile(new_path, Mode::ReadWrite); | ||
| 97 | } | ||
| 98 | |||
| 99 | VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_view new_path_) { | ||
| 100 | const auto old_path = FileUtil::SanitizePath(old_path_, true); | ||
| 101 | const auto new_path = FileUtil::SanitizePath(new_path_, true); | ||
| 102 | |||
| 103 | if (!FileUtil::Exists(old_path) || FileUtil::Exists(new_path) || | ||
| 104 | FileUtil::IsDirectory(old_path) || !FileUtil::Rename(old_path, new_path)) | ||
| 105 | return nullptr; | ||
| 106 | |||
| 107 | if (cache.find(old_path) != cache.end()) { | ||
| 108 | auto cached = cache[old_path]; | ||
| 109 | if (!cached.expired()) { | ||
| 110 | auto file = cached.lock(); | ||
| 111 | file->Open(new_path, "r+b"); | ||
| 112 | cache.erase(old_path); | ||
| 113 | cache[new_path] = file; | ||
| 114 | } | ||
| 115 | } | ||
| 116 | return OpenFile(new_path, Mode::ReadWrite); | ||
| 117 | } | ||
| 118 | |||
| 119 | bool RealVfsFilesystem::DeleteFile(std::string_view path_) { | ||
| 120 | const auto path = FileUtil::SanitizePath(path_, true); | ||
| 121 | if (cache.find(path) != cache.end()) { | ||
| 122 | if (!cache[path].expired()) | ||
| 123 | cache[path].lock()->Close(); | ||
| 124 | cache.erase(path); | ||
| 125 | } | ||
| 126 | return FileUtil::Delete(path); | ||
| 127 | } | ||
| 128 | |||
| 129 | VirtualDir RealVfsFilesystem::OpenDirectory(std::string_view path_, Mode perms) { | ||
| 130 | const auto path = FileUtil::SanitizePath(path_, true); | ||
| 131 | // Cannot use make_shared as RealVfsDirectory constructor is private | ||
| 132 | return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms)); | ||
| 133 | } | ||
| 134 | |||
| 135 | VirtualDir RealVfsFilesystem::CreateDirectory(std::string_view path_, Mode perms) { | ||
| 136 | const auto path = FileUtil::SanitizePath(path_, true); | ||
| 137 | if (!FileUtil::Exists(path) && !FileUtil::CreateDir(path)) | ||
| 138 | return nullptr; | ||
| 139 | // Cannot use make_shared as RealVfsDirectory constructor is private | ||
| 140 | return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms)); | ||
| 141 | } | ||
| 142 | |||
| 143 | VirtualDir RealVfsFilesystem::CopyDirectory(std::string_view old_path_, | ||
| 144 | std::string_view new_path_) { | ||
| 145 | const auto old_path = FileUtil::SanitizePath(old_path_, true); | ||
| 146 | const auto new_path = FileUtil::SanitizePath(new_path_, true); | ||
| 147 | if (!FileUtil::Exists(old_path) || FileUtil::Exists(new_path) || | ||
| 148 | !FileUtil::IsDirectory(old_path)) | ||
| 149 | return nullptr; | ||
| 150 | FileUtil::CopyDir(old_path, new_path); | ||
| 151 | return OpenDirectory(new_path, Mode::ReadWrite); | ||
| 152 | } | ||
| 153 | |||
| 154 | VirtualDir RealVfsFilesystem::MoveDirectory(std::string_view old_path_, | ||
| 155 | std::string_view new_path_) { | ||
| 156 | const auto old_path = FileUtil::SanitizePath(old_path_, true); | ||
| 157 | const auto new_path = FileUtil::SanitizePath(new_path_, true); | ||
| 158 | if (!FileUtil::Exists(old_path) || FileUtil::Exists(new_path) || | ||
| 159 | FileUtil::IsDirectory(old_path) || !FileUtil::Rename(old_path, new_path)) | ||
| 160 | return nullptr; | ||
| 161 | |||
| 162 | for (auto& kv : cache) { | ||
| 163 | // Path in cache starts with old_path | ||
| 164 | if (kv.first.rfind(old_path, 0) == 0) { | ||
| 165 | const auto file_old_path = FileUtil::SanitizePath(kv.first, true); | ||
| 166 | const auto file_new_path = | ||
| 167 | FileUtil::SanitizePath(new_path + DIR_SEP + kv.first.substr(old_path.size()), true); | ||
| 168 | auto cached = cache[file_old_path]; | ||
| 169 | if (!cached.expired()) { | ||
| 170 | auto file = cached.lock(); | ||
| 171 | file->Open(file_new_path, "r+b"); | ||
| 172 | cache.erase(file_old_path); | ||
| 173 | cache[file_new_path] = file; | ||
| 174 | } | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | return OpenDirectory(new_path, Mode::ReadWrite); | ||
| 179 | } | ||
| 180 | |||
| 181 | bool RealVfsFilesystem::DeleteDirectory(std::string_view path_) { | ||
| 182 | const auto path = FileUtil::SanitizePath(path_, true); | ||
| 183 | for (auto& kv : cache) { | ||
| 184 | // Path in cache starts with old_path | ||
| 185 | if (kv.first.rfind(path, 0) == 0) { | ||
| 186 | if (!cache[kv.first].expired()) | ||
| 187 | cache[kv.first].lock()->Close(); | ||
| 188 | cache.erase(kv.first); | ||
| 189 | } | ||
| 190 | } | ||
| 191 | return FileUtil::DeleteDirRecursively(path); | ||
| 192 | } | ||
| 193 | |||
| 194 | RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::shared_ptr<FileUtil::IOFile> backing_, | ||
| 195 | const std::string& path_, Mode perms_) | ||
| 196 | : base(base_), backing(std::move(backing_)), path(path_), | ||
| 41 | parent_path(FileUtil::GetParentPath(path_)), | 197 | parent_path(FileUtil::GetParentPath(path_)), |
| 42 | path_components(FileUtil::SplitPathComponents(path_)), | 198 | path_components(FileUtil::SplitPathComponents(path_)), |
| 43 | parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)), | 199 | parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)), |
| @@ -48,15 +204,15 @@ std::string RealVfsFile::GetName() const { | |||
| 48 | } | 204 | } |
| 49 | 205 | ||
| 50 | size_t RealVfsFile::GetSize() const { | 206 | size_t RealVfsFile::GetSize() const { |
| 51 | return backing.GetSize(); | 207 | return backing->GetSize(); |
| 52 | } | 208 | } |
| 53 | 209 | ||
| 54 | bool RealVfsFile::Resize(size_t new_size) { | 210 | bool RealVfsFile::Resize(size_t new_size) { |
| 55 | return backing.Resize(new_size); | 211 | return backing->Resize(new_size); |
| 56 | } | 212 | } |
| 57 | 213 | ||
| 58 | std::shared_ptr<VfsDirectory> RealVfsFile::GetContainingDirectory() const { | 214 | std::shared_ptr<VfsDirectory> RealVfsFile::GetContainingDirectory() const { |
| 59 | return std::make_shared<RealVfsDirectory>(parent_path, perms); | 215 | return base.OpenDirectory(parent_path, perms); |
| 60 | } | 216 | } |
| 61 | 217 | ||
| 62 | bool RealVfsFile::IsWritable() const { | 218 | bool RealVfsFile::IsWritable() const { |
| @@ -68,62 +224,118 @@ bool RealVfsFile::IsReadable() const { | |||
| 68 | } | 224 | } |
| 69 | 225 | ||
| 70 | size_t RealVfsFile::Read(u8* data, size_t length, size_t offset) const { | 226 | size_t RealVfsFile::Read(u8* data, size_t length, size_t offset) const { |
| 71 | if (!backing.Seek(offset, SEEK_SET)) | 227 | if (!backing->Seek(offset, SEEK_SET)) |
| 72 | return 0; | 228 | return 0; |
| 73 | return backing.ReadBytes(data, length); | 229 | return backing->ReadBytes(data, length); |
| 74 | } | 230 | } |
| 75 | 231 | ||
| 76 | size_t RealVfsFile::Write(const u8* data, size_t length, size_t offset) { | 232 | size_t RealVfsFile::Write(const u8* data, size_t length, size_t offset) { |
| 77 | if (!backing.Seek(offset, SEEK_SET)) | 233 | if (!backing->Seek(offset, SEEK_SET)) |
| 78 | return 0; | 234 | return 0; |
| 79 | return backing.WriteBytes(data, length); | 235 | return backing->WriteBytes(data, length); |
| 80 | } | 236 | } |
| 81 | 237 | ||
| 82 | bool RealVfsFile::Rename(std::string_view name) { | 238 | bool RealVfsFile::Rename(std::string_view name) { |
| 83 | std::string name_str(name.begin(), name.end()); | 239 | return base.MoveFile(path, parent_path + DIR_SEP + std::string(name)) != nullptr; |
| 84 | const auto out = FileUtil::Rename(GetName(), name_str); | 240 | } |
| 85 | 241 | ||
| 86 | path = (parent_path + DIR_SEP).append(name); | 242 | bool RealVfsFile::Close() { |
| 87 | path_components = parent_components; | 243 | return backing->Close(); |
| 88 | path_components.push_back(std::move(name_str)); | 244 | } |
| 89 | backing = FileUtil::IOFile(path, ModeFlagsToString(perms).c_str()); | 245 | |
| 246 | // TODO(DarkLordZach): MSVC would not let me combine the following two functions using 'if | ||
| 247 | // constexpr' because there is a compile error in the branch not used. | ||
| 248 | |||
| 249 | template <> | ||
| 250 | std::vector<VirtualFile> RealVfsDirectory::IterateEntries<RealVfsFile, VfsFile>() const { | ||
| 251 | if (perms == Mode::Append) | ||
| 252 | return {}; | ||
| 253 | |||
| 254 | std::vector<VirtualFile> out; | ||
| 255 | FileUtil::ForeachDirectoryEntry( | ||
| 256 | nullptr, path, | ||
| 257 | [&out, this](u64* entries_out, const std::string& directory, const std::string& filename) { | ||
| 258 | const std::string full_path = directory + DIR_SEP + filename; | ||
| 259 | if (!FileUtil::IsDirectory(full_path)) | ||
| 260 | out.emplace_back(base.OpenFile(full_path, perms)); | ||
| 261 | return true; | ||
| 262 | }); | ||
| 90 | 263 | ||
| 91 | return out; | 264 | return out; |
| 92 | } | 265 | } |
| 93 | 266 | ||
| 94 | bool RealVfsFile::Close() { | 267 | template <> |
| 95 | return backing.Close(); | 268 | std::vector<VirtualDir> RealVfsDirectory::IterateEntries<RealVfsDirectory, VfsDirectory>() const { |
| 269 | if (perms == Mode::Append) | ||
| 270 | return {}; | ||
| 271 | |||
| 272 | std::vector<VirtualDir> out; | ||
| 273 | FileUtil::ForeachDirectoryEntry( | ||
| 274 | nullptr, path, | ||
| 275 | [&out, this](u64* entries_out, const std::string& directory, const std::string& filename) { | ||
| 276 | const std::string full_path = directory + DIR_SEP + filename; | ||
| 277 | if (FileUtil::IsDirectory(full_path)) | ||
| 278 | out.emplace_back(base.OpenDirectory(full_path, perms)); | ||
| 279 | return true; | ||
| 280 | }); | ||
| 281 | |||
| 282 | return out; | ||
| 96 | } | 283 | } |
| 97 | 284 | ||
| 98 | RealVfsDirectory::RealVfsDirectory(const std::string& path_, Mode perms_) | 285 | RealVfsDirectory::RealVfsDirectory(RealVfsFilesystem& base_, const std::string& path_, Mode perms_) |
| 99 | : path(FileUtil::RemoveTrailingSlash(path_)), parent_path(FileUtil::GetParentPath(path)), | 286 | : base(base_), path(FileUtil::RemoveTrailingSlash(path_)), |
| 287 | parent_path(FileUtil::GetParentPath(path)), | ||
| 100 | path_components(FileUtil::SplitPathComponents(path)), | 288 | path_components(FileUtil::SplitPathComponents(path)), |
| 101 | parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)), | 289 | parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)), |
| 102 | perms(perms_) { | 290 | perms(perms_) { |
| 103 | if (!FileUtil::Exists(path) && perms & Mode::WriteAppend) | 291 | if (!FileUtil::Exists(path) && perms & Mode::WriteAppend) |
| 104 | FileUtil::CreateDir(path); | 292 | FileUtil::CreateDir(path); |
| 293 | } | ||
| 105 | 294 | ||
| 106 | if (perms == Mode::Append) | 295 | std::shared_ptr<VfsFile> RealVfsDirectory::GetFileRelative(std::string_view path) const { |
| 107 | return; | 296 | const auto full_path = FileUtil::SanitizePath(this->path + DIR_SEP + std::string(path)); |
| 297 | if (!FileUtil::Exists(full_path)) | ||
| 298 | return nullptr; | ||
| 299 | return base.OpenFile(full_path, perms); | ||
| 300 | } | ||
| 108 | 301 | ||
| 109 | FileUtil::ForeachDirectoryEntry( | 302 | std::shared_ptr<VfsDirectory> RealVfsDirectory::GetDirectoryRelative(std::string_view path) const { |
| 110 | nullptr, path, | 303 | const auto full_path = FileUtil::SanitizePath(this->path + DIR_SEP + std::string(path)); |
| 111 | [this](u64* entries_out, const std::string& directory, const std::string& filename) { | 304 | if (!FileUtil::Exists(full_path)) |
| 112 | std::string full_path = directory + DIR_SEP + filename; | 305 | return nullptr; |
| 113 | if (FileUtil::IsDirectory(full_path)) | 306 | return base.OpenDirectory(full_path, perms); |
| 114 | subdirectories.emplace_back(std::make_shared<RealVfsDirectory>(full_path, perms)); | 307 | } |
| 115 | else | 308 | |
| 116 | files.emplace_back(std::make_shared<RealVfsFile>(full_path, perms)); | 309 | std::shared_ptr<VfsFile> RealVfsDirectory::GetFile(std::string_view name) const { |
| 117 | return true; | 310 | return GetFileRelative(name); |
| 118 | }); | 311 | } |
| 312 | |||
| 313 | std::shared_ptr<VfsDirectory> RealVfsDirectory::GetSubdirectory(std::string_view name) const { | ||
| 314 | return GetDirectoryRelative(name); | ||
| 315 | } | ||
| 316 | |||
| 317 | std::shared_ptr<VfsFile> RealVfsDirectory::CreateFileRelative(std::string_view path) { | ||
| 318 | const auto full_path = FileUtil::SanitizePath(this->path + DIR_SEP + std::string(path)); | ||
| 319 | return base.CreateFile(full_path, perms); | ||
| 320 | } | ||
| 321 | |||
| 322 | std::shared_ptr<VfsDirectory> RealVfsDirectory::CreateDirectoryRelative(std::string_view path) { | ||
| 323 | const auto full_path = FileUtil::SanitizePath(this->path + DIR_SEP + std::string(path)); | ||
| 324 | auto parent = std::string(FileUtil::GetParentPath(full_path)); | ||
| 325 | return base.CreateDirectory(full_path, perms); | ||
| 326 | } | ||
| 327 | |||
| 328 | bool RealVfsDirectory::DeleteSubdirectoryRecursive(std::string_view name) { | ||
| 329 | auto full_path = FileUtil::SanitizePath(this->path + DIR_SEP + std::string(name)); | ||
| 330 | return base.DeleteDirectory(full_path); | ||
| 119 | } | 331 | } |
| 120 | 332 | ||
| 121 | std::vector<std::shared_ptr<VfsFile>> RealVfsDirectory::GetFiles() const { | 333 | std::vector<std::shared_ptr<VfsFile>> RealVfsDirectory::GetFiles() const { |
| 122 | return files; | 334 | return IterateEntries<RealVfsFile, VfsFile>(); |
| 123 | } | 335 | } |
| 124 | 336 | ||
| 125 | std::vector<std::shared_ptr<VfsDirectory>> RealVfsDirectory::GetSubdirectories() const { | 337 | std::vector<std::shared_ptr<VfsDirectory>> RealVfsDirectory::GetSubdirectories() const { |
| 126 | return subdirectories; | 338 | return IterateEntries<RealVfsDirectory, VfsDirectory>(); |
| 127 | } | 339 | } |
| 128 | 340 | ||
| 129 | bool RealVfsDirectory::IsWritable() const { | 341 | bool RealVfsDirectory::IsWritable() const { |
| @@ -142,57 +354,32 @@ std::shared_ptr<VfsDirectory> RealVfsDirectory::GetParentDirectory() const { | |||
| 142 | if (path_components.size() <= 1) | 354 | if (path_components.size() <= 1) |
| 143 | return nullptr; | 355 | return nullptr; |
| 144 | 356 | ||
| 145 | return std::make_shared<RealVfsDirectory>(parent_path, perms); | 357 | return base.OpenDirectory(parent_path, perms); |
| 146 | } | 358 | } |
| 147 | 359 | ||
| 148 | std::shared_ptr<VfsDirectory> RealVfsDirectory::CreateSubdirectory(std::string_view name) { | 360 | std::shared_ptr<VfsDirectory> RealVfsDirectory::CreateSubdirectory(std::string_view name) { |
| 149 | const std::string subdir_path = (path + DIR_SEP).append(name); | 361 | const std::string subdir_path = (path + DIR_SEP).append(name); |
| 150 | 362 | return base.CreateDirectory(subdir_path, perms); | |
| 151 | if (!FileUtil::CreateDir(subdir_path)) { | ||
| 152 | return nullptr; | ||
| 153 | } | ||
| 154 | |||
| 155 | subdirectories.emplace_back(std::make_shared<RealVfsDirectory>(subdir_path, perms)); | ||
| 156 | return subdirectories.back(); | ||
| 157 | } | 363 | } |
| 158 | 364 | ||
| 159 | std::shared_ptr<VfsFile> RealVfsDirectory::CreateFile(std::string_view name) { | 365 | std::shared_ptr<VfsFile> RealVfsDirectory::CreateFile(std::string_view name) { |
| 160 | const std::string file_path = (path + DIR_SEP).append(name); | 366 | const std::string file_path = (path + DIR_SEP).append(name); |
| 161 | 367 | return base.CreateFile(file_path, perms); | |
| 162 | if (!FileUtil::CreateEmptyFile(file_path)) { | ||
| 163 | return nullptr; | ||
| 164 | } | ||
| 165 | |||
| 166 | files.emplace_back(std::make_shared<RealVfsFile>(file_path, perms)); | ||
| 167 | return files.back(); | ||
| 168 | } | 368 | } |
| 169 | 369 | ||
| 170 | bool RealVfsDirectory::DeleteSubdirectory(std::string_view name) { | 370 | bool RealVfsDirectory::DeleteSubdirectory(std::string_view name) { |
| 171 | const std::string subdir_path = (path + DIR_SEP).append(name); | 371 | const std::string subdir_path = (path + DIR_SEP).append(name); |
| 172 | 372 | return base.DeleteDirectory(subdir_path); | |
| 173 | return FileUtil::DeleteDirRecursively(subdir_path); | ||
| 174 | } | 373 | } |
| 175 | 374 | ||
| 176 | bool RealVfsDirectory::DeleteFile(std::string_view name) { | 375 | bool RealVfsDirectory::DeleteFile(std::string_view name) { |
| 177 | const auto file = GetFile(name); | ||
| 178 | |||
| 179 | if (file == nullptr) { | ||
| 180 | return false; | ||
| 181 | } | ||
| 182 | |||
| 183 | files.erase(std::find(files.begin(), files.end(), file)); | ||
| 184 | |||
| 185 | auto real_file = std::static_pointer_cast<RealVfsFile>(file); | ||
| 186 | real_file->Close(); | ||
| 187 | |||
| 188 | const std::string file_path = (path + DIR_SEP).append(name); | 376 | const std::string file_path = (path + DIR_SEP).append(name); |
| 189 | return FileUtil::Delete(file_path); | 377 | return base.DeleteFile(file_path); |
| 190 | } | 378 | } |
| 191 | 379 | ||
| 192 | bool RealVfsDirectory::Rename(std::string_view name) { | 380 | bool RealVfsDirectory::Rename(std::string_view name) { |
| 193 | const std::string new_name = (parent_path + DIR_SEP).append(name); | 381 | const std::string new_name = (parent_path + DIR_SEP).append(name); |
| 194 | 382 | return base.MoveFile(path, new_name) != nullptr; | |
| 195 | return FileUtil::Rename(path, new_name); | ||
| 196 | } | 383 | } |
| 197 | 384 | ||
| 198 | std::string RealVfsDirectory::GetFullPath() const { | 385 | std::string RealVfsDirectory::GetFullPath() const { |
| @@ -202,16 +389,6 @@ std::string RealVfsDirectory::GetFullPath() const { | |||
| 202 | } | 389 | } |
| 203 | 390 | ||
| 204 | bool RealVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) { | 391 | bool RealVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) { |
| 205 | const auto iter = std::find(files.begin(), files.end(), file); | 392 | return false; |
| 206 | if (iter == files.end()) | ||
| 207 | return false; | ||
| 208 | |||
| 209 | const std::ptrdiff_t offset = std::distance(files.begin(), iter); | ||
| 210 | files[offset] = files.back(); | ||
| 211 | files.pop_back(); | ||
| 212 | |||
| 213 | subdirectories.emplace_back(std::move(dir)); | ||
| 214 | |||
| 215 | return true; | ||
| 216 | } | 393 | } |
| 217 | } // namespace FileSys | 394 | } // namespace FileSys |
diff --git a/src/core/file_sys/vfs_real.h b/src/core/file_sys/vfs_real.h index 243d58576..dbb381a2a 100644 --- a/src/core/file_sys/vfs_real.h +++ b/src/core/file_sys/vfs_real.h | |||
| @@ -6,18 +6,45 @@ | |||
| 6 | 6 | ||
| 7 | #include <string_view> | 7 | #include <string_view> |
| 8 | 8 | ||
| 9 | #include <boost/container/flat_map.hpp> | ||
| 9 | #include "common/file_util.h" | 10 | #include "common/file_util.h" |
| 10 | #include "core/file_sys/mode.h" | 11 | #include "core/file_sys/mode.h" |
| 11 | #include "core/file_sys/vfs.h" | 12 | #include "core/file_sys/vfs.h" |
| 12 | 13 | ||
| 13 | namespace FileSys { | 14 | namespace FileSys { |
| 14 | 15 | ||
| 16 | class RealVfsFilesystem : public VfsFilesystem { | ||
| 17 | public: | ||
| 18 | RealVfsFilesystem(); | ||
| 19 | |||
| 20 | std::string GetName() const override; | ||
| 21 | bool IsReadable() const override; | ||
| 22 | bool IsWritable() const override; | ||
| 23 | VfsEntryType GetEntryType(std::string_view path) const override; | ||
| 24 | VirtualFile OpenFile(std::string_view path, Mode perms = Mode::Read) override; | ||
| 25 | VirtualFile CreateFile(std::string_view path, Mode perms = Mode::ReadWrite) override; | ||
| 26 | VirtualFile CopyFile(std::string_view old_path, std::string_view new_path) override; | ||
| 27 | VirtualFile MoveFile(std::string_view old_path, std::string_view new_path) override; | ||
| 28 | bool DeleteFile(std::string_view path) override; | ||
| 29 | VirtualDir OpenDirectory(std::string_view path, Mode perms = Mode::Read) override; | ||
| 30 | VirtualDir CreateDirectory(std::string_view path, Mode perms = Mode::ReadWrite) override; | ||
| 31 | VirtualDir CopyDirectory(std::string_view old_path, std::string_view new_path) override; | ||
| 32 | VirtualDir MoveDirectory(std::string_view old_path, std::string_view new_path) override; | ||
| 33 | bool DeleteDirectory(std::string_view path) override; | ||
| 34 | |||
| 35 | private: | ||
| 36 | boost::container::flat_map<std::string, std::weak_ptr<FileUtil::IOFile>> cache; | ||
| 37 | }; | ||
| 38 | |||
| 15 | // An implmentation of VfsFile that represents a file on the user's computer. | 39 | // An implmentation of VfsFile that represents a file on the user's computer. |
| 16 | struct RealVfsFile : public VfsFile { | 40 | class RealVfsFile : public VfsFile { |
| 17 | friend struct RealVfsDirectory; | 41 | friend class RealVfsDirectory; |
| 42 | friend class RealVfsFilesystem; | ||
| 18 | 43 | ||
| 19 | RealVfsFile(const std::string& name, Mode perms = Mode::Read); | 44 | RealVfsFile(RealVfsFilesystem& base, std::shared_ptr<FileUtil::IOFile> backing, |
| 45 | const std::string& path, Mode perms = Mode::Read); | ||
| 20 | 46 | ||
| 47 | public: | ||
| 21 | std::string GetName() const override; | 48 | std::string GetName() const override; |
| 22 | size_t GetSize() const override; | 49 | size_t GetSize() const override; |
| 23 | bool Resize(size_t new_size) override; | 50 | bool Resize(size_t new_size) override; |
| @@ -31,7 +58,8 @@ struct RealVfsFile : public VfsFile { | |||
| 31 | private: | 58 | private: |
| 32 | bool Close(); | 59 | bool Close(); |
| 33 | 60 | ||
| 34 | FileUtil::IOFile backing; | 61 | RealVfsFilesystem& base; |
| 62 | std::shared_ptr<FileUtil::IOFile> backing; | ||
| 35 | std::string path; | 63 | std::string path; |
| 36 | std::string parent_path; | 64 | std::string parent_path; |
| 37 | std::vector<std::string> path_components; | 65 | std::vector<std::string> path_components; |
| @@ -40,9 +68,12 @@ private: | |||
| 40 | }; | 68 | }; |
| 41 | 69 | ||
| 42 | // An implementation of VfsDirectory that represents a directory on the user's computer. | 70 | // An implementation of VfsDirectory that represents a directory on the user's computer. |
| 43 | struct RealVfsDirectory : public VfsDirectory { | 71 | class RealVfsDirectory : public VfsDirectory { |
| 44 | RealVfsDirectory(const std::string& path, Mode perms = Mode::Read); | 72 | friend class RealVfsFilesystem; |
| 73 | |||
| 74 | RealVfsDirectory(RealVfsFilesystem& base, const std::string& path, Mode perms = Mode::Read); | ||
| 45 | 75 | ||
| 76 | public: | ||
| 46 | std::vector<std::shared_ptr<VfsFile>> GetFiles() const override; | 77 | std::vector<std::shared_ptr<VfsFile>> GetFiles() const override; |
| 47 | std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const override; | 78 | std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const override; |
| 48 | bool IsWritable() const override; | 79 | bool IsWritable() const override; |
| @@ -60,6 +91,7 @@ protected: | |||
| 60 | bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override; | 91 | bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override; |
| 61 | 92 | ||
| 62 | private: | 93 | private: |
| 94 | RealVfsFilesystem& base; | ||
| 63 | std::string path; | 95 | std::string path; |
| 64 | std::string parent_path; | 96 | std::string parent_path; |
| 65 | std::vector<std::string> path_components; | 97 | std::vector<std::string> path_components; |