added support for component() and component_type()

[SVN r28038]
This commit is contained in:
Jonathan Turkanis
2005-04-07 03:59:02 +00:00
parent f5fd20979f
commit cf1020c76d
6 changed files with 108 additions and 51 deletions

View File

@@ -15,9 +15,11 @@
#include <cassert>
#include <exception>
#include <functional> // unary_function.
#include <iterator> // advance.
#include <list>
#include <memory> // allocator, auto_ptr.
#include <stdexcept> // logic_error.
#include <typeinfo>
#include <stdexcept> // logic_error, out_of_range.
#include <boost/checked_delete.hpp>
#include <boost/config.hpp> // BOOST_MSVC, template friends.
#include <boost/detail/workaround.hpp>
@@ -34,6 +36,20 @@
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_convertible.hpp>
// 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 <cstring>
# 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<int N>
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<int N, typename T>
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<T*>(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<typename T>
void push_impl(const T& t, int buffer_size = -1, int pback_size = -1)
{
typedef typename iostreams::io_category<T>::type category;
typedef typename unwrap_ios<T>::type policy_type;
typedef streambuf_facade<
policy_type,
BOOST_IOSTREAMS_CHAR_TRAITS(char_type),
Alloc, Mode
> facade_type;
BOOST_STATIC_ASSERT((is_convertible<category, Mode>::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<facade_type>
buf(new facade_type(t, buffer_size, pback_size));
list().push_back(buf.get());
buf.release();
if (is_device<policy_type>::value)
pimpl_->flags_ |= f_complete;
if (prev) prev->set_next(list().back());
notify();
}
{
typedef typename iostreams::io_category<T>::type category;
typedef typename unwrap_ios<T>::type policy_type;
typedef streambuf_facade<
policy_type,
BOOST_IOSTREAMS_CHAR_TRAITS(char_type),
Alloc, Mode
> facade_type;
BOOST_STATIC_ASSERT((is_convertible<category, Mode>::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<facade_type>
buf(new facade_type(t, buffer_size, pback_size));
list().push_back(buf.get());
buf.release();
if (is_device<policy_type>::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<int N>
const std::type_info& component_type() const
{ return chain_->component_type<N>(); }
template<int N, typename T>
T* component() const
{ return chain_->component<N, T>(); }
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<typename T>
void push_impl(const T& t BOOST_IOSTREAMS_PUSH_PARAMS())

View File

@@ -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<std_traits, chain_traits>(c); }
{ return translate_int_type<std_traits, chain_traits>(c); }
delegate_type& delegate() { return static_cast<delegate_type&>(*chain_); }
delegate_type& delegate()
{ return static_cast<delegate_type&>(chain_.front()); }
void get_pointers()
{
setg(delegate().eback(), delegate().gptr(), delegate().egptr());

View File

@@ -13,6 +13,7 @@
#include <cassert>
#include <cstddef>
#include <typeinfo>
#include <utility> // pair.
#include <boost/config.hpp> // BOOST_DEDUCED_TYPENAME.
#include <boost/iostreams/detail/char_traits.hpp>
@@ -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<T> storage_;
char_type *ibeg_, *iend_, *obeg_, *oend_;
bool auto_close_;
bool auto_close_;
};
//------------------Implementation of direct_streambuf------------------------//

View File

@@ -13,6 +13,7 @@
#include <algorithm> // min, max.
#include <cassert>
#include <exception>
#include <typeinfo>
#include <boost/config.hpp> // Member template friends.
#include <boost/detail/workaround.hpp>
#include <boost/iostreams/constants.hpp>
@@ -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();

View File

@@ -11,6 +11,7 @@
# pragma once
#endif
#include <typeinfo>
#include <boost/config.hpp> // member template friends.
#include <boost/iostreams/detail/char_traits.hpp>
#include <boost/iostreams/detail/ios.hpp> // 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 <boost/iostreams/detail/config/enable_warnings.hpp> // MSVC.

View File

@@ -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_;
};