added auto_close support

[SVN r27993]
This commit is contained in:
Jonathan Turkanis
2005-04-05 22:57:29 +00:00
parent b0867e4725
commit bcb853efc4
5 changed files with 110 additions and 130 deletions

View File

@@ -120,12 +120,9 @@ public:
//----------Device interface----------------------------------------------//
std::streamsize read(char_type* s, std::streamsize n)
{ return list().front()->sgetn(s, n); }
void write(const char_type* s, std::streamsize n)
{ list().front()->sputn(s, n); }
off_type seek(off_type off, BOOST_IOS::seekdir way)
{ return list().front()->pubseekoff(off, way); }
std::streamsize read(char_type* s, std::streamsize n);
void write(const char_type* s, std::streamsize n);
std::streamoff seek(std::streamoff off, BOOST_IOS::seekdir way);
//----------Direct stream buffer access-----------------------------------//
@@ -141,7 +138,9 @@ public:
// 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 { return pimpl_->complete_; }
bool is_complete() const;
bool auto_close() const;
void set_auto_close(bool close);
private:
template<typename T>
void push_impl(const T& t, int buffer_size = -1, int pback_size = -1)
@@ -172,7 +171,7 @@ private:
list().push_back(buf.get());
buf.release();
if (is_device<policy_type>::value)
pimpl_->complete_ = true;
pimpl_->flags_ |= f_complete;
if (prev) prev->set_next(list().back());
notify();
}
@@ -201,22 +200,32 @@ private:
BOOST_IOS::openmode mode_;
};
friend struct closer;
enum {
f_complete = 1,
f_auto_close = 2
};
struct chain_impl {
chain_impl()
: client_(0), device_buffer_size_(default_buffer_size),
filter_buffer_size_(default_filter_buffer_size),
pback_size_(default_pback_buffer_size),
complete_(false)
flags_(f_auto_close)
{ }
~chain_impl()
{
try { close(); } catch (std::exception&) { }
try {
if ((flags_ & f_auto_close) != 0)
close();
} catch (std::exception&) { }
std::for_each( links_.begin(), links_.end(),
checked_deleter<streambuf_type>() );
}
void close()
{
if (!complete_) return;
if ((flags_ & f_complete) == 0)
return;
links_.front()->BOOST_IOSTREAMS_PUBSYNC();
if (is_convertible<Mode, input>::value)
std::for_each( links_.rbegin(), links_.rend(),
@@ -230,7 +239,7 @@ private:
int device_buffer_size_,
filter_buffer_size_,
pback_size_;
bool complete_;
int flags_;
};
friend struct chain_impl;
@@ -309,6 +318,8 @@ public:
chain_type filters() const { return *chain_; }
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); }
void set_buffer_size(std::streamsize n) { chain_->set_buffer_size(n); }
void set_filter_buffer_size(std::streamsize n)
{ chain_->set_filter_buffer_size(n); }
@@ -339,6 +350,21 @@ private:
//--------------Implementation of chain_base----------------------------------//
template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
inline std::streamsize chain_base<Self, Ch, Tr, Alloc, Mode>::read
(char_type* s, std::streamsize n)
{ return list().front()->sgetn(s, n); }
template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
inline void chain_base<Self, Ch, Tr, Alloc, Mode>::write
(const char_type* s, std::streamsize n)
{ list().front()->sputn(s, n); }
template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
inline std::streamoff chain_base<Self, Ch, Tr, Alloc, Mode>::seek
(std::streamoff off, BOOST_IOS::seekdir way)
{ return list().front()->pubseekoff(off, way); }
template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
void chain_base<Self, Ch, Tr, Alloc, Mode>::reset()
{
@@ -346,7 +372,27 @@ void chain_base<Self, Ch, Tr, Alloc, Mode>::reset()
pimpl_->close();
for_each(list().begin(), list().end(), checked_deleter<streambuf_type>());
list().clear();
pimpl_->complete_ = false;
pimpl_->flags_ &= ~f_complete;
}
template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
bool chain_base<Self, Ch, Tr, Alloc, Mode>::is_complete() const
{
return (pimpl_->flags_ & f_complete) != 0;
}
template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
bool chain_base<Self, Ch, Tr, Alloc, Mode>::auto_close() const
{
return (pimpl_->flags_ & f_auto_close) != 0;
}
template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
void chain_base<Self, Ch, Tr, Alloc, Mode>::set_auto_close(bool close)
{
pimpl_->flags_ =
(pimpl_->flags_ & ~f_auto_close) |
(close ? f_auto_close : 0);
}
template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode>
@@ -356,7 +402,7 @@ void chain_base<Self, Ch, Tr, Alloc, Mode>::pop()
pimpl_->close();
delete list().back();
list().pop_back();
pimpl_->complete_ = false;
pimpl_->flags_ &= ~f_complete;
}
} // End namespace detail.

