Bug 1428614 - Implement mozilla::IFStream and mozilla::OFStream. r=froydnj
authorMasatoshi Kimura <VYV03354@nifty.ne.jp>
Sun, 07 Jan 2018 18:31:31 +0900
changeset 403575 ce0cc721f03ea1cd2081bfbb3f7d8d66d3e53910
parent 403574 46a5b62580f6184ae1423527688f40ae3932c326
child 403576 badef7a8ef702bf5d73afd8de765f96146acc0b5
push id33438
push userrgurzau@mozilla.com
push dateWed, 14 Feb 2018 10:46:56 +0000
treeherdermozilla-central@c48e46d5edbf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1428614
milestone60.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1428614 - Implement mozilla::IFStream and mozilla::OFStream. r=froydnj This is drop-in replacements of std::ifstream and std::ofstream, but supports widechar filenames on Windows. This is just an alias of std::ofstream on other platforms. MozReview-Commit-ID: FHNatG5595k
mfbt/FStream.h
mfbt/moz.build
new file mode 100644
--- /dev/null
+++ b/mfbt/FStream.h
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Similar to std::ifstream/ofstream, but takes char16ptr_t on Windows.
+// Until C++17, std functions can only take char* filenames. So Unicode
+// filenames were lost on Windows. To address this limitations, this wrapper
+// uses proprietary wchar_t* overloads on MSVC, and __gnu_cxx::stdio_filebuf
+// extension on MinGW. Once we can use C++17 filesystem API everywhere,
+// we will be able to avoid this wrapper.
+
+#ifndef mozilla_FStream_h
+#define mozilla_FStream_h
+
+#include "mozilla/Char16.h"
+#include <iostream>
+#include <fstream>
+#if defined(__MINGW32__)
+#include "mozilla/UniquePtr.h"
+#include <fcntl.h>
+#include <ext/stdio_filebuf.h>
+#endif
+
+namespace mozilla {
+
+#if defined(__MINGW32__)
+// MinGW does not support wchar_t* overloads that are MSVC extension until
+// C++17, so we have to implement widechar wrappers using a GNU extension.
+class IFStream : public std::istream
+{
+public:
+  explicit IFStream(char16ptr_t filename, openmode mode = in);
+
+  std::filebuf* rdbuf() const { return mFileBuf.get(); }
+
+  bool is_open() const { return mFileBuf && mFileBuf->is_open(); }
+  void open(char16ptr_t filename, openmode mode = in);
+  void close() { mFileBuf && mFileBuf->close(); }
+
+private:
+  UniquePtr<std::filebuf> mFileBuf;
+};
+
+inline
+IFStream::IFStream(char16ptr_t filename, openmode mode)
+  : std::istream(nullptr)
+{
+  open(filename, mode);
+}
+
+inline void
+IFStream::open(char16ptr_t filename, openmode mode)
+{
+  int fmode = _O_RDONLY;
+  if (mode & binary) {
+    fmode |= _O_BINARY;
+  } else {
+    fmode |= _O_TEXT;
+  }
+  int fd = _wopen(filename, fmode);
+  mFileBuf = MakeUnique<__gnu_cxx::stdio_filebuf<char>>(fd, mode);
+  std::istream::rdbuf(mFileBuf.get());
+}
+
+class OFStream : public std::ostream
+{
+public:
+  explicit OFStream(char16ptr_t filename, openmode mode = out);
+
+  std::filebuf* rdbuf() const { return mFileBuf.get(); }
+
+  bool is_open() const { return mFileBuf && mFileBuf->is_open(); }
+  void open(char16ptr_t filename, openmode mode = out);
+  void close() { mFileBuf && mFileBuf->close(); }
+
+private:
+  UniquePtr<std::filebuf> mFileBuf;
+};
+
+inline
+OFStream::OFStream(char16ptr_t filename, openmode mode)
+  : std::ostream(nullptr)
+{
+  open(filename, mode);
+}
+
+inline void
+OFStream::open(char16ptr_t filename, openmode mode)
+{
+  int fmode = _O_WRONLY;
+  if (mode & binary) {
+    fmode |= _O_BINARY;
+  } else {
+    fmode |= _O_TEXT;
+  }
+  if (mode & trunc) {
+    fmode |= _O_CREAT | _O_TRUNC;
+  }
+  int fd = _wopen(filename, fmode);
+  mFileBuf = MakeUnique<__gnu_cxx::stdio_filebuf<char>>(fd, mode);
+  std::ostream::rdbuf(mFileBuf.get());
+}
+
+#elif defined(XP_WIN)
+class IFStream : public std::ifstream
+{
+public:
+  explicit IFStream(char16ptr_t filename, openmode mode = in)
+    : std::ifstream(filename, mode) {}
+
+  void open(char16ptr_t filename, openmode mode = in)
+  {
+    std::ifstream::open(filename, mode);
+  }
+};
+
+class OFStream : public std::ofstream
+{
+public:
+  explicit OFStream(char16ptr_t filename, openmode mode = out)
+    : std::ofstream(filename, mode) {}
+
+  void open(char16ptr_t filename, openmode mode = out)
+  {
+    std::ofstream::open(filename, mode);
+  }
+};
+#else
+using IFStream = std::ifstream;
+using OFStream = std::ofstream;
+#endif
+
+} // namespace mozilla
+
+#endif /* mozilla_FStream_h */
--- a/mfbt/moz.build
+++ b/mfbt/moz.build
@@ -36,16 +36,17 @@ EXPORTS.mozilla = [
     'DoublyLinkedList.h',
     'EndianUtils.h',
     'EnumeratedArray.h',
     'EnumeratedRange.h',
     'EnumSet.h',
     'EnumTypeTraits.h',
     'FastBernoulliTrial.h',
     'FloatingPoint.h',
+    'FStream.h',
     'GuardObjects.h',
     'HashFunctions.h',
     'IndexSequence.h',
     'IntegerPrintfMacros.h',
     'IntegerRange.h',
     'IntegerTypeTraits.h',
     'JSONWriter.h',
     'Likely.h',