mirror of
https://github.com/boostorg/iostreams.git
synced 2026-02-27 17:12:17 +00:00
added support for component() and component_type()
[SVN r28038]
This commit is contained in:
@@ -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())
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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------------------------//
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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_;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user