Boost logo

Boost-Commit :

From: technews_at_[hidden]
Date: 2008-06-24 20:49:24


Author: turkanis
Date: 2008-06-24 20:49:23 EDT (Tue, 24 Jun 2008)
New Revision: 46669
URL: http://svn.boost.org/trac/boost/changeset/46669

Log:
updated to allow pathnames to be supplied as Boost.Filesystem paths and to allow access to file timestamps
Text files modified:
   trunk/boost/iostreams/device/file_descriptor.hpp | 250 ++++++++++++++++-------
   trunk/libs/iostreams/src/file_descriptor.cpp | 419 ++++++++++++++++++++++++++++++---------
   2 files changed, 490 insertions(+), 179 deletions(-)

Modified: trunk/boost/iostreams/device/file_descriptor.hpp
==============================================================================
--- trunk/boost/iostreams/device/file_descriptor.hpp (original)
+++ trunk/boost/iostreams/device/file_descriptor.hpp 2008-06-24 20:49:23 EDT (Tue, 24 Jun 2008)
@@ -15,13 +15,17 @@
 # pragma once
 #endif
 
-#include <string> // file pathnames.
+#include <ctime>
+#include <string>
 #include <boost/cstdint.hpp> // intmax_t.
 #include <boost/iostreams/categories.hpp> // tags.
 #include <boost/iostreams/detail/config/auto_link.hpp>
 #include <boost/iostreams/detail/config/dyn_link.hpp>
 #include <boost/iostreams/detail/config/windows_posix.hpp>
+#include <boost/iostreams/detail/file_handle.hpp>
+#include <boost/iostreams/detail/file_times.hpp>
 #include <boost/iostreams/detail/ios.hpp> // openmode, seekdir, int types.
+#include <boost/iostreams/detail/path.hpp>
 #include <boost/iostreams/positioning.hpp>
 #include <boost/shared_ptr.hpp>
 
