[cmake-developers] [PATCH v5 1/2] Refactor FStream (basic_ifstream and basic_ofstream classes)

2016-07-16 Thread Dāvis Mosāns
Use common basic_efilebuf for both to reduce code duplication.
---
 Source/kwsys/FStream.hxx.in | 164 +---
 1 file changed, 95 insertions(+), 69 deletions(-)

diff --git a/Source/kwsys/FStream.hxx.in b/Source/kwsys/FStream.hxx.in
index 681e4d8..248b0cb 100644
--- a/Source/kwsys/FStream.hxx.in
+++ b/Source/kwsys/FStream.hxx.in
@@ -30,136 +30,162 @@ namespace @KWSYS_NAMESPACE@
   typedef std::basic_filebuf my_base_type;
   basic_filebuf *open(char const *s,std::ios_base::openmode mode)
   {
+const std::wstring wstr = Encoding::ToWide(s);
 return static_cast(
-  my_base_type::open(Encoding::ToWide(s).c_str(), mode)
+  my_base_type::open(wstr.c_str(), mode)
   );
   }
   };
 
   template >
-  class basic_ifstream : public std::basic_istream
+  class basic_efilebuf
   {
+public:
+  typedef basic_filebuf internal_buffer_type;
+
+  basic_efilebuf()
+  {
+buf_ = 0;
+  }
+
+  bool _open(char const *file_name,std::ios_base::openmode mode)
+  {
+if (is_open()) {
+  return false;
+}
+const bool success = buf_->open(file_name,mode) != 0;
+return success;
+  }
+
+  bool is_open()
+  {
+if (!buf_) {
+  return false;
+}
+return buf_->is_open();
+  }
+
+  bool is_open() const
+  {
+if (!buf_) {
+  return false;
+}
+return buf_->is_open();
+  }
+
+  bool _close()
+  {
+bool success = false;
+if (buf_) {
+  success = buf_->close() != 0;
+}
+return success;
+  }
+
+  static void _set_state(bool success, std::basic_ios 
*ios)
+  {
+if (!success) {
+  ios->setstate(std::ios_base::failbit);
+} else {
+  ios->clear();
+}
+  }
+
+  ~basic_efilebuf()
+ {
+   if (buf_) {
+ delete buf_;
+   }
+ }
+
+protected:
+  internal_buffer_type* buf_;
+  };
+
+template >
+class basic_ifstream : public std::basic_istream,
+   public basic_efilebuf
+{
+  using basic_efilebuf::is_open;
+
   public:
-typedef basic_filebuf internal_buffer_type;
+typedef typename basic_efilebuf::internal_buffer_type 
internal_buffer_type;
 typedef std::basic_istream internal_stream_type;
 
 basic_ifstream() : internal_stream_type(new internal_buffer_type())
 {
-  buf_ = static_cast(internal_stream_type::rdbuf());
+  this->buf_ = static_cast(internal_stream_type::rdbuf());
 }
 explicit basic_ifstream(char const *file_name,
 std::ios_base::openmode mode = std::ios_base::in)
   : internal_stream_type(new internal_buffer_type())
 {
-  buf_ = static_cast(internal_stream_type::rdbuf());
+  this->buf_ = static_cast(internal_stream_type::rdbuf());
   open(file_name,mode);
 }
+
 void open(char const *file_name,std::ios_base::openmode mode = 
std::ios_base::in)
 {
-  if(!buf_->open(file_name,mode | std::ios_base::in))
-{
-this->setstate(std::ios_base::failbit);
-}
-  else
-{
-this->clear();
-}
-}
-bool is_open()
-{
-  return buf_->is_open();
-}
-bool is_open() const
-{
-  return buf_->is_open();
+  mode = mode | std::ios_base::in;
+  this->_set_state(this->_open(file_name, mode), this);
 }
+
 void close()
 {
-  if(!buf_->close())
-{
-this->setstate(std::ios_base::failbit);
-}
-  else
-  {
-this->clear();
-  }
+  this->_set_state(this->_close(), this);
 }
 
 internal_buffer_type *rdbuf() const
 {
-  return buf_;
+  return this->buf_;
 }
 
 ~basic_ifstream() @KWSYS_NAMESPACE@_FStream_NOEXCEPT
 {
-  buf_->close();
-  delete buf_;
+  close();
 }
-
-  private:
-internal_buffer_type* buf_;
 };
 
 template >