View File

@@ -17,9 +17,11 @@
#include <boost/config.hpp> // BOOST_DEDUCED_TYPENAME.
#include <boost/iostreams/detail/char_traits.hpp>
#include <boost/iostreams/detail/config/wide_streams.hpp>
#include <boost/iostreams/detail/ios.hpp>
#include <boost/iostreams/detail/streambuf.hpp>
#include <boost/iostreams/detail/streambuf/linked_streambuf.hpp>
#include <boost/iostreams/detail/error.hpp>
#include <boost/iostreams/operations.hpp>
#include <boost/iostreams/traits.hpp>
#include <boost/optional.hpp>
@@ -50,6 +52,8 @@ public: // stream_facade needs access.
int /* pback_size */ );
bool is_open();
void close();
bool auto_close() const { return auto_close_; }
void set_auto_close(bool close) { auto_close_ = close; }
protected:
#if !BOOST_WORKAROUND(__GNUC__, == 2)
BOOST_IOSTREAMS_USING_PROTECTED_STREAMBUF_MEMBERS(base_type)
@@ -78,13 +82,14 @@ private:
bool two_head() const;
optional<T> storage_;
char_type *ibeg_, *iend_, *obeg_, *oend_;
bool auto_close_;
};
//------------------Implementation of direct_streambuf------------------------//
template<typename T, typename Tr>
direct_streambuf<T, Tr>::direct_streambuf()
: ibeg_(0), iend_(0), obeg_(0), oend_(0) { }
: ibeg_(0), iend_(0), obeg_(0), oend_(0), auto_close_(true) { }
template<typename T, typename Tr>
void direct_streambuf<T, Tr>::open(const T& t, int, int)
@@ -101,7 +106,14 @@ bool direct_streambuf<T, Tr>::is_open() { return ibeg_ != 0 && !obeg_ != 0; }
template<typename T, typename Tr>
void direct_streambuf<T, Tr>::close()
{ ibeg_ = iend_ = obeg_ = oend_ = 0; storage_.reset(); }
{
using namespace std;
if (ibeg_ != 0)
try { close(BOOST_IOS::in); } catch (std::exception&) { }
if (obeg_ != 0)
try { close(BOOST_IOS::out); } catch (std::exception&) { }
storage_.reset();
}
template<typename T, typename Tr>
typename direct_streambuf<T, Tr>::int_type
@@ -160,7 +172,21 @@ direct_streambuf<T, Tr>::seekpos
{ return seek_impl(sp, BOOST_IOS::beg, BOOST_IOS::in | BOOST_IOS::out); }
template<typename T, typename Tr>
void direct_streambuf<T, Tr>::close(BOOST_IOS::openmode) { close(); }
void direct_streambuf<T, Tr>::close(BOOST_IOS::openmode which)
{
if (which & BOOST_IOS::in) {
setg(0, 0, 0);
ibeg_ = iend_ = 0;
}
if (which & BOOST_IOS::out) {
sync();
setp(0, 0);
obeg_ = oend_ = 0;
}
try {
boost::iostreams::close(storage_.get(), which);
} catch (std::exception&) { }
}
template<typename T, typename Tr>
typename direct_streambuf<T, Tr>::pos_type direct_streambuf<T, Tr>::seek_impl

View File

