From 29aff8d5ab46c8d0199aa4bfa7eeff5d4fa2d7ef Mon Sep 17 00:00:00 2001
From: Zach Hilman <DarkLordZach@users.noreply.github.com>
Date: Wed, 18 Jul 2018 21:07:11 -0400
Subject: Virtual Filesystem 2: Electric Boogaloo (#676)

* Virtual Filesystem

* Fix delete bug and documentate

* Review fixes + other stuff

* Fix puyo regression
---
 src/common/file_util.cpp | 107 +++++++++++++++++++++++++++++++++++------------
 1 file changed, 81 insertions(+), 26 deletions(-)

(limited to 'src/common/file_util.cpp')

diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp
index 7213abe18d..bf955386ce 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.cpp
@@ -2,6 +2,7 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
+#include <sstream>
 #include "common/assert.h"
 #include "common/common_funcs.h"
 #include "common/common_paths.h"
@@ -386,7 +387,7 @@ u64 GetSize(FILE* f) {
 bool CreateEmptyFile(const std::string& filename) {
     LOG_TRACE(Common_Filesystem, "{}", filename);
 
-    if (!FileUtil::IOFile(filename, "wb")) {
+    if (!FileUtil::IOFile(filename, "wb").IsOpen()) {
         LOG_ERROR(Common_Filesystem, "failed {}: {}", filename, GetLastErrorMsg());
         return false;
     }
@@ -750,7 +751,7 @@ size_t WriteStringToFile(bool text_file, const std::string& str, const char* fil
 size_t ReadFileToString(bool text_file, const char* filename, std::string& str) {
     IOFile file(filename, text_file ? "r" : "rb");
 
-    if (!file)
+    if (!file.IsOpen())
         return false;
 
     str.resize(static_cast<u32>(file.GetSize()));
@@ -799,6 +800,71 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam
     }
 }
 
+std::vector<std::string> SplitPathComponents(const std::string& filename) {
+    auto copy(filename);
+    std::replace(copy.begin(), copy.end(), '\\', '/');
+    std::vector<std::string> out;
+
+    std::stringstream stream(filename);
+    std::string item;
+    while (std::getline(stream, item, '/'))
+        out.push_back(std::move(item));
+
+    return out;
+}
+
+std::string GetParentPath(const std::string& path) {
+    auto out = path;
+    const auto name_bck_index = out.find_last_of('\\');
+    const auto name_fwd_index = out.find_last_of('/');
+    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);
+}
+
+std::string GetPathWithoutTop(std::string path) {
+    if (path.empty())
+        return "";
+    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('/');
+    return path.substr(std::min<size_t>(name_bck_index, name_fwd_index) + 1);
+    return path.substr(std::min<size_t>(name_bck_index, name_fwd_index) + 1);
+}
+
+std::string GetFilename(std::string path) {
+    std::replace(path.begin(), path.end(), '\\', '/');
+    auto name_index = path.find_last_of('/');
+    if (name_index == std::string::npos)
+        return "";
+    return path.substr(name_index + 1);
+}
+
+std::string GetExtensionFromFilename(const std::string& name) {
+    size_t index = name.find_last_of('.');
+    if (index == std::string::npos)
+        return "";
+
+    return name.substr(index + 1);
+}
+
+std::string RemoveTrailingSlash(const std::string& path) {
+    if (path.empty())
+        return path;
+    if (path.back() == '\\' || path.back() == '/')
+        return path.substr(0, path.size() - 1);
+
+    return path;
+}
+
 IOFile::IOFile() {}
 
 IOFile::IOFile(const std::string& filename, const char openmode[], int flags) {
@@ -820,7 +886,6 @@ IOFile& IOFile::operator=(IOFile&& other) noexcept {
 
 void IOFile::Swap(IOFile& other) noexcept {
     std::swap(m_file, other.m_file);
-    std::swap(m_good, other.m_good);
 }
 
 bool IOFile::Open(const std::string& filename, const char openmode[], int flags) {
@@ -837,16 +902,15 @@ bool IOFile::Open(const std::string& filename, const char openmode[], int flags)
     m_file = fopen(filename.c_str(), openmode);
 #endif
 
-    m_good = IsOpen();
-    return m_good;
+    return IsOpen();
 }
 
 bool IOFile::Close() {
     if (!IsOpen() || 0 != std::fclose(m_file))
-        m_good = false;
+        return false;
 
     m_file = nullptr;
-    return m_good;
+    return true;
 }
 
 u64 IOFile::GetSize() const {
@@ -856,11 +920,8 @@ u64 IOFile::GetSize() const {
     return 0;
 }
 
-bool IOFile::Seek(s64 off, int origin) {
-    if (!IsOpen() || 0 != fseeko(m_file, off, origin))
-        m_good = false;
-
-    return m_good;
+bool IOFile::Seek(s64 off, int origin) const {
+    return IsOpen() && 0 == fseeko(m_file, off, origin);
 }
 
 u64 IOFile::Tell() const {
@@ -871,26 +932,20 @@ u64 IOFile::Tell() const {
 }
 
 bool IOFile::Flush() {
-    if (!IsOpen() || 0 != std::fflush(m_file))
-        m_good = false;
-
-    return m_good;
+    return IsOpen() && 0 == std::fflush(m_file);
 }
 
 bool IOFile::Resize(u64 size) {
-    if (!IsOpen() || 0 !=
+    return IsOpen() && 0 ==
 #ifdef _WIN32
-                         // ector: _chsize sucks, not 64-bit safe
-                         // F|RES: changed to _chsize_s. i think it is 64-bit safe
-                         _chsize_s(_fileno(m_file), size)
+                           // ector: _chsize sucks, not 64-bit safe
+                           // F|RES: changed to _chsize_s. i think it is 64-bit safe
+                           _chsize_s(_fileno(m_file), size)
 #else
-                         // TODO: handle 64bit and growing
-                         ftruncate(fileno(m_file), size)
+                           // TODO: handle 64bit and growing
+                           ftruncate(fileno(m_file), size)
 #endif
-    )
-        m_good = false;
-
-    return m_good;
+        ;
 }
 
 } // namespace FileUtil
-- 
cgit v1.2.3-70-g09d2