diff -r 000000000000 -r e4d67989cc36 ossrv_pub/boost_apis/boost/iostreams/chain.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ossrv_pub/boost_apis/boost/iostreams/chain.hpp Tue Feb 02 02:01:42 2010 +0200 @@ -0,0 +1,563 @@ +// (C) Copyright Jonathan Turkanis 2003. +// 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. + +#ifndef BOOST_IOSTREAMS_DETAIL_CHAIN_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_CHAIN_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // for_each. +#include +#include +#include // unary_function. +#include // advance. +#include +#include // allocator, auto_ptr. +#include +#include // logic_error, out_of_range. +#include +#include // BOOST_MSVC, template friends, +#include // BOOST_NESTED_TEMPLATE +#include +#include +#include +#include +#include // pubsync. +#include +#include +#include +#include // is_filter. +#include +#include +#include +#include +#include +#include +#if BOOST_WORKAROUND(BOOST_MSVC, < 1310) +# include +#endif + +// Sometimes type_info objects must be compared by name. Borrowed from +// Boost.Python and Boost.Function. +#if (defined(__GNUC__) && __GNUC__ >= 3) || \ + defined(_AIX) || \ + (defined(__sgi) && defined(__host_mips)) || \ + (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC)) \ + /**/ +# include +# define BOOST_IOSTREAMS_COMPARE_TYPE_ID(X,Y) \ + (std::strcmp((X).name(),(Y).name()) == 0) +#else +# define BOOST_IOSTREAMS_COMPARE_TYPE_ID(X,Y) ((X)==(Y)) +#endif + +// Deprecated +#define BOOST_IOSTREAMS_COMPONENT_TYPE(chain, index) \ + chain.component_type( index ) \ + /**/ + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310) +# define BOOST_IOSTREAMS_COMPONENT(chain, index, target) \ + chain.component< target >( index ) \ + /**/ +#else +# define BOOST_IOSTREAMS_COMPONENT(chain, index, target) \ + chain.component( index, ::boost::type< target >() ) \ + /**/ +#endif + +namespace boost { namespace iostreams { + +//--------------Definition of chain and wchain--------------------------------// + +namespace detail { + +template class chain_client; + +// +// Concept name: Chain. +// Description: Represents a chain of stream buffers which provides access +// to the first buffer in the chain and send notifications when the +// streambufs are added to or removed from chain. +// Refines: Closable device with mode equal to typename Chain::mode. +// Models: chain, converting_chain. +// Example: +// +// class chain { +// public: +// typedef xxx chain_type; +// typedef xxx client_type; +// typedef xxx mode; +// bool is_complete() const; // Ready for i/o. +// template +// void push( const T& t, // Adds a stream buffer to +// streamsize, // chain, based on t, with +// streamsize ); // given buffer and putback +// // buffer sizes. Pass -1 to +// // request default size. +// protected: +// void register_client(client_type* client); // Associate client. +// void notify(); // Notify client. +// }; +// + +// +// Description: Represents a chain of filters with an optional device at the +// end. +// Template parameters: +// Self - A class deriving from the current instantiation of this template. +// This is an example of the Curiously Recurring Template Pattern. +// Ch - The character type. +// Tr - The character traits type. +// Alloc - The allocator type. +// Mode - A mode tag. +// +template +class chain_base { +public: + typedef Ch char_type; + BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(Tr) + typedef Alloc allocator_type; + typedef Mode mode; + struct category + : Mode, + device_tag + { }; + typedef chain_client client_type; + friend class chain_client; +private: + typedef linked_streambuf streambuf_type; + typedef std::list list_type; + typedef chain_base my_type; +protected: + chain_base() : pimpl_(new chain_impl) { } + chain_base(const chain_base& rhs): pimpl_(rhs.pimpl_) { } +public: + + //----------Buffer sizing-------------------------------------------------// + + // Sets the size of the buffer created for the devices to be added to this + // chain. Does not affect the size of the buffer for devices already + // added. + void set_device_buffer_size(int n) { pimpl_->device_buffer_size_ = n; } + + // Sets the size of the buffer created for the filters to be added + // to this chain. Does not affect the size of the buffer for filters already + // added. + void set_filter_buffer_size(int n) { pimpl_->filter_buffer_size_ = n; } + + // Sets the size of the putback buffer for filters and devices to be added + // to this chain. Does not affect the size of the buffer for filters or + // devices already added. + void set_pback_size(int n) { pimpl_->pback_size_ = n; } + + //----------Device interface----------------------------------------------// + + std::streamsize read(char_type* s, std::streamsize n); + std::streamsize write(const char_type* s, std::streamsize n); + std::streampos seek(stream_offset off, BOOST_IOS::seekdir way); + + //----------Direct component access---------------------------------------// + + const std::type_info& component_type(int n) const + { + if (static_cast(n) >= size()) + throw std::out_of_range("bad chain offset"); + return (*boost::next(list().begin(), n))->component_type(); + } + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310) + // Deprecated. + template + const std::type_info& component_type() const { return component_type(N); } + + template + T* component(int n) const { return component(n, boost::type()); } + + // Deprecated. + template + T* component() const { return component(N); } +#endif + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310) + private: +#endif + template + T* component(int n, boost::type) const + { + if (static_cast(n) >= size()) + throw std::out_of_range("bad chain offset"); + streambuf_type* link = *boost::next(list().begin(), n); + if (BOOST_IOSTREAMS_COMPARE_TYPE_ID(link->component_type(), typeid(T))) + return static_cast(link->component_impl()); + else + return 0; + } +public: + + //----------Container-like interface--------------------------------------// + + typedef typename list_type::size_type size_type; + streambuf_type& front() { return *list().front(); } + BOOST_IOSTREAMS_DEFINE_PUSH(push, mode, char_type, push_impl) + void pop(); + bool empty() const { return list().empty(); } + size_type size() const { return list().size(); } + void reset(); + + //----------Additional i/o functions--------------------------------------// + + // Returns true if this chain is non-empty and its final link + // is a source or sink, i.e., if it is ready to perform i/o. + bool is_complete() const; + bool auto_close() const; + void set_auto_close(bool close); + bool sync() { return front().BOOST_IOSTREAMS_PUBSYNC() != -1; } + bool strict_sync(); +private: + template + void push_impl(const T& t, int buffer_size = -1, int pback_size = -1) + { + typedef typename iostreams::category_of::type category; + typedef typename unwrap_ios::type policy_type; + typedef stream_buffer< + policy_type, + BOOST_IOSTREAMS_CHAR_TRAITS(char_type), + Alloc, Mode + > facade_type; + BOOST_STATIC_ASSERT((is_convertible::value)); + if (is_complete()) + throw std::logic_error("chain complete"); + streambuf_type* prev = !empty() ? list().back() : 0; + buffer_size = + buffer_size != -1 ? + buffer_size : + iostreams::optimal_buffer_size(t); + pback_size = + pback_size != -1 ? + pback_size : + pimpl_->pback_size_; + std::auto_ptr + buf(new facade_type(t, buffer_size, pback_size)); + list().push_back(buf.get()); + buf.release(); + if (is_device::value) + pimpl_->flags_ |= f_complete | f_open; + if (prev) prev->set_next(list().back()); + notify(); + } + + list_type& list() { return pimpl_->links_; } + const list_type& list() const { return pimpl_->links_; } + void register_client(client_type* client) { pimpl_->client_ = client; } + void notify() { if (pimpl_->client_) pimpl_->client_->notify(); } + + //----------Nested classes------------------------------------------------// + + static void close(streambuf_type* b, BOOST_IOS::openmode m) + { + if (m & BOOST_IOS::out) + b->BOOST_IOSTREAMS_PUBSYNC(); + b->close(m); + } + + static void set_next(streambuf_type* b, streambuf_type* next) + { b->set_next(next); } + + static void set_auto_close(streambuf_type* b, bool close) + { b->set_auto_close(close); } + + struct closer : public std::unary_function { + closer(BOOST_IOS::openmode m) : mode_(m) { } + void operator() (streambuf_type* b) + { + close(b, mode_); + } + BOOST_IOS::openmode mode_; + }; + friend struct closer; + + enum flags { + f_complete = 1, + f_open = 2, + f_auto_close = 4 + }; + + struct chain_impl { + chain_impl() + : client_(0), device_buffer_size_(default_device_buffer_size), + filter_buffer_size_(default_filter_buffer_size), + pback_size_(default_pback_buffer_size), + flags_(f_auto_close) + { } + ~chain_impl() { try { close(); reset(); } catch (std::exception&) { } } + void close() + { + if ((flags_ & f_open) != 0) { + stream_buffer< basic_null_device > null; + if ((flags_ & f_complete) == 0) { + null.open(basic_null_device()); + set_next(links_.back(), &null); + } + links_.front()->BOOST_IOSTREAMS_PUBSYNC(); + if (is_convertible::value) + std::for_each( links_.rbegin(), links_.rend(), + closer(BOOST_IOS::in) ); + if (is_convertible::value) + std::for_each( links_.begin(), links_.end(), + closer(BOOST_IOS::out) ); + flags_ &= ~f_open; + } + } + void reset() + { + typedef typename list_type::iterator iterator; + for ( iterator first = links_.begin(), + last = links_.end(); + first != last; + ++first ) + { + if ( (flags_ & f_complete) == 0 || + (flags_ & f_auto_close) == 0 ) + { + set_auto_close(*first, false); + } + streambuf_type* buf = 0; + std::swap(buf, *first); + delete buf; + } + links_.clear(); + flags_ &= ~f_complete; + flags_ &= ~f_open; + } + list_type links_; + client_type* client_; + int device_buffer_size_, + filter_buffer_size_, + pback_size_; + int flags_; + }; + friend struct chain_impl; + + //----------Member data---------------------------------------------------// + +private: + shared_ptr pimpl_; +}; + +} // End namespace detail. + +// +// Macro: BOOST_IOSTREAMS_DECL_CHAIN(name, category) +// Description: Defines a template derived from chain_base appropriate for a +// particular i/o category. The template has the following parameters: +// Ch - The character type. +// Tr - The character traits type. +// Alloc - The allocator type. +// Macro parameters: +// name_ - The name of the template to be defined. +// category_ - The i/o category of the template to be defined. +// +#define BOOST_IOSTREAMS_DECL_CHAIN(name_, default_char_) \ + template< typename Mode, typename Ch = default_char_, \ + typename Tr = BOOST_IOSTREAMS_CHAR_TRAITS(Ch), \ + typename Alloc = std::allocator > \ + class name_ : public boost::iostreams::detail::chain_base< \ + name_, \ + Ch, Tr, Alloc, Mode \ + > \ + { \ + public: \ + struct category : device_tag, Mode { }; \ + typedef Mode mode; \ + private: \ + typedef boost::iostreams::detail::chain_base< \ + name_, \ + Ch, Tr, Alloc, Mode \ + > base_type; \ + public: \ + typedef Ch char_type; \ + typedef Tr traits_type; \ + typedef typename traits_type::int_type int_type; \ + typedef typename traits_type::off_type off_type; \ + name_() { } \ + name_(const name_& rhs) { *this = rhs; } \ + name_& operator=(const name_& rhs) \ + { base_type::operator=(rhs); return *this; } \ + }; \ + /**/ +BOOST_IOSTREAMS_DECL_CHAIN(chain, char) +BOOST_IOSTREAMS_DECL_CHAIN(wchain, wchar_t) +#undef BOOST_IOSTREAMS_DECL_CHAIN + +//--------------Definition of chain_client------------------------------------// + +namespace detail { + +// +// Template name: chain_client +// Description: Class whose instances provide access to an underlying chain +// using an interface similar to the chains. +// Subclasses: the various stream and stream buffer templates. +// +template +class chain_client { +public: + typedef Chain chain_type; + typedef typename chain_type::char_type char_type; + typedef typename chain_type::traits_type traits_type; + typedef typename chain_type::size_type size_type; + typedef typename chain_type::mode mode; + + chain_client(chain_type* chn = 0) : chain_(chn ) { } + chain_client(chain_client* client) : chain_(client->chain_) { } + virtual ~chain_client() { } + + const std::type_info& component_type(int n) const + { return chain_->component_type(n); } + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310) + // Deprecated. + template + const std::type_info& component_type() const + { return chain_->BOOST_NESTED_TEMPLATE component_type(); } + + template + T* component(int n) const + { return chain_->BOOST_NESTED_TEMPLATE component(n); } + + // Deprecated. + template + T* component() const + { return chain_->BOOST_NESTED_TEMPLATE component(); } +#else + template + T* component(int n, boost::type t) const + { return chain_->component(n, t); } +#endif + + bool is_complete() const { return chain_->is_complete(); } + bool auto_close() const { return chain_->auto_close(); } + void set_auto_close(bool close) { chain_->set_auto_close(close); } + bool strict_sync() { return chain_->strict_sync(); } + void set_device_buffer_size(std::streamsize n) + { chain_->set_device_buffer_size(n); } + void set_filter_buffer_size(std::streamsize n) + { chain_->set_filter_buffer_size(n); } + void set_pback_size(std::streamsize n) { chain_->set_pback_size(n); } + BOOST_IOSTREAMS_DEFINE_PUSH(push, mode, char_type, push_impl) + void pop() { chain_->pop(); } + bool empty() const { return chain_->empty(); } + size_type size() { return chain_->size(); } + void reset() { chain_->reset(); } + + // Returns a copy of the underlying chain. + chain_type filters() { return *chain_; } + chain_type filters() const { return *chain_; } +protected: + template + void push_impl(const T& t BOOST_IOSTREAMS_PUSH_PARAMS()) + { chain_->push(t BOOST_IOSTREAMS_PUSH_ARGS()); } + chain_type& ref() { return *chain_; } + void set_chain(chain_type* c) + { chain_ = c; chain_->register_client(this); } +#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && \ + (!BOOST_WORKAROUND(__BORLANDC__, < 0x600)) + template + friend class chain_base; +#else + public: +#endif + virtual void notify() { } +private: + chain_type* chain_; +}; + +//--------------Implementation of chain_base----------------------------------// + +template +inline std::streamsize chain_base::read + (char_type* s, std::streamsize n) +{ return iostreams::read(*list().front(), s, n); } + +template +inline std::streamsize chain_base::write + (const char_type* s, std::streamsize n) +{ return iostreams::write(*list().front(), s, n); } + +template +inline std::streampos chain_base::seek + (stream_offset off, BOOST_IOS::seekdir way) +{ return iostreams::seek(*list().front(), off, way); } + +template +void chain_base::reset() +{ + using namespace std; + pimpl_->close(); + pimpl_->reset(); +} + +template +bool chain_base::is_complete() const +{ + return (pimpl_->flags_ & f_complete) != 0; +} + +template +bool chain_base::auto_close() const +{ + return (pimpl_->flags_ & f_auto_close) != 0; +} + +template +void chain_base::set_auto_close(bool close) +{ + pimpl_->flags_ = + (pimpl_->flags_ & ~f_auto_close) | + (close ? f_auto_close : 0); +} + +template +bool chain_base::strict_sync() +{ + typedef typename list_type::iterator iterator; + bool result = true; + for ( iterator first = list().begin(), + last = list().end(); + first != last; + ++first ) + { + bool s = (*first)->strict_sync(); + result = result && s; + } + return result; +} + +template +void chain_base::pop() +{ + assert(!empty()); + if (auto_close()) + pimpl_->close(); + streambuf_type* buf = 0; + std::swap(buf, list().back()); + buf->set_auto_close(false); + buf->set_next(0); + delete buf; + list().pop_back(); + pimpl_->flags_ &= ~f_complete; + if (auto_close() || list().empty()) + pimpl_->flags_ &= ~f_open; +} + +} // End namespace detail. + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_CHAIN_HPP_INCLUDED