$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r62934 - in trunk: boost/iostreams/device libs/iostreams/src libs/iostreams/test libs/iostreams/test/detail
From: steven_at_[hidden]
Date: 2010-06-14 11:56:01
Author: steven_watanabe
Date: 2010-06-14 11:56:00 EDT (Mon, 14 Jun 2010)
New Revision: 62934
URL: http://svn.boost.org/trac/boost/changeset/62934
Log:
Rejigger file_descriptors handling of std::ios_base::openmode to match std::fstream.  In particular, truncate existing files, if std::ios_base::trunc is passed.  Refs #3323.
Text files modified: 
   trunk/boost/iostreams/device/file_descriptor.hpp   |     2                                         
   trunk/libs/iostreams/src/file_descriptor.cpp       |    35 +++-                                    
   trunk/libs/iostreams/test/detail/verification.hpp  |     7                                         
   trunk/libs/iostreams/test/file_descriptor_test.cpp |   315 +++++++++++++++++++++++++++++++++++++++ 
   4 files changed, 347 insertions(+), 12 deletions(-)
Modified: trunk/boost/iostreams/device/file_descriptor.hpp
==============================================================================
--- trunk/boost/iostreams/device/file_descriptor.hpp	(original)
+++ trunk/boost/iostreams/device/file_descriptor.hpp	2010-06-14 11:56:00 EDT (Mon, 14 Jun 2010)
@@ -115,7 +115,7 @@
     // open overload taking a detail::path
     void open( const detail::path& path, 
                BOOST_IOS::openmode, 
-               BOOST_IOS::openmode = BOOST_IOS::in | BOOST_IOS::out );
+               BOOST_IOS::openmode = BOOST_IOS::openmode(0) );
 
     typedef detail::file_descriptor_impl impl_type;
     shared_ptr<impl_type> pimpl_;
Modified: trunk/libs/iostreams/src/file_descriptor.cpp
==============================================================================
--- trunk/libs/iostreams/src/file_descriptor.cpp	(original)
+++ trunk/libs/iostreams/src/file_descriptor.cpp	2010-06-14 11:56:00 EDT (Mon, 14 Jun 2010)
@@ -113,18 +113,26 @@
         dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
         dwCreationDisposition =
             (mode & BOOST_IOS::trunc) ?
-                OPEN_ALWAYS :
+                CREATE_ALWAYS :
                 OPEN_EXISTING;
     } else if (mode & BOOST_IOS::in) {
-        if (mode & (BOOST_IOS::app |BOOST_IOS::trunc))
+        if (mode & (BOOST_IOS::app | BOOST_IOS::trunc))
             boost::throw_exception(BOOST_IOSTREAMS_FAILURE("bad open mode"));
         dwDesiredAccess = GENERIC_READ;
         dwCreationDisposition = OPEN_EXISTING;
     } else if (mode & BOOST_IOS::out) {
+        if ( (mode & (BOOST_IOS::app | BOOST_IOS::trunc))
+                 ==
+              (BOOST_IOS::app | BOOST_IOS::trunc) )
+            boost::throw_exception(BOOST_IOSTREAMS_FAILURE("bad open mode"));
         dwDesiredAccess = GENERIC_WRITE;
         dwCreationDisposition = OPEN_ALWAYS;
-        if (mode & BOOST_IOS::app)
+        if (mode & BOOST_IOS::app) {
+            dwCreationDisposition = OPEN_ALWAYS;
             flags_ |= append;
+        } else {
+            dwCreationDisposition = CREATE_ALWAYS;
+        }
     } else {
         boost::throw_exception(BOOST_IOSTREAMS_FAILURE("bad open mode"));
     }
