std::basic_filebuf::open(const wchar_t *) isn't part of C++ standard and it's only present for MSVC but it's not present in libstdc++ (MinGW) so we implement this functionality using GNU stdio_filebuf extension and _wfopen function. --- Source/kwsys/FStream.hxx.in | 117 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 109 insertions(+), 8 deletions(-)
diff --git a/Source/kwsys/FStream.hxx.in b/Source/kwsys/FStream.hxx.in index 681e4d8..f39f95a 100644 --- a/Source/kwsys/FStream.hxx.in +++ b/Source/kwsys/FStream.hxx.in @@ -14,33 +14,76 @@ #include <@KWSYS_NAMESPACE@/Encoding.hxx> #include <fstream> +#if defined(_WIN32) && !defined(_MSC_VER) +#include <ext/stdio_filebuf.h> +#endif namespace @KWSYS_NAMESPACE@ { -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#if defined(_WIN32) # if defined(_NOEXCEPT) # define @KWSYS_NAMESPACE@_FStream_NOEXCEPT _NOEXCEPT # else # define @KWSYS_NAMESPACE@_FStream_NOEXCEPT # endif + +#if defined(_MSC_VER) + template<typename CharType,typename Traits> class basic_filebuf : public std::basic_filebuf<CharType,Traits> { +# if _MSC_VER >= 1400 public: typedef std::basic_filebuf<CharType,Traits> my_base_type; basic_filebuf *open(char const *s,std::ios_base::openmode mode) { + const std::wstring wstr = Encoding::ToWide(s); return static_cast<basic_filebuf*>( - my_base_type::open(Encoding::ToWide(s).c_str(), mode) + my_base_type::open(wstr.c_str(), mode) ); } +# else +# pragma message("Warning! Opening non-ASCII files might fail!") +# endif + }; +#else + + inline const 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) { + cmode += L"w"; + plus = mode & std::ios_base::in ? true : false; + } else { + cmode += L"r"; + } + if (mode & std::ios_base::binary) { + cmode += L"b"; + } else { + cmode += L"t"; + } + if (plus) { + cmode += L"+"; + } + return cmode; + }; + +#endif + template<typename CharType,typename Traits = std::char_traits<CharType> > class basic_ifstream : public std::basic_istream<CharType,Traits> { public: +#if defined(_MSC_VER) typedef basic_filebuf<CharType,Traits> internal_buffer_type; +#else + typedef __gnu_cxx::stdio_filebuf<CharType,Traits> internal_buffer_type; +#endif typedef std::basic_istream<CharType,Traits> internal_stream_type; basic_ifstream() : internal_stream_type(new internal_buffer_type()) @@ -56,7 +99,24 @@ namespace @KWSYS_NAMESPACE@ } 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)) + mode = mode | std::ios_base::in; +#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); + this->set_rdbuf(buf_); + success = true; + } +#endif + if(!success) { this->setstate(std::ios_base::failbit); } @@ -75,7 +135,14 @@ namespace @KWSYS_NAMESPACE@ } void close() { - if(!buf_->close()) + bool success = buf_->close() != 0; +#if !defined(_MSC_VER) + if (file_) { + success = fclose(file_) == 0 ? success : false; + file_ = 0; + } +#endif + if(!success) { this->setstate(std::ios_base::failbit); } @@ -92,19 +159,26 @@ namespace @KWSYS_NAMESPACE@ ~basic_ifstream() @KWSYS_NAMESPACE@_FStream_NOEXCEPT { - buf_->close(); + close(); delete buf_; } private: internal_buffer_type* buf_; +#if !defined(_MSC_VER) + FILE *file_ = 0; +#endif }; template<typename CharType,typename Traits = std::char_traits<CharType> > class basic_ofstream : public std::basic_ostream<CharType,Traits> { public: +#if defined(_MSC_VER) typedef basic_filebuf<CharType,Traits> internal_buffer_type; +#else + typedef __gnu_cxx::stdio_filebuf<CharType,Traits> internal_buffer_type; +#endif typedef std::basic_ostream<CharType,Traits> internal_stream_type; basic_ofstream() : internal_stream_type(new internal_buffer_type()) @@ -119,7 +193,24 @@ class basic_ofstream : public std::basic_ostream<CharType,Traits> } void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::out) { - if(!buf_->open(file_name,mode | std::ios_base::out)) + mode = mode | std::ios_base::out; +#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); + this->set_rdbuf(buf_); + success = true; + } +#endif + if(!success) { this->setstate(std::ios_base::failbit); } @@ -138,7 +229,14 @@ class basic_ofstream : public std::basic_ostream<CharType,Traits> } void close() { - if(!buf_->close()) + bool success = buf_->close() != 0; +#if !defined(_MSC_VER) + if (file_) { + success = fclose(file_) == 0 ? success : false; + file_ = 0; + } +#endif + if(!success) { this->setstate(std::ios_base::failbit); } @@ -154,12 +252,15 @@ class basic_ofstream : public std::basic_ostream<CharType,Traits> } ~basic_ofstream() @KWSYS_NAMESPACE@_FStream_NOEXCEPT { - buf_->close(); + close(); delete buf_; } private: internal_buffer_type* buf_; +#if !defined(_MSC_VER) + FILE *file_ = 0; +#endif }; typedef basic_ifstream<char> ifstream; -- 2.9.0 -- 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