@@ -20,6 +20,7 @@
#include <boost/iostreams/detail/buffer.hpp>
#include <boost/iostreams/detail/config/wide_streams.hpp>
#include <boost/iostreams/detail/double_object.hpp>
#include <boost/iostreams/detail/ios.hpp>
#include <boost/iostreams/detail/push.hpp>
#include <boost/iostreams/detail/streambuf/linked_streambuf.hpp>
#include <boost/iostreams/traits.hpp>
@@ -55,11 +56,12 @@ private:
#endif
public:
indirect_streambuf();
~indirect_streambuf();
void open(const T& t BOOST_IOSTREAMS_PUSH_PARAMS());
bool is_open();
void close();
bool auto_close() const;
void set_auto_close(bool close);
//----------Direct filter or device access--------------------------------//
@@ -115,7 +117,8 @@ private:
f_open = 1,
f_input_closed = f_open << 1,
f_output_closed = f_input_closed << 1,
f_output_buffered = f_output_closed << 1
f_output_buffered = f_output_closed << 1,
f_auto_close = f_output_buffered << 1
};
optional<wrapper> storage_;
@@ -135,11 +138,7 @@ private:
template<typename T, typename Tr, typename Alloc, typename Mode>
indirect_streambuf<T, Tr, Alloc, Mode>::indirect_streambuf()
: next_(0), pback_size_(0), flags_(0) { }
template<typename T, typename Tr, typename Alloc, typename Mode>
indirect_streambuf<T, Tr, Alloc, Mode>::~indirect_streambuf()
{ try { if (is_open()) close(); } catch (std::exception&) { } }
: next_(0), pback_size_(0), flags_(f_auto_close) { }
//--------------Implementation of open, is_open and close---------------------//
@@ -201,6 +200,14 @@ void indirect_streambuf<T, Tr, Alloc, Mode>::close()
flags_ = 0;
}
template<typename T, typename Tr, typename Alloc, typename Mode>
bool indirect_streambuf<T, Tr, Alloc, Mode>::auto_close() const
{ return (flags_ & f_auto_close) != 0; }
template<typename T, typename Tr, typename Alloc, typename Mode>
void indirect_streambuf<T, Tr, Alloc, Mode>::set_auto_close(bool close)
{ flags_ = (flags_ & ~f_auto_close) | (close ? f_auto_close : 0); }
//--------------Implementation virtual functions------------------------------//
#ifndef BOOST_IOSTREAMS_NO_LOCALE

View File

@@ -107,56 +107,6 @@ private:
typedef Device policy_type;
public:
stream_facade() { }
// BEGIN DEBUG
//stream_facade(typename ::boost::iostreams::detail::param_type<Device>::type t , int buffer_size = -1 , int pback_size = -1) {
// this->open_impl(::boost::iostreams::detail::wrap(t) , buffer_size, pback_size);
//}
//stream_facade(const ::boost::reference_wrapper<Device>& ref , int buffer_size = -1 , int pback_size = -1) {
// this->open_impl(ref , buffer_size, pback_size);
//}
//void open(typename ::boost::iostreams::detail::param_type<Device>::type t , int buffer_size = -1 , int pback_size = -1) {
// this->open_impl(::boost::iostreams::detail::wrap(t) , buffer_size, pback_size);
//}
//void open(const ::boost::reference_wrapper<Device>& ref , int buffer_size = -1 , int pback_size = -1) {
// this->open_impl(ref , buffer_size, pback_size);
//}
//template< typename U0> stream_facade ( const U0 &u0) {
// this->open_impl ( Device ( u0) );
//}
//template< typename U100 > stream_facade ( U100& u100 ) {
// this->open_impl ( Device ( u100 ) );
//}
//template< typename U0 , typename U1> stream_facade ( const U0 &u0 , const U1 &u1) {
// this->open_impl ( Device ( u0 , u1) );
//}
//template< typename U100 , typename U0 > stream_facade ( U100& u100 , const U0 &u0) {
// this->open_impl ( Device ( u100 , u0) );
//}
//template< typename U0 , typename U1 , typename U2> stream_facade ( const U0 &u0 , const U1 &u1 , const U2 &u2) {
// this->open_impl ( Device ( u0 , u1 , u2) );
//}
//template< typename U100 , typename U0 , typename U1 > stream_facade ( U100& u100 , const U0 &u0 , const U1 &u1) {
// this->open_impl ( Device ( u100 , u0 , u1) );
//}
//template< typename U0> void open( const U0 &u0) {
// this->open_impl ( Device ( u0) );
//}
//template< typename U100 > void open ( U100& u100 ) {
// this->open_impl ( u100 );
//}
//template< typename U0 , typename U1> void open( const U0 &u0 , const U1 &u1) {
// this->open_impl ( Device ( u0 , u1) );
//}
//template< typename U100 , typename U0 > void open ( U100& u100 , const U0 &u0) {
// this->open_impl ( u100 , u0 );
//}
//template< typename U0 , typename U1 , typename U2> void open( const U0 &u0 , const U1 &u1 , const U2 &u2) {
// this->open_impl ( Device ( u0 , u1 , u2) );
//}
//template< typename U100 , typename U0 , typename U1 > void open ( U100& u100 , const U0 &u0 , const U1 &u1) {
// this->open_impl ( u100 , u0 , u1 );
//}
// END DEBUG
BOOST_IOSTREAMS_FORWARD( stream_facade, open_impl, Device,
BOOST_IOSTREAMS_PUSH_PARAMS,
BOOST_IOSTREAMS_PUSH_ARGS )