@@ -160,19 +168,30 @@
              ==
          (BOOST_IOS::in | BOOST_IOS::out) )
     {
-        assert(!(mode & BOOST_IOS::app));
+        if( mode & BOOST_IOS::app )
+            boost::throw_exception(BOOST_IOSTREAMS_FAILURE("bad open mode"));
         oflag |= O_RDWR;
+        if( mode & BOOST_IOS::trunc ) {
+            oflag |= O_TRUNC;
+            oflag |= O_CREAT;
+        }
     } else if (mode & BOOST_IOS::in) {
-        assert(!(mode & (BOOST_IOS::app |BOOST_IOS::trunc)));
+        if( mode & (BOOST_IOS::app | BOOST_IOS::trunc) )
+            boost::throw_exception(BOOST_IOSTREAMS_FAILURE("bad open mode"));
         oflag |= O_RDONLY;
     } else if (mode & BOOST_IOS::out) {
+        if( mode & (BOOST_IOS::app | BOOST_IOS::trunc)
+               ==
+            (BOOST_IOS::app | BOOST_IOS::trunc) )
+            boost::throw_exception(BOOST_IOSTREAMS_FAILURE("bad open mode"));
         oflag |= O_WRONLY;
-        mode |= BOOST_IOS::trunc;
         if (mode & BOOST_IOS::app)
             oflag |= O_APPEND;
+        else {
+            oflag |= O_CREAT;
+            oflag |= O_TRUNC; 
+        }
     }
-    if (mode & BOOST_IOS::trunc)
-        oflag |= O_CREAT;
     #ifdef _LARGEFILE64_SOURCE
         oflag |= O_LARGEFILE;
     #endif
Modified: trunk/libs/iostreams/test/detail/verification.hpp
==============================================================================
--- trunk/libs/iostreams/test/detail/verification.hpp	(original)
+++ trunk/libs/iostreams/test/detail/verification.hpp	2010-06-14 11:56:00 EDT (Mon, 14 Jun 2010)
@@ -100,6 +100,13 @@
     return true;
 }
 
+template<typename Container>
+bool compare_container_and_file(Container& cnt, const std::string& file)
+{
+    std::ifstream fstrm(file.c_str(), BOOST_IOS::in | BOOST_IOS::binary);
+    return compare_container_and_stream(cnt, fstrm);
+}
+
 BOOST_TEMPLATE_DECL
 void write_data_in_chars(BOOST_OSTREAM& os)
 {
Modified: trunk/libs/iostreams/test/file_descriptor_test.cpp
==============================================================================
--- trunk/libs/iostreams/test/file_descriptor_test.cpp	(original)
+++ trunk/libs/iostreams/test/file_descriptor_test.cpp	2010-06-14 11:56:00 EDT (Mon, 14 Jun 2010)
@@ -80,9 +80,41 @@
         first->close();
         BOOST_CHECK(!first->is_open());
     }
+    
+    // test illegal flag combinations
+    {
+        BOOST_CHECK_THROW(
+            file_descriptor_source(test1.name(),
+                BOOST_IOS::app),
+            BOOST_IOSTREAMS_FAILURE);
+        BOOST_CHECK_THROW(
+            file_descriptor_source(test1.name(),
+                BOOST_IOS::trunc),
+            BOOST_IOSTREAMS_FAILURE);
+        BOOST_CHECK_THROW(
+            file_descriptor_source(test1.name(),
+                BOOST_IOS::app | BOOST_IOS::trunc),
+            BOOST_IOSTREAMS_FAILURE);
+        BOOST_CHECK_THROW(
+            file_descriptor_source(test1.name(),
+                BOOST_IOS::out),
+            BOOST_IOSTREAMS_FAILURE);
+        BOOST_CHECK_THROW(
+            file_descriptor_source(test1.name(),
+                BOOST_IOS::out | BOOST_IOS::app),
+            BOOST_IOSTREAMS_FAILURE);
+        BOOST_CHECK_THROW(
+            file_descriptor_source(test1.name(),
+                BOOST_IOS::out | BOOST_IOS::trunc),
+            BOOST_IOSTREAMS_FAILURE);
+        BOOST_CHECK_THROW(
+            file_descriptor_source(test1.name(),
+                BOOST_IOS::out | BOOST_IOS::app | BOOST_IOS::trunc),
+            BOOST_IOSTREAMS_FAILURE);
+    }
 
     //--------------Test file_descriptor_sink---------------------------------//