@@ -30,82 +34,97 @@
 
 namespace boost { namespace iostreams {
 
+// Forward declarations
+class file_descriptor_source;
+class file_descriptor_sink;
+namespace detail { struct file_descriptor_impl; }
+
 class BOOST_IOSTREAMS_DECL file_descriptor {
 public:
-#ifdef BOOST_IOSTREAMS_WINDOWS
- typedef void* handle_type; // A.k.a HANDLE
-#else
- typedef int handle_type;
-#endif
- typedef char char_type;
+ friend class file_descriptor_source;
+ friend class file_descriptor_sink;
+ typedef detail::file_handle handle_type;
+ typedef char char_type;
     struct category
         : seekable_device_tag,
           closable_tag
         { };
+
+ // Default constructor
     file_descriptor();
+
+ // Constructors taking file desciptors
     explicit file_descriptor(handle_type fd, bool close_on_exit = false);
 #ifdef BOOST_IOSTREAMS_WINDOWS
     explicit file_descriptor(int fd, bool close_on_exit = false);
 #endif
+
+ // Constructor taking a std:: string
     explicit file_descriptor( const std::string& path,
                               BOOST_IOS::openmode mode =
- BOOST_IOS::in | BOOST_IOS::out,
- BOOST_IOS::openmode base_mode =
                                   BOOST_IOS::in | BOOST_IOS::out );
+
+ // Constructor taking a C-style string
     explicit file_descriptor( const char* path,
                               BOOST_IOS::openmode mode =
- BOOST_IOS::in | BOOST_IOS::out,
- BOOST_IOS::openmode base_mode =
                                   BOOST_IOS::in | BOOST_IOS::out );
+
+ // Constructor taking a Boost.Filesystem path
+ template<typename Path>
+ explicit file_descriptor( const Path& path,
+ BOOST_IOS::openmode mode =
+ BOOST_IOS::in | BOOST_IOS::out )
+ { open(detail::path(path), mode); }
+
+ // Copy constructor
+ file_descriptor(const file_descriptor& other);
+
+ // open overloads taking file descriptors
+ void open(handle_type fd, bool close_on_exit = false);
+#ifdef BOOST_IOSTREAMS_WINDOWS
+ void open(int fd, bool close_on_exit = false);
+#endif
+
+ // open overload taking a std::string
     void open( const std::string& path,
- BOOST_IOS::openmode =
- BOOST_IOS::in | BOOST_IOS::out,
- BOOST_IOS::openmode base_mode =
+ BOOST_IOS::openmode mode =
                    BOOST_IOS::in | BOOST_IOS::out );
+
+ // open overload taking C-style string
     void open( const char* path,
- BOOST_IOS::openmode =
- BOOST_IOS::in | BOOST_IOS::out,
- BOOST_IOS::openmode base_mode =
+ BOOST_IOS::openmode mode =
                    BOOST_IOS::in | BOOST_IOS::out );
- bool is_open() const { return pimpl_->flags_ != 0; }
+
+ // open overload taking a Boost.Filesystem path
+ template<typename Path>
+ void open( const Path& path,
+ BOOST_IOS::openmode mode =
+ BOOST_IOS::in | BOOST_IOS::out )
+ { open(detail::path(path), mode); }
+
+ bool is_open() const;
+ void close();
     std::streamsize read(char_type* s, std::streamsize n);
     std::streamsize write(const char_type* s, std::streamsize n);
     std::streampos seek(stream_offset off, BOOST_IOS::seekdir way);
- void close();
- handle_type handle() const { return pimpl_->handle_; }
+ handle_type handle() const;
+ std::time_t last_read_time() const;
+ void set_last_read_time(std::time_t) const;
+ std::time_t last_write_time() const;
+ void set_last_write_time(std::time_t) const;
 private:
- struct impl {
- impl() :
- #ifdef BOOST_IOSTREAMS_WINDOWS
- handle_(reinterpret_cast<handle_type>(-1)),
- #else
- handle_(-1),
- #endif
- flags_(0)
- { }
- impl(handle_type fd, bool close_on_exit)
- : handle_(fd), flags_(0)
- { if (close_on_exit) flags_ |= impl::close_on_exit; }
- ~impl()
- { if (flags_ & close_on_exit) close_impl(*this); }
- enum flags {
- close_on_exit = 1,
- append = 4
- };
- handle_type handle_;
- int flags_;
- };
- friend struct impl;
 
- static void close_impl(impl&);
-#ifdef BOOST_IOSTREAMS_WINDOWS
- static handle_type int_to_handle(int fd);
-#endif
+ // open overload taking a detail::path
+ void open( const detail::path& path,
+ BOOST_IOS::openmode,
+ BOOST_IOS::openmode = BOOST_IOS::in | BOOST_IOS::out );
 
- shared_ptr<impl> pimpl_;
+ typedef detail::file_descriptor_impl impl_type;
+ shared_ptr<impl_type> pimpl_;
 };
 
-struct file_descriptor_source : private file_descriptor {
+class file_descriptor_source : private file_descriptor {
+public:
 #ifdef BOOST_IOSTREAMS_WINDOWS
     typedef void* handle_type; // A.k.a HANDLE
 #else
@@ -117,32 +136,65 @@
         device_tag,
         closable_tag
       { };
- using file_descriptor::read;
- using file_descriptor::seek;
- using file_descriptor::open;
     using file_descriptor::is_open;
     using file_descriptor::close;
+ using file_descriptor::read;
+ using file_descriptor::seek;
     using file_descriptor::handle;
+ using file_descriptor::last_read_time;
+ using file_descriptor::set_last_read_time;
+ using file_descriptor::last_write_time;
+ using file_descriptor::set_last_write_time;
+
+ // Default constructor
     file_descriptor_source() { }
- explicit file_descriptor_source(handle_type fd, bool close_on_exit = false)
- : file_descriptor(fd, close_on_exit)
- { }
-#ifdef BOOST_IOSTREAMS_WINDOWS
- explicit file_descriptor_source(int fd, bool close_on_exit = false)
- : file_descriptor(fd, close_on_exit)
- { }
+
+ // Constructors taking file desciptors
+ explicit file_descriptor_source(handle_type fd, bool close_on_exit = false);
+#ifdef BOOST_IOSTREAMS_WINDOWS
+ explicit file_descriptor_source(int fd, bool close_on_exit = false);
 #endif
+
+ // Constructor taking a std:: string
     explicit file_descriptor_source( const std::string& path,
- BOOST_IOS::openmode m = BOOST_IOS::in )
- : file_descriptor(path, m & ~BOOST_IOS::out, BOOST_IOS::in)
- { }
+ BOOST_IOS::openmode mode = BOOST_IOS::in );
+
+ // Constructor taking a C-style string
     explicit file_descriptor_source( const char* path,
- BOOST_IOS::openmode m = BOOST_IOS::in )
- : file_descriptor(path, m & ~BOOST_IOS::out, BOOST_IOS::in)
- { }
+ BOOST_IOS::openmode mode = BOOST_IOS::in );
+
+ // Constructor taking a Boost.Filesystem path
+ template<typename Path>
+ explicit file_descriptor_source( const Path& path,
+ BOOST_IOS::openmode mode = BOOST_IOS::in )
+ { open(detail::path(path), mode); }
+
+ // Copy constructor
+ file_descriptor_source(const file_descriptor_source& other);
+
+ // open overloads taking file descriptors
+ void open(handle_type fd, bool close_on_exit = false);
+#ifdef BOOST_IOSTREAMS_WINDOWS
+ void open(int fd, bool close_on_exit = false);
+#endif
+
+ // open overload taking a std::string
+ void open(const std::string& path, BOOST_IOS::openmode mode = BOOST_IOS::in);
+
+ // open overload taking C-style string
+ void open(const char* path, BOOST_IOS::openmode mode = BOOST_IOS::in);
+
+ // open overload taking a Boost.Filesystem path
+ template<typename Path>
+ void open(const Path& path, BOOST_IOS::openmode mode = BOOST_IOS::in);
+private:
+
+ // open overload taking a detail::path
+ void open(const detail::path& path, BOOST_IOS::openmode);
 };
 
-struct file_descriptor_sink : private file_descriptor {
+class file_descriptor_sink : private file_descriptor {
+public:
 #ifdef BOOST_IOSTREAMS_WINDOWS
     typedef void* handle_type; // A.k.a HANDLE
 #else
@@ -154,29 +206,65 @@
         device_tag,
         closable_tag
       { };
- using file_descriptor::write;
- using file_descriptor::seek;
- using file_descriptor::open;
     using file_descriptor::is_open;
     using file_descriptor::close;
+ using file_descriptor::write;
+ using file_descriptor::seek;
     using file_descriptor::handle;
+ using file_descriptor::last_read_time;
+ using file_descriptor::set_last_read_time;
+ using file_descriptor::last_write_time;
+ using file_descriptor::set_last_write_time;
+
+ // Default constructor
     file_descriptor_sink() { }
- explicit file_descriptor_sink(handle_type fd, bool close_on_exit = false)
- : file_descriptor(fd, close_on_exit)
- { }
-#ifdef BOOST_IOSTREAMS_WINDOWS
- explicit file_descriptor_sink(int fd, bool close_on_exit = false)
- : file_descriptor(fd, close_on_exit)
- { }
+
+ // Constructors taking file desciptors
+ explicit file_descriptor_sink(handle_type fd, bool close_on_exit = false);
+#ifdef BOOST_IOSTREAMS_WINDOWS
+ explicit file_descriptor_sink(int fd, bool close_on_exit = false);
 #endif
+
+ // Constructor taking a std:: string
     explicit file_descriptor_sink( const std::string& path,
- BOOST_IOS::openmode m = BOOST_IOS::out )
- : file_descriptor(path, m & ~BOOST_IOS::in, BOOST_IOS::out)
- { }
+ BOOST_IOS::openmode mode = BOOST_IOS::out );
+
+ // Constructor taking a C-style string
     explicit file_descriptor_sink( const char* path,
- BOOST_IOS::openmode m = BOOST_IOS::out )
- : file_descriptor(path, m & ~BOOST_IOS::in, BOOST_IOS::out)
- { }
+ BOOST_IOS::openmode mode = BOOST_IOS::out );
+
+ // Constructor taking a Boost.Filesystem path
+ template<typename Path>
+ explicit file_descriptor_sink( const Path& path,
+ BOOST_IOS::openmode mode = BOOST_IOS::out )
+ { open(detail::path(path), mode); }
+
+ // Copy constructor
+ file_descriptor_sink(const file_descriptor_sink& other);
+
+ // open overloads taking file descriptors
+ void open(handle_type fd, bool close_on_exit = false);
+#ifdef BOOST_IOSTREAMS_WINDOWS
+ void open(int fd, bool close_on_exit = false);
+#endif
+
+ // open overload taking a std::string
+ void open( const std::string& path,
+ BOOST_IOS::openmode mode = BOOST_IOS::out );
+
+ // open overload taking C-style string
+ void open( const char* path,
+ BOOST_IOS::openmode mode = BOOST_IOS::out );
+
+ // open overload taking a Boost.Filesystem path
+ template<typename Path>
+ void open( const Path& path,
+ BOOST_IOS::openmode mode = BOOST_IOS::out )
+ { open(detail::path(path), mode); }
+private:
+
+ // open overload taking a detail::path
+ void open(const detail::path& path, BOOST_IOS::openmode);
 };
 
 } } // End namespaces iostreams, boost.

