Boost logo

Boost-Commit :

From: technews_at_[hidden]
Date: 2008-06-25 14:23:59


Author: turkanis
Date: 2008-06-25 14:23:59 EDT (Wed, 25 Jun 2008)
New Revision: 46692
URL: http://svn.boost.org/trac/boost/changeset/46692

Log:
applied changes from Jorge Lodos (with modifications)
Text files modified:
   trunk/boost/iostreams/device/mapped_file.hpp | 575 ++++++++++++++++++++++++-------
   trunk/libs/iostreams/src/mapped_file.cpp | 722 +++++++++++++++++++++------------------
   trunk/libs/iostreams/test/mapped_file_test.cpp | 188 +++++++--
   3 files changed, 982 insertions(+), 503 deletions(-)

Modified: trunk/boost/iostreams/device/mapped_file.hpp
==============================================================================
--- trunk/boost/iostreams/device/mapped_file.hpp (original)
+++ trunk/boost/iostreams/device/mapped_file.hpp 2008-06-25 14:23:59 EDT (Wed, 25 Jun 2008)
@@ -1,41 +1,16 @@
-// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
-// (C) Copyright 2003-2007 Jonathan Turkanis
+// (C) Copyright Jorge Lodos 2008.
+// (C) Copyright Jonathan Turkanis 2003.
 // (C) Copyright Craig Henderson 2002. 'boost/memmap.hpp' from sandbox
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
 
-// See http://www.boost.org/libs/iostreams for documentation.
-
-//
-// This header and its accompanying source file libs/iostreams/memmap.cpp are
-// an adaptation of Craig Henderson's memmory mapped file library. The
-// interface has been revised significantly, but the underlying OS-specific
-// code is essentially the same, with some code from Boost.Filesystem
-// mixed in. (See notations in source.)
-//
-// The following changes have been made:
-//
-// 1. OS-specific code put in a .cpp file.
-// 2. Name of main class changed to mapped_file.
-// 3. mapped_file given an interface similar to std::fstream (open(),
-// is_open(), close()) and std::string (data(), size(), begin(), end()).
-// 4. An additional class readonly_mapped_file has been provided as a
-// convenience.
-// 5. [Obsolete: Error states are reported using filesystem::error_code.]
-// 6. Read-only or read-write states are specified using ios_base::openmode.
-// 7. Access to the underlying file handles and to security parameters
-// has been removed.
-//
-
-#ifndef BOOST_IOSTREAMS_MAPPED_FILE_HPP_INCLUDED
-#define BOOST_IOSTREAMS_MAPPED_FILE_HPP_INCLUDED
-
 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
 # pragma once
 #endif
 
 #include <boost/config.hpp> // make sure size_t is in std.
 #include <cstddef> // size_t.
+#include <ctime> // size_t.
 #include <string> // pathnames.
 #include <utility> // pair.
 #include <boost/config.hpp> // BOOST_MSVC.
@@ -44,90 +19,178 @@
 #include <boost/iostreams/concepts.hpp>
 #include <boost/iostreams/detail/config/auto_link.hpp>
 #include <boost/iostreams/detail/config/dyn_link.hpp>
-#include <boost/iostreams/detail/ios.hpp> // openmode.
+#include <boost/iostreams/detail/ios.hpp> // openmode, failure
+#include <boost/iostreams/detail/path.hpp>
 #include <boost/iostreams/operations_fwd.hpp>
 #include <boost/iostreams/positioning.hpp>
 #include <boost/shared_ptr.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_same.hpp>
 
 // Must come last.
