ossrv_pub/boost_apis/boost/iostreams/chain.hpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 // (C) Copyright Jonathan Turkanis 2003.
       
     2 // Distributed under the Boost Software License, Version 1.0. (See accompanying
       
     3 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
       
     4 
       
     5 // See http://www.boost.org/libs/iostreams for documentation.
       
     6 
       
     7 #ifndef BOOST_IOSTREAMS_DETAIL_CHAIN_HPP_INCLUDED
       
     8 #define BOOST_IOSTREAMS_DETAIL_CHAIN_HPP_INCLUDED
       
     9 
       
    10 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
       
    11 # pragma once
       
    12 #endif
       
    13 
       
    14 #include <algorithm>                            // for_each.
       
    15 #include <cassert>
       
    16 #include <exception>
       
    17 #include <functional>                           // unary_function.
       
    18 #include <iterator>                             // advance.
       
    19 #include <list>
       
    20 #include <memory>                               // allocator, auto_ptr.
       
    21 #include <typeinfo>
       
    22 #include <stdexcept>                            // logic_error, out_of_range.
       
    23 #include <boost/checked_delete.hpp>
       
    24 #include <boost/config.hpp>                     // BOOST_MSVC, template friends,
       
    25 #include <boost/detail/workaround.hpp>          // BOOST_NESTED_TEMPLATE 
       
    26 #include <boost/iostreams/constants.hpp>
       
    27 #include <boost/iostreams/detail/access_control.hpp>
       
    28 #include <boost/iostreams/detail/char_traits.hpp>
       
    29 #include <boost/iostreams/detail/push.hpp>
       
    30 #include <boost/iostreams/detail/streambuf.hpp> // pubsync.
       
    31 #include <boost/iostreams/detail/wrap_unwrap.hpp>
       
    32 #include <boost/iostreams/device/null.hpp>
       
    33 #include <boost/iostreams/positioning.hpp>
       
    34 #include <boost/iostreams/traits.hpp>           // is_filter.
       
    35 #include <boost/iostreams/stream_buffer.hpp>
       
    36 #include <boost/next_prior.hpp>
       
    37 #include <boost/shared_ptr.hpp>
       
    38 #include <boost/static_assert.hpp>
       
    39 #include <boost/type_traits/is_convertible.hpp>
       
    40 #include <boost/type.hpp>
       
    41 #if BOOST_WORKAROUND(BOOST_MSVC, < 1310)
       
    42 # include <boost/mpl/int.hpp>
       
    43 #endif
       
    44 
       
    45 // Sometimes type_info objects must be compared by name. Borrowed from
       
    46 // Boost.Python and Boost.Function.
       
    47 #if (defined(__GNUC__) && __GNUC__ >= 3) || \
       
    48      defined(_AIX) || \
       
    49     (defined(__sgi) && defined(__host_mips)) || \
       
    50     (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC)) \
       
    51     /**/
       
    52 # include <cstring>
       
    53 # define BOOST_IOSTREAMS_COMPARE_TYPE_ID(X,Y) \
       
    54      (std::strcmp((X).name(),(Y).name()) == 0)
       
    55 #else
       
    56 # define BOOST_IOSTREAMS_COMPARE_TYPE_ID(X,Y) ((X)==(Y))
       
    57 #endif
       
    58 
       
    59 // Deprecated
       
    60 #define BOOST_IOSTREAMS_COMPONENT_TYPE(chain, index) \
       
    61     chain.component_type( index ) \
       
    62     /**/
       
    63 
       
    64 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1310)
       
    65 # define BOOST_IOSTREAMS_COMPONENT(chain, index, target) \
       
    66     chain.component< target >( index ) \
       
    67     /**/
       
    68 #else
       
    69 # define BOOST_IOSTREAMS_COMPONENT(chain, index, target) \
       
    70     chain.component( index, ::boost::type< target >() ) \
       
    71     /**/
       
    72 #endif
       
    73 
       
    74 namespace boost { namespace iostreams {
       
    75 
       
    76 //--------------Definition of chain and wchain--------------------------------//
       
    77 
       
    78 namespace detail {
       
    79 
       
    80 template<typename Chain> class chain_client;
       
    81 
       
    82 //
       
    83 // Concept name: Chain.
       
    84 // Description: Represents a chain of stream buffers which provides access
       
    85 //     to the first buffer in the chain and send notifications when the
       
    86 //     streambufs are added to or removed from chain.
       
    87 // Refines: Closable device with mode equal to typename Chain::mode.
       
    88 // Models: chain, converting_chain.
       
    89 // Example:
       
    90 //
       
    91 //    class chain {
       
    92 //    public:
       
    93 //        typedef xxx chain_type;
       
    94 //        typedef xxx client_type;
       
    95 //        typedef xxx mode;
       
    96 //        bool is_complete() const;                  // Ready for i/o.
       
    97 //        template<typename T>
       
    98 //        void push( const T& t,                     // Adds a stream buffer to
       
    99 //                   streamsize,                     // chain, based on t, with
       
   100 //                   streamsize );                   // given buffer and putback
       
   101 //                                                   // buffer sizes. Pass -1 to
       
   102 //                                                   // request default size.
       
   103 //    protected:
       
   104 //        void register_client(client_type* client); // Associate client.
       
   105 //        void notify();                             // Notify client.
       
   106 //    };
       
   107 //
       
   108 
       
   109 //
       
   110 // Description: Represents a chain of filters with an optional device at the
       
   111 //      end.
       
   112 // Template parameters:
       
   113 //      Self - A class deriving from the current instantiation of this template.
       
   114 //          This is an example of the Curiously Recurring Template Pattern.
       
   115 //      Ch - The character type.
       
   116 //      Tr - The character traits type.
       
   117 //      Alloc - The allocator type.
       
   118 //      Mode - A mode tag.
       
   119 //
       
   120 template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
       
   121 class chain_base {
       
   122 public:
       
   123     typedef Ch                                     char_type;
       
   124     BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(Tr)
       
   125     typedef Alloc                                  allocator_type;
       
   126     typedef Mode                                   mode;
       
   127     struct category
       
   128         : Mode,
       
   129           device_tag
       
   130         { };
       
   131     typedef chain_client<Self>                     client_type;
       
   132     friend class chain_client<Self>;
       
   133 private:
       
   134     typedef linked_streambuf<Ch>                   streambuf_type;
       
   135     typedef std::list<streambuf_type*>             list_type;
       
   136     typedef chain_base<Self, Ch, Tr, Alloc, Mode>  my_type;
       
   137 protected:
       
   138     chain_base() : pimpl_(new chain_impl) { }
       
   139     chain_base(const chain_base& rhs): pimpl_(rhs.pimpl_) { }
       
   140 public:
       
   141 
       
   142     //----------Buffer sizing-------------------------------------------------//
       
   143 
       
   144     // Sets the size of the buffer created for the devices to be added to this
       
   145     // chain. Does not affect the size of the buffer for devices already
       
   146     // added.
       
   147     void set_device_buffer_size(int n) { pimpl_->device_buffer_size_ = n; }
       
   148 
       
   149     // Sets the size of the buffer created for the filters to be added
       
   150     // to this chain. Does not affect the size of the buffer for filters already
       
   151     // added.
       
   152     void set_filter_buffer_size(int n) { pimpl_->filter_buffer_size_ = n; }
       
   153 
       
   154     // Sets the size of the putback buffer for filters and devices to be added
       
   155     // to this chain. Does not affect the size of the buffer for filters or
       
   156     // devices already added.
       
   157     void set_pback_size(int n) { pimpl_->pback_size_ = n; }
       
   158 
       
   159     //----------Device interface----------------------------------------------//
       
   160 
       
   161     std::streamsize read(char_type* s, std::streamsize n);
       
   162     std::streamsize write(const char_type* s, std::streamsize n);
       
   163     std::streampos seek(stream_offset off, BOOST_IOS::seekdir way);
       
   164 
       
   165     //----------Direct component access---------------------------------------//
       
   166 
       
   167     const std::type_info& component_type(int n) const
       
   168     {
       
   169         if (static_cast<size_type>(n) >= size())
       
   170             throw std::out_of_range("bad chain offset");
       
   171         return (*boost::next(list().begin(), n))->component_type();
       
   172     }
       
   173 
       
   174 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1310)
       
   175     // Deprecated.
       
   176     template<int N>
       
   177     const std::type_info& component_type() const { return component_type(N); }
       
   178 
       
   179     template<typename T>
       
   180     T* component(int n) const { return component(n, boost::type<T>()); }
       
   181 
       
   182     // Deprecated.
       
   183     template<int N, typename T> 
       
   184     T* component() const { return component<T>(N); }
       
   185 #endif
       
   186 
       
   187 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1310)
       
   188     private:
       
   189 #endif
       
   190     template<typename T>
       
   191     T* component(int n, boost::type<T>) const
       
   192     {
       
   193         if (static_cast<size_type>(n) >= size())
       
   194             throw std::out_of_range("bad chain offset");
       
   195         streambuf_type* link = *boost::next(list().begin(), n);
       
   196         if (BOOST_IOSTREAMS_COMPARE_TYPE_ID(link->component_type(), typeid(T)))
       
   197             return static_cast<T*>(link->component_impl());
       
   198         else
       
   199             return 0;
       
   200     }
       
   201 public:
       
   202 
       
   203     //----------Container-like interface--------------------------------------//
       
   204 
       
   205     typedef typename list_type::size_type size_type;
       
   206     streambuf_type& front() { return *list().front(); }
       
   207     BOOST_IOSTREAMS_DEFINE_PUSH(push, mode, char_type, push_impl)
       
   208     void pop();
       
   209     bool empty() const { return list().empty(); }
       
   210     size_type size() const { return list().size(); }
       
   211     void reset();
       
   212 
       
   213     //----------Additional i/o functions--------------------------------------//
       
   214 
       
   215     // Returns true if this chain is non-empty and its final link
       
   216     // is a source or sink, i.e., if it is ready to perform i/o.
       
   217     bool is_complete() const;
       
   218     bool auto_close() const;
       
   219     void set_auto_close(bool close);
       
   220     bool sync() { return front().BOOST_IOSTREAMS_PUBSYNC() != -1; }
       
   221     bool strict_sync();
       
   222 private:
       
   223     template<typename T>
       
   224     void push_impl(const T& t, int buffer_size = -1, int pback_size = -1)
       
   225     {
       
   226         typedef typename iostreams::category_of<T>::type  category;
       
   227         typedef typename unwrap_ios<T>::type              policy_type;
       
   228         typedef stream_buffer<
       
   229                     policy_type,
       
   230                     BOOST_IOSTREAMS_CHAR_TRAITS(char_type),
       
   231                     Alloc, Mode
       
   232                 >                                         facade_type;
       
   233         BOOST_STATIC_ASSERT((is_convertible<category, Mode>::value));
       
   234         if (is_complete())
       
   235             throw std::logic_error("chain complete");
       
   236         streambuf_type* prev = !empty() ? list().back() : 0;
       
   237         buffer_size =
       
   238             buffer_size != -1 ?
       
   239                 buffer_size :
       
   240                 iostreams::optimal_buffer_size(t);
       
   241         pback_size =
       
   242             pback_size != -1 ?
       
   243                 pback_size :
       
   244                 pimpl_->pback_size_;
       
   245         std::auto_ptr<facade_type>
       
   246             buf(new facade_type(t, buffer_size, pback_size));
       
   247         list().push_back(buf.get());
       
   248         buf.release();
       
   249         if (is_device<policy_type>::value)
       
   250             pimpl_->flags_ |= f_complete | f_open;
       
   251         if (prev) prev->set_next(list().back());
       
   252         notify();
       
   253     }
       
   254 
       
   255     list_type& list() { return pimpl_->links_; }
       
   256     const list_type& list() const { return pimpl_->links_; }
       
   257     void register_client(client_type* client) { pimpl_->client_ = client; }
       
   258     void notify() { if (pimpl_->client_) pimpl_->client_->notify(); }
       
   259 
       
   260     //----------Nested classes------------------------------------------------//
       
   261 
       
   262     static void close(streambuf_type* b, BOOST_IOS::openmode m)
       
   263     {
       
   264         if (m & BOOST_IOS::out)
       
   265             b->BOOST_IOSTREAMS_PUBSYNC();
       
   266         b->close(m);
       
   267     }
       
   268 
       
   269     static void set_next(streambuf_type* b, streambuf_type* next)
       
   270     { b->set_next(next); }
       
   271 
       
   272     static void set_auto_close(streambuf_type* b, bool close)
       
   273     { b->set_auto_close(close); }
       
   274 
       
   275     struct closer  : public std::unary_function<streambuf_type*, void>  {
       
   276         closer(BOOST_IOS::openmode m) : mode_(m) { }
       
   277         void operator() (streambuf_type* b)
       
   278         {
       
   279             close(b, mode_);
       
   280         }
       
   281         BOOST_IOS::openmode mode_;
       
   282     };
       
   283     friend struct closer;
       
   284 
       
   285     enum flags {
       
   286         f_complete = 1,
       
   287         f_open = 2,
       
   288         f_auto_close = 4
       
   289     };
       
   290 
       
   291     struct chain_impl {
       
   292         chain_impl()
       
   293             : client_(0), device_buffer_size_(default_device_buffer_size),
       
   294               filter_buffer_size_(default_filter_buffer_size),
       
   295               pback_size_(default_pback_buffer_size),
       
   296               flags_(f_auto_close)
       
   297             { }
       
   298         ~chain_impl() { try { close(); reset(); } catch (std::exception&) { } }
       
   299         void close()
       
   300             {
       
   301                 if ((flags_ & f_open) != 0) {
       
   302                     stream_buffer< basic_null_device<Ch, Mode> > null;
       
   303                     if ((flags_ & f_complete) == 0) {
       
   304                         null.open(basic_null_device<Ch, Mode>());
       
   305                         set_next(links_.back(), &null);
       
   306                     }
       
   307                     links_.front()->BOOST_IOSTREAMS_PUBSYNC();
       
   308                     if (is_convertible<Mode, input>::value)
       
   309                         std::for_each( links_.rbegin(), links_.rend(),
       
   310                                        closer(BOOST_IOS::in) );
       
   311                     if (is_convertible<Mode, output>::value)
       
   312                         std::for_each( links_.begin(), links_.end(),
       
   313                                        closer(BOOST_IOS::out) );
       
   314                     flags_ &= ~f_open;
       
   315                 }
       
   316             }
       
   317         void reset()
       
   318             {
       
   319                 typedef typename list_type::iterator iterator;
       
   320                 for ( iterator first = links_.begin(),
       
   321                                last = links_.end();
       
   322                       first != last;
       
   323                       ++first )
       
   324                 {
       
   325                     if ( (flags_ & f_complete) == 0 ||
       
   326                          (flags_ & f_auto_close) == 0 )
       
   327                     {
       
   328                         set_auto_close(*first, false);
       
   329                     }
       
   330                     streambuf_type* buf = 0;
       
   331                     std::swap(buf, *first);
       
   332                     delete buf;
       
   333                 }
       
   334                 links_.clear();
       
   335                 flags_ &= ~f_complete;
       
   336                 flags_ &= ~f_open;
       
   337             }
       
   338         list_type     links_;
       
   339         client_type*  client_;
       
   340         int           device_buffer_size_,
       
   341                       filter_buffer_size_,
       
   342                       pback_size_;
       
   343         int           flags_;
       
   344     };
       
   345     friend struct chain_impl;
       
   346 
       
   347     //----------Member data---------------------------------------------------//
       
   348 
       
   349 private:
       
   350     shared_ptr<chain_impl> pimpl_;
       
   351 };
       
   352 
       
   353 } // End namespace detail.
       
   354 
       
   355 //
       
   356 // Macro: BOOST_IOSTREAMS_DECL_CHAIN(name, category)
       
   357 // Description: Defines a template derived from chain_base appropriate for a
       
   358 //      particular i/o category. The template has the following parameters:
       
   359 //      Ch - The character type.
       
   360 //      Tr - The character traits type.
       
   361 //      Alloc - The allocator type.
       
   362 // Macro parameters:
       
   363 //      name_ - The name of the template to be defined.
       
   364 //      category_ - The i/o category of the template to be defined.
       
   365 //
       
   366 #define BOOST_IOSTREAMS_DECL_CHAIN(name_, default_char_) \
       
   367     template< typename Mode, typename Ch = default_char_, \
       
   368               typename Tr = BOOST_IOSTREAMS_CHAR_TRAITS(Ch), \
       
   369               typename Alloc = std::allocator<Ch> > \
       
   370     class name_ : public boost::iostreams::detail::chain_base< \
       
   371                             name_<Mode, Ch, Tr, Alloc>, \
       
   372                             Ch, Tr, Alloc, Mode \
       
   373                          > \
       
   374     { \
       
   375     public: \
       
   376         struct category : device_tag, Mode { }; \
       
   377         typedef Mode                                   mode; \
       
   378     private: \
       
   379         typedef boost::iostreams::detail::chain_base< \
       
   380                     name_<Mode, Ch, Tr, Alloc>, \
       
   381                     Ch, Tr, Alloc, Mode \
       
   382                 >                                      base_type; \
       
   383     public: \
       
   384         typedef Ch                                     char_type; \
       
   385         typedef Tr                                     traits_type; \
       
   386         typedef typename traits_type::int_type         int_type; \
       
   387         typedef typename traits_type::off_type         off_type; \
       
   388         name_() { } \
       
   389         name_(const name_& rhs) { *this = rhs; } \
       
   390         name_& operator=(const name_& rhs) \
       
   391         { base_type::operator=(rhs); return *this; } \
       
   392     }; \
       
   393     /**/
       
   394 BOOST_IOSTREAMS_DECL_CHAIN(chain, char)
       
   395 BOOST_IOSTREAMS_DECL_CHAIN(wchain, wchar_t)
       
   396 #undef BOOST_IOSTREAMS_DECL_CHAIN
       
   397 
       
   398 //--------------Definition of chain_client------------------------------------//
       
   399 
       
   400 namespace detail {
       
   401 
       
   402 //
       
   403 // Template name: chain_client
       
   404 // Description: Class whose instances provide access to an underlying chain
       
   405 //      using an interface similar to the chains.
       
   406 // Subclasses: the various stream and stream buffer templates.
       
   407 //
       
   408 template<typename Chain>
       
   409 class chain_client {
       
   410 public:
       
   411     typedef Chain                             chain_type;
       
   412     typedef typename chain_type::char_type    char_type;
       
   413     typedef typename chain_type::traits_type  traits_type;
       
   414     typedef typename chain_type::size_type    size_type;
       
   415     typedef typename chain_type::mode         mode;
       
   416 
       
   417     chain_client(chain_type* chn = 0) : chain_(chn ) { }
       
   418     chain_client(chain_client* client) : chain_(client->chain_) { }
       
   419     virtual ~chain_client() { }
       
   420 
       
   421     const std::type_info& component_type(int n) const
       
   422     { return chain_->component_type(n); }
       
   423 
       
   424 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1310)
       
   425     // Deprecated.
       
   426     template<int N>
       
   427     const std::type_info& component_type() const
       
   428     { return chain_->BOOST_NESTED_TEMPLATE component_type<N>(); }
       
   429 
       
   430     template<typename T>
       
   431     T* component(int n) const
       
   432     { return chain_->BOOST_NESTED_TEMPLATE component<T>(n); }
       
   433 
       
   434     // Deprecated.
       
   435     template<int N, typename T>
       
   436     T* component() const
       
   437     { return chain_->BOOST_NESTED_TEMPLATE component<N, T>(); }
       
   438 #else
       
   439     template<typename T>
       
   440     T* component(int n, boost::type<T> t) const
       
   441     { return chain_->component(n, t); }
       
   442 #endif
       
   443 
       
   444     bool is_complete() const { return chain_->is_complete(); }
       
   445     bool auto_close() const { return chain_->auto_close(); }
       
   446     void set_auto_close(bool close) { chain_->set_auto_close(close); }
       
   447     bool strict_sync() { return chain_->strict_sync(); }
       
   448     void set_device_buffer_size(std::streamsize n)
       
   449         { chain_->set_device_buffer_size(n); }
       
   450     void set_filter_buffer_size(std::streamsize n)
       
   451         { chain_->set_filter_buffer_size(n); }
       
   452     void set_pback_size(std::streamsize n) { chain_->set_pback_size(n); }
       
   453     BOOST_IOSTREAMS_DEFINE_PUSH(push, mode, char_type, push_impl)
       
   454     void pop() { chain_->pop(); }
       
   455     bool empty() const { return chain_->empty(); }
       
   456     size_type size() { return chain_->size(); }
       
   457     void reset() { chain_->reset(); }
       
   458 
       
   459     // Returns a copy of the underlying chain.
       
   460     chain_type filters() { return *chain_; }
       
   461     chain_type filters() const { return *chain_; }
       
   462 protected:
       
   463     template<typename T>
       
   464     void push_impl(const T& t BOOST_IOSTREAMS_PUSH_PARAMS())
       
   465     { chain_->push(t BOOST_IOSTREAMS_PUSH_ARGS()); }
       
   466     chain_type& ref() { return *chain_; }
       
   467     void set_chain(chain_type* c)
       
   468     { chain_ = c; chain_->register_client(this); }
       
   469 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && \
       
   470     (!BOOST_WORKAROUND(__BORLANDC__, < 0x600))
       
   471     template<typename S, typename C, typename T, typename A, typename M>
       
   472     friend class chain_base;
       
   473 #else
       
   474     public:
       
   475 #endif
       
   476     virtual void notify() { }
       
   477 private:
       
   478     chain_type* chain_;
       
   479 };
       
   480 
       
   481 //--------------Implementation of chain_base----------------------------------//
       
   482 
       
   483 template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
       
   484 inline std::streamsize chain_base<Self, Ch, Tr, Alloc, Mode>::read
       
   485     (char_type* s, std::streamsize n)
       
   486 { return iostreams::read(*list().front(), s, n); }
       
   487 
       
   488 template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
       
   489 inline std::streamsize chain_base<Self, Ch, Tr, Alloc, Mode>::write
       
   490     (const char_type* s, std::streamsize n)
       
   491 { return iostreams::write(*list().front(), s, n); }
       
   492 
       
   493 template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
       
   494 inline std::streampos chain_base<Self, Ch, Tr, Alloc, Mode>::seek
       
   495     (stream_offset off, BOOST_IOS::seekdir way)
       
   496 { return iostreams::seek(*list().front(), off, way); }
       
   497 
       
   498 template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
       
   499 void chain_base<Self, Ch, Tr, Alloc, Mode>::reset()
       
   500 {
       
   501     using namespace std;
       
   502     pimpl_->close();
       
   503     pimpl_->reset();
       
   504 }
       
   505 
       
   506 template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
       
   507 bool chain_base<Self, Ch, Tr, Alloc, Mode>::is_complete() const
       
   508 {
       
   509     return (pimpl_->flags_ & f_complete) != 0;
       
   510 }
       
   511 
       
   512 template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
       
   513 bool chain_base<Self, Ch, Tr, Alloc, Mode>::auto_close() const
       
   514 {
       
   515     return (pimpl_->flags_ & f_auto_close) != 0;
       
   516 }
       
   517 
       
   518 template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
       
   519 void chain_base<Self, Ch, Tr, Alloc, Mode>::set_auto_close(bool close)
       
   520 {
       
   521     pimpl_->flags_ =
       
   522         (pimpl_->flags_ & ~f_auto_close) |
       
   523         (close ? f_auto_close : 0);
       
   524 }
       
   525 
       
   526 template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
       
   527 bool chain_base<Self, Ch, Tr, Alloc, Mode>::strict_sync()
       
   528 {
       
   529     typedef typename list_type::iterator iterator;
       
   530     bool result = true;
       
   531     for ( iterator first = list().begin(),
       
   532                    last = list().end();
       
   533           first != last;
       
   534           ++first )
       
   535     {
       
   536         bool s = (*first)->strict_sync();
       
   537         result = result && s;
       
   538     }
       
   539     return result;
       
   540 }
       
   541 
       
   542 template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
       
   543 void chain_base<Self, Ch, Tr, Alloc, Mode>::pop()
       
   544 {
       
   545     assert(!empty());
       
   546     if (auto_close())
       
   547         pimpl_->close();
       
   548     streambuf_type* buf = 0;
       
   549     std::swap(buf, list().back());
       
   550     buf->set_auto_close(false);
       
   551     buf->set_next(0);
       
   552     delete buf;
       
   553     list().pop_back();
       
   554     pimpl_->flags_ &= ~f_complete;
       
   555     if (auto_close() || list().empty())
       
   556         pimpl_->flags_ &= ~f_open;
       
   557 }
       
   558 
       
   559 } // End namespace detail.
       
   560 
       
   561 } } // End namespaces iostreams, boost.
       
   562 
       
   563 #endif // #ifndef BOOST_IOSTREAMS_DETAIL_CHAIN_HPP_INCLUDED