Modified: trunk/libs/iostreams/src/file_descriptor.cpp
==============================================================================
--- trunk/libs/iostreams/src/file_descriptor.cpp (original)
+++ trunk/libs/iostreams/src/file_descriptor.cpp 2008-06-24 20:49:23 EDT (Tue, 24 Jun 2008)
@@ -5,9 +5,6 @@
 
 // See http://www.boost.org/libs/iostreams for documentation.
 
-// Inspired by fdstream.hpp, (C) Copyright Nicolai M. Josuttis 2001,
-// available at http://www.josuttis.com/cppcode/fdstream.html.
-
 // Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp>
 // knows that we are building the library (possibly exporting code), rather
 // than using it (possibly importing code).
@@ -21,6 +18,7 @@
 #include <boost/iostreams/detail/config/dyn_link.hpp>
 #include <boost/iostreams/detail/config/rtl.hpp> // BOOST_IOSTREAMS_FD_XXX
 #include <boost/iostreams/detail/config/windows_posix.hpp>
+#include <boost/iostreams/detail/system_failure.hpp>
 #include <boost/iostreams/detail/ios.hpp> // openmodes, failure.
 #include <boost/iostreams/device/file_descriptor.hpp>
 #include <boost/integer_traits.hpp>
@@ -43,68 +41,100 @@
 
 namespace boost { namespace iostreams {
 
-//------------------Implementation of file_descriptor-------------------------//
+//------------------Definition of file_descriptor_impl------------------------//
 
-file_descriptor::file_descriptor() : pimpl_(new impl) { }
-
-file_descriptor::file_descriptor(handle_type fd, bool close_on_exit)
- : pimpl_(new impl(fd, close_on_exit))
- { }
+namespace detail {
 
+// Contains the platform dependant implementation
+struct file_descriptor_impl {
+ file_descriptor_impl();
+ ~file_descriptor_impl();
+ void open(file_handle fd, bool close_on_exit);
 #ifdef BOOST_IOSTREAMS_WINDOWS
- file_descriptor::file_descriptor(int fd, bool close_on_exit)
- : pimpl_(new impl(int_to_handle(fd), close_on_exit))
- { }
+ void open(int fd, bool close_on_exit);
 #endif
+ void open(const detail::path&, BOOST_IOS::openmode);
+ bool is_open() const;
+ void close();
+ std::streamsize read(char* s, std::streamsize n);
+ std::streamsize write(const char* s, std::streamsize n);
+ std::streampos seek(stream_offset off, BOOST_IOS::seekdir way);
+ std::time_t last_read_time() const;
+ void set_last_read_time(std::time_t) const;
+ std::time_t last_write_time() const;
+ void set_last_write_time(std::time_t) const;
+ static file_handle invalid_handle();
+ enum flags {
+ close_on_exit = 1,
+ append = 4
+ };
+ file_handle handle_;
+ int flags_;
+};
 
-file_descriptor::file_descriptor( const char* path,
- BOOST_IOS::openmode mode,
- BOOST_IOS::openmode base_mode )
- : pimpl_(new impl)
-{ open(std::string(path), mode, base_mode); }
+//------------------Implementation of file_descriptor_impl--------------------//
 
-file_descriptor::file_descriptor( const std::string& path,
- BOOST_IOS::openmode mode,
- BOOST_IOS::openmode base_mode )
- : pimpl_(new impl)
-{ open(path, mode, base_mode); }
-
-void file_descriptor::open
- ( const std::string& path, BOOST_IOS::openmode m,
- BOOST_IOS::openmode base )
+file_descriptor_impl::file_descriptor_impl()
+ : handle_(invalid_handle()), flags_(0)
+ { }
+
+file_descriptor_impl::~file_descriptor_impl()
+{ if (flags_ & close_on_exit) close(); }
+
+void file_descriptor_impl::open(file_handle fd, bool close_on_exit)
+{
+ handle_ = fd;
+ flags_ = close_on_exit ?
+ file_descriptor_impl::close_on_exit :
+ 0;
+}
+
+#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
+
+void file_descriptor_impl::open(int fd, bool close_on_exit)
+{ open(reinterpret_cast<file_handle>(_get_osfhandle(fd)), close_on_exit); }
+
+#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
+
+void file_descriptor_impl::open(const detail::path& p, BOOST_IOS::openmode mode)
 {
- using namespace std;
- m |= base;
 #ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
     DWORD dwDesiredAccess;
     DWORD dwCreationDisposition;
- if ( (m & (BOOST_IOS::in | BOOST_IOS::out))
+ if ( (mode & (BOOST_IOS::in | BOOST_IOS::out))
              ==
          (BOOST_IOS::in | BOOST_IOS::out) )
     {
- if (m & BOOST_IOS::app)
+ if (mode & BOOST_IOS::app)
             throw BOOST_IOSTREAMS_FAILURE("bad open mode");
         dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
         dwCreationDisposition =
- (m & BOOST_IOS::trunc) ?
+ (mode & BOOST_IOS::trunc) ?
                 OPEN_ALWAYS :
                 OPEN_EXISTING;
- } else if (m & BOOST_IOS::in) {
- if (m & (BOOST_IOS::app |BOOST_IOS::trunc))
+ } else if (mode & BOOST_IOS::in) {
+ if (mode & (BOOST_IOS::app |BOOST_IOS::trunc))
             throw BOOST_IOSTREAMS_FAILURE("bad open mode");
         dwDesiredAccess = GENERIC_READ;
         dwCreationDisposition = OPEN_EXISTING;
- } else if (m & BOOST_IOS::out) {
+ } else if (mode & BOOST_IOS::out) {
         dwDesiredAccess = GENERIC_WRITE;
         dwCreationDisposition = OPEN_ALWAYS;
- if (m & BOOST_IOS::app)
- pimpl_->flags_ |= impl::append;
+ if (mode & BOOST_IOS::app)
+ flags_ |= append;
     } else {
         throw BOOST_IOSTREAMS_FAILURE("bad open mode");
     }
 
- HANDLE handle =
- ::CreateFileA( path.c_str(),
+ HANDLE handle = p.is_wide() ?
+ ::CreateFileW( p.to_wstring().c_str(),
+ dwDesiredAccess,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, // lpSecurityAttributes
+ dwCreationDisposition,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL ) : // hTemplateFile
+ ::CreateFileA( p.to_string().c_str(),
                        dwDesiredAccess,
                        FILE_SHARE_READ | FILE_SHARE_WRITE,
                        NULL, // lpSecurityAttributes
@@ -112,33 +142,33 @@
                        FILE_ATTRIBUTE_NORMAL,
                        NULL ); // hTemplateFile
     if (handle != INVALID_HANDLE_VALUE) {
- pimpl_->handle_ = handle;
- pimpl_->flags_ |= impl::close_on_exit;
+ handle_ = handle;
+ flags_ |= close_on_exit;
     } else {
- pimpl_->flags_ = 0;
- throw BOOST_IOSTREAMS_FAILURE("bad open");
+ flags_ = 0;
+ throw_system_failure("failed opening file");
     }
 #else // #ifdef BOOST_IOSTREAMS_WINDOWS //------------------------------------//
 
         // Calculate oflag argument to open.
 
     int oflag = 0;
- if ( (m & (BOOST_IOS::in | BOOST_IOS::out))
+ if ( (mode & (BOOST_IOS::in | BOOST_IOS::out))
              ==
          (BOOST_IOS::in | BOOST_IOS::out) )
     {
- assert(!(m & BOOST_IOS::app));
+ assert(!(mode & BOOST_IOS::app));
         oflag |= O_RDWR;
- } else if (m & BOOST_IOS::in) {
- assert(!(m & (BOOST_IOS::app |BOOST_IOS::trunc)));
+ } else if (mode & BOOST_IOS::in) {
+ assert(!(mode & (BOOST_IOS::app |BOOST_IOS::trunc)));
         oflag |= O_RDONLY;
- } else if (m & BOOST_IOS::out) {
+ } else if (mode & BOOST_IOS::out) {
         oflag |= O_WRONLY;
- m |= BOOST_IOS::trunc;
- if (m & BOOST_IOS::app)
+ mode |= BOOST_IOS::trunc;
+ if (mode & BOOST_IOS::app)
             oflag |= O_APPEND;
     }
- if (m & BOOST_IOS::trunc)
+ if (mode & BOOST_IOS::trunc)
         oflag |= O_CREAT;
     #ifdef _LARGEFILE64_SOURCE
         oflag |= O_LARGEFILE;
@@ -154,68 +184,81 @@
 
     int fd = BOOST_IOSTREAMS_FD_OPEN(path.c_str(), oflag, pmode);
     if (fd == -1) {
- throw BOOST_IOSTREAMS_FAILURE("bad open");
+ throw throw_system_failure("failed opening file");
     } else {
- pimpl_->handle_ = fd;
- pimpl_->flags_ = impl::close_on_exit;
+ handle_ = fd;
+ flags_ = close_on_exit;
     }
 #endif // #ifndef BOOST_IOSTREAMS_WINDOWS //----------------------------------//
 }
 
-void file_descriptor::open
- ( const char* path, BOOST_IOS::openmode m,
- BOOST_IOS::openmode base )
-{ open(std::string(path), m, base); }
+bool file_descriptor_impl::is_open() const
+{ return handle_ != invalid_handle(); }
 
-std::streamsize file_descriptor::read(char_type* s, std::streamsize n)
+void file_descriptor_impl::close()
+{
+ if (handle_ != invalid_handle()) {
+ bool success =
+ #ifdef BOOST_IOSTREAMS_WINDOWS
+ ::CloseHandle(handle_) == 1;
+ #else
+ BOOST_IOSTREAMS_FD_CLOSE(handle_) != -1;
+ #endif
+ if (!success)
+ throw_system_failure("failed closing file");
+ handle_ = invalid_handle();
+ flags_ = 0;
+ }
+}
+
+std::streamsize file_descriptor_impl::read(char* s, std::streamsize n)
 {
 #ifdef BOOST_IOSTREAMS_WINDOWS
     DWORD result;
- if (!::ReadFile(pimpl_->handle_, s, n, &result, NULL))
- throw detail::bad_read();
+ if (!::ReadFile(handle_, s, n, &result, NULL))
+ throw_system_failure("failed reading");
     return result == 0 ? -1 : static_cast<std::streamsize>(result);
 #else // #ifdef BOOST_IOSTREAMS_WINDOWS
     errno = 0;
- std::streamsize result = BOOST_IOSTREAMS_FD_READ(pimpl_->handle_, s, n);
+ std::streamsize result = BOOST_IOSTREAMS_FD_READ(handle_, s, n);
     if (errno != 0)
- throw detail::bad_read();
+ throw_system_failure("failed reading");
     return result == 0 ? -1 : result;
 #endif // #ifdef BOOST_IOSTREAMS_WINDOWS
 }
 
-std::streamsize file_descriptor::write(const char_type* s, std::streamsize n)
+std::streamsize file_descriptor_impl::write(const char* s, std::streamsize n)
 {
 #ifdef BOOST_IOSTREAMS_WINDOWS
- if (pimpl_->flags_ & impl::append) {
+ if (flags_ & append) {
         DWORD const dwResult =
- ::SetFilePointer(pimpl_->handle_, 0, NULL, FILE_END);
+ ::SetFilePointer(handle_, 0, NULL, FILE_END);
         if ( dwResult == INVALID_SET_FILE_POINTER &&
              ::GetLastError() != NO_ERROR )
         {
- throw detail::bad_seek();
+ throw_system_failure("failed seeking within file");
         }
     }
     DWORD ignore;
- if (!::WriteFile(pimpl_->handle_, s, n, &ignore, NULL))
- throw detail::bad_write();
+ if (!::WriteFile(handle_, s, n, &ignore, NULL))
+ throw_system_failure("failed writing");
     return n;
 #else // #ifdef BOOST_IOSTREAMS_WINDOWS
- int amt = BOOST_IOSTREAMS_FD_WRITE(pimpl_->handle_, s, n);
- if (amt < n)
- throw detail::bad_write(); // Handles blocking fd's only.
+ int amt = BOOST_IOSTREAMS_FD_WRITE(handle_, s, n);
+ if (amt < n) // Handles blocking fd's only.
+ throw_system_failure("failed writing");
     return n;
 #endif // #ifdef BOOST_IOSTREAMS_WINDOWS
 }
 
-std::streampos file_descriptor::seek
+std::streampos file_descriptor_impl::seek
     (stream_offset off, BOOST_IOS::seekdir way)
 {
- using namespace std;
 #ifdef BOOST_IOSTREAMS_WINDOWS
     LONG lDistanceToMove = static_cast<LONG>(off & 0xffffffff);
     LONG lDistanceToMoveHigh = static_cast<LONG>(off >> 32);
     DWORD dwResultLow =
- ::SetFilePointer( pimpl_->handle_,
+ ::SetFilePointer( handle_,
                           lDistanceToMove,
                           &lDistanceToMoveHigh,
                           way == BOOST_IOS::beg ?
@@ -226,7 +269,7 @@
     if ( dwResultLow == INVALID_SET_FILE_POINTER &&
          ::GetLastError() != NO_ERROR )
     {
- throw detail::bad_seek();
+ throw system_failure("failed seeking");
     } else {
        return offset_to_position(
                          (stream_offset(lDistanceToMoveHigh) << 32) + dwResultLow
@@ -240,7 +283,7 @@
     }
     stream_offset result =
         BOOST_IOSTREAMS_FD_SEEK(
- pimpl_->handle_,
+ handle_,
             static_cast<BOOST_IOSTREAMS_FD_OFFSET>(off),
             ( way == BOOST_IOS::beg ?
                   SEEK_SET :
@@ -249,38 +292,218 @@
                       SEEK_END )
         );
     if (result == -1)
- throw detail::bad_seek();
+ throw system_failure("failed seeking");
     return offset_to_position(result);
 #endif // #ifdef BOOST_IOSTREAMS_WINDOWS
 }
 
-void file_descriptor::close() { close_impl(*pimpl_); }
+std::time_t file_descriptor_impl::last_read_time() const
+{ return detail::last_read_time(handle_); }
+
+void file_descriptor_impl::set_last_read_time(std::time_t tm) const
+{ detail::set_last_read_time(handle_, tm); }
+
+std::time_t file_descriptor_impl::last_write_time() const
+{ return detail::last_write_time(handle_); }
 
-void file_descriptor::close_impl(impl& i)
+void file_descriptor_impl::set_last_write_time(std::time_t tm) const
+{ detail::set_last_write_time(handle_, tm); }
+
+// Returns the value stored in a file_handle variable when no file is open
+file_handle file_descriptor_impl::invalid_handle()
 {
 #ifdef BOOST_IOSTREAMS_WINDOWS
- if (i.handle_ != reinterpret_cast<handle_type>(-1)) {
- if (!::CloseHandle(i.handle_))
- throw BOOST_IOSTREAMS_FAILURE("bad close");
- i.handle_ = reinterpret_cast<handle_type>(-1);
- i.flags_ = 0;
- return;
- }
-#else // #ifdef BOOST_IOSTREAMS_WINDOWS
- if (i.handle_ != -1) {
- if (BOOST_IOSTREAMS_FD_CLOSE(i.handle_) == -1)
- throw BOOST_IOSTREAMS_FAILURE("bad close");
- i.handle_ = -1;
- i.flags_ = 0;
- }
-#endif // #ifdef BOOST_IOSTREAMS_WINDOWS
+ return INVALID_HANDLE_VALUE;
+#else
+ return -1;
+#endif
 }
 
-#ifdef BOOST_IOSTREAMS_WINDOWS
-file_descriptor::handle_type file_descriptor::int_to_handle(int fd)
+} // End namespace detail.
+
+//------------------Implementation of file_descriptor-------------------------//
+
+file_descriptor::file_descriptor() : pimpl_(new impl_type) { }
+
+file_descriptor::file_descriptor(handle_type fd, bool close_on_exit)
+ : pimpl_(new impl_type)
+{ open(fd, close_on_exit); }
+
+#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
+
+file_descriptor::file_descriptor(int fd, bool close_on_exit)
+ : pimpl_(new impl_type)
+{ open(fd, close_on_exit); }
+
+#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
+
+file_descriptor::file_descriptor( const std::string& path,
+ BOOST_IOS::openmode mode )
+ : pimpl_(new impl_type)
+{ open(path, mode); }
+
+file_descriptor::file_descriptor( const char* path,
+ BOOST_IOS::openmode mode )
+ : pimpl_(new impl_type)
+{ open(path, mode); }
+
+file_descriptor::file_descriptor(const file_descriptor& other)
+ : pimpl_(other.pimpl_)
+ { }
+
+void file_descriptor::open(handle_type fd, bool close_on_exit)
+{ pimpl_->open(fd, close_on_exit); }
+
+#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
+
+void file_descriptor::open(int fd, bool close_on_exit)
+{ pimpl_->open(fd, close_on_exit); }
+
+#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
+
+void file_descriptor::open(const std::string& path, BOOST_IOS::openmode mode)
+{ open(detail::path(path), mode); }
+
+void file_descriptor::open(const char* path, BOOST_IOS::openmode mode)
+{ open(detail::path(path), mode); }
+
+bool file_descriptor::is_open() const { return pimpl_->is_open(); }
+
+std::streamsize file_descriptor::read(char_type* s, std::streamsize n)
+{ return pimpl_->read(s, n); }
+
+std::streamsize file_descriptor::write(const char_type* s, std::streamsize n)
+{ return pimpl_->write(s, n); }
+
+std::streampos file_descriptor::seek(stream_offset off, BOOST_IOS::seekdir way)
+{ return pimpl_->seek(off, way); }
+
+void file_descriptor::close() { pimpl_->close(); }
+
+detail::file_handle file_descriptor::handle() const { return pimpl_->handle_; }
+
+std::time_t file_descriptor::last_read_time() const
+{ return pimpl_->last_read_time(); }
+
+void file_descriptor::set_last_read_time(std::time_t tm) const
+{ pimpl_->set_last_read_time(tm); }
+
+std::time_t file_descriptor::last_write_time() const
+{ return pimpl_->last_write_time(); }
+
+void file_descriptor::set_last_write_time(std::time_t tm) const
+{ pimpl_->set_last_write_time(tm); }
+
+void file_descriptor::open(
+ const detail::path& path,
+ BOOST_IOS::openmode mode,
+ BOOST_IOS::openmode base )
 {
- return reinterpret_cast<handle_type>(_get_osfhandle(fd));
+ mode |= base;
+ pimpl_->open(path, mode);
+}
+
+//------------------Implementation of file_descriptor_source------------------//
+
+file_descriptor_source::file_descriptor_source(
+ handle_type fd, bool close_on_exit)
+{ open(fd, close_on_exit); }
+
+#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
+
+file_descriptor_source::file_descriptor_source(int fd, bool close_on_exit)
+{ open(fd, close_on_exit); }
+
+#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
+
+file_descriptor_source::file_descriptor_source(
+ const std::string& path, BOOST_IOS::openmode mode)
+{ open(path, mode); }
+
+file_descriptor_source::file_descriptor_source(
+ const char* path, BOOST_IOS::openmode mode)
+{ open(path, mode); }
+
+file_descriptor_source::file_descriptor_source(
+ const file_descriptor_source& other)
+ : file_descriptor(static_cast<const file_descriptor&>(other))
+ { }
+
+void file_descriptor_source::open(handle_type fd, bool close_on_exit)
+{ file_descriptor::open(fd, close_on_exit); }
+
+#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
+
+void file_descriptor_source::open(int fd, bool close_on_exit)
+{ file_descriptor::open(fd, close_on_exit); }
+
+#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
+
+void file_descriptor_source::open(
+ const std::string& path, BOOST_IOS::openmode mode)
+{ open(detail::path(path), mode); }
+
+void file_descriptor_source::open(
+ const char* path, BOOST_IOS::openmode mode)
+{ open(detail::path(path), mode); }
+
+void file_descriptor_source::open(
+ const detail::path& path, BOOST_IOS::openmode mode)
+{
+ if (mode & (BOOST_IOS::out | BOOST_IOS::app | BOOST_IOS::trunc))
+ throw BOOST_IOSTREAMS_FAILURE("invalid mode");
+ file_descriptor::open(path, mode, BOOST_IOS::in);
+}
+
+//------------------Implementation of file_descriptor_sink--------------------//
+
+file_descriptor_sink::file_descriptor_sink(
+ handle_type fd, bool close_on_exit)
+{ open(fd, close_on_exit); }
+
+#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
+
+file_descriptor_sink::file_descriptor_sink(int fd, bool close_on_exit)
+{ open(fd, close_on_exit); }
+
+#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
+
+file_descriptor_sink::file_descriptor_sink(
+ const std::string& path, BOOST_IOS::openmode mode)
+{ open(path, mode); }
+
+file_descriptor_sink::file_descriptor_sink(
+ const char* path, BOOST_IOS::openmode mode)
+{ open(path, mode); }
+
+file_descriptor_sink::file_descriptor_sink(const file_descriptor_sink& other)
+ : file_descriptor(static_cast<const file_descriptor&>(other))
+ { }
+
+void file_descriptor_sink::open(handle_type fd, bool close_on_exit)
+{ file_descriptor::open(fd, close_on_exit); }
+
+#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
+
+void file_descriptor_sink::open(int fd, bool close_on_exit)
+{ file_descriptor::open(fd, close_on_exit); }
+
+#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
+
+void file_descriptor_sink::open(
+ const std::string& path, BOOST_IOS::openmode mode)
+{ open(detail::path(path), mode); }
+
+void file_descriptor_sink::open(
+ const char* path, BOOST_IOS::openmode mode)
+{ open(detail::path(path), mode); }
+
+void file_descriptor_sink::open(
+ const detail::path& path, BOOST_IOS::openmode mode)
+{
+ if (mode & BOOST_IOS::in)
+ throw BOOST_IOSTREAMS_FAILURE("invalid mode");
+ file_descriptor::open(path, mode, BOOST_IOS::out);
 }
-#endif
 
 } } // End namespaces iostreams, boost.


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk