|
Boost-Commit : |
From: technews_at_[hidden]
Date: 2008-05-25 18:03:23
Author: turkanis
Date: 2008-05-25 18:03:22 EDT (Sun, 25 May 2008)
New Revision: 45752
URL: http://svn.boost.org/trac/boost/changeset/45752
Log:
made tee work with input streams (fixes #791)
Text files modified:
trunk/boost/iostreams/tee.hpp | 112 +++++++++++++++++++++++++++------------
trunk/libs/iostreams/test/tee_test.cpp | 60 +++++++++++++++++++++
2 files changed, 136 insertions(+), 36 deletions(-)
Modified: trunk/boost/iostreams/tee.hpp
==============================================================================
--- trunk/boost/iostreams/tee.hpp (original)
+++ trunk/boost/iostreams/tee.hpp 2008-05-25 18:03:22 EDT (Sun, 25 May 2008)
@@ -40,7 +40,8 @@
typedef typename detail::param_type<Device>::type param_type;
typedef typename char_type_of<Device>::type char_type;
struct category
- : multichar_output_filter_tag,
+ : dual_use_filter_tag,
+ multichar_tag,
closable_tag,
flushable_tag,
localizable_tag,
@@ -57,6 +58,18 @@
: detail::filter_adapter<Device>(dev)
{ }
+ template<typename Source>
+ std::streamsize read(Source& src, char_type* s, std::streamsize n)
+ {
+ std::streamsize result = iostreams::read(src, s, n);
+ if (result != -1) {
+ std::streamsize result2 = iostreams::write(this->component(), s, result);
+ (void) result2; // Suppress 'unused variable' warning.
+ assert(result == result2);
+ }
+ return result;
+ }
+
template<typename Sink>
std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
{
@@ -68,7 +81,7 @@
}
template<typename Next>
- void close(Next&)
+ void close(Next&, BOOST_IOS::openmode)
{
detail::close_all(this->component());
}
@@ -86,48 +99,75 @@
//
// Template name: tee_device.
// Template paramters:
-// Sink1 - A blocking Sink.
-// Sink2 - A blocking Sink.
+// Device - A blocking Device.
+// Sink - A blocking Sink.
//
-template<typename Sink1, typename Sink2>
+template<typename Device, typename Sink>
class tee_device {
public:
- typedef typename detail::param_type<Sink1>::type param_type1;
- typedef typename detail::param_type<Sink2>::type param_type2;
- typedef typename detail::value_type<Sink1>::type value_type1;
- typedef typename detail::value_type<Sink2>::type value_type2;
- typedef typename char_type_of<Sink1>::type char_type;
+ typedef typename detail::param_type<Device>::type device_param;
+ typedef typename detail::param_type<Sink>::type sink_param;
+ typedef typename detail::value_type<Device>::type device_value;
+ typedef typename detail::value_type<Sink>::type sink_value;
+ typedef typename char_type_of<Device>::type char_type;
+ typedef typename
+ mpl::if_<
+ is_convertible<
+ BOOST_DEDUCED_TYPENAME
+ iostreams::category_of<Device>::type,
+ output
+ >,
+ output,
+ input
+ >::type mode;
BOOST_STATIC_ASSERT((
is_same<
char_type,
- BOOST_DEDUCED_TYPENAME char_type_of<Sink2>::type
- >::value
- ));
- BOOST_STATIC_ASSERT((
- is_convertible< // Using mode_of causes failures on VC6-7.0.
- BOOST_DEDUCED_TYPENAME iostreams::category_of<Sink1>::type, output
+ BOOST_DEDUCED_TYPENAME char_type_of<Sink>::type
>::value
));
BOOST_STATIC_ASSERT((
- is_convertible< // Using mode_of causes failures on VC6-7.0.
- BOOST_DEDUCED_TYPENAME iostreams::category_of<Sink2>::type, output
+ is_convertible<
+ BOOST_DEDUCED_TYPENAME iostreams::category_of<Sink>::type,
+ output
>::value
));
struct category
- : output,
+ : mode,
device_tag,
closable_tag,
flushable_tag,
localizable_tag,
optimally_buffered_tag
{ };
- tee_device(param_type1 sink1, param_type2 sink2)
- : sink1_(sink1), sink2_(sink2)
+ tee_device(device_param device, sink_param sink)
+ : dev_(device), sink_(sink)
{ }
+ std::streamsize read(char_type* s, std::streamsize n)
+ {
+ BOOST_STATIC_ASSERT((
+ is_convertible<
+ BOOST_DEDUCED_TYPENAME iostreams::category_of<Device>::type, input
+ >::value
+ ));
+ std::streamsize result1 = iostreams::read(dev_, s, n);
+ if (result1 != -1) {
+ std::streamsize result2 = iostreams::write(sink_, s, result1);
+ (void) result1; // Suppress 'unused variable' warning.
+ (void) result2;
+ assert(result1 == result2);
+ }
+ return result1;
+ }
std::streamsize write(const char_type* s, std::streamsize n)
{
- std::streamsize result1 = iostreams::write(sink1_, s, n);
- std::streamsize result2 = iostreams::write(sink2_, s, n);
+ BOOST_STATIC_ASSERT((
+ is_convertible<
+ BOOST_DEDUCED_TYPENAME iostreams::category_of<Device>::type, output
+ >::value
+ ));
+ std::streamsize result1 = iostreams::write(dev_, s, n);
+ std::streamsize result2 = iostreams::write(sink_, s, n);
(void) result1; // Suppress 'unused variable' warning.
(void) result2;
assert(result1 == n && result2 == n);
@@ -135,38 +175,38 @@
}
void close()
{
- detail::execute_all( detail::call_close_all(sink1_),
- detail::call_close_all(sink2_) );
+ detail::execute_all( detail::call_close_all(dev_),
+ detail::call_close_all(sink_) );
}
bool flush()
{
- bool r1 = iostreams::flush(sink1_);
- bool r2 = iostreams::flush(sink2_);
+ bool r1 = iostreams::flush(dev_);
+ bool r2 = iostreams::flush(sink_);
return r1 && r2;
}
template<typename Locale>
void imbue(const Locale& loc)
{
- iostreams::imbue(sink1_, loc);
- iostreams::imbue(sink2_, loc);
+ iostreams::imbue(dev_, loc);
+ iostreams::imbue(sink_, loc);
}
std::streamsize optimal_buffer_size() const
{
- return (std::max) ( iostreams::optimal_buffer_size(sink1_),
- iostreams::optimal_buffer_size(sink2_) );
+ return (std::max) ( iostreams::optimal_buffer_size(dev_),
+ iostreams::optimal_buffer_size(sink_) );
}
private:
- value_type1 sink1_;
- value_type2 sink2_;
+ device_value dev_;
+ sink_value sink_;
};
template<typename Sink>
tee_filter<Sink> tee(const Sink& snk)
{ return tee_filter<Sink>(snk); }
-template<typename Sink1, typename Sink2>
-tee_device<Sink1, Sink2> tee(const Sink1& sink1, const Sink2& sink2)
-{ return tee_device<Sink1, Sink2>(sink1, sink2); }
+template<typename Device, typename Sink>
+tee_device<Device, Sink> tee(const Device& dev, const Sink& sink)
+{ return tee_device<Device, Sink>(dev, sink); }
} } // End namespaces iostreams, boost.
Modified: trunk/libs/iostreams/test/tee_test.cpp
==============================================================================
--- trunk/libs/iostreams/test/tee_test.cpp (original)
+++ trunk/libs/iostreams/test/tee_test.cpp 2008-05-25 18:03:22 EDT (Sun, 25 May 2008)
@@ -27,6 +27,36 @@
void read_write_test()
{
{
+ test_file src1, src2;
+ temp_file dest;
+ filtering_istream first, second;
+ first.push(tee(file_sink(dest.name(), out_mode)));
+ first.push(file_source(src1.name(), in_mode));
+ second.push(file_source(src2.name(), in_mode));
+ compare_streams_in_chars(first, second); // ignore return value
+ first.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest.name(), src1.name()),
+ "failed reading from a tee_filter in chars"
+ );
+ }
+
+ {
+ test_file src1, src2;
+ temp_file dest;
+ filtering_istream first, second;
+ first.push(tee(file_sink(dest.name(), out_mode)));
+ first.push(file_source(src1.name(), in_mode));
+ second.push(file_source(src2.name(), in_mode));
+ compare_streams_in_chunks(first, second); // ignore return value
+ first.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest.name(), src1.name()),
+ "failed reading from a tee_filter in chunks"
+ );
+ }
+
+ {
temp_file dest1;
temp_file dest2;
filtering_ostream out;
@@ -55,6 +85,36 @@
}
{
+ test_file src1, src2;
+ temp_file dest;
+ filtering_istream first, second;
+ first.push( tee( file_source(src1.name(), in_mode),
+ file_sink(dest.name(), out_mode) ) );
+ second.push(file_source(src2.name(), in_mode));
+ compare_streams_in_chars(first, second); // ignore return value
+ first.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest.name(), src1.name()),
+ "failed reading from a tee_device in chars"
+ );
+ }
+
+ {
+ test_file src1, src2;
+ temp_file dest;
+ filtering_istream first, second;
+ first.push( tee( file_source(src1.name(), in_mode),
+ file_sink(dest.name(), out_mode) ) );
+ second.push(file_source(src2.name(), in_mode));
+ compare_streams_in_chunks(first, second); // ignore return value
+ first.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest.name(), src1.name()),
+ "failed reading from a tee_device in chunks"
+ );
+ }
+
+ {
temp_file dest1;
temp_file dest2;
filtering_ostream out;
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk