Boost logo

Boost-Commit :

From: technews_at_[hidden]
Date: 2007-12-25 20:07:13


Author: turkanis
Date: 2007-12-25 20:07:12 EST (Tue, 25 Dec 2007)
New Revision: 42305
URL: http://svn.boost.org/trac/boost/changeset/42305

Log:
Resolved issue #1033 (iostreams)

  restrict.hpp:
    - added static asserts to prevent using restrict with bidirectional filters
      and devices (since it would not be clear which of the two sequences is to
      be restricted). To restrict a bidirectional component, combine the
      restrictions of a read-only and a write-only view of the component, using
      combine() and detail::mode_adapter (which should probably be made public)
    - added special treatment for dual_use filters, to make sure the "which"
      argument to seek is set correctly (although I don't know of any examples
      of seekable dual use filters)
  skip.hpp:
    - added a "which" parameter to skip() for filters
    - added more fine-grained analysis of modes to determine whether to call
      the optimized version of detail::skip()
    - added static asserts to rule out the case where skip is called with
      a non-seekable output-only device
  test/close_test.cpp
    - removed uses of restrict with bidirectional devices, since this doesn't
      make sense and is now officially prohibited
    
  
Text files modified:
   branches/iostreams_dev/boost/iostreams/restrict.hpp | 37 +++++++++++++++++++++----
   branches/iostreams_dev/boost/iostreams/skip.hpp | 49 +++++++++++++++++++++++++---------
   branches/iostreams_dev/libs/iostreams/test/close_test.cpp | 57 ----------------------------------------
   3 files changed, 66 insertions(+), 77 deletions(-)

Modified: branches/iostreams_dev/boost/iostreams/restrict.hpp
==============================================================================
--- branches/iostreams_dev/boost/iostreams/restrict.hpp (original)
+++ branches/iostreams_dev/boost/iostreams/restrict.hpp 2007-12-25 20:07:12 EST (Tue, 25 Dec 2007)
@@ -49,9 +49,11 @@
 private:
     typedef typename detail::param_type<Device>::type param_type;
 public:
- typedef typename char_type_of<Device>::type char_type;
+ typedef typename char_type_of<Device>::type char_type;
+ typedef typename mode_of<Device>::type mode;
+ BOOST_STATIC_ASSERT(!(is_convertible<mode, detail::two_sequence>::value));
     struct category
- : mode_of<Device>::type,
+ : mode,
           device_tag,
           closable_tag,
           flushable_tag,
@@ -78,6 +80,8 @@
 public:
     typedef typename char_type_of<Device>::type char_type;
     typedef std::pair<char_type*, char_type*> pair_type;
+ typedef typename mode_of<Device>::type mode;
+ BOOST_STATIC_ASSERT(!(is_convertible<mode, detail::two_sequence>::value));
     struct category
         : mode_of<Device>::type,
           device_tag,