-                                                    
+
     {
         temp_file             temp;
         file_descriptor_sink  file(temp.name(), BOOST_IOS::trunc);
@@ -142,11 +174,78 @@
         file.close();
         BOOST_CHECK(!file.is_open());
     }
+                                                    
+    {
+        temp_file             temp;
+        // set up the tests
+        {
+            file_descriptor_sink  file(temp.name(), BOOST_IOS::trunc);
+            fdostream             out(file);
+            write_data_in_chunks(out);
+            out.close();
+            file.close();
+        }
+        // test std::ios_base::app
+        {
+            file_descriptor_sink  file(temp.name(), BOOST_IOS::app);
+            fdostream             out(file);
+            BOOST_CHECK(out->is_open());
+            write_data_in_chars(out);
+            out.close();
+            std::string expected(narrow_data());
+            expected += narrow_data();
+            BOOST_CHECK_MESSAGE(
+                compare_container_and_file(expected, temp.name()),
+                "failed writing to file_descriptor_sink in append mode"
+            );
+            file.close();
+            BOOST_CHECK(!file.is_open());
+        }
+        // test std::ios_base::trunc
+        {
+            file_descriptor_sink  file(temp.name(), BOOST_IOS::trunc);
+            fdostream             out(file);
+            BOOST_CHECK(out->is_open());
+            write_data_in_chars(out);
+            out.close();
+            BOOST_CHECK_MESSAGE(
+                compare_files(test1.name(), temp.name()),
+                "failed writing to file_descriptor_sink in trunc mode"
+            );
+            file.close();
+            BOOST_CHECK(!file.is_open());
+        }
+        
+        // test illegal flag combinations
+        {
+            BOOST_CHECK_THROW(
+                file_descriptor_sink(temp.name(),
+                    BOOST_IOS::trunc | BOOST_IOS::app),
+                BOOST_IOSTREAMS_FAILURE);
+            BOOST_CHECK_THROW(
+                file_descriptor_sink(temp.name(),
+                    BOOST_IOS::in),
+                BOOST_IOSTREAMS_FAILURE);
+            BOOST_CHECK_THROW(
+                file_descriptor_sink(temp.name(),
+                    BOOST_IOS::in | BOOST_IOS::app),
+                BOOST_IOSTREAMS_FAILURE);
+            BOOST_CHECK_THROW(
+                file_descriptor_sink(temp.name(),
+                    BOOST_IOS::in | BOOST_IOS::trunc),
+                BOOST_IOSTREAMS_FAILURE);
+            BOOST_CHECK_THROW(
+                file_descriptor_sink(temp.name(),
+                    BOOST_IOS::in | BOOST_IOS::trunc | BOOST_IOS::app),
+                BOOST_IOSTREAMS_FAILURE);
+        }
+    }
 
     //--Test seeking with file_descriptor_source and file_descriptor_sink-----//
 
