Re: [cmake-developers] [PATCH v4] Add MinGW support for FStream

2016-07-13 Thread Brad King
On 07/12/2016 10:05 PM, Dāvis Mosāns wrote:
> 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.

Thanks.

> +IF(KWSYS_USE_FStream)
> +  INCLUDE(CheckIncludeFileCXX)
> +  CHECK_INCLUDE_FILE_CXX(ext/stdio_filebuf.h HAVE_EXT_STDIO_FILEBUF_H)
> +  IF(HAVE_EXT_STDIO_FILEBUF_H)
> +add_definitions(-DHAVE_EXT_STDIO_FILEBUF_H=1)
> +  ENDIF()
> +ENDIF()

Please use KWSYS_PLATFORM_CXX_TEST with kwsysPlatformTestsCXX.cxx to
do this check, and then store the result in Configure.hxx so that
KWSys clients do not have to repeat the check.  See the existing
case of KWSYS_STL_HAS_WSTRING for an example.  We could name the
new check KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H.

> -  class basic_ifstream : public std::basic_istream
> +  class basic_efilebuf
[snip]
> +class basic_ifstream : public std::basic_istream,
> +   public basic_efilebuf

Please split this refactoring out into a preceding commit.

Thanks,
-Brad

-- 

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: 
http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more 
information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake-developers

[cmake-developers] [PATCH v4] Add MinGW support for FStream

2016-07-12 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.
---
 CMakeLists.txt  |  14 +++
 Source/kwsys/CMakeLists.txt |   8 ++
 Source/kwsys/FStream.hxx.in | 235 +++-
 3 files changed, 187 insertions(+), 70 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 792b5a5..b53c6b1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -273,6 +273,20 @@ macro (CMAKE_BUILD_UTILITIES)
 CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestSharedForward 
"${kwsys_folder}")
   endif()
 
+  IF(KWSYS_USE_SystemTools)
+SET(KWSYS_USE_Directory 1)
+SET(KWSYS_USE_FStream 1)
+SET(KWSYS_USE_Encoding 1)
+  ENDIF()
+
+  IF(KWSYS_USE_FStream)
+INCLUDE(CheckIncludeFileCXX)
+CHECK_INCLUDE_FILE_CXX(ext/stdio_filebuf.h HAVE_EXT_STDIO_FILEBUF_H)
+IF(HAVE_EXT_STDIO_FILEBUF_H)
+  add_definitions(-DHAVE_EXT_STDIO_FILEBUF_H=1)
+ENDIF()
+  ENDIF()
+
   #-
   # Setup third-party libraries.
   # Everything in the tree should be able to include files from the
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index 33a97e6..02ba2db 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -636,6 +636,14 @@ IF(KWSYS_USE_SystemInformation)
   ENDIF()
 ENDIF()
 
+IF(KWSYS_USE_FStream)
+  INCLUDE(CheckIncludeFileCXX)
+  CHECK_INCLUDE_FILE_CXX(ext/stdio_filebuf.h HAVE_EXT_STDIO_FILEBUF_H)
+  IF(HAVE_EXT_STDIO_FILEBUF_H)
+add_definitions(-DHAVE_EXT_STDIO_FILEBUF_H=1)
+  ENDIF()
+ENDIF()
+
 #-
 # Choose a directory for the generated headers.
 IF(NOT KWSYS_HEADER_ROOT)
diff --git a/Source/kwsys/FStream.hxx.in b/Source/kwsys/FStream.hxx.in
index 681e4d8..eb911c9 100644
--- a/Source/kwsys/FStream.hxx.in
+++ b/Source/kwsys/FStream.hxx.in
@@ -14,152 +14,247 @@
 
 #include <@KWSYS_NAMESPACE@/Encoding.hxx>
 #include 
+#if defined(_WIN32)
+#  if !defined(_MSC_VER) && defined(HAVE_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) || defined(HAVE_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)
   {
+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)
   );
   }
+# 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_ifstream : public std::basic_istream
+  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() : file_(0)
+  {
+buf_ = 0;
+  }
+
+  bool _open(char const *file_name,std::ios_base::openmode mode)
+  {
+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(), cmode.c_str());
+if (file_) {
+  if (buf_) {
+delete buf_;
+  }
+  buf_ = new internal_buffer_type(file_, mode);
+  success = true;
+}
+#endif
+