From 7c45afecb2a157088591a94f8c008d74419243d1 Mon Sep 17 00:00:00 2001
From: JosJuice <josjuice@gmail.com>
Date: Thu, 30 Jul 2015 15:06:23 +0200
Subject: [PATCH] Filesystem: Use file info in arguments instead of path

Some callers already have the file info, making the relatively slow
FindFileInfo calls unnecessary. Callers that didn't have the file info
will now need to call FindFileInfo on their own.
---
 Source/Core/Core/HW/DVD/FileMonitor.cpp       |  9 ++--
 Source/Core/DiscIO/FileSystemGCWii.cpp        | 45 ++++++++++---------
 Source/Core/DiscIO/FileSystemGCWii.h          |  6 +--
 Source/Core/DiscIO/Filesystem.h               |  6 +--
 Source/Core/DiscIO/VolumeGC.cpp               | 12 ++++-
 Source/Core/DiscIO/VolumeWii.cpp              |  3 +-
 .../ISOProperties/FilesystemPanel.cpp         | 11 +++--
 7 files changed, 53 insertions(+), 39 deletions(-)

diff --git a/Source/Core/Core/HW/DVD/FileMonitor.cpp b/Source/Core/Core/HW/DVD/FileMonitor.cpp
index f6c984c4fc..980bc5454f 100644
--- a/Source/Core/Core/HW/DVD/FileMonitor.cpp
+++ b/Source/Core/Core/HW/DVD/FileMonitor.cpp
@@ -88,18 +88,19 @@ void Log(u64 offset, const DiscIO::Partition& partition)
   if (!s_filesystem)
     return;
 
-  const std::string path = s_filesystem->GetPath(offset);
+  const DiscIO::FileInfo* file_info = s_filesystem->FindFileInfo(offset);
 
   // Do nothing if no file was found at that offset
-  if (path.empty())
+  if (!file_info)
     return;
 
+  const std::string path = s_filesystem->GetPath(file_info->GetOffset());
+
   // Do nothing if we found the same file again
   if (s_previous_file == path)
     return;
 
-  const u64 size = s_filesystem->GetFileSize(path);
-  const std::string size_string = ThousandSeparate(size / 1000, 7);
+  const std::string size_string = ThousandSeparate(file_info->GetSize() / 1000, 7);
 
   const std::string log_string = StringFromFormat("%s kB %s", size_string.c_str(), path.c_str());
   if (IsSoundFile(path))
diff --git a/Source/Core/DiscIO/FileSystemGCWii.cpp b/Source/Core/DiscIO/FileSystemGCWii.cpp
index f8ddab28fe..d799caf435 100644
--- a/Source/Core/DiscIO/FileSystemGCWii.cpp
+++ b/Source/Core/DiscIO/FileSystemGCWii.cpp
@@ -50,31 +50,35 @@ const std::vector<FileInfoGCWii>& FileSystemGCWii::GetFileList()
   return m_FileInfoVector;
 }
 
-const FileInfo* FileSystemGCWii::FindFileInfo(const std::string& _rFullPath)
+const FileInfo* FileSystemGCWii::FindFileInfo(const std::string& path)
 {
   if (!m_Initialized)
     InitFileSystem();
 
   for (size_t i = 0; i < m_FileInfoVector.size(); ++i)
   {
-    if (!strcasecmp(GetPathFromFSTOffset(i).c_str(), _rFullPath.c_str()))
+    if (!strcasecmp(GetPathFromFSTOffset(i).c_str(), path.c_str()))
       return &m_FileInfoVector[i];
   }
 
   return nullptr;
 }
 
-u64 FileSystemGCWii::GetFileSize(const std::string& _rFullPath)
+const FileInfo* FileSystemGCWii::FindFileInfo(u64 disc_offset)
 {
   if (!m_Initialized)
     InitFileSystem();
 
-  const FileInfo* pFileInfo = FindFileInfo(_rFullPath);
+  for (auto& file_info : m_FileInfoVector)
+  {
+    if ((file_info.GetOffset() <= disc_offset) &&
+        ((file_info.GetOffset() + file_info.GetSize()) > disc_offset))
+    {
+      return &file_info;
+    }
+  }
 
-  if (pFileInfo != nullptr && !pFileInfo->IsDirectory())
-    return pFileInfo->GetSize();
-
-  return 0;
+  return nullptr;
 }
 
 std::string FileSystemGCWii::GetPath(u64 _Address)
@@ -135,42 +139,39 @@ std::string FileSystemGCWii::GetPathFromFSTOffset(size_t file_info_offset)
   }
 }
 
-u64 FileSystemGCWii::ReadFile(const std::string& _rFullPath, u8* _pBuffer, u64 _MaxBufferSize,
+u64 FileSystemGCWii::ReadFile(const FileInfo* file_info, u8* _pBuffer, u64 _MaxBufferSize,
                               u64 _OffsetInFile)
 {
   if (!m_Initialized)
     InitFileSystem();
 
-  const FileInfo* pFileInfo = FindFileInfo(_rFullPath);
-  if (pFileInfo == nullptr)
+  if (!file_info || file_info->IsDirectory())
     return 0;
 
-  if (_OffsetInFile >= pFileInfo->GetSize())
+  if (_OffsetInFile >= file_info->GetSize())
     return 0;
 
-  u64 read_length = std::min(_MaxBufferSize, pFileInfo->GetSize() - _OffsetInFile);
+  u64 read_length = std::min(_MaxBufferSize, file_info->GetSize() - _OffsetInFile);
 
   DEBUG_LOG(DISCIO, "Reading %" PRIx64 " bytes at %" PRIx64 " from file %s. Offset: %" PRIx64
                     " Size: %" PRIx64,
-            read_length, _OffsetInFile, _rFullPath.c_str(), pFileInfo->GetOffset(),
-            pFileInfo->GetSize());
+            read_length, _OffsetInFile, GetPath(file_info->GetOffset()).c_str(),
+            file_info->GetOffset(), file_info->GetSize());
 
-  m_rVolume->Read(pFileInfo->GetOffset() + _OffsetInFile, read_length, _pBuffer, m_partition);
+  m_rVolume->Read(file_info->GetOffset() + _OffsetInFile, read_length, _pBuffer, m_partition);
   return read_length;
 }
 
-bool FileSystemGCWii::ExportFile(const std::string& _rFullPath, const std::string& _rExportFilename)
+bool FileSystemGCWii::ExportFile(const FileInfo* file_info, const std::string& _rExportFilename)
 {
   if (!m_Initialized)
     InitFileSystem();
 
-  const FileInfo* pFileInfo = FindFileInfo(_rFullPath);
-
-  if (!pFileInfo)
+  if (!file_info || file_info->IsDirectory())
     return false;
 
-  u64 remainingSize = pFileInfo->GetSize();
-  u64 fileOffset = pFileInfo->GetOffset();
+  u64 remainingSize = file_info->GetSize();
+  u64 fileOffset = file_info->GetOffset();
 
   File::IOFile f(_rExportFilename, "wb");
   if (!f)
diff --git a/Source/Core/DiscIO/FileSystemGCWii.h b/Source/Core/DiscIO/FileSystemGCWii.h
index 37e972e542..9c31c1bcc8 100644
--- a/Source/Core/DiscIO/FileSystemGCWii.h
+++ b/Source/Core/DiscIO/FileSystemGCWii.h
@@ -44,12 +44,12 @@ public:
   bool IsValid() const override { return m_Valid; }
   const std::vector<FileInfoGCWii>& GetFileList() override;
   const FileInfo* FindFileInfo(const std::string& path) override;
-  u64 GetFileSize(const std::string& _rFullPath) override;
+  const FileInfo* FindFileInfo(u64 disc_offset) override;
   std::string GetPath(u64 _Address) override;
   std::string GetPathFromFSTOffset(size_t file_info_offset) override;
-  u64 ReadFile(const std::string& _rFullPath, u8* _pBuffer, u64 _MaxBufferSize,
+  u64 ReadFile(const FileInfo* file_info, u8* _pBuffer, u64 _MaxBufferSize,
                u64 _OffsetInFile) override;
-  bool ExportFile(const std::string& _rFullPath, const std::string& _rExportFilename) override;
+  bool ExportFile(const FileInfo* file_info, const std::string& _rExportFilename) override;
   bool ExportApploader(const std::string& _rExportFolder) const override;
   bool ExportDOL(const std::string& _rExportFolder) const override;
   std::optional<u64> GetBootDOLOffset() const override;
diff --git a/Source/Core/DiscIO/Filesystem.h b/Source/Core/DiscIO/Filesystem.h
index c27d6e9636..22cc9bc47a 100644
--- a/Source/Core/DiscIO/Filesystem.h
+++ b/Source/Core/DiscIO/Filesystem.h
@@ -40,11 +40,11 @@ public:
   virtual bool IsValid() const = 0;
   // TODO: Should only return FileInfo, not FileInfoGCWii
   virtual const std::vector<FileInfoGCWii>& GetFileList() = 0;
-  virtual u64 GetFileSize(const std::string& _rFullPath) = 0;
   virtual const FileInfo* FindFileInfo(const std::string& path) = 0;
-  virtual u64 ReadFile(const std::string& _rFullPath, u8* _pBuffer, u64 _MaxBufferSize,
+  virtual const FileInfo* FindFileInfo(u64 disc_offset) = 0;
+  virtual u64 ReadFile(const FileInfo* file_info, u8* _pBuffer, u64 _MaxBufferSize,
                        u64 _OffsetInFile = 0) = 0;
-  virtual bool ExportFile(const std::string& _rFullPath, const std::string& _rExportFilename) = 0;
+  virtual bool ExportFile(const FileInfo* file_info, const std::string& _rExportFilename) = 0;
   virtual bool ExportApploader(const std::string& _rExportFolder) const = 0;
   virtual bool ExportDOL(const std::string& _rExportFolder) const = 0;
   virtual std::string GetPath(u64 _Address) = 0;
diff --git a/Source/Core/DiscIO/VolumeGC.cpp b/Source/Core/DiscIO/VolumeGC.cpp
index 39bc029ec2..09f073d075 100644
--- a/Source/Core/DiscIO/VolumeGC.cpp
+++ b/Source/Core/DiscIO/VolumeGC.cpp
@@ -177,7 +177,11 @@ void VolumeGC::LoadBannerFile() const
   if (!file_system)
     return;
 
-  size_t file_size = static_cast<size_t>(file_system->GetFileSize("opening.bnr"));
+  const FileInfo* file_info = file_system->FindFileInfo("opening.bnr");
+  if (!file_info)
+    return;
+
+  size_t file_size = static_cast<size_t>(file_info->GetSize());
   constexpr int BNR1_MAGIC = 0x31524e42;
   constexpr int BNR2_MAGIC = 0x32524e42;
   if (file_size != BNR1_SIZE && file_size != BNR2_SIZE)
@@ -186,7 +190,11 @@ void VolumeGC::LoadBannerFile() const
     return;
   }
 
-  file_system->ReadFile("opening.bnr", reinterpret_cast<u8*>(&banner_file), file_size);
+  if (file_size != file_system->ReadFile(file_info, reinterpret_cast<u8*>(&banner_file), file_size))
+  {
+    WARN_LOG(DISCIO, "Could not read opening.bnr.");
+    return;
+  }
 
   bool is_bnr1;
   if (banner_file.id == BNR1_MAGIC && file_size == BNR1_SIZE)
diff --git a/Source/Core/DiscIO/VolumeWii.cpp b/Source/Core/DiscIO/VolumeWii.cpp
index ceb1fa5788..6b1cf6dafa 100644
--- a/Source/Core/DiscIO/VolumeWii.cpp
+++ b/Source/Core/DiscIO/VolumeWii.cpp
@@ -274,7 +274,8 @@ std::map<Language, std::string> VolumeWii::GetLongNames() const
     return {};
 
   std::vector<u8> opening_bnr(NAMES_TOTAL_BYTES);
-  size_t size = file_system->ReadFile("opening.bnr", opening_bnr.data(), opening_bnr.size(), 0x5C);
+  const FileInfo* file_info = file_system->FindFileInfo("opening.bnr");
+  size_t size = file_system->ReadFile(file_info, opening_bnr.data(), opening_bnr.size(), 0x5C);
   opening_bnr.resize(size);
   return ReadWiiNames(opening_bnr);
 }
diff --git a/Source/Core/DolphinWX/ISOProperties/FilesystemPanel.cpp b/Source/Core/DolphinWX/ISOProperties/FilesystemPanel.cpp
index ebad7364ef..cb4e3fd059 100644
--- a/Source/Core/DolphinWX/ISOProperties/FilesystemPanel.cpp
+++ b/Source/Core/DolphinWX/ISOProperties/FilesystemPanel.cpp
@@ -405,12 +405,14 @@ void FilesystemPanel::ExtractSingleFile(const wxString& output_file_path) const
     // Remove "Partition x/"
     selection_file_path.erase(0, slash_index + 1);
 
-    partition->filesystem->ExportFile(WxStrToStr(selection_file_path),
-                                      WxStrToStr(output_file_path));
+    partition->filesystem->ExportFile(
+        partition->filesystem->FindFileInfo(WxStrToStr(selection_file_path)),
+        WxStrToStr(output_file_path));
   }
   else
   {
-    m_filesystem->ExportFile(WxStrToStr(selection_file_path), WxStrToStr(output_file_path));
+    m_filesystem->ExportFile(m_filesystem->FindFileInfo(WxStrToStr(selection_file_path)),
+                             WxStrToStr(output_file_path));
   }
 }
 
@@ -456,6 +458,7 @@ void FilesystemPanel::ExtractDirectories(const std::string& full_path,
   else
   {
     // Look for the dir we are going to extract
+    // TODO: Make this more efficient
     for (index = 0; index < fst.size(); ++index)
     {
       if (filesystem->GetPathFromFSTOffset(index) == full_path)
@@ -513,7 +516,7 @@ void FilesystemPanel::ExtractDirectories(const std::string& full_path,
           StringFromFormat("%s/%s", output_folder.c_str(), path.c_str());
       INFO_LOG(DISCIO, "%s", export_name.c_str());
 
-      if (!File::Exists(export_name) && !filesystem->ExportFile(path, export_name))
+      if (!File::Exists(export_name) && !filesystem->ExportFile(&fst[index], export_name))
       {
         ERROR_LOG(DISCIO, "Could not export %s", export_name.c_str());
       }