>(loc).always_noconv())
+ throw std::runtime_error("Converting codecvts are not supported");
}
-
-#ifdef BOOST_NOWIDE_DEBUG_FILEBUF
- void print_buf(char *b,char *p,char *e)
- {
- std::cerr << "-- Is Null: " << (b==0) << std::endl;;
- if(b==0)
- return;
- if(e != 0)
- std::cerr << "-- Total: " << e - b <<" offset from start " << p - b << std::endl;
- else
- std::cerr << "-- Total: " << p - b << std::endl;
-
- std::cerr << "-- [";
- for(char *ptr = b;ptrprint_state();
- }
- ~print_guard()
+ assert(n >= 0);
+ // Maximum compatibility: Discard all local buffers and use user-provided values
+ // Users should call sync() before or better use it before any IO is done or any file is opened
+ setg(NULL, NULL, NULL);
+ setp(NULL, NULL);
+ if(owns_buffer_)
{
- std::cerr << "Out: " << f << std::endl;
- self->print_state();
+ delete[] buffer_;
+ owns_buffer_ = false;
}
- basic_filebuf *self;
- char const *f;
- };
-#else
-#endif
-
- int overflow(int c)
+ buffer_ = s;
+ buffer_size_ = (n >= 0) ? static_cast(n) : 0;
+ return this;
+ }
+
+ int overflow(int c = EOF) override
{
-#ifdef BOOST_NOWIDE_DEBUG_FILEBUF
- print_guard g(this,__FUNCTION__);
-#endif
- if(!file_)
+ if(!(mode_ & (std::ios_base::out | std::ios_base::app)))
return EOF;
-
- if(fixg() < 0)
+
+ if(!stop_reading())
return EOF;
size_t n = pptr() - pbase();
- if(n > 0) {
- if(::fwrite(pbase(),1,n,file_) < n)
- return -1;
- fflush(file_);
- }
-
- if(buffer_size_ > 0) {
- make_buffer();
- setp(buffer_,buffer_+buffer_size_);
- if(c!=EOF)
- sputc(c);
- }
- else if(c!=EOF) {
- if(::fputc(c,file_)==EOF)
+ if(n > 0)
+ {
+ if(std::fwrite(pbase(), 1, n, file_) != n)
+ return EOF;
+ setp(buffer_, buffer_ + buffer_size_);
+ if(c != EOF)
+ {
+ *buffer_ = Traits::to_char_type(c);
+ pbump(1);
+ }
+ } else if(c != EOF)
+ {
+ if(buffer_size_ > 0)
+ {
+ make_buffer();
+ setp(buffer_, buffer_ + buffer_size_);
+ *buffer_ = Traits::to_char_type(c);
+ pbump(1);
+ } else if(std::fputc(c, file_) == EOF)
+ {
return EOF;
- fflush(file_);
+ } else if(!pptr())
+ {
+ // Set to dummy value so we know we have written something
+ setp(last_char_, last_char_);
+ }
}
- return 0;
+ return Traits::not_eof(c);
}
-
-
- int sync()
+
+ int sync() override
{
- return overflow(EOF);
+ if(!file_)
+ return 0;
+ bool result;
+ if(pptr())
+ {
+ result = overflow() != EOF;
+ // Only flush if anything was written, otherwise behavior of fflush is undefined
+ if(std::fflush(file_) != 0)
+ return result = false;
+ } else
+ result = stop_reading();
+ return result ? 0 : -1;
}
- int underflow()
+ int underflow() override
{
-#ifdef BOOST_NOWIDE_DEBUG_FILEBUF
- print_guard g(this,__FUNCTION__);
-#endif
- if(!file_)
+ if(!(mode_ & std::ios_base::in))
return EOF;
- if(fixp() < 0)
+ if(!stop_writing())
return EOF;
- if(buffer_size_ == 0) {
- int c = ::fgetc(file_);
- if(c==EOF) {
+ // In text mode we cannot use a buffer size of more than 1 (i.e. single char only)
+ // This is due to the need to seek back in case of a sync to "put back" unread chars.
+ // However determining the number of chars to seek back is impossible in case there are newlines
+ // as we cannot know if those were converted.
+ if(buffer_size_ == 0 || !(mode_ & std::ios_base::binary))
+ {
+ const int c = std::fgetc(file_);
+ if(c == EOF)
+ return EOF;
+ last_char_[0] = Traits::to_char_type(c);
+ setg(last_char_, last_char_, last_char_ + 1);
+ } else
+ {
+ make_buffer();
+ const size_t n = std::fread(buffer_, 1, buffer_size_, file_);
+ setg(buffer_, buffer_, buffer_ + n);
+ if(n == 0)
return EOF;
- }
- last_char_ = c;
- setg(&last_char_,&last_char_,&last_char_ + 1);
- return c;
}
- make_buffer();
- size_t n = ::fread(buffer_,1,buffer_size_,file_);
- setg(buffer_,buffer_,buffer_+n);
- if(n == 0)
- return EOF;
- return std::char_traits::to_int_type(*gptr());
+ return Traits::to_int_type(*gptr());
}
- int pbackfail(int)
+ int pbackfail(int c = EOF) override
{
- return pubseekoff(-1,std::ios::cur);
+ if(!(mode_ & std::ios_base::in))
+ return EOF;
+ if(!stop_writing())
+ return EOF;
+ if(gptr() > eback())
+ gbump(-1);
+ else if(seekoff(-1, std::ios_base::cur) != std::streampos(std::streamoff(-1)))
+ {
+ if(underflow() == EOF)
+ return EOF;
+ } else
+ return EOF;
+
+ // Case 1: Caller just wanted space for 1 char
+ if(c == EOF)
+ return Traits::not_eof(c);
+ // Case 2: Caller wants to put back different char
+ // gptr now points to the (potentially newly read) previous char
+ if(*gptr() != c)
+ *gptr() = Traits::to_char_type(c);
+ return Traits::not_eof(c);
}
std::streampos seekoff(std::streamoff off,
- std::ios_base::seekdir seekdir,
- std::ios_base::openmode /*m*/)
+ std::ios_base::seekdir seekdir,
+ std::ios_base::openmode = std::ios_base::in | std::ios_base::out) override
{
-#ifdef BOOST_NOWIDE_DEBUG_FILEBUF
- print_guard g(this,__FUNCTION__);
-#endif
if(!file_)
return EOF;
- if(fixp() < 0 || fixg() < 0)
+ // Switching between input<->output requires a seek
+ // So do NOT optimize for seekoff(0, cur) as No-OP
+
+ // On some implementations a seek also flushes, so do a full sync
+ if(sync() != 0)
return EOF;
- if(seekdir == std::ios_base::cur) {
- if( ::fseek(file_,off,SEEK_CUR) < 0)
- return EOF;
- }
- else if(seekdir == std::ios_base::beg) {
- if( ::fseek(file_,off,SEEK_SET) < 0)
- return EOF;
- }
- else if(seekdir == std::ios_base::end) {
- if( ::fseek(file_,off,SEEK_END) < 0)
- return EOF;
+ int whence;
+ switch(seekdir)
+ {
+ case std::ios_base::beg: whence = SEEK_SET; break;
+ case std::ios_base::cur: whence = SEEK_CUR; break;
+ case std::ios_base::end: whence = SEEK_END; break;
+ default: assert(false); return EOF;
}
- else
- return -1;
- return ftell(file_);
+ if(detail::fseek(file_, off, whence) != 0)
+ return EOF;
+ return detail::ftell(file_);
}
- std::streampos seekpos(std::streampos off,std::ios_base::openmode m)
+ std::streampos seekpos(std::streampos pos,
+ std::ios_base::openmode m = std::ios_base::in | std::ios_base::out) override
{
- return seekoff(std::streamoff(off),std::ios_base::beg,m);
+ // Standard mandates "as-if fsetpos", but assume the effect is the same as fseek
+ return seekoff(pos, std::ios_base::beg, m);
}
+ void imbue(const std::locale& loc) override
+ {
+ validate_cvt(loc);
+ }
+
private:
- int fixg()
+ /// Stop reading adjusting the file pointer if necessary
+ /// Postcondition: gptr() == NULL
+ bool stop_reading()
{
- if(gptr()!=egptr()) {
- std::streamsize off = gptr() - egptr();
- setg(0,0,0);
- if(fseek(file_,off,SEEK_CUR) != 0)
- return -1;
- }
- setg(0,0,0);
- return 0;
+ if(!gptr())
+ return true;
+ const auto off = gptr() - egptr();
+ setg(0, 0, 0);
+ if(!off)
+ return true;
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare"
+#endif
+ // coverity[result_independent_of_operands]
+ if(off > std::numeric_limits::max())
+ return false;
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+ return detail::fseek(file_, static_cast(off), SEEK_CUR) == 0;
}
-
- int fixp()
+
+ /// Stop writing. If any bytes are to be written, writes them to file
+ /// Postcondition: pptr() == NULL
+ bool stop_writing()
{
- if(pptr()!=0) {
- int r = sync();
- setp(0,0);
- return r;
+ if(pptr())
+ {
+ const char* const base = pbase();
+ const size_t n = pptr() - base;
+ setp(0, 0);
+ if(n && std::fwrite(base, 1, n, file_) != n)
+ return false;
}
- return 0;
+ return true;
}
- void reset(FILE *f = 0)
+ void reset(FILE* f = 0)
{
sync();
- if(file_) {
+ if(file_)
+ {
fclose(file_);
file_ = 0;
}
file_ = f;
}
-
-
- static wchar_t const *get_mode(std::ios_base::openmode mode)
+
+ static const wchar_t* get_mode(std::ios_base::openmode mode)
{
//
// done according to n2914 table 106 27.9.1.4
@@ -384,32 +459,32 @@ namespace nowide {
return L"a+b";
if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::app))
return L"a+b";
- return 0;
+ return 0;
}
-
+
size_t buffer_size_;
- char *buffer_;
- FILE *file_;
- bool own_;
- char last_char_;
+ char* buffer_;
+ FILE* file_;
+ bool owns_buffer_;
+ char last_char_[1];
std::ios::openmode mode_;
};
-
+
///
/// \brief Convenience typedef
///
- typedef basic_filebuf filebuf;
-
- #endif // windows
-
-} // nowide
-} // namespace boost
+ using filebuf = basic_filebuf;
-#ifdef BOOST_MSVC
-# pragma warning(pop)
-#endif
+ /// Swap the basic_filebuf instances
+ template
+ void swap(basic_filebuf& lhs, basic_filebuf& rhs)
+ {
+ lhs.swap(rhs);
+ }
+#endif // windows
-#endif
+} // namespace nowide
+} // namespace boost
-// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
+#endif
diff --git a/xs/src/boost/nowide/filesystem.hpp b/xs/src/boost/nowide/filesystem.hpp
new file mode 100644
index 0000000000..68e398d798
--- /dev/null
+++ b/xs/src/boost/nowide/filesystem.hpp
@@ -0,0 +1,27 @@
+//
+// Copyright (c) 2012 Artyom Beilis (Tonkikh)
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+#ifndef BOOST_NOWIDE_INTEGRATION_FILESYSTEM_HPP_INCLUDED
+#define BOOST_NOWIDE_INTEGRATION_FILESYSTEM_HPP_INCLUDED
+
+#include
+#include
+
+namespace boost {
+namespace nowide {
+ ///
+ /// Install utf8_codecvt facet into boost::filesystem::path such all char strings are interpreted as utf-8 strings
+ ///
+ inline std::locale nowide_filesystem()
+ {
+ std::locale tmp = std::locale(std::locale(), new boost::nowide::utf8_codecvt());
+ return boost::filesystem::path::imbue(tmp);
+ }
+} // namespace nowide
+} // namespace boost
+
+#endif
diff --git a/xs/src/boost/nowide/fstream.hpp b/xs/src/boost/nowide/fstream.hpp
old mode 100755
new mode 100644
index 35604d277b..ca946f310c
--- a/xs/src/boost/nowide/fstream.hpp
+++ b/xs/src/boost/nowide/fstream.hpp
@@ -2,282 +2,357 @@
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
-// accompanying file LICENSE_1_0.txt or copy at
+// accompanying file LICENSE or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
-#ifndef BOOST_NOWIDE_FSTREAM_INCLUDED_HPP
-#define BOOST_NOWIDE_FSTREAM_INCLUDED_HPP
+#ifndef BOOST_NOWIDE_FSTREAM_HPP_INCLUDED
+#define BOOST_NOWIDE_FSTREAM_HPP_INCLUDED
-//#include
-#include
-#include
-#include
-#include
-#include
+#include
+#include
#include
+#include
+#include
+#include
namespace boost {
-///
-/// \brief This namespace includes implementation of the standard library functions
-/// such that they accept UTF-8 strings on Windows. On other platforms it is just an alias
-/// of std namespace (i.e. not on Windows)
-///
namespace nowide {
-#if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_FSTREAM_TESTS) && !defined(BOOST_NOWIDE_DOXYGEN)
+ /// \cond INTERNAL
+ namespace detail {
+ // clang-format off
+ struct StreamTypeIn
+ {
+ static std::ios_base::openmode mode() { return std::ios_base::in; }
+ static std::ios_base::openmode mode_modifier() { return mode(); }
+ template
+ struct stream_base{
+ using type = std::basic_istream;
+ };
+ };
+ struct StreamTypeOut
+ {
+ static std::ios_base::openmode mode() { return std::ios_base::out; }
+ static std::ios_base::openmode mode_modifier() { return mode(); }
+ template
+ struct stream_base{
+ using type = std::basic_ostream;
+ };
+ };
+ struct StreamTypeInOut
+ {
+ static std::ios_base::openmode mode() { return std::ios_base::in | std::ios_base::out; }
+ static std::ios_base::openmode mode_modifier() { return std::ios_base::openmode(); }
+ template
+ struct stream_base{
+ using type = std::basic_iostream;
+ };
+ };
+ // clang-format on
- using std::basic_ifstream;
- using std::basic_ofstream;
- using std::basic_fstream;
- using std::ifstream;
- using std::ofstream;
- using std::fstream;
+ /// Base class for all basic_*fstream classes
+ /// Contains basic_filebuf instance so its pointer can be used to construct basic_*stream
+ /// Provides common functions to reduce boilerplate code including inheriting from
+ /// the correct std::basic_[io]stream class and initializing it
+ /// \tparam T_StreamType One of StreamType* above.
+ /// Class used instead of value, because openmode::operator| may not be constexpr
+ /// \tparam FileBufType Discriminator to force a differing ABI if depending on the contained filebuf
+ template
+ class fstream_impl;
+
+ } // namespace detail
+ /// \endcond
-#else
///
/// \brief Same as std::basic_ifstream but accepts UTF-8 strings under Windows
///
- template >
- class basic_ifstream : public std::basic_istream
+ template>
+ class basic_ifstream : public detail::fstream_impl
{
+ using fstream_impl = detail::fstream_impl;
+
public:
- typedef basic_filebuf internal_buffer_type;
- typedef std::basic_istream internal_stream_type;
+ basic_ifstream()
+ {}
- basic_ifstream() :
- internal_stream_type(0)
+ explicit basic_ifstream(const char* file_name, std::ios_base::openmode mode = std::ios_base::in)
{
- buf_.reset(new internal_buffer_type());
- std::ios::rdbuf(buf_.get());
+ open(file_name, mode);
}
-
- explicit basic_ifstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::in) :
- internal_stream_type(0)
+#if BOOST_NOWIDE_USE_WCHAR_OVERLOADS
+ explicit basic_ifstream(const wchar_t* file_name, std::ios_base::openmode mode = std::ios_base::in)
{
- buf_.reset(new internal_buffer_type());
- std::ios::rdbuf(buf_.get());
- open(file_name,mode);
- }
-
- explicit basic_ifstream(std::string const &file_name,std::ios_base::openmode mode = std::ios_base::in) :
- internal_stream_type(0)
- {
- buf_.reset(new internal_buffer_type());
- std::ios::rdbuf(buf_.get());
- open(file_name,mode);
+ open(file_name, mode);
}
+#endif
-
- void open(std::string const &file_name,std::ios_base::openmode mode = std::ios_base::in)
- {
- open(file_name.c_str(),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();
- }
- void close()
+ explicit basic_ifstream(const std::string& file_name, std::ios_base::openmode mode = std::ios_base::in)
{
- if(!buf_->close())
- this->setstate(std::ios_base::failbit);
- else
- this->clear();
+ open(file_name, mode);
}
- internal_buffer_type *rdbuf() const
+ template
+ explicit basic_ifstream(const Path& file_name,
+ detail::enable_if_path_t mode = std::ios_base::in)
{
- return buf_.get();
+ open(file_name, mode);
}
- ~basic_ifstream()
+ using fstream_impl::open;
+ using fstream_impl::is_open;
+ using fstream_impl::close;
+ using fstream_impl::rdbuf;
+ using fstream_impl::swap;
+ basic_ifstream(const basic_ifstream&) = delete;
+ basic_ifstream& operator=(const basic_ifstream&) = delete;
+ basic_ifstream(basic_ifstream&& other) noexcept : fstream_impl(std::move(other))
+ {}
+ basic_ifstream& operator=(basic_ifstream&& rhs) noexcept
{
- buf_->close();
+ fstream_impl::operator=(std::move(rhs));
+ return *this;
}
-
- private:
- boost::scoped_ptr buf_;
};
///
/// \brief Same as std::basic_ofstream but accepts UTF-8 strings under Windows
///
- template >
- class basic_ofstream : public std::basic_ostream
+ template>
+ class basic_ofstream : public detail::fstream_impl
{
- public:
- typedef basic_filebuf internal_buffer_type;
- typedef std::basic_ostream internal_stream_type;
+ using fstream_impl = detail::fstream_impl;
- basic_ofstream() :
- internal_stream_type(0)
- {
- buf_.reset(new internal_buffer_type());
- std::ios::rdbuf(buf_.get());
- }
- explicit basic_ofstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::out) :
- internal_stream_type(0)
- {
- buf_.reset(new internal_buffer_type());
- std::ios::rdbuf(buf_.get());
- open(file_name,mode);
- }
- explicit basic_ofstream(std::string const &file_name,std::ios_base::openmode mode = std::ios_base::out) :
- internal_stream_type(0)
- {
- buf_.reset(new internal_buffer_type());
- std::ios::rdbuf(buf_.get());
- open(file_name,mode);
- }
- void open(std::string const &file_name,std::ios_base::openmode mode = std::ios_base::out)
+ public:
+ basic_ofstream()
+ {}
+ explicit basic_ofstream(const char* file_name, std::ios_base::openmode mode = std::ios_base::out)
{
- open(file_name.c_str(),mode);
+ open(file_name, mode);
}
- void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::out)
+#if BOOST_NOWIDE_USE_WCHAR_OVERLOADS
+ explicit basic_ofstream(const wchar_t* file_name, std::ios_base::openmode mode = std::ios_base::out)
{
- if(!buf_->open(file_name,mode | std::ios_base::out)) {
- this->setstate(std::ios_base::failbit);
- }
- else {
- this->clear();
- }
+ open(file_name, mode);
}
- bool is_open()
- {
- return buf_->is_open();
- }
- bool is_open() const
+#endif
+ explicit basic_ofstream(const std::string& file_name, std::ios_base::openmode mode = std::ios_base::out)
{
- return buf_->is_open();
+ open(file_name, mode);
}
- void close()
+ template
+ explicit basic_ofstream(const Path& file_name,
+ detail::enable_if_path_t mode = std::ios_base::out)
{
- if(!buf_->close())
- this->setstate(std::ios_base::failbit);
- else
- this->clear();
+ open(file_name, mode);
}
- internal_buffer_type *rdbuf() const
- {
- return buf_.get();
- }
- ~basic_ofstream()
+ using fstream_impl::open;
+ using fstream_impl::is_open;
+ using fstream_impl::close;
+ using fstream_impl::rdbuf;
+ using fstream_impl::swap;
+ basic_ofstream(const basic_ofstream&) = delete;
+ basic_ofstream& operator=(const basic_ofstream&) = delete;
+ basic_ofstream(basic_ofstream&& other) noexcept : fstream_impl(std::move(other))
+ {}
+ basic_ofstream& operator=(basic_ofstream&& rhs)
{
- buf_->close();
+ fstream_impl::operator=(std::move(rhs));
+ return *this;
}
-
- private:
- boost::scoped_ptr buf_;
};
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable : 4250) // : inherits via dominance
+#endif
///
/// \brief Same as std::basic_fstream but accepts UTF-8 strings under Windows
///
-
- template >
- class basic_fstream : public std::basic_iostream
+ template>
+ class basic_fstream : public detail::fstream_impl
{
- public:
- typedef basic_filebuf internal_buffer_type;
- typedef std::basic_iostream internal_stream_type;
+ using fstream_impl = detail::fstream_impl;
- basic_fstream() :
- internal_stream_type(0)
- {
- buf_.reset(new internal_buffer_type());
- std::ios::rdbuf(buf_.get());
- }
- explicit basic_fstream(char const *file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::in) :
- internal_stream_type(0)
- {
- buf_.reset(new internal_buffer_type());
- std::ios::rdbuf(buf_.get());
- open(file_name,mode);
- }
- explicit basic_fstream(std::string const &file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::in) :
- internal_stream_type(0)
- {
- buf_.reset(new internal_buffer_type());
- std::ios::rdbuf(buf_.get());
- open(file_name,mode);
- }
- void open(std::string const &file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::out)
- {
- open(file_name.c_str(),mode);
- }
- void open(char const *file_name,std::ios_base::openmode mode = std::ios_base::out | std::ios_base::out)
+ public:
+ basic_fstream()
+ {}
+ explicit basic_fstream(const char* file_name,
+ std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
{
- if(!buf_->open(file_name,mode)) {
- this->setstate(std::ios_base::failbit);
- }
- else {
- this->clear();
- }
+ open(file_name, mode);
}
- bool is_open()
+#if BOOST_NOWIDE_USE_WCHAR_OVERLOADS
+ explicit basic_fstream(const wchar_t* file_name,
+ std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
{
- return buf_->is_open();
+ open(file_name, mode);
}
- bool is_open() const
+#endif
+ explicit basic_fstream(const std::string& file_name,
+ std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
{
- return buf_->is_open();
+ open(file_name, mode);
}
- void close()
+ template
+ explicit basic_fstream(const Path& file_name,
+ detail::enable_if_path_t mode = std::ios_base::in
+ | std::ios_base::out)
{
- if(!buf_->close())
- this->setstate(std::ios_base::failbit);
- else
- this->clear();
+ open(file_name, mode);
}
- internal_buffer_type *rdbuf() const
- {
- return buf_.get();
- }
- ~basic_fstream()
+ using fstream_impl::open;
+ using fstream_impl::is_open;
+ using fstream_impl::close;
+ using fstream_impl::rdbuf;
+ using fstream_impl::swap;
+ basic_fstream(const basic_fstream&) = delete;
+ basic_fstream& operator=(const basic_fstream&) = delete;
+ basic_fstream(basic_fstream&& other) noexcept : fstream_impl(std::move(other))
+ {}
+ basic_fstream& operator=(basic_fstream&& rhs)
{
- buf_->close();
+ fstream_impl::operator=(std::move(rhs));
+ return *this;
}
-
- private:
- boost::scoped_ptr buf_;
};
+ template
+ void swap(basic_ifstream& lhs, basic_ifstream& rhs)
+ {
+ lhs.swap(rhs);
+ }
+ template
+ void swap(basic_ofstream& lhs, basic_ofstream& rhs)
+ {
+ lhs.swap(rhs);
+ }
+ template
+ void swap(basic_fstream& lhs, basic_fstream& rhs)
+ {
+ lhs.swap(rhs);
+ }
///
- /// \brief Same as std::filebuf but accepts UTF-8 strings under Windows
+ /// Same as std::filebuf but accepts UTF-8 strings under Windows
///
- typedef basic_filebuf filebuf;
+ using filebuf = basic_filebuf;
///
/// Same as std::ifstream but accepts UTF-8 strings under Windows
+ /// and *\::filesystem::path on all systems
///
- typedef basic_ifstream ifstream;
+ using ifstream = basic_ifstream;
///
/// Same as std::ofstream but accepts UTF-8 strings under Windows
+ /// and *\::filesystem::path on all systems
///
- typedef basic_ofstream ofstream;
+ using ofstream = basic_ofstream;
///
/// Same as std::fstream but accepts UTF-8 strings under Windows
+ /// and *\::filesystem::path on all systems
///
- typedef basic_fstream fstream;
+ using fstream = basic_fstream;
-#endif
-} // nowide
-} // namespace boost
+ // Implementation
+ namespace detail {
+ /// Holds an instance of T
+ /// Required to make sure this is constructed first before passing it to sibling classes
+ template
+ struct buf_holder
+ {
+ T buf_;
+ };
+ template
+ class fstream_impl : private buf_holder>, // must be first due to init order
+ public T_StreamType::template stream_base::type
+ {
+ using internal_buffer_type = basic_filebuf;
+ using base_buf_holder = buf_holder