os/ossrv/ossrv_pub/boost_apis/boost/iostreams/chain.hpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/ossrv_pub/boost_apis/boost/iostreams/chain.hpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,563 @@
     1.4 +// (C) Copyright Jonathan Turkanis 2003.
     1.5 +// Distributed under the Boost Software License, Version 1.0. (See accompanying
     1.6 +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
     1.7 +
     1.8 +// See http://www.boost.org/libs/iostreams for documentation.
     1.9 +
    1.10 +#ifndef BOOST_IOSTREAMS_DETAIL_CHAIN_HPP_INCLUDED
    1.11 +#define BOOST_IOSTREAMS_DETAIL_CHAIN_HPP_INCLUDED
    1.12 +
    1.13 +#if defined(_MSC_VER) && (_MSC_VER >= 1020)
    1.14 +# pragma once
    1.15 +#endif
    1.16 +
    1.17 +#include <algorithm>                            // for_each.
    1.18 +#include <cassert>
    1.19 +#include <exception>
    1.20 +#include <functional>                           // unary_function.
    1.21 +#include <iterator>                             // advance.
    1.22 +#include <list>
    1.23 +#include <memory>                               // allocator, auto_ptr.
    1.24 +#include <typeinfo>
    1.25 +#include <stdexcept>                            // logic_error, out_of_range.
    1.26 +#include <boost/checked_delete.hpp>
    1.27 +#include <boost/config.hpp>                     // BOOST_MSVC, template friends,
    1.28 +#include <boost/detail/workaround.hpp>          // BOOST_NESTED_TEMPLATE 
    1.29 +#include <boost/iostreams/constants.hpp>
    1.30 +#include <boost/iostreams/detail/access_control.hpp>
    1.31 +#include <boost/iostreams/detail/char_traits.hpp>
    1.32 +#include <boost/iostreams/detail/push.hpp>
    1.33 +#include <boost/iostreams/detail/streambuf.hpp> // pubsync.
    1.34 +#include <boost/iostreams/detail/wrap_unwrap.hpp>
    1.35 +#include <boost/iostreams/device/null.hpp>
    1.36 +#include <boost/iostreams/positioning.hpp>
    1.37 +#include <boost/iostreams/traits.hpp>           // is_filter.
    1.38 +#include <boost/iostreams/stream_buffer.hpp>
    1.39 +#include <boost/next_prior.hpp>
    1.40 +#include <boost/shared_ptr.hpp>
    1.41 +#include <boost/static_assert.hpp>
    1.42 +#include <boost/type_traits/is_convertible.hpp>
    1.43 +#include <boost/type.hpp>
    1.44 +#if BOOST_WORKAROUND(BOOST_MSVC, < 1310)
    1.45 +# include <boost/mpl/int.hpp>
    1.46 +#endif
    1.47 +
    1.48 +// Sometimes type_info objects must be compared by name. Borrowed from
    1.49 +// Boost.Python and Boost.Function.
    1.50 +#if (defined(__GNUC__) && __GNUC__ >= 3) || \
    1.51 +     defined(_AIX) || \
    1.52 +    (defined(__sgi) && defined(__host_mips)) || \
    1.53 +    (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC)) \
    1.54 +    /**/
    1.55 +# include <cstring>
    1.56 +# define BOOST_IOSTREAMS_COMPARE_TYPE_ID(X,Y) \
    1.57 +     (std::strcmp((X).name(),(Y).name()) == 0)
    1.58 +#else
    1.59 +# define BOOST_IOSTREAMS_COMPARE_TYPE_ID(X,Y) ((X)==(Y))
    1.60 +#endif
    1.61 +
    1.62 +// Deprecated
    1.63 +#define BOOST_IOSTREAMS_COMPONENT_TYPE(chain, index) \
    1.64 +    chain.component_type( index ) \
    1.65 +    /**/
    1.66 +
    1.67 +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310)
    1.68 +# define BOOST_IOSTREAMS_COMPONENT(chain, index, target) \
    1.69 +    chain.component< target >( index ) \
    1.70 +    /**/
    1.71 +#else
    1.72 +# define BOOST_IOSTREAMS_COMPONENT(chain, index, target) \
    1.73 +    chain.component( index, ::boost::type< target >() ) \
    1.74 +    /**/
    1.75 +#endif
    1.76 +
    1.77 +namespace boost { namespace iostreams {
    1.78 +
    1.79 +//--------------Definition of chain and wchain--------------------------------//
    1.80 +
    1.81 +namespace detail {
    1.82 +
    1.83 +template<typename Chain> class chain_client;
    1.84 +
    1.85 +//
    1.86 +// Concept name: Chain.
    1.87 +// Description: Represents a chain of stream buffers which provides access
    1.88 +//     to the first buffer in the chain and send notifications when the
    1.89 +//     streambufs are added to or removed from chain.
    1.90 +// Refines: Closable device with mode equal to typename Chain::mode.
    1.91 +// Models: chain, converting_chain.
    1.92 +// Example:
    1.93 +//
    1.94 +//    class chain {
    1.95 +//    public:
    1.96 +//        typedef xxx chain_type;
    1.97 +//        typedef xxx client_type;
    1.98 +//        typedef xxx mode;
    1.99 +//        bool is_complete() const;                  // Ready for i/o.
   1.100 +//        template<typename T>
   1.101 +//        void push( const T& t,                     // Adds a stream buffer to
   1.102 +//                   streamsize,                     // chain, based on t, with
   1.103 +//                   streamsize );                   // given buffer and putback
   1.104 +//                                                   // buffer sizes. Pass -1 to
   1.105 +//                                                   // request default size.
   1.106 +//    protected:
   1.107 +//        void register_client(client_type* client); // Associate client.
   1.108 +//        void notify();                             // Notify client.
   1.109 +//    };
   1.110 +//
   1.111 +
   1.112 +//
   1.113 +// Description: Represents a chain of filters with an optional device at the
   1.114 +//      end.
   1.115 +// Template parameters:
   1.116 +//      Self - A class deriving from the current instantiation of this template.
   1.117 +//          This is an example of the Curiously Recurring Template Pattern.
   1.118 +//      Ch - The character type.
   1.119 +//      Tr - The character traits type.
   1.120 +//      Alloc - The allocator type.
   1.121 +//      Mode - A mode tag.
   1.122 +//
   1.123 +template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
   1.124 +class chain_base {
   1.125 +public:
   1.126 +    typedef Ch                                     char_type;
   1.127 +    BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(Tr)
   1.128 +    typedef Alloc                                  allocator_type;
   1.129 +    typedef Mode                                   mode;
   1.130 +    struct category
   1.131 +        : Mode,
   1.132 +          device_tag
   1.133 +        { };
   1.134 +    typedef chain_client<Self>                     client_type;
   1.135 +    friend class chain_client<Self>;
   1.136 +private:
   1.137 +    typedef linked_streambuf<Ch>                   streambuf_type;
   1.138 +    typedef std::list<streambuf_type*>             list_type;
   1.139 +    typedef chain_base<Self, Ch, Tr, Alloc, Mode>  my_type;
   1.140 +protected:
   1.141 +    chain_base() : pimpl_(new chain_impl) { }
   1.142 +    chain_base(const chain_base& rhs): pimpl_(rhs.pimpl_) { }
   1.143 +public:
   1.144 +
   1.145 +    //----------Buffer sizing-------------------------------------------------//
   1.146 +
   1.147 +    // Sets the size of the buffer created for the devices to be added to this
   1.148 +    // chain. Does not affect the size of the buffer for devices already
   1.149 +    // added.
   1.150 +    void set_device_buffer_size(int n) { pimpl_->device_buffer_size_ = n; }
   1.151 +
   1.152 +    // Sets the size of the buffer created for the filters to be added
   1.153 +    // to this chain. Does not affect the size of the buffer for filters already
   1.154 +    // added.
   1.155 +    void set_filter_buffer_size(int n) { pimpl_->filter_buffer_size_ = n; }
   1.156 +
   1.157 +    // Sets the size of the putback buffer for filters and devices to be added
   1.158 +    // to this chain. Does not affect the size of the buffer for filters or
   1.159 +    // devices already added.
   1.160 +    void set_pback_size(int n) { pimpl_->pback_size_ = n; }
   1.161 +
   1.162 +    //----------Device interface----------------------------------------------//
   1.163 +
   1.164 +    std::streamsize read(char_type* s, std::streamsize n);
   1.165 +    std::streamsize write(const char_type* s, std::streamsize n);
   1.166 +    std::streampos seek(stream_offset off, BOOST_IOS::seekdir way);
   1.167 +
   1.168 +    //----------Direct component access---------------------------------------//
   1.169 +
   1.170 +    const std::type_info& component_type(int n) const
   1.171 +    {
   1.172 +        if (static_cast<size_type>(n) >= size())
   1.173 +            throw std::out_of_range("bad chain offset");
   1.174 +        return (*boost::next(list().begin(), n))->component_type();
   1.175 +    }
   1.176 +
   1.177 +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310)
   1.178 +    // Deprecated.
   1.179 +    template<int N>
   1.180 +    const std::type_info& component_type() const { return component_type(N); }
   1.181 +
   1.182 +    template<typename T>
   1.183 +    T* component(int n) const { return component(n, boost::type<T>()); }
   1.184 +
   1.185 +    // Deprecated.
   1.186 +    template<int N, typename T> 
   1.187 +    T* component() const { return component<T>(N); }
   1.188 +#endif
   1.189 +
   1.190 +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310)
   1.191 +    private:
   1.192 +#endif
   1.193 +    template<typename T>
   1.194 +    T* component(int n, boost::type<T>) const
   1.195 +    {
   1.196 +        if (static_cast<size_type>(n) >= size())
   1.197 +            throw std::out_of_range("bad chain offset");
   1.198 +        streambuf_type* link = *boost::next(list().begin(), n);
   1.199 +        if (BOOST_IOSTREAMS_COMPARE_TYPE_ID(link->component_type(), typeid(T)))
   1.200 +            return static_cast<T*>(link->component_impl());
   1.201 +        else
   1.202 +            return 0;
   1.203 +    }
   1.204 +public:
   1.205 +
   1.206 +    //----------Container-like interface--------------------------------------//
   1.207 +
   1.208 +    typedef typename list_type::size_type size_type;
   1.209 +    streambuf_type& front() { return *list().front(); }
   1.210 +    BOOST_IOSTREAMS_DEFINE_PUSH(push, mode, char_type, push_impl)
   1.211 +    void pop();
   1.212 +    bool empty() const { return list().empty(); }
   1.213 +    size_type size() const { return list().size(); }
   1.214 +    void reset();
   1.215 +
   1.216 +    //----------Additional i/o functions--------------------------------------//
   1.217 +
   1.218 +    // Returns true if this chain is non-empty and its final link
   1.219 +    // is a source or sink, i.e., if it is ready to perform i/o.
   1.220 +    bool is_complete() const;
   1.221 +    bool auto_close() const;
   1.222 +    void set_auto_close(bool close);
   1.223 +    bool sync() { return front().BOOST_IOSTREAMS_PUBSYNC() != -1; }
   1.224 +    bool strict_sync();
   1.225 +private:
   1.226 +    template<typename T>
   1.227 +    void push_impl(const T& t, int buffer_size = -1, int pback_size = -1)
   1.228 +    {
   1.229 +        typedef typename iostreams::category_of<T>::type  category;
   1.230 +        typedef typename unwrap_ios<T>::type              policy_type;
   1.231 +        typedef stream_buffer<
   1.232 +                    policy_type,
   1.233 +                    BOOST_IOSTREAMS_CHAR_TRAITS(char_type),
   1.234 +                    Alloc, Mode
   1.235 +                >                                         facade_type;
   1.236 +        BOOST_STATIC_ASSERT((is_convertible<category, Mode>::value));
   1.237 +        if (is_complete())
   1.238 +            throw std::logic_error("chain complete");
   1.239 +        streambuf_type* prev = !empty() ? list().back() : 0;
   1.240 +        buffer_size =
   1.241 +            buffer_size != -1 ?
   1.242 +                buffer_size :
   1.243 +                iostreams::optimal_buffer_size(t);
   1.244 +        pback_size =
   1.245 +            pback_size != -1 ?
   1.246 +                pback_size :
   1.247 +                pimpl_->pback_size_;
   1.248 +        std::auto_ptr<facade_type>
   1.249 +            buf(new facade_type(t, buffer_size, pback_size));
   1.250 +        list().push_back(buf.get());
   1.251 +        buf.release();
   1.252 +        if (is_device<policy_type>::value)
   1.253 +            pimpl_->flags_ |= f_complete | f_open;
   1.254 +        if (prev) prev->set_next(list().back());
   1.255 +        notify();
   1.256 +    }
   1.257 +
   1.258 +    list_type& list() { return pimpl_->links_; }
   1.259 +    const list_type& list() const { return pimpl_->links_; }
   1.260 +    void register_client(client_type* client) { pimpl_->client_ = client; }
   1.261 +    void notify() { if (pimpl_->client_) pimpl_->client_->notify(); }
   1.262 +
   1.263 +    //----------Nested classes------------------------------------------------//
   1.264 +
   1.265 +    static void close(streambuf_type* b, BOOST_IOS::openmode m)
   1.266 +    {
   1.267 +        if (m & BOOST_IOS::out)
   1.268 +            b->BOOST_IOSTREAMS_PUBSYNC();
   1.269 +        b->close(m);
   1.270 +    }
   1.271 +
   1.272 +    static void set_next(streambuf_type* b, streambuf_type* next)
   1.273 +    { b->set_next(next); }
   1.274 +
   1.275 +    static void set_auto_close(streambuf_type* b, bool close)
   1.276 +    { b->set_auto_close(close); }
   1.277 +
   1.278 +    struct closer  : public std::unary_function<streambuf_type*, void>  {
   1.279 +        closer(BOOST_IOS::openmode m) : mode_(m) { }
   1.280 +        void operator() (streambuf_type* b)
   1.281 +        {
   1.282 +            close(b, mode_);
   1.283 +        }
   1.284 +        BOOST_IOS::openmode mode_;
   1.285 +    };
   1.286 +    friend struct closer;
   1.287 +
   1.288 +    enum flags {
   1.289 +        f_complete = 1,
   1.290 +        f_open = 2,
   1.291 +        f_auto_close = 4
   1.292 +    };
   1.293 +
   1.294 +    struct chain_impl {
   1.295 +        chain_impl()
   1.296 +            : client_(0), device_buffer_size_(default_device_buffer_size),
   1.297 +              filter_buffer_size_(default_filter_buffer_size),
   1.298 +              pback_size_(default_pback_buffer_size),
   1.299 +              flags_(f_auto_close)
   1.300 +            { }
   1.301 +        ~chain_impl() { try { close(); reset(); } catch (std::exception&) { } }
   1.302 +        void close()
   1.303 +            {
   1.304 +                if ((flags_ & f_open) != 0) {
   1.305 +                    stream_buffer< basic_null_device<Ch, Mode> > null;
   1.306 +                    if ((flags_ & f_complete) == 0) {
   1.307 +                        null.open(basic_null_device<Ch, Mode>());
   1.308 +                        set_next(links_.back(), &null);
   1.309 +                    }
   1.310 +                    links_.front()->BOOST_IOSTREAMS_PUBSYNC();
   1.311 +                    if (is_convertible<Mode, input>::value)
   1.312 +                        std::for_each( links_.rbegin(), links_.rend(),
   1.313 +                                       closer(BOOST_IOS::in) );
   1.314 +                    if (is_convertible<Mode, output>::value)
   1.315 +                        std::for_each( links_.begin(), links_.end(),
   1.316 +                                       closer(BOOST_IOS::out) );
   1.317 +                    flags_ &= ~f_open;
   1.318 +                }
   1.319 +            }
   1.320 +        void reset()
   1.321 +            {
   1.322 +                typedef typename list_type::iterator iterator;
   1.323 +                for ( iterator first = links_.begin(),
   1.324 +                               last = links_.end();
   1.325 +                      first != last;
   1.326 +                      ++first )
   1.327 +                {
   1.328 +                    if ( (flags_ & f_complete) == 0 ||
   1.329 +                         (flags_ & f_auto_close) == 0 )
   1.330 +                    {
   1.331 +                        set_auto_close(*first, false);
   1.332 +                    }
   1.333 +                    streambuf_type* buf = 0;
   1.334 +                    std::swap(buf, *first);
   1.335 +                    delete buf;
   1.336 +                }
   1.337 +                links_.clear();
   1.338 +                flags_ &= ~f_complete;
   1.339 +                flags_ &= ~f_open;
   1.340 +            }
   1.341 +        list_type     links_;
   1.342 +        client_type*  client_;
   1.343 +        int           device_buffer_size_,
   1.344 +                      filter_buffer_size_,
   1.345 +                      pback_size_;
   1.346 +        int           flags_;
   1.347 +    };
   1.348 +    friend struct chain_impl;
   1.349 +
   1.350 +    //----------Member data---------------------------------------------------//
   1.351 +
   1.352 +private:
   1.353 +    shared_ptr<chain_impl> pimpl_;
   1.354 +};
   1.355 +
   1.356 +} // End namespace detail.
   1.357 +
   1.358 +//
   1.359 +// Macro: BOOST_IOSTREAMS_DECL_CHAIN(name, category)
   1.360 +// Description: Defines a template derived from chain_base appropriate for a
   1.361 +//      particular i/o category. The template has the following parameters:
   1.362 +//      Ch - The character type.
   1.363 +//      Tr - The character traits type.
   1.364 +//      Alloc - The allocator type.
   1.365 +// Macro parameters:
   1.366 +//      name_ - The name of the template to be defined.
   1.367 +//      category_ - The i/o category of the template to be defined.
   1.368 +//
   1.369 +#define BOOST_IOSTREAMS_DECL_CHAIN(name_, default_char_) \
   1.370 +    template< typename Mode, typename Ch = default_char_, \
   1.371 +              typename Tr = BOOST_IOSTREAMS_CHAR_TRAITS(Ch), \
   1.372 +              typename Alloc = std::allocator<Ch> > \
   1.373 +    class name_ : public boost::iostreams::detail::chain_base< \
   1.374 +                            name_<Mode, Ch, Tr, Alloc>, \
   1.375 +                            Ch, Tr, Alloc, Mode \
   1.376 +                         > \
   1.377 +    { \
   1.378 +    public: \
   1.379 +        struct category : device_tag, Mode { }; \
   1.380 +        typedef Mode                                   mode; \
   1.381 +    private: \
   1.382 +        typedef boost::iostreams::detail::chain_base< \
   1.383 +                    name_<Mode, Ch, Tr, Alloc>, \
   1.384 +                    Ch, Tr, Alloc, Mode \
   1.385 +                >                                      base_type; \
   1.386 +    public: \
   1.387 +        typedef Ch                                     char_type; \
   1.388 +        typedef Tr                                     traits_type; \
   1.389 +        typedef typename traits_type::int_type         int_type; \
   1.390 +        typedef typename traits_type::off_type         off_type; \
   1.391 +        name_() { } \
   1.392 +        name_(const name_& rhs) { *this = rhs; } \
   1.393 +        name_& operator=(const name_& rhs) \
   1.394 +        { base_type::operator=(rhs); return *this; } \
   1.395 +    }; \
   1.396 +    /**/
   1.397 +BOOST_IOSTREAMS_DECL_CHAIN(chain, char)
   1.398 +BOOST_IOSTREAMS_DECL_CHAIN(wchain, wchar_t)
   1.399 +#undef BOOST_IOSTREAMS_DECL_CHAIN
   1.400 +
   1.401 +//--------------Definition of chain_client------------------------------------//
   1.402 +
   1.403 +namespace detail {
   1.404 +
   1.405 +//
   1.406 +// Template name: chain_client
   1.407 +// Description: Class whose instances provide access to an underlying chain
   1.408 +//      using an interface similar to the chains.
   1.409 +// Subclasses: the various stream and stream buffer templates.
   1.410 +//
   1.411 +template<typename Chain>
   1.412 +class chain_client {
   1.413 +public:
   1.414 +    typedef Chain                             chain_type;
   1.415 +    typedef typename chain_type::char_type    char_type;
   1.416 +    typedef typename chain_type::traits_type  traits_type;
   1.417 +    typedef typename chain_type::size_type    size_type;
   1.418 +    typedef typename chain_type::mode         mode;
   1.419 +
   1.420 +    chain_client(chain_type* chn = 0) : chain_(chn ) { }
   1.421 +    chain_client(chain_client* client) : chain_(client->chain_) { }
   1.422 +    virtual ~chain_client() { }
   1.423 +
   1.424 +    const std::type_info& component_type(int n) const
   1.425 +    { return chain_->component_type(n); }
   1.426 +
   1.427 +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310)
   1.428 +    // Deprecated.
   1.429 +    template<int N>
   1.430 +    const std::type_info& component_type() const
   1.431 +    { return chain_->BOOST_NESTED_TEMPLATE component_type<N>(); }
   1.432 +
   1.433 +    template<typename T>
   1.434 +    T* component(int n) const
   1.435 +    { return chain_->BOOST_NESTED_TEMPLATE component<T>(n); }
   1.436 +
   1.437 +    // Deprecated.
   1.438 +    template<int N, typename T>
   1.439 +    T* component() const
   1.440 +    { return chain_->BOOST_NESTED_TEMPLATE component<N, T>(); }
   1.441 +#else
   1.442 +    template<typename T>
   1.443 +    T* component(int n, boost::type<T> t) const
   1.444 +    { return chain_->component(n, t); }
   1.445 +#endif
   1.446 +
   1.447 +    bool is_complete() const { return chain_->is_complete(); }
   1.448 +    bool auto_close() const { return chain_->auto_close(); }
   1.449 +    void set_auto_close(bool close) { chain_->set_auto_close(close); }
   1.450 +    bool strict_sync() { return chain_->strict_sync(); }
   1.451 +    void set_device_buffer_size(std::streamsize n)
   1.452 +        { chain_->set_device_buffer_size(n); }
   1.453 +    void set_filter_buffer_size(std::streamsize n)
   1.454 +        { chain_->set_filter_buffer_size(n); }
   1.455 +    void set_pback_size(std::streamsize n) { chain_->set_pback_size(n); }
   1.456 +    BOOST_IOSTREAMS_DEFINE_PUSH(push, mode, char_type, push_impl)
   1.457 +    void pop() { chain_->pop(); }
   1.458 +    bool empty() const { return chain_->empty(); }
   1.459 +    size_type size() { return chain_->size(); }
   1.460 +    void reset() { chain_->reset(); }
   1.461 +
   1.462 +    // Returns a copy of the underlying chain.
   1.463 +    chain_type filters() { return *chain_; }
   1.464 +    chain_type filters() const { return *chain_; }
   1.465 +protected:
   1.466 +    template<typename T>
   1.467 +    void push_impl(const T& t BOOST_IOSTREAMS_PUSH_PARAMS())
   1.468 +    { chain_->push(t BOOST_IOSTREAMS_PUSH_ARGS()); }
   1.469 +    chain_type& ref() { return *chain_; }
   1.470 +    void set_chain(chain_type* c)
   1.471 +    { chain_ = c; chain_->register_client(this); }
   1.472 +#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && \
   1.473 +    (!BOOST_WORKAROUND(__BORLANDC__, < 0x600))
   1.474 +    template<typename S, typename C, typename T, typename A, typename M>
   1.475 +    friend class chain_base;
   1.476 +#else
   1.477 +    public:
   1.478 +#endif
   1.479 +    virtual void notify() { }
   1.480 +private:
   1.481 +    chain_type* chain_;
   1.482 +};
   1.483 +
   1.484 +//--------------Implementation of chain_base----------------------------------//
   1.485 +
   1.486 +template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
   1.487 +inline std::streamsize chain_base<Self, Ch, Tr, Alloc, Mode>::read
   1.488 +    (char_type* s, std::streamsize n)
   1.489 +{ return iostreams::read(*list().front(), s, n); }
   1.490 +
   1.491 +template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
   1.492 +inline std::streamsize chain_base<Self, Ch, Tr, Alloc, Mode>::write
   1.493 +    (const char_type* s, std::streamsize n)
   1.494 +{ return iostreams::write(*list().front(), s, n); }
   1.495 +
   1.496 +template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
   1.497 +inline std::streampos chain_base<Self, Ch, Tr, Alloc, Mode>::seek
   1.498 +    (stream_offset off, BOOST_IOS::seekdir way)
   1.499 +{ return iostreams::seek(*list().front(), off, way); }
   1.500 +
   1.501 +template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
   1.502 +void chain_base<Self, Ch, Tr, Alloc, Mode>::reset()
   1.503 +{
   1.504 +    using namespace std;
   1.505 +    pimpl_->close();
   1.506 +    pimpl_->reset();
   1.507 +}
   1.508 +
   1.509 +template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
   1.510 +bool chain_base<Self, Ch, Tr, Alloc, Mode>::is_complete() const
   1.511 +{
   1.512 +    return (pimpl_->flags_ & f_complete) != 0;
   1.513 +}
   1.514 +
   1.515 +template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
   1.516 +bool chain_base<Self, Ch, Tr, Alloc, Mode>::auto_close() const
   1.517 +{
   1.518 +    return (pimpl_->flags_ & f_auto_close) != 0;
   1.519 +}
   1.520 +
   1.521 +template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
   1.522 +void chain_base<Self, Ch, Tr, Alloc, Mode>::set_auto_close(bool close)
   1.523 +{
   1.524 +    pimpl_->flags_ =
   1.525 +        (pimpl_->flags_ & ~f_auto_close) |
   1.526 +        (close ? f_auto_close : 0);
   1.527 +}
   1.528 +
   1.529 +template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
   1.530 +bool chain_base<Self, Ch, Tr, Alloc, Mode>::strict_sync()
   1.531 +{
   1.532 +    typedef typename list_type::iterator iterator;
   1.533 +    bool result = true;
   1.534 +    for ( iterator first = list().begin(),
   1.535 +                   last = list().end();
   1.536 +          first != last;
   1.537 +          ++first )
   1.538 +    {
   1.539 +        bool s = (*first)->strict_sync();
   1.540 +        result = result && s;
   1.541 +    }
   1.542 +    return result;
   1.543 +}
   1.544 +
   1.545 +template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
   1.546 +void chain_base<Self, Ch, Tr, Alloc, Mode>::pop()
   1.547 +{
   1.548 +    assert(!empty());
   1.549 +    if (auto_close())
   1.550 +        pimpl_->close();
   1.551 +    streambuf_type* buf = 0;
   1.552 +    std::swap(buf, list().back());
   1.553 +    buf->set_auto_close(false);
   1.554 +    buf->set_next(0);
   1.555 +    delete buf;
   1.556 +    list().pop_back();
   1.557 +    pimpl_->flags_ &= ~f_complete;
   1.558 +    if (auto_close() || list().empty())
   1.559 +        pimpl_->flags_ &= ~f_open;
   1.560 +}
   1.561 +
   1.562 +} // End namespace detail.
   1.563 +
   1.564 +} } // End namespaces iostreams, boost.
   1.565 +
   1.566 +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_CHAIN_HPP_INCLUDED