file_util, vfs: Use std::string_view where applicable
Avoids unnecessary construction of std::string instances where applicable.
This commit is contained in:
parent
ef163c1a15
commit
398444e676
|
@ -802,66 +802,80 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> SplitPathComponents(const std::string& filename) {
|
std::vector<std::string> SplitPathComponents(std::string_view filename) {
|
||||||
auto copy(filename);
|
std::string copy(filename);
|
||||||
std::replace(copy.begin(), copy.end(), '\\', '/');
|
std::replace(copy.begin(), copy.end(), '\\', '/');
|
||||||
std::vector<std::string> out;
|
std::vector<std::string> out;
|
||||||
|
|
||||||
std::stringstream stream(filename);
|
std::stringstream stream(copy);
|
||||||
std::string item;
|
std::string item;
|
||||||
while (std::getline(stream, item, '/'))
|
while (std::getline(stream, item, '/')) {
|
||||||
out.push_back(std::move(item));
|
out.push_back(std::move(item));
|
||||||
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetParentPath(const std::string& path) {
|
std::string_view GetParentPath(std::string_view path) {
|
||||||
auto out = path;
|
const auto name_bck_index = path.rfind('\\');
|
||||||
const auto name_bck_index = out.find_last_of('\\');
|
const auto name_fwd_index = path.rfind('/');
|
||||||
const auto name_fwd_index = out.find_last_of('/');
|
|
||||||
size_t name_index;
|
size_t name_index;
|
||||||
if (name_bck_index == std::string::npos || name_fwd_index == std::string::npos)
|
|
||||||
name_index = std::min<size_t>(name_bck_index, name_fwd_index);
|
|
||||||
else
|
|
||||||
name_index = std::max<size_t>(name_bck_index, name_fwd_index);
|
|
||||||
|
|
||||||
return out.erase(name_index);
|
if (name_bck_index == std::string_view::npos || name_fwd_index == std::string_view::npos) {
|
||||||
|
name_index = std::min(name_bck_index, name_fwd_index);
|
||||||
|
} else {
|
||||||
|
name_index = std::max(name_bck_index, name_fwd_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return path.substr(0, name_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetPathWithoutTop(std::string path) {
|
std::string_view GetPathWithoutTop(std::string_view path) {
|
||||||
if (path.empty())
|
if (path.empty()) {
|
||||||
return "";
|
return path;
|
||||||
while (path[0] == '\\' || path[0] == '/') {
|
|
||||||
path = path.substr(1);
|
|
||||||
if (path.empty())
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
const auto name_bck_index = path.find_first_of('\\');
|
|
||||||
const auto name_fwd_index = path.find_first_of('/');
|
while (path[0] == '\\' || path[0] == '/') {
|
||||||
|
path.remove_suffix(1);
|
||||||
|
if (path.empty()) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto name_bck_index = path.find('\\');
|
||||||
|
const auto name_fwd_index = path.find('/');
|
||||||
return path.substr(std::min(name_bck_index, name_fwd_index) + 1);
|
return path.substr(std::min(name_bck_index, name_fwd_index) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetFilename(std::string path) {
|
std::string_view GetFilename(std::string_view path) {
|
||||||
std::replace(path.begin(), path.end(), '\\', '/');
|
const auto name_index = path.find_last_of("\\/");
|
||||||
auto name_index = path.find_last_of('/');
|
|
||||||
if (name_index == std::string::npos)
|
if (name_index == std::string_view::npos) {
|
||||||
return "";
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
return path.substr(name_index + 1);
|
return path.substr(name_index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetExtensionFromFilename(const std::string& name) {
|
std::string_view GetExtensionFromFilename(std::string_view name) {
|
||||||
size_t index = name.find_last_of('.');
|
const size_t index = name.rfind('.');
|
||||||
if (index == std::string::npos)
|
|
||||||
return "";
|
if (index == std::string_view::npos) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
return name.substr(index + 1);
|
return name.substr(index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string RemoveTrailingSlash(const std::string& path) {
|
std::string_view RemoveTrailingSlash(std::string_view path) {
|
||||||
if (path.empty())
|
if (path.empty()) {
|
||||||
return path;
|
return path;
|
||||||
if (path.back() == '\\' || path.back() == '/')
|
}
|
||||||
return path.substr(0, path.size() - 1);
|
|
||||||
|
if (path.back() == '\\' || path.back() == '/') {
|
||||||
|
path.remove_suffix(1);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
@ -151,22 +152,22 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam
|
||||||
|
|
||||||
// Splits the path on '/' or '\' and put the components into a vector
|
// Splits the path on '/' or '\' and put the components into a vector
|
||||||
// i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" }
|
// i.e. "C:\Users\Yuzu\Documents\save.bin" becomes {"C:", "Users", "Yuzu", "Documents", "save.bin" }
|
||||||
std::vector<std::string> SplitPathComponents(const std::string& filename);
|
std::vector<std::string> SplitPathComponents(std::string_view filename);
|
||||||
|
|
||||||
// Gets all of the text up to the last '/' or '\' in the path.
|
// Gets all of the text up to the last '/' or '\' in the path.
|
||||||
std::string GetParentPath(const std::string& path);
|
std::string_view GetParentPath(std::string_view path);
|
||||||
|
|
||||||
// Gets all of the text after the first '/' or '\' in the path.
|
// Gets all of the text after the first '/' or '\' in the path.
|
||||||
std::string GetPathWithoutTop(std::string path);
|
std::string_view GetPathWithoutTop(std::string_view path);
|
||||||
|
|
||||||
// Gets the filename of the path
|
// Gets the filename of the path
|
||||||
std::string GetFilename(std::string path);
|
std::string_view GetFilename(std::string_view path);
|
||||||
|
|
||||||
// Gets the extension of the filename
|
// Gets the extension of the filename
|
||||||
std::string GetExtensionFromFilename(const std::string& name);
|
std::string_view GetExtensionFromFilename(std::string_view name);
|
||||||
|
|
||||||
// Removes the final '/' or '\' if one exists
|
// Removes the final '/' or '\' if one exists
|
||||||
std::string RemoveTrailingSlash(const std::string& path);
|
std::string_view RemoveTrailingSlash(std::string_view path);
|
||||||
|
|
||||||
// Creates a new vector containing indices [first, last) from the original.
|
// Creates a new vector containing indices [first, last) from the original.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace FileSys {
|
||||||
VfsFile::~VfsFile() = default;
|
VfsFile::~VfsFile() = default;
|
||||||
|
|
||||||
std::string VfsFile::GetExtension() const {
|
std::string VfsFile::GetExtension() const {
|
||||||
return FileUtil::GetExtensionFromFilename(GetName());
|
return std::string(FileUtil::GetExtensionFromFilename(GetName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
VfsDirectory::~VfsDirectory() = default;
|
VfsDirectory::~VfsDirectory() = default;
|
||||||
|
@ -46,64 +46,80 @@ size_t VfsFile::WriteBytes(const std::vector<u8>& data, size_t offset) {
|
||||||
return Write(data.data(), data.size(), offset);
|
return Write(data.data(), data.size(), offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<VfsFile> VfsDirectory::GetFileRelative(const std::string& path) const {
|
std::shared_ptr<VfsFile> VfsDirectory::GetFileRelative(std::string_view path) const {
|
||||||
auto vec = FileUtil::SplitPathComponents(path);
|
auto vec = FileUtil::SplitPathComponents(path);
|
||||||
vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
|
vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
|
||||||
vec.end());
|
vec.end());
|
||||||
if (vec.empty())
|
if (vec.empty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (vec.size() == 1)
|
}
|
||||||
|
|
||||||
|
if (vec.size() == 1) {
|
||||||
return GetFile(vec[0]);
|
return GetFile(vec[0]);
|
||||||
|
}
|
||||||
|
|
||||||
auto dir = GetSubdirectory(vec[0]);
|
auto dir = GetSubdirectory(vec[0]);
|
||||||
for (size_t component = 1; component < vec.size() - 1; ++component) {
|
for (size_t component = 1; component < vec.size() - 1; ++component) {
|
||||||
if (dir == nullptr)
|
if (dir == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
dir = dir->GetSubdirectory(vec[component]);
|
dir = dir->GetSubdirectory(vec[component]);
|
||||||
}
|
}
|
||||||
if (dir == nullptr)
|
|
||||||
|
if (dir == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
return dir->GetFile(vec.back());
|
return dir->GetFile(vec.back());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<VfsFile> VfsDirectory::GetFileAbsolute(const std::string& path) const {
|
std::shared_ptr<VfsFile> VfsDirectory::GetFileAbsolute(std::string_view path) const {
|
||||||
if (IsRoot())
|
if (IsRoot()) {
|
||||||
return GetFileRelative(path);
|
return GetFileRelative(path);
|
||||||
|
}
|
||||||
|
|
||||||
return GetParentDirectory()->GetFileAbsolute(path);
|
return GetParentDirectory()->GetFileAbsolute(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<VfsDirectory> VfsDirectory::GetDirectoryRelative(const std::string& path) const {
|
std::shared_ptr<VfsDirectory> VfsDirectory::GetDirectoryRelative(std::string_view path) const {
|
||||||
auto vec = FileUtil::SplitPathComponents(path);
|
auto vec = FileUtil::SplitPathComponents(path);
|
||||||
vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
|
vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
|
||||||
vec.end());
|
vec.end());
|
||||||
if (vec.empty())
|
if (vec.empty()) {
|
||||||
// TODO(DarkLordZach): Return this directory if path is '/' or similar. Can't currently
|
// TODO(DarkLordZach): Return this directory if path is '/' or similar. Can't currently
|
||||||
// because of const-ness
|
// because of const-ness
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
auto dir = GetSubdirectory(vec[0]);
|
auto dir = GetSubdirectory(vec[0]);
|
||||||
for (size_t component = 1; component < vec.size(); ++component) {
|
for (size_t component = 1; component < vec.size(); ++component) {
|
||||||
if (dir == nullptr)
|
if (dir == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
dir = dir->GetSubdirectory(vec[component]);
|
dir = dir->GetSubdirectory(vec[component]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<VfsDirectory> VfsDirectory::GetDirectoryAbsolute(const std::string& path) const {
|
std::shared_ptr<VfsDirectory> VfsDirectory::GetDirectoryAbsolute(std::string_view path) const {
|
||||||
if (IsRoot())
|
if (IsRoot()) {
|
||||||
return GetDirectoryRelative(path);
|
return GetDirectoryRelative(path);
|
||||||
|
}
|
||||||
|
|
||||||
return GetParentDirectory()->GetDirectoryAbsolute(path);
|
return GetParentDirectory()->GetDirectoryAbsolute(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<VfsFile> VfsDirectory::GetFile(const std::string& name) const {
|
std::shared_ptr<VfsFile> VfsDirectory::GetFile(std::string_view name) const {
|
||||||
const auto& files = GetFiles();
|
const auto& files = GetFiles();
|
||||||
const auto iter = std::find_if(files.begin(), files.end(),
|
const auto iter = std::find_if(files.begin(), files.end(),
|
||||||
[&name](const auto& file1) { return name == file1->GetName(); });
|
[&name](const auto& file1) { return name == file1->GetName(); });
|
||||||
return iter == files.end() ? nullptr : *iter;
|
return iter == files.end() ? nullptr : *iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<VfsDirectory> VfsDirectory::GetSubdirectory(const std::string& name) const {
|
std::shared_ptr<VfsDirectory> VfsDirectory::GetSubdirectory(std::string_view name) const {
|
||||||
const auto& subs = GetSubdirectories();
|
const auto& subs = GetSubdirectories();
|
||||||
const auto iter = std::find_if(subs.begin(), subs.end(),
|
const auto iter = std::find_if(subs.begin(), subs.end(),
|
||||||
[&name](const auto& file1) { return name == file1->GetName(); });
|
[&name](const auto& file1) { return name == file1->GetName(); });
|
||||||
|
@ -128,77 +144,96 @@ size_t VfsDirectory::GetSize() const {
|
||||||
return file_total + subdir_total;
|
return file_total + subdir_total;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<VfsFile> VfsDirectory::CreateFileRelative(const std::string& path) {
|
std::shared_ptr<VfsFile> VfsDirectory::CreateFileRelative(std::string_view path) {
|
||||||
auto vec = FileUtil::SplitPathComponents(path);
|
auto vec = FileUtil::SplitPathComponents(path);
|
||||||
vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
|
vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
|
||||||
vec.end());
|
vec.end());
|
||||||
if (vec.empty())
|
if (vec.empty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (vec.size() == 1)
|
}
|
||||||
|
|
||||||
|
if (vec.size() == 1) {
|
||||||
return CreateFile(vec[0]);
|
return CreateFile(vec[0]);
|
||||||
|
}
|
||||||
|
|
||||||
auto dir = GetSubdirectory(vec[0]);
|
auto dir = GetSubdirectory(vec[0]);
|
||||||
if (dir == nullptr) {
|
if (dir == nullptr) {
|
||||||
dir = CreateSubdirectory(vec[0]);
|
dir = CreateSubdirectory(vec[0]);
|
||||||
if (dir == nullptr)
|
if (dir == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dir->CreateFileRelative(FileUtil::GetPathWithoutTop(path));
|
return dir->CreateFileRelative(FileUtil::GetPathWithoutTop(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<VfsFile> VfsDirectory::CreateFileAbsolute(const std::string& path) {
|
std::shared_ptr<VfsFile> VfsDirectory::CreateFileAbsolute(std::string_view path) {
|
||||||
if (IsRoot())
|
if (IsRoot()) {
|
||||||
return CreateFileRelative(path);
|
return CreateFileRelative(path);
|
||||||
|
}
|
||||||
|
|
||||||
return GetParentDirectory()->CreateFileAbsolute(path);
|
return GetParentDirectory()->CreateFileAbsolute(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<VfsDirectory> VfsDirectory::CreateDirectoryRelative(const std::string& path) {
|
std::shared_ptr<VfsDirectory> VfsDirectory::CreateDirectoryRelative(std::string_view path) {
|
||||||
auto vec = FileUtil::SplitPathComponents(path);
|
auto vec = FileUtil::SplitPathComponents(path);
|
||||||
vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
|
vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
|
||||||
vec.end());
|
vec.end());
|
||||||
if (vec.empty())
|
if (vec.empty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (vec.size() == 1)
|
}
|
||||||
|
|
||||||
|
if (vec.size() == 1) {
|
||||||
return CreateSubdirectory(vec[0]);
|
return CreateSubdirectory(vec[0]);
|
||||||
|
}
|
||||||
|
|
||||||
auto dir = GetSubdirectory(vec[0]);
|
auto dir = GetSubdirectory(vec[0]);
|
||||||
if (dir == nullptr) {
|
if (dir == nullptr) {
|
||||||
dir = CreateSubdirectory(vec[0]);
|
dir = CreateSubdirectory(vec[0]);
|
||||||
if (dir == nullptr)
|
if (dir == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dir->CreateDirectoryRelative(FileUtil::GetPathWithoutTop(path));
|
return dir->CreateDirectoryRelative(FileUtil::GetPathWithoutTop(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<VfsDirectory> VfsDirectory::CreateDirectoryAbsolute(const std::string& path) {
|
std::shared_ptr<VfsDirectory> VfsDirectory::CreateDirectoryAbsolute(std::string_view path) {
|
||||||
if (IsRoot())
|
if (IsRoot()) {
|
||||||
return CreateDirectoryRelative(path);
|
return CreateDirectoryRelative(path);
|
||||||
|
}
|
||||||
|
|
||||||
return GetParentDirectory()->CreateDirectoryAbsolute(path);
|
return GetParentDirectory()->CreateDirectoryAbsolute(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VfsDirectory::DeleteSubdirectoryRecursive(const std::string& name) {
|
bool VfsDirectory::DeleteSubdirectoryRecursive(std::string_view name) {
|
||||||
auto dir = GetSubdirectory(name);
|
auto dir = GetSubdirectory(name);
|
||||||
if (dir == nullptr)
|
if (dir == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
for (const auto& file : dir->GetFiles()) {
|
for (const auto& file : dir->GetFiles()) {
|
||||||
if (!DeleteFile(file->GetName()))
|
if (!DeleteFile(file->GetName())) {
|
||||||
success = false;
|
success = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& sdir : dir->GetSubdirectories()) {
|
for (const auto& sdir : dir->GetSubdirectories()) {
|
||||||
if (!dir->DeleteSubdirectoryRecursive(sdir->GetName()))
|
if (!dir->DeleteSubdirectoryRecursive(sdir->GetName())) {
|
||||||
success = false;
|
success = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VfsDirectory::Copy(const std::string& src, const std::string& dest) {
|
bool VfsDirectory::Copy(std::string_view src, std::string_view dest) {
|
||||||
const auto f1 = GetFile(src);
|
const auto f1 = GetFile(src);
|
||||||
auto f2 = CreateFile(dest);
|
auto f2 = CreateFile(dest);
|
||||||
if (f1 == nullptr || f2 == nullptr)
|
if (f1 == nullptr || f2 == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!f2->Resize(f1->GetSize())) {
|
if (!f2->Resize(f1->GetSize())) {
|
||||||
DeleteFile(dest);
|
DeleteFile(dest);
|
||||||
|
@ -216,23 +251,23 @@ bool ReadOnlyVfsDirectory::IsReadable() const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectory::CreateSubdirectory(const std::string& name) {
|
std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectory::CreateSubdirectory(std::string_view name) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<VfsFile> ReadOnlyVfsDirectory::CreateFile(const std::string& name) {
|
std::shared_ptr<VfsFile> ReadOnlyVfsDirectory::CreateFile(std::string_view name) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReadOnlyVfsDirectory::DeleteSubdirectory(const std::string& name) {
|
bool ReadOnlyVfsDirectory::DeleteSubdirectory(std::string_view name) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReadOnlyVfsDirectory::DeleteFile(const std::string& name) {
|
bool ReadOnlyVfsDirectory::DeleteFile(std::string_view name) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReadOnlyVfsDirectory::Rename(const std::string& name) {
|
bool ReadOnlyVfsDirectory::Rename(std::string_view name) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} // namespace FileSys
|
} // namespace FileSys
|
||||||
|
|
|
@ -6,11 +6,11 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "boost/optional.hpp"
|
#include "boost/optional.hpp"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/file_util.h"
|
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
struct VfsFile;
|
struct VfsFile;
|
||||||
|
@ -112,7 +112,7 @@ struct VfsFile : NonCopyable {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renames the file to name. Returns whether or not the operation was successsful.
|
// Renames the file to name. Returns whether or not the operation was successsful.
|
||||||
virtual bool Rename(const std::string& name) = 0;
|
virtual bool Rename(std::string_view name) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A class representing a directory in an abstract filesystem.
|
// A class representing a directory in an abstract filesystem.
|
||||||
|
@ -121,27 +121,27 @@ struct VfsDirectory : NonCopyable {
|
||||||
|
|
||||||
// Retrives the file located at path as if the current directory was root. Returns nullptr if
|
// Retrives the file located at path as if the current directory was root. Returns nullptr if
|
||||||
// not found.
|
// not found.
|
||||||
virtual std::shared_ptr<VfsFile> GetFileRelative(const std::string& path) const;
|
virtual std::shared_ptr<VfsFile> GetFileRelative(std::string_view path) const;
|
||||||
// Calls GetFileRelative(path) on the root of the current directory.
|
// Calls GetFileRelative(path) on the root of the current directory.
|
||||||
virtual std::shared_ptr<VfsFile> GetFileAbsolute(const std::string& path) const;
|
virtual std::shared_ptr<VfsFile> GetFileAbsolute(std::string_view path) const;
|
||||||
|
|
||||||
// Retrives the directory located at path as if the current directory was root. Returns nullptr
|
// Retrives the directory located at path as if the current directory was root. Returns nullptr
|
||||||
// if not found.
|
// if not found.
|
||||||
virtual std::shared_ptr<VfsDirectory> GetDirectoryRelative(const std::string& path) const;
|
virtual std::shared_ptr<VfsDirectory> GetDirectoryRelative(std::string_view path) const;
|
||||||
// Calls GetDirectoryRelative(path) on the root of the current directory.
|
// Calls GetDirectoryRelative(path) on the root of the current directory.
|
||||||
virtual std::shared_ptr<VfsDirectory> GetDirectoryAbsolute(const std::string& path) const;
|
virtual std::shared_ptr<VfsDirectory> GetDirectoryAbsolute(std::string_view path) const;
|
||||||
|
|
||||||
// Returns a vector containing all of the files in this directory.
|
// Returns a vector containing all of the files in this directory.
|
||||||
virtual std::vector<std::shared_ptr<VfsFile>> GetFiles() const = 0;
|
virtual std::vector<std::shared_ptr<VfsFile>> GetFiles() const = 0;
|
||||||
// Returns the file with filename matching name. Returns nullptr if directory dosen't have a
|
// Returns the file with filename matching name. Returns nullptr if directory dosen't have a
|
||||||
// file with name.
|
// file with name.
|
||||||
virtual std::shared_ptr<VfsFile> GetFile(const std::string& name) const;
|
virtual std::shared_ptr<VfsFile> GetFile(std::string_view name) const;
|
||||||
|
|
||||||
// Returns a vector containing all of the subdirectories in this directory.
|
// Returns a vector containing all of the subdirectories in this directory.
|
||||||
virtual std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const = 0;
|
virtual std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const = 0;
|
||||||
// Returns the directory with name matching name. Returns nullptr if directory dosen't have a
|
// Returns the directory with name matching name. Returns nullptr if directory dosen't have a
|
||||||
// directory with name.
|
// directory with name.
|
||||||
virtual std::shared_ptr<VfsDirectory> GetSubdirectory(const std::string& name) const;
|
virtual std::shared_ptr<VfsDirectory> GetSubdirectory(std::string_view name) const;
|
||||||
|
|
||||||
// Returns whether or not the directory can be written to.
|
// Returns whether or not the directory can be written to.
|
||||||
virtual bool IsWritable() const = 0;
|
virtual bool IsWritable() const = 0;
|
||||||
|
@ -161,49 +161,49 @@ struct VfsDirectory : NonCopyable {
|
||||||
|
|
||||||
// Creates a new subdirectory with name name. Returns a pointer to the new directory or nullptr
|
// Creates a new subdirectory with name name. Returns a pointer to the new directory or nullptr
|
||||||
// if the operation failed.
|
// if the operation failed.
|
||||||
virtual std::shared_ptr<VfsDirectory> CreateSubdirectory(const std::string& name) = 0;
|
virtual std::shared_ptr<VfsDirectory> CreateSubdirectory(std::string_view name) = 0;
|
||||||
// Creates a new file with name name. Returns a pointer to the new file or nullptr if the
|
// Creates a new file with name name. Returns a pointer to the new file or nullptr if the
|
||||||
// operation failed.
|
// operation failed.
|
||||||
virtual std::shared_ptr<VfsFile> CreateFile(const std::string& name) = 0;
|
virtual std::shared_ptr<VfsFile> CreateFile(std::string_view name) = 0;
|
||||||
|
|
||||||
// Creates a new file at the path relative to this directory. Also creates directories if
|
// Creates a new file at the path relative to this directory. Also creates directories if
|
||||||
// they do not exist and is supported by this implementation. Returns nullptr on any failure.
|
// they do not exist and is supported by this implementation. Returns nullptr on any failure.
|
||||||
virtual std::shared_ptr<VfsFile> CreateFileRelative(const std::string& path);
|
virtual std::shared_ptr<VfsFile> CreateFileRelative(std::string_view path);
|
||||||
|
|
||||||
// Creates a new file at the path relative to root of this directory. Also creates directories
|
// Creates a new file at the path relative to root of this directory. Also creates directories
|
||||||
// if they do not exist and is supported by this implementation. Returns nullptr on any failure.
|
// if they do not exist and is supported by this implementation. Returns nullptr on any failure.
|
||||||
virtual std::shared_ptr<VfsFile> CreateFileAbsolute(const std::string& path);
|
virtual std::shared_ptr<VfsFile> CreateFileAbsolute(std::string_view path);
|
||||||
|
|
||||||
// Creates a new directory at the path relative to this directory. Also creates directories if
|
// Creates a new directory at the path relative to this directory. Also creates directories if
|
||||||
// they do not exist and is supported by this implementation. Returns nullptr on any failure.
|
// they do not exist and is supported by this implementation. Returns nullptr on any failure.
|
||||||
virtual std::shared_ptr<VfsDirectory> CreateDirectoryRelative(const std::string& path);
|
virtual std::shared_ptr<VfsDirectory> CreateDirectoryRelative(std::string_view path);
|
||||||
|
|
||||||
// Creates a new directory at the path relative to root of this directory. Also creates
|
// Creates a new directory at the path relative to root of this directory. Also creates
|
||||||
// directories if they do not exist and is supported by this implementation. Returns nullptr on
|
// directories if they do not exist and is supported by this implementation. Returns nullptr on
|
||||||
// any failure.
|
// any failure.
|
||||||
virtual std::shared_ptr<VfsDirectory> CreateDirectoryAbsolute(const std::string& path);
|
virtual std::shared_ptr<VfsDirectory> CreateDirectoryAbsolute(std::string_view path);
|
||||||
|
|
||||||
// Deletes the subdirectory with name and returns true on success.
|
// Deletes the subdirectory with name and returns true on success.
|
||||||
virtual bool DeleteSubdirectory(const std::string& name) = 0;
|
virtual bool DeleteSubdirectory(std::string_view name) = 0;
|
||||||
// Deletes all subdirectories and files of subdirectory with name recirsively and then deletes
|
// Deletes all subdirectories and files of subdirectory with name recirsively and then deletes
|
||||||
// the subdirectory. Returns true on success.
|
// the subdirectory. Returns true on success.
|
||||||
virtual bool DeleteSubdirectoryRecursive(const std::string& name);
|
virtual bool DeleteSubdirectoryRecursive(std::string_view name);
|
||||||
// Returnes whether or not the file with name name was deleted successfully.
|
// Returnes whether or not the file with name name was deleted successfully.
|
||||||
virtual bool DeleteFile(const std::string& name) = 0;
|
virtual bool DeleteFile(std::string_view name) = 0;
|
||||||
|
|
||||||
// Returns whether or not this directory was renamed to name.
|
// Returns whether or not this directory was renamed to name.
|
||||||
virtual bool Rename(const std::string& name) = 0;
|
virtual bool Rename(std::string_view name) = 0;
|
||||||
|
|
||||||
// Returns whether or not the file with name src was successfully copied to a new file with name
|
// Returns whether or not the file with name src was successfully copied to a new file with name
|
||||||
// dest.
|
// dest.
|
||||||
virtual bool Copy(const std::string& src, const std::string& dest);
|
virtual bool Copy(std::string_view src, std::string_view dest);
|
||||||
|
|
||||||
// Interprets the file with name file instead as a directory of type directory.
|
// Interprets the file with name file instead as a directory of type directory.
|
||||||
// The directory must have a constructor that takes a single argument of type
|
// The directory must have a constructor that takes a single argument of type
|
||||||
// std::shared_ptr<VfsFile>. Allows to reinterpret container files (i.e NCA, zip, XCI, etc) as a
|
// std::shared_ptr<VfsFile>. Allows to reinterpret container files (i.e NCA, zip, XCI, etc) as a
|
||||||
// subdirectory in one call.
|
// subdirectory in one call.
|
||||||
template <typename Directory>
|
template <typename Directory>
|
||||||
bool InterpretAsDirectory(const std::string& file) {
|
bool InterpretAsDirectory(std::string_view file) {
|
||||||
auto file_p = GetFile(file);
|
auto file_p = GetFile(file);
|
||||||
if (file_p == nullptr)
|
if (file_p == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
@ -221,10 +221,10 @@ protected:
|
||||||
struct ReadOnlyVfsDirectory : public VfsDirectory {
|
struct ReadOnlyVfsDirectory : public VfsDirectory {
|
||||||
bool IsWritable() const override;
|
bool IsWritable() const override;
|
||||||
bool IsReadable() const override;
|
bool IsReadable() const override;
|
||||||
std::shared_ptr<VfsDirectory> CreateSubdirectory(const std::string& name) override;
|
std::shared_ptr<VfsDirectory> CreateSubdirectory(std::string_view name) override;
|
||||||
std::shared_ptr<VfsFile> CreateFile(const std::string& name) override;
|
std::shared_ptr<VfsFile> CreateFile(std::string_view name) override;
|
||||||
bool DeleteSubdirectory(const std::string& name) override;
|
bool DeleteSubdirectory(std::string_view name) override;
|
||||||
bool DeleteFile(const std::string& name) override;
|
bool DeleteFile(std::string_view name) override;
|
||||||
bool Rename(const std::string& name) override;
|
bool Rename(std::string_view name) override;
|
||||||
};
|
};
|
||||||
} // namespace FileSys
|
} // namespace FileSys
|
||||||
|
|
|
@ -80,7 +80,7 @@ size_t OffsetVfsFile::WriteBytes(const std::vector<u8>& data, size_t r_offset) {
|
||||||
return file->Write(data.data(), TrimToFit(data.size(), r_offset), offset + r_offset);
|
return file->Write(data.data(), TrimToFit(data.size(), r_offset), offset + r_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OffsetVfsFile::Rename(const std::string& name) {
|
bool OffsetVfsFile::Rename(std::string_view name) {
|
||||||
return file->Rename(name);
|
return file->Rename(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
#include "core/file_sys/vfs.h"
|
#include "core/file_sys/vfs.h"
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
|
@ -30,7 +33,7 @@ struct OffsetVfsFile : public VfsFile {
|
||||||
bool WriteByte(u8 data, size_t offset) override;
|
bool WriteByte(u8 data, size_t offset) override;
|
||||||
size_t WriteBytes(const std::vector<u8>& data, size_t offset) override;
|
size_t WriteBytes(const std::vector<u8>& data, size_t offset) override;
|
||||||
|
|
||||||
bool Rename(const std::string& name) override;
|
bool Rename(std::string_view name) override;
|
||||||
|
|
||||||
size_t GetOffset() const;
|
size_t GetOffset() const;
|
||||||
|
|
||||||
|
|
|
@ -72,12 +72,15 @@ size_t RealVfsFile::Write(const u8* data, size_t length, size_t offset) {
|
||||||
return backing.WriteBytes(data, length);
|
return backing.WriteBytes(data, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RealVfsFile::Rename(const std::string& name) {
|
bool RealVfsFile::Rename(std::string_view name) {
|
||||||
const auto out = FileUtil::Rename(GetName(), name);
|
std::string name_str(name.begin(), name.end());
|
||||||
path = parent_path + DIR_SEP + name;
|
const auto out = FileUtil::Rename(GetName(), name_str);
|
||||||
|
|
||||||
|
path = (parent_path + DIR_SEP).append(name);
|
||||||
path_components = parent_components;
|
path_components = parent_components;
|
||||||
path_components.push_back(name);
|
path_components.push_back(std::move(name_str));
|
||||||
backing = FileUtil::IOFile(path, PermissionsToCharArray(perms).c_str());
|
backing = FileUtil::IOFile(path, PermissionsToCharArray(perms).c_str());
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,36 +138,54 @@ std::shared_ptr<VfsDirectory> RealVfsDirectory::GetParentDirectory() const {
|
||||||
return std::make_shared<RealVfsDirectory>(parent_path, perms);
|
return std::make_shared<RealVfsDirectory>(parent_path, perms);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<VfsDirectory> RealVfsDirectory::CreateSubdirectory(const std::string& name) {
|
std::shared_ptr<VfsDirectory> RealVfsDirectory::CreateSubdirectory(std::string_view name) {
|
||||||
if (!FileUtil::CreateDir(path + DIR_SEP + name))
|
const std::string subdir_path = (path + DIR_SEP).append(name);
|
||||||
|
|
||||||
|
if (!FileUtil::CreateDir(subdir_path)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
subdirectories.emplace_back(std::make_shared<RealVfsDirectory>(path + DIR_SEP + name, perms));
|
}
|
||||||
|
|
||||||
|
subdirectories.emplace_back(std::make_shared<RealVfsDirectory>(subdir_path, perms));
|
||||||
return subdirectories.back();
|
return subdirectories.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<VfsFile> RealVfsDirectory::CreateFile(const std::string& name) {
|
std::shared_ptr<VfsFile> RealVfsDirectory::CreateFile(std::string_view name) {
|
||||||
if (!FileUtil::CreateEmptyFile(path + DIR_SEP + name))
|
const std::string file_path = (path + DIR_SEP).append(name);
|
||||||
|
|
||||||
|
if (!FileUtil::CreateEmptyFile(file_path)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
files.emplace_back(std::make_shared<RealVfsFile>(path + DIR_SEP + name, perms));
|
}
|
||||||
|
|
||||||
|
files.emplace_back(std::make_shared<RealVfsFile>(file_path, perms));
|
||||||
return files.back();
|
return files.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RealVfsDirectory::DeleteSubdirectory(const std::string& name) {
|
bool RealVfsDirectory::DeleteSubdirectory(std::string_view name) {
|
||||||
return FileUtil::DeleteDirRecursively(path + DIR_SEP + name);
|
const std::string subdir_path = (path + DIR_SEP).append(name);
|
||||||
|
|
||||||
|
return FileUtil::DeleteDirRecursively(subdir_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RealVfsDirectory::DeleteFile(const std::string& name) {
|
bool RealVfsDirectory::DeleteFile(std::string_view name) {
|
||||||
auto file = GetFile(name);
|
const auto file = GetFile(name);
|
||||||
if (file == nullptr)
|
|
||||||
|
if (file == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
files.erase(std::find(files.begin(), files.end(), file));
|
files.erase(std::find(files.begin(), files.end(), file));
|
||||||
|
|
||||||
auto real_file = std::static_pointer_cast<RealVfsFile>(file);
|
auto real_file = std::static_pointer_cast<RealVfsFile>(file);
|
||||||
real_file->Close();
|
real_file->Close();
|
||||||
return FileUtil::Delete(path + DIR_SEP + name);
|
|
||||||
|
const std::string file_path = (path + DIR_SEP).append(name);
|
||||||
|
return FileUtil::Delete(file_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RealVfsDirectory::Rename(const std::string& name) {
|
bool RealVfsDirectory::Rename(std::string_view name) {
|
||||||
return FileUtil::Rename(path, parent_path + DIR_SEP + name);
|
const std::string new_name = (parent_path + DIR_SEP).append(name);
|
||||||
|
|
||||||
|
return FileUtil::Rename(path, new_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RealVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
|
bool RealVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
#include "common/file_util.h"
|
#include "common/file_util.h"
|
||||||
#include "core/file_sys/mode.h"
|
#include "core/file_sys/mode.h"
|
||||||
#include "core/file_sys/vfs.h"
|
#include "core/file_sys/vfs.h"
|
||||||
|
@ -24,7 +26,7 @@ struct RealVfsFile : public VfsFile {
|
||||||
bool IsReadable() const override;
|
bool IsReadable() const override;
|
||||||
size_t Read(u8* data, size_t length, size_t offset) const override;
|
size_t Read(u8* data, size_t length, size_t offset) const override;
|
||||||
size_t Write(const u8* data, size_t length, size_t offset) override;
|
size_t Write(const u8* data, size_t length, size_t offset) override;
|
||||||
bool Rename(const std::string& name) override;
|
bool Rename(std::string_view name) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool Close();
|
bool Close();
|
||||||
|
@ -47,11 +49,11 @@ struct RealVfsDirectory : public VfsDirectory {
|
||||||
bool IsReadable() const override;
|
bool IsReadable() const override;
|
||||||
std::string GetName() const override;
|
std::string GetName() const override;
|
||||||
std::shared_ptr<VfsDirectory> GetParentDirectory() const override;
|
std::shared_ptr<VfsDirectory> GetParentDirectory() const override;
|
||||||
std::shared_ptr<VfsDirectory> CreateSubdirectory(const std::string& name) override;
|
std::shared_ptr<VfsDirectory> CreateSubdirectory(std::string_view name) override;
|
||||||
std::shared_ptr<VfsFile> CreateFile(const std::string& name) override;
|
std::shared_ptr<VfsFile> CreateFile(std::string_view name) override;
|
||||||
bool DeleteSubdirectory(const std::string& name) override;
|
bool DeleteSubdirectory(std::string_view name) override;
|
||||||
bool DeleteFile(const std::string& name) override;
|
bool DeleteFile(std::string_view name) override;
|
||||||
bool Rename(const std::string& name) override;
|
bool Rename(std::string_view name) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
|
bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace Service::FileSystem {
|
||||||
constexpr u64 EMULATED_SD_REPORTED_SIZE = 32000000000;
|
constexpr u64 EMULATED_SD_REPORTED_SIZE = 32000000000;
|
||||||
|
|
||||||
static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base,
|
static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base,
|
||||||
const std::string& dir_name) {
|
std::string_view dir_name) {
|
||||||
if (dir_name.empty() || dir_name == "." || dir_name == "/" || dir_name == "\\")
|
if (dir_name.empty() || dir_name == "." || dir_name == "/" || dir_name == "\\")
|
||||||
return base;
|
return base;
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,8 @@ FileType GuessFromFilename(const std::string& name) {
|
||||||
if (name == "main")
|
if (name == "main")
|
||||||
return FileType::DeconstructedRomDirectory;
|
return FileType::DeconstructedRomDirectory;
|
||||||
|
|
||||||
const std::string extension = Common::ToLower(FileUtil::GetExtensionFromFilename(name));
|
const std::string extension =
|
||||||
|
Common::ToLower(std::string(FileUtil::GetExtensionFromFilename(name)));
|
||||||
|
|
||||||
if (extension == "elf")
|
if (extension == "elf")
|
||||||
return FileType::ELF;
|
return FileType::ELF;
|
||||||
|
|
Reference in New Issue