@@ -105,8 +109,10 @@
 class restricted_filter : public filter_adapter<Filter> {
 public:
     typedef typename char_type_of<Filter>::type char_type;
+ typedef typename mode_of<Filter>::type mode;
+ BOOST_STATIC_ASSERT(!(is_convertible<mode, detail::two_sequence>::value));
     struct category
- : mode_of<Filter>::type,
+ : mode,
           filter_tag,
           multichar_tag,
           closable_tag,
@@ -121,7 +127,7 @@
     {
         using namespace std;
         if (!open_)
- open(src);
+ open(src, BOOST_IOS::in);
         streamsize amt =
             end_ != -1 ?
                 (std::min) (n, static_cast<streamsize>(end_ - pos_)) :
@@ -136,7 +142,7 @@
     std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
     {
         if (!open_)
- open(snk);
+ open(snk, BOOST_IOS::out);
         if (end_ != -1 && pos_ + n >= end_)
             bad_write();
         std::streamsize result =
@@ -167,13 +173,30 @@
         pos_ = this->component().seek(dev, next, BOOST_IOS::cur);
         return offset_to_position(pos_ - beg_);
     }
+
+ template<typename Device>
+ void close(Device& dev)
+ {
+ open_ = false;
+ detail::close_all(this->component(), dev);
+ }
+
+ template<typename Device>
+ void close(Device& dev, BOOST_IOS::openmode which)
+ {
+ open_ = false;
+ iostreams::close(this->component(), dev, which);
+ }
 private:
     template<typename Device>
- void open(Device& dev)
+ void open(Device& dev, BOOST_IOS::openmode which)
     {
+ typedef typename is_convertible<mode, dual_use>::type is_dual_use;
         open_ = true;
- iostreams::skip(this->component(), dev, beg_);
+ which = is_dual_use() ? which : (BOOST_IOS::in | BOOST_IOS::out);
+ iostreams::skip(this->component(), dev, beg_, which);
     }
+
     stream_offset beg_, pos_, end_;
     bool open_;
 };

Modified: branches/iostreams_dev/boost/iostreams/skip.hpp
==============================================================================
--- branches/iostreams_dev/boost/iostreams/skip.hpp (original)
+++ branches/iostreams_dev/boost/iostreams/skip.hpp 2007-12-25 20:07:12 EST (Tue, 25 Dec 2007)
@@ -16,9 +16,11 @@
 #include <boost/iostreams/char_traits.hpp>
 #include <boost/iostreams/detail/ios.hpp> // failure.
 #include <boost/iostreams/operations.hpp>
+#include <boost/iostreams/seek.hpp>
 #include <boost/iostreams/traits.hpp>
 #include <boost/mpl/and.hpp>
 #include <boost/mpl/bool.hpp>
+#include <boost/mpl/or.hpp>
 #include <boost/type_traits/is_convertible.hpp>
 
 namespace boost { namespace iostreams {
@@ -44,11 +46,13 @@
 }
 
 template<typename Filter, typename Device>
-void skip(Filter& flt, Device& dev, stream_offset off, mpl::true_)
-{ flt.seek(dev, off, BOOST_IOS::cur); }
+void skip( Filter& flt, Device& dev, stream_offset off,
+ BOOST_IOS::openmode which, mpl::true_ )
+{ boost::iostreams::seek(flt, dev, off, BOOST_IOS::cur, which); }
 
 template<typename Filter, typename Device>
-void skip(Filter& flt, Device& dev, stream_offset off, mpl::false_)
+void skip( Filter& flt, Device& dev, stream_offset off,
+ BOOST_IOS::openmode, mpl::false_ )
 {
     typedef typename char_type_of<Device>::type char_type;
     char_type c;
@@ -66,20 +70,39 @@
 template<typename Device>
 void skip(Device& dev, stream_offset off)
 {
- typedef typename mode_of<Device>::type mode;
- detail::skip(dev, off, is_convertible<mode, seekable>());
+ typedef typename mode_of<Device>::type mode;
+ typedef mpl::or_<
+ is_convertible<mode, input_seekable>,
+ is_convertible<mode, output_seekable>
+ > can_seek;
+ BOOST_STATIC_ASSERT(
+ (can_seek::value || is_convertible<mode, input>::value)
+ );
+ detail::skip(dev, off, can_seek());
 }
 
 template<typename Filter, typename Device>
-void skip(Filter& flt, Device& dev, stream_offset off)
+void skip( Filter& flt, Device& dev, stream_offset off,
+ BOOST_IOS::openmode which = BOOST_IOS::in | BOOST_IOS::out )
 {
- typedef typename mode_of<Filter>::type filter_mode;
- typedef typename mode_of<Device>::type device_mode;
- typedef mpl::and_<
- is_convertible<filter_mode, output_seekable>,
- is_convertible<device_mode, output_seekable>
- > can_seek;
- detail::skip(flt, dev, off, can_seek());
+ typedef typename mode_of<Filter>::type filter_mode;
+ typedef typename mode_of<Device>::type device_mode;
+ typedef mpl::or_<
+ mpl::and_<
+ is_convertible<filter_mode, input_seekable>,
+ is_convertible<device_mode, input_seekable>
+ >,
+ mpl::and_<
+ is_convertible<filter_mode, output_seekable>,
+ is_convertible<device_mode, output_seekable>
+ >
+ > can_seek;
+ BOOST_STATIC_ASSERT(
+ ( can_seek::value ||
+ is_convertible<filter_mode, input>::value &&
+ is_convertible<device_mode, input>::value )
+ );
+ detail::skip(flt, dev, off, which, can_seek());
 }
 
 } } // End namespaces iostreams, boost.

Modified: branches/iostreams_dev/libs/iostreams/test/close_test.cpp
==============================================================================
--- branches/iostreams_dev/libs/iostreams/test/close_test.cpp (original)
+++ branches/iostreams_dev/libs/iostreams/test/close_test.cpp 2007-12-25 20:07:12 EST (Tue, 25 Dec 2007)
@@ -1062,23 +1062,6 @@
         BOOST_CHECK_OPERATION_SEQUENCE(seq);
     }
 
- // Restrict a bidirectional device
- {
- operation_sequence seq;
- chain<bidirectional> ch;
- ch.push(
- io::restrict(
- closable_device<bidirectional>(
- seq.new_operation(1),
- seq.new_operation(2)
- ),
- 0
- )
- );
- BOOST_CHECK_NO_THROW(ch.reset());
- BOOST_CHECK_OPERATION_SEQUENCE(seq);
- }
-
     // Restrict a seekable device
     {
         operation_sequence seq;
@@ -1101,23 +1084,6 @@
         BOOST_CHECK_OPERATION_SEQUENCE(seq);
     }
 
- // Restrict a direct bidirectional device
- {
- operation_sequence seq;
- chain<bidirectional> ch;
- ch.push(
- io::restrict(
- closable_device<direct_bidirectional>(
- seq.new_operation(1),
- seq.new_operation(2)
- ),
- 0
- )
- );
- BOOST_CHECK_NO_THROW(ch.reset());
- BOOST_CHECK_OPERATION_SEQUENCE(seq);
- }
-
     // Restrict a direct seekable device
     {
         operation_sequence seq;
@@ -1142,29 +1108,6 @@
         BOOST_CHECK_OPERATION_SEQUENCE(seq);
     }
 
- // Restrict a bidirectional filter
- {
- operation_sequence seq;
- chain<bidirectional> ch;
- ch.push(
- io::restrict(
- closable_filter<bidirectional>(
- seq.new_operation(2),
- seq.new_operation(3)
- ),
- 0
- )
- );
- ch.push(
- closable_device<bidirectional>(
- seq.new_operation(1),
- seq.new_operation(4)
- )
- );
- BOOST_CHECK_NO_THROW(ch.reset());
- BOOST_CHECK_OPERATION_SEQUENCE(seq);
- }
-
     // Restrict a seekable filter
     {
         operation_sequence seq;


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