tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

FStream.h (3643B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 // Similar to std::ifstream/ofstream, but takes char16ptr_t on Windows.
      8 // Until C++17, std functions can only take char* filenames. So Unicode
      9 // filenames were lost on Windows. To address this limitations, this wrapper
     10 // uses proprietary wchar_t* overloads on MSVC, and __gnu_cxx::stdio_filebuf
     11 // extension on MinGW. Once we can use C++17 filesystem API everywhere,
     12 // we will be able to avoid this wrapper.
     13 
     14 #ifndef mozilla_FStream_h
     15 #define mozilla_FStream_h
     16 
     17 #include "mozilla/Char16.h"
     18 #include <istream>
     19 #include <ostream>
     20 #include <fstream>
     21 #if defined(__MINGW32__) && defined(__GLIBCXX__)
     22 #  include "mozilla/UniquePtr.h"
     23 #  include <fcntl.h>
     24 #  include <ext/stdio_filebuf.h>
     25 #endif
     26 
     27 namespace mozilla {
     28 
     29 #if defined(__MINGW32__) && defined(__GLIBCXX__)
     30 // MinGW does not support wchar_t* overloads that are MSVC extension until
     31 // C++17, so we have to implement widechar wrappers using a GNU extension.
     32 class IFStream : public std::istream {
     33 public:
     34  explicit IFStream(char16ptr_t filename, openmode mode = in);
     35 
     36  std::filebuf* rdbuf() const { return mFileBuf.get(); }
     37 
     38  bool is_open() const { return mFileBuf && mFileBuf->is_open(); }
     39  void open(char16ptr_t filename, openmode mode = in);
     40  void close() { mFileBuf && mFileBuf->close(); }
     41 
     42 private:
     43  UniquePtr<std::filebuf> mFileBuf;
     44 };
     45 
     46 inline IFStream::IFStream(char16ptr_t filename, openmode mode)
     47    : std::istream(nullptr) {
     48  open(filename, mode);
     49 }
     50 
     51 inline void IFStream::open(char16ptr_t filename, openmode mode) {
     52  int fmode = _O_RDONLY;
     53  if (mode & binary) {
     54    fmode |= _O_BINARY;
     55  } else {
     56    fmode |= _O_TEXT;
     57  }
     58  int fd = _wopen(filename, fmode);
     59  mFileBuf = MakeUnique<__gnu_cxx::stdio_filebuf<char>>(fd, mode);
     60  std::istream::rdbuf(mFileBuf.get());
     61 }
     62 
     63 class OFStream : public std::ostream {
     64 public:
     65  explicit OFStream(char16ptr_t filename, openmode mode = out);
     66 
     67  std::filebuf* rdbuf() const { return mFileBuf.get(); }
     68 
     69  bool is_open() const { return mFileBuf && mFileBuf->is_open(); }
     70  void open(char16ptr_t filename, openmode mode = out);
     71  void close() { mFileBuf && mFileBuf->close(); }
     72 
     73 private:
     74  UniquePtr<std::filebuf> mFileBuf;
     75 };
     76 
     77 inline OFStream::OFStream(char16ptr_t filename, openmode mode)
     78    : std::ostream(nullptr) {
     79  open(filename, mode);
     80 }
     81 
     82 inline void OFStream::open(char16ptr_t filename, openmode mode) {
     83  int fmode = _O_WRONLY;
     84  if (mode & binary) {
     85    fmode |= _O_BINARY;
     86  } else {
     87    fmode |= _O_TEXT;
     88  }
     89  if (mode & trunc) {
     90    fmode |= _O_CREAT | _O_TRUNC;
     91  }
     92  int fd = _wopen(filename, fmode);
     93  mFileBuf = MakeUnique<__gnu_cxx::stdio_filebuf<char>>(fd, mode);
     94  std::ostream::rdbuf(mFileBuf.get());
     95 }
     96 
     97 #elif defined(XP_WIN)
     98 class IFStream : public std::ifstream {
     99 public:
    100  explicit IFStream(char16ptr_t filename, openmode mode = in)
    101      : std::ifstream(filename, mode) {}
    102 
    103  void open(char16ptr_t filename, openmode mode = in) {
    104    std::ifstream::open(filename, mode);
    105  }
    106 };
    107 
    108 class OFStream : public std::ofstream {
    109 public:
    110  explicit OFStream(char16ptr_t filename, openmode mode = out)
    111      : std::ofstream(filename, mode) {}
    112 
    113  void open(char16ptr_t filename, openmode mode = out) {
    114    std::ofstream::open(filename, mode);
    115  }
    116 };
    117 #else
    118 using IFStream = std::ifstream;
    119 using OFStream = std::ofstream;
    120 #endif
    121 
    122 }  // namespace mozilla
    123 
    124 #endif /* mozilla_FStream_h */