View File

@@ -78,62 +78,13 @@ public:
BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(Tr)
public:
streambuf_facade() { }
//// BEGIN DEBUG
//streambuf_facade(typename ::boost::iostreams::detail::param_type<T>::type t , int buffer_size = -1 , int pback_size = -1) {
// this->open_impl(::boost::iostreams::detail::wrap(t) , buffer_size, pback_size);
//}
//streambuf_facade(const ::boost::reference_wrapper<T>& ref , int buffer_size = -1 , int pback_size = -1) {
// this->open_impl(ref , buffer_size, pback_size);
//}
//void open(typename ::boost::iostreams::detail::param_type<T>::type t , int buffer_size = -1 , int pback_size = -1) {
// this->open_impl(::boost::iostreams::detail::wrap(t) , buffer_size, pback_size);
//}
//void open(const ::boost::reference_wrapper<T>& ref , int buffer_size = -1 , int pback_size = -1) {
// this->open_impl(ref , buffer_size, pback_size);
//}
//template< typename U0>
//streambuf_facade ( const U0 &u0) {
// this->open_impl ( T ( u0) );
//}
//template< typename U100 >
//streambuf_facade ( U100& u100 ) {
// this->open_impl ( T ( u100 ) );
//}
//template< typename U0 , typename U1>
//streambuf_facade ( const U0 &u0 , const U1 &u1) {
// this->open_impl ( T ( u0 , u1) );
//}
//template< typename U100 , typename U0 >
//streambuf_facade ( U100& u100 , const U0 &u0) {
// this->open_impl ( T ( u100 , u0) );
//}
//template< typename U0 , typename U1 , typename U2>
//streambuf_facade ( const U0 &u0 , const U1 &u1 , const U2 &u2) {
// this->open_impl ( T ( u0 , u1 , u2) );
//}
//template< typename U100 , typename U0 , typename U1 >
//streambuf_facade ( U100& u100 , const U0 &u0 , const U1 &u1) {
// this->open_impl ( T ( u100 , u0 , u1) );
//}
//template< typename U0> void open( const U0 &u0) {
// this->open_impl ( T ( u0) );
//}
//template< typename U100 > void open ( U100& u100 ) {
// this->open_impl ( u100 );
//}
//template< typename U0 , typename U1> void open( const U0 &u0 , const U1 &u1) {
// this->open_impl ( T ( u0 , u1) );
//}
//template< typename U100 , typename U0 > void open ( U100& u100 , const U0 &u0) {
// this->open_impl ( u100 , u0 );
//}
//template< typename U0 , typename U1 , typename U2> void open( const U0 &u0 , const U1 &u1 , const U2 &u2) {
// this->open_impl ( T ( u0 , u1 , u2) );
//}
//template< typename U100 , typename U0 , typename U1 > void open ( U100& u100 , const U0 &u0 , const U1 &u1) {
// this->open_impl ( u100 , u0 , u1 );
//}
//// END DEBUG
~streambuf_facade()
{
try {
if (this->is_open() && this->auto_close())
this->close();
} catch (std::exception&) { }
}
BOOST_IOSTREAMS_FORWARD( streambuf_facade, open_impl, T,
BOOST_IOSTREAMS_PUSH_PARAMS,
BOOST_IOSTREAMS_PUSH_ARGS )