-class basic_ofstream : public std::basic_ostream
+class basic_ofstream : public std::basic_ostream,
+   public basic_efilebuf
 {
+  using basic_efilebuf::is_open;
+
   public:
-  typedef basic_filebuf internal_buffer_type;
+  typedef typename basic_efilebuf::internal_buffer_type 
internal_buffer_type;
   typedef std::basic_ostream internal_stream_type;
 
   basic_ofstream() : internal_stream_type(new internal_buffer_type())
   {
-  buf_ = static_cast(internal_stream_type::rdbuf());
+this->buf_ = static_cast(internal_stream_type::rdbuf());
   }
   explicit basic_ofstream(char const *file_name,std::ios_base::openmode mode = 
std::ios_base::out) :
   internal_stream_type(new internal_buffer_type())
   {
-buf_ = static_cast(internal_stream_type::rdbuf());
+this->buf_ = static_cast(internal_stream_type::rdbuf());
 open(file_name,mode);
   }
   void open(char const *file_name,std::ios_base::openmode mode = 
std::ios_base::out)
   {

[cmake-developers] [PATCH v5 2/2] Add MinGW support for FStream

2016-07-16 Thread Dāvis Mosāns
std::basic_filebuf::open(const wchar_t *) isn't part of C++ standard
and it's only present for MSVC but it isn't present in libstdc++ (MinGW)
so we implement this functionality using GNU libstdc++ stdio_filebuf
extension and _wfopen function.
---
 Source/kwsys/CMakeLists.txt|  5 ++
 Source/kwsys/Configure.hxx.in  |  7 ++-
 Source/kwsys/FStream.hxx.in| 86 ++
 Source/kwsys/kwsysPlatformTestsCXX.cxx |  6 +++
 bootstrap  | 11 +
 5 files changed, 105 insertions(+), 10 deletions(-)

diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index 33a97e6..297a7bd 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -636,6 +636,11 @@ IF(KWSYS_USE_SystemInformation)
   ENDIF()
 ENDIF()
 
+IF(KWSYS_USE_FStream)
+  KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H
+"Checking whether  is available" DIRECT)
+ENDIF()
+
 #-
 # Choose a directory for the generated headers.
 IF(NOT KWSYS_HEADER_ROOT)
diff --git a/Source/kwsys/Configure.hxx.in b/Source/kwsys/Configure.hxx.in
index ff8e49d..4ce680d 100644
--- a/Source/kwsys/Configure.hxx.in
+++ b/Source/kwsys/Configure.hxx.in
@@ -17,6 +17,8 @@
 
 /* Whether wstring is available.  */
 #define @KWSYS_NAMESPACE@_STL_HAS_WSTRING @KWSYS_STL_HAS_WSTRING@
+/* Whether  is available. */
+#define @KWSYS_NAMESPACE@_CXX_HAS_EXT_STDIO_FILEBUF_H 
@KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H@
 
 /* If building a C++ file in kwsys itself, give the source file
access to the macros without a configured namespace.  */
@@ -24,8 +26,9 @@
 # if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
 #  define kwsys @KWSYS_NAMESPACE@
 # endif
-# define KWSYS_NAME_IS_KWSYS@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-# define KWSYS_STL_HAS_WSTRING  @KWSYS_NAMESPACE@_STL_HAS_WSTRING
+# define KWSYS_NAME_IS_KWSYS   @KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# define KWSYS_STL_HAS_WSTRING @KWSYS_NAMESPACE@_STL_HAS_WSTRING
+# define KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H 
@KWSYS_NAMESPACE@_CXX_HAS_EXT_STDIO_FILEBUF_H
 #endif
 
 #endif
diff --git a/Source/kwsys/FStream.hxx.in b/Source/kwsys/FStream.hxx.in
index 248b0cb..c13f91d 100644
--- a/Source/kwsys/FStream.hxx.in
+++ b/Source/kwsys/FStream.hxx.in
@@ -12,20 +12,32 @@
 #ifndef @KWSYS_NAMESPACE@_FStream_hxx
 #define @KWSYS_NAMESPACE@_FStream_hxx
 
+#include <@KWSYS_NAMESPACE@/Configure.hxx>
 #include <@KWSYS_NAMESPACE@/Encoding.hxx>
 #include 
+#if defined(_WIN32)
+#  if !defined(_MSC_VER) && @KWSYS_NAMESPACE@_CXX_HAS_EXT_STDIO_FILEBUF_H
+#include 
+#  elif !defined(_MSC_VER) || _MSC_VER < 1400
+#pragma message("WARNING: Opening non-ASCII files might fail!")
+#  endif
+#endif
 
 namespace @KWSYS_NAMESPACE@
 {
-#if defined(_MSC_VER) && _MSC_VER >= 1400
+#if defined(_WIN32) && (defined(_MSC_VER) || 
@KWSYS_NAMESPACE@_CXX_HAS_EXT_STDIO_FILEBUF_H)
 # if defined(_NOEXCEPT)
 #  define @KWSYS_NAMESPACE@_FStream_NOEXCEPT _NOEXCEPT
 # else
 #  define @KWSYS_NAMESPACE@_FStream_NOEXCEPT
 # endif
+
+#if defined(_MSC_VER)
+
   template
   class basic_filebuf : public std::basic_filebuf
   {
+# if _MSC_VER >= 1400
 public:
   typedef std::basic_filebuf my_base_type;
   basic_filebuf *open(char const *s,std::ios_base::openmode mode)
@@ -35,25 +47,73 @@ namespace @KWSYS_NAMESPACE@
   my_base_type::open(wstr.c_str(), mode)
   );
   }
+# endif
+  };
+
+#else
+
+  inline std::wstring getcmode(const std::ios_base::openmode mode) {
+std::wstring cmode;
+bool plus = false;
+if (mode & std::ios_base::app) {
+  cmode += L"a";
+  plus = mode & std::ios_base::in ? true : false;
+} else if (mode & std::ios_base::trunc ||
+(mode & std::ios_base::out && (mode & std::ios_base::in) == 
0)) {
+  cmode += L"w";
+  plus = mode & std::ios_base::in ? true : false;
+} else {
+  cmode += L"r";
+  plus = mode & std::ios_base::out ? true : false;
+}
+if (plus) {
+  cmode += L"+";
+}
+if (mode & std::ios_base::binary) {
+  cmode += L"b";
+} else {
+  cmode += L"t";
+}
+return cmode;
   };
 
+#endif
+
   template >
   class basic_efilebuf
   {
 public:
+#if defined(_MSC_VER)
   typedef basic_filebuf internal_buffer_type;
+#else
+  typedef __gnu_cxx::stdio_filebuf internal_buffer_type;
+#endif
 
-  basic_efilebuf()
+  basic_efilebuf() : file_(0)
   {
 buf_ = 0;
   }
 
   bool _open(char const *file_name,std::ios_base::openmode mode)
   {
-if (is_open()) {
+if (is_open() || file_) {
   return false;
 }
+#if defined(_MSC_VER)
 const bool success = buf_->open(file_name,mode) != 0;
+#else
+const std::wstring wstr = Encoding::ToWide(file_name);
+bool success = false;
+std::wstring cmode = getcmode(mode);
+file_ = _wfopen(wstr.c_str(), cm