+    test_file test3;
     {
-        file_descriptor_sink  sink(test1.name());
+        file_descriptor_sink  sink(test3.name());
         fdostream             out(sink);
         BOOST_CHECK(out->is_open());
         BOOST_CHECK_MESSAGE(
@@ -156,7 +255,7 @@
         out->close();
         BOOST_CHECK(!out->is_open());
 
-        file_descriptor_source  source(test1.name());
+        file_descriptor_source  source(test3.name());
         fdistream               in(source);
         BOOST_CHECK(in->is_open());
         BOOST_CHECK_MESSAGE(
@@ -196,6 +295,216 @@
             "failed seeking within a file_descriptor, in chunks"
         );
     }
+    
+    //--------------Test read-only file_descriptor----------------------------//
+    
+    {
+        fdstream   first(file_descriptor(test1.name(), BOOST_IOS::in), 0);
+        ifstream   second(test2.name().c_str());
+        BOOST_CHECK(first->is_open());
+        write_data_in_chars(first);
+        BOOST_CHECK(first.fail());
+        first.clear();
+        BOOST_CHECK_MESSAGE(
+            compare_streams_in_chars(first, second),
+            "failed reading from file_descriptor in chars with no buffer"
+        );
+        first->close();
+        BOOST_CHECK(!first->is_open());
+    }
+
+    {
+        fdstream   first(file_descriptor(test1.name(), BOOST_IOS::in), 0);
+        ifstream   second(test2.name().c_str());
+        BOOST_CHECK(first->is_open());
+        write_data_in_chunks(first);
+        BOOST_CHECK(first.fail());
+        first.clear();
+        BOOST_CHECK_MESSAGE(
+            compare_streams_in_chunks(first, second),
+            "failed reading from file_descriptor in chunks with no buffer"
+        );
+        first->close();
+        BOOST_CHECK(!first->is_open());
+    }
+
+    {
+        file_descriptor         file(test1.name(), BOOST_IOS::in);
+        fdstream                first(file);
+        ifstream                second(test2.name().c_str());
+        BOOST_CHECK(first->is_open());
+        write_data_in_chars(first);
+        BOOST_CHECK(first.fail());
+        first.clear();
+        first.seekg(0, BOOST_IOS::beg);
+        BOOST_CHECK_MESSAGE(
+            compare_streams_in_chars(first, second),
+            "failed reading from file_descriptor in chars with buffer"
+        );
+        first->close();
+        BOOST_CHECK(!first->is_open());
+    }
+
+    {
+        file_descriptor         file(test1.name(), BOOST_IOS::in);
+        fdstream                first(file);
+        ifstream                second(test2.name().c_str());
+        BOOST_CHECK(first->is_open());
+        write_data_in_chunks(first);
+        BOOST_CHECK(first.fail());
+        first.clear();
+        first.seekg(0, BOOST_IOS::beg);
+        BOOST_CHECK_MESSAGE(
+            compare_streams_in_chunks(first, second),
+            "failed reading from file_descriptor in chunks with buffer"
+        );
+        first->close();
+        BOOST_CHECK(!first->is_open());
+    }
+
+    //--------------Test write-only file_descriptor---------------------------//
+    {
+        temp_file             temp;
+        file_descriptor       file( temp.name(),
+                                    BOOST_IOS::out |
+                                    BOOST_IOS::trunc );
+        fdstream              out(file, 0);
+        BOOST_CHECK(out->is_open());
+        out.get();
+        BOOST_CHECK(out.fail());
+        out.clear();
+        write_data_in_chars(out);
+        out.seekg(0, BOOST_IOS::beg);
+        out.get();
+        BOOST_CHECK(out.fail());
+        out.clear();
+        out.close();
+        BOOST_CHECK_MESSAGE(
+            compare_files(test1.name(), temp.name()),
+            "failed writing to file_descriptor in chars with no buffer"
+        );
+        file.close();
+        BOOST_CHECK(!file.is_open());
+    }
+
+    {
+        temp_file             temp;
+        file_descriptor       file( temp.name(),
+                                    BOOST_IOS::out |
+                                    BOOST_IOS::trunc );
+        fdstream              out(file, 0);
+        BOOST_CHECK(out->is_open());
+        out.get();
+        BOOST_CHECK(out.fail());
+        out.clear();
+        write_data_in_chunks(out);
+        out.seekg(0, BOOST_IOS::beg);
+        out.get();
+        BOOST_CHECK(out.fail());
+        out.clear();
+        out.close();
+        BOOST_CHECK_MESSAGE(
+            compare_files(test1.name(), temp.name()),
+            "failed writing to file_descriptor_sink in chunks with no buffer"
+        );
+        file.close();
+        BOOST_CHECK(!file.is_open());
+    }
+
+    {
+        temp_file             temp;
+        file_descriptor       file( temp.name(),
+                                    BOOST_IOS::out |
+                                    BOOST_IOS::trunc );
+        fdstream              out(file);
+        BOOST_CHECK(out->is_open());
+        out.get();
+        BOOST_CHECK(out.fail());
+        out.clear();
+        write_data_in_chars(out);
+        out.seekg(0, BOOST_IOS::beg);
+        out.get();
+        BOOST_CHECK(out.fail());
+        out.clear();
+        out.close();
+        BOOST_CHECK_MESSAGE(
+            compare_files(test1.name(), temp.name()),
+            "failed writing to file_descriptor_sink in chars with buffer"
+        );
+        file.close();
+        BOOST_CHECK(!file.is_open());
+    }
+
+    {
+        temp_file             temp;
+        file_descriptor       file( temp.name(),
+                                    BOOST_IOS::out |
+                                    BOOST_IOS::trunc );
+        fdstream              out(file);
+        BOOST_CHECK(out->is_open());
+        out.get();
+        BOOST_CHECK(out.fail());
+        out.clear();
+        write_data_in_chunks(out);
+        out.seekg(0, BOOST_IOS::beg);
+        out.get();
+        BOOST_CHECK(out.fail());
+        out.clear();
+        out.close();
+        BOOST_CHECK_MESSAGE(
+            compare_files(test1.name(), temp.name()),
+            "failed writing to file_descriptor_sink in chunks with buffer"
+        );
+        file.close();
+        BOOST_CHECK(!file.is_open());
+    }
+
+    // test illegal flag combinations
+    {
+        BOOST_CHECK_THROW(
+            file_descriptor(test1.name(),
+                BOOST_IOS::openmode(0)),
+            BOOST_IOSTREAMS_FAILURE);
+        BOOST_CHECK_THROW(
+            file_descriptor(test1.name(),
+                BOOST_IOS::app),
+            BOOST_IOSTREAMS_FAILURE);
+        BOOST_CHECK_THROW(
+            file_descriptor(test1.name(),
+                BOOST_IOS::trunc),
+            BOOST_IOSTREAMS_FAILURE);
+        BOOST_CHECK_THROW(
+            file_descriptor(test1.name(),
+                BOOST_IOS::app | BOOST_IOS::trunc),
+            BOOST_IOSTREAMS_FAILURE);
+        BOOST_CHECK_THROW(
+            file_descriptor(test1.name(),
+                BOOST_IOS::in | BOOST_IOS::app),
+            BOOST_IOSTREAMS_FAILURE);
+        BOOST_CHECK_THROW(
+            file_descriptor(test1.name(),
+                BOOST_IOS::in | BOOST_IOS::trunc),
+            BOOST_IOSTREAMS_FAILURE);
+        BOOST_CHECK_THROW(
+            file_descriptor(test1.name(),
+                BOOST_IOS::in | BOOST_IOS::app | BOOST_IOS::trunc),
+            BOOST_IOSTREAMS_FAILURE);
+        BOOST_CHECK_THROW(
+            file_descriptor(test1.name(),
+                BOOST_IOS::out | BOOST_IOS::app | BOOST_IOS::trunc),
+            BOOST_IOSTREAMS_FAILURE);
+        BOOST_CHECK_THROW(
+            file_descriptor(test1.name(),
+                BOOST_IOS::in | BOOST_IOS::out | BOOST_IOS::app),
+            BOOST_IOSTREAMS_FAILURE);
+        BOOST_CHECK_THROW(
+            file_descriptor(test1.name(),
+                BOOST_IOS::in |
+                BOOST_IOS::out |
+                BOOST_IOS::app |
+                BOOST_IOS::trunc),
+            BOOST_IOSTREAMS_FAILURE);
+    }
 }
 
 test_suite* init_unit_test_suite(int, char* [])