From cf1020c76d8fefae1ce83cc04712700221afcc32 Mon Sep 17 00:00:00 2001 From: Jonathan Turkanis Date: Thu, 7 Apr 2005 03:59:02 +0000 Subject: [PATCH] added support for component() and component_type() [SVN r28038] --- include/boost/iostreams/chain.hpp | 117 ++++++++++++------ .../iostreams/detail/streambuf/chainbuf.hpp | 5 +- .../detail/streambuf/direct_streambuf.hpp | 14 ++- .../detail/streambuf/indirect_streambuf.hpp | 16 ++- .../detail/streambuf/linked_streambuf.hpp | 5 +- include/boost/iostreams/filtering_stream.hpp | 2 +- 6 files changed, 108 insertions(+), 51 deletions(-) diff --git a/include/boost/iostreams/chain.hpp b/include/boost/iostreams/chain.hpp index 10511a0..2e3a591 100755 --- a/include/boost/iostreams/chain.hpp +++ b/include/boost/iostreams/chain.hpp @@ -15,9 +15,11 @@ #include #include #include // unary_function. +#include // advance. #include #include // allocator, auto_ptr. -#include // logic_error. +#include +#include // logic_error, out_of_range. #include #include // BOOST_MSVC, template friends. #include @@ -34,6 +36,20 @@ #include #include +// 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 + namespace boost { namespace iostreams { //--------------Definition of chain and wchain--------------------------------// @@ -126,12 +142,31 @@ public: void write(const char_type* s, std::streamsize n); std::streamoff seek(std::streamoff off, BOOST_IOS::seekdir way); - //----------Direct stream buffer access-----------------------------------// + //----------Direct component access---------------------------------------// + + template + const std::type_info& component_type() const + { + if (N >= size()) + throw std::out_of_range("bad chain offset"); + return std::advance(list().begin(), N)->component_type(); + } + + template + T* component() const + { + if (N >= size()) + throw std::out_of_range("bad chain offset"); + streambuf_type* link = + *std::advance(list().begin(), N)->component_type(); + if (BOOST_IOSTREAMS_COMPARE_TYPE_ID(link->component_type(), typeid(T))) + return static_cast(link->component_impl()); + } + + //----------Container-like interface--------------------------------------// - streambuf_type& operator*() { return *list().front(); } - streambuf_type* operator->() { return list().front(); } -public: 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(); } @@ -146,35 +181,35 @@ public: private: template void push_impl(const T& t, int buffer_size = -1, int pback_size = -1) - { - typedef typename iostreams::io_category::type category; - typedef typename unwrap_ios::type policy_type; - typedef streambuf_facade< - 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; - if (prev) prev->set_next(list().back()); - notify(); - } + { + typedef typename iostreams::io_category::type category; + typedef typename unwrap_ios::type policy_type; + typedef streambuf_facade< + 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; + if (prev) prev->set_next(list().back()); + notify(); + } list_type& list() { return pimpl_->links_; } const list_type& list() const { return pimpl_->links_; } @@ -317,9 +352,13 @@ public: chain_client(chain_client* client) : chain_(client->chain_) { } virtual ~chain_client() { } - // Returns a copy of the underlying chain. - chain_type filters() { return *chain_; } - chain_type filters() const { return *chain_; } + template + const std::type_info& component_type() const + { return chain_->component_type(); } + + template + T* component() const + { return chain_->component(); } bool is_complete() const { return chain_->is_complete(); } bool auto_close() const { return chain_->auto_close(); } @@ -334,6 +373,10 @@ public: 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()) diff --git a/include/boost/iostreams/detail/streambuf/chainbuf.hpp b/include/boost/iostreams/detail/streambuf/chainbuf.hpp index ea616bd..f8d2193 100755 --- a/include/boost/iostreams/detail/streambuf/chainbuf.hpp +++ b/include/boost/iostreams/detail/streambuf/chainbuf.hpp @@ -84,9 +84,10 @@ private: typedef typename Chain::traits_type chain_traits; typename chain_traits::int_type static translate(typename std_traits::int_type c) - { return translate_int_type(c); } + { return translate_int_type(c); } - delegate_type& delegate() { return static_cast(*chain_); } + delegate_type& delegate() + { return static_cast(chain_.front()); } void get_pointers() { setg(delegate().eback(), delegate().gptr(), delegate().egptr()); diff --git a/include/boost/iostreams/detail/streambuf/direct_streambuf.hpp b/include/boost/iostreams/detail/streambuf/direct_streambuf.hpp index 8dbb205..e4bfeda 100755 --- a/include/boost/iostreams/detail/streambuf/direct_streambuf.hpp +++ b/include/boost/iostreams/detail/streambuf/direct_streambuf.hpp @@ -13,6 +13,7 @@ #include #include +#include #include // pair. #include // BOOST_DEDUCED_TYPENAME. #include @@ -47,13 +48,14 @@ private: char_type, traits_type ) streambuf_type; public: // stream_facade needs access. - void open( const T& t, - int /* buffer_size */, - int /* pback_size */ ); + void open(const T& t, int buffer_size, int pback_size); bool is_open(); void close(); bool auto_close() const { return auto_close_; } void set_auto_close(bool close) { auto_close_ = close; } + + // Declared in linked_streambuf. + T* component() { return storage_.get_ptr(); } protected: #if !BOOST_WORKAROUND(__GNUC__, == 2) BOOST_IOSTREAMS_USING_PROTECTED_STREAMBUF_MEMBERS(base_type) @@ -68,7 +70,11 @@ protected: pos_type seekoff( off_type off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which ); pos_type seekpos(pos_type sp, BOOST_IOS::openmode which); + + // Declared in linked_streambuf. void close(BOOST_IOS::openmode m); + const std::type_info& component_type() const { return typeid(T); } + void* component_impl() { return component(); } private: pos_type seek_impl( off_type off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which ); @@ -82,7 +88,7 @@ private: bool two_head() const; optional storage_; char_type *ibeg_, *iend_, *obeg_, *oend_; - bool auto_close_; + bool auto_close_; }; //------------------Implementation of direct_streambuf------------------------// diff --git a/include/boost/iostreams/detail/streambuf/indirect_streambuf.hpp b/include/boost/iostreams/detail/streambuf/indirect_streambuf.hpp index f99a889..ad010ef 100755 --- a/include/boost/iostreams/detail/streambuf/indirect_streambuf.hpp +++ b/include/boost/iostreams/detail/streambuf/indirect_streambuf.hpp @@ -13,6 +13,7 @@ #include // min, max. #include #include +#include #include // Member template friends. #include #include @@ -63,10 +64,8 @@ public: bool auto_close() const; void set_auto_close(bool close); - //----------Direct filter or device access--------------------------------// - - T& operator*() { return *obj(); } - T* operator->() { return &*obj(); } + // Declared in linked_streambuf. + T* component() { return &*obj(); } protected: #if !BOOST_WORKAROUND(__GNUC__, == 2) BOOST_IOSTREAMS_USING_PROTECTED_STREAMBUF_MEMBERS(base_type) @@ -86,8 +85,12 @@ protected: pos_type seekoff( off_type off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which ); pos_type seekpos(pos_type sp, BOOST_IOS::openmode which); - void close(BOOST_IOS::openmode m); // Declared in linked_streambuf. - void set_next(streambuf_type* next); // Declared in linked_streambuf. + + // Declared in linked_streambuf. + void set_next(streambuf_type* next); + void close(BOOST_IOS::openmode m); + const std::type_info& component_type() const { return typeid(T); } + void* component_impl() { return component(); } private: //----------Accessor functions--------------------------------------------// @@ -103,6 +106,7 @@ private: void set_flags(int f) { flags_ = f; } //----------State changing functions--------------------------------------// + virtual void init_get_area(); virtual void init_put_area(); diff --git a/include/boost/iostreams/detail/streambuf/linked_streambuf.hpp b/include/boost/iostreams/detail/streambuf/linked_streambuf.hpp index cc9f3d6..660afd3 100755 --- a/include/boost/iostreams/detail/streambuf/linked_streambuf.hpp +++ b/include/boost/iostreams/detail/streambuf/linked_streambuf.hpp @@ -11,6 +11,7 @@ # pragma once #endif +#include #include // member template friends. #include #include // openmode. @@ -55,8 +56,10 @@ public: #endif virtual void set_next(link* /* next */) { } virtual void close(BOOST_IOS::openmode) = 0; + virtual const std::type_info& component_type() const = 0; + virtual void* component_impl() = 0; }; - + } } } // End namespaces detail, iostreams, boost. #include // MSVC. diff --git a/include/boost/iostreams/filtering_stream.hpp b/include/boost/iostreams/filtering_stream.hpp index d37b737..557c511 100755 --- a/include/boost/iostreams/filtering_stream.hpp +++ b/include/boost/iostreams/filtering_stream.hpp @@ -75,7 +75,7 @@ protected: >::type stream_type; filtering_stream_base() : stream_type(0) { this->set_chain(&chain_); } private: - void notify() { this->rdbuf(chain_.empty() ? 0 : &*chain_); } + void notify() { this->rdbuf(chain_.empty() ? 0 : &chain_.front()); } Chain chain_; };