From 3ee4432fe391282ac2a5ab5492ff915b0c2adf28 Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Wed, 13 Apr 2016 19:10:54 -0400
Subject: [PATCH 1/5] file_util: Make IOFile data members private

---
 src/common/file_util.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/common/file_util.h b/src/common/file_util.h
index 880b8a1e3..80e618aca 100644
--- a/src/common/file_util.h
+++ b/src/common/file_util.h
@@ -260,6 +260,7 @@ public:
     // clear error state
     void Clear() { m_good = true; std::clearerr(m_file); }
 
+private:
     std::FILE* m_file;
     bool m_good;
 };

From bf9945b81bf7d41c197ac8b190cab9e1c7176733 Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Wed, 13 Apr 2016 19:20:23 -0400
Subject: [PATCH 2/5] file_util: Check for is_trivially_copyable

Also applies the template checks to ReadArray as well.
---
 src/common/file_util.h | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/common/file_util.h b/src/common/file_util.h
index 80e618aca..dd151575f 100644
--- a/src/common/file_util.h
+++ b/src/common/file_util.h
@@ -192,6 +192,9 @@ public:
     template <typename T>
     size_t ReadArray(T* data, size_t length)
     {
+        static_assert(std::is_standard_layout<T>(), "Given array does not consist of standard layout objects");
+        static_assert(std::is_trivially_copyable<T>(), "Given array does not consist of trivially copyable objects");
+
         if (!IsOpen()) {
             m_good = false;
             return -1;
@@ -207,9 +210,8 @@ public:
     template <typename T>
     size_t WriteArray(const T* data, size_t length)
     {
-        static_assert(std::is_standard_layout<T>::value, "Given array does not consist of standard layout objects");
-        // TODO: gcc 4.8 does not support is_trivially_copyable, but we really should check for it here.
-        //static_assert(std::is_trivially_copyable<T>::value, "Given array does not consist of trivially copyable objects");
+        static_assert(std::is_standard_layout<T>(), "Given array does not consist of standard layout objects");
+        static_assert(std::is_trivially_copyable<T>(), "Given array does not consist of trivially copyable objects");
 
         if (!IsOpen()) {
             m_good = false;

From a4120ca66cc6c0f3a8056c6ea247c15f63c7feff Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Wed, 13 Apr 2016 19:29:16 -0400
Subject: [PATCH 3/5] file_util: Don't expose IOFile internals through the API

---
 src/common/file_util.cpp                   | 25 +++-------------------
 src/common/file_util.h                     |  9 +-------
 src/video_core/debug_utils/debug_utils.cpp | 17 ++++++++++++++-
 3 files changed, 20 insertions(+), 31 deletions(-)

diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp
index 9ada09f8a..578c673b9 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.cpp
@@ -824,13 +824,12 @@ 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)
 {
-    FileUtil::IOFile file(filename, text_file ? "r" : "rb");
-    auto const f = file.GetHandle();
+    IOFile file(filename, text_file ? "r" : "rb");
 
-    if (!f)
+    if (!file)
         return false;
 
-    str.resize(static_cast<u32>(GetSize(f)));
+    str.resize(static_cast<u32>(file.GetSize()));
     return file.ReadArray(&str[0], str.size());
 }
 
@@ -880,10 +879,6 @@ IOFile::IOFile()
     : m_file(nullptr), m_good(true)
 {}
 
-IOFile::IOFile(std::FILE* file)
-    : m_file(file), m_good(true)
-{}
-
 IOFile::IOFile(const std::string& filename, const char openmode[])
     : m_file(nullptr), m_good(true)
 {
@@ -935,20 +930,6 @@ bool IOFile::Close()
     return m_good;
 }
 
-std::FILE* IOFile::ReleaseHandle()
-{
-    std::FILE* const ret = m_file;
-    m_file = nullptr;
-    return ret;
-}
-
-void IOFile::SetHandle(std::FILE* file)
-{
-    Close();
-    Clear();
-    m_file = file;
-}
-
 u64 IOFile::GetSize()
 {
     if (IsOpen())
diff --git a/src/common/file_util.h b/src/common/file_util.h
index dd151575f..8f72fb4e2 100644
--- a/src/common/file_util.h
+++ b/src/common/file_util.h
@@ -176,7 +176,6 @@ class IOFile : public NonCopyable
 {
 public:
     IOFile();
-    explicit IOFile(std::FILE* file);
     IOFile(const std::string& filename, const char openmode[]);
 
     ~IOFile();
@@ -245,13 +244,7 @@ public:
 
     // m_good is set to false when a read, write or other function fails
     bool IsGood() const { return m_good; }
-    operator void*() { return m_good ? m_file : nullptr; }
-
-    std::FILE* ReleaseHandle();
-
-    std::FILE* GetHandle() { return m_file; }
-
-    void SetHandle(std::FILE* file);
+    explicit operator bool() const { return IsGood(); }
 
     bool Seek(s64 off, int origin);
     u64 Tell();
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp
index 693f93597..c8752c003 100644
--- a/src/video_core/debug_utils/debug_utils.cpp
+++ b/src/video_core/debug_utils/debug_utils.cpp
@@ -586,6 +586,21 @@ TextureInfo TextureInfo::FromPicaRegister(const Regs::TextureConfig& config,
     return info;
 }
 
+#ifdef HAVE_PNG
+// Adapter functions to libpng to write/flush to File::IOFile instances.
+static void WriteIOFile(png_structp png_ptr, png_bytep data, png_size_t length) {
+    auto* fp = static_cast<FileUtil::IOFile*>(png_get_io_ptr(png_ptr));
+    if (!fp->WriteBytes(data, length))
+         png_error(png_ptr, "Failed to write to output PNG file.");
+}
+
+static void FlushIOFile(png_structp png_ptr) {
+    auto* fp = static_cast<FileUtil::IOFile*>(png_get_io_ptr(png_ptr));
+    if (!fp->Flush())
+         png_error(png_ptr, "Failed to flush to output PNG file.");
+}
+#endif
+
 void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) {
 #ifndef HAVE_PNG
     return;
@@ -629,7 +644,7 @@ void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data) {
         goto finalise;
     }
 
-    png_init_io(png_ptr, fp.GetHandle());
+    png_set_write_fn(png_ptr, static_cast<void*>(&fp), WriteIOFile, FlushIOFile);
 
     // Write header (8 bit color depth)
     png_set_IHDR(png_ptr, info_ptr, texture_config.width, texture_config.height,

From 655623ebb2dd6f3f1451e5b8b92dc755868347c8 Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Wed, 13 Apr 2016 19:38:01 -0400
Subject: [PATCH 4/5] file_util: const qualify IOFile's Tell and GetSize
 functions

---
 src/common/file_util.cpp | 12 ++++++------
 src/common/file_util.h   |  4 ++--
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp
index 578c673b9..7d96d04d9 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.cpp
@@ -930,12 +930,12 @@ bool IOFile::Close()
     return m_good;
 }
 
-u64 IOFile::GetSize()
+u64 IOFile::GetSize() const
 {
     if (IsOpen())
         return FileUtil::GetSize(m_file);
-    else
-        return 0;
+
+    return 0;
 }
 
 bool IOFile::Seek(s64 off, int origin)
@@ -946,12 +946,12 @@ bool IOFile::Seek(s64 off, int origin)
     return m_good;
 }
 
-u64 IOFile::Tell()
+u64 IOFile::Tell() const
 {
     if (IsOpen())
         return ftello(m_file);
-    else
-        return -1;
+
+    return -1;
 }
 
 bool IOFile::Flush()
diff --git a/src/common/file_util.h b/src/common/file_util.h
index 8f72fb4e2..d520130ce 100644
--- a/src/common/file_util.h
+++ b/src/common/file_util.h
@@ -247,8 +247,8 @@ public:
     explicit operator bool() const { return IsGood(); }
 
     bool Seek(s64 off, int origin);
-    u64 Tell();
-    u64 GetSize();
+    u64 Tell() const;
+    u64 GetSize() const;
     bool Resize(u64 size);
     bool Flush();
 

From 5f51622e9de0483519f47c749888fe7d5b120c79 Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Wed, 13 Apr 2016 19:48:03 -0400
Subject: [PATCH 5/5] file_util: In-class initialize data members

---
 src/common/file_util.cpp | 6 ++----
 src/common/file_util.h   | 4 ++--
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp
index 7d96d04d9..53700c865 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.cpp
@@ -876,11 +876,10 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam
 }
 
 IOFile::IOFile()
-    : m_file(nullptr), m_good(true)
-{}
+{
+}
 
 IOFile::IOFile(const std::string& filename, const char openmode[])
-    : m_file(nullptr), m_good(true)
 {
     Open(filename, openmode);
 }
@@ -891,7 +890,6 @@ IOFile::~IOFile()
 }
 
 IOFile::IOFile(IOFile&& other)
-    : m_file(nullptr), m_good(true)
 {
     Swap(other);
 }
diff --git a/src/common/file_util.h b/src/common/file_util.h
index d520130ce..b54a9fb72 100644
--- a/src/common/file_util.h
+++ b/src/common/file_util.h
@@ -256,8 +256,8 @@ public:
     void Clear() { m_good = true; std::clearerr(m_file); }
 
 private:
-    std::FILE* m_file;
-    bool m_good;
+    std::FILE* m_file = nullptr;
+    bool m_good = true;
 };
 
 }  // namespace