aboutsummaryrefslogtreecommitdiff
path: root/src/fs.cpp
diff options
context:
space:
mode:
authorChun Kuan Lee <ken2812221@gmail.com>2018-08-04 13:27:38 +0000
committerChun Kuan Lee <ken2812221@gmail.com>2018-09-26 08:47:42 +0800
commit86eb3b3f1ab594142b6baa9576717ff121f3b745 (patch)
tree6c95ca5128235530be1d376239b12e623ef465da /src/fs.cpp
parentcc7258bdfb44c5b5f3498296d8c9e6791655e89f (diff)
utils: Add fsbridge fstream function wrapper
Diffstat (limited to 'src/fs.cpp')
-rw-r--r--src/fs.cpp102
1 files changed, 102 insertions, 0 deletions
diff --git a/src/fs.cpp b/src/fs.cpp
index df79b5e3df..a146107c4c 100644
--- a/src/fs.cpp
+++ b/src/fs.cpp
@@ -113,4 +113,106 @@ std::string get_filesystem_error_message(const fs::filesystem_error& e)
#endif
}
+#ifdef WIN32
+#ifdef __GLIBCXX__
+
+// reference: https://github.com/gcc-mirror/gcc/blob/gcc-7_3_0-release/libstdc%2B%2B-v3/include/std/fstream#L270
+
+static std::string openmodeToStr(std::ios_base::openmode mode)
+{
+ switch (mode & ~std::ios_base::ate) {
+ case std::ios_base::out:
+ case std::ios_base::out | std::ios_base::trunc:
+ return "w";
+ case std::ios_base::out | std::ios_base::app:
+ case std::ios_base::app:
+ return "a";
+ case std::ios_base::in:
+ return "r";
+ case std::ios_base::in | std::ios_base::out:
+ return "r+";
+ case std::ios_base::in | std::ios_base::out | std::ios_base::trunc:
+ return "w+";
+ case std::ios_base::in | std::ios_base::out | std::ios_base::app:
+ case std::ios_base::in | std::ios_base::app:
+ return "a+";
+ case std::ios_base::out | std::ios_base::binary:
+ case std::ios_base::out | std::ios_base::trunc | std::ios_base::binary:
+ return "wb";
+ case std::ios_base::out | std::ios_base::app | std::ios_base::binary:
+ case std::ios_base::app | std::ios_base::binary:
+ return "ab";
+ case std::ios_base::in | std::ios_base::binary:
+ return "rb";
+ case std::ios_base::in | std::ios_base::out | std::ios_base::binary:
+ return "r+b";
+ case std::ios_base::in | std::ios_base::out | std::ios_base::trunc | std::ios_base::binary:
+ return "w+b";
+ case std::ios_base::in | std::ios_base::out | std::ios_base::app | std::ios_base::binary:
+ case std::ios_base::in | std::ios_base::app | std::ios_base::binary:
+ return "a+b";
+ default:
+ return std::string();
+ }
+}
+
+void ifstream::open(const fs::path& p, std::ios_base::openmode mode)
+{
+ close();
+ m_file = fsbridge::fopen(p, openmodeToStr(mode).c_str());
+ if (m_file == nullptr) {
+ return;
+ }
+ m_filebuf = __gnu_cxx::stdio_filebuf<char>(m_file, mode);
+ rdbuf(&m_filebuf);
+ if (mode & std::ios_base::ate) {
+ seekg(0, std::ios_base::end);
+ }
+}
+
+void ifstream::close()
+{
+ if (m_file != nullptr) {
+ m_filebuf.close();
+ fclose(m_file);
+ }
+ m_file = nullptr;
+}
+
+void ofstream::open(const fs::path& p, std::ios_base::openmode mode)
+{
+ close();
+ m_file = fsbridge::fopen(p, openmodeToStr(mode).c_str());
+ if (m_file == nullptr) {
+ return;
+ }
+ m_filebuf = __gnu_cxx::stdio_filebuf<char>(m_file, mode);
+ rdbuf(&m_filebuf);
+ if (mode & std::ios_base::ate) {
+ seekp(0, std::ios_base::end);
+ }
+}
+
+void ofstream::close()
+{
+ if (m_file != nullptr) {
+ m_filebuf.close();
+ fclose(m_file);
+ }
+ m_file = nullptr;
+}
+#else // __GLIBCXX__
+
+static_assert(sizeof(*fs::path().BOOST_FILESYSTEM_C_STR) == sizeof(wchar_t),
+ "Warning: This build is using boost::filesystem ofstream and ifstream "
+ "implementations which will fail to open paths containing multibyte "
+ "characters. You should delete this static_assert to ignore this warning, "
+ "or switch to a different C++ standard library like the Microsoft C++ "
+ "Standard Library (where boost uses non-standard extensions to construct "
+ "stream objects with wide filenames), or the GNU libstdc++ library (where "
+ "a more complicated workaround has been implemented above).");
+
+#endif // __GLIBCXX__
+#endif // WIN32
+
} // fsbridge