[cmake-developers] [PATCH v5 1/2] Refactor FStream (basic_ifstream and basic_ofstream classes)
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
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