Add missing changes from yuzu file_util

This commit is contained in:
James Rowe 2019-09-07 16:11:35 -06:00
parent 4e9ec4efd0
commit be52d3a7d0
2 changed files with 142 additions and 10 deletions

View File

@ -4,6 +4,7 @@
#include <array> #include <array>
#include <memory> #include <memory>
#include <sstream>
#include <unordered_map> #include <unordered_map>
#include "common/assert.h" #include "common/assert.h"
#include "common/common_funcs.h" #include "common/common_funcs.h"
@ -355,12 +356,12 @@ u64 GetSize(FILE* f) {
// can't use off_t here because it can be 32-bit // can't use off_t here because it can be 32-bit
u64 pos = ftello(f); u64 pos = ftello(f);
if (fseeko(f, 0, SEEK_END) != 0) { if (fseeko(f, 0, SEEK_END) != 0) {
LOG_ERROR(Common_Filesystem, "GetSize: seek failed {}: {}", (void*)f, GetLastErrorMsg()); LOG_ERROR(Common_Filesystem, "GetSize: seek failed {}: {}", fmt::ptr(f), GetLastErrorMsg());
return 0; return 0;
} }
u64 size = ftello(f); u64 size = ftello(f);
if ((size != pos) && (fseeko(f, pos, SEEK_SET) != 0)) { if ((size != pos) && (fseeko(f, pos, SEEK_SET) != 0)) {
LOG_ERROR(Common_Filesystem, "GetSize: seek failed {}: {}", (void*)f, GetLastErrorMsg()); LOG_ERROR(Common_Filesystem, "GetSize: seek failed {}: {}", fmt::ptr(f), GetLastErrorMsg());
return 0; return 0;
} }
return size; return size;
@ -369,7 +370,7 @@ u64 GetSize(FILE* f) {
bool CreateEmptyFile(const std::string& filename) { bool CreateEmptyFile(const std::string& filename) {
LOG_TRACE(Common_Filesystem, "{}", filename); LOG_TRACE(Common_Filesystem, "{}", filename);
if (!FileUtil::IOFile(filename, "wb")) { if (!FileUtil::IOFile(filename, "wb").IsOpen()) {
LOG_ERROR(Common_Filesystem, "failed {}: {}", filename, GetLastErrorMsg()); LOG_ERROR(Common_Filesystem, "failed {}: {}", filename, GetLastErrorMsg());
return false; return false;
} }
@ -541,12 +542,11 @@ std::optional<std::string> GetCurrentDir() {
// Get the current working directory (getcwd uses malloc) // Get the current working directory (getcwd uses malloc)
#ifdef _WIN32 #ifdef _WIN32
wchar_t* dir; wchar_t* dir;
if (!(dir = _wgetcwd(nullptr, 0))) if (!(dir = _wgetcwd(nullptr, 0))) {
#else #else
char* dir; char* dir;
if (!(dir = getcwd(nullptr, 0))) if (!(dir = getcwd(nullptr, 0))) {
#endif #endif
{
LOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: {}", GetLastErrorMsg()); LOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: {}", GetLastErrorMsg());
return {}; return {};
} }
@ -557,7 +557,7 @@ std::optional<std::string> GetCurrentDir() {
#endif #endif
free(dir); free(dir);
return strDir; return strDir;
} } // namespace FileUtil
bool SetCurrentDir(const std::string& directory) { bool SetCurrentDir(const std::string& directory) {
#ifdef _WIN32 #ifdef _WIN32
@ -733,7 +733,6 @@ const std::string& GetUserPath(UserPath path) {
SetUserPath(); SetUserPath();
return g_paths[path]; return g_paths[path];
} }
std::size_t WriteStringToFile(bool text_file, const std::string& filename, std::string_view str) { std::size_t WriteStringToFile(bool text_file, const std::string& filename, std::string_view str) {
return IOFile(filename, text_file ? "w" : "wb").WriteString(str); return IOFile(filename, text_file ? "w" : "wb").WriteString(str);
} }
@ -741,8 +740,8 @@ std::size_t WriteStringToFile(bool text_file, const std::string& filename, std::
std::size_t ReadFileToString(bool text_file, const std::string& filename, std::string& str) { std::size_t ReadFileToString(bool text_file, const std::string& filename, std::string& str) {
IOFile file(filename, text_file ? "r" : "rb"); IOFile file(filename, text_file ? "r" : "rb");
if (!file) if (!file.IsOpen())
return false; return 0;
str.resize(static_cast<u32>(file.GetSize())); str.resize(static_cast<u32>(file.GetSize()));
return file.ReadArray(&str[0], str.size()); return file.ReadArray(&str[0], str.size());
@ -783,6 +782,103 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam
} }
} }
std::vector<std::string> SplitPathComponents(std::string_view filename) {
std::string copy(filename);
std::replace(copy.begin(), copy.end(), '\\', '/');
std::vector<std::string> out;
std::stringstream stream(copy);
std::string item;
while (std::getline(stream, item, '/')) {
out.push_back(std::move(item));
}
return out;
}
std::string_view GetParentPath(std::string_view path) {
const auto name_bck_index = path.rfind('\\');
const auto name_fwd_index = path.rfind('/');
std::size_t 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_view GetPathWithoutTop(std::string_view path) {
if (path.empty()) {
return path;
}
while (path[0] == '\\' || path[0] == '/') {
path.remove_prefix(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);
}
std::string_view GetFilename(std::string_view path) {
const auto name_index = path.find_last_of("\\/");
if (name_index == std::string_view::npos) {
return {};
}
return path.substr(name_index + 1);
}
std::string_view GetExtensionFromFilename(std::string_view name) {
const std::size_t index = name.rfind('.');
if (index == std::string_view::npos) {
return {};
}
return name.substr(index + 1);
}
std::string_view RemoveTrailingSlash(std::string_view path) {
if (path.empty()) {
return path;
}
if (path.back() == '\\' || path.back() == '/') {
path.remove_suffix(1);
return path;
}
return path;
}
std::string SanitizePath(std::string_view path_, DirectorySeparator directory_separator) {
std::string path(path_);
char type1 = directory_separator == DirectorySeparator::BackwardSlash ? '/' : '\\';
char type2 = directory_separator == DirectorySeparator::BackwardSlash ? '\\' : '/';
if (directory_separator == DirectorySeparator::PlatformDefault) {
#ifdef _WIN32
type1 = '/';
type2 = '\\';
#endif
}
std::replace(path.begin(), path.end(), type1, type2);
path.erase(std::unique(path.begin(), path.end(),
[type2](char c1, char c2) { return c1 == type2 && c2 == type2; }),
path.end());
return std::string(RemoveTrailingSlash(path));
}
IOFile::IOFile() {} IOFile::IOFile() {}
IOFile::IOFile(const std::string& filename, const char openmode[], int flags) { IOFile::IOFile(const std::string& filename, const char openmode[], int flags) {

View File

@ -11,6 +11,7 @@
#include <limits> #include <limits>
#include <optional> #include <optional>
#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"
@ -166,6 +167,41 @@ std::size_t ReadFileToString(bool text_file, const std::string& filename, std::s
void SplitFilename83(const std::string& filename, std::array<char, 9>& short_name, void SplitFilename83(const std::string& filename, std::array<char, 9>& short_name,
std::array<char, 4>& extension); std::array<char, 4>& extension);
// 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" }
std::vector<std::string> SplitPathComponents(std::string_view filename);
// Gets all of the text up to the last '/' or '\' in the path.
std::string_view GetParentPath(std::string_view path);
// Gets all of the text after the first '/' or '\' in the path.
std::string_view GetPathWithoutTop(std::string_view path);
// Gets the filename of the path
std::string_view GetFilename(std::string_view path);
// Gets the extension of the filename
std::string_view GetExtensionFromFilename(std::string_view name);
// Removes the final '/' or '\' if one exists
std::string_view RemoveTrailingSlash(std::string_view path);
// Creates a new vector containing indices [first, last) from the original.
template <typename T>
std::vector<T> SliceVector(const std::vector<T>& vector, std::size_t first, std::size_t last) {
if (first >= last)
return {};
last = std::min<std::size_t>(last, vector.size());
return std::vector<T>(vector.begin() + first, vector.begin() + first + last);
}
enum class DirectorySeparator { ForwardSlash, BackwardSlash, PlatformDefault };
// Removes trailing slash, makes all '\\' into '/', and removes duplicate '/'. Makes '/' into '\\'
// depending if directory_separator is BackwardSlash or PlatformDefault and running on windows
std::string SanitizePath(std::string_view path,
DirectorySeparator directory_separator = DirectorySeparator::ForwardSlash);
// simple wrapper for cstdlib file functions to // simple wrapper for cstdlib file functions to
// hopefully will make error checking easier // hopefully will make error checking easier
// and make forgetting an fclose() harder // and make forgetting an fclose() harder