-#include <boost/iostreams/detail/config/disable_warnings.hpp>
 #include <boost/config/abi_prefix.hpp>
 
 namespace boost { namespace iostreams {
 
+//------------------Definition of mapped_file_base and mapped_file_params-----//
+
+// Forward declarations
+class mapped_file_source;
+class mapped_file_sink;
+class mapped_file;
+namespace detail { class mapped_file_impl; }
+
+class mapped_file_base {
+public:
+ enum mapmode {
+ readonly = 1,
+ readwrite = 2,
+ priv = 4
+ };
+};
+
+// Bitmask operations for mapped_file_base::mapmode
+mapped_file_base::mapmode
+operator|(mapped_file_base::mapmode a, mapped_file_base::mapmode b);
+
+mapped_file_base::mapmode
+operator&(mapped_file_base::mapmode a, mapped_file_base::mapmode b);
+
+mapped_file_base::mapmode
+operator^(mapped_file_base::mapmode a, mapped_file_base::mapmode b);
+
+mapped_file_base::mapmode
+operator~(mapped_file_base::mapmode a);
+
+mapped_file_base::mapmode
+operator|=(mapped_file_base::mapmode& a, mapped_file_base::mapmode b);
+
+mapped_file_base::mapmode
+operator&=(mapped_file_base::mapmode& a, mapped_file_base::mapmode b);
+
+mapped_file_base::mapmode
+operator^=(mapped_file_base::mapmode& a, mapped_file_base::mapmode b);
+
+//------------------Definition of mapped_file_params--------------------------//
+
 namespace detail {
 
-struct mapped_file_impl;
+struct mapped_file_params_base {
+ mapped_file_params_base()
+ : flags(static_cast<mapped_file_base::mapmode>(0)),
+ mode(), offset(0), length(static_cast<std::size_t>(-1)),
+ new_file_size(0), hint(0)
+ { }
+private:
+ friend class mapped_file_impl;
+ void normalize();
+public:
+ mapped_file_base::mapmode flags;
+ BOOST_IOS::openmode mode; // Deprecated
+ stream_offset offset;
+ std::size_t length;
+ stream_offset new_file_size;
+ const char* hint;
+};
 
 } // End namespace detail.
 
-struct mapped_file_params {
- explicit mapped_file_params()
- #if BOOST_WORKAROUND(BOOST_MSVC, < 1400) && defined(BOOST_RWSTD_VER) || \
- defined(__BORLANDC__) && defined(_CPPLIB_VER)
- /**/
- : mode(std::ios_base::openmode(0)),
- #else
- : mode(),
- #endif
- offset(0), length(static_cast<std::size_t>(-1)),
- new_file_size(0), hint(0)
+// This template allows Boost.Filesystem paths to be specified when creating or
+// reopening a memory mapped file, without creating a dependence on
+// Boost.Filesystem. Possible values of Path include std::string,
+// boost::filesystem::path, boost::filesystem::wpath,
+// and boost::iostreams::detail::path (used to store either a std::string or a
+// std::wstring).
+template<typename Path>
+struct basic_mapped_file_params
+ : detail::mapped_file_params_base
+{
+ typedef detail::mapped_file_params_base base_type;
+
+ // For wide paths, instantiate basic_mapped_file_params
+ // with boost::filesystem::wpath
+ BOOST_STATIC_ASSERT((!is_same<Path, std::wstring>::value));
+
+ // Default constructor
+ basic_mapped_file_params() { }
+
+ // Construction from a Path
+ explicit basic_mapped_file_params(const Path& p) : path(p) { }
+
+ // Construction from a path of a different type
+ template<typename PathT>
+ explicit basic_mapped_file_params(const PathT& p) : path(p) { }
+
+ // Copy constructor
+ basic_mapped_file_params(const basic_mapped_file_params& other)
+ : base_type(other), path(other.path)
         { }
- explicit mapped_file_params(const std::string& path)
- : path(path),
- #if BOOST_WORKAROUND(BOOST_MSVC, < 1400) && defined(BOOST_RWSTD_VER) || \
- defined(__BORLANDC__) && defined(_CPPLIB_VER)
- mode(std::ios_base::openmode(0)),
- #else
- mode(),
- #endif
- offset(0), length(static_cast<std::size_t>(-1)),
- new_file_size(0), hint(0)
+
+ // Templated copy constructor
+ template<typename PathT>
+ basic_mapped_file_params(const basic_mapped_file_params<PathT>& other)
+ : base_type(other), path(other.path)
         { }
- std::string path;
- BOOST_IOS::openmode mode;
- stream_offset offset;
- std::size_t length;
- stream_offset new_file_size;
- const char* hint;
+
+ typedef Path path_type;
+ Path path;
 };
 
+typedef basic_mapped_file_params<std::string> mapped_file_params;
+
 //------------------Definition of mapped_file_source--------------------------//
 
-class BOOST_IOSTREAMS_DECL mapped_file_source {
+class BOOST_IOSTREAMS_DECL mapped_file_source : public mapped_file_base {
 private:
- struct safe_bool_helper { int x; }; // From Bronek Kozicki.
- typedef int safe_bool_helper::* safe_bool;
- friend struct operations<mapped_file_source>;
+ struct safe_bool_helper { int x; };
+ typedef int safe_bool_helper::* safe_bool;
+ typedef detail::mapped_file_impl impl_type;
+ typedef basic_mapped_file_params<detail::path> param_type;
+ friend class mapped_file;
+ friend class impl_type;
+ friend struct boost::iostreams::operations<mapped_file_source>;
 public:
- typedef char char_type;
+ typedef char char_type;
     struct category
         : public source_tag,
           public direct_tag,
           public closable_tag
         { };
- typedef std::size_t size_type;
- typedef const char* iterator;
+ typedef std::size_t size_type;
+ typedef const char* iterator;
     BOOST_STATIC_CONSTANT(size_type, max_length = static_cast<size_type>(-1));
 
- mapped_file_source() { }
- explicit mapped_file_source(mapped_file_params);
- explicit mapped_file_source( const std::string& path,
+ // Default constructor
+ mapped_file_source();
+
+ // Constructor taking a parameters object
+ template<typename Path>
+ explicit mapped_file_source(const basic_mapped_file_params<Path>& p);
+
+ // Constructor taking a list of parameters
+ template<typename Path>
+ explicit mapped_file_source( const Path& path,
                                  size_type length = max_length,
                                  boost::intmax_t offset = 0 );
 
+ // Copy Constructor
+ mapped_file_source(const mapped_file_source& other);
+
     //--------------Stream interface------------------------------------------//
 
- void open(mapped_file_params params);
- void open( const std::string& path,
+ template<typename Path>
+ void open(const basic_mapped_file_params<Path>& p);
+
+ template<typename Path>
+ void open( const Path& path,
                size_type length = max_length,
                boost::intmax_t offset = 0 );
+
     bool is_open() const;
     void close();
-
     operator safe_bool() const;
     bool operator!() const;
- BOOST_IOS::openmode mode() const;
+ mapmode flags() const;
 
     //--------------Container interface---------------------------------------//
 
@@ -136,114 +199,328 @@
     iterator begin() const;
     iterator end() const;
 
+ //--------------File access and modification times------------------------//
+
+ 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;
+
     //--------------Query admissible offsets----------------------------------//
 
     // Returns the allocation granularity for virtual memory. Values passed
     // as offsets must be multiples of this value.
     static int alignment();
+
 private:
- friend class mapped_file;
- typedef detail::mapped_file_impl impl_type;
- void open_impl(mapped_file_params);
+ void init();
+ void open_impl(const param_type& p);
 
     boost::shared_ptr<impl_type> pimpl_;
 };
 
 //------------------Definition of mapped_file---------------------------------//
 
-class BOOST_IOSTREAMS_DECL mapped_file {
+class BOOST_IOSTREAMS_DECL mapped_file : public mapped_file_base {
 private:
- typedef mapped_file_source delegate_type;
- delegate_type delegate_;
- friend struct operations<mapped_file>;
+ typedef mapped_file_source delegate_type;
+ typedef delegate_type::safe_bool safe_bool;
+ typedef basic_mapped_file_params<detail::path> param_type;
+ friend struct boost::iostreams::operations<mapped_file >;
+ friend class mapped_file_sink;
 public:
- typedef char char_type;
+ typedef char char_type;
     struct category
         : public seekable_device_tag,
           public direct_tag,
           public closable_tag
         { };
- typedef mapped_file_source::size_type size_type;
- typedef char* iterator;
- typedef const char* const_iterator;
+ typedef mapped_file_source::size_type size_type;
+ typedef char* iterator;
+ typedef const char* const_iterator;
     BOOST_STATIC_CONSTANT(size_type, max_length = delegate_type::max_length);
+
+ // Default constructor
     mapped_file() { }
- explicit mapped_file(mapped_file_params p);
- explicit mapped_file( const std::string& path,
+
+ // Construstor taking a parameters object
+ template<typename Path>
+ explicit mapped_file(const basic_mapped_file_params<Path>& p);
+
+ // Constructor taking a list of parameters
+ template<typename Path>
+ mapped_file( const Path& path,
+ mapmode flags,
+ size_type length = max_length,
+ stream_offset offset = 0 );
+
+ // Constructor taking a list of parameters, including a
+ // std::ios_base::openmode (deprecated)
+ template<typename Path>
+ explicit mapped_file( const Path& path,
                           BOOST_IOS::openmode mode =
                               BOOST_IOS::in | BOOST_IOS::out,
                           size_type length = max_length,
                           stream_offset offset = 0 );
 
- //--------------Conversion to readonly_mapped_file------------------------//
+ // Copy Constructor
+ mapped_file(const mapped_file& other);
+
+ //--------------Conversion to mapped_file_source (deprecated)-------------//
 
     operator mapped_file_source&() { return delegate_; }
     operator const mapped_file_source&() const { return delegate_; }
 
     //--------------Stream interface------------------------------------------//
 
- void open(mapped_file_params p);
- void open( const std::string& path,
+ // open overload taking a parameters object
+ template<typename Path>
+ void open(const basic_mapped_file_params<Path>& p);
+
+ // open overload taking a list of parameters
+ template<typename Path>
+ void open( const Path& path,
+ mapmode mode,
+ size_type length = max_length,
+ stream_offset offset = 0 );
+
+ // open overload taking a list of parameters, including a
+ // std::ios_base::openmode (deprecated)
+ template<typename Path>
+ void open( const Path& path,
                BOOST_IOS::openmode mode =
                    BOOST_IOS::in | BOOST_IOS::out,
                size_type length = max_length,
                stream_offset offset = 0 );
+
     bool is_open() const { return delegate_.is_open(); }
     void close() { delegate_.close(); }
- operator delegate_type::safe_bool() const { return delegate_; }
- bool operator!() const { return !is_open(); }
- BOOST_IOS::openmode mode() const { return delegate_.mode(); }
+ operator safe_bool() const { return delegate_; }
+ bool operator!() const { return !delegate_; }
+ mapmode flags() const { return delegate_.flags(); }
 
     //--------------Container interface---------------------------------------//
 
     size_type size() const { return delegate_.size(); }
- char* data() const
- {
- return (mode() & BOOST_IOS::out) ?
- const_cast<char*>(delegate_.data()) :
- 0;
- }
+ char* data() const;
     const char* const_data() const { return delegate_.data(); }
     iterator begin() const { return data(); }
- const_iterator const_begin() const { return data(); }
+ const_iterator const_begin() const { return const_data(); }
     iterator end() const { return data() + size(); }
- const_iterator const_end() const { return data() + size(); }
+ const_iterator const_end() const { return const_data() + size(); }
 
     //--------------Query admissible offsets----------------------------------//
 
     // Returns the allocation granularity for virtual memory. Values passed
     // as offsets must be multiples of this value.
     static int alignment() { return mapped_file_source::alignment(); }
+
+ //--------------File access----------------------------------------------//
+
+ void resize(stream_offset new_size);
+ 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:
+ delegate_type delegate_;
 };
 
-struct BOOST_IOSTREAMS_DECL mapped_file_sink : private mapped_file {
- friend struct operations<mapped_file_sink>;
- typedef char char_type;
+//------------------Definition of mapped_file_sink----------------------------//
+
+class BOOST_IOSTREAMS_DECL mapped_file_sink : private mapped_file {
+public:
+ friend struct boost::iostreams::operations<mapped_file_sink>;
+ using mapped_file::mapmode;
+ using mapped_file::readonly;
+ using mapped_file::readwrite;
+ using mapped_file::priv;
+ using mapped_file::char_type;
     struct category
         : public sink_tag,
           public direct_tag,
           public closable_tag
         { };
+ using mapped_file::size_type;
+ using mapped_file::iterator;
+ using mapped_file::max_length;
+ using mapped_file::is_open;
     using mapped_file::close;
+ using mapped_file::operator safe_bool;
+ using mapped_file::operator !;
+ using mapped_file::flags;
     using mapped_file::size;
- explicit mapped_file_sink(mapped_file_params p);
- explicit mapped_file_sink( const std::string& path,
+ using mapped_file::data;
+ using mapped_file::begin;
+ using mapped_file::end;
+ using mapped_file::alignment;
+ using mapped_file::resize;
+ using mapped_file::last_read_time;
+ using mapped_file::set_last_read_time;
+ using mapped_file::last_write_time;
+ using mapped_file::set_last_write_time;
+
+ // Default constructor
+ mapped_file_sink() { }
+
+ // Constructor taking a parameters object
+ template<typename Path>
+ explicit mapped_file_sink(const basic_mapped_file_params<Path>& p);
+
+ // Constructor taking a list of parameters
+ template<typename Path>
+ explicit mapped_file_sink( const Path& path,
                                size_type length = max_length,
- boost::intmax_t offset = 0 );
- void open(mapped_file_params p);
- void open( const std::string& path,
+ boost::intmax_t offset = 0,
+ mapmode flags = readwrite );
+
+ // Copy Constructor
+ mapped_file_sink(const mapped_file_sink& other);
+
+ // open overload taking a parameters object
+ template<typename Path>
+ void open(const basic_mapped_file_params<Path>& p);
+
+ // open overload taking a list of parameters
+ template<typename Path>
+ void open( const Path& path,
                size_type length = max_length,
- boost::intmax_t offset = 0 );
+ boost::intmax_t offset = 0,
+ mapmode flags = readwrite );
 };
 
+//------------------Implementation of mapped_file_source----------------------//
+
+template<typename Path>
+mapped_file_source::mapped_file_source(const basic_mapped_file_params<Path>& p)
+{ init(); open(p); }
+
+template<typename Path>
+mapped_file_source::mapped_file_source(
+ const Path& path, size_type length, boost::intmax_t offset)
+{ init(); open(path, length, offset); }
+
+template<typename Path>
+void mapped_file_source::open(const basic_mapped_file_params<Path>& p)
+{
+ param_type params(p);
+ if (params.flags) {
+ if (params.flags != mapped_file::readonly)
+ throw new BOOST_IOSTREAMS_FAILURE("invalid flags");
+ } else {
+ if (params.mode & BOOST_IOS::out)
+ throw new BOOST_IOSTREAMS_FAILURE("invalid mode");
+ params.mode |= BOOST_IOS::in;
+ }
+ open_impl(params);
+}
+
+template<typename Path>
+void mapped_file_source::open(
+ const Path& path, size_type length, boost::intmax_t offset)
+{
+ param_type p(path);
+ p.length = length;
+ p.offset = offset;
+ open(p);
+}
+
+//------------------Implementation of mapped_file-----------------------------//
+
+template<typename Path>
+mapped_file::mapped_file(const basic_mapped_file_params<Path>& p)
+{ open(p); }
+
+template<typename Path>
+mapped_file::mapped_file(
+ const Path& path, mapmode flags,
+ size_type length, stream_offset offset )
+{ open(path, flags, length, offset); }
+
+template<typename Path>
+mapped_file::mapped_file(
+ const Path& path, BOOST_IOS::openmode mode,
+ size_type length, stream_offset offset )
+{ open(path, mode, length, offset); }
+
+template<typename Path>
+void mapped_file::open(const basic_mapped_file_params<Path>& p)
+{ delegate_.open_impl(p); }
+
+template<typename Path>
+void mapped_file::open(
+ const Path& path, mapmode flags,
+ size_type length, stream_offset offset )
+{
+ param_type p(path);
+ p.flags = flags;
+ p.length = length;
+ p.offset = offset;
+ open(p);
+}
+
+template<typename Path>
+void mapped_file::open(
+ const Path& path, BOOST_IOS::openmode mode,
+ size_type length, stream_offset offset )
+{
+ param_type p(path);
+ p.mode = mode;
+ p.length = length;
+ p.offset = offset;
+ open(p);
+}
+
+inline char* mapped_file::data() const
+{ return (flags() != readonly) ? const_cast<char*>(delegate_.data()) : 0; }
+
+//------------------Implementation of mapped_file_sink------------------------//
+
+template<typename Path>
+mapped_file_sink::mapped_file_sink(const basic_mapped_file_params<Path>& p)
+{ open(p); }
+
+template<typename Path>
+mapped_file_sink::mapped_file_sink(
+ const Path& path, size_type length,
+ boost::intmax_t offset, mapmode flags )
+{ open(path, length, offset, flags); }
+
+template<typename Path>
+void mapped_file_sink::open(const basic_mapped_file_params<Path>& p)
+{
+ param_type params(p);
+ if (params.flags) {
+ if (params.flags & mapped_file::readonly)
+ throw new BOOST_IOSTREAMS_FAILURE("invalid flags");
+ } else {
+ if (params.mode & BOOST_IOS::in)
+ throw new BOOST_IOSTREAMS_FAILURE("invalid mode");
+ params.mode |= BOOST_IOS::out;
+ }
+ mapped_file::open(params);
+}
+
+template<typename Path>
+void mapped_file_sink::open(
+ const Path& path, size_type length,
+ boost::intmax_t offset, mapmode flags )
+{
+ param_type p(path);
+ p.flags = flags;
+ p.length = length;
+ p.offset = offset;
+ open(p);
+}
+
 //------------------Specialization of direct_impl-----------------------------//
 
 template<>
-struct operations<boost::iostreams::mapped_file_source>
- : detail::close_impl<closable_tag>
+struct operations<mapped_file_source>
+ : boost::iostreams::detail::close_impl<closable_tag>
 {
     static std::pair<char*, char*>
- input_sequence(boost::iostreams::mapped_file_source& src)
+ input_sequence(mapped_file_source& src)
     {
         return std::make_pair( const_cast<char*>(src.begin()),
                                const_cast<char*>(src.end()) );
@@ -251,35 +528,79 @@
 };
 
 template<>
-struct operations<boost::iostreams::mapped_file_sink>
- : detail::close_impl<closable_tag>
+struct operations<mapped_file>
+ : boost::iostreams::detail::close_impl<closable_tag>
 {
     static std::pair<char*, char*>
- output_sequence(boost::iostreams::mapped_file_sink& sink)
+ input_sequence(mapped_file& file)
     {
- return std::make_pair(sink.begin(), sink.end());
+ return std::make_pair(file.begin(), file.end());
     }
-};
-
-template<>
-struct operations<boost::iostreams::mapped_file>
- : detail::close_impl<closable_tag>
-{
     static std::pair<char*, char*>
- input_sequence(boost::iostreams::mapped_file& file)
+ output_sequence(mapped_file& file)
     {
         return std::make_pair(file.begin(), file.end());
     }
+};
+
+template<>
+struct operations<mapped_file_sink>
+ : boost::iostreams::detail::close_impl<closable_tag>
+{
     static std::pair<char*, char*>
- output_sequence(boost::iostreams::mapped_file& file)
+ output_sequence(mapped_file_sink& sink)
     {
- return std::make_pair(file.begin(), file.end());
+ return std::make_pair(sink.begin(), sink.end());
     }
 };
+
+//------------------Definition of mapmode operators---------------------------//
+
+inline mapped_file::mapmode
+operator|(mapped_file::mapmode a, mapped_file::mapmode b)
+{
+ return static_cast<mapped_file::mapmode>
+ (static_cast<int>(a) | static_cast<int>(b));
+}
+
+inline mapped_file::mapmode
+operator&(mapped_file::mapmode a, mapped_file::mapmode b)
+{
+ return static_cast<mapped_file::mapmode>
+ (static_cast<int>(a) & static_cast<int>(b));
+}
+
+inline mapped_file::mapmode
+operator^(mapped_file::mapmode a, mapped_file::mapmode b)
+{
+ return static_cast<mapped_file::mapmode>
+ (static_cast<int>(a) ^ static_cast<int>(b));
+}
+
+inline mapped_file::mapmode
+operator~(mapped_file::mapmode a)
+{
+ return static_cast<mapped_file::mapmode>(~static_cast<int>(a));
+}
+
+inline mapped_file::mapmode
+operator|=(mapped_file::mapmode& a, mapped_file::mapmode b)
+{
+ return a = a | b;
+}
+
+inline mapped_file::mapmode
+operator&=(mapped_file::mapmode& a, mapped_file::mapmode b)
+{
+ return a = a & b;
+}
+
+inline mapped_file::mapmode
+operator^=(mapped_file::mapmode& a, mapped_file::mapmode b)
+{
+ return a = a ^ b;
+}
 
 } } // End namespaces iostreams, boost.
 
 #include <boost/config/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
-#include <boost/iostreams/detail/config/enable_warnings.hpp> // MSVC.
-
-#endif // #ifndef BOOST_IOSTREAMS_MAPPED_FILE_HPP_INCLUDED

Modified: trunk/libs/iostreams/src/mapped_file.cpp
==============================================================================
--- trunk/libs/iostreams/src/mapped_file.cpp (original)
+++ trunk/libs/iostreams/src/mapped_file.cpp 2008-06-25 14:23:59 EDT (Wed, 25 Jun 2008)
@@ -1,12 +1,7 @@
-// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
-// (C) Copyright 2004-2007 Jonathan Turkanis
 // (C) Copyright Craig Henderson 2002 'boost/memmap.hpp' from sandbox
+// (C) Copyright Jonathan Turkanis 2004.
 // (C) Copyright Jonathan Graehl 2004.
-
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
-
-// See http://www.boost.org/libs/iostreams for documentation.
+// (C) Copyright Jorge Lodos 2008.
 
 // Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp>
 // knows that we are building the library (possibly exporting code), rather
@@ -14,21 +9,17 @@
 #define BOOST_IOSTREAMS_SOURCE
 
 #include <cassert>
-#ifndef NDEBUG
-# include <boost/iostreams/detail/absolute_path.hpp>
-#endif
-#include <boost/iostreams/detail/config/dyn_link.hpp>
+#include <boost/iostreams/detail/config/rtl.hpp>
 #include <boost/iostreams/detail/config/windows_posix.hpp>
-#include <boost/iostreams/detail/ios.hpp> // failure.
+#include <boost/iostreams/detail/file_handle.hpp>
+#include <boost/iostreams/detail/file_times.hpp>
 #include <boost/iostreams/detail/system_failure.hpp>
 #include <boost/iostreams/device/mapped_file.hpp>
 
 #ifdef BOOST_IOSTREAMS_WINDOWS
 # define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
 # include <windows.h>
-# ifndef INVALID_SET_FILE_POINTER
-# define INVALID_SET_FILE_POINTER ((DWORD)-1)
-# endif
+# include <time.h>
 #else
 # include <errno.h>
 # include <fcntl.h>
@@ -38,423 +29,494 @@
 # include <unistd.h> // sysconf.
 #endif
 
-#include <boost/iostreams/detail/config/disable_warnings.hpp>
-
 namespace boost { namespace iostreams {
 
 namespace detail {
 
-struct mapped_file_impl {
- mapped_file_impl() { clear(false); }
- ~mapped_file_impl() { try { close(); } catch (...) { } }
- void clear(bool error)
- {
- data_ = 0;
- size_ = 0;
- mode_ = BOOST_IOS::openmode();
- error_ = error;
- #ifdef BOOST_IOSTREAMS_WINDOWS
- handle_ = INVALID_HANDLE_VALUE;
- mapped_handle_ = NULL;
- #else
- handle_ = 0;
- #endif
- #ifndef NDEBUG
- path_.erase();
- #endif
- }
- void close()
- {
- bool error = false;
- #ifdef BOOST_IOSTREAMS_WINDOWS
- if (handle_ == INVALID_HANDLE_VALUE)
- return;
- error = !::UnmapViewOfFile(data_) || error;
- error = !::CloseHandle(mapped_handle_) || error;
- error = !::CloseHandle(handle_) || error;
- handle_ = INVALID_HANDLE_VALUE;
- mapped_handle_ = NULL;
- #else
- if (!handle_)
- return;
- error = ::munmap(reinterpret_cast<char*>(data_), size_) != 0 || error;
- error = ::close(handle_) != 0 || error;
- handle_ = 0;
- #endif
- data_ = 0;
- size_ = 0;
- mode_ = BOOST_IOS::openmode();
- if (error) {
- std::string msg("error closing mapped file");
- #ifndef NDEBUG
- msg += std::string(" (\"") + path_ + "\")";
- #endif
- throw_system_failure(msg);
- }
- #ifndef NDEBUG
- path_.erase();
- #endif
- }
- char* data_;
- std::size_t size_;
- BOOST_IOS::openmode mode_;
- bool error_;
+// Class containing the platform-sepecific implementation
+// Invariant: The members params_, data_, size_, handle_ (and mapped_handle_
+// on Windows) either
+// - all have default values (or INVALID_HANDLE_VALUE for
+// Windows handles), or
+// - all have values reflecting a successful mapping.
+// In the first case, error_ may be true, reflecting a recent unsuccessful
+// open or close attempt; in the second case, error_ is always false.
+class mapped_file_impl {
+public:
+ typedef mapped_file_source::size_type size_type;
+ typedef mapped_file_source::param_type param_type;
+ typedef mapped_file_source::mapmode mapmode;
+ BOOST_STATIC_CONSTANT(
+ size_type, max_length = mapped_file_source::max_length);
+ mapped_file_impl();
+ ~mapped_file_impl();
+ void open(param_type p);
+ bool is_open() const { return data_ != 0; }
+ void close();
+ bool error() const { return error_; }
+ mapmode flags() const { return params_.flags; }
+ std::size_t size() const { return size_; }
+ char* data() const { return data_; }
+ void resize(stream_offset new_size);
+ 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 int alignment();
+private:
+ void open_file(param_type p);
+ void try_map_file(param_type p);
+ void map_file(param_type& p);
+ bool unmap_file();
+ void clear(bool error);
+ void cleanup_and_throw(const char* msg);
+ param_type params_;
+ char* data_;
+ stream_offset size_;
+ file_handle handle_;
 #ifdef BOOST_IOSTREAMS_WINDOWS
- HANDLE handle_;
- HANDLE mapped_handle_;
-#else
- int handle_;
-#endif
-#ifndef NDEBUG
- std::string path_;
+ file_handle mapped_handle_;
 #endif
+ bool error_;
 };
 
-} // End namespace detail.
-
-//------------------Definition of mapped_file_source--------------------------//
-
-mapped_file_source::mapped_file_source(mapped_file_params p) { open(p); }
-
-mapped_file_source::mapped_file_source( const std::string& path,
- mapped_file_source::size_type length,
- boost::intmax_t offset )
-{ open(path, length, offset); }
+mapped_file_impl::mapped_file_impl() { clear(false); }
 
-void mapped_file_source::open(mapped_file_params p)
-{
- p.mode &= ~BOOST_IOS::out;
- open_impl(p);
-}
+mapped_file_impl::~mapped_file_impl()
+{ try { close(); } catch (...) { } }
 
-void mapped_file_source::open( const std::string& path,
- mapped_file_source::size_type length,
- boost::intmax_t offset )
+void mapped_file_impl::open(param_type p)
 {
- mapped_file_params p(path);
- p.mode = BOOST_IOS::in;
- p.length = length;
- p.offset = offset;
- open_impl(p);
-}
-
-mapped_file_source::size_type mapped_file_source::size() const
-{ return pimpl_->size_; }
-
-void mapped_file_source::close() { pimpl_->close(); }
-
-mapped_file_source::operator mapped_file_source::safe_bool() const
-{
- return !!pimpl_ && pimpl_->error_ == false ?
- &safe_bool_helper::x : 0;
+ if (is_open())
+ throw BOOST_IOSTREAMS_FAILURE("file already open");
+ p.normalize();
+ open_file(p);
+ map_file(p); // May modify p.hint
+ params_ = p;
+}
+
+void mapped_file_impl::close()
+{
+ if (data_ == 0)
+ return;
+ bool error = false;
+ error = !unmap_file() || error;
+ error =
+ #ifdef BOOST_IOSTREAMS_WINDOWS
+ !::CloseHandle(handle_)
+ #else
+ ::close(handle_) != 0
+ #endif
+ || error;
+ clear(error);
+ if (error)
+ throw_system_failure("failed closing mapped file");
+}
+
+void mapped_file_impl::resize(stream_offset new_size)
+{
+ if (!is_open())
+ throw BOOST_IOSTREAMS_FAILURE("file is closed");
+ if (flags() & mapped_file::priv)
+ throw BOOST_IOSTREAMS_FAILURE("can't resize private mapped file");
+ if (!(flags() & mapped_file::readwrite))
+ throw BOOST_IOSTREAMS_FAILURE("can't resize readonly mapped file");
+ if (params_.offset >= new_size)
+ throw BOOST_IOSTREAMS_FAILURE("can't resize below mapped offset");
+ if (!unmap_file())
+ cleanup_and_throw("failed unmapping file");
+#ifdef BOOST_IOSTREAMS_WINDOWS
+ stream_offset offset = ::SetFilePointer(handle_, 0, NULL, FILE_CURRENT);
+ if (::GetLastError() != NO_ERROR)
+ cleanup_and_throw("failed querying file pointer");
+ LONG sizehigh = (new_size >> (sizeof(LONG) * 8));
+ LONG sizelow = (new_size & 0xffffffff);
+ ::SetFilePointer(handle_, sizelow, &sizehigh, FILE_BEGIN);
+ if (::GetLastError() != NO_ERROR || !::SetEndOfFile(handle_))
+ cleanup_and_throw("failed resizing mapped file");
+ sizehigh = (offset >> (sizeof(LONG) * 8));
+ sizelow = (offset & 0xffffffff);
+ ::SetFilePointer(handle_, sizelow, &sizehigh, FILE_BEGIN);
+#else
+ if (BOOST_IOSTREAMS_FD_TRUNCATE(handle_, new_size) == -1)
+ cleanup_and_throw("failed resizing mapped file");
+#endif
+ size_ = new_size;
+ param_type p(params_);
+ map_file(p); // May modify p.hint
+ params_ = p;
 }
 
-bool mapped_file_source::operator!() const
-{ return !pimpl_ || pimpl_->error_; }
-
-BOOST_IOS::openmode mapped_file_source::mode() const { return pimpl_->mode_; }
-
-const char* mapped_file_source::data() const { return pimpl_->data_; }
+std::time_t mapped_file_impl::last_read_time() const
+{ return detail::last_read_time(handle_); }
 
-const char* mapped_file_source::begin() const { return data(); }
+void mapped_file_impl::set_last_read_time(std::time_t tm) const
+{ detail::set_last_read_time(handle_, tm); }
 
-const char* mapped_file_source::end() const { return data() + size(); }
+std::time_t mapped_file_impl::last_write_time() const
+{ return detail::last_write_time(handle_); }
 
-#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
+void mapped_file_impl::set_last_write_time(std::time_t tm) const
+{ detail::set_last_write_time(handle_, tm); }
 
-namespace detail {
-
-void cleanup_and_throw(detail::mapped_file_impl& impl, std::string msg)
+int mapped_file_impl::alignment()
 {
- #ifndef NDEBUG
- msg += std::string(" (\"") + impl.path_ + "\")";
- #endif
- if (impl.mapped_handle_ != INVALID_HANDLE_VALUE)
- ::CloseHandle(impl.mapped_handle_);
- if (impl.handle_ != NULL)
- ::CloseHandle(impl.handle_);
- impl.clear(true);
- throw_system_failure(msg);
+#ifdef BOOST_IOSTREAMS_WINDOWS
+ SYSTEM_INFO info;
+ ::GetSystemInfo(&info);
+ return static_cast<int>(info.dwAllocationGranularity);
+#else
+ return static_cast<int>(sysconf(_SC_PAGESIZE));
+#endif
 }
 
-} // End namespace detail.
-
-void mapped_file_source::open_impl(mapped_file_params p)
+void mapped_file_impl::open_file(param_type p)
 {
- using namespace std;
-
- if (is_open())
- throw BOOST_IOSTREAMS_FAILURE("file already open");
- if (!pimpl_)
- pimpl_.reset(new impl_type);
- else
- pimpl_->clear(false);
- bool readonly = (p.mode & BOOST_IOS::out) == 0;
- pimpl_->mode_ = readonly ? BOOST_IOS::in : (BOOST_IOS::in | BOOST_IOS::out);
- #ifndef NDEBUG
- pimpl_->path_ = detail::absolute_path(p.path);
- #endif
-
- //--------------Open underlying file--------------------------------------//
-
- pimpl_->handle_ =
- ::CreateFileA( p.path.c_str(),
- readonly ? GENERIC_READ : GENERIC_ALL,
- FILE_SHARE_READ,
- NULL,
- (p.new_file_size != 0 && !readonly) ?
- CREATE_ALWAYS :
- OPEN_EXISTING,
- readonly ?
- FILE_ATTRIBUTE_READONLY :
- FILE_ATTRIBUTE_TEMPORARY,
- NULL );
-
- if (pimpl_->handle_ == INVALID_HANDLE_VALUE) {
- detail::cleanup_and_throw(*pimpl_, "failed opening file");
- }
+ bool readonly = p.flags != mapped_file::readwrite;
+#ifdef BOOST_IOSTREAMS_WINDOWS
 
- //--------------Set file size---------------------------------------------//
+ // Open file
+ DWORD dwDesiredAccess = readonly ? GENERIC_READ : GENERIC_ALL;
+ DWORD dwCreationDisposition = (p.new_file_size != 0 && !readonly) ?
+ CREATE_ALWAYS :
+ OPEN_EXISTING;
+ DWORD dwFlagsandAttributes =
+ readonly ?
+ FILE_ATTRIBUTE_READONLY :
+ FILE_ATTRIBUTE_TEMPORARY;
+ handle_ = p.path.is_wide() ?
+ ::CreateFileW(
+ p.path.to_wstring().c_str(),
+ dwDesiredAccess,
+ FILE_SHARE_READ,
+ NULL,
+ dwCreationDisposition,
+ dwFlagsandAttributes,
+ NULL ) :
+ ::CreateFileA(
+ p.path.to_string().c_str(),
+ dwDesiredAccess,
+ FILE_SHARE_READ,
+ NULL,
+ dwCreationDisposition,
+ dwFlagsandAttributes,
+ NULL );
+ if (handle_ == INVALID_HANDLE_VALUE)
+ cleanup_and_throw("failed opening file");
 
+ // Set file size
     if (p.new_file_size != 0 && !readonly) {
         LONG sizehigh = (p.new_file_size >> (sizeof(LONG) * 8));
         LONG sizelow = (p.new_file_size & 0xffffffff);
- DWORD result =
- ::SetFilePointer(pimpl_->handle_, sizelow, &sizehigh, FILE_BEGIN);
- if ( result == INVALID_SET_FILE_POINTER &&
- ::GetLastError() != NO_ERROR ||
- !::SetEndOfFile(pimpl_->handle_) )
- {
- detail::cleanup_and_throw(*pimpl_, "failed setting file size");
- }
+ ::SetFilePointer(handle_, sizelow, &sizehigh, FILE_BEGIN);
+ if (::GetLastError() != NO_ERROR || !::SetEndOfFile(handle_))
+ cleanup_and_throw("failed setting file size");
     }
 
- //--------------Create mapping--------------------------------------------//
-
- try_again: // Target of goto in following section.
-
- pimpl_->mapped_handle_ =
- ::CreateFileMappingA( pimpl_->handle_, NULL,
- readonly ? PAGE_READONLY : PAGE_READWRITE,
- 0, 0, NULL );
- if (pimpl_->mapped_handle_ == NULL) {
- detail::cleanup_and_throw(*pimpl_, "couldn't create mapping");
- }
-
- //--------------Access data-----------------------------------------------//
-
- void* data =
- ::MapViewOfFileEx( pimpl_->mapped_handle_,
- readonly ? FILE_MAP_READ : FILE_MAP_WRITE,
- (DWORD) (p.offset >> 32),
- (DWORD) (p.offset & 0xffffffff),
- p.length != max_length ? p.length : 0, (LPVOID) p.hint );
- if (!data) {
- if (p.hint != 0) {
- p.hint = 0;
- goto try_again;
- }
- detail::cleanup_and_throw(*pimpl_, "failed mapping view");
- }
-
- //--------------Determing file size---------------------------------------//
-
- // Dynamically locate GetFileSizeEx (thanks to Pavel Vozenilik).
+ // Determine file size. Dynamically locate GetFileSizeEx for compatibility
+ // with old Platform SDK (thanks to Pavel Vozenilik).
     typedef BOOL (WINAPI *func)(HANDLE, PLARGE_INTEGER);
     HMODULE hmod = ::GetModuleHandleA("kernel32.dll");
     func get_size =
         reinterpret_cast<func>(::GetProcAddress(hmod, "GetFileSizeEx"));
-
     if (get_size) {
         LARGE_INTEGER info;
- if (get_size(pimpl_->handle_, &info)) {
+ if (get_size(handle_, &info)) {
             boost::intmax_t size =
                 ( (static_cast<boost::intmax_t>(info.HighPart) << 32) |
                   info.LowPart );
- pimpl_->size_ =
+ size_ =
                 static_cast<std::size_t>(
                     p.length != max_length ?
                         std::min<boost::intmax_t>(p.length, size) :
                         size
                 );
         } else {
- detail::cleanup_and_throw(*pimpl_, "failed getting file size");
+ cleanup_and_throw("failed querying file size");
             return;
         }
     } else {
         DWORD hi;
         DWORD low;
- if ( (low = ::GetFileSize(pimpl_->handle_, &hi))
+ if ( (low = ::GetFileSize(handle_, &hi))
                  !=
              INVALID_FILE_SIZE )
         {
             boost::intmax_t size =
                 (static_cast<boost::intmax_t>(hi) << 32) | low;
- pimpl_->size_ =
+ size_ =
                 static_cast<std::size_t>(
                     p.length != max_length ?
                         std::min<boost::intmax_t>(p.length, size) :
                         size
                 );
         } else {
- detail::cleanup_and_throw(*pimpl_, "failed getting file size");
+ cleanup_and_throw("failed querying file size");
             return;
         }
     }
+#else // #ifdef BOOST_IOSTREAMS_WINDOWS
+
+ // Open file
+ int flags = (readonly ? O_RDONLY : O_RDWR);
+ if (p.new_file_size != 0 && !readonly)
+ flags |= (O_CREAT | O_TRUNC);
+ #ifdef _LARGEFILE64_SOURCE
+ oflag |= O_LARGEFILE;
+ #endif
+ errno = 0;
+ handle_ = ::open(p.path.to_string().c_str(), flags, S_IRWXU);
+ if (errno != 0)
+ cleanup_and_throw("failed opening file");
+
+ //--------------Set file size---------------------------------------------//
+
+ if (p.new_file_size != 0 && !readonly)
+ if (BOOST_IOSTREAMS_FD_TRUNCATE(handle_, p.new_file_size) == -1)
+ cleanup_and_throw("failed setting file size");
+
+ //--------------Determine file size---------------------------------------//
+
+ bool success = true;
+ if (p.length != max_length) {
+ size_ = p.length;
+ } else {
+ struct BOOST_IOSTREAMS_FD_STAT info;
+ success = ::BOOST_IOSTREAMS_FD_FSTAT(handle_, &info) != -1;
+ size_ = info.st_size;
+ }
+ if (!success)
+ cleanup_and_throw("failed querying file size");
+#endif // #ifdef BOOST_IOSTREAMS_WINDOWS
+}
 
- pimpl_->data_ = reinterpret_cast<char*>(data);
+void mapped_file_impl::try_map_file(param_type p)
+{
+ bool priv = p.flags == mapped_file::priv;
+ bool readonly = p.flags == mapped_file::readonly;
+#ifdef BOOST_IOSTREAMS_WINDOWS
+
+ // Create mapping
+ DWORD protect = priv ?
+ PAGE_WRITECOPY :
+ readonly ?
+ PAGE_READONLY :
+ PAGE_READWRITE;
+ mapped_handle_ =
+ ::CreateFileMappingA(
+ handle_,
+ NULL,
+ protect,
+ 0,
+ 0,
+ NULL );
+ if (mapped_handle_ == NULL)
+ cleanup_and_throw("failed create mapping");
+
+ // Access data
+ DWORD access = priv ?
+ FILE_MAP_COPY :
+ readonly ?
+ FILE_MAP_READ :
+ FILE_MAP_WRITE;
+ void* data =
+ ::MapViewOfFileEx(
+ mapped_handle_,
+ access,
+ (DWORD) (params_.offset >> 32),
+ (DWORD) (params_.offset & 0xffffffff),
+ size_ != max_length ? size_ : 0,
+ (LPVOID) p.hint );
+ if (!data)
+ cleanup_and_throw("failed mapping view");
+#else
+ void* data =
+ ::BOOST_IOSTREAMS_FD_MMAP(
+ p.hint_,
+ size_,
+ readonly ? PROT_READ : (PROT_READ | PROT_WRITE),
+ priv ? MAP_PRIVATE : MAP_SHARED,
+ handle_,
+ params_.offset );
+ if (data == MAP_FAILED)
+ cleanup_and_throw("failed mapping file");
+#endif
+ data_ = static_cast<char*>(data);
 }
 
-bool mapped_file_source::is_open() const
-{ return !!pimpl_ && pimpl_->handle_ != INVALID_HANDLE_VALUE; }
+void mapped_file_impl::map_file(param_type& p)
+{
+ try {
+ try_map_file(p);
+ } catch (const std::exception& e) {
+ if (p.hint) {
+ p.hint = 0;
+ try_map_file(p);
+ } else {
+ throw e;
+ }
+ }
+}
 
-int mapped_file_source::alignment()
+bool mapped_file_impl::unmap_file()
 {
- SYSTEM_INFO info;
- ::GetSystemInfo(&info);
- return static_cast<int>(info.dwAllocationGranularity);
+#ifdef BOOST_IOSTREAMS_WINDOWS
+ bool error = false;
+ error = !::UnmapViewOfFile(data_) || error;
+ error = !::CloseHandle(mapped_handle_) || error;
+ mapped_handle_ = NULL;
+ return !error;
+#else
+ return ::munmap(data_, size_) == 0;
+#endif
 }
 
-#else // #ifdef BOOST_IOSTREAMS_WINDOWS //------------------------------------//
+void mapped_file_impl::clear(bool error)
+{
+ params_ = param_type();
+ data_ = 0;
+ size_ = 0;
+#ifdef BOOST_IOSTREAMS_WINDOWS
+ handle_ = INVALID_HANDLE_VALUE;
+ mapped_handle_ = NULL;
+#else
+ handle_ = 0;
+#endif
+ error_ = error;
+}
 
-namespace detail {
+// Called when an error is encountered during the execution of open_file or
+// map_file
+void mapped_file_impl::cleanup_and_throw(const char* msg)
+{
+#ifdef BOOST_IOSTREAMS_WINDOWS
+ DWORD error = GetLastError();
+ if (mapped_handle_ != INVALID_HANDLE_VALUE)
+ ::CloseHandle(mapped_handle_);
+ if (handle_ != NULL)
+ ::CloseHandle(handle_);
+ SetLastError(error);
+#else
+ int error = errno;
+ if (handle_ != 0)
+ ::close(handle_);
+ errno = error;
+#endif
+ clear(true);
+ boost::iostreams::detail::throw_system_failure(msg);
+}
 
- void cleanup_and_throw(detail::mapped_file_impl& impl, std::string msg)
+//------------------Implementation of mapped_file_params_base-----------------//
+
+void mapped_file_params_base::normalize()
 {
- #ifndef NDEBUG
- msg += std::string(" (\"") + impl.path_ + "\")";
- #endif
- if (impl.handle_ != 0)
- ::close(impl.handle_);
- impl.clear(true);
- throw_system_failure(msg);
+ if (mode && flags)
+ throw BOOST_IOSTREAMS_FAILURE(
+ "at most one of 'mode' and 'flags' may be specified"
+ );
+ if (flags) {
+ switch (flags) {
+ case mapped_file::readonly:
+ case mapped_file::readwrite:
+ case mapped_file::priv:
+ break;
+ default:
+ throw BOOST_IOSTREAMS_FAILURE("invalid flags");
+ }
+ } else {
+ flags = (mode & BOOST_IOS::out) ?
+ mapped_file::readwrite :
+ mapped_file::readonly;
+ mode = BOOST_IOS::openmode();
+ }
+ if (offset < 0)
+ throw BOOST_IOSTREAMS_FAILURE("invalid offset");
+ if (new_file_size < 0)
+ throw BOOST_IOSTREAMS_FAILURE("invalid new file size");
 }
 
 } // End namespace detail.
 
+//------------------Implementation of mapped_file_source----------------------//
 
-void mapped_file_source::open_impl(mapped_file_params p)
-{
- using namespace std;
+mapped_file_source::mapped_file_source()
+ : pimpl_(new impl_type)
+ { }
+
+mapped_file_source::mapped_file_source(const mapped_file_source& other)
+ : pimpl_(other.pimpl_)
+ { }
 
- if (is_open())
- throw BOOST_IOSTREAMS_FAILURE("file already open");
- if (!pimpl_)
- pimpl_.reset(new impl_type);
- else
- pimpl_->clear(false);
- bool readonly = (p.mode & BOOST_IOS::out) == 0;
- pimpl_->mode_ = readonly ? BOOST_IOS::in : (BOOST_IOS::in | BOOST_IOS::out);
- #ifndef NDEBUG
- pimpl_->path_ = detail::absolute_path(p.path);
- #endif
+bool mapped_file_source::is_open() const
+{ return pimpl_->is_open(); }
 
- //--------------Open underlying file--------------------------------------//
+void mapped_file_source::close() { pimpl_->close(); }
 
- int flags = (readonly ? O_RDONLY : O_RDWR);
- if (p.new_file_size != 0 && !readonly)
- flags |= (O_CREAT | O_TRUNC);
- errno = 0;
- pimpl_->handle_ = ::open(p.path.c_str(), flags, S_IRWXU);
- if (errno != 0)
- detail::cleanup_and_throw(*pimpl_, "failed opening file");
+mapped_file_source::operator safe_bool() const
+{ return pimpl_->error() ? &safe_bool_helper::x : 0; }
 
- //--------------Set file size---------------------------------------------//
+bool mapped_file_source::operator!() const
+{ return pimpl_->error(); }
 
- if (p.new_file_size != 0 && !readonly)
- if (ftruncate(pimpl_->handle_, p.new_file_size) == -1)
- detail::cleanup_and_throw(*pimpl_, "failed setting file size");
+mapped_file_source::mapmode mapped_file_source::flags() const
+{ return pimpl_->flags(); }
 
- //--------------Determine file size---------------------------------------//
+mapped_file_source::size_type mapped_file_source::size() const
+{ return pimpl_->size(); }
 
- bool success = true;
- struct stat info;
- if (p.length != max_length)
- pimpl_->size_ = p.length;
- else {
- success = ::fstat(pimpl_->handle_, &info) != -1;
- pimpl_->size_ = info.st_size;
- }
- if (!success)
- detail::cleanup_and_throw(*pimpl_, "failed getting file size");
+const char* mapped_file_source::data() const { return pimpl_->data(); }
+
+const char* mapped_file_source::begin() const { return data(); }
 
- //--------------Create mapping--------------------------------------------//
+const char* mapped_file_source::end() const { return data() + size(); }
 
- try_again: // Target of goto in following section.
+std::time_t mapped_file_source::last_read_time() const
+{ return pimpl_->last_read_time(); }
 
- char* hint = const_cast<char*>(p.hint);
- void* data = ::mmap( hint, pimpl_->size_,
- readonly ? PROT_READ : (PROT_READ | PROT_WRITE),
- readonly ? MAP_PRIVATE : MAP_SHARED,
- pimpl_->handle_, p.offset );
- if (data == MAP_FAILED) {
- if (hint != 0) {
- hint = 0;
- goto try_again;
- }
- detail::cleanup_and_throw(*pimpl_, "failed mapping file");
- }
- pimpl_->data_ = reinterpret_cast<char*>(data);
+void mapped_file_source::set_last_read_time(std::time_t tm) const
+{ pimpl_->set_last_read_time(tm); }
 
- return;
-}
+std::time_t mapped_file_source::last_write_time() const
+{ return pimpl_->last_write_time(); }
 
-bool mapped_file_source::is_open() const
-{ return !!pimpl_ && pimpl_->handle_ != 0; }
+void mapped_file_source::set_last_write_time(std::time_t tm) const
+{ pimpl_->set_last_write_time(tm); }
 
 int mapped_file_source::alignment()
-{ return static_cast<int>(sysconf(_SC_PAGESIZE)); }
+{ return detail::mapped_file_impl::alignment(); }
 
-#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
+void mapped_file_source::init() { pimpl_.reset(new impl_type); }
+
+void mapped_file_source::open_impl(const param_type& p)
+{ pimpl_->open(p); }
 
 //------------------Implementation of mapped_file-----------------------------//
 
-mapped_file::mapped_file(mapped_file_params p) { delegate_.open_impl(p); }
+mapped_file::mapped_file(const mapped_file& other)
+ : delegate_(other.delegate_)
+ { }
 
-mapped_file::mapped_file( const std::string& path, BOOST_IOS::openmode mode,
- size_type length, stream_offset offset )
-{ open(path, mode, length, offset); }
-
-void mapped_file::open(mapped_file_params p)
-{ delegate_.open_impl(p); }
-
-void mapped_file::open( const std::string& path, BOOST_IOS::openmode mode,
- size_type length, stream_offset offset )
-{
- mapped_file_params p(path);
- p.mode = mode;
- p.length = length;
- p.offset = offset;
- open(p);
-}
+void mapped_file::resize(stream_offset new_size)
+{ delegate_.pimpl_->resize(new_size); }
 
-//------------------Implementation of mapped_file_sink------------------------//
+std::time_t mapped_file::last_read_time() const
+{ return delegate_.pimpl_->last_read_time(); }
 
-mapped_file_sink::mapped_file_sink(mapped_file_params p) { open(p); }
+void mapped_file::set_last_read_time(std::time_t tm) const
+{ delegate_.pimpl_->set_last_read_time(tm); }
 
-mapped_file_sink::mapped_file_sink( const std::string& path,
- size_type length, stream_offset offset )
-{ open(path, length, offset); }
+std::time_t mapped_file::last_write_time() const
+{ return delegate_.pimpl_->last_write_time(); }
 
-void mapped_file_sink::open(mapped_file_params p)
-{
- p.mode |= BOOST_IOS::out;
- p.mode &= ~BOOST_IOS::in;
- mapped_file::open(p);
-}
+void mapped_file::set_last_write_time(std::time_t tm) const
+{ delegate_.pimpl_->set_last_write_time(tm); }
 
-void mapped_file_sink::open( const std::string& path, size_type length,
- stream_offset offset )
-{
- mapped_file_params p(path);
- p.mode = BOOST_IOS::out;
- p.length = length;
- p.offset = offset;
- open(p);
-}
+//------------------Implementation of mapped_file_sink------------------------//
+
+mapped_file_sink::mapped_file_sink(const mapped_file_sink& other)
+ : mapped_file(static_cast<const mapped_file&>(other))
+ { }
 
 //----------------------------------------------------------------------------//
 
 } } // End namespaces iostreams, boost.
-
-#include <boost/iostreams/detail/config/enable_warnings.hpp>

Modified: trunk/libs/iostreams/test/mapped_file_test.cpp
==============================================================================
--- trunk/libs/iostreams/test/mapped_file_test.cpp (original)
+++ trunk/libs/iostreams/test/mapped_file_test.cpp 2008-06-25 14:23:59 EDT (Wed, 25 Jun 2008)
@@ -1,33 +1,70 @@
-// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
-// (C) Copyright 2004-2007 Jonathan Turkanis
+// (C) Copyright Jorge Lodos 2008
+// (C) Copyright Jonathan Turkanis 2004
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
 
 // See http://www.boost.org/libs/iostreams for documentation.
 
+// This is the original (boost 1.34) boost::iostream test for the mapped files with the
+// following modifications:
+// 1. The namespace for the mapped file was changed to seglib::filemap.
+// 2. Added test for privately mapped files.
+// 3. The test test_writeable was added for mapped files.
+// 4. The test test_resizeable was added for mapped files.
+//
+
 #include <fstream>
 #include <boost/config.hpp>
 #include <boost/detail/workaround.hpp>
-#include <boost/iostreams/device/mapped_file.hpp>
-#include <boost/iostreams/stream.hpp>
 #include <boost/test/test_tools.hpp>
 #include <boost/test/unit_test.hpp>
+
+#include <boost/iostreams/stream.hpp>
+#include <boost/iostreams/device/mapped_file.hpp>
 #include "detail/temp_file.hpp"
 #include "detail/verification.hpp"
 
-using namespace std;
-using namespace boost;
-using namespace boost::iostreams;
-using namespace boost::iostreams::test;
-using boost::unit_test::test_suite;
-
 // Code generation bugs cause tests to fail with global optimization.
 #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
 # pragma optimize("g", off)
 #endif
 
+namespace boost { namespace iostreams { namespace test {
+
+bool test_writeable(mapped_file& mf)
+{
+ // Test writing
+ for (int i = 0; i < data_reps; ++i) {
+ memcpy(mf.data(), narrow_data(), chunk_size);
+ char buf[chunk_size];
+ memcpy(buf, mf.const_data(), chunk_size);
+ if (strncmp(buf, narrow_data(), chunk_size) != 0)
+ return false;
+ memset(mf.data(), 0, chunk_size);
+ }
+ return true;
+}
+
+bool test_resizeable(mapped_file& mf)
+{
+ // Test resizing
+ mapped_file::size_type size = mf.size();
+ if (size == 0)
+ return false;
+ mf.resize(size/2);
+ if (mf.size() != size/2)
+ return false;
+ mf.resize(size);
+ if (mf.size() != size)
+ return false;
+ return true;
+}
+
+} } } // End namespaces test, iostreams, boost.
+
 void mapped_file_test()
 {
+ using namespace boost::iostreams;
     BOOST_MESSAGE("about to begin");
 
     //--------------Reading from a mapped_file_source-------------------------//
@@ -38,13 +75,13 @@
 
         // Test reading from a stream based on a mapped_file_source,
         // in chars.
- test_file test1, test2;
- stream<mapped_file_source> first(test1.name());
+ boost::iostreams::test::test_file test1, test2;
+ boost::iostreams::stream<mapped_file_source> first(test1.name());
         {
- ifstream second( test2.name().c_str(),
+ std::ifstream second( test2.name().c_str(),
                              BOOST_IOS::in | BOOST_IOS::binary );
             BOOST_CHECK_MESSAGE(
- compare_streams_in_chars(first, second),
+ boost::iostreams::test::compare_streams_in_chars(first, second),
                 "failed reading from stream<mapped_file_source> in chars"
             );
 
@@ -56,12 +93,12 @@
 
         // Test reading from a stream based on a mapped_file_source,
         // in chunks. (Also tests reopening the stream.)
- first.open(mapped_file_source(test1.name()));
+ first.open(mapped_file_source(test1.name()));
         {
- ifstream second( test2.name().c_str(),
+ std::ifstream second( test2.name().c_str(),
                              BOOST_IOS::in | BOOST_IOS::binary );
             BOOST_CHECK_MESSAGE(
- compare_streams_in_chunks(first, second),
+ boost::iostreams::test::compare_streams_in_chunks(first, second),
                 "failed reading from stream<mapped_file_source> in chunks"
             );
 
@@ -76,15 +113,15 @@
     {
         // Test writing to a stream based on a mapped_file_sink, in
         // chars.
- uppercase_file first, second; // Will overwrite these.
- test_file test;
+ boost::iostreams::test::uppercase_file first, second; // Will overwrite these.
+ boost::iostreams::test::test_file test;
 
- stream<mapped_file_sink> out;
- out.open(mapped_file_sink(first.name()));
- write_data_in_chars(out);
+ boost::iostreams::stream<mapped_file_sink> out;
+ out.open(mapped_file_sink(first.name()));
+ boost::iostreams::test::write_data_in_chars(out);
         out.close();
         BOOST_CHECK_MESSAGE(
- compare_files(first.name(), test.name()),
+ boost::iostreams::test::compare_files(first.name(), test.name()),
             "failed writing to stream<mapped_file_sink> in chars"
         );
 
@@ -94,11 +131,11 @@
 
         // Test writing to a stream based on a mapped_file_sink, in
         // chunks. (Also tests reopening the stream.)
- out.open(mapped_file_sink(second.name()));
- write_data_in_chunks(out);
+ out.open(mapped_file_sink(second.name()));
+ boost::iostreams::test::write_data_in_chunks(out);
         out.close();
         BOOST_CHECK_MESSAGE(
- compare_files(second.name(), test.name()),
+ boost::iostreams::test::compare_files(second.name(), test.name()),
             "failed writing to stream<mapped_file_sink> in chunks"
         );
 
@@ -107,21 +144,21 @@
         );
     }
 
- //--------------Writing to a newly created file-----------------------------//
+ //--------------Writing to a newly created file---------------------------//
 
     {
         // Test writing to a newly created mapped file.
- temp_file first, second;
- test_file test;
+ boost::iostreams::test::temp_file first, second;
+ boost::iostreams::test::test_file test;
 
- mapped_file_params p(first.name());
- p.new_file_size = data_reps * data_length();
- stream<mapped_file_sink> out;
- out.open(mapped_file_sink(p));
- write_data_in_chars(out);
+ mapped_file_params p(first.name());
+ p.new_file_size = boost::iostreams::test::data_reps * boost::iostreams::test::data_length();
+ boost::iostreams::stream<mapped_file_sink> out;
+ out.open(mapped_file_sink(p));
+ boost::iostreams::test::write_data_in_chars(out);
         out.close();
         BOOST_CHECK_MESSAGE(
- compare_files(first.name(), test.name()),
+ boost::iostreams::test::compare_files(first.name(), test.name()),
             "failed writing to newly created mapped file in chars"
         );
 
@@ -129,11 +166,11 @@
         // Test writing to a newly created mapped file.
         // (Also tests reopening the stream.)
         p.path = second.name();
- out.open(mapped_file_sink(p));
- write_data_in_chunks(out);
+ out.open(mapped_file_sink(p));
+ boost::iostreams::test::write_data_in_chunks(out);
         out.close();
         BOOST_CHECK_MESSAGE(
- compare_files(second.name(), test.name()),
+ boost::iostreams::test::compare_files(second.name(), test.name()),
             "failed writing to newly created mapped file in chunks"
         );
     }
@@ -143,11 +180,11 @@
     {
         // Test reading, writing and seeking within a stream based on a
         // mapped_file, in chars.
- test_file test;
- stream<mapped_file> io;
- io.open(mapped_file(test.name()));
+ boost::iostreams::test::test_file test;
+ boost::iostreams::stream<mapped_file> io;
+ io.open(mapped_file(test.name()));
         BOOST_CHECK_MESSAGE(
- test_seekable_in_chars(io),
+ boost::iostreams::test::test_seekable_in_chars(io),
             "failed seeking within stream<mapped_file> in chars"
         );
 
@@ -160,9 +197,9 @@
         // Test reading, writing and seeking within a stream based on a
         // mapped_file, in chunks. (Also tests reopening the
         // stream.)
- io.open(mapped_file(test.name()));
+ io.open(mapped_file(test.name()));
         BOOST_CHECK_MESSAGE(
- test_seekable_in_chunks(io),
+ boost::iostreams::test::test_seekable_in_chunks(io),
             "failed seeking within stream<mapped_file> in chunks"
         );
 
@@ -170,15 +207,74 @@
             "done seeking within stream<mapped_file> in chunks"
         );
     }
+
+ //--------------Resizing a mapped_file------------------------------------//
+
+ {
+ // Test resizing a mapped_file.
+ boost::iostreams::test::test_file test;
+ mapped_file mf;
+ mf.open(test.name());
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::test::test_resizeable(mf),
+ "failed resizing a mapped_file"
+ );
+
+ BOOST_MESSAGE(
+ "done resizing a mapped_file"
+ );
+ }
+
+ //--------------Random access with a private mapped_file------------------//
+
+ {
+ // Use 2 copies of the file to compare later
+ boost::iostreams::test::test_file orig, copy;
+
+ // Test reading and writing within a mapped_file.
+ // Since the file is privately mapped, it should remain
+ // unchanged after writing when opened in readonly mode.
+ mapped_file mf;
+ mf.open(orig.name(), mapped_file::priv);
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::test::test_writeable(mf),
+ "failed seeking within private mapped_file"
+ );
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::test::compare_files(orig.name(), copy.name()),
+ "failed writing to private mapped_file"
+ );
+
+ BOOST_MESSAGE(
+ "done seeking within private mapped_file"
+ );
+
+ mf.close();
+
+ // Test reopening the mapped file.
+ mf.open(orig.name(), mapped_file::priv);
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::test::test_writeable(mf),
+ "failed reopening private mapped_file"
+ );
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::test::compare_files(orig.name(), copy.name()),
+ "failed writing to reopened private mapped_file"
+ );
+
+ BOOST_MESSAGE(
+ "done reopening private mapped_file"
+ );
+ }
 }
 
 #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
 # pragma optimize("", on)
 #endif
 
-test_suite* init_unit_test_suite(int, char* [])
+boost::unit_test::test_suite* init_unit_test_suite(int, char* [])
 {
- test_suite* test = BOOST_TEST_SUITE("mapped_file test");
+ boost::unit_test::test_suite* test = BOOST_TEST_SUITE("mapped_file test");
     test->add(BOOST_TEST_CASE(&mapped_file_test));
     return test;
 }


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